//===-- go-llvm.cpp - LLVM implementation of 'Backend'  -------------------===//
//
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//
//===----------------------------------------------------------------------===//
//
// Methods for class Llvm_backend, a subclass of the gofrontend class
// Backend, with LLVM-specific implementation methods.
//
//===----------------------------------------------------------------------===//

#include "go-llvm.h"
#include "go-llvm-builtins.h"
#include "go-llvm-diagnostics.h"
#include "backend.h"
#include "go-c.h"
#include "go-system.h"
#include "go-llvm-linemap.h"
#include "go-llvm-dibuildhelper.h"
#include "go-llvm-cabi-oracle.h"
#include "go-llvm-irbuilders.h"
#include "gogo.h"

#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Value.h"
#include "llvm/IR/Verifier.h"

Llvm_backend::Llvm_backend(llvm::LLVMContext &context,
                           llvm::Module *module,
                           Llvm_linemap *linemap,
                           unsigned addrspace)
    : TypeManager(context, llvm::CallingConv::X86_64_SysV, addrspace)
    , context_(context)
    , module_(module)
    , datalayout_(module ? &module->getDataLayout() : nullptr)
    , nbuilder_(this)
    , linemap_(linemap)
    , addressSpace_(addrspace)
    , traceLevel_(0)
    , noInline_(false)
    , noFpElim_(false)
    , useSplitStack_(true)
    , compilingRuntime_(false)
    , checkIntegrity_(true)
    , createDebugMetaData_(true)
    , exportDataStarted_(false)
    , exportDataFinalized_(false)
    , errorCount_(0u)
    , compositeSizeThreshold_(8u) // TODO: adjust later to larger value
    , TLI_(nullptr)
    , builtinTable_(new BuiltinTable(typeManager(), false))
    , errorFunction_(nullptr)
    , personalityFunction_(nullptr)
    , dummyPersonalityFunction_(nullptr)
    , gcStrategy_("")
    , autoFDO_(false)
{
  // If nobody passed in a linemap, create one for internal use (unit testing)
  if (!linemap_) {
    ownLinemap_.reset(new Llvm_linemap());
    linemap_ = ownLinemap_.get();
  }

  // Similarly for the LLVM module (unit testing)
  if (!module_) {
    ownModule_.reset(new llvm::Module("gomodule", context));
    ownModule_->setTargetTriple("x86_64-unknown-linux-gnu");
    ownModule_->setDataLayout("e-m:e-i64:64-f80:128-n8:16:32:64-S128");
    module_ = ownModule_.get();
  }

  datalayout_ = &module_->getDataLayout();

  // Reuse the error function as the value for error_expression
  errorExpression_ = nbuilder_.mkError(errorType());

  // We now have the necessary bits to finish initialization of the
  // type manager.
  initializeTypeManager(errorExpression(),
                        datalayout_,
                        nameTags());

  // Create and record an error function. By marking it as varargs this will
  // avoid any collisions with things that the front end might create, since
  // Go varargs is handled/lowered entirely by the front end.
  llvm::SmallVector<llvm::Type *, 1> elems(0);
  elems.push_back(llvmPtrType());
  const bool isVarargs = true;
  llvm::FunctionType *eft = llvm::FunctionType::get(
      llvm::Type::getVoidTy(context_), elems, isVarargs);
  llvm::GlobalValue::LinkageTypes plinkage = llvm::GlobalValue::ExternalLinkage;
  llvm::Function *ef = llvm::Function::Create(eft, plinkage, "", module_);
  errorFunction_.reset(new Bfunction(ef, makeAuxFcnType(eft), "", "",
                                     Location(), typeManager()));

  // Error statement.
  errorStatement_ = nbuilder_.mkErrorStmt();

  // Error variable.
  Location loc;
  errorVariable_.reset(
      new Bvariable(errorType(), loc, "", ErrorVar, false, nullptr));

  // Initialize machinery for builtins
  builtinTable_->defineAllBuiltins();

  if (createDebugMetaData_)
    dibuildhelper_.reset(new DIBuildHelper(module_, typeManager(), linemap_));
}

Llvm_backend::~Llvm_backend() {
  for (auto &kv : valueVarMap_)
    delete kv.second;
  for (auto &bfcn : functions_)
    delete bfcn;
}

TypeManager *Llvm_backend::typeManager() const {
  const TypeManager *tm = this;
  return const_cast<TypeManager*>(tm);
}

void Llvm_backend::setTraceLevel(unsigned level)
{
  traceLevel_ = level;
  setTypeManagerTraceLevel(level);
}

void Llvm_backend::addDebugPrefix(std::pair<llvm::StringRef, llvm::StringRef> prefix)
{
  dibuildhelper_->addDebugPrefix(prefix);
}

void Llvm_backend::setTargetCpuAttr(const std::string &cpu)
{
  targetCpuAttr_ = cpu;
}

void Llvm_backend::setTargetFeaturesAttr(const std::string &attrs)
{
  targetFeaturesAttr_ = attrs;
}

void
Llvm_backend::verifyModule()
{
  bool broken = llvm::verifyModule(module(), &llvm::dbgs());
  assert(!broken && "Module not well-formed.");
}

void
Llvm_backend::dumpModule()
{
  std::string s;
  llvm::raw_string_ostream os(s);
  module().print(os, nullptr,
                 /*ShouldPreserveUseListOrder=*/false, /*IsForDebug=*/true);
  std::cerr << os.str();
}

void Llvm_backend::dumpExpr(Bexpression *e)
{
  if (e) {
    e->srcDump(linemap_);
    TreeIntegCtl ctl(DumpPointers, ReportRepairableSharing, BatchMode);
    auto p = checkTreeIntegrity(e, ctl);
    if (p.first)
      std::cerr << p.second;
  }
}

void Llvm_backend::dumpStmt(Bstatement *s)
{
  if (s) {
    s->srcDump(linemap_);
    TreeIntegCtl ctl(DumpPointers, ReportRepairableSharing, BatchMode);
    auto p = checkTreeIntegrity(s, ctl);
    if (p.first)
      std::cerr << p.second;
  }
}

void Llvm_backend::dumpVar(Bvariable *v)
{
  if (v)
    v->srcDump(linemap_);
}

std::pair<bool, std::string>
Llvm_backend::checkTreeIntegrity(Bnode *n, TreeIntegCtl control)
{
  Llvm_backend *be = const_cast<Llvm_backend *>(this);
  IntegrityVisitor iv(be, control);
  bool rval = iv.examine(n);
  return std::make_pair(rval, iv.msg());
}

void Llvm_backend::disableIntegrityChecks()
{
  checkIntegrity_ = false;
  nodeBuilder().setIntegrityChecks(false);
}

void Llvm_backend::enforceTreeIntegrity(Bnode *n)
{
  Llvm_backend *be = const_cast<Llvm_backend *>(this);
  TreeIntegCtl control(DumpPointers, DontReportRepairableSharing, BatchMode);
  IntegrityVisitor iv(be, control);
  bool res = iv.examine(n);
  if (!res && checkIntegrity_) {
    std::cerr << iv.msg() << "\n";
    assert(false);
  }
}

Btype *Llvm_backend::error_type() {
  errorCount_++;
  return errorType();
}

Btype *Llvm_backend::void_type() { return voidType(); }

Btype *Llvm_backend::bool_type() { return boolType(); }

// Get an unnamed float type.

Btype *Llvm_backend::float_type(int bits)
{
  return floatType(bits);
}

Btype *Llvm_backend::integer_type(bool is_unsigned, int bits)
{
  return integerType(is_unsigned, bits);
}

Btype *Llvm_backend::struct_type(const std::vector<Btyped_identifier> &fields)
{
  return structType(fields);
}

// Create a placeholder for a struct type.
Btype *Llvm_backend::placeholder_struct_type(const std::string &name,
                                             Location location)
{
  return placeholderStructType(name, location);
}

Btype *Llvm_backend::complex_type(int bits) {
  return complexType(bits);
}

// Get a pointer type.

Btype *Llvm_backend::pointer_type(Btype *toType)
{
  return pointerType(toType);
}

Btype *Llvm_backend::placeholder_pointer_type(const std::string &name,
                                              Location location, bool forfunc)
{
  return placeholderPointerType(name, location, forfunc);
}

// Make a function type.

Btype *
Llvm_backend::function_type(const Btyped_identifier &receiver,
                            const std::vector<Btyped_identifier> &parameters,
                            const std::vector<Btyped_identifier> &results,
                            Btype *result_struct, Location loc) {
  bool followsCabi = true;
  return functionType(receiver, parameters, results,
                      result_struct, followsCabi, loc);
}

Btype *Llvm_backend::array_type(Btype *elemType, Bexpression *length)
{
  return arrayType(elemType, length);
}

Btype *Llvm_backend::placeholder_array_type(const std::string &name,
                                            Location location)
{
  return placeholderArrayType(name, location);
}

bool Llvm_backend::set_placeholder_pointer_type(Btype *placeholder,
                                                Btype *to_type)
{
  return setPlaceholderPointerType(placeholder, to_type);
}

bool Llvm_backend::set_placeholder_function_type(Btype *placeholder,
                                                 Btype *ft) {
  return setPlaceholderPointerType(placeholder, ft);
}

bool
Llvm_backend::set_placeholder_struct_type(Btype *placeholder,
                            const std::vector<Btyped_identifier> &fields)
{
  return setPlaceholderStructType(placeholder, fields);
}

// Fill in the components of a placeholder array type.

bool Llvm_backend::set_placeholder_array_type(Btype *placeholder,
                                              Btype *element_btype,
                                              Bexpression *length) {
  return setPlaceholderArrayType(placeholder, element_btype, length);
}

Btype *Llvm_backend::named_type(const std::string &name,
                                Btype *btype,
                                Location location)
{
  return namedType(name, btype, location);
}

Btype *Llvm_backend::circular_pointer_type(Btype *placeholder, bool isf) {
  return circularPointerType(placeholder, isf);
}

bool Llvm_backend::is_circular_pointer_type(Btype *btype) {
  return isCircularPointerType(btype) || isCircularFunctionType(btype);
}

int64_t Llvm_backend::type_size(Btype *btype) {
  return typeSize(btype);
}

int64_t Llvm_backend::type_alignment(Btype *btype) {
  return typeAlignment(btype);
}

int64_t Llvm_backend::type_field_alignment(Btype *btype)
{
  return typeFieldAlignment(btype);
}

int64_t Llvm_backend::type_field_offset(Btype *btype, size_t index)
{
  return typeFieldOffset(btype, index);
}

llvm::Function *Llvm_backend::personalityFunction()
{
  if (personalityFunction_)
    return personalityFunction_;

  llvm::FunctionType *pft = personalityFunctionType();
  llvm::GlobalValue::LinkageTypes plinkage = llvm::GlobalValue::ExternalLinkage;
  const char *pfn = "__gccgo_personality_v0";
  personalityFunction_ =
      llvm::Function::Create(pft, plinkage, pfn, module_);
  return personalityFunction_;
}

llvm::Function *Llvm_backend::dummyPersonalityFunction()
{
  if (gcStrategy_.empty())
    // GC is not enabled, no need to attach dummy personality function.
    return nullptr;
  if (dummyPersonalityFunction_)
    return dummyPersonalityFunction_;

  llvm::FunctionType *pft = personalityFunctionType();
  llvm::GlobalValue::LinkageTypes plinkage = llvm::GlobalValue::ExternalLinkage;
  const char *pfn = "__gccgo_personality_dummy";
  dummyPersonalityFunction_ =
      llvm::Function::Create(pft, plinkage, pfn, module_);
  return dummyPersonalityFunction_;
}

Bfunction *Llvm_backend::createIntrinsicFcn(const std::string &name,
                                            llvm::Function *fcn)
{
  llvm::PointerType *llpft =
      llvm::cast<llvm::PointerType>(fcn->getType());
  llvm::FunctionType *llft =
      llvm::cast<llvm::FunctionType>(llpft->getElementType());
  BFunctionType *fcnType = makeAuxFcnType(llft);
  Location pdcl = linemap()->get_predeclared_location();
  Bfunction *bfunc = new Bfunction(fcn, fcnType, name, name, pdcl,
                                   typeManager());
  return bfunc;
}

// Look up a named built-in function in the current backend implementation.
// Returns NULL if no built-in function by that name exists.

Bfunction *Llvm_backend::lookup_builtin(const std::string &name) {

  // Do we have an entry at all for this builtin?
  BuiltinEntry *be = builtinTable_->lookup(name);
  if (!be)
    return nullptr;

  // We have an entry -- have we materialized a Bfunction for it yet?
  Bfunction *bf = be->bfunction();
  if (bf != nullptr)
    return bf;

  // Materialize a Bfunction for the builtin
  if (be->flavor() == BuiltinEntry::IntrinsicBuiltin) {
    llvm::Function *fcn;
    llvm::Intrinsic::ID id = be->intrinsicId();
    if (!llvm::Intrinsic::isOverloaded(id))
      fcn = llvm::Intrinsic::getDeclaration(module_, id);
    else {
      llvm::SmallVector<llvm::Type *, 8> ltypes;
      for (auto &t : be->types())
        ltypes.push_back(t->type());
      fcn = llvm::Intrinsic::getDeclaration(module_, id, ltypes);
    }
    assert(fcn != nullptr);
    assert(fcn->isIntrinsic() && fcn->getIntrinsicID() == id);
    bf = createIntrinsicFcn(be->name(), fcn);
  } else if (be->flavor() == BuiltinEntry::LibcallBuiltin) {
    bf = createBuiltinFcn(be);

    // FIXME: add attributes this function? Such as maybe
    // llvm::Attribute::ArgMemOnly, llvm::Attribute::ReadOnly?

    // FIXME: once we have a pass manager set up for the back end, we'll
    // want to turn on this code, since it will be helpful to catch
    // errors/mistakes. For the time being it can't be turned on (not
    // pass manager is set up).

    llvm::LibFunc lf = be->libfunc();
    if (TLI_ && lf != llvm::LibFunc::NumLibFuncs) {

      // Verify that the function is available on this target.
      assert(TLI_->has(lf));

      // Verify that the name and type we've computer so far matches up
      // with how LLVM views the routine. For example, if we are trying
      // to create a version of memcmp() that takes a single boolean as
      // an argument, that's going to be a show-stopper type problem.
      assert(TLI_->getLibFunc(*bf->function(), lf));
    }
  } else {
    assert(be->flavor() == BuiltinEntry::InlinedBuiltin);

    bf = createBuiltinFcn(be);
  }
  be->setBfunction(bf);

  return bf;
}

Bfunction *Llvm_backend::createBuiltinFcn(BuiltinEntry *be)
{
  // Create function type.
  Btyped_identifier receiver;
  std::vector<Btyped_identifier> params;
  std::vector<Btyped_identifier> results;
  Location bloc(linemap_->get_predeclared_location());
  const BuiltinEntryTypeVec &types = be->types();
  if (types.size() > 0 && types[0] != nullptr) {
    Btyped_identifier result("ret", types[0], bloc);
    results.push_back(result);
  }
  for (unsigned idx = 1; idx < types.size(); ++idx)
    params.push_back(Btyped_identifier("", types[idx], bloc));
  bool followsCabi = false;
  Btype *fcnType = functionType(receiver, params, results, nullptr,
                                followsCabi, bloc);

  // FIXME: may want to revisit these settings at some point. For example,
  // do we want to mark builtins as no-split-stack? Also it might be useful
  // to allow for creation of no-return builtins (such as longjmp, perhaps).
  unsigned flags = (Backend::function_is_visible |
                    Backend::function_is_inlinable |
                    (!useSplitStack_ ? Backend::function_no_split_stack : 0));

  // Create function
  return function(fcnType, be->name(), be->name(), flags, bloc);
}

bool Llvm_backend::moduleScopeValue(llvm::Value *val, Btype *btype) const
{
  valbtype vbt(std::make_pair(val, btype));
  return (valueExprmap_.find(vbt) != valueExprmap_.end());
}

Bexpression *Llvm_backend::makeGlobalExpression(Bexpression *expr,
                                                llvm::Value *val,
                                                Btype *btype,
                                                Location location) {
  assert(! llvm::isa<llvm::Instruction>(val));
  valbtype vbt(std::make_pair(val, btype));
  auto it = valueExprmap_.find(vbt);
  if (it != valueExprmap_.end()) {
    nbuilder_.freeNode(expr);
    return it->second;
  }
  valueExprmap_[vbt] = expr;
  return expr;
}

// Return the zero value for a type.

Bexpression *Llvm_backend::zero_expression(Btype *btype) {
  if (btype == errorType())
    return errorExpression();
  llvm::Value *zeroval = llvm::Constant::getNullValue(btype->type());
  Bexpression *cexpr = nbuilder_.mkConst(btype, zeroval);
  return makeGlobalExpression(cexpr, zeroval, btype, Location());
}

Bexpression *Llvm_backend::error_expression()
{
  errorCount_++;
  return errorExpression();
}

Bexpression *Llvm_backend::nil_pointer_expression()
{
  // What type should we assign a NIL pointer expression? This
  // is something of a head-scratcher. For now use uintptr.
  return zero_expression(pointerType(uintPtrType()));
}

Bexpression *Llvm_backend::genCircularConversion(Btype *toType,
                                                 Bexpression *expr,
                                                 Location loc)
{
  llvm::Value *val = expr->value();
  llvm::Type *vt = val->getType();
  assert(vt->isPointerTy());
  llvm::Type *llToType = toType->type();
  if (expr->varExprPending()) {
    llvm::Type *et = expr->btype()->type();
    if (vt->getPointerElementType() == et)
      llToType = llvm::PointerType::get(llToType, vt->getPointerAddressSpace());
  }
  if (vt == llToType)
    return expr;

  std::string tag(namegen("cast"));
  LIRBuilder builder(context_, llvm::ConstantFolder());
  llvm::Value *bitcast = builder.CreatePointerBitCastOrAddrSpaceCast(val, llToType, tag);
  return nbuilder_.mkConversion(toType, bitcast, expr, loc);
}

Bexpression *Llvm_backend::genLoad(Bexpression *expr,
                                   Btype *btype,
                                   Location loc,
                                   const std::string &tag)
{
  // If this is a load from a pointer flagged as being a circular
  // type, insert a conversion prior to the load so as to force
  // the value to the correct type. This is weird but necessary,
  // since the LLVM type system can't accurately model Go circular
  // pointer types.
  Bexpression *space = expr;
  Btype *loadResultType;
  if (btype) {
    loadResultType = btype;
    Btype *tctyp = circularTypeLoadConversion(expr->btype());
    if (tctyp != nullptr) {
      space = genCircularConversion(pointer_type(tctyp), expr, loc);
      loadResultType = tctyp;
    }
  } else {
    // Here we are resolving a pending var expression. The LLVM
    // value should already be pointer to the expression type.
    // No need to check circular pointer type.
    loadResultType = expr->btype();
  }

  llvm::Value *spaceVal = space->value();
  if (spaceVal == nil_pointer_expression()->value()) {
    llvm::Function *dummyFcn = errorFunction_->function();
    BlockLIRBuilder builder(dummyFcn, this);
    llvm::Type *spaceTyp = llvm::PointerType::get(loadResultType->type(), addressSpace_);
    std::string tag(namegen("cast"));
    spaceVal = builder.CreateBitCast(spaceVal, spaceTyp, tag);
    space->appendInstructions(builder.instructions());
  }

  llvm::PointerType *llpt =
      llvm::cast<llvm::PointerType>(spaceVal->getType());
  llvm::Type *llrt = llpt->getElementType();

  // If this type meets our criteria (composite/aggregate whose
  // size is above a certain threshhold) then assume that the
  // consumer will want an address (for memcpy) instead of a
  // value.
  Bexpression *rval = nullptr;
  if (! useCopyForLoadStore(llrt)) {
    // Non-composite value.
    std::string ldname(tag);
    ldname += ".ld";
    ldname = namegen(ldname);
    llvm::Instruction *loadInst = new llvm::LoadInst(spaceVal, ldname);
    rval = nbuilder_.mkDeref(loadResultType, loadInst, space, loc);
    rval->appendInstruction(loadInst);
  } else {
    // Composite value. Note that "var expr pending" is being set on
    // the resulting expression to flag the fact that there is a
    // disconnect between the concrete Btype (for example, maybe
    // "{ int64, int64}") and the llvm::Type of the llvm::Value (which in
    // this case will be a pointer to struct, "{ int64, int64 }*").
    rval = nbuilder_.mkDeref(loadResultType, spaceVal, space, loc);
    rval->setVarExprPending(false, 0);
  }
  return rval;
}

// An expression that indirectly references an expression.

Bexpression *Llvm_backend::indirect_expression(Btype *btype,
                                               Bexpression *expr,
                                               bool known_valid,
                                               Location location)
{

  if (expr == errorExpression() || btype == errorType())
    return errorExpression();

  assert(expr->btype()->type()->isPointerTy());

  Bexpression *rval = nbuilder_.mkDeref(btype, nullptr, expr, location);
  return rval;
}

// Get the address of an expression.

Bexpression *Llvm_backend::address_expression(Bexpression *bexpr,
                                              Location location)
{
  if (bexpr == errorExpression())
    return errorExpression();

  Btype *pt = pointer_type(bexpr->btype());
  Bexpression *rval = nbuilder_.mkAddress(pt, nullptr, bexpr, location);
  return rval;
}

bool Llvm_backend::exprVectorHasError(const std::vector<Bexpression *> &vals) {
  for (auto v : vals)
    if (v == errorExpression())
      return true;
  return false;
}

bool Llvm_backend::stmtVectorHasError(const std::vector<Bstatement *> &stmts)
{
  for (auto s : stmts)
    if (s == errorStatement())
      return true;
  return false;
}

Bexpression *Llvm_backend::resolve(Bexpression *expr,
                                   Varexpr_context ctx)

{
  if (expr->compositeInitPending())
    expr = resolveCompositeInit(expr, nullptr);
  if (expr->varExprPending())
    expr = resolveVarContext(expr, ctx);
  return expr;
}

Bexpression *Llvm_backend::resolveVarContext(Bexpression *expr,
                                             Varexpr_context ctx)

{
  if (expr->varExprPending()) {
    const VarContext &vc = expr->varContext();
    assert(vc.addrLevel() == 0 || vc.addrLevel() == 1);
    if (vc.addrLevel() == 1 || vc.lvalue() || ctx == VE_lvalue) {
      assert(vc.addrLevel() == 0 || expr->btype()->type()->isPointerTy());
      expr->resetVarExprContext();
      return expr;
    }
    Bexpression *rval = genLoad(expr, nullptr, expr->location(), expr->tag());
    return rval;
  }
  return expr;
}

// This helper function takes a constant value and a specified type and tries to
// create an equivalent constant value using using the new type. It is designed
// primarily for aggreate types, but will work for other types as well.
//
// Background: conversions of aggregate constant values are a problem area for
// the bridge, due to the front end's use of placeholder types, and to the way
// that LLVM implements placeholders.
//
// For example, suppose that the front end creates a placholder struct type PH,
// then later on resolves the placeholder to the struct type "{ i64, i64 }". In
// the world of LLVM types, the resulting type is named (has name "PH") but is
// also a struct type with two fields.
//
// Elsewhere in the compilation constant struct value of "{ 13, 14 }" is created
// using an anonymous struct type T of the form "{ i64, i64 }". Since this type
// is not named, it has a separate, distinct LLVM type from PH.
//
// The front end sees these two types as equivalent, however, so it can often
// take constant values of type T and assign them (either directly or via an
// initializer) to variables of type PH (or vice versa), adding conversions if
// the backend types don't match. LLVM, however, doesn't allow you to convert an
// aggregate value V1 (with type T1) to another value V2 (with different type
// T2) using a bitcast -- the IR builder will reject the cast.
//
// One way around this is to take the address of V1, convert the resulting
// pointer to "pointer to T2", then dereference the pointer and assign
// the result to V2.
//
// This routine takes a different route, which is to pick apart the constant
// value (of type T1) and create an equivalent constant value of type T2.
// Note that if the types are sufficiently different (for example, different
// number of struct fields or different size) the process will fail and
// a null pointer will be returned.

llvm::Constant *Llvm_backend::genConvertedConstant(llvm::Constant *fromVal,
                                                   llvm::Type *llToType)
{
  llvm::Type *llFromType = fromVal->getType();
  if (llFromType == llToType)
    return fromVal;

  // There must be agreement in type class (struct -> struct, etc).
  bool isFromComposite = llvm::isa<llvm::CompositeType>(llFromType);
  bool isToComposite = llvm::isa<llvm::CompositeType>(llToType);
  if (isFromComposite != isToComposite)
    return nullptr;

  // If the type in question is not an aggregate, go ahead and
  // apply a bitcast to perform the conversion.
  LIRBuilder builder(context_, llvm::ConstantFolder());
  if (! isToComposite) {
    llvm::Value *bitcast = builder.CreatePointerBitCastOrAddrSpaceCast(fromVal, llToType);
    assert(llvm::isa<llvm::Constant>(bitcast));
    llvm::Constant *constCast = llvm::cast<llvm::Constant>(bitcast);
    return constCast;
  }

  // Collect disposition of type (struct vs array) and number of elements,
  // and weed out any clashes between 'from' and 'to' types.
  unsigned numElements = 0;
  bool isFromStructTy = llFromType->isStructTy();
  bool isToStructTy = llToType->isStructTy();
  if (isFromStructTy) {
    if (! isToStructTy)
      return nullptr;
    llvm::StructType *fromStTy = llvm::cast<llvm::StructType>(llFromType);
    llvm::StructType *toStTy = llvm::cast<llvm::StructType>(llToType);
    numElements = fromStTy->getNumElements();
    if (numElements != toStTy->getNumElements())
      return nullptr;
  } else {
    assert(llFromType->isArrayTy());
    if (! llToType->isArrayTy())
      return nullptr;
    llvm::ArrayType *fromArTy = llvm::cast<llvm::ArrayType>(llFromType);
    llvm::ArrayType *toArTy = llvm::cast<llvm::ArrayType>(llToType);
    numElements = fromArTy->getNumElements();
    if (numElements != toArTy->getNumElements())
      return nullptr;
  }

  // Do a lookup to see if we have a memoized value from a previous
  // conversion.
  auto candidate = std::make_pair(fromVal, llToType);
  auto it = genConvConstMap_.find(candidate);
  if (it != genConvConstMap_.end())
    return it->second;

  // Grab from/to types as composites.
  llvm::CompositeType *llFromCT = llvm::cast<llvm::CompositeType>(llFromType);
  llvm::CompositeType *llToCT = llvm::cast<llvm::CompositeType>(llToType);
  assert(llFromCT != nullptr);
  assert(llToCT != nullptr);

  // Walk through the child values and convert them.
  llvm::SmallVector<llvm::Constant *, 64> newvals(numElements);
  for (unsigned idx = 0; idx < numElements; idx++) {
    llvm::Type *toEltType = llToCT->getTypeAtIndex(idx);
    llvm::Constant *constElt = fromVal->getAggregateElement(idx);
    llvm::Constant *convElt = genConvertedConstant(constElt, toEltType);
    if (convElt == nullptr)
      return nullptr;
    newvals[idx] = convElt;
  }

  // Materialize final constant value.
  llvm::Constant *toVal = nullptr;
  if (llToType->isStructTy()) {
    llvm::StructType *llst = llvm::cast<llvm::StructType>(llToType);
    toVal = llvm::ConstantStruct::get(llst, newvals);
  } else {
    llvm::ArrayType *llat = llvm::cast<llvm::ArrayType>(llToType);
    toVal = llvm::ConstantArray::get(llat, newvals);
  }

  // Cache the result.
  genConvConstMap_[candidate] = toVal;

  // Return the final product.
  return toVal;
}


Bvariable *Llvm_backend::genVarForConstant(llvm::Constant *conval,
                                           Btype *type)
{
  auto it = genVarConstMap_.find(conval);
  if (it != genVarConstMap_.end())
    return it->second;

  std::string ctag(namegen("const"));
  Bvariable *rv = makeModuleVar(type, ctag, "", Location(),
                                MV_Constant, MV_DefaultSection,
                                MV_NotInComdat,
                                MV_NotExternallyInitialized, MV_SkipDebug,
                                llvm::GlobalValue::PrivateLinkage,
                                conval, 0);
  assert(llvm::isa<llvm::GlobalVariable>(rv->value()));
  genVarConstMap_[conval] = rv;
  return rv;
}

llvm::Value *Llvm_backend::genStore(BlockLIRBuilder *builder,
                                    Btype *srcType,
                                    bool srcConstant,
                                    llvm::Type *dstType,
                                    llvm::Value *srcVal,
                                    llvm::Value *dstLoc)
{
  // Don't try to emit a store if the value in question is void
  // (for example, the return value from a call to a function that
  // returns a struct with no fields). In this case just manufacture
  // an undef and return it.
  if (srcVal->getType()->isVoidTy() || typeSize(srcType) == 0)
    return llvm::UndefValue::get(srcVal->getType());

  // Decide whether we want a simple store instruction or a memcpy.
  if (! useCopyForLoadStore(srcType)) {

    if (srcVal->getType()->isPointerTy()) {
      llvm::PointerType *dstpt =
          llvm::cast<llvm::PointerType>(dstType);
      srcVal = convertForAssignment(srcType, srcVal,
                                    dstpt->getElementType(), builder);
    }

    // At this point the types should agree
    llvm::PointerType *dpt = llvm::cast<llvm::PointerType>(dstType);
    assert(srcVal->getType() == dpt->getElementType());

    // Create and return store
    return builder->CreateStore(srcVal, dstLoc);
  }

  // destination should be pointer
  assert(dstLoc->getType()->isPointerTy());

  // memcpy src: handle constant input (we need something addressable
  // in order to do a memcpy, not a raw constant value)
  if (srcConstant) {
    llvm::Constant *cval = llvm::cast<llvm::Constant>(srcVal);
    Bvariable *cvar = genVarForConstant(cval, srcType);
    srcVal = cvar->value();
  }
  assert(srcVal->getType()->isPointerTy());

  // number of bytes to copy
  uint64_t sz = typeSize(srcType);

  // alignment of src expr
  unsigned algn = typeAlignment(srcType);

  // Q: should we be using memmove here instead?
  llvm::CallInst *call = builder->CreateMemCpy(dstLoc, algn, srcVal, algn, sz);

  return call;
}

Bexpression *Llvm_backend::genStore(Bfunction *func,
                                    Bexpression *srcExpr,
                                    Bexpression *dstExpr,
                                    Location location)
{
  llvm::Function *dummyFcn = errorFunction_->function();
  BlockLIRBuilder builder(dummyFcn, this);

  Varexpr_context ctx = varContextDisp(srcExpr);

  // Resolve pending var exprs and/or composites
  Bexpression *valexp = resolve(srcExpr, ctx);

  // Call helper to generate instructions
  llvm::Value *val = valexp->value();
  llvm::Value *dst = dstExpr->value();
  llvm::Value *result = genStore(&builder, srcExpr->btype(),
                                 valexp->isConstant(),
                                 dstExpr->value()->getType(),
                                 val, dst);

  // Wrap result in a Bexpression
  Binstructions insns(builder.instructions());
  Bexpression *rval =
      nbuilder_.mkBinaryOp(OPERATOR_EQ, valexp->btype(), result,
                             dstExpr, valexp, insns, location);
  return rval;
}

Bexpression *Llvm_backend::genArrayInit(llvm::ArrayType *llat,
                                        Bexpression *expr,
                                        llvm::Value *storage)
{
  Location loc = expr->location();
  Btype *btype = expr->btype();
  std::vector<Bexpression *> aexprs = nbuilder_.extractChildenAndDestroy(expr);
  expr = nullptr;

  unsigned nElements = llat->getNumElements();
  assert(nElements == aexprs.size());

  llvm::Function *dummyFcn = errorFunction_->function();
  BlockLIRBuilder builder(dummyFcn, this);
  std::vector<Bexpression *> values;

  for (unsigned eidx = 0; eidx < nElements; ++eidx) {

    // Construct an appropriate GEP
    llvm::SmallVector<llvm::Value *, 2> elems(2);
    llvm::Value *idxval = llvm::ConstantInt::get(llvmInt32Type(), eidx);
    elems[0] = llvm::ConstantInt::get(llvmInt32Type(), 0);
    elems[1] = idxval;
    std::string tag(namegen("index"));
    llvm::Value *gep = builder.CreateGEP(llat, storage, elems, tag);

    // Resolve element value if needed
    Varexpr_context ctx = varContextDisp(aexprs[eidx]);
    Bexpression *valexp = resolve(aexprs[eidx], ctx);

    // Store field value into GEP
    genStore(&builder, valexp->btype(), valexp->isConstant(),
             gep->getType(), valexp->value(), gep);

    values.push_back(valexp);
  }

  Binstructions instructions(builder.instructions());
  Bexpression *arexp =
      nbuilder_.mkComposite(btype, storage, values, instructions, loc);
  return arexp;
}

Bexpression *Llvm_backend::genStructInit(llvm::StructType *llst,
                                         Bexpression *expr,
                                         llvm::Value *storage)
{
  Location loc = expr->location();
  Btype *btype = expr->btype();
  std::vector<Bexpression *> fexprs = nbuilder_.extractChildenAndDestroy(expr);
  expr = nullptr;
  unsigned nFields = llst->getNumElements();
  assert(nFields == fexprs.size());

  llvm::Function *dummyFcn = errorFunction_->function();
  BlockLIRBuilder builder(dummyFcn, this);
  std::vector<Bexpression *> values;

  for (unsigned fidx = 0; fidx < nFields; ++fidx) {
    Bexpression *fieldValExpr = fexprs[fidx];
    assert(fieldValExpr);

    Varexpr_context ctx = varContextDisp(fieldValExpr);
    Bexpression *valexp = resolve(fieldValExpr, ctx);

    // Create GEP
    assert(fidx < llst->getNumElements());
    std::string tag(namegen("field"));
    llvm::Value *gep =
        builder.CreateConstInBoundsGEP2_32(llst, storage,
                                           0, fidx, tag);

    // Store field value into GEP
    genStore(&builder, valexp->btype(), valexp->isConstant(),
             gep->getType(), valexp->value(), gep);

    values.push_back(valexp);
  }

  Binstructions instructions(builder.instructions());
  Bexpression *structexp =
      nbuilder_.mkComposite(btype, storage, values, instructions, loc);
  return structexp;
}

Bexpression *Llvm_backend::resolveCompositeInit(Bexpression *expr,
                                                llvm::Value *storage)
{
  assert(expr != errorExpression());
  bool setPending = false;
  Bvariable *tvar = nullptr;
  if (!storage) {
    std::string tname(namegen("tmp"));
    tvar = nbuilder_.mkTempVar(expr->btype(), expr->location(), tname);
    assert(tvar != errorVariable_.get());
    storage = tvar->value();
    setPending = true;
  }

  // Call separate helper depending on array or struct
  llvm::Type *llt = expr->btype()->type();
  assert(llt->isStructTy() || llt->isArrayTy());
  Bexpression *rval = nullptr;
  if (llt->isStructTy()) {
    llvm::StructType *llst = llvm::cast<llvm::StructType>(llt);
    rval = genStructInit(llst, expr, storage);
  } else {
    llvm::ArrayType *llat = llvm::cast<llvm::ArrayType>(llt);
    rval = genArrayInit(llat, expr, storage);
  }
  if (setPending) {
    rval->setVarExprPending(false, 0);
    tvar->setInitializerExpr(rval);
  }
  return rval;
}

Varexpr_context Llvm_backend::varContextDisp(Bexpression *varexp)
{
  if (useCopyForLoadStore(varexp->btype()))
    return VE_lvalue;
  return VE_rvalue;
}

// Create a temporary variable holding the value of EXPR.
// Return the variable and the assignment statement (to be
// attached to some node).

std::pair<Bvariable*, Bstatement*>
Llvm_backend::makeTempVar(Bexpression *expr, Location location) {
  assert(expr);
  std::string tname(namegen("tmp"));
  Bvariable *var = nbuilder_.mkTempVar(expr->btype(), location, tname);
  assert(var != errorVariable_.get());
  Bfunction *dummyFcn = errorFunction_.get();
  Bstatement *init = makeInitStatement(dummyFcn, var, expr);
  assert(init != errorStatement_);
  return std::make_pair(var, init);
}

// An expression that references a variable.

Bexpression *Llvm_backend::var_expression(Bvariable *var,
                                          Location location)
{
  if (var == errorVariable_.get())
    return errorExpression();

  // Normal case
  llvm::Value *varval = var->value();

  // Special case for zero-sized globals. These require a type conversion,
  // since the underlying definition has been coerced to something with
  // non-zero size (as a means of avoiding linker misbehavior).
  Btype *underlyingType = var->underlyingType();
  if (underlyingType != nullptr) {
    LIRBuilder irbuilder(context_, llvm::ConstantFolder());
    std::string tag(namegen("zeroSizeCast"));
    llvm::Type *toType = llvm::PointerType::get(var->btype()->type(),
                                                addressSpace_);
    llvm::Value *bitcast =
        irbuilder.CreateBitCast(var->value(), toType, tag);
    varval = bitcast;
  }

  Bexpression *varexp = nbuilder_.mkVar(var, varval, location);
  varexp->setTag(var->name().c_str());
  return varexp;
}

// Return an expression that declares a constant named NAME with the
// constant value VAL in BTYPE.

Bexpression *Llvm_backend::named_constant_expression(Btype *btype,
                                                     const std::string &name,
                                                     Bexpression *val,
                                                     Location location) {
  if (btype == errorType() || val == errorExpression())
    return errorExpression();

  // FIXME: declare named read-only variable with initial value 'val'

  return val;
}

template <typename wideint_t>
wideint_t checked_convert_mpz_to_int(mpz_t value) {
  // See http://gmplib.org/manual/Integer-Import-and-Export.html for an
  // explanation of this formula
  size_t numbits = 8 * sizeof(wideint_t);
  size_t count = (mpz_sizeinbase(value, 2) + numbits - 1) / numbits;
  // frontend should have insured this already
  assert(count <= 2);
  count = 2;
  wideint_t receive[2];
  receive[0] = 0;
  receive[1] = 0;
  mpz_export(&receive[0], &count, -1, sizeof(wideint_t), 0, 0, value);
  // frontend should have insured this already
  assert(receive[1] == 0);
  wideint_t rval = receive[0];
  if (mpz_sgn(value) < 0)
    rval = -rval;
  return rval;
}

// Return a typed value as a constant integer.

Bexpression *Llvm_backend::integer_constant_expression(Btype *btype,
                                                       mpz_t mpz_val) {
  if (btype == errorType())
    return errorExpression();
  assert(btype->type()->isIntegerTy());

  // Force mpz_val into either into uint64_t or int64_t depending on
  // whether btype was declared as signed or unsigned.

  Bexpression *rval;
  BIntegerType *bit = btype->castToBIntegerType();
  if (bit->isUnsigned()) {
    uint64_t val = checked_convert_mpz_to_int<uint64_t>(mpz_val);
    llvm::APInt apiv(bit->bits(), val);
    llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), apiv);
    Bexpression *bconst = nbuilder_.mkConst(btype, lval);
    return makeGlobalExpression(bconst, lval, btype, Location());
  } else {
    int64_t val = checked_convert_mpz_to_int<int64_t>(mpz_val);
    llvm::APInt apiv(bit->bits(), val, true);
    llvm::Constant *lval = llvm::ConstantInt::get(btype->type(), apiv);
    Bexpression *bconst = nbuilder_.mkConst(btype, lval);
    return makeGlobalExpression(bconst, lval, btype, Location());
  }
  return rval;
}

Bexpression *Llvm_backend::makeIntegerOneExpr()
{
  llvm::Constant *one = llvm::ConstantInt::get(uintPtrType()->type(), 1);
  Bexpression *bconst = nbuilder_.mkConst(uintPtrType(), one);
  return makeGlobalExpression(bconst, one, uintPtrType(), Location());
}

// Return a typed value as a constant floating-point number.

Bexpression *Llvm_backend::float_constant_expression(Btype *btype, mpfr_t val) {
  if (btype == errorType())
    return errorExpression();

  // Force the mpfr value into float, double, or APFloat as appropriate.
  //
  // Note: at the moment there is no way to create an APFloat from a
  // "long double" value, so this code takes the unpleasant step of
  // converting a quad mfr value from text and then back into APFloat
  // from there.

  if (btype->type() == llvmFloatType()) {
    float fval = mpfr_get_flt(val, GMP_RNDN);
    llvm::APFloat apf(fval);
    llvm::Constant *fcon = llvm::ConstantFP::get(context_, apf);
    Bexpression *bconst = nbuilder_.mkConst(btype, fcon);
    return makeGlobalExpression(bconst, fcon, btype, Location());
  } else if (btype->type() == llvmDoubleType()) {
    double dval = mpfr_get_d(val, GMP_RNDN);
    llvm::APFloat apf(dval);
    llvm::Constant *fcon = llvm::ConstantFP::get(context_, apf);
    Bexpression *bconst = nbuilder_.mkConst(btype, fcon);
    return makeGlobalExpression(bconst, fcon, btype, Location());
  } else if (btype->type() == llvmLongDoubleType()) {
    assert("not yet implemented" && false);
    return nullptr;
  } else {
    return errorExpression();
  }
}

// Return a typed real and imaginary value as a constant complex number.

Bexpression *Llvm_backend::complex_constant_expression(Btype *btype,
                                                       mpc_t val) {
  if (btype == errorType())
    return errorExpression();

  BComplexType *bct = btype->castToBComplexType();
  assert(bct);
  llvm::Type *llt = btype->type();
  assert(llt->isStructTy());
  llvm::StructType *llst = llvm::cast<llvm::StructType>(llt);
  assert(llst->getNumElements() == 2);
  llvm::Type *llet = llst->getElementType(0);
  assert(llet == llst->getElementType(1));

  std::vector<Bexpression *> exps;

  if (llet == llvmFloatType()) {
    float frval = mpfr_get_flt(mpc_realref(val), GMP_RNDN);
    float fival = mpfr_get_flt(mpc_imagref(val), GMP_RNDN);
    llvm::APFloat apr(frval);
    llvm::APFloat api(fival);
    llvm::Constant *rcon = llvm::ConstantFP::get(context_, apr);
    llvm::Constant *icon = llvm::ConstantFP::get(context_, api);

    Btype *bet = floatType(32);
    Bexpression *brcon = nbuilder_.mkConst(bet, rcon);
    Bexpression *bicon = nbuilder_.mkConst(bet, icon);
    exps.push_back(brcon);
    exps.push_back(bicon);
  } else if (llet == llvmDoubleType()) {
    double drval = mpfr_get_d(mpc_realref(val), GMP_RNDN);
    double dival = mpfr_get_d(mpc_imagref(val), GMP_RNDN);
    llvm::APFloat apr(drval);
    llvm::APFloat api(dival);
    llvm::Constant *rcon = llvm::ConstantFP::get(context_, apr);
    llvm::Constant *icon = llvm::ConstantFP::get(context_, api);

    Btype *bet = floatType(64);
    Bexpression *brcon = nbuilder_.mkConst(bet, rcon);
    Bexpression *bicon = nbuilder_.mkConst(bet, icon);
    exps.push_back(brcon);
    exps.push_back(bicon);
  } else {
    assert(false && "unknown complex type");
    return nullptr;
  }

  return makeConstCompositeExpr(btype, llst, 2, nullptr, exps, Location());
}

// Make a constant string expression.

Bexpression *Llvm_backend::string_constant_expression(const std::string &val)
{
  if (val.size() == 0) {
    llvm::Value *zer = llvm::Constant::getNullValue(stringType()->type());
    Bexpression *bconst = nbuilder_.mkConst(stringType(), zer);
    return makeGlobalExpression(bconst, zer, stringType(), Location());
  }

  // Create constant
  bool doAddNull = true;
  llvm::Constant *scon =
      llvm::ConstantDataArray::getString(context_,
                                         llvm::StringRef(val),
                                         doAddNull);

  // Return existing const if installed in table already.
  auto it = stringConstantMap_.find(scon);
  if (it != stringConstantMap_.end())
    return it->second;

  // New string. Manufacture a module-scope var to hold the constant,
  // then install various maps.
  std::string ctag(namegen("const"));
  Bvariable *svar =
      makeModuleVar(makeAuxType(scon->getType()),
                    ctag, "", Location(), MV_Constant, MV_DefaultSection,
                    MV_NotInComdat, MV_NotExternallyInitialized,
                    MV_SkipDebug, llvm::GlobalValue::PrivateLinkage,
                    scon, 1);
  llvm::Constant *varval = llvm::cast<llvm::Constant>(svar->value());
  llvm::Constant *bitcast =
      llvm::ConstantExpr::getBitCast(varval, stringType()->type());
  Bexpression *bconst = nbuilder_.mkConst(stringType(), bitcast);
  Bexpression *rval =
      makeGlobalExpression(bconst, bitcast, stringType(), Location());
  stringConstantMap_[scon] = rval;
  return rval;
}

// Make a constant boolean expression.

Bexpression *Llvm_backend::boolean_constant_expression(bool val) {
  LIRBuilder builder(context_, llvm::ConstantFolder());
  llvm::Value *con = (val ? llvm::ConstantInt::getTrue(context_)
                          : llvm::ConstantInt::getFalse(context_));
  llvm::Value *tobool = builder.CreateZExt(con, bool_type()->type(), "");

  Bexpression *bconst = nbuilder_.mkConst(bool_type(), tobool);
  return makeGlobalExpression(bconst, tobool, bool_type(), Location());
}

// Return the real part of a complex expression.

Bexpression *Llvm_backend::real_part_expression(Bexpression *bcomplex,
                                                Location location)
{
  if (bcomplex == errorExpression())
    return errorExpression();

  BComplexType *bct = bcomplex->btype()->castToBComplexType();
  assert(bct);
  Btype *bft = elementTypeByIndex(bct, 0);
  unsigned fIndex = 0;
  Bexpression *rval = nbuilder_.mkStructField(bft, nullptr,
                                              bcomplex, fIndex, location);
  rval->setTag(".real");
  return rval;
}

// Return the imaginary part of a complex expression.

Bexpression *Llvm_backend::imag_part_expression(Bexpression *bcomplex,
                                                Location location) {
  if (bcomplex == errorExpression())
    return errorExpression();

  BComplexType *bct = bcomplex->btype()->castToBComplexType();
  assert(bct);
  Btype *bft = elementTypeByIndex(bct, 0);
  unsigned fIndex = 1;
  Bexpression *rval = nbuilder_.mkStructField(bft, nullptr,
                                              bcomplex, fIndex, location);
  rval->setTag(".imag");
  return rval;
}

// Make a complex expression given its real and imaginary parts.

Bexpression *Llvm_backend::complex_expression(Bexpression *breal,
                                              Bexpression *bimag,
                                              Location location) {
  if (breal == errorExpression() || bimag == errorExpression())
    return errorExpression();

  BFloatType *brft = breal->btype()->castToBFloatType();
  BFloatType *bift = bimag->btype()->castToBFloatType();
  assert(brft && bift);
  assert(brft->bits() == bift->bits());
  Btype *bct = complexType(brft->bits()*2);
  std::vector<Bexpression *> vals = { breal, bimag };
  Binstructions noInstructions;
  Bexpression *rval = nbuilder_.mkComposite(bct, nullptr, vals,
                                            noInstructions, location);
  return rval;
}

Bexpression *Llvm_backend::makeComplexConvertExpr(Btype *type,
                                                  Bexpression *expr,
                                                  Location location) {
  if (expr->btype()->type() == type->type())
    return expr;

  BComplexType *bct = type->castToBComplexType();
  assert(bct);
  assert(expr->btype()->castToBComplexType());
  Btype *bft = floatType(bct->bits()/2);

  // We need to avoid sharing between real part and imag part of the operand.
  // Create temp variables and assign operand to the temp variable first.
  // TODO: maybe not make temp var if the operand is already a var or constant?
  auto p = makeTempVar(expr, location);
  Bvariable *var = p.first;
  Bstatement *einit = p.second;

  Bexpression *vex = nbuilder_.mkVar(var, var->value(), location);
  vex->setVarExprPending(false, 0);
  Bexpression *vexr = real_part_expression(vex, location);
  Bexpression *vexi = imag_part_expression(vex, location);

  // Make the conversion
  Bexpression *valr = convert_expression(bft, vexr, location);
  Bexpression *vali = convert_expression(bft, vexi, location);
  Bexpression *val = complex_expression(valr, vali, location);

  // Wrap result and the init statements in a compound expression.
  // Currently we can't resolve composite storage for compound
  // expression, so we resolve the inner complex expression
  // here with another temp variable.
  auto p2 = makeTempVar(val, location);
  Bvariable *rvar = p2.first;
  Bstatement *rinit = p2.second;
  Bexpression *rvex = nbuilder_.mkVar(rvar, rvar->value(), location);
  Bstatement *init = statement_list(std::vector<Bstatement*>{einit, rinit});
  return nbuilder_.mkCompound(init, rvex, nullptr, location);
}

// An expression that converts an expression to a different type.

Bexpression *Llvm_backend::convert_expression(Btype *type,
                                              Bexpression *expr,
                                              Location location)
{
  if (type == errorType() || expr == errorExpression())
    return errorExpression();
  if (expr->btype() == type)
    return expr;

  // When the frontend casts something to function type, what this
  // really means in the LLVM realm is "pointer to function" type.
  llvm::Type *toType = type->type();
  if (toType->isFunctionTy()) {
    type = pointer_type(type);
    toType = type->type();
  }

  // Complex -> complex conversion
  if (type->castToBComplexType())
    return makeComplexConvertExpr(type, expr, location);

  Bexpression *rval = nbuilder_.mkConversion(type, nullptr, expr, location);
  return rval;
}

// Get the address of a function.

Bexpression *Llvm_backend::function_code_expression(Bfunction *bfunc,
                                                    Location location) {
  if (bfunc == errorFunction_.get())
    return errorExpression();

  // Look up pointer-to-function type.
  // Function is always in address space 0.
  Btype *fpBtype = addrSpacePointerType(bfunc->fcnType(), 0);

  llvm::Constant *fpval = bfunc->fcnValue();

  // Create an address-of-function expr
  Bexpression *fexpr = nbuilder_.mkFcnAddress(fpBtype, fpval,
                                              bfunc, location);
  return makeGlobalExpression(fexpr, fpval, fpBtype, location);
}

// Return an expression for the field at INDEX in BSTRUCT.

Bexpression *Llvm_backend::struct_field_expression(Bexpression *bstruct,
                                                   size_t index,
                                                   Location location)
{
  if (bstruct == errorExpression())
    return errorExpression();

  Btype *bft = elementTypeByIndex(bstruct->btype(), index);
  Bexpression *rval = nbuilder_.mkStructField(bft, nullptr,
                                              bstruct, index, location);
  return rval;
}

// Return an expression that executes BSTAT before BEXPR.

Bexpression *Llvm_backend::compound_expression(Bstatement *bstat,
                                               Bexpression *bexpr,
                                               Location location)
{
  if (bstat == errorStatement() || bexpr == errorExpression())
    return errorExpression();

  Bexpression *rval = nbuilder_.mkCompound(bstat, bexpr, nullptr, location);
  return rval;
}

// Return an expression that executes THEN_EXPR if CONDITION is true, or
// ELSE_EXPR otherwise.

Bexpression *Llvm_backend::conditional_expression(Bfunction *function,
                                                  Btype *btype,
                                                  Bexpression *condition,
                                                  Bexpression *then_expr,
                                                  Bexpression *else_expr,
                                                  Location location)
{
  if (function == errorFunction_.get() ||
      btype == errorType() ||
      condition == errorExpression() ||
      then_expr == errorExpression() ||
      else_expr == errorExpression())
    return errorExpression();

  assert(condition && then_expr);

  Bexpression *rval =
      nbuilder_.mkConditional(function, btype, condition,
                              then_expr, else_expr, location);
  return rval;
}

// Return an expression for the unary operation OP EXPR.

Bexpression *Llvm_backend::unary_expression(Operator op,
                                            Bexpression *expr,
                                            Location location)
{
  if (expr == errorExpression())
    return errorExpression();

  Btype *bt = expr->btype();

  if (op == OPERATOR_MINUS) {
    // Special handling for unary minus applied to fp type.
    BFloatType *ft = bt->castToBFloatType();
    Bexpression *zerexp = (ft ? minusZeroExpr(ft) : zero_expression(bt));
    return binary_expression(OPERATOR_MINUS, zerexp, expr, location);
  }

  Bexpression *rval = nbuilder_.mkUnaryOp(op, bt, nullptr, expr, location);
  return rval;
}

Bexpression *Llvm_backend::minusZeroExpr(BFloatType *typ)
{
  assert(typ);
  llvm::Constant *nzcon = llvm::ConstantFP::getNegativeZero(typ->type());
  Bexpression *bconst = nbuilder_.mkConst(typ, nzcon);
  return makeGlobalExpression(bconst, nzcon, typ, Location());
}

Bexpression *Llvm_backend::makeComplexBinaryExpr(Operator op, Bexpression *left,
                                                 Bexpression *right,
                                                 Location location) {
  // We need to avoid sharing between real part and imag part of the operand.
  // Create temp variables and assign operands to the temp vars first.
  // TODO: maybe not make temp var if the operand is already a var or constant?
  auto p = makeTempVar(left, location), p2 = makeTempVar(right, location);
  Bvariable *lvar = p.first, *rvar = p2.first;
  Bstatement *linit = p.second, *rinit = p2.second;

  Bexpression *lvex = nbuilder_.mkVar(lvar, lvar->value(), location);
  lvex->setVarExprPending(false, 0);
  Bexpression *rvex = nbuilder_.mkVar(rvar, rvar->value(), location);
  rvex->setVarExprPending(false, 0);
  Bexpression *lr = real_part_expression(lvex, location);
  Bexpression *li = imag_part_expression(lvex, location);
  Bexpression *rr = real_part_expression(rvex, location);
  Bexpression *ri = imag_part_expression(rvex, location);
  Bexpression *val;

  switch (op) {
  case OPERATOR_PLUS:
  case OPERATOR_MINUS: {
    Bexpression *valr = binary_expression(op, lr, rr, location);
    Bexpression *vali = binary_expression(op, li, ri, location);
    val = complex_expression(valr, vali, location);
    break;
  }
  case OPERATOR_MULT: {
    // (a+bi)*(c+di) = (ac-bd) + (ad+bc)i
    Bexpression *ac = binary_expression(OPERATOR_MULT, lr, rr, location);
    Bexpression *bd = binary_expression(OPERATOR_MULT, li, ri, location);
    Bexpression *ad = binary_expression(OPERATOR_MULT, lr, ri, location);
    Bexpression *bc = binary_expression(OPERATOR_MULT, li, rr, location);
    Bexpression *valr = binary_expression(OPERATOR_MINUS, ac, bd, location);
    Bexpression *vali = binary_expression(OPERATOR_PLUS, ad, bc, location);
    val = complex_expression(valr, vali, location);
    break;
  }
  case OPERATOR_EQEQ:
  case OPERATOR_NOTEQ: {
    Bexpression *cmpr = binary_expression(op, lr, rr, location);
    Bexpression *cmpi = binary_expression(op, li, ri, location);
    if (op == OPERATOR_EQEQ)
      val = binary_expression(OPERATOR_ANDAND, cmpr, cmpi, location);
    else
      val = binary_expression(OPERATOR_OROR, cmpr, cmpi, location);
    Bstatement *init = statement_list(std::vector<Bstatement*>{linit, rinit});
    return materialize(compound_expression(init, val, location));
  }
  default:
    std::cerr << "Op " << op << " unhandled\n";
    assert(false);
  }

  // Wrap result and the init statements in a compound expression.
  // Currently we can't resolve composite storage for compound
  // expression, so we resolve the inner complex expression
  // here with another temp variable.
  auto p3 = makeTempVar(val, location);
  Bvariable *vvar = p3.first;
  Bstatement *vinit = p3.second;
  Bexpression *vvex = nbuilder_.mkVar(vvar, vvar->value(), location);
  Bstatement *init = statement_list(std::vector<Bstatement*>{linit, rinit, vinit});
  return compound_expression(init, vvex, location);
}

// Return an expression for the binary operation LEFT OP RIGHT.

Bexpression *Llvm_backend::binary_expression(Operator op, Bexpression *left,
                                             Bexpression *right,
                                             Location location) {
  if (left == errorExpression() || right == errorExpression())
    return errorExpression();

  Btype *bltype = left->btype();
  Btype *brtype = right->btype();
  BComplexType *blctype = bltype->castToBComplexType();
  BComplexType *brctype = brtype->castToBComplexType();
  assert((blctype == nullptr) == (brctype == nullptr));
  if (blctype)
    return makeComplexBinaryExpr(op, left, right, location);

  // Arbitrarily select the left child type as the type for the binop.
  // This may be revised later during materializeBinary.
  // The FE should have handled operations with aggregate types, e.g.
  // string concatenation or comparisons of structs/arrays.
  assert(!bltype->type()->isAggregateType());
  Bexpression *rval =
      nbuilder_.mkBinaryOp(op, bltype, nullptr, left, right, location);
  return rval;
}

bool
Llvm_backend::valuesAreConstant(const std::vector<Bexpression *> &vals)
{
  for (auto &val : vals)
    if (!val->isConstant())
       return false;
  return true;
}

// Return an expression that constructs BTYPE with VALS.

Bexpression *Llvm_backend::constructor_expression(
    Btype *btype, const std::vector<Bexpression *> &vals, Location location) {
  if (btype == errorType() || exprVectorHasError(vals))
    return errorExpression();

  Binstructions noInstructions;
  Bexpression *rval = nbuilder_.mkComposite(btype, nullptr, vals,
                                            noInstructions, location);
  return rval;
}

Bexpression *Llvm_backend::array_constructor_expression(
    Btype *array_btype, const std::vector<unsigned long> &indexes,
    const std::vector<Bexpression *> &vals, Location location)
{
  if (array_btype == errorType() || exprVectorHasError(vals))
    return errorExpression();

  Binstructions noInstructions;
  Bexpression *rval =
      nbuilder_.mkIndexedComposite(array_btype, nullptr, vals,
                                   indexes, noInstructions, location);
  return rval;
}

// Return an expression for the address of BASE[INDEX].

Bexpression *Llvm_backend::pointer_offset_expression(Bexpression *base,
                                                     Bexpression *index,
                                                     Location location) {
  if (base == errorExpression() || index == errorExpression())
    return errorExpression();

  Bexpression *rval = nbuilder_.mkPointerOffset(base->btype(), nullptr,
                                                base, index, location);
  return rval;
}

// Return an expression representing ARRAY[INDEX]

Bexpression *Llvm_backend::array_index_expression(Bexpression *barray,
                                                  Bexpression *index,
                                                  Location location)
{
  if (barray == errorExpression() || index == errorExpression())
    return errorExpression();

  Btype *bet = elementTypeByIndex(barray->btype(), 0);
  Bexpression *rval =
      nbuilder_.mkArrayIndex(bet, nullptr, barray, index, location);
  return rval;
}

// Create an expression for a call to FN_EXPR with FN_ARGS.
Bexpression *
Llvm_backend::call_expression(Bfunction *caller,
                              Bexpression *fn_expr,
                              const std::vector<Bexpression *> &fn_args,
                              Bexpression *chain_expr,
                              Location location) {
  if (fn_expr == errorExpression() || exprVectorHasError(fn_args) ||
      chain_expr == errorExpression())
    return errorExpression();

  BFunctionType *ft = unpackFunctionType(fn_expr->btype());
  Btype *rbtype = ft->resultType();
  Binstructions noInstructions;
  if (!chain_expr)
    chain_expr = nbuilder_.mkVoidValue(void_type());
  Bexpression *rval = nbuilder_.mkCall(rbtype, nullptr, caller,
                                       fn_expr, chain_expr, fn_args,
                                       noInstructions, location);
  return rval;
}

Bstatement *Llvm_backend::error_statement()
{
  errorCount_++;
  return errorStatement();
}

// An expression as a statement.

Bstatement *Llvm_backend::expression_statement(Bfunction *bfunction,
                                               Bexpression *expr)
{
  if (expr == errorExpression() || bfunction == errorFunction_.get())
    return errorStatement();
  expr = materialize(expr);
  Bstatement *es =
      nbuilder_.mkExprStmt(bfunction, resolve(expr), expr->location());
  return es;
}

// Variable initialization.

Bstatement *Llvm_backend::init_statement(Bfunction *bfunction,
                                         Bvariable *var,
                                         Bexpression *init)
{
  if (var == errorVariable_.get() || init == errorExpression() ||
      bfunction == errorFunction_.get())
    return errorStatement();

  return makeInitStatement(bfunction, var, init);
}

Bstatement *Llvm_backend::makeInitStatement(Bfunction *bfunction,
                                            Bvariable *var,
                                            Bexpression *init)
{
  if (init) {
    if (traceLevel() > 1) {
      std::cerr << "\n^ init statement " << ((void*)var)
                << " = " << ((void*)init) << "\n";
      std::cerr << "\nLHS:\n";
      var->dump();
      std::cerr << "\nRHS:\n";
      init->dump();
    }

    init = materialize(init);
    if (init->compositeInitPending()) {
      init = resolveCompositeInit(init, var->value());
      Bstatement *es = nbuilder_.mkExprStmt(bfunction, init,
                                            init->location());
      var->setInitializer(es->getExprStmtExpr()->value());
      return es;
    }
  } else {
    init = zero_expression(var->btype());
  }
  Bexpression *varexp = nbuilder_.mkVar(var, var->value(), var->location());
  Bstatement *st = makeAssignment(bfunction, var->value(),
                                  varexp, init, Location());
  llvm::Value *ival = st->getExprStmtExpr()->value();
  if (! llvm::isa<llvm::UndefValue>(ival))
    var->setInitializer(ival);
  return st;
}

Bstatement *Llvm_backend::makeAssignment(Bfunction *function,
                                         llvm::Value *lval, Bexpression *lhs,
                                         Bexpression *rhs, Location location)
{
  assert(lval->getType()->isPointerTy());

  // This cases should have been handled in the caller
  assert(!rhs->compositeInitPending());

  // Invoke helper to create store or memcpy
  Bexpression *stexp = genStore(function, rhs, lhs, location);

  // Return wrapped in statement
  return nbuilder_.mkExprStmt(function, stexp, location);
}

// Assignment.

Bstatement *Llvm_backend::assignment_statement(Bfunction *bfunction,
                                               Bexpression *lhs,
                                               Bexpression *rhs,
                                               Location location) {
  if (lhs == errorExpression() || rhs == errorExpression() ||
      bfunction == errorFunction_.get())
    return errorStatement();

  if (traceLevel() > 1) {
    std::cerr << "\n^ assignment statement " << ((void*)lhs)
              << " = " << ((void*)rhs) << "\n";
    std::cerr << "\nLHS:\n";
    lhs->dump();
    std::cerr << "\nRHS:\n";
    rhs->dump();
  }

  lhs = materialize(lhs, VE_lvalue);
  rhs = materialize(rhs);
  Bexpression *lhs2 = resolveVarContext(lhs, VE_lvalue);
  Bexpression *rhs2 = rhs;
  if (rhs->compositeInitPending()) {
    rhs2 = resolveCompositeInit(rhs, lhs2->value());
    Bexpression *stexp =
        nbuilder_.mkBinaryOp(OPERATOR_EQ, voidType(), lhs2->value(),
                             lhs2, rhs2, location);
    Bstatement *es = nbuilder_.mkExprStmt(bfunction, stexp, location);
    return es;
  }

  Bstatement *st = makeAssignment(bfunction, lhs->value(),
                                  lhs2, rhs2, location);
  return st;
}

Bstatement*
Llvm_backend::return_statement(Bfunction *bfunction,
                               const std::vector<Bexpression *> &vals,
                               Location location)
{
  if (bfunction == errorFunction_.get() || exprVectorHasError(vals))
    return errorStatement();

  // Materialize llvm instructions/values for the return vals.
  std::vector<Bexpression *> materializedVals;
  for (auto &val : vals)
    materializedVals.push_back(materialize(val));

  // Resolve arguments
  std::vector<Bexpression *> resolvedVals;
  for (auto &val : materializedVals)
    resolvedVals.push_back(resolve(val, varContextDisp(val)));

  // Collect up the return value
  Bexpression *toret = nullptr;
  if (vals.size() == 0) {
    // The return Bexpression node has a single child, so in the case
    // of the void function, create a dummy return value (easier than
    // making return a variadic node).
    toret = nbuilder_.mkConst(voidType(),
                              llvm::UndefValue::get(llvmVoidType()));
  } else if (vals.size() == 1) {
    toret = resolvedVals[0];
  } else {
    Btype *rtyp = bfunction->fcnType()->resultType();
    Bexpression *structVal =
        materialize(constructor_expression(rtyp, resolvedVals, location));
    if (structVal->compositeInitPending()) {
      structVal = resolveCompositeInit(structVal, nullptr);
    } else if (structVal->isConstant()) {
      llvm::Constant *cval = llvm::cast<llvm::Constant>(structVal->value());
      Bvariable *cv = genVarForConstant(cval, structVal->btype());
      structVal = var_expression(cv, location);
      structVal = materialize(address_expression(structVal, location));
    }
    toret = structVal;
  }

  Binstructions retInsns;
  llvm::Value *rval = bfunction->genReturnSequence(toret, &retInsns, this);
  llvm::ReturnInst *ri = llvm::ReturnInst::Create(context_, rval);
  toret->appendInstructions(retInsns.instructions());
  toret->appendInstruction(ri);
  Bstatement *rst =
      nbuilder_.mkReturn(bfunction, toret, location);
  return rst;
}

// Create a statement that attempts to execute BSTAT and calls EXCEPT_STMT if an
// error occurs.  EXCEPT_STMT may be NULL.  FINALLY_STMT may be NULL and if not
// NULL, it will always be executed.  This is used for handling defers in Go
// functions.  In C++, the resulting code is of this form:
//   try { BSTAT; } catch { EXCEPT_STMT; } finally { FINALLY_STMT; }

Bstatement *Llvm_backend::exception_handler_statement(Bstatement *bstat,
                                                      Bstatement *except_stmt,
                                                      Bstatement *finally_stmt,
                                                      Location location)
{
  if (bstat == errorStatement() ||
      except_stmt == errorStatement() ||
      finally_stmt == errorStatement())
    return errorStatement();

  Bfunction *func = bstat->function();
  assert(func == except_stmt->function());
  assert(!finally_stmt || func == finally_stmt->function());

  std::string tname(namegen("finvar"));
  Bvariable *tvar = func->localVariable(tname, boolType(),
                                        nullptr, false, location);
  tvar->markAsTemporary();
  Bstatement *excepst = nbuilder_.mkExcepStmt(func, bstat,
                                              except_stmt,
                                              finally_stmt, tvar,
                                              location);
  return excepst;
}

// If statement.

Bstatement *Llvm_backend::if_statement(Bfunction *bfunction,
                                       Bexpression *condition,
                                       Bblock *then_block, Bblock *else_block,
                                       Location location) {
  if (condition == errorExpression() || then_block->hasError())
    return errorStatement();
  if (else_block && else_block->hasError())
    return errorStatement();
  Btype *bt = makeAuxType(llvmBoolType());
  Bexpression *conv = convert_expression(bt, condition, location);
  conv = materialize(conv);
  assert(then_block);

  Bstatement *ifst = nbuilder_.mkIfStmt(bfunction, conv, then_block,
                                        else_block, location);
  return ifst;
}

// Switch.

Bstatement *Llvm_backend::switch_statement(Bfunction *bfunction,
                                           Bexpression *value,
    const std::vector<std::vector<Bexpression *>> &cases,
    const std::vector<Bstatement *> &statements, Location switch_location)
{
  // Error handling
  if (value == errorExpression())
    return errorStatement();
  for (auto casev : cases)
    if (exprVectorHasError(casev))
      return errorStatement();
  if (stmtVectorHasError(statements))
      return errorStatement();

  value = materialize(value);

  // Resolve value
  value = resolve(value);

  // Case expressions are expected to be constants for this flavor of switch
  for (auto &bexpvec : cases)
    for (auto &exp : bexpvec)
      if (! llvm::cast<llvm::Constant>(exp->value()))
        go_assert(false && "bad case value expression");

  // Store results stmt
  Bstatement *swst =
      nbuilder_.mkSwitchStmt(bfunction, value, cases, statements,
                             switch_location);
  return swst;
}

// Pair of statements.

Bstatement *Llvm_backend::compound_statement(Bstatement *s1, Bstatement *s2) {
  if (s1 == errorStatement() || s2 == errorStatement())
    return errorStatement();

  assert(!s1->function() || !s2->function() ||
         s1->function() == s2->function());

  std::vector<Bstatement *> stvec;
  stvec.push_back(s1);
  stvec.push_back(s2);
  return statement_list(stvec);
}

// List of statements.

Bstatement *
Llvm_backend::statement_list(const std::vector<Bstatement *> &statements) {

  Bfunction *func = nullptr;
  for (auto &st : statements) {
    if (st == errorStatement())
      return errorStatement();
    if (st->function()) {
      if (func)
        assert(st->function() == func);
      else
        func = st->function();
    }
  }

  std::vector<Bvariable *> novars;
  Bblock *block = nbuilder_.mkBlock(func, novars, Location());
  for (auto &st : statements)
    nbuilder_.addStatementToBlock(block, st);
  return block;
}

Bblock *Llvm_backend::block(Bfunction *function, Bblock *enclosing,
                            const std::vector<Bvariable *> &vars,
                            Location start_location, Location) {
  assert(function);

  // FIXME: record debug location

  // Create new Bblock
  Bblock *bb = nbuilder_.mkBlock(function, vars, start_location);
  function->addBlock(bb);

  // FIXME:
  // Mark start and end of lifetime for each variable
  // for (auto var : vars) {
  //   Not yet implemented
  // }

  return bb;
}

// Add statements to a block.

void Llvm_backend::block_add_statements(Bblock *bblock,
                           const std::vector<Bstatement *> &statements) {
  for (auto st : statements)
    if (st == errorStatement()) {
      if (bblock)
        bblock->setError();
      return;
  }
  assert(bblock);
  for (auto st : statements)
    nbuilder_.addStatementToBlock(bblock, st);
}

// Return a block as a statement.

Bstatement *Llvm_backend::block_statement(Bblock *bblock)
{
  if (bblock->hasError())
    return errorStatement();
  return bblock; // class Bblock inherits from Bstatement
}

// Helper routine for creating module-scope variables (static, global, etc).

Bvariable *
Llvm_backend::makeModuleVar(Btype *btype,
                            const std::string &name,
                            const std::string &asm_name,
                            Location location,
                            ModVarConstant isConstant,
                            ModVarSec inUniqueSection,
                            ModVarComdat inComdat,
                            ModVarExtInit isExtInit,
                            ModVarGenDebug genDebug,
                            llvm::GlobalValue::LinkageTypes linkage,
                            llvm::Constant *initializer,
                            unsigned alignment)
{
  if (btype == errorType())
    return errorVariable_.get();

  // Special handling for zero-sized globals.
  Btype *underlyingType = btype;
  if (typeSize(btype) == 0) {
    underlyingType = synthesizeNonZeroSizeType(btype, makeIntegerOneExpr());
    initializer = nullptr;
  }

  // FIXME: at the moment the driver is enabling separate sections
  // for all variables, since there doesn't seem to be an easily
  // accessible hook for requesting a separate section for a single
  // variable.
  assert(inUniqueSection == MV_DefaultSection);

  if (initializer == nullptr && isExtInit == MV_NotExternallyInitialized)
    initializer = llvm::Constant::getNullValue(underlyingType->type());
  std::string gname(asm_name.empty() ? name : asm_name);
  llvm::GlobalVariable *glob = module_->getGlobalVariable(gname);
  llvm::Value *old = nullptr;
  if (glob && glob->getLinkage() == linkage) {
    // A global variable with same name already exists.
    if (glob->getType()->getElementType() == btype->type()) {
      if (isExtInit == MV_NotExternallyInitialized) {
        // A definition overrides a declaration for external var.
        glob->setExternallyInitialized(false);
        glob->setConstant(isConstant == MV_Constant);
        if (inComdat == MV_InComdat) {
          assert(! gname.empty());
          glob->setComdat(module().getOrInsertComdat(gname));
        }
        if (alignment)
          glob->setAlignment(alignment);
        if (initializer)
          glob->setInitializer(initializer);
      }

      auto it = valueVarMap_.find(glob);
      assert(it != valueVarMap_.end());
      Bvariable *bv = it->second;
      return bv;
    } else {
      if (isExtInit == MV_NotExternallyInitialized) {
        // A declaration with different type is found.
        // Remove this declaration. Its references will be replaced
        // with a new definition bit-casted to the old type.
        old = glob;
        glob->removeFromParent();
      } else {
        // A definition with different type is found.
        // Here we are creating an external declaration
        // of a different type. We make a bitcast to the
        // new type.
        llvm::Constant *decl = module_->getOrInsertGlobal(gname, btype->type());
        bool addressTaken = true; // for now
        Bvariable *bv =
            new Bvariable(btype, location, gname, GlobalVar, addressTaken, decl);
        assert(valueVarMap_.find(bv->value()) == valueVarMap_.end());
        valueVarMap_[bv->value()] = bv;
        if (genDebug == MV_GenDebug && dibuildhelper() && !errorCount_) {
          bool exported = (linkage == llvm::GlobalValue::ExternalLinkage);
          dibuildhelper()->processGlobal(bv, exported);
        }
        return bv;
      }
    }
  }

  llvm::GlobalValue::ThreadLocalMode threadlocal =
      llvm::GlobalValue::NotThreadLocal;
  glob = new llvm::GlobalVariable(module(), underlyingType->type(),
                                  isConstant == MV_Constant,
                                  linkage, initializer, gname, nullptr,
                                  threadlocal, addressSpace_);

  if (alignment)
    glob->setAlignment(alignment);
  if (inComdat == MV_InComdat) {
    assert(! gname.empty());
    glob->setComdat(module().getOrInsertComdat(gname));
  }
  if (isExtInit == MV_ExternallyInitialized) {
    assert(!initializer);
    glob->setExternallyInitialized(true);
  }

  bool addressTaken = true; // for now
  Bvariable *bv =
      (underlyingType != btype ?
       new Bvariable(btype, underlyingType,
                     location, gname, GlobalVar, addressTaken, glob) :
       new Bvariable(btype, location, gname, GlobalVar, addressTaken, glob));
  assert(valueVarMap_.find(bv->value()) == valueVarMap_.end());
  valueVarMap_[bv->value()] = bv;
  if (genDebug == MV_GenDebug && dibuildhelper() && !errorCount_) {
    bool exported = (linkage == llvm::GlobalValue::ExternalLinkage);
    dibuildhelper()->processGlobal(bv, exported);
  }

  // Fix up old declaration if there is one
  if (old) {
    assert(llvm::isa<llvm::PointerType>(old->getType()));
    llvm::Type *declTyp =
        llvm::cast<llvm::PointerType>(old->getType())->getElementType();
    llvm::Constant *newDecl = module_->getOrInsertGlobal(gname, declTyp);
    old->replaceAllUsesWith(newDecl);
    old->deleteValue();
    Bvariable *declbv = valueVarMap_[old];
    declbv->setValue(newDecl);
    valueVarMap_.erase(old);
    valueVarMap_[newDecl] = declbv;
  }

  return bv;
}

// Make a global variable.

Bvariable *Llvm_backend::global_variable(const std::string &var_name,
                                         const std::string &asm_name,
                                         Btype *btype,
                                         bool is_external,
                                         bool is_hidden,
                                         bool in_unique_section,
                                         Location location)
{
  llvm::GlobalValue::LinkageTypes linkage =
      ( is_hidden ? llvm::GlobalValue::InternalLinkage :
                    llvm::GlobalValue::ExternalLinkage);

  ModVarSec inUniqSec =
      (in_unique_section ? MV_UniqueSection : MV_DefaultSection);
  ModVarExtInit extInit =
      (is_external ? MV_ExternallyInitialized : MV_NotExternallyInitialized);
  Bvariable *gvar =
      makeModuleVar(btype, var_name, asm_name, location,
                    MV_NonConstant, inUniqSec, MV_NotInComdat,
                    extInit, MV_GenDebug, linkage, nullptr);
  return gvar;
}

// Set the initial value of a global variable.

void Llvm_backend::global_variable_set_init(Bvariable *var, Bexpression *expr)
{
  if (var == errorVariable_.get() || expr == errorExpression())
    return;
  assert(llvm::isa<llvm::GlobalVariable>(var->value()));
  llvm::GlobalVariable *gvar = llvm::cast<llvm::GlobalVariable>(var->value());

  expr = materialize(expr);

  if (expr->compositeInitPending())
    expr = resolveCompositeInit(expr, gvar);

  assert(llvm::isa<llvm::Constant>(expr->value()));
  llvm::Constant *econ = llvm::cast<llvm::Constant>(expr->value());

  // Special case for zero-sized globals...
  if (typeSize(expr->btype()) == 0)
    return;

  gvar->setInitializer(econ);
}

Bvariable *Llvm_backend::error_variable()
{
  errorCount_++;
  return errorVariable_.get();
}

// Make a local variable.

Bvariable *Llvm_backend::local_variable(Bfunction *function,
                                        const std::string &name,
                                        Btype *btype,
                                        Bvariable *decl_var,
                                        bool is_address_taken,
                                        Location location)
{
  assert(function);
  if (btype == errorType() || function == errorFunction_.get())
    return errorVariable_.get();
  return function->localVariable(name, btype, decl_var,
                                 is_address_taken, location);
}

// Make a function parameter variable.

Bvariable *Llvm_backend::parameter_variable(Bfunction *function,
                                            const std::string &name,
                                            Btype *btype, bool is_address_taken,
                                            Location location)
{
  assert(function);
  if (btype == errorType() || function == errorFunction_.get())
    return errorVariable_.get();
  return function->parameterVariable(name, btype,
                                     is_address_taken, location);
}

// Make a static chain variable.

Bvariable *Llvm_backend::static_chain_variable(Bfunction *function,
                                               const std::string &name,
                                               Btype *btype,
                                               Location location)
{
  if (function == errorFunction_.get() || btype == errorType())
    return errorVariable_.get();
  return function->staticChainVariable(name, btype, location);
}

// Make a temporary variable.

Bvariable *Llvm_backend::temporary_variable(Bfunction *function,
                                            Bblock *bblock,
                                            Btype *btype,
                                            Bexpression *binit,
                                            bool is_address_taken,
                                            Location location,
                                            Bstatement **pstatement)
{
  if (binit == errorExpression())
    return errorVariable_.get();
  std::string tname(namegen("tmpv"));
  Bvariable *tvar = local_variable(function, tname, btype, nullptr,
                                   is_address_taken, location);
  if (tvar == errorVariable_.get()) {
    *pstatement = errorStatement();
    return tvar;
  }
  tvar->markAsTemporary();
  Bstatement *is;
  if (binit)
    is = init_statement(function, tvar, binit);
  else
    is = statement_list({}); // dummy
  *pstatement = is;
  return tvar;
}

// Create an implicit variable that is compiler-defined.  This is used when
// generating GC root variables and storing the values of a slice initializer.

Bvariable *Llvm_backend::implicit_variable(const std::string &name,
                                           const std::string &asm_name,
                                           Btype *btype,
                                           bool is_hidden,
                                           bool is_constant,
                                           bool is_common,
                                           int64_t ialignment)
{
  if (btype == errorType())
    return errorVariable_.get();

  // Vett alignment
  assert(ialignment >= 0);
  assert(ialignment < 1<<30);
  unsigned alignment = static_cast<unsigned>(ialignment);

  // Common + hidden makes no sense
  assert(!(is_hidden && is_common));

  llvm::GlobalValue::LinkageTypes linkage =
      (is_hidden ? llvm::GlobalValue::InternalLinkage :
       (is_common ? llvm::GlobalValue::WeakAnyLinkage
        : llvm::GlobalValue::ExternalLinkage));

  ModVarComdat inComdat = (is_common ? MV_InComdat : MV_NotInComdat);
  ModVarSec inUniqSec = MV_DefaultSection;
  ModVarConstant isConst = (is_constant ? MV_Constant : MV_NonConstant);
  ModVarExtInit extInit = MV_NotExternallyInitialized;

  Bvariable *gvar =
      makeModuleVar(btype, name, asm_name, Location(),
                    isConst, inUniqSec, inComdat,
                    extInit, MV_SkipDebug, linkage,
                    nullptr, alignment);
  return gvar;
}

// Set the initalizer for a variable created by implicit_variable.
// This is where we finish compiling the variable.

void Llvm_backend::implicit_variable_set_init(Bvariable *var,
                                              const std::string &,
                                              Btype *type,
                                              bool, bool, bool is_common,
                                              Bexpression *init)
{
  if (init != nullptr && init == errorExpression())
    return;
  if (var == errorVariable_.get())
    return;
  if (!init)
    init = zero_expression(type);
  global_variable_set_init(var, init);
}

// Return a reference to an implicit variable defined in another package.

Bvariable *Llvm_backend::implicit_variable_reference(const std::string &name,
                                                     const std::string &asmname,
                                                     Btype *btype)
{
  bool is_external = true, is_hidden = false, in_unique_section = false;
  Location location; // dummy
  return global_variable(name, asmname, btype, is_external, is_hidden,
                         in_unique_section, location);
}

// Create a named immutable initialized data structure.

Bvariable *Llvm_backend::immutable_struct(const std::string &name,
                                          const std::string &asm_name,
                                          bool is_hidden,
                                          bool is_common,
                                          Btype *btype,
                                          Location location)
{
  if (btype == errorType())
    return errorVariable_.get();

  // Common + hidden makes no sense
  assert(!(is_hidden && is_common));

  llvm::GlobalValue::LinkageTypes linkage =
      (is_hidden ? llvm::GlobalValue::InternalLinkage :
       (is_common ? llvm::GlobalValue::WeakAnyLinkage
        : llvm::GlobalValue::ExternalLinkage));

  ModVarSec inUniqueSec = MV_DefaultSection;
  ModVarComdat inComdat = (is_common ? MV_InComdat : MV_NotInComdat);
  ModVarExtInit extInit = MV_NotExternallyInitialized;
  Bvariable *gvar =
      makeModuleVar(btype, name, asm_name, location,
                    MV_Constant, inUniqueSec, inComdat,
                    extInit, MV_SkipDebug, linkage, nullptr);
  return gvar;
}

// Set the initializer for a variable created by immutable_struct.
// This is where we finish compiling the variable.

void Llvm_backend::immutable_struct_set_init(Bvariable *var,
                                             const std::string &,
                                             bool is_hidden,
                                             bool is_common,
                                             Btype *,
                                             Location,
                                             Bexpression *initializer)
{
  if (var == errorVariable_.get() || initializer == errorExpression())
    return;

  initializer = materialize(initializer);

  assert(llvm::isa<llvm::GlobalVariable>(var->value()));
  llvm::GlobalVariable *gvar = llvm::cast<llvm::GlobalVariable>(var->value());
  assert(llvm::isa<llvm::Constant>(var->value()));
  llvm::Constant *econ = llvm::cast<llvm::Constant>(initializer->value());
  gvar->setInitializer(econ);
}

// Return a reference to an immutable initialized data structure
// defined in another package.

Bvariable *Llvm_backend::immutable_struct_reference(const std::string &name,
                                                    const std::string &asm_name,
                                                    Btype *btype,
                                                    Location location)
{
  if (btype == errorType())
    return errorVariable_.get();

  // Seen this already?
  std::string gname(asm_name.empty() ? name : asm_name);
  auto it = immutableStructRefs_.find(gname);
  if (it != immutableStructRefs_.end()) {
    // type should agree
    Bvariable *existing = it->second;
    assert(btype->type() == existing->btype()->type());
    return existing;
  }

  // A global with the same name already declared?
  llvm::GlobalVariable *glob = module_->getGlobalVariable(gname);
  if (glob) {
    assert(glob->getType()->getElementType() == btype->type());
    auto it = valueVarMap_.find(glob);
    assert(it != valueVarMap_.end());
    Bvariable *bv = it->second;
    immutableStructRefs_[gname] = bv;
    return bv;
  }

  // Create new external global
  llvm::GlobalValue::LinkageTypes linkage = llvm::GlobalValue::ExternalLinkage;
  bool isConstant = true;
  llvm::Constant *init = nullptr;
  llvm::GlobalValue::ThreadLocalMode threadlocal =
      llvm::GlobalValue::NotThreadLocal;
  glob = new llvm::GlobalVariable(module(), btype->type(), isConstant,
                                  linkage, init, gname, nullptr,
                                  threadlocal, addressSpace_);

  Bvariable *bv =
      new Bvariable(btype, location, name, GlobalVar, false, glob);
  assert(valueVarMap_.find(bv->value()) == valueVarMap_.end());
  valueVarMap_[bv->value()] = bv;
  immutableStructRefs_[gname] = bv;

  return bv;
}

// Make a label.

Blabel *Llvm_backend::label(Bfunction *function,
                            const std::string &name,
                            Location location)
{
  assert(function);
  return function->newLabel(location);
}

// Make a statement which defines a label.

Bstatement *Llvm_backend::label_definition_statement(Blabel *label)
{
  Bfunction *function = label->function();
  Bstatement *st = nbuilder_.mkLabelDefStmt(function, label, label->location());
  function->registerLabelDefStatement(st, label);
  return st;
}

// Make a goto statement.

Bstatement *Llvm_backend::goto_statement(Blabel *label, Location location)
{
  Bfunction *function = label->function();
  return nbuilder_.mkGotoStmt(function, label, location);
}

// Get the address of a label.

Bexpression *Llvm_backend::label_address(Blabel *label, Location location)
{
  assert(label);

  // Reuse existing placeholder (if address already taken for this label), or
  // create new placeholder if needed.
  llvm::Value *pval = nullptr;
  if (label->placeholder()) {
    pval = label->placeholder();
  } else {
    Bfunction *fcn = label->function();
    pval = fcn->createLabelAddressPlaceholder(boolType());
    label->setPlaceholder(pval);
  }
  // Note: the expression we're creating will eventually be replaced
  // by an llvm::BlockAddress value, which will have type "i8*", so
  // use that type here so as to avoid having to insert conversions.
  Btype *ppt = pointerType(boolType());
  return nbuilder_.mkLabelAddress(ppt, pval, label, location);
}

Bfunction *Llvm_backend::error_function()
{
  errorCount_++;
  return errorFunction_.get();
}

// This is a list of functions the call sites of which are not
// GC statepoints.
//
// Keep this sync with the runtime and the frontend.
static std::string gcleaffuncs[] = {
  "runtime.gcWriteBarrier",
  "runtime.typedmemmove",
};

static bool isGCLeaf(std::string name)
{

  for (auto f : gcleaffuncs)
    if (name == f)
      return true;
  return false;

}

// Declare or define a new function.

Bfunction *Llvm_backend::function(Btype *fntype, const std::string &name,
                                  const std::string &asm_name, unsigned flags,
                                  Location location)
{
  if (fntype == errorType())
    return errorFunction_.get();
  BFunctionType *ft = fntype->castToBFunctionType();
  assert(ft);
  llvm::FunctionType *fty = llvm::cast<llvm::FunctionType>(ft->type());

  // If this is a declaration, then look to see if we already have an existing
  // function with the same name, and reuse that if need be. Check to make
  // sure that the function types agree if we see a hit in the cache.
  std::string fns(!asm_name.empty() ? asm_name : name);
  if ((flags & Backend::function_is_declaration) != 0) {
    assert(ft);
    fcnNameAndType candidate(std::make_pair(ft, fns));
    auto it = fcnDeclMap_.find(candidate);
    if (it != fcnDeclMap_.end()) {
      Bfunction *found = it->second;
      return found;
    }
  }

  // At the moment don't allow the combination of only_inline and non-visible.
  // The assumption is that if the FE exports an inlinable function, that
  // function will be visible (in the ELF object file sense) in the host pkg.
  assert(((flags & Backend::function_only_inline) == 0) ||
         ((flags & Backend::function_is_visible) != 0));

  llvm::GlobalValue::LinkageTypes linkage =
      llvm::GlobalValue::InternalLinkage;
  if ((flags & Backend::function_is_visible) != 0) {
    if ((flags & Backend::function_only_inline) != 0)
      linkage = llvm::GlobalValue::AvailableExternallyLinkage;
    else
      linkage = llvm::GlobalValue::ExternalLinkage;
  }
  llvm::StringRef fn(fns);
  llvm::Constant *fcnValue = nullptr;
  llvm::Value *declVal = module_->getNamedValue(fn);
  if (((flags & Backend::function_is_declaration) == 0) || !declVal) {
    llvm::Function *declFnVal = nullptr;
    llvm::FunctionType *declFnTyp;
    if (((flags & Backend::function_is_declaration) == 0) && declVal &&
        llvm::isa<llvm::Function>(declVal)) {
      declFnVal = llvm::cast<llvm::Function>(declVal);
      declFnTyp = declFnVal->getFunctionType();
      if (declFnTyp == fty) {
        // A function of the same name is already declared with the
        // correct type.
        fcnValue = declFnVal;
        goto createbfunc;
      }
      // A function of the same name has already been created in this
      // module with a different type. Remove this declaration. Its
      // references will be replaced with a constant corresponding
      // to the newly defined function bit-casted to the old type.
      declFnVal->removeFromParent();
    }

    llvm::Twine fnt(fns);
    llvm::Function *fcn = llvm::Function::Create(fty, linkage, fnt, module_);

    if (!gcStrategy_.empty())
      fcn->setGC(gcStrategy_);

    fcn->addFnAttr("disable-tail-calls", "true");
    fcn->addFnAttr("null-pointer-is-valid", "true"); // Don't optimize nil pointer deref to undefined

    // inline/noinline
    if ((flags & Backend::function_is_inlinable) == 0 || noInline_)
      fcn->addFnAttr(llvm::Attribute::NoInline);
    // TODO: should we use inlinehint for imported only_inline functions?

    // split-stack or nosplit
    if (useSplitStack_ && (flags & Backend::function_no_split_stack) == 0)
      fcn->addFnAttr("split-stack");

    // allow elim frame pointer or not
    fcn->addFnAttr("no-frame-pointer-elim", noFpElim_ ? "true" : "false");

    // set suffix elision policy if autoFDO in effect
    if (autoFDO_)
      fcn->addFnAttr("sample-profile-suffix-elision-policy", "selected");

    // no-return
    if ((flags & Backend::function_does_not_return) != 0)
      fcn->addFnAttr(llvm::Attribute::NoReturn);

    // attributes for target CPU and features
    fcn->addFnAttr("target-cpu", targetCpuAttr_);
    fcn->addFnAttr("target-features", targetFeaturesAttr_);

    // attribute for GC leaf function (i.e. not a statepoint)
    if (isGCLeaf(fns))
      fcn->addFnAttr("gc-leaf-function");

    // attributes about runtime functions, to help the optimizer
    if (fns == "runtime.newobject" ||
        fns == "runtime.makeslice" ||
        fns == "runtime.makeslice64" ||
        fns == "runtime.makechan" ||
        fns == "runtime.makechan64") {
      fcn->addAttribute(llvm::AttributeList::ReturnIndex,
                        llvm::Attribute::NonNull);
      fcn->addAttribute(llvm::AttributeList::ReturnIndex,
                        llvm::Attribute::NoAlias);
    }

    // makemap may return its argument, so not noalias.
    if (fns == "runtime.makemap" ||
        fns == "runtime.makemap64" ||
        fns == "runtime.makemap_small")
      fcn->addAttribute(llvm::AttributeList::ReturnIndex,
                        llvm::Attribute::NonNull);

    // mapaccess1 and mapassign never return nil.
    if (fns == "runtime.mapaccess1" ||
        fns == "runtime.mapaccess1_fast32" ||
        fns == "runtime.mapaccess1_fast64" ||
        fns == "runtime.mapaccess1_faststr" ||
        fns == "runtime.mapaccess1_fat" ||
        fns == "runtime.mapassign" ||
        fns == "runtime.mapassign_fast32" ||
        fns == "runtime.mapassign_fast64" ||
        fns == "runtime.mapassign_fast32ptr" ||
        fns == "runtime.mapassign_fast64ptr" ||
        fns == "runtime.mapassign_faststr")
      fcn->addAttribute(llvm::AttributeList::ReturnIndex,
                        llvm::Attribute::NonNull);

    // mapaccess is pure function.
    if (!compilingRuntime_ &&
        (fns == "runtime.mapaccess1" ||
         fns == "runtime.mapaccess1_fast32" ||
         fns == "runtime.mapaccess1_fast64" ||
         fns == "runtime.mapaccess1_faststr" ||
         fns == "runtime.mapaccess1_fat" ||
         fns == "runtime.mapaccess2" ||
         fns == "runtime.mapaccess2_fast32" ||
         fns == "runtime.mapaccess2_fast64" ||
         fns == "runtime.mapaccess2_faststr" ||
         fns == "runtime.mapaccess2_fat"))
      fcn->addFnAttr(llvm::Attribute::ReadOnly);

    // memcmp-like.
    if (fns == "runtime.memequal" ||
        fns == "runtime.cmpstring") {
      fcn->addFnAttr(llvm::Attribute::ReadOnly);
      fcn->addFnAttr(llvm::Attribute::ArgMemOnly);
    }

    if (fns == "runtime.memclrNoHeapPointers")
      fcn->addFnAttr(llvm::Attribute::ArgMemOnly);

    // These functions are called in unlikely branches. But they
    // themselves are not actually cold in the runtime. So only
    // mark cold when we are not compiling the runtime.
    if (!compilingRuntime_ &&
        (fns == "runtime.gcWriteBarrier" ||
         fns == "runtime.typedmemmove" ||
         fns == "runtime.growslice"))
      fcn->addFnAttr(llvm::Attribute::Cold);

    fcnValue = fcn;

    // Fix up references to declaration of old type.
    if (declFnVal && declFnTyp != fty) {
      llvm::Constant *newDeclVal = llvm::cast<llvm::Constant>(
          module_->getOrInsertFunction(fn, declFnTyp).getCallee());
      declFnVal->replaceAllUsesWith(newDeclVal);
      declFnVal->deleteValue();
      for (auto it = fcnDeclMap_.begin(); it != fcnDeclMap_.end(); it++) {
        if (it->first.second.compare(fns) == 0) {
          Bfunction *found = it->second;
          if (found->fcnValue() == declFnVal)
            found->setFcnValue(newDeclVal);
        }
      }
    }
  } else {

    // A function of the same name has already been created in this
    // module. Call a module helper to get a constant corresponding
    // to the original fcn bit-casted to the new type.
    fcnValue = llvm::cast<llvm::Constant>(
        module_->getOrInsertFunction(fn, fty).getCallee());
  }

createbfunc:
  BFunctionType *fcnType = fntype->castToBFunctionType();
  assert(fcnType);
  Bfunction *bfunc = new Bfunction(fcnValue, fcnType, name, asm_name, location,
                                   typeManager());

  // split-stack or nosplit
  if (!useSplitStack_ || (flags & Backend::function_no_split_stack) != 0)
    bfunc->setSplitStack(Bfunction::NoSplit);

  // TODO: unique section support. llvm::GlobalObject has support for
  // setting COMDAT groups and section names, but there doesn't seem
  // to be an interface available to request a unique section on a
  // per-function basis (only a translation-unit-wide default).
  assert((flags & Backend::function_in_unique_section) == 0 ||
         (flags & Backend::function_is_declaration) != 0);

  if ((flags & Backend::function_is_declaration) != 0) {
    fcnNameAndType candidate(std::make_pair(ft, fns));
    fcnDeclMap_[candidate] = bfunc;
  }
  functions_.push_back(bfunc);
  return bfunc;
}

// Create a statement that runs all deferred calls for FUNCTION.  This should
// be a statement that looks like this in C++:
//   finish:
//     try { UNDEFER; } catch { CHECK_DEFER; goto finish; }

Bstatement *Llvm_backend::function_defer_statement(Bfunction *function,
                                                   Bexpression *undefer,
                                                   Bexpression *defer,
                                                   Location location)
{
  if (function == errorFunction_.get() ||
      undefer == errorExpression() ||
      defer == errorExpression())
    return errorStatement();

  undefer = materialize(undefer);
  defer = materialize(defer);

  Bstatement *defst = nbuilder_.mkDeferStmt(function, undefer, defer,
                                            location);
  return defst;
}

// Record PARAM_VARS as the variables to use for the parameters of FUNCTION.
// This will only be called for a function definition.

bool Llvm_backend::function_set_parameters(
    Bfunction *function, const std::vector<Bvariable *> &param_vars)
{
  if (function == errorFunction_.get())
    return true;

  // If the number of param vars doesn't match up with the number expected,
  // we interpret that to mean that the FE encountered a syntax error
  // while processing a parameter. Flag the function in this case so that
  // we can avoid avoid asserting when doing prolog processing for
  // the function.
  if (function->fcnType()->paramTypes().size() != param_vars.size())
    function->setErrorSeen(true);

  return true;
}

//
// Helper class for assigning instructions to LLVM basic blocks
// and materializing control transfers.
//
// FIXME: convert to use new Bnode walk paradigm.
//
class GenBlocks {
 public:
  GenBlocks(llvm::LLVMContext &context, Llvm_backend *be,
            Bfunction *function, Bnode *topNode,
            DIBuildHelper *diBuildHelper, llvm::BasicBlock *entryBlock);

  // Here 'stmt' is the containing stmt, or null if node itself is a stmt.
  llvm::BasicBlock *walk(Bnode *node,
                         Bstatement *stmt,
                         llvm::BasicBlock *curblock);
  void finishFunction(llvm::BasicBlock *entry);

  Bfunction *function() { return function_; }
  llvm::BasicBlock *genIf(Bstatement *ifst,
                          llvm::BasicBlock *curblock);
  llvm::BasicBlock *genSwitch(Bstatement *swst,
                              llvm::BasicBlock *curblock);
  llvm::BasicBlock *genDefer(Bstatement *defst,
                             llvm::BasicBlock *curblock);
  llvm::BasicBlock *genReturn(Bstatement *rst,
                             llvm::BasicBlock *curblock);
  llvm::BasicBlock *genExcep(Bstatement *excepst,
                             llvm::BasicBlock *curblock);

 private:
  llvm::BasicBlock *mkLLVMBlock(const std::string &name,
                            unsigned expl = Llvm_backend::ChooseVer);
  llvm::BasicBlock *eraseBlockIfUnused(llvm::BasicBlock *bb);
  llvm::BasicBlock *getBlockForLabel(Blabel *lab);
  llvm::BasicBlock *walkExpr(llvm::BasicBlock *curblock,
                             Bstatement *containingStmt,
                             Bexpression *expr,
                             bool subexpr=false);
  std::pair<llvm::Instruction*, llvm::BasicBlock *>
  rewriteToMayThrowCall(llvm::CallInst *call,
                        llvm::BasicBlock *curblock);
  std::pair<llvm::Instruction*, llvm::BasicBlock *>
  postProcessInst(llvm::Instruction *inst,
                  llvm::BasicBlock *curblock);
  llvm::Value *populateCatchPadBlock(llvm::BasicBlock *catchpadbb,
                                     Bvariable *finvar);
  llvm::BasicBlock *populateFinallyBlock(llvm::BasicBlock *finBB,
                                         Bvariable *finvar,
                                         llvm::Value *extmp);
  void genDeferReturn(llvm::BasicBlock *curblock);
  void walkReturn(llvm::BasicBlock *curblock,
                  Bstatement *stmt,
                  Bexpression *re);
  void appendLifetimeIntrinsic(llvm::Value *alloca,
                               llvm::Instruction *insertBefore,
                               llvm::BasicBlock *curBlock,
                               bool isStart);
  void insertLifetimeMarkersForBlock(Bblock *block,
                                     llvm::Instruction *insertBefore,
                                     llvm::BasicBlock *llbb,
                                     bool isStart);
  DIBuildHelper *dibuildhelper() const { return dibuildhelper_; }
  Llvm_linemap *linemap() { return be_->linemap(); }

 private:
  llvm::LLVMContext &context_;
  Llvm_backend *be_;
  Bfunction *function_;
  DIBuildHelper *dibuildhelper_;
  std::vector<Bblock *> blockStack_;
  std::map<LabelId, llvm::BasicBlock *> labelmap_;
  std::vector<llvm::BasicBlock*> padBlockStack_;
  std::set<llvm::Instruction *> temporariesDiscovered_;
  std::vector<llvm::Instruction *> newTemporaries_;
  std::map<llvm::Value *, llvm::Instruction *> instRewrites_;
  llvm::BasicBlock *finallyBlock_;
  Bstatement *cachedReturn_;
};

GenBlocks::GenBlocks(llvm::LLVMContext &context,
                     Llvm_backend *be,
                     Bfunction *function,
                     Bnode *topNode,
                     DIBuildHelper *dibuildhelper,
                     llvm::BasicBlock *entryBlock)
    : context_(context), be_(be), function_(function),
      dibuildhelper_(dibuildhelper), finallyBlock_(nullptr),
      cachedReturn_(nullptr)
{
  if (dibuildhelper_)
    dibuildhelper_->beginFunction(function, topNode, entryBlock);
}

void GenBlocks::finishFunction(llvm::BasicBlock *entry)
{
  function_->fixupProlog(entry, newTemporaries_);

  llvm::Function *func = function_->function();
  if (! func->hasPersonalityFn())
    func->setPersonalityFn(be_->dummyPersonalityFunction());

  if (dibuildhelper_)
    dibuildhelper_->endFunction(function_);
}

llvm::BasicBlock *GenBlocks::mkLLVMBlock(const std::string &name,
                                         unsigned expl)
{
  std::string tname = be_->namegen(name, expl);
  llvm::Function *func = function()->function();
  return llvm::BasicBlock::Create(context_, tname, func);
}

llvm::BasicBlock *GenBlocks::getBlockForLabel(Blabel *lab) {
  auto it = labelmap_.find(lab->label());
  if (it != labelmap_.end())
    return it->second;
  llvm::BasicBlock *bb = mkLLVMBlock("label", lab->label());
  labelmap_[lab->label()] = bb;
  return bb;
}

void GenBlocks::appendLifetimeIntrinsic(llvm::Value *alloca,
                                        llvm::Instruction *insertBefore,
                                        llvm::BasicBlock *curBlock,
                                        bool isStart)
{
  LIRBuilder builder(context_, llvm::ConstantFolder());
  if (insertBefore)
    builder.SetInsertPoint(insertBefore);
  else
    builder.SetInsertPoint(curBlock);

  if (auto *ascast = llvm::dyn_cast<llvm::AddrSpaceCastInst>(alloca))
    alloca = ascast->getPointerOperand();
  llvm::AllocaInst *ai = llvm::cast<llvm::AllocaInst>(alloca);

  // expect array size of 1 given how we constructed it
  assert(ai->getArraySize() == builder.getInt64(1) ||
         ai->getArraySize() == builder.getInt32(1));

  // grab type, compute type size
  llvm::Type *ait = ai->getAllocatedType();
  uint64_t typSiz = be_->llvmTypeSize(ait);
  llvm::ConstantInt *allocaSize = builder.getInt64(typSiz);

  if (isStart)
    builder.CreateLifetimeStart(alloca, allocaSize);
  else
    builder.CreateLifetimeEnd(alloca, allocaSize);
}

// A couple of notes on lifetime markers:
//
// Markers are used to feed information on variable lifetimes from the
// front end to the back end; they describe the range within which a
// variable is being used. If two variables have disjoint lifetime
// ranges, they can be allocated to the same stack slot. Example:
//
//     func foo(x int) {
//       var k [10]int64
//       if ... {
//          var q [10]int64
//          ...
//       } else {
//          var r [10]int64
//          ...
//       }
//
// Assuming that 'q' and 'r' are stack allocated, one can observe that
// it is safe to have them share a single region on the stack, since
// their lifetimes are disjoint. Conversely, 'q' and 'k' are not safe
// to share a stack slot, since their lifetimes overlap.
//
// The front end helpfully informs the backend about lifetimes of
// user-declared variables by calling out the specific vars declared within
// a block when the block is created. Given a block, this routine below
// walks through the block and inserts either lifetime "begin" markers
// or lifetime "end" markers depending on which the caller requests.
//
// A couple of items to note:
//
// - the front end also manufactures compiler temporaries, however at the
//   moment it doesn't try to associate temps with a given block (the code
//   below doesn't address these sorts of variables)
//
// - if there are no lifetime intrinsics for a given stack-allocated
//   variable, the back end will assume that it is live throughout the
//   entire function (the BE will not attempt to retroactively discover
//   the var lifetime)
//
// - the LLVM inliner will insert lifetime intrinsics for stack-allocated
//   variables that don't already have lifetime intrinsics when inlining
//   a function body (for example, if the variable 'k' in the function
//   above had no lifetime markers, and 'foo' were inlined into another
//   routine, the inliner will place markers for 'k' before/after the
//   blob of IR corresponding to the function body.
//
// - the BE is designed to tolerate lifetime markers that are imprecise
//   in the sense that they over-estimate var lifetimes. It is not set up
//   to handle markers under-estimate lifetimes.
//

void GenBlocks::insertLifetimeMarkersForBlock(Bblock *block,
                                              llvm::Instruction *insertBefore,
                                              llvm::BasicBlock *llbb,
                                              bool isStart)
{
  assert(llbb);
  for (auto v : block->vars()) {
    if (v->isDeclVar()) {
      // This variable does not have its own alloca -- it is borrowing the
      // alloca instruction from some other outer-scope var, hence we
      // don't have as much information about its lifetime: avoid inserting
      // lifetime ops.
      continue;
    }
    llvm::Value *ai = v->value();
    appendLifetimeIntrinsic(ai, insertBefore, llbb, isStart);
  }
}

// This helper routine takes a garden variety call instruction and
// rewrites it to an equivalent llvm::InvokeInst that may throw an
// exception (with associated explicit EH control flow). The helper is
// used to fix up calls that appear within the body or catch clauses
// of an EH statement (see Llvm_backend::exception_handler_statement).
// Redoing calls in this way (as opposed to creating the correct
// flavor of call from the get-go) is mildly hacky, but seems to be
// the most practical way to get the sort of call we need, given that
// at the point where Backend::call_expression is originally invoked
// we don't know whether the call will reside in a try block.

std::pair<llvm::Instruction*, llvm::BasicBlock *>
GenBlocks::rewriteToMayThrowCall(llvm::CallInst *call,
                                 llvm::BasicBlock *curblock)
{
  llvm::BasicBlock *padbb = padBlockStack_.back();
  llvm::Function *func = function()->function();

  // Create 'continue' block, where control will flow if
  // the call to the function does not result in an exception.
  llvm::BasicBlock *contbb =
      llvm::BasicBlock::Create(context_, be_->namegen("cont"), func);

  // Create a new InvokeInst that is equivalent (in terms of
  // target, operands, etc) to the CallInst 'call', but uses a
  // possibly-excepting call with landing pad.
  llvm::SmallVector<llvm::Value *, 8> args(call->arg_begin(), call->arg_end());
  llvm::InvokeInst *invcall =
      llvm::InvokeInst::Create(call->getCalledValue(),
                               contbb, padbb, args,
                               call->getName());

  // Rewrite uses of the original call's return value to be the new call's
  // return value.
  call->replaceAllUsesWith(invcall);

  // Add an entry in the rewrites map to record the fact that we've replaced the
  // call with an invoke. This is to take care of situations where the LLVM
  // value for a given Bexpression is inherited by the expression's parent.
  // Example:
  //
  //    func f(...) int64 { ... }
  //    ...
  //    func g() {
  //      defer func() { ... }()
  //      z = uint64(f(...))
  //      ...
  //    }
  //
  // This will result in a call parented by a conversion, e.g.
  //
  //    conv: [ btype: [uns] 'uint64' i64 ]
  //       call: [ btype: 'int64' i64 ]
  //          fcn: [ btype: i64 (i8*, i64)* ] main.F
  //          ...
  //
  // Both the call and the convert will wind up with the same LLVM Value,
  // hence we need to rewrite the value not just of the Bexpression for the
  // call, but also the Bexpression for the convert.
  //
  assert(instRewrites_.find(call) == instRewrites_.end());
  instRewrites_[call] = invcall;

  // New call needs same attributes
  invcall->setAttributes(call->getAttributes());

  return std::make_pair(invcall, contbb);
}

// Hook to post-process an LLVM instruction immediately before it
// is assigned to a block.

std::pair<llvm::Instruction*, llvm::BasicBlock *>
GenBlocks::postProcessInst(llvm::Instruction *inst,
                           llvm::BasicBlock *curblock)
{
  for (llvm::Instruction::op_iterator oi = inst->op_begin(),
           oe = inst->op_end(); oi != oe; ++oi) {
    if (llvm::isa<llvm::AllocaInst>(*oi) ||
        llvm::isa<llvm::AddrSpaceCastInst>(*oi)) {
      llvm::Instruction *ai = llvm::cast<llvm::Instruction>(*oi);

      // If this alloca is associated with a temporary variable
      // that was manufactured at some point during IR construction,
      // then gather it up into a set to be inserted into the prolog
      // block.
      Bvariable *tvar = be_->nodeBuilder().adoptTemporaryVariable(ai);
      if (tvar) {
        temporariesDiscovered_.insert(ai);
        newTemporaries_.push_back(ai);
        delete tvar;
      }
    }
  }

  if (llvm::isa<llvm::CallInst>(inst) && !padBlockStack_.empty()) {
    llvm::CallInst *call = llvm::cast<llvm::CallInst>(inst);
    llvm::Function *func = call->getCalledFunction();
    if (!func || !func->isIntrinsic())
      return rewriteToMayThrowCall(call, curblock);
  }
  return std::make_pair(inst, curblock);
}

static bool isNoReturnCall(llvm::Instruction *inst)
{
  llvm::Function *func = nullptr;
  if (llvm::isa<llvm::CallInst>(inst)) {
    llvm::CallInst *call = llvm::cast<llvm::CallInst>(inst);
    func = call->getCalledFunction();
  } else if (llvm::isa<llvm::InvokeInst>(inst)) {
    llvm::InvokeInst *invoke = llvm::cast<llvm::InvokeInst>(inst);
    func = invoke->getCalledFunction();
  }
  if (func != nullptr && func->hasFnAttribute(llvm::Attribute::NoReturn))
    return true;
  return false;
}

llvm::BasicBlock *GenBlocks::walkExpr(llvm::BasicBlock *curblock,
                                      Bstatement *containingStmt,
                                      Bexpression *expr,
                                      bool subexpr)
{
  // Delete dead instructions before visiting the children,
  // as they may use values defined in the children. Uses
  // need to be deleted before deleting definition.
  if (!curblock)
    be_->nodeBuilder().destroy(expr, DelInstructions, false);

  // Visit children first
  const std::vector<Bnode *> &kids = expr->children();
  for (auto &child : kids) {
    Bexpression *expr = child->castToBexpression();
    if (expr)
      curblock = walkExpr(curblock, containingStmt, expr, true);
    else
      curblock = walk(child, containingStmt, curblock);
  }

  // In case it becomes dead after visiting some child...
  if (!curblock)
    be_->nodeBuilder().destroy(expr, DelInstructions, false);

  // Now visit instructions for this expr. Note: if as part of this loop a
  // no-return call is encountered, we'll wind up changing from live code to
  // dead code; handle this case appropriately.
  bool changed = false;
  std::vector<llvm::Instruction*> newinsts;
  for (auto originst : expr->instructions()) {
    auto pair = postProcessInst(originst, curblock);
    auto inst = pair.first;
    if (inst != originst)
      changed = true;
    if (dibuildhelper_)
      dibuildhelper_->processExprInst(containingStmt, expr, inst);
    curblock->getInstList().push_back(inst);
    curblock = pair.second;
    newinsts.push_back(inst);

    // Check for no-return call
    if (isNoReturnCall(inst)) {
      // Insert 'unreachable' inst into current block, then end
      // current block.
      LIRBuilder builder(context_, llvm::ConstantFolder());
      llvm::Instruction *unreachable = builder.CreateUnreachable();
      curblock->getInstList().push_back(unreachable);
      curblock = nullptr;
      changed = true;

      // Mark nil checks "make_implicit". GoNilChecks pass will
      // try to elide the branch.
      if (llvm::Function *fn = llvm::cast<llvm::CallBase>(inst)->getCalledFunction())
        if (fn->getName() == "__go_runtime_error")
          if (llvm::BasicBlock *pred = inst->getParent()->getSinglePredecessor()) {
            llvm::Instruction *br = pred->getTerminator();
            br->setMetadata(llvm::LLVMContext::MD_make_implicit,
                            llvm::MDNode::get(inst->getContext(), {}));
          }

      break;
    }
  }
  if (changed)
    be_->nodeBuilder().updateInstructions(expr, newinsts);
  expr->clear();

  // Rewrite value for this expr if needed.
  auto it = instRewrites_.find(expr->value());
  if (it != instRewrites_.end())
    be_->nodeBuilder().updateValue(expr, it->second);

  // If this is a top-level expression (e.g. expression parented by statement,
  // as opposed to expression parented by some other expr), then at this
  // point we can delete any inst that appears as a key in the rewrite
  // map (we don't expect to see any other uses).
  if (!subexpr) {
    for (auto it = instRewrites_.begin(); it != instRewrites_.end(); it++)
      it->first->deleteValue();
    instRewrites_.clear();
  }

  return curblock;
}

llvm::BasicBlock *GenBlocks::genIf(Bstatement *ifst,
                                   llvm::BasicBlock *curblock)
{
  assert(ifst->flavor() == N_IfStmt);

  Bexpression *cond = ifst->getIfStmtCondition();
  Bstatement *trueStmt = ifst->getIfStmtTrueBlock();
  Bstatement *falseStmt = ifst->getIfStmtFalseBlock();

  // Walk condition first
  curblock = walkExpr(curblock, ifst, cond);

  // Create true block
  llvm::BasicBlock *tblock = curblock ? mkLLVMBlock("then") : nullptr;

  // Create fallthrough block
  llvm::BasicBlock *ft = curblock ? mkLLVMBlock("fallthrough") : nullptr;

  // Create false block if present
  llvm::BasicBlock *fblock = ft;
  if (falseStmt)
    fblock = curblock ? mkLLVMBlock("else") : nullptr;

  // Insert conditional branch into current block
  if (curblock) {
    llvm::Value *cval = cond->value();
    llvm::BranchInst::Create(tblock, fblock, cval, curblock);
  }

  // Visit true block
  llvm::BasicBlock *tsucc = walk(trueStmt, nullptr, tblock);
  if (tsucc && ! tsucc->getTerminator())
    llvm::BranchInst::Create(ft, tsucc);

  // Walk false block if present
  if (falseStmt) {
    llvm::BasicBlock *fsucc = walk(falseStmt, nullptr, fblock);
    if (fsucc && ! fsucc->getTerminator())
      llvm::BranchInst::Create(ft, fsucc);
  }

  // Remove fallthrough block if it was never used
  ft = eraseBlockIfUnused(ft);

  return ft;
}

llvm::BasicBlock *GenBlocks::genSwitch(Bstatement *swst,
                                       llvm::BasicBlock *curblock)
{
  assert(swst->flavor() == N_SwitchStmt);

  // Walk switch value first
  Bexpression *swval = swst->getSwitchStmtValue();
  curblock = walkExpr(curblock, swst, swval);

  // Unpack switch
  unsigned ncases = swst->getSwitchStmtNumCases();

  // No need to walk switch value expressions -- they should all be constants.

  // Create blocks
  llvm::BasicBlock *defBB = nullptr;
  std::vector<llvm::BasicBlock *> blocks(ncases);
  for (unsigned idx = 0; idx < ncases; ++idx) {
    std::vector<Bexpression *> thiscase =
        swst->getSwitchStmtNthCase(idx);
    bool isDefault = (thiscase.size() == 0);
    std::string bname(isDefault ? "default" : "case");
    blocks[idx] = curblock ? mkLLVMBlock(bname) : nullptr;
    if (isDefault) {
      assert(! defBB);
      defBB = blocks[idx];
    }
  }
  llvm::BasicBlock *epilogBB = mkLLVMBlock("epilog");
  if (!defBB)
    defBB = epilogBB;

  LIRBuilder builder(context_, llvm::ConstantFolder());

  // Walk statement/block
  for (unsigned idx = 0; idx < ncases; ++idx) {
    Bstatement *st = swst->getSwitchStmtNthStmt(idx);
    llvm::BasicBlock *newblock = walk(st, nullptr, blocks[idx]);
    if (newblock && newblock->getTerminator() == nullptr) {
      // The front end inserts a goto statement at the end for
      // non-fallthrough cases. Fall through to the next case
      // otherwise.
      assert(idx < ncases-1);
      builder.SetInsertPoint(newblock);
      builder.CreateBr(blocks[idx+1]);
    }
  }

  // Create switch
  if (curblock) {
    builder.SetInsertPoint(curblock);
    llvm::SwitchInst *swinst = builder.CreateSwitch(swval->value(), defBB);

    // Connect values with blocks
    for (unsigned idx = 0; idx < blocks.size(); ++idx) {
      std::vector<Bexpression *> thiscase =
          swst->getSwitchStmtNthCase(idx);
      for (auto &exp : thiscase) {
        llvm::ConstantInt *ci = llvm::cast<llvm::ConstantInt>(exp->value());
        swinst->addCase(ci, blocks[idx]);
      }
    }
  }

  // Delete epilog if not needed
  epilogBB = eraseBlockIfUnused(epilogBB);

  return epilogBB;
}

// If specified BB has no predecessors, remove it and return nullptr.
// Returns unmodified BB if the block does have preds.

llvm::BasicBlock *GenBlocks::eraseBlockIfUnused(llvm::BasicBlock *bb)
{
  if (bb == nullptr)
    return bb;
  if (llvm::pred_begin(bb) == llvm::pred_end(bb)) {
    // Block should be empty in this case
    assert(bb->begin() == bb->end());
    bb->eraseFromParent();
    return nullptr;
  }
  return bb;
}

void GenBlocks::walkReturn(llvm::BasicBlock *curblock,
                           Bstatement *stmt,
                           Bexpression *re)
{
  llvm::BasicBlock *bb = walkExpr(curblock, stmt, re);
  assert(curblock == bb);
  if (curblock) {
    llvm::Instruction *term = curblock->getTerminator();
    assert(term);
    for (auto it = blockStack_.rbegin(); it != blockStack_.rend(); ++it)
      insertLifetimeMarkersForBlock(*it, term, curblock, false);
  }
}


// In most cases a return statement is handled in canonical way,
// that is, any associated expressions are added to the current block
// (including an llvm::ReturnInst) and the current block is closed out.
//
// Special handling is needed when the return appears within a
// try/catch block (see Llvm_backend::exception_handler_statement)
// with a "finally" clause. In such cases we have to rewrite each
// return instruction into a jump to the finally block.
//
// HACK: we're taking advantage of the fact that the front end always
// stores return values to a local variable as opposed to returning
// those values directly (hence evern return sequence should always
// look like "return X" where X is a load from an appropriately typed
// variable. This fact permits us to copy a return from one place in
// the program to another while getting the same semantics.

llvm::BasicBlock *GenBlocks::genReturn(Bstatement *rst,
                                       llvm::BasicBlock *curblock)
{
  assert(rst->flavor() == N_ReturnStmt);

  Bexpression *re = rst->getReturnStmtExpr();

  if (finallyBlock_) {
    // Here we also cache away a return statement so as to relocate
    // it after the 'finally' block.
    if (cachedReturn_ == nullptr) {
      // Steal this return.
      cachedReturn_ = rst;
    } else {
      be_->nodeBuilder().destroy(re, DelInstructions);
    }
    if (curblock)
      genDeferReturn(curblock);
  } else {
    // Walk return expression
    walkReturn(curblock, rst, re);
  }

  // A return terminates the current block
  return nullptr;
}

// A helper function that clones an instruction, and fixes up the operands
// if they are previously cloned values.
static llvm::Instruction *
cloneInstruction(llvm::Instruction *inst,
                 std::unordered_map<llvm::Value*, llvm::Value*> &argMap)
{
  llvm::Instruction *c = inst->clone();
  assert(argMap.find(inst) == argMap.end());
  argMap[inst] = c;
  for (unsigned i = 0, n = c->getNumOperands(); i < n; i++) {
    auto it = argMap.find(c->getOperand(i));
    if (it != argMap.end())
      c->setOperand(i, it->second);
  }
  return c;
}

// Generate the DEFERRETURN call for return statement in functions
// that has defer.
// We could simply rewrite the return to a jump into the 'finally'
// block (see above). However, for the GC support each return
// path may have different set of live variables. We need to
// "unshare" the DEFERRETURN calls.
// We do this by copying the instructions from 'finally' block.
// By the construction we need to copy up to the first invoke
// instruction (DEFERRETURN).
void GenBlocks::genDeferReturn(llvm::BasicBlock *curblock)
{
  llvm::BasicBlock *blockToClone = finallyBlock_;
  assert(blockToClone);

  // A map from old value to new value, used to fix up operands.
  std::unordered_map<llvm::Value*, llvm::Value*> argMap;

  while (1) {
    llvm::Instruction *term = blockToClone->getTerminator();
    for (llvm::Instruction &inst : *blockToClone) {
      if (&inst == term)
        break; // terminator is handled below
      llvm::Instruction *c = cloneInstruction(&inst, argMap);
      curblock->getInstList().push_back(c);
    }
    if (llvm::isa<llvm::InvokeInst>(term)) {
      // This is the call to DEFERRETURN. Copy this then we're done.
      llvm::Instruction *c = cloneInstruction(term, argMap);
      curblock->getInstList().push_back(c);
      break;
    }
    // By construction it should be linear code.
    // No need to copy the jump instruction.
    blockToClone = blockToClone->getSingleSuccessor();
    assert(blockToClone);
  }
}

llvm::BasicBlock *GenBlocks::genDefer(Bstatement *defst,
                                      llvm::BasicBlock *curblock)
{
  assert(defst->flavor() == N_DeferStmt);

  // Insure that current function has personality routine set.
  llvm::Function *func = function()->function();
  if (! func->hasPersonalityFn())
    func->setPersonalityFn(be_->personalityFunction());

  Bexpression *defcallex = defst->getDeferStmtDeferCall();
  Bexpression *undcallex = defst->getDeferStmtUndeferCall();

  // Landing pad to which control will be transferred if an exception
  // is thrown when executing "undcallex".
  llvm::BasicBlock *padbb =
      llvm::BasicBlock::Create(context_, be_->namegen("pad"), func);

  // Catch BB will contain checkdefer (defercall) code.
  llvm::BasicBlock *catchbb =
      llvm::BasicBlock::Create(context_, be_->namegen("catch"), func);

  // Finish bb (see the comments for Llvm_backend::function_defer_statement
  // as to why we use this name).
  llvm::BasicBlock *finbb =
      llvm::BasicBlock::Create(context_, be_->namegen("finish"), func);

  if (curblock)
    llvm::BranchInst::Create(finbb, curblock);
  curblock = finbb;

  // Push pad block onto stack. This will be an indication that any call
  // in the undcallex subtree should be converted into an invoke with
  // suitable landing pad.
  padBlockStack_.push_back(padbb);

  // Walk the undcall expression.
  curblock = walkExpr(curblock, defst, undcallex);

  // Pop the pad block stack.
  padBlockStack_.pop_back();

  // Emit landing pad into pad block, followed by branch to catch block.
  llvm::LandingPadInst *padinst =
      llvm::LandingPadInst::Create(be_->landingPadExceptionType(),
                                   0, be_->namegen("ex"), padbb);
  padinst->addClause(llvm::Constant::getNullValue(be_->llvmPtrType()));
  llvm::BranchInst::Create(catchbb, padbb);

  llvm::BasicBlock *contbb = curblock;

  // Catch block containing defer call.
  curblock = catchbb;
  auto bb = walkExpr(curblock, defst, defcallex);
  assert(bb == curblock);
  llvm::BranchInst::Create(finbb, catchbb);

  // Continue bb is final bb.
  return contbb;
}

// Populate the landing pad used to catch exceptions thrown from
// the catch code from an exceptions handling statement (pad "P2"
// in the diagram in the header comment for GenBlocks::genExcep).

llvm::Value *GenBlocks::populateCatchPadBlock(llvm::BasicBlock *catchpadbb,
                                              Bvariable *finvar)
{
  LIRBuilder builder(context_, llvm::ConstantFolder());
  builder.SetInsertPoint(catchpadbb);

  // Create landing pad instruction.
  llvm::Type *eht = be_->landingPadExceptionType();
  llvm::LandingPadInst *caughtResult =
      builder.CreateLandingPad(eht, 0, be_->namegen("ex2"));
  caughtResult->setCleanup(true);

  // Create temporary into which caught result will be stored
  std::string tag(be_->namegen("ehtmp"));
  llvm::Instruction *ai = new llvm::AllocaInst(eht, 0, tag);
  temporariesDiscovered_.insert(ai);
  newTemporaries_.push_back(ai);

  // Store caught result into temporary.
  builder.CreateStore(caughtResult, ai);

  // Emit "finally = false" into catch pad BB following pad inst
  builder.SetInsertPoint(catchpadbb);
  llvm::Value *fval = be_->boolean_constant_expression(false)->value();
  builder.CreateStore(fval, finvar->value());

  return ai;
}

// At end of finally BB, emit:
//
//   if (finok)
//     return
//   else
//     resume EXC
//
// where EXC is the exception that caused control to flow
// into the catch pad bb.
//
// In addition, this routine creates the shared return statement
// (if there is a cached return) and fixes up the finally stmt
// resume block.

llvm::BasicBlock *GenBlocks::populateFinallyBlock(llvm::BasicBlock *finBB,
                                                  Bvariable *finvar,
                                                  llvm::Value *extmp)
{
  LIRBuilder builder(context_, llvm::ConstantFolder());
  builder.SetInsertPoint(finBB);
  llvm::Function *func = function()->function();
  llvm::BasicBlock *finResBB =
      llvm::BasicBlock::Create(context_, be_->namegen("finres"), func);
  llvm::BasicBlock *finRetBB =
      llvm::BasicBlock::Create(context_, be_->namegen("finret"), func);
  std::string lname(be_->namegen("fload"));
  llvm::LoadInst *finvarload = builder.CreateLoad(finvar->value(), lname);
  llvm::Value *tval = be_->boolean_constant_expression(true)->value();
  llvm::Value *cmp = builder.CreateICmp(llvm::CmpInst::Predicate::ICMP_EQ,
                                        finvarload, tval,
                                        be_->namegen("icmp"));
  builder.CreateCondBr(cmp, finRetBB, finResBB);

  // Populate return block
  if (cachedReturn_ != nullptr) {
    llvm::BasicBlock *curblock = finRetBB;
    Bexpression *re = cachedReturn_->getReturnStmtExpr();
    walkReturn(curblock, cachedReturn_, re);
    cachedReturn_ = nullptr;
    finRetBB = nullptr;
  }

  // Populate resume block
  builder.SetInsertPoint(finResBB);
  std::string ename(be_->namegen("excv"));
  llvm::LoadInst *exload = builder.CreateLoad(extmp, ename);
  builder.CreateResume(exload);

  return finRetBB;
}

// Create the needed control flow for an exception handler statement.
// At a high level, we want something that looks like:
//
//    try { body }
//    catch { exceptioncode }
//    finally { finallycode }
//
// This means creating the following landing pads + control flow:
//
//    { /* begin body */
//      <any calls are converted to invoke instructions,
//       targeting landing pad P1>
//      /* end body */
//    }
//    goto finok;
//    pad P1:
//      goto catch;
//    catch: {
//      /* begin exceptioncode */
//      <any calls are converted to invoke inst,
//       targeting landing pad P2>
//      /* end exceptioncode */
//    }
//    goto finok;
//    pad P2:
//      store exception -> ehtmp
//      finvar = false
//      goto finally;
//    finok:
//      finvar = true
//    finally:
//    { /* begin finallycode */
//      <calls here are left as is>
//      /* end finallycode */
//    }
//    if (finvar)
//      <normal return>
//    else
//      rethrow exception ehtmp
//

llvm::BasicBlock *GenBlocks::genExcep(Bstatement *excepst,
                                      llvm::BasicBlock *curblock)
{
  assert(excepst->flavor() == N_ExcepStmt);

  // Insure that current function has personality set.
  llvm::Function *func = function()->function();
  if (! func->hasPersonalityFn())
    func->setPersonalityFn(be_->personalityFunction());

  Bstatement *body = excepst->getExcepStmtBody();
  assert(body);
  Bstatement *ifexception = excepst->getExcepStmtOnException();
  assert(ifexception);
  Bstatement *finally = excepst->getExcepStmtFinally(); // may be null

  // This temp will track what sort of action is needed at the end of
  // of the "finally" clause.  For this variable, a value of 'true'
  // signals a normal return, and a value of 'false' indicates that
  // there was an additional exception thrown during execution of the
  // "ifexception" code (as opposed to an exception thrown during
  // execution of "body") that needs to be passed to unwind/resume
  // after the "finally" code.
  Bvariable *finvar = excepst->var();
  assert(finvar);

  // Create a "finok" BB; this block will set the "finally" variable
  // to true and then jump to the finally block.
  std::string fbbname(be_->namegen("finok"));
  llvm::BasicBlock *finokBB =
      llvm::BasicBlock::Create(context_, fbbname, func);

  // Create a "finally" BB, corresponding to where control will wind
  // up once both the body and (possibly) the exception clause are
  // complete. This will also be where we'll place any code in the
  // "finally" statement above.
  std::string cbbname(be_->namegen("finally"));
  llvm::BasicBlock *contBB =
      llvm::BasicBlock::Create(context_, cbbname, func);

  // Emit an assignment "finally = true" into the finok block,
  // then a jump to the finally block.
  {
    LIRBuilder builder(context_, llvm::ConstantFolder());
    builder.SetInsertPoint(finokBB);
    llvm::Value *tval = be_->boolean_constant_expression(true)->value();
    builder.CreateStore(tval, finvar->value());
    llvm::BranchInst::Create(contBB, finokBB);
  }

  // Handle finally statement where applicable.
  llvm::BasicBlock *bodyBB = curblock; // record where we're going to emit the body
  curblock = contBB;
  llvm::BasicBlock *finishBB = nullptr; // record where we're going to emit the finishing code
  if (finally != nullptr) {
    curblock = walk(finally, nullptr, curblock);
    finishBB = curblock;
  }

  // Create a landing pad block. This pad will be where control
  // will arrive if an exception is thrown within the "body" code.
  llvm::BasicBlock *padbb =
      llvm::BasicBlock::Create(context_, be_->namegen("pad"), func);

  // Block containing catch code
  llvm::BasicBlock *catchbb =
      llvm::BasicBlock::Create(context_, be_->namegen("catch"), func);

  // Emit landing pad inst in pad block, followed by branch to catch bb.
  {
    LIRBuilder builder(context_, llvm::ConstantFolder());
    builder.SetInsertPoint(padbb);
    llvm::LandingPadInst *padinst =
        builder.CreateLandingPad(be_->landingPadExceptionType(),
                                 0, be_->namegen("ex"));
    padinst->addClause(llvm::Constant::getNullValue(be_->llvmPtrType()));
    llvm::BranchInst::Create(catchbb, padbb);
  }

  // Create second pad block. Here the idea is that if an exception
  // is thrown as a result of any call within the catch ("ifexception" code)
  // it will wind up at this pad.
  llvm::BasicBlock *catchpadbb =
      llvm::BasicBlock::Create(context_, be_->namegen("catchpad"), func);

  // Create landing pad instruction in the second pad block. For this
  // landing pad, we want to capture the exception object into a
  // temporary, and set "finally = false" to indicate that an exception
  // was thrown.
  llvm::Value *extmp = populateCatchPadBlock(catchpadbb, finvar);
  llvm::BranchInst::Create(contBB, catchpadbb);

  // Now we are going to emit the body.

  // Not expecting to see nested exception statements, assert if this
  // crops up.
  assert(padBlockStack_.empty());

  // If there is a finally block, then record the block for purposes
  // of return handling.
  finallyBlock_ = (finally ? finokBB : nullptr);
  assert(!cachedReturn_);

  // Push first pad block onto stack. The presence of a non-empty pad
  // block stack will be an indication that any call in the body
  // subtree should be converted into an invoke using the pad.
  padBlockStack_.push_back(padbb);

  // Walk the body statement.
  curblock = bodyBB;
  curblock = walk(body, nullptr, curblock);

  // Pop the pad block stack.
  padBlockStack_.pop_back();

  // If the body block ended without a return, then insert a deferreturn;
  if (curblock)
    genDeferReturn(curblock);

  // Push second pad, walk exception stmt, then pop the pad.
  padBlockStack_.push_back(catchpadbb);
  auto bb = walk(ifexception, nullptr, catchbb);
  if (bb)
    llvm::BranchInst::Create(finokBB, bb);
  padBlockStack_.pop_back();

  // Return handling now complete.
  finallyBlock_ = nullptr;

  // Handle finally statement where applicable.
  curblock = finishBB;
  if (curblock)
    // Augment the end of the finally block with an if/jump to
    // return or resume, and populate the return/resume blocks.
    curblock = populateFinallyBlock(curblock, finvar, extmp);

  return curblock;
}

llvm::BasicBlock *GenBlocks::walk(Bnode *node,
                                  Bstatement *containingStmt,
                                  llvm::BasicBlock *curblock)
{
  Bexpression *expr = node->castToBexpression();
  if (expr)
    return walkExpr(curblock, containingStmt, expr);
  Bstatement *stmt = node->castToBstatement();
  assert(stmt);
  switch (stmt->flavor()) {
    case N_ExprStmt: {
      curblock = walkExpr(curblock, stmt, stmt->getExprStmtExpr());
      break;
    }
    case N_BlockStmt: {
      Bblock *bblock = stmt->castToBblock();
      if (curblock)
        insertLifetimeMarkersForBlock(bblock, nullptr, curblock, true);
      blockStack_.push_back(bblock);
      if (dibuildhelper_)
        dibuildhelper_->beginLexicalBlock(bblock);
      for (auto &st : stmt->getChildStmts())
        curblock = walk(st, nullptr, curblock);
      if (dibuildhelper_)
        dibuildhelper_->endLexicalBlock(bblock);
      if (curblock)
        insertLifetimeMarkersForBlock(bblock, nullptr, curblock, false);
      blockStack_.pop_back();
      break;
    }
    case N_IfStmt: {
      curblock = genIf(stmt, curblock);
      break;
    }
    case N_SwitchStmt: {
      curblock = genSwitch(stmt, curblock);
      break;
    }
    case N_ReturnStmt: {
      curblock = genReturn(stmt, curblock);
      break;
    }
    case N_DeferStmt: {
      curblock = genDefer(stmt, curblock);
      break;
    }
    case N_ExcepStmt: {
      curblock = genExcep(stmt, curblock);
      break;
    }
    case N_GotoStmt: {
      llvm::BasicBlock *lbb = getBlockForLabel(stmt->getGotoStmtTargetLabel());
      if (curblock && ! curblock->getTerminator())
        llvm::BranchInst::Create(lbb, curblock);
      curblock = nullptr;
      break;
    }
    case N_LabelStmt: {
      Blabel *label = stmt->getLabelStmtDefinedLabel();
      llvm::BasicBlock *lbb = getBlockForLabel(label);
      if (label->placeholder())
        function()->replaceLabelAddressPlaceholder(label->placeholder(), lbb);
      if (curblock)
        llvm::BranchInst::Create(lbb, curblock);
      curblock = lbb;
      break;
    }
    default:
      assert(false && "not yet handled");
  }
  return curblock;
}

llvm::BasicBlock *Llvm_backend::genEntryBlock(Bfunction *bfunction) {
  llvm::Function *func = bfunction->function();
  llvm::BasicBlock *entry = llvm::BasicBlock::Create(context_, "entry", func);

  // Spill parameters/arguments, insert allocas for local vars
  bfunction->genProlog(entry);

  return entry;
}

void Llvm_backend::fixupEpilogBlock(Bfunction *bfunction,
                                   llvm::BasicBlock *epilog)
{
  // Append a return instruction if the block does not end with
  // a control transfer.
  if (epilog->empty() || !epilog->back().isTerminator()) {
    LIRBuilder builder(context_, llvm::ConstantFolder());
    llvm::Function *func = bfunction->function();
    llvm::Type *rtyp= func->getFunctionType()->getReturnType();
    llvm::ReturnInst *ri = nullptr;
    if (rtyp->isVoidTy()) {
      ri = builder.CreateRetVoid();
    } else {
      llvm::Value *zv = llvm::Constant::getNullValue(rtyp);
      ri = builder.CreateRet(zv);
    }
    epilog->getInstList().push_back(ri);
  }
}

// Set the function body for FUNCTION using the code in CODE_BLOCK.

bool Llvm_backend::function_set_body(Bfunction *function,
                                     Bstatement *code_stmt)
{
  if (function == errorFunction_.get())
    return true;

  // debugging
  if (traceLevel() > 1) {
    std::cerr << "\nStatement tree dump:\n";
    code_stmt->dump();
  }

  // Invoke the tree integrity checker. We do this even if
  // checkIntegrity_ is false so to deal with any repairable
  // sharing that the front end may have introduced.
  enforceTreeIntegrity(code_stmt);

  // Create and populate entry block
  llvm::BasicBlock *entryBlock = genEntryBlock(function);

  // Avoid debug metadata generation if errors seen
  DIBuildHelper *dibh = nullptr;
  if (createDebugMetaData_ && errorCount_ == 0 && !go_be_saw_errors())
    dibh = dibuildhelper();

  // Walk the code statements
  GenBlocks gb(context_, this, function, code_stmt,
               dibh, entryBlock);
  llvm::BasicBlock *block = gb.walk(code_stmt, nullptr, entryBlock);
  gb.finishFunction(entryBlock);

  // Fix up epilog block if needed
  if (block)
    fixupEpilogBlock(function, block);

  // debugging
  if (traceLevel() > 0) {
    std::cerr << "LLVM function dump:\n";
    std::string s;
    llvm::raw_string_ostream os(s);
    function->function()->print(os);
    std::cerr << os.str();
  }

  return true;
}

// Write the definitions for all TYPE_DECLS, CONSTANT_DECLS,
// FUNCTION_DECLS, and VARIABLE_DECLS declared globally, as well as
// emit early debugging information.

void Llvm_backend::write_global_definitions(
    const std::vector<Btype *> &type_decls,
    const std::vector<Bexpression *> &constant_decls,
    const std::vector<Bfunction *> &function_decls,
    const std::vector<Bvariable *> &variable_decls) {

  finalizeExportData();

  // At the moment there isn't anything to do here with the
  // inputs we're being passed.

}

// Post-process export data to escape quotes, etc, writing bytes
// to the specified stringstream.
static void postProcessExportDataChunk(const char *bytes,
                                       unsigned int size,
                                       std::stringstream &ss)
{
  std::map<char, std::string> rewrites = { { '\\', "\\\\" },
                                           { '\0', "\\000" },
                                           { '\n', "\\n" },
                                           { '"', "\\\"" } };

  for (unsigned idx = 0; idx < size; ++idx) {
    const char byte = bytes[idx];
    auto it = rewrites.find(byte);
    if (it != rewrites.end())
      ss << it->second;
    else
      ss << byte;
  }
}

// Finalize export data.

void Llvm_backend::finalizeExportData()
{
  // Calling this here, for lack of a better spot
  if (errorCount_ == 0 && dibuildhelper())
    dibuildhelper_->finalize();

  assert(! exportDataFinalized_);
  exportDataFinalized_ = true;
  module().appendModuleInlineAsm("\t.text\n");

  if (traceLevel() > 1) {
    std::cerr << "Export data emitted:\n";
    std::cerr << module().getModuleInlineAsm();
  }
}

// This is called by the Go frontend proper to add data to the
// section containing Go export data.

void Llvm_backend::write_export_data(const char *bytes, unsigned int size)
{
  // FIXME: this is hacky and currently very ELF-specific. Better to
  // add real support in MC object file layer.

  assert(! exportDataFinalized_);

  if (! exportDataStarted_) {
    exportDataStarted_ = true;
    const char *preamble = "\t.section \".go_export\",\"e\",@progbits";
    module().appendModuleInlineAsm(preamble);
  }

  std::stringstream ss;
  ss << "\t.ascii \"";
  postProcessExportDataChunk(bytes, size, ss);
  ss << "\"\n";
  module().appendModuleInlineAsm(ss.str());
}


// Convert an identifier for use in an error message.
// TODO(tham): scan the identifier to determine if contains
// only ASCII or printable UTF-8, then perform character set
// conversions if needed.

const char *go_localize_identifier(const char *ident) { return ident; }

// Return a new backend generator.

Backend *go_get_backend(llvm::LLVMContext &context) {
  return new Llvm_backend(context, nullptr, nullptr, 0);
}
