//===--- GenDecl.cpp - IR Generation for Declarations ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
//  This file implements IR generation for local and global
//  declarations in Swift.
//
//===----------------------------------------------------------------------===//

#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/GenericSignature.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/Module.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/Pattern.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/TypeMemberVisitor.h"
#include "swift/AST/Types.h"
#include "swift/ClangImporter/ClangModule.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/IRGen/Linking.h"
#include "swift/Runtime/HeapObject.h"
#include "swift/SIL/FormalLinkage.h"
#include "swift/SIL/SILDebugScope.h"
#include "swift/SIL/SILModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/GlobalDecl.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TypeBuilder.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Transforms/Utils/ModuleUtils.h"

#include "Callee.h"
#include "ConformanceDescription.h"
#include "ConstantBuilder.h"
#include "Explosion.h"
#include "FixedTypeInfo.h"
#include "GenCall.h"
#include "GenClass.h"
#include "GenDecl.h"
#include "GenMeta.h"
#include "GenObjC.h"
#include "GenOpaque.h"
#include "GenProto.h"
#include "GenType.h"
#include "IRGenDebugInfo.h"
#include "IRGenFunction.h"
#include "IRGenMangler.h"
#include "IRGenModule.h"
#include "LoadableTypeInfo.h"
#include "MetadataRequest.h"
#include "ProtocolInfo.h"
#include "Signature.h"
#include "StructLayout.h"

using namespace swift;
using namespace irgen;

bool IRGenerator::tryEnableLazyTypeMetadata(NominalTypeDecl *Nominal) {
  // When compiling with -Onone keep all metadata for the debugger. Even if it
  // is not used by the program itself.
  if (!Opts.shouldOptimize())
    return false;
  if (Opts.UseJIT)
    return false;

  switch (Nominal->getKind()) {
    case DeclKind::Enum:
    case DeclKind::Struct:
      break;
    default:
      // Keep all metadata for classes, because a class can be instantiated by
      // using the library function _typeByName or NSClassFromString.
      return false;
  }

  switch (getDeclLinkage(Nominal)) {
    case FormalLinkage::PublicUnique:
    case FormalLinkage::PublicNonUnique:
      // We can't remove metadata for externally visible types.
      return false;
    case FormalLinkage::HiddenUnique:
      // In non-whole-module mode, also internal types are visible externally.
      if (!SIL.isWholeModule())
        return false;
      break;
    case FormalLinkage::Private:
      break;
  }

  auto insertResult = LazyTypeGlobals.try_emplace(Nominal);
  auto &entry = insertResult.first->second;
  assert(!entry.IsLazy);
  entry.IsLazy = true;
  if (entry.IsMetadataUsed)
    LazyTypeMetadata.push_back(Nominal);
  if (entry.IsDescriptorUsed)
    LazyTypeContextDescriptors.push_back(Nominal);

  return true;
}

namespace {
  
/// Add methods, properties, and protocol conformances from a JITed extension
/// to an ObjC class using the ObjC runtime.
///
/// This must happen after ObjCProtocolInitializerVisitor if any @objc protocols
/// were defined in the TU.
class CategoryInitializerVisitor
  : public ClassMemberVisitor<CategoryInitializerVisitor>
{
  IRGenFunction &IGF;
  IRGenModule &IGM = IGF.IGM;
  IRBuilder &Builder = IGF.Builder;
  
  llvm::Constant *class_replaceMethod;
  llvm::Constant *class_addProtocol;
  
  llvm::Value *classMetadata;
  llvm::Constant *metaclassMetadata;
  
public:
  CategoryInitializerVisitor(IRGenFunction &IGF, ExtensionDecl *ext)
    : IGF(IGF)
  {
    class_replaceMethod = IGM.getClassReplaceMethodFn();
    class_addProtocol = IGM.getClassAddProtocolFn();

    CanType origTy = ext->getSelfNominalTypeDecl()
        ->getDeclaredType()->getCanonicalType();
    classMetadata = emitClassHeapMetadataRef(IGF, origTy,
                                             MetadataValueType::ObjCClass,
                                             MetadataState::Complete,
                                             /*allow uninitialized*/ false);
    classMetadata = Builder.CreateBitCast(classMetadata, IGM.ObjCClassPtrTy);
    metaclassMetadata = IGM.getAddrOfMetaclassObject(
                                       origTy.getClassOrBoundGenericClass(),
                                                         NotForDefinition);
    metaclassMetadata = llvm::ConstantExpr::getBitCast(metaclassMetadata,
                                                   IGM.ObjCClassPtrTy);

    // Register ObjC protocol conformances.
    for (auto *p : ext->getLocalProtocols()) {
      if (!p->isObjC())
        continue;
      
      llvm::Value *protoRef = IGM.getAddrOfObjCProtocolRef(p, NotForDefinition);
      auto proto = Builder.CreateLoad(protoRef, IGM.getPointerAlignment());
      Builder.CreateCall(class_addProtocol, {classMetadata, proto});
    }
  }
  
  void visitMembers(ExtensionDecl *ext) {
    for (Decl *member : ext->getMembers())
      visit(member);
  }

  void visitTypeDecl(TypeDecl *type) {
    // We'll visit nested types separately if necessary.
  }

  void visitMissingMemberDecl(MissingMemberDecl *placeholder) {}
  
  void visitFuncDecl(FuncDecl *method) {
    if (!requiresObjCMethodDescriptor(method)) return;

    // Don't emit getters/setters for @NSManaged methods.
    if (method->getAttrs().hasAttribute<NSManagedAttr>())
      return;

    llvm::Constant *name, *imp, *types;
    emitObjCMethodDescriptorParts(IGM, method, /*concrete*/true,
                                  name, types, imp);
    
    // When generating JIT'd code, we need to call sel_registerName() to force
    // the runtime to unique the selector.
    llvm::Value *sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(),
                                          name);
    
    llvm::Value *args[] = {
      method->isStatic() ? metaclassMetadata : classMetadata,
      sel,
      imp,
      types
    };
    
    Builder.CreateCall(class_replaceMethod, args);
  }

  // Can't be added in an extension.
  void visitDestructorDecl(DestructorDecl *dtor) {}

  void visitConstructorDecl(ConstructorDecl *constructor) {
    if (!requiresObjCMethodDescriptor(constructor)) return;
    llvm::Constant *name, *imp, *types;
    emitObjCMethodDescriptorParts(IGM, constructor, /*concrete*/true,
                                  name, types, imp);

    // When generating JIT'd code, we need to call sel_registerName() to force
    // the runtime to unique the selector.
    llvm::Value *sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(),
                                          name);

    llvm::Value *args[] = {
      classMetadata,
      sel,
      imp,
      types
    };

    Builder.CreateCall(class_replaceMethod, args);
  }

  void visitPatternBindingDecl(PatternBindingDecl *binding) {
    // Ignore the PBD and just handle the individual vars.
  }
  
  void visitVarDecl(VarDecl *prop) {
    if (!requiresObjCPropertyDescriptor(IGM, prop)) return;

    // FIXME: register property metadata in addition to the methods.
    // ObjC doesn't have a notion of class properties, so we'd only do this
    // for instance properties.

    // Don't emit getters/setters for @NSManaged properties.
    if (prop->getAttrs().hasAttribute<NSManagedAttr>())
      return;

    llvm::Constant *name, *imp, *types;
    emitObjCGetterDescriptorParts(IGM, prop,
                                  name, types, imp);
    // When generating JIT'd code, we need to call sel_registerName() to force
    // the runtime to unique the selector.
    llvm::Value *sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(),
                                          name);
    auto theClass = prop->isStatic() ? metaclassMetadata : classMetadata;
    llvm::Value *getterArgs[] = {theClass, sel, imp, types};
    Builder.CreateCall(class_replaceMethod, getterArgs);

    if (prop->isSettable(prop->getDeclContext())) {
      emitObjCSetterDescriptorParts(IGM, prop,
                                    name, types, imp);
      sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(),
                               name);
      llvm::Value *setterArgs[] = {theClass, sel, imp, types};
      
      Builder.CreateCall(class_replaceMethod, setterArgs);
    }
  }

  void visitSubscriptDecl(SubscriptDecl *subscript) {
    assert(!subscript->isStatic() && "objc doesn't support class subscripts");
    if (!requiresObjCSubscriptDescriptor(IGM, subscript)) return;
    
    llvm::Constant *name, *imp, *types;
    emitObjCGetterDescriptorParts(IGM, subscript,
                                  name, types, imp);
    // When generating JIT'd code, we need to call sel_registerName() to force
    // the runtime to unique the selector.
    llvm::Value *sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(),
                                          name);
    llvm::Value *getterArgs[] = {classMetadata, sel, imp, types};
    Builder.CreateCall(class_replaceMethod, getterArgs);

    if (subscript->isSettable()) {
      emitObjCSetterDescriptorParts(IGM, subscript,
                                    name, types, imp);
      sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(),
                               name);
      llvm::Value *setterArgs[] = {classMetadata, sel, imp, types};
      
      Builder.CreateCall(class_replaceMethod, setterArgs);
    }
  }
};

/// Create a descriptor for JITed @objc protocol using the ObjC runtime.
class ObjCProtocolInitializerVisitor
  : public ClassMemberVisitor<ObjCProtocolInitializerVisitor>
{
  IRGenFunction &IGF;
  IRGenModule &IGM = IGF.IGM;
  IRBuilder &Builder = IGF.Builder;

  llvm::Constant *objc_getProtocol,
                 *objc_allocateProtocol,
                 *objc_registerProtocol,
                 *protocol_addMethodDescription,
                 *protocol_addProtocol;
  
  llvm::Value *NewProto = nullptr;
  
public:
  ObjCProtocolInitializerVisitor(IRGenFunction &IGF)
    : IGF(IGF)
  {
    objc_getProtocol = IGM.getGetObjCProtocolFn();
    objc_allocateProtocol = IGM.getAllocateObjCProtocolFn();
    objc_registerProtocol = IGM.getRegisterObjCProtocolFn();
    protocol_addMethodDescription = IGM.getProtocolAddMethodDescriptionFn();
    protocol_addProtocol = IGM.getProtocolAddProtocolFn();
  }
  
  void visitMembers(ProtocolDecl *proto) {
    // Check if the ObjC runtime already has a descriptor for this
    // protocol. If so, use it.
    SmallString<32> buf;
    auto protocolName
      = IGM.getAddrOfGlobalString(proto->getObjCRuntimeName(buf));
    
    auto existing = Builder.CreateCall(objc_getProtocol, protocolName);
    auto isNull = Builder.CreateICmpEQ(existing,
                   llvm::ConstantPointerNull::get(IGM.ProtocolDescriptorPtrTy));

    auto existingBB = IGF.createBasicBlock("existing_protocol");
    auto newBB = IGF.createBasicBlock("new_protocol");
    auto contBB = IGF.createBasicBlock("cont");
    Builder.CreateCondBr(isNull, newBB, existingBB);
    
    // Nothing to do if there's already a descriptor.
    Builder.emitBlock(existingBB);
    Builder.CreateBr(contBB);
    
    Builder.emitBlock(newBB);
    
    // Allocate the protocol descriptor.
    NewProto = Builder.CreateCall(objc_allocateProtocol, protocolName);
    
    // Add the parent protocols.
    for (auto parentProto : proto->getInheritedProtocols()) {
      if (!parentProto->isObjC())
        continue;
      llvm::Value *parentRef = IGM.getAddrOfObjCProtocolRef(parentProto,
                                                            NotForDefinition);
      parentRef = IGF.Builder.CreateBitCast(parentRef,
                                            IGM.ProtocolDescriptorPtrTy
                                              ->getPointerTo());
      auto parent = Builder.CreateLoad(parentRef,
                                       IGM.getPointerAlignment());
      Builder.CreateCall(protocol_addProtocol, {NewProto, parent});
    }
    
    // Add the members.
    for (Decl *member : proto->getMembers())
      visit(member);
    
    // Register it.
    Builder.CreateCall(objc_registerProtocol, NewProto);
    Builder.CreateBr(contBB);
    
    // Store the reference to the runtime's idea of the protocol descriptor.
    Builder.emitBlock(contBB);
    auto result = Builder.CreatePHI(IGM.ProtocolDescriptorPtrTy, 2);
    result->addIncoming(existing, existingBB);
    result->addIncoming(NewProto, newBB);
    
    llvm::Value *ref = IGM.getAddrOfObjCProtocolRef(proto, NotForDefinition);
    ref = IGF.Builder.CreateBitCast(ref,
                                  IGM.ProtocolDescriptorPtrTy->getPointerTo());

    Builder.CreateStore(result, ref, IGM.getPointerAlignment());
  }

  void visitTypeDecl(TypeDecl *type) {
    // We'll visit nested types separately if necessary.
  }

  void visitMissingMemberDecl(MissingMemberDecl *placeholder) {}

  void visitAbstractFunctionDecl(AbstractFunctionDecl *method) {
    if (isa<AccessorDecl>(method)) {
      // Accessors are handled as part of their AbstractStorageDecls.
      return;
    }

    llvm::Constant *name, *imp, *types;
    emitObjCMethodDescriptorParts(IGM, method, /*concrete*/false,
                                  name, types, imp);
    
    // When generating JIT'd code, we need to call sel_registerName() to force
    // the runtime to unique the selector.
    llvm::Value *sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(), name);

    llvm::Value *args[] = {
      NewProto, sel, types,
      // required?
      llvm::ConstantInt::get(IGM.ObjCBoolTy,
                             !method->getAttrs().hasAttribute<OptionalAttr>()),
      // instance?
      llvm::ConstantInt::get(IGM.ObjCBoolTy,
                   isa<ConstructorDecl>(method) || method->isInstanceMember()),
    };
    
    Builder.CreateCall(protocol_addMethodDescription, args);
  }
  
  void visitPatternBindingDecl(PatternBindingDecl *binding) {
    // Ignore the PBD and just handle the individual vars.
  }
  
  void visitAbstractStorageDecl(AbstractStorageDecl *prop) {
    // TODO: Add properties to protocol.
    
    llvm::Constant *name, *imp, *types;
    emitObjCGetterDescriptorParts(IGM, prop,
                                  name, types, imp);
    // When generating JIT'd code, we need to call sel_registerName() to force
    // the runtime to unique the selector.
    llvm::Value *sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(), name);
    llvm::Value *getterArgs[] = {
      NewProto, sel, types,
      // required?
      llvm::ConstantInt::get(IGM.ObjCBoolTy,
                             !prop->getAttrs().hasAttribute<OptionalAttr>()),
      // instance?
      llvm::ConstantInt::get(IGM.ObjCBoolTy,
                             prop->isInstanceMember()),
    };
    Builder.CreateCall(protocol_addMethodDescription, getterArgs);
    
    if (prop->isSettable(nullptr)) {
      emitObjCSetterDescriptorParts(IGM, prop,
                                    name, types, imp);
      sel = Builder.CreateCall(IGM.getObjCSelRegisterNameFn(), name);
      llvm::Value *setterArgs[] = {
        NewProto, sel, types,
        // required?
        llvm::ConstantInt::get(IGM.ObjCBoolTy,
                               !prop->getAttrs().hasAttribute<OptionalAttr>()),
        // instance?
        llvm::ConstantInt::get(IGM.ObjCBoolTy,
                               prop->isInstanceMember()),
      };
      Builder.CreateCall(protocol_addMethodDescription, setterArgs);
    }
  }
};

} // end anonymous namespace

namespace {
class PrettySourceFileEmission : public llvm::PrettyStackTraceEntry {
  const SourceFile &SF;
public:
  explicit PrettySourceFileEmission(const SourceFile &SF) : SF(SF) {}

  void print(raw_ostream &os) const override {
    os << "While emitting IR for source file " << SF.getFilename() << '\n';
  }
};
} // end anonymous namespace

/// Emit all the top-level code in the source file.
void IRGenModule::emitSourceFile(SourceFile &SF) {
  PrettySourceFileEmission StackEntry(SF);
  llvm::SaveAndRestore<SourceFile *> SetCurSourceFile(CurSourceFile, &SF);

  // Emit types and other global decls.
  for (auto *decl : SF.Decls)
    emitGlobalDecl(decl);
  for (auto *localDecl : SF.LocalTypeDecls)
    emitGlobalDecl(localDecl);

  SF.collectLinkLibraries([this](LinkLibrary linkLib) {
      this->addLinkLibrary(linkLib);
  });

  if (ObjCInterop)
    this->addLinkLibrary(LinkLibrary("objc", LibraryKind::Library));
}

/// Collect elements of an already-existing global list with the given
/// \c name into \c list.
///
/// We use this when Clang code generation might populate the list.
static void collectGlobalList(IRGenModule &IGM,
                              SmallVectorImpl<llvm::WeakTrackingVH> &list,
                              StringRef name) {
  if (auto *existing = IGM.Module.getGlobalVariable(name)) {
    auto *globals = cast<llvm::ConstantArray>(existing->getInitializer());
    for (auto &use : globals->operands()) {
      auto *global = use.get();
      list.push_back(global);
    }
    existing->eraseFromParent();
  }

  std::for_each(list.begin(), list.end(),
                [](const llvm::WeakTrackingVH &global) {
    assert(!isa<llvm::GlobalValue>(global) ||
           !cast<llvm::GlobalValue>(global)->isDeclaration() &&
           "all globals in the 'used' list must be definitions");
  });
}

/// Emit a global list, i.e. a global constant array holding all of a
/// list of values.  Generally these lists are for various LLVM
/// metadata or runtime purposes.
static llvm::GlobalVariable *
emitGlobalList(IRGenModule &IGM, ArrayRef<llvm::WeakTrackingVH> handles,
               StringRef name, StringRef section,
               llvm::GlobalValue::LinkageTypes linkage,
               llvm::Type *eltTy,
               bool isConstant) {
  // Do nothing if the list is empty.
  if (handles.empty()) return nullptr;

  // For global lists that actually get linked (as opposed to notional
  // ones like @llvm.used), it's important to set an explicit alignment
  // so that the linker doesn't accidentally put padding in the list.
  Alignment alignment = IGM.getPointerAlignment();

  // We have an array of value handles, but we need an array of constants.
  SmallVector<llvm::Constant*, 8> elts;
  elts.reserve(handles.size());
  for (auto &handle : handles) {
    auto elt = cast<llvm::Constant>(&*handle);
    if (elt->getType() != eltTy)
      elt = llvm::ConstantExpr::getBitCast(elt, eltTy);
    elts.push_back(elt);
  }

  auto varTy = llvm::ArrayType::get(eltTy, elts.size());
  auto init = llvm::ConstantArray::get(varTy, elts);
  auto var = new llvm::GlobalVariable(IGM.Module, varTy, isConstant, linkage,
                                      init, name);
  var->setSection(section);
  var->setAlignment(alignment.getValue());
  disableAddressSanitizer(IGM, var);

  // Mark the variable as used if doesn't have external linkage.
  // (Note that we'd specifically like to not put @llvm.used in itself.)
  if (llvm::GlobalValue::isLocalLinkage(linkage))
    IGM.addUsedGlobal(var);
  return var;
}

void IRGenModule::emitRuntimeRegistration() {
  // Duck out early if we have nothing to register.
  if (SwiftProtocols.empty() && ProtocolConformances.empty() &&
      RuntimeResolvableTypes.empty() &&
      (!ObjCInterop || (ObjCProtocols.empty() && ObjCClasses.empty() &&
                        ObjCCategoryDecls.empty())) &&
      FieldDescriptors.empty())
    return;
  
  // Find the entry point.
  SILFunction *EntryPoint =
    getSILModule().lookUpFunction(SWIFT_ENTRY_POINT_FUNCTION);
  
  // If we're debugging (and not in the REPL), we don't have a
  // main. Find a function marked with the LLDBDebuggerFunction
  // attribute instead.
  if (!EntryPoint && Context.LangOpts.DebuggerSupport) {
    for (SILFunction &SF : getSILModule()) {
      if (SF.hasLocation()) {
        if (Decl* D = SF.getLocation().getAsASTNode<Decl>()) {
          if (auto *FD = dyn_cast<FuncDecl>(D)) {
            if (FD->getAttrs().hasAttribute<LLDBDebuggerFunctionAttr>()) {
              EntryPoint = &SF;
              break;
            }
          }
        }
      }
    }
  }
  
  if (!EntryPoint)
    return;
    
  llvm::Function *EntryFunction = Module.getFunction(EntryPoint->getName());
  if (!EntryFunction)
    return;
  
  // Create a new function to contain our logic.
  auto fnTy = llvm::FunctionType::get(VoidTy, /*varArg*/ false);
  auto RegistrationFunction = llvm::Function::Create(fnTy,
                                           llvm::GlobalValue::PrivateLinkage,
                                           "runtime_registration",
                                           getModule());
  RegistrationFunction->setAttributes(constructInitialAttributes());
  
  // Insert a call into the entry function.
  {
    llvm::BasicBlock *EntryBB = &EntryFunction->getEntryBlock();
    llvm::BasicBlock::iterator IP = EntryBB->getFirstInsertionPt();
    IRBuilder Builder(getLLVMContext(),
                      DebugInfo && !Context.LangOpts.DebuggerSupport);
    Builder.llvm::IRBuilderBase::SetInsertPoint(EntryBB, IP);
    if (DebugInfo && !Context.LangOpts.DebuggerSupport)
      DebugInfo->setEntryPointLoc(Builder);
    Builder.CreateCall(RegistrationFunction, {});
  }
  
  IRGenFunction RegIGF(*this, RegistrationFunction);
  if (DebugInfo && !Context.LangOpts.DebuggerSupport)
    DebugInfo->emitArtificialFunction(RegIGF, RegistrationFunction);
  
  // Register ObjC protocols we added.
  if (ObjCInterop) {
    if (!ObjCProtocols.empty()) {
      // We need to initialize ObjC protocols in inheritance order, parents
      // first.
      
      llvm::DenseSet<ProtocolDecl*> protos;
      for (auto &proto : ObjCProtocols)
        protos.insert(proto.first);
      
      llvm::SmallVector<ProtocolDecl*, 4> protoInitOrder;

      std::function<void(ProtocolDecl*)> orderProtocol
        = [&](ProtocolDecl *proto) {
          // Recursively put parents first.
          for (auto parent : proto->getInheritedProtocols())
            orderProtocol(parent);

          // Skip if we don't need to reify this protocol.
          auto found = protos.find(proto);
          if (found == protos.end())
            return;
          protos.erase(found);
          protoInitOrder.push_back(proto);
        };
      
      while (!protos.empty()) {
        orderProtocol(*protos.begin());
      }

      // Visit the protocols in the order we established.
      for (auto *proto : protoInitOrder) {
        ObjCProtocolInitializerVisitor(RegIGF)
          .visitMembers(proto);
      }
    }
  }

  // Register Swift protocols if we added any.
  if (!SwiftProtocols.empty()) {
    llvm::Constant *protocols = emitSwiftProtocols();

    llvm::Constant *beginIndices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, 0),
    };
    auto begin = llvm::ConstantExpr::getGetElementPtr(
        /*Ty=*/nullptr, protocols, beginIndices);
    llvm::Constant *endIndices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, SwiftProtocols.size()),
    };
    auto end = llvm::ConstantExpr::getGetElementPtr(
        /*Ty=*/nullptr, protocols, endIndices);

    RegIGF.Builder.CreateCall(getRegisterProtocolsFn(), {begin, end});
  }

  // Register Swift protocol conformances if we added any.
  if (llvm::Constant *conformances = emitProtocolConformances()) {
    llvm::Constant *beginIndices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, 0),
    };
    auto begin = llvm::ConstantExpr::getGetElementPtr(
        /*Ty=*/nullptr, conformances, beginIndices);
    llvm::Constant *endIndices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, ProtocolConformances.size()),
    };
    auto end = llvm::ConstantExpr::getGetElementPtr(
        /*Ty=*/nullptr, conformances, endIndices);
    
    RegIGF.Builder.CreateCall(getRegisterProtocolConformancesFn(), {begin, end});
  }

  if (!RuntimeResolvableTypes.empty()) {
    llvm::Constant *records = emitTypeMetadataRecords();

    llvm::Constant *beginIndices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, 0),
    };
    auto begin = llvm::ConstantExpr::getGetElementPtr(
        /*Ty=*/nullptr, records, beginIndices);
    llvm::Constant *endIndices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, RuntimeResolvableTypes.size()),
    };
    auto end = llvm::ConstantExpr::getGetElementPtr(
        /*Ty=*/nullptr, records, endIndices);

    RegIGF.Builder.CreateCall(getRegisterTypeMetadataRecordsFn(), {begin, end});
  }

  // Register Objective-C classes and extensions we added.
  if (ObjCInterop) {
    for (llvm::WeakTrackingVH &ObjCClass : ObjCClasses) {
      RegIGF.Builder.CreateCall(getInstantiateObjCClassFn(), {ObjCClass});
    }

    for (ExtensionDecl *ext : ObjCCategoryDecls) {
      CategoryInitializerVisitor(RegIGF, ext).visitMembers(ext);
    }
  }

  if (!FieldDescriptors.empty()) {
    emitFieldDescriptors();
  }

  RegIGF.Builder.CreateRetVoid();
}

/// Return the address of the context descriptor representing the given
/// decl context.
///
/// For a nominal type context, this returns the address of the nominal type
/// descriptor.
/// For an extension context, this returns the address of the extension
/// context descriptor.
/// For a module or file unit context, this returns the address of the module
/// context descriptor.
/// For any other kind of context, this returns an anonymous context descriptor
/// for the context.
ConstantReference
IRGenModule::getAddrOfParentContextDescriptor(DeclContext *from,
                                              bool fromAnonymousContext) {
  // Some types get special treatment.
  if (auto Type = dyn_cast<NominalTypeDecl>(from)) {
    // Use a special module context if we have one.
    if (auto context =
            Mangle::ASTMangler::getSpecialManglingContext(
              Type, /*UseObjCProtocolNames=*/false)) {
      switch (*context) {
      case Mangle::ASTMangler::ObjCContext:
        return {getAddrOfObjCModuleContextDescriptor(),
                ConstantReference::Direct};
      case Mangle::ASTMangler::ClangImporterContext:
        return {getAddrOfClangImporterModuleContextDescriptor(),
                ConstantReference::Direct};
      }
    }

    // Wrap up private types in an anonymous context for the containing file
    // unit so that the runtime knows they have unstable identity.
    if (!fromAnonymousContext && Type->isOutermostPrivateOrFilePrivateScope())
      return {getAddrOfAnonymousContextDescriptor(Type),
              ConstantReference::Direct};
  }
  
  auto parent = from->getParent();
  
  switch (parent->getContextKind()) {
  case DeclContextKind::AbstractClosureExpr:
  case DeclContextKind::AbstractFunctionDecl:
  case DeclContextKind::SubscriptDecl:
  case DeclContextKind::EnumElementDecl:
  case DeclContextKind::TopLevelCodeDecl:
  case DeclContextKind::Initializer:
  case DeclContextKind::SerializedLocal:
    return {getAddrOfAnonymousContextDescriptor(
              fromAnonymousContext ? parent : from),
            ConstantReference::Direct};

  case DeclContextKind::GenericTypeDecl:
    if (auto nomTy = dyn_cast<NominalTypeDecl>(parent)) {
      return {getAddrOfTypeContextDescriptor(nomTy, DontRequireMetadata),
              ConstantReference::Direct};
    }
    return {getAddrOfAnonymousContextDescriptor(
              fromAnonymousContext ? parent : from),
            ConstantReference::Direct};

  case DeclContextKind::ExtensionDecl: {
    auto ext = cast<ExtensionDecl>(parent);
    // If the extension is equivalent to its extended context (that is, it's
    // in the same module as the original non-protocol type and
    // has no constraints), then we can use the original nominal type context
    // (assuming there is one).
    if (ext->isEquivalentToExtendedContext()) {
      auto nominal = ext->getExtendedNominal();
      // If the extended type is an ObjC class, it won't have a nominal type
      // descriptor, so we'll just emit an extension context.
      auto clas = dyn_cast<ClassDecl>(nominal);
      if (!clas || clas->isForeign() || hasKnownSwiftMetadata(*this, clas)) {
        // Some targets don't support relative references to undefined symbols.
        // If the extension is in a different file from the original type
        // declaration, it may not get emitted in this TU. Use an indirect
        // reference to work around the object format limitation.
        auto shouldBeIndirect =
            parent->getModuleScopeContext() != from->getModuleScopeContext()
          ? ConstantReference::Indirect
          : ConstantReference::Direct;
        
        IRGen.noteUseOfTypeContextDescriptor(nominal, DontRequireMetadata);
        return getAddrOfLLVMVariableOrGOTEquivalent(
                                LinkEntity::forNominalTypeDescriptor(nominal),
                                shouldBeIndirect);
      }
    }
    return {getAddrOfExtensionContextDescriptor(ext),
            ConstantReference::Direct};
  }
      
  case DeclContextKind::FileUnit:
    parent = parent->getParentModule();
    LLVM_FALLTHROUGH;
      
  case DeclContextKind::Module:
    return {getAddrOfModuleContextDescriptor(cast<ModuleDecl>(parent)),
            ConstantReference::Direct};
  }
  llvm_unreachable("unhandled kind");
}

/// Add the given global value to @llvm.used.
///
/// This value must have a definition by the time the module is finalized.
void IRGenModule::addUsedGlobal(llvm::GlobalValue *global) {
  LLVMUsed.push_back(global);
}

/// Add the given global value to @llvm.compiler.used.
///
/// This value must have a definition by the time the module is finalized.
void IRGenModule::addCompilerUsedGlobal(llvm::GlobalValue *global) {
  LLVMCompilerUsed.push_back(global);
}

/// Add the given global value to the Objective-C class list.
void IRGenModule::addObjCClass(llvm::Constant *classPtr, bool nonlazy) {
  ObjCClasses.push_back(classPtr);
  if (nonlazy)
    ObjCNonLazyClasses.push_back(classPtr);
}

void IRGenModule::addRuntimeResolvableType(NominalTypeDecl *nominal) {
  // Collect the nominal type records we emit into a special section.
  RuntimeResolvableTypes.push_back(nominal);

  // As soon as the type metadata is available, all the type's conformances
  // must be available, too. The reason is that a type (with the help of its
  // metadata) can be checked at runtime if it conforms to a protocol.
  addLazyConformances(nominal);
}

ConstantReference
IRGenModule::getConstantReferenceForProtocolDescriptor(ProtocolDecl *proto) {
  if (proto->isObjC()) {
    // ObjC protocol descriptors don't have a unique address, but get uniqued
    // by the Objective-C runtime at load time.
    // Get the indirected address of the protocol descriptor reference variable
    // that the ObjC runtime uniques.
    auto refVar = getAddrOfObjCProtocolRef(proto, NotForDefinition);
    return ConstantReference(refVar, ConstantReference::Indirect);
  }
  
  // Try to form a direct reference to the nominal type descriptor if it's in
  // the same binary, or use the GOT entry if it's from another binary.
  return getAddrOfLLVMVariableOrGOTEquivalent(
                                     LinkEntity::forProtocolDescriptor(proto));
}

void IRGenModule::addLazyConformances(DeclContext *dc) {
  for (const ProtocolConformance *conf :
         dc->getLocalConformances(ConformanceLookupKind::All, nullptr)) {
    IRGen.addLazyWitnessTable(conf);
  }
}

std::string IRGenModule::GetObjCSectionName(StringRef Section,
                                            StringRef MachOAttributes) {
  assert(Section.substr(0, 2) == "__" && "expected the name to begin with __");

  switch (TargetInfo.OutputObjectFormat) {
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("must know the object file format");
  case llvm::Triple::MachO:
    return MachOAttributes.empty()
               ? ("__DATA," + Section).str()
               : ("__DATA," + Section + "," + MachOAttributes).str();
  case llvm::Triple::ELF:
    return Section.substr(2).str();
  case llvm::Triple::COFF:
    return ("." + Section.substr(2) + "$B").str();
  case llvm::Triple::Wasm:
    return Section.substr(2).str();
  }

  llvm_unreachable("unexpected object file format");
}

void IRGenModule::SetCStringLiteralSection(llvm::GlobalVariable *GV,
                                           ObjCLabelType Type) {
  switch (TargetInfo.OutputObjectFormat) {
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("must know the object file format");
  case llvm::Triple::MachO:
    switch (Type) {
    case ObjCLabelType::ClassName:
      GV->setSection("__TEXT,__objc_classname,cstring_literals");
      return;
    case ObjCLabelType::MethodVarName:
      GV->setSection("__TEXT,__objc_methname,cstring_literals");
      return;
    case ObjCLabelType::MethodVarType:
      GV->setSection("__TEXT,__objc_methtype,cstring_literals");
      return;
    case ObjCLabelType::PropertyName:
      GV->setSection("__TEXT,__cstring,cstring_literals");
      return;
    }
  case llvm::Triple::ELF:
    return;
  case llvm::Triple::COFF:
    return;
  case llvm::Triple::Wasm:
    return;
  }

  llvm_unreachable("unexpected object file format");
}

void IRGenModule::emitGlobalLists() {
  if (ObjCInterop) {
    // Objective-C class references go in a variable with a meaningless
    // name but a magic section.
    emitGlobalList(*this, ObjCClasses, "objc_classes",
                   GetObjCSectionName("__objc_classlist",
                                      "regular,no_dead_strip"),
                   llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);

    // So do categories.
    emitGlobalList(*this, ObjCCategories, "objc_categories",
                   GetObjCSectionName("__objc_catlist",
                                      "regular,no_dead_strip"),
                   llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);

    // Emit nonlazily realized class references in a second magic section to make
    // sure they are realized by the Objective-C runtime before any instances
    // are allocated.
    emitGlobalList(*this, ObjCNonLazyClasses, "objc_non_lazy_classes",
                   GetObjCSectionName("__objc_nlclslist",
                                      "regular,no_dead_strip"),
                   llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
  }

  // @llvm.used

  // Collect llvm.used globals already in the module (coming from ClangCodeGen).
  collectGlobalList(*this, LLVMUsed, "llvm.used");
  emitGlobalList(*this, LLVMUsed, "llvm.used", "llvm.metadata",
                 llvm::GlobalValue::AppendingLinkage,
                 Int8PtrTy,
                 false);

  // Collect llvm.compiler.used globals already in the module (coming
  // from ClangCodeGen).
  collectGlobalList(*this, LLVMCompilerUsed, "llvm.compiler.used");
  emitGlobalList(*this, LLVMCompilerUsed, "llvm.compiler.used", "llvm.metadata",
                 llvm::GlobalValue::AppendingLinkage,
                 Int8PtrTy,
                 false);
}

static bool hasCodeCoverageInstrumentation(SILFunction &f, SILModule &m) {
  return f.getProfiler() && m.getOptions().EmitProfileCoverageMapping;
}

void IRGenerator::emitGlobalTopLevel() {
  // Generate order numbers for the functions in the SIL module that
  // correspond to definitions in the LLVM module.
  unsigned nextOrderNumber = 0;
  for (auto &silFn : PrimaryIGM->getSILModule().getFunctions()) {
    // Don't bother adding external declarations to the function order.
    if (!silFn.isDefinition()) continue;
    FunctionOrder.insert(std::make_pair(&silFn, nextOrderNumber++));
  }

  // Ensure that relative symbols are collocated in the same LLVM module.
  for (auto &wt : PrimaryIGM->getSILModule().getWitnessTableList()) {
    CurrentIGMPtr IGM = getGenModule(wt.getDeclContext());
    ensureRelativeSymbolCollocation(wt);
  }

  for (auto &wt : PrimaryIGM->getSILModule().getDefaultWitnessTableList()) {
    CurrentIGMPtr IGM = getGenModule(wt.getProtocol()->getDeclContext());
    ensureRelativeSymbolCollocation(wt);
  }

  for (SILGlobalVariable &v : PrimaryIGM->getSILModule().getSILGlobals()) {
    Decl *decl = v.getDecl();
    CurrentIGMPtr IGM = getGenModule(decl ? decl->getDeclContext() : nullptr);
    IGM->emitSILGlobalVariable(&v);
  }
  
  // Emit SIL functions.
  for (SILFunction &f : PrimaryIGM->getSILModule()) {
    // Eagerly emit functions that are externally visible. Functions with code
    // coverage instrumentation must also be eagerly emitted. So must functions
    // that are a dynamic replacement for another.
    if (!f.isPossiblyUsedExternally() &&
        !f.getDynamicallyReplacedFunction() &&
        !hasCodeCoverageInstrumentation(f, PrimaryIGM->getSILModule()))
      continue;

    CurrentIGMPtr IGM = getGenModule(&f);
    IGM->emitSILFunction(&f);
  }

  // Emit static initializers.
  for (auto Iter : *this) {
    IRGenModule *IGM = Iter.second;
    IGM->emitSILStaticInitializers();
  }

  // Emit witness tables.
  for (SILWitnessTable &wt : PrimaryIGM->getSILModule().getWitnessTableList()) {
    CurrentIGMPtr IGM = getGenModule(wt.getDeclContext());
    if (!canEmitWitnessTableLazily(&wt)) {
      IGM->emitSILWitnessTable(&wt);
    }
  }
  
  // Emit property descriptors.
  for (auto &prop : PrimaryIGM->getSILModule().getPropertyList()) {
    CurrentIGMPtr IGM = getGenModule(prop.getDecl()->getInnermostDeclContext());
    IGM->emitSILProperty(&prop);
  }
  
  // Emit code coverage mapping data.
  PrimaryIGM->emitCoverageMapping();

  for (auto Iter : *this) {
    IRGenModule *IGM = Iter.second;
    IGM->finishEmitAfterTopLevel();
  }
}

void IRGenModule::finishEmitAfterTopLevel() {
  // Emit the implicit import of the swift standard library.
  // FIXME: We'd get the exact set of implicit imports if we went through the
  // SourceFile's getImportedModules instead, but then we'd lose location info
  // for the explicit imports.
  if (DebugInfo) {
    if (ModuleDecl *TheStdlib = Context.getStdlibModule()) {
      if (TheStdlib != getSwiftModule()) {
        std::pair<swift::Identifier, swift::SourceLoc> AccessPath[] = {
          { Context.StdlibModuleName, swift::SourceLoc() }
        };

        auto Imp = ImportDecl::create(Context,
                                      getSwiftModule(),
                                      SourceLoc(),
                                      ImportKind::Module, SourceLoc(),
                                      AccessPath);
        Imp->setModule(TheStdlib);
        DebugInfo->emitImport(Imp);
      }
    }
  }
}

void IRGenerator::emitSwiftProtocols() {
  for (auto &m : *this) {
    m.second->emitSwiftProtocols();
  }
}

void IRGenerator::emitProtocolConformances() {
  for (auto &m : *this) {
    m.second->emitProtocolConformances();
  }
}

void IRGenerator::emitTypeMetadataRecords() {
  for (auto &m : *this) {
    m.second->emitTypeMetadataRecords();
  }
}

/// Emit any lazy definitions (of globals or functions or whatever
/// else) that we require.
void IRGenerator::emitLazyDefinitions() {
  while (!LazyTypeMetadata.empty() ||
         !LazyTypeContextDescriptors.empty() ||
         !LazyFunctionDefinitions.empty() ||
         !LazyWitnessTables.empty()) {

    // Emit any lazy type metadata we require.
    while (!LazyTypeMetadata.empty()) {
      NominalTypeDecl *type = LazyTypeMetadata.pop_back_val();
      auto &entry = LazyTypeGlobals.find(type)->second;
      assert(entry.IsLazy && entry.IsMetadataUsed && !entry.IsMetadataEmitted);
      entry.IsMetadataEmitted = true;
      CurrentIGMPtr IGM = getGenModule(type->getDeclContext());
      emitLazyTypeMetadata(*IGM.get(), type);
    }
    while (!LazyTypeContextDescriptors.empty()) {
      NominalTypeDecl *type = LazyTypeContextDescriptors.pop_back_val();
      auto &entry = LazyTypeGlobals.find(type)->second;
      assert(entry.IsLazy && entry.IsDescriptorUsed &&
             !entry.IsDescriptorEmitted);
      entry.IsDescriptorEmitted = true;
      CurrentIGMPtr IGM = getGenModule(type->getDeclContext());
      emitLazyTypeContextDescriptor(*IGM.get(), type,
                                    RequireMetadata_t(entry.IsMetadataUsed));
    }
    while (!LazyWitnessTables.empty()) {
      SILWitnessTable *wt = LazyWitnessTables.pop_back_val();
      CurrentIGMPtr IGM = getGenModule(wt->getDeclContext());
      IGM->emitSILWitnessTable(wt);
    }

    // Emit any lazy function definitions we require.
    while (!LazyFunctionDefinitions.empty()) {
      SILFunction *f = LazyFunctionDefinitions.pop_back_val();
      CurrentIGMPtr IGM = getGenModule(f);
      assert(!f->isPossiblyUsedExternally()
             && "function with externally-visible linkage emitted lazily?");
      IGM->emitSILFunction(f);
    }
  }
}

void IRGenerator::addLazyFunction(SILFunction *f) {
  // Add it to the queue if it hasn't already been put there.
  if (!LazilyEmittedFunctions.insert(f).second)
    return;

  LazyFunctionDefinitions.push_back(f);

  if (auto *dc = f->getDeclContext())
    if (dc->getParentSourceFile())
      return;

  if (CurrentIGM == nullptr)
    return;

  // Don't update the map if we already have an entry.
  DefaultIGMForFunction.insert(std::make_pair(f, CurrentIGM));
}

void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
                                       bool isUseOfMetadata,
                                       RequireMetadata_t requireMetadata) {
  if (!type)
    return;
  
  // Try to create a new record of the fact that we used this type.
  auto insertResult = LazyTypeGlobals.try_emplace(type);
  auto &entry = insertResult.first->second;

  // Imported structs and enums types are known to be lazy.
  if (insertResult.second) {
    entry.IsLazy = requiresForeignTypeMetadata(type);
  }

  bool metadataWasUsed = entry.IsMetadataUsed;
  bool descriptorWasUsed = entry.IsDescriptorUsed;

  bool isNovelUseOfMetadata = false;
  bool isNovelUseOfDescriptor = false;

  // Flag that we have a use of the metadata if
  //   - the reference was directly to the metadata
  //   - the reference was to the descriptor, but it requested the emission
  //     of metadata
  if (!metadataWasUsed && (isUseOfMetadata || requireMetadata)) {
    if (metadataWasUsed) return;
    entry.IsMetadataUsed = true;
    isNovelUseOfMetadata = true;
  }

  if (!descriptorWasUsed && !isUseOfMetadata) {
    if (descriptorWasUsed) return;
    entry.IsDescriptorUsed = true;
    isNovelUseOfDescriptor = true;
  }

  // If the type isn't known to be lazy, don't mess around with the queues.
  if (!entry.IsLazy)
    return;

  // Enqueue metadata emission if we have a novel use of it.
  if (isNovelUseOfMetadata)
    LazyTypeMetadata.push_back(type);

  // Enqueue descriptor emission if we have a novel use of it or if we
  // need to re-emit it because we're suddenly using metadata for it.
  if (isNovelUseOfDescriptor ||
      (isNovelUseOfMetadata && entry.IsDescriptorEmitted)) {
    entry.IsDescriptorEmitted = false; // clear this in case it was true
    LazyTypeContextDescriptors.push_back(type);
  }
}
static std::string getDynamicReplacementSection(IRGenModule &IGM) {
  std::string sectionName;
  switch (IGM.TargetInfo.OutputObjectFormat) {
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("Don't know how to emit field records table for "
                     "the selected object format.");
  case llvm::Triple::MachO:
    sectionName = "__TEXT, __swift5_replace, regular, no_dead_strip";
    break;
  case llvm::Triple::ELF:
  case llvm::Triple::Wasm:
    sectionName = "swift5_replace";
    break;
  case llvm::Triple::COFF:
    sectionName = ".sw5repl$B";
    break;
  }
  return sectionName;
}

llvm::GlobalVariable *IRGenModule::getGlobalForDynamicallyReplaceableThunk(
    LinkEntity &entity, llvm::Type *type, ForDefinition_t forDefinition) {
  return cast<llvm::GlobalVariable>(
      getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo()));
}

/// Creates a dynamic replacement chain entry for \p SILFn that contains either
/// the implementation function pointer \p or a nullptr, the next pointer of the
/// chain entry is set to nullptr.
///   struct ChainEntry {
///      void *funPtr;
///      struct ChainEntry *next;
///   }
static llvm::GlobalVariable *getChainEntryForDynamicReplacement(
    IRGenModule &IGM, SILFunction *SILFn,
    llvm::Function *implFunction = nullptr,
    ForDefinition_t forDefinition = ForDefinition) {

  LinkEntity entity =
      LinkEntity::forDynamicallyReplaceableFunctionVariable(SILFn);
  auto linkEntry = IGM.getGlobalForDynamicallyReplaceableThunk(
      entity, IGM.DynamicReplacementLinkEntryTy, forDefinition);
  if (!forDefinition)
    return linkEntry;

  auto *funPtr =
      implFunction ? llvm::ConstantExpr::getBitCast(implFunction, IGM.Int8PtrTy)
                   : llvm::ConstantExpr::getNullValue(IGM.Int8PtrTy);
  auto *nextEntry =
      llvm::ConstantExpr::getNullValue(IGM.DynamicReplacementLinkEntryPtrTy);
  llvm::Constant *fields[] = {funPtr, nextEntry};
  auto *entry =
      llvm::ConstantStruct::get(IGM.DynamicReplacementLinkEntryTy, fields);
  linkEntry->setInitializer(entry);
  return linkEntry;
}

void IRGenerator::emitDynamicReplacements() {
  if (DynamicReplacements.empty())
    return;

  auto &IGM = *getPrimaryIGM();

  // struct ReplacementScope {
  //   uint32t flags; // unused
  //   uint32t numReplacements;
  //   struct Entry {
  //     RelativeIndirectablePointer<KeyEntry, false> replacedFunctionKey;
  //     RelativeDirectPointer<void> newFunction;
  //     RelativeDirectPointer<LinkEntry> replacement;
  //     uint32_t flags; // shouldChain.
  //   }[0]
  // };
  ConstantInitBuilder builder(IGM);
  auto replacementScope = builder.beginStruct();
  replacementScope.addInt32(0); // unused flags.
  replacementScope.addInt32(DynamicReplacements.size());

  auto replacementsArray =
      replacementScope.beginArray();
  for (auto *newFunc : DynamicReplacements) {
    auto replacementLinkEntry =
        getChainEntryForDynamicReplacement(IGM, newFunc);
    // TODO: replacementLinkEntry->setZeroSection()
    auto *origFunc = newFunc->getDynamicallyReplacedFunction();
    assert(origFunc);
    auto keyRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
        LinkEntity::forDynamicallyReplaceableFunctionKey(origFunc));

    llvm::Constant *newFnPtr = llvm::ConstantExpr::getBitCast(
        IGM.getAddrOfSILFunction(newFunc, NotForDefinition), IGM.Int8PtrTy);

    auto replacement = replacementsArray.beginStruct();
    replacement.addRelativeAddress(keyRef); // tagged relative reference.
    replacement.addRelativeAddress(newFnPtr); // direct relative reference.
    replacement.addRelativeAddress(
        replacementLinkEntry); // direct relative reference.
    replacement.addInt32(
        Opts.EnableDynamicReplacementChaining ? 1 : 0);
    replacement.finishAndAddTo(replacementsArray);
  }
  replacementsArray.finishAndAddTo(replacementScope);

  auto var = replacementScope.finishAndCreateGlobal(
      "\x01l_unnamed_dynamic_replacements", IGM.getPointerAlignment(),
      /*isConstant*/ true, llvm::GlobalValue::PrivateLinkage);
  IGM.setTrueConstGlobal(var);
  IGM.addUsedGlobal(var);

  // Emit the data for automatic replacement to happen on load.
  // struct AutomaticReplacements {
  //   uint32t flags; // unused
  //   uint32t numReplacements;
  //   struct Entry {
  //     RelativeDirectPointer<ReplacementScope> replacements;
  //     uint32_t flags; // unused.
  //   }[0]
  // };
  auto autoReplacements = builder.beginStruct();
  autoReplacements.addInt32(0); // unused flags.
  autoReplacements.addInt32(1); // number of replacement entries.
  auto autoReplacementsArray = autoReplacements.beginArray();
  autoReplacementsArray.addRelativeAddress(var);
  autoReplacementsArray.finishAndAddTo(autoReplacements);
  auto autoReplVar = autoReplacements.finishAndCreateGlobal(
      "\x01l_auto_dynamic_replacements", IGM.getPointerAlignment(),
      /*isConstant*/ true, llvm::GlobalValue::PrivateLinkage);
  autoReplVar->setSection(getDynamicReplacementSection(IGM));
  IGM.addUsedGlobal(autoReplVar);
}

void IRGenerator::emitEagerClassInitialization() {
  if (ClassesForEagerInitialization.empty())
    return;

  // Emit the register function in the primary module.
  IRGenModule *IGM = getPrimaryIGM();

  llvm::Function *RegisterFn = llvm::Function::Create(
                                llvm::FunctionType::get(IGM->VoidTy, false),
                                llvm::GlobalValue::PrivateLinkage,
                                "_swift_eager_class_initialization");
  IGM->Module.getFunctionList().push_back(RegisterFn);
  IRGenFunction RegisterIGF(*IGM, RegisterFn);
  RegisterFn->setAttributes(IGM->constructInitialAttributes());
  RegisterFn->setCallingConv(IGM->DefaultCC);

  for (ClassDecl *CD : ClassesForEagerInitialization) {
    Type Ty = CD->getDeclaredType();
    llvm::Value *MetaData = RegisterIGF.emitTypeMetadataRef(getAsCanType(Ty));
    assert(CD->getAttrs().hasAttribute<StaticInitializeObjCMetadataAttr>());

    // Get the metadata to make sure that the class is registered. We need to 
    // add a use (empty inline asm instruction) for the metadata. Otherwise
    // llvm would optimize the metadata accessor call away because it's
    // defined as "readnone".
    llvm::FunctionType *asmFnTy =
      llvm::FunctionType::get(IGM->VoidTy, {MetaData->getType()},
                              false /* = isVarArg */);
    llvm::InlineAsm *inlineAsm =
      llvm::InlineAsm::get(asmFnTy, "", "r", true /* = SideEffects */);
    RegisterIGF.Builder.CreateAsmCall(inlineAsm, MetaData);
  }
  RegisterIGF.Builder.CreateRetVoid();

  // Add the registration function as a static initializer. We use a priority
  // slightly lower than used for C++ global constructors, so that the code is
  // executed before C++ global constructors (in case someone uses archives
  // from a C++ global constructor).
  llvm::appendToGlobalCtors(IGM->Module, RegisterFn, 60000, nullptr);
}

/// Emit symbols for eliminated dead methods, which can still be referenced
/// from other modules. This happens e.g. if a public class contains a (dead)
/// private method.
void IRGenModule::emitVTableStubs() {
  llvm::Function *stub = nullptr;
  for (auto I = getSILModule().zombies_begin();
           I != getSILModule().zombies_end(); ++I) {
    const SILFunction &F = *I;
    if (! F.isExternallyUsedSymbol())
      continue;
    
    if (!stub) {
      // Create a single stub function which calls swift_deletedMethodError().
      stub = llvm::Function::Create(llvm::FunctionType::get(VoidTy, false),
                                    llvm::GlobalValue::InternalLinkage,
                                    "_swift_dead_method_stub");
      stub->setAttributes(constructInitialAttributes());
      Module.getFunctionList().push_back(stub);
      stub->setCallingConv(DefaultCC);
      auto *entry = llvm::BasicBlock::Create(getLLVMContext(), "entry", stub);
      auto *errorFunc = getDeletedMethodErrorFn();
      llvm::CallInst::Create(errorFunc, ArrayRef<llvm::Value *>(), "", entry);
      new llvm::UnreachableInst(getLLVMContext(), entry);
    }

    // For each eliminated method symbol create an alias to the stub.
    auto *alias = llvm::GlobalAlias::create(llvm::GlobalValue::ExternalLinkage,
                                            F.getName(), stub);

    if (F.getEffectiveSymbolLinkage() == SILLinkage::Hidden)
      alias->setVisibility(llvm::GlobalValue::HiddenVisibility);
    else
      ApplyIRLinkage(IRLinkage::ExternalExport).to(alias);
  }
}

static IRLinkage
getIRLinkage(const UniversalLinkageInfo &info, SILLinkage linkage,
             ForDefinition_t isDefinition,
             bool isWeakImported) {
#define RESULT(LINKAGE, VISIBILITY, DLL_STORAGE)                               \
  IRLinkage{llvm::GlobalValue::LINKAGE##Linkage,                               \
            llvm::GlobalValue::VISIBILITY##Visibility,                         \
            llvm::GlobalValue::DLL_STORAGE##StorageClass}

  // Use protected visibility for public symbols we define on ELF.  ld.so
  // doesn't support relative relocations at load time, which interferes with
  // our metadata formats.  Default visibility should suffice for other object
  // formats.
  llvm::GlobalValue::VisibilityTypes PublicDefinitionVisibility =
      info.IsELFObject ? llvm::GlobalValue::ProtectedVisibility
                       : llvm::GlobalValue::DefaultVisibility;
  llvm::GlobalValue::DLLStorageClassTypes ExportedStorage =
      info.UseDLLStorage ? llvm::GlobalValue::DLLExportStorageClass
                         : llvm::GlobalValue::DefaultStorageClass;
  llvm::GlobalValue::DLLStorageClassTypes ImportedStorage =
      info.UseDLLStorage ? llvm::GlobalValue::DLLImportStorageClass
                         : llvm::GlobalValue::DefaultStorageClass;

  switch (linkage) {
  case SILLinkage::Public:
    return {llvm::GlobalValue::ExternalLinkage, PublicDefinitionVisibility,
            ExportedStorage};

  case SILLinkage::PublicNonABI:
    return isDefinition ? RESULT(WeakODR, Hidden, Default)
                        : RESULT(External, Hidden, Default);

  case SILLinkage::Shared:
  case SILLinkage::SharedExternal:
    return isDefinition ? RESULT(LinkOnceODR, Hidden, Default)
                        : RESULT(External, Hidden, Default);

  case SILLinkage::Hidden:
    return RESULT(External, Hidden, Default);

  case SILLinkage::Private: {
    if (info.forcePublicDecls() && !isDefinition)
      return getIRLinkage(info, SILLinkage::PublicExternal, isDefinition,
                          isWeakImported);
    auto linkage = info.needLinkerToMergeDuplicateSymbols()
                       ? llvm::GlobalValue::LinkOnceODRLinkage
                       : llvm::GlobalValue::InternalLinkage;
    auto visibility = info.shouldAllPrivateDeclsBeVisibleFromOtherFiles()
                          ? llvm::GlobalValue::HiddenVisibility
                          : llvm::GlobalValue::DefaultVisibility;
    return {linkage, visibility, llvm::GlobalValue::DefaultStorageClass};
  }

  case SILLinkage::PublicExternal: {
    if (isDefinition)
      return RESULT(AvailableExternally, Default, Default);

    auto linkage = isWeakImported ? llvm::GlobalValue::ExternalWeakLinkage
                                  : llvm::GlobalValue::ExternalLinkage;
    return {linkage, llvm::GlobalValue::DefaultVisibility, ImportedStorage};
  }

  case SILLinkage::HiddenExternal:
  case SILLinkage::PrivateExternal:
    if (isDefinition)
      return RESULT(AvailableExternally, Hidden, Default);

    return {llvm::GlobalValue::ExternalLinkage,
            llvm::GlobalValue::DefaultVisibility, ImportedStorage};

  }

  llvm_unreachable("bad SIL linkage");
}

/// Given that we're going to define a global value but already have a
/// forward-declaration of it, update its linkage.
void irgen::updateLinkageForDefinition(IRGenModule &IGM,
                                       llvm::GlobalValue *global,
                                       const LinkEntity &entity) {
  // TODO: there are probably cases where we can avoid redoing the
  // entire linkage computation.
  UniversalLinkageInfo linkInfo(IGM);
  bool weakImported = entity.isWeakImported(IGM.getSwiftModule(),
                                            IGM.getAvailabilityContext());
  auto IRL =
      getIRLinkage(linkInfo, entity.getLinkage(ForDefinition),
                   ForDefinition, weakImported);
  ApplyIRLinkage(IRL).to(global);

  // Everything externally visible is considered used in Swift.
  // That mostly means we need to be good at not marking things external.
  //
  // Exclude "main", because it should naturally be used, and because adding it
  // to llvm.used leaves a dangling use when the REPL attempts to discard
  // intermediate mains.
  if (LinkInfo::isUsed(IRL) && global->getName() != SWIFT_ENTRY_POINT_FUNCTION)
    IGM.addUsedGlobal(global);
}

LinkInfo LinkInfo::get(IRGenModule &IGM, const LinkEntity &entity,
                       ForDefinition_t isDefinition) {
  return LinkInfo::get(UniversalLinkageInfo(IGM),
                       IGM.getSwiftModule(),
                       IGM.getAvailabilityContext(),
                       entity, isDefinition);
}

LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo,
                       ModuleDecl *swiftModule,
                       AvailabilityContext availabilityContext,
                       const LinkEntity &entity,
                       ForDefinition_t isDefinition) {
  LinkInfo result;
  // FIXME: For anything in the standard library, we assume is locally defined.
  // The only two ways imported interfaces are currently created is via a shims
  // interface where the ClangImporter will correctly give us the proper DLL
  // storage for the declaration.  Otherwise, it is from a `@_silgen_name`
  // attributed declaration, which we explicitly handle elsewhere.  So, in the
  // case of a standard library build, just assume everything is locally
  // defined.  Ideally, we would integrate the linkage calculation properly to
  // avoid this special casing.
  ForDefinition_t isStdlibOrDefinition =
      ForDefinition_t(swiftModule->isStdlibModule() || isDefinition);

  entity.mangle(result.Name);
  bool weakImported = entity.isWeakImported(swiftModule, availabilityContext);
  result.IRL = getIRLinkage(linkInfo, entity.getLinkage(isStdlibOrDefinition),
                            isDefinition, weakImported);
  result.ForDefinition = isDefinition;
  return result;
}

LinkInfo LinkInfo::get(const UniversalLinkageInfo &linkInfo, StringRef name,
                       SILLinkage linkage, ForDefinition_t isDefinition,
                       bool isWeakImported) {
  LinkInfo result;

  result.Name += name;
  result.IRL = getIRLinkage(linkInfo, linkage, isDefinition, isWeakImported);
  result.ForDefinition = isDefinition;
  return result;
}

static bool isPointerTo(llvm::Type *ptrTy, llvm::Type *objTy) {
  return cast<llvm::PointerType>(ptrTy)->getElementType() == objTy;
}

/// Get or create an LLVM function with these linkage rules.
llvm::Function *irgen::createFunction(IRGenModule &IGM,
                                      LinkInfo &linkInfo,
                                      const Signature &signature,
                                      llvm::Function *insertBefore,
                                      OptimizationMode FuncOptMode) {
  auto name = linkInfo.getName();

  llvm::Function *existing = IGM.Module.getFunction(name);
  if (existing) {
    if (isPointerTo(existing->getType(), signature.getType()))
      return cast<llvm::Function>(existing);

    IGM.error(SourceLoc(),
              "program too clever: function collides with existing symbol " +
                  name);

    // Note that this will implicitly unique if the .unique name is also taken.
    existing->setName(name + ".unique");
  }

  llvm::Function *fn =
    llvm::Function::Create(signature.getType(), linkInfo.getLinkage(), name);
  fn->setCallingConv(signature.getCallingConv());

  if (insertBefore) {
    IGM.Module.getFunctionList().insert(insertBefore->getIterator(), fn);
  } else {
    IGM.Module.getFunctionList().push_back(fn);
  }

  ApplyIRLinkage({linkInfo.getLinkage(), linkInfo.getVisibility(), linkInfo.getDLLStorage()})
      .to(fn);

  llvm::AttrBuilder initialAttrs;
  IGM.constructInitialFnAttributes(initialAttrs, FuncOptMode);
  // Merge initialAttrs with attrs.
  auto updatedAttrs =
    signature.getAttributes().addAttributes(IGM.getLLVMContext(),
                                      llvm::AttributeList::FunctionIndex,
                                            initialAttrs);
  if (!updatedAttrs.isEmpty())
    fn->setAttributes(updatedAttrs);

  // Everything externally visible is considered used in Swift.
  // That mostly means we need to be good at not marking things external.
  //
  // Exclude "main", because it should naturally be used, and because adding it
  // to llvm.used leaves a dangling use when the REPL attempts to discard
  // intermediate mains.
  if (linkInfo.isUsed() && name != SWIFT_ENTRY_POINT_FUNCTION) {
    IGM.addUsedGlobal(fn);
  }

  return fn;
}

bool LinkInfo::isUsed(IRLinkage IRL) {
  // Everything externally visible is considered used in Swift.
  // That mostly means we need to be good at not marking things external.
  return IRL.Linkage == llvm::GlobalValue::ExternalLinkage &&
         (IRL.Visibility == llvm::GlobalValue::DefaultVisibility ||
          IRL.Visibility == llvm::GlobalValue::ProtectedVisibility) &&
         (IRL.DLLStorage == llvm::GlobalValue::DefaultStorageClass ||
          IRL.DLLStorage == llvm::GlobalValue::DLLExportStorageClass);
}

/// Get or create an LLVM global variable with these linkage rules.
llvm::GlobalVariable *swift::irgen::createVariable(
    IRGenModule &IGM, LinkInfo &linkInfo, llvm::Type *storageType,
    Alignment alignment, DebugTypeInfo DbgTy, Optional<SILLocation> DebugLoc,
    StringRef DebugName, bool inFixedBuffer) {
  auto name = linkInfo.getName();
  llvm::GlobalValue *existingValue = IGM.Module.getNamedGlobal(name);
  if (existingValue) {
    auto existingVar = dyn_cast<llvm::GlobalVariable>(existingValue);
    if (existingVar && isPointerTo(existingVar->getType(), storageType))
      return existingVar;

    IGM.error(SourceLoc(),
              "program too clever: variable collides with existing symbol " +
                  name);

    // Note that this will implicitly unique if the .unique name is also taken.
    existingValue->setName(name + ".unique");
  }

  auto var = new llvm::GlobalVariable(IGM.Module, storageType,
                                      /*constant*/ false, linkInfo.getLinkage(),
                                      /*initializer*/ nullptr, name);
  ApplyIRLinkage({linkInfo.getLinkage(),
                  linkInfo.getVisibility(),
                  linkInfo.getDLLStorage()})
      .to(var);
  var->setAlignment(alignment.getValue());

  // Everything externally visible is considered used in Swift.
  // That mostly means we need to be good at not marking things external.
  if (linkInfo.isUsed()) {
    IGM.addUsedGlobal(var);
  }

  if (IGM.DebugInfo && !DbgTy.isNull() && linkInfo.isForDefinition())
    IGM.DebugInfo->emitGlobalVariableDeclaration(
        var, DebugName.empty() ? name : DebugName, name, DbgTy,
        var->hasInternalLinkage(), inFixedBuffer, DebugLoc);

  return var;
}

void swift::irgen::disableAddressSanitizer(IRGenModule &IGM, llvm::GlobalVariable *var) {
  // Add an operand to llvm.asan.globals blacklisting this global variable.
  llvm::Metadata *metadata[] = {
    // The global variable to blacklist.
    llvm::ConstantAsMetadata::get(var),
    
    // Source location. Optional, unnecessary here.
    nullptr,
    
    // Name. Optional, unnecessary here.
    nullptr,
    
    // Whether the global is dynamically initialized.
    llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
      llvm::Type::getInt1Ty(IGM.Module.getContext()), false)),
    
    // Whether the global is blacklisted.
    llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
      llvm::Type::getInt1Ty(IGM.Module.getContext()), true))};
  
  auto *globalNode = llvm::MDNode::get(IGM.Module.getContext(), metadata);
  auto *asanMetadata = IGM.Module.getOrInsertNamedMetadata("llvm.asan.globals");
  asanMetadata->addOperand(globalNode);
}

/// Emit a global declaration.
void IRGenModule::emitGlobalDecl(Decl *D) {
  switch (D->getKind()) {
  case DeclKind::Extension:
    return emitExtension(cast<ExtensionDecl>(D));

  case DeclKind::Protocol:
    return emitProtocolDecl(cast<ProtocolDecl>(D));

  case DeclKind::PatternBinding:
    // The global initializations are in SIL.
    return;

  case DeclKind::Param:
    llvm_unreachable("there are no global function parameters");

  case DeclKind::Subscript:
    llvm_unreachable("there are no global subscript operations");
      
  case DeclKind::EnumCase:
  case DeclKind::EnumElement:
    llvm_unreachable("there are no global enum elements");

  case DeclKind::Constructor:
    llvm_unreachable("there are no global constructor");

  case DeclKind::Destructor:
    llvm_unreachable("there are no global destructor");

  case DeclKind::MissingMember:
    llvm_unreachable("there are no global member placeholders");

  case DeclKind::TypeAlias:
  case DeclKind::GenericTypeParam:
  case DeclKind::AssociatedType:
  case DeclKind::IfConfig: 
  case DeclKind::PoundDiagnostic:
    return;

  case DeclKind::Enum:
    return emitEnumDecl(cast<EnumDecl>(D));

  case DeclKind::Struct:
    return emitStructDecl(cast<StructDecl>(D));

  case DeclKind::Class:
    return emitClassDecl(cast<ClassDecl>(D));

  // These declarations are only included in the debug info.
  case DeclKind::Import:
    if (DebugInfo)
      DebugInfo->emitImport(cast<ImportDecl>(D));
    return;

  // We emit these as part of the PatternBindingDecl.
  case DeclKind::Var:
    return;

  case DeclKind::Func:
  case DeclKind::Accessor:
    // Handled in SIL.
    return;

  case DeclKind::TopLevelCode:
    // All the top-level code will be lowered separately.
    return;
      
  // Operator decls aren't needed for IRGen.
  case DeclKind::InfixOperator:
  case DeclKind::PrefixOperator:
  case DeclKind::PostfixOperator:
  case DeclKind::PrecedenceGroup:
    return;

  case DeclKind::Module:
    return;
  }

  llvm_unreachable("bad decl kind!");
}

Address IRGenModule::getAddrOfSILGlobalVariable(SILGlobalVariable *var,
                                                const TypeInfo &ti,
                                                ForDefinition_t forDefinition) {
  if (auto clangDecl = var->getClangDecl()) {
    auto addr = getAddrOfClangGlobalDecl(cast<clang::VarDecl>(clangDecl),
                                         forDefinition);

    // If we're not emitting this to define it, make sure we cast it to the
    // right type.
    if (!forDefinition) {
      auto ptrTy = ti.getStorageType()->getPointerTo();
      addr = llvm::ConstantExpr::getBitCast(addr, ptrTy);
    }

    auto alignment =
      Alignment(getClangASTContext().getDeclAlign(clangDecl).getQuantity());
    return Address(addr, alignment);
  }

  LinkEntity entity = LinkEntity::forSILGlobalVariable(var);
  ResilienceExpansion expansion = getResilienceExpansionForLayout(var);

  llvm::Type *storageType;
  llvm::Type *castStorageToType = nullptr;
  Size fixedSize;
  Alignment fixedAlignment;
  bool inFixedBuffer = false;

  if (var->isInitializedObject()) {
    assert(ti.isFixedSize(expansion));
    StructLayout *Layout = StaticObjectLayouts[var].get();
    if (!Layout) {
      // Create the layout (includes the llvm type) for the statically
      // initialized object and store it for later.
      ObjectInst *OI = cast<ObjectInst>(var->getStaticInitializerValue());
      llvm::SmallVector<SILType, 16> TailTypes;
      for (SILValue TailOp : OI->getTailElements()) {
        TailTypes.push_back(TailOp->getType());
      }
      Layout = getClassLayoutWithTailElems(*this,
                                           var->getLoweredType(), TailTypes);
      StaticObjectLayouts[var] = std::unique_ptr<StructLayout>(Layout);
    }
    storageType = Layout->getType();
    fixedSize = Layout->getSize();
    fixedAlignment = Layout->getAlignment();
    castStorageToType = cast<FixedTypeInfo>(ti).getStorageType();
    assert(fixedAlignment >= TargetInfo.HeapObjectAlignment);
  } else if (ti.isFixedSize(expansion)) {
    // Allocate static storage.
    auto &fixedTI = cast<FixedTypeInfo>(ti);
    storageType = fixedTI.getStorageType();
    fixedSize = fixedTI.getFixedSize();
    fixedAlignment = fixedTI.getFixedAlignment();
  } else {
    // Allocate a fixed-size buffer and possibly heap-allocate a payload at
    // runtime if the runtime size of the type does not fit in the buffer.
    inFixedBuffer = true;
    storageType = getFixedBufferTy();
    fixedSize = Size(DataLayout.getTypeAllocSize(storageType));
    fixedAlignment = Alignment(DataLayout.getABITypeAlignment(storageType));
  }

  // Check whether we've created the global variable already.
  // FIXME: We should integrate this into the LinkEntity cache more cleanly.
  auto gvar = Module.getGlobalVariable(var->getName(), /*allowInternal*/ true);
  if (gvar) {
    if (forDefinition)
      updateLinkageForDefinition(*this, gvar, entity);
  } else {
    LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
    llvm::Type *storageTypeWithContainer = storageType;
    if (var->isInitializedObject()) {
      // A statically initialized object must be placed into a container struct
      // because the swift_initStaticObject needs a swift_once_t at offset -1:
      //     struct Container {
      //       swift_once_t token[fixedAlignment / sizeof(swift_once_t)];
      //       HeapObject object;
      //     };
      std::string typeName = storageType->getStructName().str() + 'c';
      assert(fixedAlignment >= getPointerAlignment());
      unsigned numTokens = fixedAlignment.getValue() /
        getPointerAlignment().getValue();
      storageTypeWithContainer = llvm::StructType::create(getLLVMContext(),
              {llvm::ArrayType::get(OnceTy, numTokens), storageType}, typeName);
      gvar = createVariable(*this, link, storageTypeWithContainer,
                            fixedAlignment);
    } else {
      StringRef name;
      Optional<SILLocation> loc;
      if (var->getDecl()) {
        // Use the VarDecl for more accurate debugging information.
        loc = var->getDecl();
        name = var->getDecl()->getName().str();
      } else {
        if (var->hasLocation())
          loc = var->getLocation();
        name = var->getName();
      }
      auto DbgTy = DebugTypeInfo::getGlobal(var, storageTypeWithContainer,
                                            fixedSize, fixedAlignment);
      gvar = createVariable(*this, link, storageTypeWithContainer,
                            fixedAlignment, DbgTy, loc, name, inFixedBuffer);
    }
    /// Add a zero initializer.
    if (forDefinition)
      gvar->setInitializer(llvm::Constant::getNullValue(storageTypeWithContainer));
    else
      gvar->setComdat(nullptr);
  }
  llvm::Constant *addr = gvar;
  if (var->isInitializedObject()) {
    // Project out the object from the container.
    llvm::Constant *Indices[2] = {
      llvm::ConstantExpr::getIntegerValue(Int32Ty, APInt(32, 0)),
      llvm::ConstantExpr::getIntegerValue(Int32Ty, APInt(32, 1))
    };
    // Return the address of the initialized object itself (and not the address
    // to a reference to it).
    addr = llvm::ConstantExpr::getGetElementPtr(nullptr, gvar, Indices);
  }
  addr = llvm::ConstantExpr::getBitCast(
      addr,
      castStorageToType ? castStorageToType : storageType->getPointerTo());
  return Address(addr, Alignment(gvar->getAlignment()));
}

/// Return True if the function \p f is a 'readonly' function. Checking
/// for the SIL @_effects(readonly) attribute is not enough because this
/// definition does not match the definition of the LLVM readonly function
/// attribute. In this function we do the actual check.
static bool isReadOnlyFunction(SILFunction *f) {
  // Check if the function has any 'owned' parameters. Owned parameters may
  // call the destructor of the object which could violate the readonly-ness
  // of the function.
  if (f->hasOwnedParameters() || f->hasIndirectFormalResults())
    return false;

  auto Eff = f->getEffectsKind();

  // Swift's readonly does not automatically match LLVM's readonly.
  // Swift SIL optimizer relies on @_effects(readonly) to remove e.g.
  // dead code remaining from initializers of strings or dictionaries
  // of variables that are not used. But those initializers are often
  // not really readonly in terms of LLVM IR. For example, the
  // Dictionary.init() is marked as @_effects(readonly) in Swift, but
  // it does invoke reference-counting operations.
  if (Eff == EffectsKind::ReadOnly || Eff == EffectsKind::ReadNone) {
    // TODO: Analyze the body of function f and return true if it is
    // really readonly.
    return false;
  }

  return false;
}

static clang::GlobalDecl getClangGlobalDeclForFunction(const clang::Decl *decl) {
  if (auto ctor = dyn_cast<clang::CXXConstructorDecl>(decl))
    return clang::GlobalDecl(ctor, clang::Ctor_Complete);
  if (auto dtor = dyn_cast<clang::CXXDestructorDecl>(decl))
    return clang::GlobalDecl(dtor, clang::Dtor_Complete);
  return clang::GlobalDecl(cast<clang::FunctionDecl>(decl));
}

static void addLLVMFunctionAttributes(SILFunction *f, Signature &signature) {
  auto &attrs = signature.getMutableAttributes();
  switch (f->getInlineStrategy()) {
  case NoInline:
    attrs = attrs.addAttribute(signature.getType()->getContext(),
                               llvm::AttributeList::FunctionIndex,
                               llvm::Attribute::NoInline);
    break;
  case AlwaysInline:
    // FIXME: We do not currently transfer AlwaysInline since doing so results
    // in test failures, which must be investigated first.
  case InlineDefault:
    break;
  }

  if (isReadOnlyFunction(f)) {
    attrs = attrs.addAttribute(signature.getType()->getContext(),
                               llvm::AttributeList::FunctionIndex,
                               llvm::Attribute::ReadOnly);
  }
}

/// Create a key entry for a dynamic function replacement. A key entry refers to
/// the link entry for the dynamic replaceable function.
/// struct KeyEntry {
///   RelativeDirectPointer<LinkEntry> linkEntry;
///   int32_t flags;
/// }
static llvm::GlobalVariable *createGlobalForDynamicReplacementFunctionKey(
    IRGenModule &IGM, SILFunction *SILFn, llvm::GlobalVariable *linkEntry) {
  LinkEntity keyEntity =
      LinkEntity::forDynamicallyReplaceableFunctionKey(SILFn);
  auto key = IGM.getGlobalForDynamicallyReplaceableThunk(
      keyEntity, IGM.DynamicReplacementKeyTy, ForDefinition);

  ConstantInitBuilder builder(IGM);
  auto B = builder.beginStruct(IGM.DynamicReplacementKeyTy);
  B.addRelativeAddress(linkEntry);
  B.addInt32(0);
  B.finishAndSetAsInitializer(key);
  key->setConstant(true);
  IGM.setTrueConstGlobal(key);
  return key;
}

/// Emit the thunk that dispatches to the dynamically replaceable function.
static void emitDynamicallyReplaceableThunk(IRGenModule &IGM,
                                            SILFunction *SILFn,
                                            llvm::Function *dispatchFn,
                                            llvm::Function *implFn,
                                            Signature &signature) {

  // Create and initialize the first link entry for the chain of replacements.
  // The first implementation is initialized with 'implFn'.
  auto linkEntry = getChainEntryForDynamicReplacement(IGM, SILFn, implFn);

  // Create the key data structure. This is used from other modules to refer to
  // the chain of replacements.
  createGlobalForDynamicReplacementFunctionKey(IGM, SILFn, linkEntry);

  // We should never inline the implementation function.
  implFn->addFnAttr(llvm::Attribute::NoInline);

  // Load the function and dispatch to it forwarding our arguments.
  llvm::BasicBlock *entryBB =
      llvm::BasicBlock::Create(IGM.getLLVMContext(), "entry", dispatchFn);
  IRBuilder B(IGM.getLLVMContext(), false);
  B.SetInsertPoint(entryBB);
  if (IGM.DebugInfo)
    IGM.DebugInfo->emitArtificialFunction(B, dispatchFn);
  llvm::Constant *indices[] = {llvm::ConstantInt::get(IGM.Int32Ty, 0),
                               llvm::ConstantInt::get(IGM.Int32Ty, 0)};
  auto *fnPtr = B.CreateLoad(
      llvm::ConstantExpr::getInBoundsGetElementPtr(nullptr, linkEntry, indices),
      IGM.getPointerAlignment());
  auto *typeFnPtr = B.CreateBitOrPointerCast(fnPtr, implFn->getType());
  SmallVector<llvm::Value *, 16> forwardedArgs;
  for (auto &arg : dispatchFn->args())
    forwardedArgs.push_back(&arg);
  auto *Res =
      B.CreateCall(FunctionPointer(typeFnPtr, signature), forwardedArgs);
  Res->setTailCall();
  if (implFn->getReturnType()->isVoidTy())
    B.CreateRetVoid();
  else
    B.CreateRet(Res);
}

/// Calls the previous implementation before this dynamic replacement became
/// active.
void IRGenModule::emitDynamicReplacementOriginalFunctionThunk(SILFunction *f) {
  assert(f->getDynamicallyReplacedFunction());

  auto entity = LinkEntity::forSILFunction(f, true);

  Signature signature = getSignature(f->getLoweredFunctionType());
  addLLVMFunctionAttributes(f, signature);

  LinkInfo implLink = LinkInfo::get(*this, entity, ForDefinition);
  auto implFn =
      createFunction(*this, implLink, signature, nullptr /*insertBefore*/,
                     f->getOptimizationMode());
  implFn->addFnAttr(llvm::Attribute::NoInline);

  auto linkEntry =
      getChainEntryForDynamicReplacement(*this, f, nullptr, NotForDefinition);

  // Load the function and dispatch to it forwarding our arguments.
  llvm::BasicBlock *entryBB =
      llvm::BasicBlock::Create(getLLVMContext(), "entry", implFn);
  IRBuilder B(getLLVMContext(), false);
  B.SetInsertPoint(entryBB);
  llvm::Constant *indices[] = {llvm::ConstantInt::get(Int32Ty, 0),
                               llvm::ConstantInt::get(Int32Ty, 0)};

  auto *fnPtr = B.CreateLoad(
      llvm::ConstantExpr::getInBoundsGetElementPtr(nullptr, linkEntry, indices),
      getPointerAlignment());
  auto *typeFnPtr = B.CreateBitOrPointerCast(fnPtr, implFn->getType());

  SmallVector<llvm::Value *, 16> forwardedArgs;
  for (auto &arg : implFn->args())
    forwardedArgs.push_back(&arg);
  auto *Res =
      B.CreateCall(FunctionPointer(typeFnPtr, signature), forwardedArgs);

  if (implFn->getReturnType()->isVoidTy())
    B.CreateRetVoid();
  else
    B.CreateRet(Res);
}

/// Find the entry point for a SIL function.
llvm::Function *IRGenModule::getAddrOfSILFunction(
    SILFunction *f, ForDefinition_t forDefinition,
    bool isDynamicallyReplaceableImplementation,
    bool shouldCallPreviousImplementation) {
  assert(forDefinition || !isDynamicallyReplaceableImplementation);
  assert(!forDefinition || !shouldCallPreviousImplementation);

  LinkEntity entity =
      LinkEntity::forSILFunction(f, shouldCallPreviousImplementation);

  // Check whether we've created the function already.
  // FIXME: We should integrate this into the LinkEntity cache more cleanly.
  llvm::Function *fn = Module.getFunction(entity.mangleAsString());
  if (fn) {
    if (forDefinition) {
      updateLinkageForDefinition(*this, fn, entity);
      if (isDynamicallyReplaceableImplementation) {
        // Create the dynamically replacement thunk.
        LinkEntity implEntity = LinkEntity::forSILFunction(f, true);
        auto existingImpl = Module.getFunction(implEntity.mangleAsString());
        assert(!existingImpl);
        (void) existingImpl;
        Signature signature = getSignature(f->getLoweredFunctionType());
        addLLVMFunctionAttributes(f, signature);
        LinkInfo implLink = LinkInfo::get(*this, implEntity, forDefinition);
        auto implFn = createFunction(*this, implLink, signature, fn,
                                     f->getOptimizationMode());
        emitDynamicallyReplaceableThunk(*this, f, fn, implFn, signature);
        return implFn;
      }
    }
    return fn;
  }

  // If it's a Clang declaration, ask Clang to generate the IR declaration.
  // This might generate new functions, so we should do it before computing
  // the insert-before point.
  llvm::Constant *clangAddr = nullptr;
  if (auto clangDecl = f->getClangDecl()) {
    auto globalDecl = getClangGlobalDeclForFunction(clangDecl);
    clangAddr = getAddrOfClangGlobalDecl(globalDecl, forDefinition);
  }

  bool isDefinition = f->isDefinition();
  bool hasOrderNumber =
      isDefinition && !shouldCallPreviousImplementation;
  unsigned orderNumber = ~0U;
  llvm::Function *insertBefore = nullptr;

  // If the SIL function has a definition, we should have an order
  // number for it; make sure to insert it in that position relative
  // to other ordered functions.
  if (hasOrderNumber) {
    orderNumber = IRGen.getFunctionOrder(f);
    if (auto emittedFunctionIterator
          = EmittedFunctionsByOrder.findLeastUpperBound(orderNumber))
      insertBefore = *emittedFunctionIterator;
  }

  // If it's a Clang declaration, check whether Clang gave us a declaration.
  if (clangAddr) {
    fn = dyn_cast<llvm::Function>(clangAddr->stripPointerCasts());

    // If we have a function, move it to the appropriate position.
    if (fn) {
      if (hasOrderNumber) {
        auto &fnList = Module.getFunctionList();
        fnList.remove(fn);
        fnList.insert(llvm::Module::iterator(insertBefore), fn);

        EmittedFunctionsByOrder.insert(orderNumber, fn);
      }
      return fn;
    }

  // Otherwise, if we have a lazy definition for it, be sure to queue that up.
  } else if (isDefinition && !forDefinition && !f->isPossiblyUsedExternally() &&
             !hasCodeCoverageInstrumentation(*f, getSILModule())) {
    IRGen.addLazyFunction(f);
  }

  Signature signature = getSignature(f->getLoweredFunctionType());
  addLLVMFunctionAttributes(f, signature);

  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);

  fn = createFunction(*this, link, signature, insertBefore,
                      f->getOptimizationMode());

  // If `hasCReferences` is true, then the function is either marked with
  // @_silgen_name OR @_cdecl.  If it is the latter, it must have a definition
  // associated with it.  The combination of the two allows us to identify the
  // @_silgen_name functions.  These are locally defined function thunks used in
  // the standard library.  Do not give them DLLImport DLL Storage.
  if (!forDefinition) {
    fn->setComdat(nullptr);
    if (f->hasCReferences())
      fn->setDLLStorageClass(llvm::GlobalValue::DefaultStorageClass);
  }

  // If we have an order number for this function, set it up as appropriate.
  if (hasOrderNumber) {
    EmittedFunctionsByOrder.insert(orderNumber, fn);
  }

  if (isDynamicallyReplaceableImplementation && forDefinition) {
    LinkEntity implEntity = LinkEntity::forSILFunction(f, true);
    LinkInfo implLink = LinkInfo::get(*this, implEntity, forDefinition);
    auto implFn = createFunction(*this, implLink, signature, insertBefore,
                                 f->getOptimizationMode());

    emitDynamicallyReplaceableThunk(*this, f, fn, implFn, signature);
    return implFn;
  }
  return fn;
}

static llvm::GlobalVariable *createGOTEquivalent(IRGenModule &IGM,
                                                 llvm::Constant *global,
                                                 LinkEntity entity) {
  // Determine the name of this entity.
  llvm::SmallString<64> globalName;
  entity.mangle(globalName);

  if (IGM.Triple.getObjectFormat() == llvm::Triple::COFF) {
    if (cast<llvm::GlobalValue>(global)->hasDLLImportStorageClass()) {
      llvm::GlobalVariable *GV =
          new llvm::GlobalVariable(IGM.Module, global->getType(),
                                   /*Constant=*/true,
                                   llvm::GlobalValue::ExternalLinkage,
                                   nullptr, llvm::Twine("__imp_") + globalName);
      GV->setExternallyInitialized(true);
      return GV;
    }
  }

  auto gotEquivalent = new llvm::GlobalVariable(IGM.Module,
                                      global->getType(),
                                      /*constant*/ true,
                                      llvm::GlobalValue::PrivateLinkage,
                                      global,
                                      llvm::Twine("got.") + globalName);
  gotEquivalent->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
  return gotEquivalent;
}

llvm::Constant *IRGenModule::getOrCreateGOTEquivalent(llvm::Constant *global,
                                                      LinkEntity entity) {
  auto &gotEntry = GlobalGOTEquivalents[entity];
  if (gotEntry) {
    return gotEntry;
  }

  // Use the global as the initializer for an anonymous constant. LLVM can treat
  // this as equivalent to the global's GOT entry.
  auto gotEquivalent = createGOTEquivalent(*this, global, entity);
  gotEntry = gotEquivalent;
  return gotEquivalent;
}

static llvm::Constant *getElementBitCast(llvm::Constant *ptr,
                                         llvm::Type *newEltType) {
  auto ptrType = cast<llvm::PointerType>(ptr->getType());
  if (ptrType->getElementType() == newEltType) {
    return ptr;
  } else {
    auto newPtrType = newEltType->getPointerTo(ptrType->getAddressSpace());
    return llvm::ConstantExpr::getBitCast(ptr, newPtrType);
  }
}

/// Return a reference to an object that's suitable for being used for
/// the given kind of reference.
///
/// Note that, if the requested reference kind is a relative reference.
/// the returned constant will not actually be a relative reference.
/// To form the actual relative reference, you must pass the returned
/// result to emitRelativeReference, passing the correct base-address
/// information.
ConstantReference
IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
                                   ConstantInit definition,
                                   DebugTypeInfo debugType,
                                   SymbolReferenceKind refKind,
                                   llvm::Type *overrideDeclType) {
  switch (refKind) {
  case SymbolReferenceKind::Relative_Direct:
  case SymbolReferenceKind::Far_Relative_Direct:
    assert(!definition);
    // FIXME: don't just fall through; force the creation of a weak
    // definition so that we can emit a relative reference.
    LLVM_FALLTHROUGH;

  case SymbolReferenceKind::Absolute:
    return { getAddrOfLLVMVariable(entity, definition, debugType,
                                   overrideDeclType),
             ConstantReference::Direct };


  case SymbolReferenceKind::Relative_Indirectable:
  case SymbolReferenceKind::Far_Relative_Indirectable:
    assert(!definition);
    return getAddrOfLLVMVariableOrGOTEquivalent(entity);
  }
  llvm_unreachable("bad reference kind");
}

/// A convenient wrapper around getAddrOfLLVMVariable which uses the
/// default type as the definition type.
llvm::Constant *
IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
                                   ForDefinition_t forDefinition,
                                   DebugTypeInfo debugType) {
  auto definition = forDefinition
      ? ConstantInit::getDelayed(entity.getDefaultDeclarationType(*this))
      : ConstantInit();
  return getAddrOfLLVMVariable(entity, definition, debugType);
}

/// Get or create an llvm::GlobalVariable.
///
/// If a definition type is given, the result will always be an
/// llvm::GlobalVariable of that type.  Otherwise, the result will
/// have type pointerToDefaultType and may involve bitcasts.
llvm::Constant *
IRGenModule::getAddrOfLLVMVariable(LinkEntity entity,
                                   ConstantInit definition,
                                   DebugTypeInfo DbgTy,
                                   llvm::Type *overrideDeclType) {
  // This function assumes that 'globals' only contains GlobalValue
  // values for the entities that it will look up.

  llvm::Type *definitionType = (definition ? definition.getType() : nullptr);
  auto defaultType = overrideDeclType
    ? overrideDeclType
    : entity.getDefaultDeclarationType(*this);
  
  auto &entry = GlobalVars[entity];
  if (entry) {
    auto existing = cast<llvm::GlobalValue>(entry);

    // If we're looking to define something, we may need to replace a
    // forward declaration.
    if (definitionType) {
      assert(existing->isDeclaration() && "already defined");
      updateLinkageForDefinition(*this, existing, entity);

      // If the existing entry is a variable of the right type,
      // set the initializer on it and return.
      if (auto var = dyn_cast<llvm::GlobalVariable>(existing)) {
        if (definitionType == var->getValueType()) {
          if (definition.hasInit())
            definition.getInit().installInGlobal(var);
          return var;
        }
      }

      // Fall out to the case below, clearing the name so that
      // createVariable doesn't detect a collision.
      entry->setName("");

    // Otherwise, we have a previous declaration or definition which
    // we need to ensure has the right type.
    } else {
      return getElementBitCast(entry, defaultType);
    }
  }

  ForDefinition_t forDefinition = (ForDefinition_t) (definitionType != nullptr);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);

  // Clang may have defined the variable already.
  if (auto existing = Module.getNamedGlobal(link.getName()))
    return getElementBitCast(existing, defaultType);

  // If we're not defining the object now, forward declare it with the default
  // type.
  if (!definitionType) definitionType = defaultType;

  // Create the variable.
  auto var = createVariable(*this, link, definitionType,
                            entity.getAlignment(*this), DbgTy);

  // Install the concrete definition if we have one.
  if (definition && definition.hasInit()) {
    definition.getInit().installInGlobal(var);
  }

  // If we have an existing entry, destroy it, replacing it with the
  // new variable.
  if (entry) {
    auto existing = cast<llvm::GlobalValue>(entry);
    auto castVar = llvm::ConstantExpr::getBitCast(var, entry->getType());
    existing->replaceAllUsesWith(castVar);
    existing->eraseFromParent();
  }

  // If there's also an existing GOT-equivalent entry, rewrite it too, since
  // LLVM won't recognize a global with bitcasts in its initializers as GOT-
  // equivalent. rdar://problem/22388190
  auto foundGOTEntry = GlobalGOTEquivalents.find(entity);
  if (foundGOTEntry != GlobalGOTEquivalents.end() && foundGOTEntry->second) {
    auto existingGOTEquiv = cast<llvm::GlobalVariable>(foundGOTEntry->second);

    // Make a new GOT equivalent referring to the new variable with its
    // definition type.
    auto newGOTEquiv = createGOTEquivalent(*this, var, entity);
    auto castGOTEquiv = llvm::ConstantExpr::getBitCast(newGOTEquiv,
                                                   existingGOTEquiv->getType());
    existingGOTEquiv->replaceAllUsesWith(castGOTEquiv);
    existingGOTEquiv->eraseFromParent();
    GlobalGOTEquivalents[entity] = newGOTEquiv;
  }

  // Cache and return.
  entry = var;
  return var;
}

/// Get or create a "GOT equivalent" llvm::GlobalVariable, if applicable.
///
/// Creates a private, unnamed constant containing the address of another
/// global variable. LLVM can replace relative references to this variable with
/// relative references to the GOT entry for the variable in the object file.
ConstantReference
IRGenModule::getAddrOfLLVMVariableOrGOTEquivalent(LinkEntity entity,
                              ConstantReference::Directness forceIndirectness) {
  // Handle SILFunctions specially, because unlike other entities they aren't
  // variables and aren't kept in the GlobalVars table.
  if (entity.isSILFunction()) {
    auto *silFn = entity.getSILFunction();
    auto fn = getAddrOfSILFunction(silFn, NotForDefinition);
    if (silFn->isDefinition() &&
        !isAvailableExternally(silFn->getLinkage()) &&
        this == IRGen.getGenModule(silFn)) {
      return {fn, ConstantReference::Direct};
    }
    
    auto gotEquivalent = getOrCreateGOTEquivalent(fn, entity);
    return {gotEquivalent, ConstantReference::Indirect};
  }
  
  // ObjC class references can always be directly referenced, even in
  // the weird cases where we don't see a definition.
  if (entity.isObjCClassRef()) {
    auto value = getAddrOfObjCClassRef(
      const_cast<ClassDecl *>(cast<ClassDecl>(entity.getDecl())));
    return { cast<llvm::Constant>(value.getAddress()),
             ConstantReference::Direct };
  }
  
  // Ensure the variable is at least forward-declared.
  if (entity.isForeignTypeMetadataCandidate()) {
    auto foreignCandidate
      = getAddrOfForeignTypeMetadataCandidate(entity.getType());
    (void)foreignCandidate;
  } else {
    getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
  }

  // Guess whether a global entry is a definition from this TU. This isn't
  // bulletproof, but at the point we emit conformance tables, we're far enough
  // along that we should have emitted any metadata objects we were going to.
  auto isDefinition = [&](llvm::Constant *global) -> bool {
    // We only emit aliases for definitions. (An extern alias would be an
    // extern global.)
    if (isa<llvm::GlobalAlias>(global))
      return true;
    // Global vars are definitions if they have an initializer.
    if (auto var = dyn_cast<llvm::GlobalVariable>(global))
      return var->hasInitializer();
    // Assume anything else isn't a definition.
    return false;
  };
  
  //
  auto entry = GlobalVars[entity];
  
  /// Returns a direct reference.
  auto direct = [&]() -> ConstantReference {
    // FIXME: Relative references to aliases break MC on 32-bit Mach-O
    // platforms (rdar://problem/22450593 ), so substitute an alias with its
    // aliasee to work around that.
    if (auto alias = dyn_cast<llvm::GlobalAlias>(entry))
      return {alias->getAliasee(), ConstantReference::Direct};
    return {entry, ConstantReference::Direct};
  };
  
  /// Returns an indirect reference.
  auto indirect = [&]() -> ConstantReference {
    auto gotEquivalent = getOrCreateGOTEquivalent(
      cast<llvm::GlobalValue>(entry), entity);
    return {gotEquivalent, ConstantReference::Indirect};
  };
  
  // Return the GOT entry if we were asked to.
  if (forceIndirectness == ConstantReference::Indirect)
    return indirect();
  
  // The integrated REPL incrementally adds new definitions, so always use
  // indirect references in this mode.
  if (IRGen.Opts.IntegratedREPL)
    return indirect();
  
  // If the variable has already been defined in this TU,
  // then it definitely doesn't need a GOT entry, and we can
  // relative-reference it directly.
  if ((!entity.isAvailableExternally(*this) || isDefinition(entry))) {
    return direct();
  }

  // If the entity will be emitted as part of the current source file
  // (if we know what that is), then we can reference it directly.
  if (CurSourceFile
      && !isa<ClangModuleUnit>(CurSourceFile)
      && CurSourceFile == entity.getSourceFileForEmission())
    return direct();
  
  // TODO: If we know the target entry is going to be linked into the same
  // binary, then we ought to be able to directly relative-reference the
  // symbol. However, some platforms don't have the necessary relocations to
  // represent a relative reference to an undefined symbol, so conservatively
  // produce an indirect reference in this case.

  // Fall back to an indirect reference if we can't establish that a direct
  // reference is OK.
  return indirect();
}

static TypeEntityReference
getContextDescriptorEntityReference(IRGenModule &IGM, const LinkEntity &entity){
  // TODO: consider using a symbolic reference (i.e. a symbol string
  // to be looked up dynamically) for types defined outside the module.
  auto ref = IGM.getAddrOfLLVMVariableOrGOTEquivalent(entity);
  auto kind = ref.isIndirect()
                ? TypeReferenceKind::IndirectTypeDescriptor
                : TypeReferenceKind::DirectTypeDescriptor;
  return TypeEntityReference(kind, ref.getValue());
}

static TypeEntityReference
getTypeContextDescriptorEntityReference(IRGenModule &IGM,
                                        NominalTypeDecl *decl) {
  auto entity = LinkEntity::forNominalTypeDescriptor(decl);
  IGM.IRGen.noteUseOfTypeContextDescriptor(decl, DontRequireMetadata);
  return getContextDescriptorEntityReference(IGM, entity);
}

static TypeEntityReference
getProtocolDescriptorEntityReference(IRGenModule &IGM, ProtocolDecl *protocol) {
  assert(!protocol->isObjC() &&
         "objc protocols don't have swift protocol descriptors");
  auto entity = LinkEntity::forProtocolDescriptor(protocol);
  return getContextDescriptorEntityReference(IGM, entity);
}

static TypeEntityReference
getObjCClassByNameReference(IRGenModule &IGM, ClassDecl *cls) {
  auto kind = TypeReferenceKind::DirectObjCClassName;
  SmallString<64> objcRuntimeNameBuffer;
  auto ref = IGM.getAddrOfGlobalString(
                                 cls->getObjCRuntimeName(objcRuntimeNameBuffer),
                                 /*willByRelativelyAddressed=*/true);

  return TypeEntityReference(kind, ref);
}

TypeEntityReference
IRGenModule::getTypeEntityReference(NominalTypeDecl *decl) {
  if (auto protocol = dyn_cast<ProtocolDecl>(decl)) {
    assert(!protocol->isObjC() && "imported protocols not handled here");
    return getProtocolDescriptorEntityReference(*this, protocol);
  }

  auto clas = dyn_cast<ClassDecl>(decl);
  if (!clas) {
    return getTypeContextDescriptorEntityReference(*this, decl);
  }

  switch (clas->getForeignClassKind()) {
  case ClassDecl::ForeignKind::RuntimeOnly:
    return getObjCClassByNameReference(*this, clas);

  case ClassDecl::ForeignKind::CFType:
    return getTypeContextDescriptorEntityReference(*this, clas);

  case ClassDecl::ForeignKind::Normal:
    if (hasKnownSwiftMetadata(*this, clas)) {
      return getTypeContextDescriptorEntityReference(*this, clas);
    }

    // Note: we would like to use an Objective-C class reference, but the
    // Darwin linker currently has a bug where it will coalesce these symbols
    // *after* computing a relative offset, causing incorrect relative
    // offsets in the metadata. Therefore, reference Objective-C classes by
    // their runtime names.
    return getObjCClassByNameReference(*this, clas);
  }
  llvm_unreachable("bad foreign type kind");
}

/// Form an LLVM constant for the relative distance between a reference
/// (appearing at gep (0, indices) of `base`) and `target`.
llvm::Constant *
IRGenModule::emitRelativeReference(ConstantReference target,
                                   llvm::Constant *base,
                                   ArrayRef<unsigned> baseIndices) {
  llvm::Constant *relativeAddr =
    emitDirectRelativeReference(target.getValue(), base, baseIndices);

  // If the reference is indirect, flag it by setting the low bit.
  // (All of the base, direct target, and GOT entry need to be pointer-aligned
  // for this to be OK.)
  if (target.isIndirect()) {
    relativeAddr = llvm::ConstantExpr::getAdd(relativeAddr,
                             llvm::ConstantInt::get(RelativeAddressTy, 1));
  }

  return relativeAddr;
}

/// Form an LLVM constant for the relative distance between a reference
/// (appearing at gep (0, indices...) of `base`) and `target`.  For now,
/// for this to succeed portably, both need to be globals defined in the
/// current translation unit.
llvm::Constant *
IRGenModule::emitDirectRelativeReference(llvm::Constant *target,
                                         llvm::Constant *base,
                                         ArrayRef<unsigned> baseIndices) {
  // Convert the target to an integer.
  auto targetAddr = llvm::ConstantExpr::getPtrToInt(target, SizeTy);

  SmallVector<llvm::Constant*, 4> indices;
  indices.push_back(llvm::ConstantInt::get(Int32Ty, 0));
  for (unsigned baseIndex : baseIndices) {
    indices.push_back(llvm::ConstantInt::get(Int32Ty, baseIndex));
  };

  // Drill down to the appropriate address in the base, then convert
  // that to an integer.
  auto baseElt = llvm::ConstantExpr::getInBoundsGetElementPtr(
                       base->getType()->getPointerElementType(), base, indices);
  auto baseAddr = llvm::ConstantExpr::getPtrToInt(baseElt, SizeTy);

  // The relative address is the difference between those.
  auto relativeAddr = llvm::ConstantExpr::getSub(targetAddr, baseAddr);

  // Relative addresses can be 32-bit even on 64-bit platforms.
  if (SizeTy != RelativeAddressTy)
    relativeAddr = llvm::ConstantExpr::getTrunc(relativeAddr,
                                                RelativeAddressTy);

  return relativeAddr;
}

/// Emit the protocol descriptors list and return it.
llvm::Constant *IRGenModule::emitSwiftProtocols() {
  if (SwiftProtocols.empty())
    return nullptr;

  // Define the global variable for the protocol list.
  ConstantInitBuilder builder(*this);
  auto recordsArray = builder.beginArray(ProtocolRecordTy);

  for (auto *protocol : SwiftProtocols) {
    auto record = recordsArray.beginStruct(ProtocolRecordTy);

    // Relative reference to the protocol descriptor.
    auto descriptorRef = getAddrOfLLVMVariableOrGOTEquivalent(
                                   LinkEntity::forProtocolDescriptor(protocol));
    record.addRelativeAddress(descriptorRef);

    record.finishAndAddTo(recordsArray);
  }

  // FIXME: This needs to be a linker-local symbol in order for Darwin ld to
  // resolve relocations relative to it.

  auto var = recordsArray.finishAndCreateGlobal(
                                            "\x01l_protocols",
                                            Alignment(4),
                                            /*isConstant*/ true,
                                            llvm::GlobalValue::PrivateLinkage);

  StringRef sectionName;
  switch (TargetInfo.OutputObjectFormat) {
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("Don't know how to emit protocols for "
                     "the selected object format.");
  case llvm::Triple::MachO:
    sectionName = "__TEXT, __swift5_protos, regular, no_dead_strip";
    break;
  case llvm::Triple::ELF:
  case llvm::Triple::Wasm:
    sectionName = "swift5_protocols";
    break;
  case llvm::Triple::COFF:
    sectionName = ".sw5prt$B";
    break;
  }

  var->setSection(sectionName);
  
  disableAddressSanitizer(*this, var);
  
  addUsedGlobal(var);
  return var;
}

void IRGenModule::addProtocolConformance(ConformanceDescription &&record) {
  // Add this protocol conformance.
  ProtocolConformances.push_back(std::move(record));
}

/// Emit the protocol conformance list and return it.
llvm::Constant *IRGenModule::emitProtocolConformances() {
  if (ProtocolConformances.empty())
    return nullptr;

  // Emit the conformances.
  for (const auto &record : ProtocolConformances)
    emitProtocolConformance(record);

  // Define the global variable for the conformance list.
  ConstantInitBuilder builder(*this);
  auto descriptorArray = builder.beginArray(RelativeAddressTy);

  for (const auto &record : ProtocolConformances) {
    auto conformance = record.conformance;
    auto entity = LinkEntity::forProtocolConformanceDescriptor(conformance);
    auto descriptor =
      getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
    descriptorArray.addRelativeAddress(descriptor);
  }

  // FIXME: This needs to be a linker-local symbol in order for Darwin ld to
  // resolve relocations relative to it.

  auto var = descriptorArray.finishAndCreateGlobal(
                                          "\x01l_protocol_conformances",
                                          Alignment(4),
                                          /*isConstant*/ true,
                                          llvm::GlobalValue::PrivateLinkage);

  StringRef sectionName;
  switch (TargetInfo.OutputObjectFormat) {
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("Don't know how to emit protocol conformances for "
                     "the selected object format.");
  case llvm::Triple::MachO:
    sectionName = "__TEXT, __swift5_proto, regular, no_dead_strip";
    break;
  case llvm::Triple::ELF:
  case llvm::Triple::Wasm:
    sectionName = "swift5_protocol_conformances";
    break;
  case llvm::Triple::COFF:
    sectionName = ".sw5prtc$B";
    break;
  }

  var->setSection(sectionName);

  disableAddressSanitizer(*this, var);
  
  addUsedGlobal(var);
  return var;
}


/// Emit type metadata for types that might not have explicit protocol conformances.
llvm::Constant *IRGenModule::emitTypeMetadataRecords() {
  std::string sectionName;
  switch (TargetInfo.OutputObjectFormat) {
  case llvm::Triple::MachO:
    sectionName = "__TEXT, __swift5_types, regular, no_dead_strip";
    break;
  case llvm::Triple::ELF:
  case llvm::Triple::Wasm:
    sectionName = "swift5_type_metadata";
    break;
  case llvm::Triple::COFF:
    sectionName = ".sw5tymd$B";
    break;
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("Don't know how to emit type metadata table for "
                     "the selected object format.");
  }

  // Do nothing if the list is empty.
  if (RuntimeResolvableTypes.empty())
    return nullptr;

  // Define the global variable for the conformance list.
  // We have to do this before defining the initializer since the entries will
  // contain offsets relative to themselves.
  auto arrayTy = llvm::ArrayType::get(TypeMetadataRecordTy,
                                      RuntimeResolvableTypes.size());

  // FIXME: This needs to be a linker-local symbol in order for Darwin ld to
  // resolve relocations relative to it.
  auto var = new llvm::GlobalVariable(Module, arrayTy,
                                      /*isConstant*/ true,
                                      llvm::GlobalValue::PrivateLinkage,
                                      /*initializer*/ nullptr,
                                      "\x01l_type_metadata_table");

  SmallVector<llvm::Constant *, 8> elts;
  for (auto type : RuntimeResolvableTypes) {
    auto ref = getTypeEntityReference(type);

    // Form the relative address, with the type reference kind in the low bits.
    unsigned arrayIdx = elts.size();
    llvm::Constant *relativeAddr =
      emitDirectRelativeReference(ref.getValue(), var, { arrayIdx, 0 });
    unsigned lowBits = static_cast<unsigned>(ref.getKind());
    if (lowBits != 0) {
      relativeAddr = llvm::ConstantExpr::getAdd(relativeAddr,
                       llvm::ConstantInt::get(RelativeAddressTy, lowBits));
    }

    llvm::Constant *recordFields[] = { relativeAddr };
    auto record = llvm::ConstantStruct::get(TypeMetadataRecordTy,
                                            recordFields);
    elts.push_back(record);
  }

  auto initializer = llvm::ConstantArray::get(arrayTy, elts);

  var->setInitializer(initializer);
  var->setSection(sectionName);
  var->setAlignment(4);

  disableAddressSanitizer(*this, var);
  
  addUsedGlobal(var);
  return var;
}

llvm::Constant *IRGenModule::emitFieldDescriptors() {
  std::string sectionName;
  switch (TargetInfo.OutputObjectFormat) {
  case llvm::Triple::MachO:
    sectionName = "__TEXT, __swift5_fieldmd, regular, no_dead_strip";
    break;
  case llvm::Triple::ELF:
  case llvm::Triple::Wasm:
    sectionName = "swift5_fieldmd";
    break;
  case llvm::Triple::COFF:
    sectionName = ".sw5flmd$B";
    break;
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("Don't know how to emit field records table for "
                     "the selected object format.");
  }

  // Do nothing if the list is empty.
  if (FieldDescriptors.empty())
    return nullptr;

  // Define the global variable for the field record list.
  // We have to do this before defining the initializer since the entries will
  // contain offsets relative to themselves.
  auto arrayTy =
      llvm::ArrayType::get(FieldDescriptorPtrTy, FieldDescriptors.size());

  // FIXME: This needs to be a linker-local symbol in order for Darwin ld to
  // resolve relocations relative to it.
  auto var = new llvm::GlobalVariable(
      Module, arrayTy,
      /*isConstant*/ true, llvm::GlobalValue::PrivateLinkage,
      /*initializer*/ nullptr, "\x01l_type_metadata_table");

  SmallVector<llvm::Constant *, 8> elts;
  for (auto *descriptor : FieldDescriptors)
    elts.push_back(
        llvm::ConstantExpr::getBitCast(descriptor, FieldDescriptorPtrTy));

  var->setInitializer(llvm::ConstantArray::get(arrayTy, elts));
  var->setSection(sectionName);
  var->setAlignment(4);
  
  disableAddressSanitizer(*this, var);
  
  addUsedGlobal(var);
  return var;
}

/// Fetch a global reference to a reference to the given Objective-C class.
/// The result is of type ObjCClassPtrTy->getPointerTo().
Address IRGenModule::getAddrOfObjCClassRef(ClassDecl *theClass) {
  assert(ObjCInterop && "getting address of ObjC class ref in no-interop mode");

  LinkEntity entity = LinkEntity::forObjCClassRef(theClass);
  auto DbgTy = DebugTypeInfo::getObjCClass(
      theClass, ObjCClassPtrTy, getPointerSize(), getPointerAlignment());
  auto addr = getAddrOfLLVMVariable(entity, ConstantInit(), DbgTy);

  // Define it lazily.
  if (auto global = dyn_cast<llvm::GlobalVariable>(addr)) {
    if (global->isDeclaration()) {
      global->setSection(GetObjCSectionName("__objc_classrefs",
                                            "regular,no_dead_strip"));
      global->setLinkage(llvm::GlobalVariable::PrivateLinkage);
      global->setExternallyInitialized(true);
      global->setInitializer(getAddrOfObjCClass(theClass, NotForDefinition));
      addCompilerUsedGlobal(global);
    }
  }

  return Address(addr, entity.getAlignment(*this));
}

/// Fetch a global reference to the given Objective-C class.  The
/// result is of type ObjCClassPtrTy.
llvm::Constant *IRGenModule::getAddrOfObjCClass(ClassDecl *theClass,
                                                ForDefinition_t forDefinition) {
  assert(ObjCInterop && "getting address of ObjC class in no-interop mode");
  assert(!theClass->isForeign());
  LinkEntity entity = LinkEntity::forObjCClass(theClass);
  auto DbgTy = DebugTypeInfo::getObjCClass(
      theClass, ObjCClassPtrTy, getPointerSize(), getPointerAlignment());
  auto addr = getAddrOfLLVMVariable(entity, forDefinition, DbgTy);
  return addr;
}

/// Fetch the declaration of a metaclass object. The result is always a
/// GlobalValue of ObjCClassPtrTy, and is either the Objective-C metaclass or
/// the Swift metaclass stub, depending on whether the class is published as an
/// ObjC class.
llvm::Constant *
IRGenModule::getAddrOfMetaclassObject(ClassDecl *decl,
                                      ForDefinition_t forDefinition) {
  assert((!decl->isGenericContext() || decl->hasClangNode()) &&
         "generic classes do not have a static metaclass object");

  auto entity = decl->getMetaclassKind() == ClassDecl::MetaclassKind::ObjC
                    ? LinkEntity::forObjCMetaclass(decl)
                    : LinkEntity::forSwiftMetaclassStub(decl);

  auto DbgTy = DebugTypeInfo::getObjCClass(
      decl, ObjCClassPtrTy, getPointerSize(), getPointerAlignment());
  auto addr = getAddrOfLLVMVariable(entity, forDefinition, DbgTy);
  return addr;
}

/// Fetch the declaration of an Objective-C metadata update callback.
llvm::Function *
IRGenModule::getAddrOfObjCMetadataUpdateFunction(ClassDecl *classDecl,
                                                 ForDefinition_t forDefinition) {
  assert(ObjCInterop);

  LinkEntity entity = LinkEntity::forObjCMetadataUpdateFunction(classDecl);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  // Class _Nullable callback(Class _Nonnull cls, void * _Nullable arg);
  Signature signature(ObjCUpdateCallbackTy, llvm::AttributeList(), DefaultCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Fetch the declaration of an Objective-C resilient class stub.
llvm::Constant *
IRGenModule::getAddrOfObjCResilientClassStub(ClassDecl *classDecl,
                                             ForDefinition_t forDefinition,
                                             TypeMetadataAddress addr) {
  assert(ObjCInterop);
  assert(getClassMetadataStrategy(classDecl) ==
         ClassMetadataStrategy::Resilient);

  LinkEntity entity = LinkEntity::forObjCResilientClassStub(classDecl, addr);
  return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
}

/// Fetch the type metadata access function for a non-generic type.
llvm::Function *
IRGenModule::getAddrOfTypeMetadataAccessFunction(CanType type,
                                              ForDefinition_t forDefinition) {
  assert(!type->hasArchetype() && !type->hasTypeParameter());
  NominalTypeDecl *Nominal = type->getNominalOrBoundGenericNominal();
  IRGen.noteUseOfTypeMetadata(Nominal);

  LinkEntity entity = LinkEntity::forTypeMetadataAccessFunction(type);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  llvm::Type *params[] = { SizeTy }; // MetadataRequest
  auto fnType = llvm::FunctionType::get(TypeMetadataResponseTy, params, false);
  Signature signature(fnType, llvm::AttributeList(), SwiftCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Fetch the type metadata access function for the given generic type.
llvm::Function *
IRGenModule::getAddrOfGenericTypeMetadataAccessFunction(
                                           NominalTypeDecl *nominal,
                                           ArrayRef<llvm::Type *> genericArgs,
                                           ForDefinition_t forDefinition) {
  assert(nominal->isGenericContext());
  assert(!genericArgs.empty() ||
         nominal->getGenericSignature()->areAllParamsConcrete());
  IRGen.noteUseOfTypeMetadata(nominal);

  auto type = nominal->getDeclaredType()->getCanonicalType();
  assert(type->hasUnboundGenericType());
  LinkEntity entity = LinkEntity::forTypeMetadataAccessFunction(type);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  // If we have more arguments than can be passed directly, all of the
  // generic arguments are passed as an array.
  llvm::Type *paramTypesArray[NumDirectGenericTypeMetadataAccessFunctionArgs+1];

  paramTypesArray[0] = SizeTy; // MetadataRequest
  size_t numParams = 1;

  size_t numGenericArgs = genericArgs.size();
  if (numGenericArgs > NumDirectGenericTypeMetadataAccessFunctionArgs) {
    paramTypesArray[1] = Int8PtrPtrTy;
    numParams++;
  } else {
    for (size_t i : indices(genericArgs))
      paramTypesArray[i + 1] = genericArgs[i];
    numParams += numGenericArgs;
  }

  auto paramTypes = llvm::makeArrayRef(paramTypesArray, numParams);
  auto fnType = llvm::FunctionType::get(TypeMetadataResponseTy,
                                        paramTypes, false);
  Signature signature(fnType, llvm::AttributeList(), SwiftCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Get or create a type metadata cache variable.  These are an
/// implementation detail of type metadata access functions.
llvm::Constant *
IRGenModule::getAddrOfTypeMetadataLazyCacheVariable(CanType type,
                                              ForDefinition_t forDefinition) {
  assert(!type->hasArchetype() && !type->hasTypeParameter());
  LinkEntity entity = LinkEntity::forTypeMetadataLazyCacheVariable(type);
  auto variable =
    getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());

  // Zero-initialize if we're asking for a definition.
  if (forDefinition) {
    cast<llvm::GlobalVariable>(variable)->setInitializer(
      llvm::ConstantPointerNull::get(TypeMetadataPtrTy));
  }

  return variable;
}

llvm::Constant *
IRGenModule::getAddrOfTypeMetadataSingletonInitializationCache(
                                           NominalTypeDecl *D,
                                           ForDefinition_t forDefinition) {
  auto entity = LinkEntity::forTypeMetadataSingletonInitializationCache(D);
  auto variable =
    getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());

  // Zero-initialize if we're asking for a definition.
  if (forDefinition) {
    cast<llvm::GlobalVariable>(variable)->setInitializer(
      llvm::Constant::getNullValue(variable->getType()->getPointerElementType()));
  }

  return variable;
}

llvm::GlobalValue *IRGenModule::defineAlias(LinkEntity entity,
                                            llvm::Constant *definition) {
  // Check for an existing forward declaration of the alias.
  auto &entry = GlobalVars[entity];
  llvm::GlobalValue *existingVal = nullptr;
  if (entry) {
    existingVal = cast<llvm::GlobalValue>(entry);
    // Clear the existing value's name so we can steal it.
    existingVal->setName("");
  }

  LinkInfo link = LinkInfo::get(*this, entity, ForDefinition);
  auto *ptrTy = cast<llvm::PointerType>(definition->getType());
  auto *alias = llvm::GlobalAlias::create(
      ptrTy->getElementType(), ptrTy->getAddressSpace(), link.getLinkage(),
      link.getName(), definition, &Module);
  ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()})
      .to(alias);

  if (link.isUsed()) {
    addUsedGlobal(alias);
  }

  // Replace an existing external declaration for the address point.
  if (entry) {
    auto existingVal = cast<llvm::GlobalValue>(entry);

    // FIXME: MC breaks when emitting alias references on some platforms
    // (rdar://problem/22450593 ). Work around this by referring to the aliasee
    // instead.
    llvm::Constant *aliasCast = alias->getAliasee();
    aliasCast = llvm::ConstantExpr::getBitCast(aliasCast,
                                               entry->getType());
    existingVal->replaceAllUsesWith(aliasCast);
    existingVal->eraseFromParent();
  }
  entry = alias;

  return alias;
}

/// Define the metadata for a type.
///
/// Some type metadata has information before the address point that the
/// public symbol for the metadata references. This function will rewrite any
/// existing external declaration to the address point as an alias into the
/// full metadata object.
llvm::GlobalValue *IRGenModule::defineTypeMetadata(CanType concreteType,
                                                   bool isPattern,
                                                   bool isConstant,
                                                   ConstantInitFuture init,
                                                   llvm::StringRef section) {
  assert(init);

  if (isPattern) {
    assert(isConstant && "Type metadata patterns must be constant");
    auto addr = getAddrOfTypeMetadataPattern(concreteType->getAnyNominal(),
                                             init, section);

    return cast<llvm::GlobalValue>(addr);
  }

  /// For concrete metadata, we want to use the initializer on the
  /// "full metadata", and define the "direct" address point as an alias.
  TypeMetadataAddress addrKind;
  unsigned adjustmentIndex;

  if (concreteType->getClassOrBoundGenericClass()) {
    addrKind = TypeMetadataAddress::FullMetadata;
    adjustmentIndex = MetadataAdjustmentIndex::Class;
  } else {
    addrKind = TypeMetadataAddress::FullMetadata;
    adjustmentIndex = MetadataAdjustmentIndex::ValueType;
  }

  auto entity = LinkEntity::forTypeMetadata(concreteType, addrKind);

  auto DbgTy = DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
    entity.getDefaultDeclarationType(*this)->getPointerTo(),
    Size(0), Alignment(1));

  // Define the variable.
  llvm::GlobalVariable *var = cast<llvm::GlobalVariable>(
      getAddrOfLLVMVariable(entity, init, DbgTy));

  var->setConstant(isConstant);
  if (!section.empty())
    var->setSection(section);

  LinkInfo link = LinkInfo::get(*this, entity, ForDefinition);
  if (link.isUsed())
    addUsedGlobal(var);

  // Keep type metadata around for all types.
  if (auto nominal = concreteType->getAnyNominal())
    addRuntimeResolvableType(nominal);

  // For concrete metadata, declare the alias to its address point.
  auto directEntity = LinkEntity::forTypeMetadata(concreteType,
                                             TypeMetadataAddress::AddressPoint);

  llvm::Constant *addr = var;
  // Do an adjustment if necessary.
  if (adjustmentIndex) {
    llvm::Constant *indices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, adjustmentIndex)
    };
    addr = llvm::ConstantExpr::getInBoundsGetElementPtr(/*Ty=*/nullptr,
                                                        addr, indices);
  }
  addr = llvm::ConstantExpr::getBitCast(addr, TypeMetadataPtrTy);
  return defineAlias(directEntity, addr);
}

/// Fetch the declaration of the metadata (or metadata template) for a
/// type.
///
/// If the definition type is specified, the result will always be a
/// GlobalValue of the given type, which may not be at the
/// canonical address point for a type metadata.
///
/// If the definition type is not specified, then:
///   - if the metadata is indirect, then the result will not be adjusted
///     and it will have the type pointer-to-T, where T is the type
///     of a direct metadata;
///   - if the metadata is a pattern, then the result will not be
///     adjusted and it will have FullTypeMetadataPtrTy;
///   - otherwise it will be adjusted to the canonical address point
///     for a type metadata and it will have type TypeMetadataPtrTy.
llvm::Constant *IRGenModule::getAddrOfTypeMetadata(CanType concreteType) {
  return getAddrOfTypeMetadata(concreteType,
                               SymbolReferenceKind::Absolute).getDirectValue();
}

ConstantReference IRGenModule::getAddrOfTypeMetadata(CanType concreteType,
                                               SymbolReferenceKind refKind) {
  assert(!isa<UnboundGenericType>(concreteType));

  llvm::Type *defaultVarTy;
  unsigned adjustmentIndex;

  ClassDecl *ObjCClass = nullptr;
  
  // Objective-C classes use the ObjC class object.
  if (isa<ClassType>(concreteType) &&
      !hasKnownSwiftMetadata(*this, cast<ClassType>(concreteType)->getDecl())) {
    defaultVarTy = TypeMetadataStructTy;
    adjustmentIndex = 0;
    ObjCClass = cast<ClassType>(concreteType)->getDecl();
  // The symbol for other nominal type metadata is generated at the address
  // point.
  } else if (isa<ClassType>(concreteType) ||
             isa<BoundGenericClassType>(concreteType)) {
    assert(!concreteType->getClassOrBoundGenericClass()->isForeign()
           && "metadata for foreign classes should be emitted as "
              "foreign candidate");
    defaultVarTy = TypeMetadataStructTy;
    adjustmentIndex = 0;
  } else if (auto nom = concreteType->getAnyNominal()) {
    assert(!isa<ClangModuleUnit>(nom->getModuleScopeContext())
           && "metadata for foreign type should be emitted as "
              "foreign candidate");
    (void)nom;
    
    defaultVarTy = TypeMetadataStructTy;
    adjustmentIndex = 0;
  } else {
    // FIXME: Non-nominal metadata provided by the C++ runtime is exported
    // with the address of the start of the full metadata object, since
    // Clang doesn't provide an easy way to emit symbols aliasing into the
    // middle of an object.
    defaultVarTy = FullTypeMetadataStructTy;
    adjustmentIndex = MetadataAdjustmentIndex::ValueType;
  }

  // If this is a use, and the type metadata is emitted lazily,
  // trigger lazy emission of the metadata.
  if (NominalTypeDecl *nominal = concreteType->getAnyNominal()) {
    IRGen.noteUseOfTypeMetadata(nominal);
  }

  LinkEntity entity
    = ObjCClass ? LinkEntity::forObjCClass(ObjCClass)
                : LinkEntity::forTypeMetadata(concreteType,
                                     TypeMetadataAddress::AddressPoint);

  auto DbgTy =
      ObjCClass
          ? DebugTypeInfo::getObjCClass(ObjCClass, ObjCClassPtrTy,
                                        getPointerSize(), getPointerAlignment())
          : DebugTypeInfo::getMetadata(MetatypeType::get(concreteType),
                                       defaultVarTy->getPointerTo(), Size(0),
                                       Alignment(1));

  auto addr = getAddrOfLLVMVariable(entity, ConstantInit(), DbgTy, refKind,
                                    defaultVarTy);

  // FIXME: MC breaks when emitting alias references on some platforms
  // (rdar://problem/22450593 ). Work around this by referring to the aliasee
  // instead.
  if (auto alias = dyn_cast<llvm::GlobalAlias>(addr.getValue()))
    addr = ConstantReference(alias->getAliasee(), addr.isIndirect());

  // Adjust if necessary.
  if (adjustmentIndex) {
    llvm::Constant *indices[] = {
      llvm::ConstantInt::get(Int32Ty, 0),
      llvm::ConstantInt::get(Int32Ty, adjustmentIndex)
    };
    addr = ConstantReference(
             llvm::ConstantExpr::getInBoundsGetElementPtr(
                                    /*Ty=*/nullptr, addr.getValue(), indices),
                             addr.isIndirect());
  }
  
  return addr;
}

llvm::Constant *
IRGenModule::getAddrOfTypeMetadataPattern(NominalTypeDecl *D) {
  return getAddrOfTypeMetadataPattern(D, ConstantInit(), "");
}

llvm::Constant *
IRGenModule::getAddrOfTypeMetadataPattern(NominalTypeDecl *D,
                                          ConstantInit init,
                                          StringRef section) {
  if (!init)
    IRGen.noteUseOfTypeMetadata(D);

  LinkEntity entity = LinkEntity::forTypeMetadataPattern(D);
  auto addr = getAddrOfLLVMVariable(entity, init, DebugTypeInfo());

  if (init) {
    auto var = cast<llvm::GlobalVariable>(addr);
    var->setConstant(true);
    if (!section.empty())
      var->setSection(section);

    // Keep type metadata around for all types.
    addRuntimeResolvableType(D);
  }

  return addr;
}

/// Returns the address of a class metadata base offset.
llvm::Constant *
IRGenModule::getAddrOfClassMetadataBounds(ClassDecl *D,
                                          ForDefinition_t forDefinition) {
  LinkEntity entity = LinkEntity::forClassMetadataBaseOffset(D);
  return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
}

/// Return the address of a generic type's metadata instantiation cache.
llvm::Constant *
IRGenModule::getAddrOfTypeMetadataInstantiationCache(NominalTypeDecl *D,
                                                ForDefinition_t forDefinition) {
  auto entity = LinkEntity::forTypeMetadataInstantiationCache(D);
  return getAddrOfLLVMVariable(entity, forDefinition, DebugTypeInfo());
}

llvm::Function *
IRGenModule::getAddrOfTypeMetadataInstantiationFunction(NominalTypeDecl *D,
                                              ForDefinition_t forDefinition) {
  LinkEntity entity = LinkEntity::forTypeMetadataInstantiationFunction(D);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  // This function is used in two cases -- allocating generic type metadata,
  // and relocating non-generic resilient class metadata.
  llvm::FunctionType *fnType;

  if (D->isGenericContext()) {
    // MetadataInstantiator in ABI/Metadata.h
    llvm::Type *argTys[] = {
      /// Type descriptor.
      TypeContextDescriptorPtrTy,
      /// Generic arguments.
      Int8PtrPtrTy,
      /// Generic metadata pattern.
      Int8PtrTy
    };

    fnType = llvm::FunctionType::get(TypeMetadataPtrTy, argTys,
                                     /*isVarArg*/ false);
  } else {
    assert(isa<ClassDecl>(D));

    // MetadataRelocator in ABI/Metadata.h
    llvm::Type *argTys[] = {
      /// Type descriptor.
      TypeContextDescriptorPtrTy,
      /// Resilient metadata pattern.
      Int8PtrTy
    };

    fnType = llvm::FunctionType::get(TypeMetadataPtrTy, argTys,
                                     /*isVarArg*/ false);
  }

  Signature signature(fnType, llvm::AttributeList(), DefaultCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

llvm::Function *
IRGenModule::getAddrOfTypeMetadataCompletionFunction(NominalTypeDecl *D,
                                              ForDefinition_t forDefinition) {
  LinkEntity entity = LinkEntity::forTypeMetadataCompletionFunction(D);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  llvm::Type *argTys[] = {
    /// Type metadata.
    TypeMetadataPtrTy,
    /// Metadata completion context.
    Int8PtrTy,
    /// Generic metadata pattern.
    Int8PtrPtrTy
  };
  auto fnType = llvm::FunctionType::get(TypeMetadataResponseTy,
                                        argTys, /*isVarArg*/ false);
  Signature signature(fnType, llvm::AttributeList(), SwiftCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Return the address of a nominal type descriptor.
llvm::Constant *IRGenModule::getAddrOfTypeContextDescriptor(NominalTypeDecl *D,
                                              RequireMetadata_t requireMetadata,
                                              ConstantInit definition) {
  IRGen.noteUseOfTypeContextDescriptor(D, requireMetadata);

  auto entity = LinkEntity::forNominalTypeDescriptor(D);
  return getAddrOfLLVMVariable(entity,
                               definition,
                               DebugTypeInfo());
}

llvm::Constant *IRGenModule::
getAddrOfReflectionBuiltinDescriptor(CanType type,
                                     ConstantInit definition) {
  auto entity = LinkEntity::forReflectionBuiltinDescriptor(type);
  return getAddrOfLLVMVariable(entity,
                               definition,
                               DebugTypeInfo());
}

llvm::Constant *IRGenModule::
getAddrOfReflectionFieldDescriptor(CanType type,
                                   ConstantInit definition) {
  auto entity = LinkEntity::forReflectionFieldDescriptor(type);
  return getAddrOfLLVMVariable(entity,
                               definition,
                               DebugTypeInfo());
}

llvm::Constant *IRGenModule::
getAddrOfReflectionAssociatedTypeDescriptor(const ProtocolConformance *c,
                                            ConstantInit definition) {
  auto entity = LinkEntity::forReflectionAssociatedTypeDescriptor(c);
  return getAddrOfLLVMVariable(entity,
                               definition,
                               DebugTypeInfo());
}

/// Return the address of a property descriptor.
llvm::Constant *IRGenModule::getAddrOfPropertyDescriptor(AbstractStorageDecl *D,
                                                      ConstantInit definition) {
  auto entity = LinkEntity::forPropertyDescriptor(D);
  return getAddrOfLLVMVariable(entity,
                               definition,
                               DebugTypeInfo());
}

llvm::Constant *IRGenModule::getAddrOfProtocolDescriptor(ProtocolDecl *D,
                                                      ConstantInit definition) {
  if (D->isObjC()) {
    assert(!definition &&
           "cannot define an @objc protocol descriptor this way");
    return getAddrOfObjCProtocolRecord(D, NotForDefinition);
  }

  auto entity = LinkEntity::forProtocolDescriptor(D);
  return getAddrOfLLVMVariable(entity, definition,
                               DebugTypeInfo());
}

llvm::Constant *IRGenModule::getAddrOfProtocolRequirementsBaseDescriptor(
                                                         ProtocolDecl *proto) {
  auto entity = LinkEntity::forProtocolRequirementsBaseDescriptor(proto);
  return getAddrOfLLVMVariable(entity, ConstantInit(),
                               DebugTypeInfo());
}

llvm::GlobalValue *IRGenModule::defineProtocolRequirementsBaseDescriptor(
                                                ProtocolDecl *proto,
                                                llvm::Constant *definition) {
  auto entity = LinkEntity::forProtocolRequirementsBaseDescriptor(proto);
  return defineAlias(entity, definition);
}

llvm::Constant *IRGenModule::getAddrOfAssociatedTypeDescriptor(
                                               AssociatedTypeDecl *assocType) {
  auto entity = LinkEntity::forAssociatedTypeDescriptor(assocType);
  return getAddrOfLLVMVariable(entity, ConstantInit(),
                               DebugTypeInfo());
}

llvm::GlobalValue *IRGenModule::defineAssociatedTypeDescriptor(
                                                 AssociatedTypeDecl *assocType,
                                                 llvm::Constant *definition) {
  auto entity = LinkEntity::forAssociatedTypeDescriptor(assocType);
  return defineAlias(entity, definition);
}

llvm::Constant *IRGenModule::getAddrOfAssociatedConformanceDescriptor(
                                          AssociatedConformance conformance) {
  auto entity = LinkEntity::forAssociatedConformanceDescriptor(conformance);
  return getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
}

llvm::GlobalValue *IRGenModule::defineAssociatedConformanceDescriptor(
                                            AssociatedConformance conformance,
                                            llvm::Constant *definition) {
  auto entity = LinkEntity::forAssociatedConformanceDescriptor(conformance);
  return defineAlias(entity, definition);
}

llvm::Constant *IRGenModule::getAddrOfBaseConformanceDescriptor(
                                                BaseConformance conformance) {
  auto entity = LinkEntity::forBaseConformanceDescriptor(conformance);
  return getAddrOfLLVMVariable(entity, ConstantInit(), DebugTypeInfo());
}

llvm::GlobalValue *IRGenModule::defineBaseConformanceDescriptor(
                                            BaseConformance conformance,
                                            llvm::Constant *definition) {
  auto entity = LinkEntity::forBaseConformanceDescriptor(conformance);
  return defineAlias(entity, definition);
}

llvm::Constant *IRGenModule::getAddrOfProtocolConformanceDescriptor(
                                const RootProtocolConformance *conformance,
                                ConstantInit definition) {
  IRGen.addLazyWitnessTable(conformance);

  auto entity = LinkEntity::forProtocolConformanceDescriptor(conformance);
  return getAddrOfLLVMVariable(entity, definition,
                               DebugTypeInfo());
}

/// Fetch the declaration of the ivar initializer for the given class.
Optional<llvm::Function*> IRGenModule::getAddrOfIVarInitDestroy(
                            ClassDecl *cd,
                            bool isDestroyer,
                            bool isForeign,
                            ForDefinition_t forDefinition) {
  auto silRef = SILDeclRef(cd,
                           isDestroyer
                           ? SILDeclRef::Kind::IVarDestroyer
                           : SILDeclRef::Kind::IVarInitializer)
    .asForeign(isForeign);

  // Find the SILFunction for the ivar initializer or destroyer.
  if (auto silFn = getSILModule().lookUpFunction(silRef)) {
    return getAddrOfSILFunction(silFn, forDefinition);
  }

  return None;
}

/// Returns the address of a value-witness function.
llvm::Function *IRGenModule::getAddrOfValueWitness(CanType abstractType,
                                                   ValueWitness index,
                                                ForDefinition_t forDefinition) {
  // We shouldn't emit value witness symbols for generic type instances.
  assert(!isa<BoundGenericType>(abstractType) &&
         "emitting value witness for generic type instance?!");
  
  LinkEntity entity = LinkEntity::forValueWitness(abstractType, index);

  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  auto signature = getValueWitnessSignature(index);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Returns the address of a value-witness table.  If a definition
/// type is provided, the table is created with that type; the return
/// value will be an llvm::GlobalValue.  Otherwise, the result will
/// have type WitnessTablePtrTy.
llvm::Constant *
IRGenModule::getAddrOfValueWitnessTable(CanType concreteType,
                                        ConstantInit definition) {
  LinkEntity entity = LinkEntity::forValueWitnessTable(concreteType);
  return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
}

static Address getAddrOfSimpleVariable(IRGenModule &IGM,
                             llvm::DenseMap<LinkEntity, llvm::Constant*> &cache,
                             LinkEntity entity,
                             ForDefinition_t forDefinition) {
  auto alignment = entity.getAlignment(IGM);
  auto type = entity.getDefaultDeclarationType(IGM);
  
  // Check whether it's already cached.
  llvm::Constant *&entry = cache[entity];
  if (entry) {
    auto existing = cast<llvm::GlobalValue>(entry);
    assert(alignment == Alignment(existing->getAlignment()));
    if (forDefinition) updateLinkageForDefinition(IGM, existing, entity);
    return Address(entry, alignment);
  }

  // Otherwise, we need to create it.
  LinkInfo link = LinkInfo::get(IGM, entity, forDefinition);
  auto addr = createVariable(IGM, link, type, alignment);

  entry = addr;
  return Address(addr, alignment);
}

/// getAddrOfFieldOffset - Get the address of the global variable
/// which contains an offset to apply to either an object (if direct)
/// or a metadata object in order to find an offset to apply to an
/// object (if indirect).
///
/// The result is always a GlobalValue.
Address IRGenModule::getAddrOfFieldOffset(VarDecl *var,
                                          ForDefinition_t forDefinition) {
  LinkEntity entity = LinkEntity::forFieldOffset(var);
  return getAddrOfSimpleVariable(*this, GlobalVars, entity,
                                 forDefinition);
}

Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case,
                                       ForDefinition_t forDefinition) {
  LinkEntity entity = LinkEntity::forEnumCase(Case);
  auto addr = getAddrOfSimpleVariable(*this, GlobalVars, entity, forDefinition);

  auto *global = cast<llvm::GlobalVariable>(addr.getAddress());
  global->setConstant(true);

  return addr;
}

void IRGenModule::emitNestedTypeDecls(DeclRange members) {
  for (Decl *member : members) {
    switch (member->getKind()) {
    case DeclKind::Import:
    case DeclKind::TopLevelCode:
    case DeclKind::Protocol:
    case DeclKind::Extension:
    case DeclKind::InfixOperator:
    case DeclKind::PrefixOperator:
    case DeclKind::PostfixOperator:
    case DeclKind::Param:
    case DeclKind::Module:
    case DeclKind::PrecedenceGroup:
      llvm_unreachable("decl not allowed in type context");

    case DeclKind::IfConfig:
    case DeclKind::PoundDiagnostic:
      continue;

    case DeclKind::Var:
    case DeclKind::Subscript:
    case DeclKind::PatternBinding:
    case DeclKind::Func:
    case DeclKind::Accessor:
    case DeclKind::Constructor:
    case DeclKind::Destructor:
    case DeclKind::EnumCase:
    case DeclKind::EnumElement:
    case DeclKind::MissingMember:
      // Skip non-type members.
      continue;

    case DeclKind::AssociatedType:
    case DeclKind::GenericTypeParam:
      // Do nothing.
      continue;

    case DeclKind::TypeAlias:
      // Do nothing.
      continue;

    case DeclKind::Enum:
      emitEnumDecl(cast<EnumDecl>(member));
      continue;
    case DeclKind::Struct:
      emitStructDecl(cast<StructDecl>(member));
      continue;
    case DeclKind::Class:
      emitClassDecl(cast<ClassDecl>(member));
      continue;
    }
  }
}

static bool shouldEmitCategory(IRGenModule &IGM, ExtensionDecl *ext) {
  for (auto conformance : ext->getLocalConformances()) {
    if (conformance->getProtocol()->isObjC())
      return true;
  }

  for (auto member : ext->getMembers()) {
    if (auto func = dyn_cast<FuncDecl>(member)) {
      if (requiresObjCMethodDescriptor(func))
        return true;
    } else if (auto constructor = dyn_cast<ConstructorDecl>(member)) {
      if (requiresObjCMethodDescriptor(constructor))
        return true;
    } else if (auto var = dyn_cast<VarDecl>(member)) {
      if (requiresObjCPropertyDescriptor(IGM, var))
        return true;
    } else if (auto subscript = dyn_cast<SubscriptDecl>(member)) {
      if (requiresObjCSubscriptDescriptor(IGM, subscript))
        return true;
    }
  }

  return false;
}

void IRGenModule::emitExtension(ExtensionDecl *ext) {
  emitNestedTypeDecls(ext->getMembers());

  addLazyConformances(ext);

  // Generate a category if the extension either introduces a
  // conformance to an ObjC protocol or introduces a method
  // that requires an Objective-C entry point.
  ClassDecl *origClass = ext->getSelfClassDecl();
  if (!origClass)
    return;

  if (shouldEmitCategory(*this, ext)) {
    assert(origClass && !origClass->isForeign() &&
           "foreign types cannot have categories emitted");
    llvm::Constant *category = emitCategoryData(*this, ext);
    category = llvm::ConstantExpr::getBitCast(category, Int8PtrTy);
    ObjCCategories.push_back(category);
    ObjCCategoryDecls.push_back(ext);
  }
}


/// Create an allocation on the stack.
Address IRGenFunction::createAlloca(llvm::Type *type,
                                    Alignment alignment,
                                    const llvm::Twine &name) {
  llvm::AllocaInst *alloca =
      new llvm::AllocaInst(type, IGM.DataLayout.getAllocaAddrSpace(), name,
                           AllocaIP);
  alloca->setAlignment(alignment.getValue());
  return Address(alloca, alignment);
}

/// Create an allocation of an array on the stack.
Address IRGenFunction::createAlloca(llvm::Type *type,
                                    llvm::Value *ArraySize,
                                    Alignment alignment,
                                    const llvm::Twine &name) {
  llvm::AllocaInst *alloca =
      new llvm::AllocaInst(type, IGM.DataLayout.getAllocaAddrSpace(), ArraySize,
                           alignment.getValue(), name, AllocaIP);
  return Address(alloca, alignment);
}

/// Allocate a fixed-size buffer on the stack.
Address IRGenFunction::createFixedSizeBufferAlloca(const llvm::Twine &name) {
  return createAlloca(IGM.getFixedBufferTy(),
                      getFixedBufferAlignment(IGM),
                      name);
}

/// Get or create a global string constant.
///
/// \returns an i8* with a null terminator; note that embedded nulls
///   are okay
///
/// FIXME: willBeRelativelyAddressed is only needed to work around an ld64 bug
/// resolving relative references to coalesceable symbols.
/// It should be removed when fixed. rdar://problem/22674524
llvm::Constant *IRGenModule::getAddrOfGlobalString(StringRef data,
                                               bool willBeRelativelyAddressed) {
  // Check whether this string already exists.
  auto &entry = GlobalStrings[data];
  if (entry.second) {
    // FIXME: Clear unnamed_addr if the global will be relative referenced
    // to work around an ld64 bug. rdar://problem/22674524
    if (willBeRelativelyAddressed)
      entry.first->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::None);
    return entry.second;
  }

  entry = createStringConstant(data, willBeRelativelyAddressed);
  return entry.second;
}

/// Get or create a global UTF-16 string constant.
///
/// \returns an i16* with a null terminator; note that embedded nulls
///   are okay
llvm::Constant *IRGenModule::getAddrOfGlobalUTF16String(StringRef utf8) {
  // Check whether this string already exists.
  auto &entry = GlobalUTF16Strings[utf8];
  if (entry) return entry;

  // If not, first transcode it to UTF16.
  SmallVector<llvm::UTF16, 128> buffer(utf8.size() + 1); // +1 for ending nulls.
  const llvm::UTF8 *fromPtr = (const llvm::UTF8 *) utf8.data();
  llvm::UTF16 *toPtr = &buffer[0];
  (void) ConvertUTF8toUTF16(&fromPtr, fromPtr + utf8.size(),
                            &toPtr, toPtr + utf8.size(),
                            llvm::strictConversion);

  // The length of the transcoded string in UTF-8 code points.
  size_t utf16Length = toPtr - &buffer[0];

  // Null-terminate the UTF-16 string.
  *toPtr = 0;
  ArrayRef<llvm::UTF16> utf16(&buffer[0], utf16Length + 1);

  auto init = llvm::ConstantDataArray::get(LLVMContext, utf16);
  auto global = new llvm::GlobalVariable(Module, init->getType(), true,
                                         llvm::GlobalValue::PrivateLinkage,
                                         init);
  global->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

  // Drill down to make an i16*.
  auto zero = llvm::ConstantInt::get(SizeTy, 0);
  llvm::Constant *indices[] = { zero, zero };
  auto address = llvm::ConstantExpr::getInBoundsGetElementPtr(
      global->getValueType(), global, indices);

  // Cache and return.
  entry = address;
  return address;
}

/// Do we have to use resilient access patterns when working with this
/// declaration?
///
/// IRGen is primarily concerned with resilient handling of the following:
/// - For structs, a struct's size might change
/// - For enums, new cases can be added
/// - For classes, the superclass might change the size or number
///   of stored properties
bool IRGenModule::isResilient(NominalTypeDecl *D, ResilienceExpansion expansion) {
  if (expansion == ResilienceExpansion::Maximal &&
      Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
    return false;
  }
  return D->isResilient(getSwiftModule(), expansion);
}

/// Do we have to use resilient access patterns when working with this
/// class?
///
/// For classes, this means that virtual method calls use dispatch thunks
/// rather than accessing metadata members directly.
bool IRGenModule::hasResilientMetadata(ClassDecl *D,
                                       ResilienceExpansion expansion) {
  if (expansion == ResilienceExpansion::Maximal &&
      Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile) {
    return false;
  }
  return D->hasResilientMetadata(getSwiftModule(), expansion);
}

// The most general resilience expansion where the given declaration is visible.
ResilienceExpansion
IRGenModule::getResilienceExpansionForAccess(NominalTypeDecl *decl) {
  if (decl->getModuleContext() == getSwiftModule() &&
      decl->getEffectiveAccess() < AccessLevel::Public)
    return ResilienceExpansion::Maximal;
  return ResilienceExpansion::Minimal;
}

// The most general resilience expansion which has knowledge of the declaration's
// layout. Calling isResilient() with this scope will always return false.
ResilienceExpansion
IRGenModule::getResilienceExpansionForLayout(NominalTypeDecl *decl) {
  if (Types.getLoweringMode() == TypeConverter::Mode::CompletelyFragile)
    return ResilienceExpansion::Minimal;

  if (isResilient(decl, ResilienceExpansion::Minimal))
    return ResilienceExpansion::Maximal;

  return getResilienceExpansionForAccess(decl);
}

// The most general resilience expansion which has knowledge of the global
// variable's layout.
ResilienceExpansion
IRGenModule::getResilienceExpansionForLayout(SILGlobalVariable *global) {
  if (hasPublicVisibility(global->getLinkage()))
    return ResilienceExpansion::Minimal;
  return ResilienceExpansion::Maximal;
}

llvm::Function *
IRGenModule::getAddrOfGenericWitnessTableInstantiationFunction(
                                      const NormalProtocolConformance *conf) {
  auto forDefinition = ForDefinition;

  LinkEntity entity =
    LinkEntity::forGenericProtocolWitnessTableInstantiationFunction(conf);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  auto fnType = llvm::FunctionType::get(
      VoidTy, {WitnessTablePtrTy, TypeMetadataPtrTy, Int8PtrPtrTy},
      /*varargs*/ false);
  Signature signature(fnType, llvm::AttributeList(), DefaultCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Fetch the lazy witness table access function for a protocol conformance.
llvm::Function *
IRGenModule::getAddrOfWitnessTableLazyAccessFunction(
                                      const NormalProtocolConformance *conf,
                                              CanType conformingType,
                                              ForDefinition_t forDefinition) {
  LinkEntity entity =
    LinkEntity::forProtocolWitnessTableLazyAccessFunction(conf, conformingType);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  llvm::FunctionType *fnType
    = llvm::FunctionType::get(WitnessTablePtrTy, false);

  Signature signature(fnType, llvm::AttributeList(), DefaultCC);
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  ApplyIRLinkage({link.getLinkage(), link.getVisibility(), link.getDLLStorage()})
      .to(entry);
  return entry;
}

/// Get or create a witness table cache variable.  These are an
/// implementation detail of witness table lazy access functions.
llvm::Constant *
IRGenModule::getAddrOfWitnessTableLazyCacheVariable(
                                      const NormalProtocolConformance *conf,
                                              CanType conformingType,
                                              ForDefinition_t forDefinition) {
  assert(!conformingType->hasArchetype());
  LinkEntity entity =
    LinkEntity::forProtocolWitnessTableLazyCacheVariable(conf, conformingType);
  auto variable = getAddrOfLLVMVariable(entity,
                                        forDefinition,
                                        DebugTypeInfo());

  // Zero-initialize if we're asking for a definition.
  if (forDefinition) {
    cast<llvm::GlobalVariable>(variable)->setInitializer(
      llvm::ConstantPointerNull::get(WitnessTablePtrTy));
  }

  return variable;
}

/// Look up the address of a witness table.
///
/// This can only be used with non-dependent conformances.
llvm::Constant*
IRGenModule::getAddrOfWitnessTable(const RootProtocolConformance *conf,
                                   ConstantInit definition) {
  IRGen.addLazyWitnessTable(conf);

  auto entity = LinkEntity::forProtocolWitnessTable(conf);
  return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
}

/// Look up the address of a witness table pattern.
///
/// This can only be used with dependent conformances from inside the
/// defining module.
llvm::Constant*
IRGenModule::getAddrOfWitnessTablePattern(const NormalProtocolConformance *conf,
                                          ConstantInit definition) {
  IRGen.addLazyWitnessTable(conf);

  auto entity = LinkEntity::forProtocolWitnessTablePattern(conf);
  return getAddrOfLLVMVariable(entity, definition, DebugTypeInfo());
}

llvm::Function *
IRGenModule::getAddrOfAssociatedTypeWitnessTableAccessFunction(
                                  const NormalProtocolConformance *conformance,
                                  const AssociatedConformance &association) {
  auto forDefinition = ForDefinition;

  LinkEntity entity =
    LinkEntity::forAssociatedTypeWitnessTableAccessFunction(conformance,
                                                            association);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  auto signature = getAssociatedTypeWitnessTableAccessFunctionSignature();
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

llvm::Function *
IRGenModule::getAddrOfDefaultAssociatedConformanceAccessor(
                                         AssociatedConformance requirement) {
  auto forDefinition = ForDefinition;

  LinkEntity entity =
    LinkEntity::forDefaultAssociatedConformanceAccessor(requirement);
  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) {
    if (forDefinition) updateLinkageForDefinition(*this, entry, entity);
    return entry;
  }

  auto signature = getAssociatedTypeWitnessTableAccessFunctionSignature();
  LinkInfo link = LinkInfo::get(*this, entity, forDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

llvm::Function *
IRGenModule::getAddrOfContinuationPrototype(CanSILFunctionType fnType) {
  LinkEntity entity = LinkEntity::forCoroutineContinuationPrototype(fnType);

  llvm::Function *&entry = GlobalFuncs[entity];
  if (entry) return entry;

  auto signature = Signature::forCoroutineContinuation(*this, fnType);
  LinkInfo link = LinkInfo::get(*this, entity, NotForDefinition);
  entry = createFunction(*this, link, signature);
  return entry;
}

/// Should we be defining the given helper function?
static llvm::Function *shouldDefineHelper(IRGenModule &IGM,
                                          llvm::Constant *fn,
                                          bool setIsNoInline) {
  auto *def = dyn_cast<llvm::Function>(fn);
  if (!def) return nullptr;
  if (!def->empty()) return nullptr;

  ApplyIRLinkage(IRLinkage::InternalLinkOnceODR).to(def);
  def->setDoesNotThrow();
  def->setCallingConv(IGM.DefaultCC);
  if (setIsNoInline)
    def->addFnAttr(llvm::Attribute::NoInline);
  return def;
}

/// Get or create a helper function with the given name and type, lazily
/// using the given generation function to fill in its body.
///
/// The helper function will be shared between translation units within the
/// current linkage unit, so choose the name carefully to ensure that it
/// does not collide with any other helper function.  In general, it should
/// be a Swift-specific C reserved name; that is, it should start with
//  "__swift".
llvm::Constant *
IRGenModule::getOrCreateHelperFunction(StringRef fnName, llvm::Type *resultTy,
                                       ArrayRef<llvm::Type*> paramTys,
                        llvm::function_ref<void(IRGenFunction &IGF)> generate,
                        bool setIsNoInline) {
  llvm::FunctionType *fnTy =
    llvm::FunctionType::get(resultTy, paramTys, false);

  llvm::Constant *fn = Module.getOrInsertFunction(fnName, fnTy);

  if (llvm::Function *def = shouldDefineHelper(*this, fn, setIsNoInline)) {
    IRGenFunction IGF(*this, def);
    if (DebugInfo)
      DebugInfo->emitArtificialFunction(IGF, def);
    generate(IGF);
  }

  return fn;
}
