//===--- GenKeyPath.cpp - IRGen support for key path objects --------------===//
//
// 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 contains code for emitting key path patterns, which can be used
//  by the standard library to instantiate key path objects.
//
//===----------------------------------------------------------------------===//

#include "Callee.h"
#include "ClassLayout.h"
#include "ConstantBuilder.h"
#include "Explosion.h"
#include "GenClass.h"
#include "GenDecl.h"
#include "GenMeta.h"
#include "GenProto.h"
#include "GenStruct.h"
#include "GenType.h"
#include "GenericRequirement.h"
#include "IRGenDebugInfo.h"
#include "IRGenFunction.h"
#include "IRGenMangler.h"
#include "IRGenModule.h"
#include "MetadataLayout.h"
#include "ProtocolInfo.h"
#include "StructLayout.h"
#include "TypeInfo.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Function.h"
#include "swift/SIL/SILInstruction.h"
#include "swift/SIL/SILLocation.h"
#include "swift/SIL/TypeLowering.h"
#include "swift/ABI/KeyPath.h"
#include "swift/ABI/HeapObject.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/Decl.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/AST/DiagnosticsIRGen.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Statistic.h"
#include "swift/IRGen/Linking.h"

using namespace swift;
using namespace irgen;

#define DEBUG_TYPE "IRGen key paths"
STATISTIC(NumTrivialPropertyDescriptors, "# of trivial property descriptors");
STATISTIC(NumNonTrivialPropertyDescriptors, "# of nontrivial property descriptors");

enum KeyPathAccessor {
  Getter,
  Setter,
  Equals,
  Hash,
};

static void
bindPolymorphicArgumentsFromComponentIndices(IRGenFunction &IGF,
                                     const KeyPathPatternComponent &component,
                                     GenericEnvironment *genericEnv,
                                     ArrayRef<GenericRequirement> requirements,
                                     llvm::Value *args,
                                     llvm::Value *size,
                                     bool hasSubscriptIndices) {
  if (!genericEnv)
    return;
  
  // The generic environment is marshaled into the end of the component
  // argument area inside the instance. Bind the generic information out of
  // the buffer.
  if (hasSubscriptIndices) {
    auto genericArgsSize = llvm::ConstantInt::get(IGF.IGM.SizeTy,
      requirements.size() * IGF.IGM.getPointerSize().getValue());

    auto genericArgsOffset = IGF.Builder.CreateSub(size, genericArgsSize);
    args = IGF.Builder.CreateInBoundsGEP(args, genericArgsOffset);
  }
  bindFromGenericRequirementsBuffer(IGF, requirements,
    Address(args, IGF.IGM.getPointerAlignment()),
    MetadataState::Complete,
    [&](CanType t) {
      return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
    });
}

static llvm::Function *
getAccessorForComputedComponent(IRGenModule &IGM,
                                const KeyPathPatternComponent &component,
                                KeyPathAccessor whichAccessor,
                                GenericEnvironment *genericEnv,
                                ArrayRef<GenericRequirement> requirements,
                                bool hasSubscriptIndices) {
  SILFunction *accessor;
  switch (whichAccessor) {
  case Getter:
    accessor = component.getComputedPropertyGetter();
    break;
  case Setter:
    accessor = component.getComputedPropertySetter();
    break;
  case Equals:
    accessor = component.getSubscriptIndexEquals();
    break;
  case Hash:
    accessor = component.getSubscriptIndexHash();
    break;
  }
  
  // If the accessor is not generic, and locally available, we can use it as is.
  // If it's only externally available, we need a local thunk to relative-
  // reference.
  if (requirements.empty() &&
      !isAvailableExternally(accessor->getLinkage()) &&
      &IGM == IGM.IRGen.getGenModule(accessor)) {
    return IGM.getAddrOfSILFunction(accessor, NotForDefinition);
  }
  auto accessorFn = IGM.getAddrOfSILFunction(accessor, NotForDefinition);
  
  auto accessorFnTy = cast<llvm::FunctionType>(
    accessorFn->getType()->getPointerElementType());;
  
  // Otherwise, we need a thunk to unmarshal the generic environment from the
  // argument area. It'd be nice to have a good way to represent this
  // directly in SIL, of course...
  const char *thunkName;
  unsigned numArgsToForward;

  switch (whichAccessor) {
  case Getter:
    thunkName = "keypath_get";
    numArgsToForward = 2;
    break;
  case Setter:
    thunkName = "keypath_set";
    numArgsToForward = 2;
    break;
  case Equals:
    thunkName = "keypath_equals";
    numArgsToForward = 2;
    break;
  case Hash:
    thunkName = "keypath_hash";
    numArgsToForward = 1;
    break;
  }

  SmallVector<llvm::Type *, 4> thunkParams;
  for (unsigned i = 0; i < numArgsToForward; ++i)
    thunkParams.push_back(accessorFnTy->getParamType(i));
  
  switch (whichAccessor) {
  case Getter:
  case Setter:
    thunkParams.push_back(IGM.Int8PtrTy);
    break;
  case Equals:
  case Hash:
    break;
  }
  thunkParams.push_back(IGM.SizeTy);

  auto thunkType = llvm::FunctionType::get(accessorFnTy->getReturnType(),
                                           thunkParams,
                                           /*vararg*/ false);
  
  auto accessorThunk = llvm::Function::Create(thunkType,
    llvm::GlobalValue::PrivateLinkage, thunkName, IGM.getModule());
  accessorThunk->setAttributes(IGM.constructInitialAttributes());
  accessorThunk->setCallingConv(IGM.SwiftCC);

  switch (whichAccessor) {
  case Getter:
    // Original accessor's args should be @in or @out, meaning they won't be
    // captured or aliased.
    accessorThunk->addAttribute(1, llvm::Attribute::NoCapture);
    accessorThunk->addAttribute(1, llvm::Attribute::NoAlias);
    accessorThunk->addAttribute(2, llvm::Attribute::NoCapture);
    accessorThunk->addAttribute(2, llvm::Attribute::NoAlias);
    // Output is sret.
    accessorThunk->addAttribute(1, llvm::Attribute::StructRet);
    break;
  case Setter:
    // Original accessor's args should be @in or @out, meaning they won't be
    // captured or aliased.
    accessorThunk->addAttribute(1, llvm::Attribute::NoCapture);
    accessorThunk->addAttribute(1, llvm::Attribute::NoAlias);
    accessorThunk->addAttribute(2, llvm::Attribute::NoCapture);
    accessorThunk->addAttribute(2, llvm::Attribute::NoAlias);
    break;
  case Equals:
  case Hash:
    break;
  }

  {
    IRGenFunction IGF(IGM, accessorThunk);
    if (IGM.DebugInfo)
      IGM.DebugInfo->emitArtificialFunction(IGF, accessorThunk);
      
    auto params = IGF.collectParameters();
    Explosion forwardedArgs;
    forwardedArgs.add(params.claim(numArgsToForward));
    
    llvm::Value *componentArgsBuf;
    switch (whichAccessor) {
    case Getter:
    case Setter:
      // The component arguments are passed alongside the base being projected.
      componentArgsBuf = params.claimNext();
      // Pass the argument pointer down to the underlying function, if it
      // wants it.
      if (hasSubscriptIndices) {
        forwardedArgs.add(componentArgsBuf);
      }
      break;
    case Equals:
    case Hash:
      // We're operating directly on the component argument buffer.
      componentArgsBuf = forwardedArgs.getAll()[0];
      break;
    }
    auto componentArgsBufSize = params.claimNext();
    bindPolymorphicArgumentsFromComponentIndices(IGF, component,
                                                 genericEnv, requirements,
                                                 componentArgsBuf,
                                                 componentArgsBufSize,
                                                 hasSubscriptIndices);
    
    // Use the bound generic metadata to form a call to the original generic
    // accessor.
    if (genericEnv) {
      WitnessMetadata ignoreWitnessMetadata;
      auto forwardingSubs = genericEnv->getForwardingSubstitutionMap();
      emitPolymorphicArguments(IGF, accessor->getLoweredFunctionType(),
                               forwardingSubs,
                               &ignoreWitnessMetadata,
                               forwardedArgs);
    }
    auto fnPtr = FunctionPointer::forDirect(IGM, accessorFn,
                                          accessor->getLoweredFunctionType());
    auto call = IGF.Builder.CreateCall(fnPtr, forwardedArgs.claimAll());
    
    if (call->getType()->isVoidTy())
      IGF.Builder.CreateRetVoid();
    else
      IGF.Builder.CreateRet(call);
  }
  
  return accessorThunk;
}

static llvm::Constant *
getLayoutFunctionForComputedComponent(IRGenModule &IGM,
                                    const KeyPathPatternComponent &component,
                                    GenericEnvironment *genericEnv,
                                    ArrayRef<GenericRequirement> requirements) {
  // Generate a function that returns the expected size and alignment necessary
  // to store captured generic context and subscript index arguments.
  auto retTy = llvm::StructType::get(IGM.getLLVMContext(),
                                     {IGM.SizeTy, IGM.SizeTy});
  auto fnTy = llvm::FunctionType::get(
    retTy, { IGM.Int8PtrTy }, /*vararg*/ false);
    
  auto layoutFn = llvm::Function::Create(fnTy,
    llvm::GlobalValue::PrivateLinkage, "keypath_get_arg_layout", IGM.getModule());
    
  {
    IRGenFunction IGF(IGM, layoutFn);
    if (IGM.DebugInfo)
      IGM.DebugInfo->emitArtificialFunction(IGF, layoutFn);
    // Unmarshal the generic environment from the argument buffer.
    auto parameters = IGF.collectParameters();
    auto args = parameters.claimNext();
    
    if (genericEnv) {
      bindFromGenericRequirementsBuffer(IGF, requirements,
        Address(args, IGF.IGM.getPointerAlignment()),
        MetadataState::Complete,
        [&](CanType t) {
          return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
        });
    }
    
    // Run through the captured index types to determine the size and alignment
    // needed. Start with pointer alignment for the generic environment.
    llvm::Value *size = llvm::ConstantInt::get(IGM.SizeTy, 0);
    llvm::Value *alignMask = llvm::ConstantInt::get(IGM.SizeTy, 0);

    for (auto &index : component.getSubscriptIndices()) {
      auto ty = genericEnv
        ? genericEnv->mapTypeIntoContext(IGM.getSILModule(), index.LoweredType)
        : index.LoweredType;
      auto &ti = IGM.getTypeInfo(ty);
      auto indexSize = ti.getSize(IGF, ty);
      auto indexAlign = ti.getAlignmentMask(IGF, ty);
      
      auto notIndexAlign = IGF.Builder.CreateNot(indexAlign);
      
      size = IGF.Builder.CreateAdd(size, indexAlign);
      size = IGF.Builder.CreateAnd(size, notIndexAlign);
      size = IGF.Builder.CreateAdd(size, indexSize);
      
      alignMask = IGF.Builder.CreateOr(alignMask, indexAlign);
    }
    
    // If there's generic environment to capture, then it's stored as a block
    // of pointer-aligned words after the captured values.
    
    auto genericsSize = llvm::ConstantInt::get(IGM.SizeTy,
      IGM.getPointerSize().getValue() * requirements.size());
    auto genericsAlign = llvm::ConstantInt::get(IGM.SizeTy,
      IGM.getPointerAlignment().getValue() - 1);
    auto notGenericsAlign = llvm::ConstantExpr::getNot(genericsAlign);
    size = IGF.Builder.CreateAdd(size, genericsAlign);
    size = IGF.Builder.CreateAnd(size, notGenericsAlign);
    size = IGF.Builder.CreateAdd(size, genericsSize);
    alignMask = IGF.Builder.CreateOr(alignMask, genericsAlign);

    llvm::Value *retValue = IGF.Builder.CreateInsertValue(
      llvm::UndefValue::get(retTy), size, 0);
    retValue = IGF.Builder.CreateInsertValue(
      retValue, alignMask, 1);
      
    IGF.Builder.CreateRet(retValue);
  }
  
  return layoutFn;
}

static llvm::Constant *
getWitnessTableForComputedComponent(IRGenModule &IGM,
                                    const KeyPathPatternComponent &component,
                                    GenericEnvironment *genericEnv,
                                    ArrayRef<GenericRequirement> requirements) {
  // If the only thing we're capturing is generic environment, then we can
  // use a prefab witness table from the runtime. A null reference will be
  // filled in by the runtime.
  if (component.getSubscriptIndices().empty()) {
    return nullptr;
  }
  
  // Are the index values trivial?
  bool isTrivial = true;
  for (auto &component : component.getSubscriptIndices()) {
    auto ty = genericEnv
      ? genericEnv->mapTypeIntoContext(IGM.getSILModule(), component.LoweredType)
      : component.LoweredType;
    auto &ti = IGM.getTypeInfo(ty);
    isTrivial &= ti.isPOD(ResilienceExpansion::Minimal);
  }
  
  llvm::Constant *destroy;
  llvm::Constant *copy;
  if (isTrivial) {
    // We can use prefab witnesses for handling trivial copying and destruction.
    // A null destructor witness signals that the payload is trivial.
    destroy = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
    copy = IGM.getCopyKeyPathTrivialIndicesFn();
  } else {
    // Generate a destructor for this set of indices.
    {
      auto destroyType = llvm::FunctionType::get(IGM.VoidTy,
                                                 {IGM.Int8PtrTy, IGM.SizeTy},
                                                 /*vararg*/ false);
      auto destroyFn = llvm::Function::Create(destroyType,
        llvm::GlobalValue::PrivateLinkage, "keypath_destroy", IGM.getModule());
      destroy = destroyFn;
      
      IRGenFunction IGF(IGM, destroyFn);
      if (IGM.DebugInfo)
        IGM.DebugInfo->emitArtificialFunction(IGF, destroyFn);
    
      auto params = IGF.collectParameters();
      auto componentArgsBuf = params.claimNext();
      auto componentArgsBufSize = params.claimNext();
      bindPolymorphicArgumentsFromComponentIndices(IGF, component,
                                     genericEnv, requirements,
                                     componentArgsBuf,
                                     componentArgsBufSize,
                                     !component.getSubscriptIndices().empty());
      
      llvm::Value *offset = nullptr;
      for (auto &component : component.getSubscriptIndices()) {
        auto ty = genericEnv
          ? genericEnv->mapTypeIntoContext(IGM.getSILModule(),
                                           component.LoweredType)
          : component.LoweredType;
        auto &ti = IGM.getTypeInfo(ty);
        if (offset) {
          auto align = ti.getAlignmentMask(IGF, ty);
          auto notAlign = IGF.Builder.CreateNot(align);
          offset = IGF.Builder.CreateAdd(offset, align);
          offset = IGF.Builder.CreateAnd(offset, notAlign);
        } else {
          offset = llvm::ConstantInt::get(IGM.SizeTy, 0);
        }
        auto elt = IGF.Builder.CreateInBoundsGEP(componentArgsBuf, offset);
        auto eltAddr = ti.getAddressForPointer(
          IGF.Builder.CreateBitCast(elt, ti.getStorageType()->getPointerTo()));
        ti.destroy(IGF, eltAddr, ty,
                   true /*witness table: need it to be fast*/);
        auto size = ti.getSize(IGF, ty);
        offset = IGF.Builder.CreateAdd(offset, size);
      }
      IGF.Builder.CreateRetVoid();
    }
    // Generate a copier for this set of indices.
    {
      auto copyType = llvm::FunctionType::get(IGM.VoidTy,
                                              {IGM.Int8PtrTy, IGM.Int8PtrTy,
                                               IGM.SizeTy},
                                              /*vararg*/ false);
      auto copyFn = llvm::Function::Create(copyType,
        llvm::GlobalValue::PrivateLinkage, "keypath_copy", IGM.getModule());
      copy = copyFn;
      
      IRGenFunction IGF(IGM, copyFn);
      if (IGM.DebugInfo)
        IGM.DebugInfo->emitArtificialFunction(IGF, copyFn);
    
      auto params = IGF.collectParameters();
      auto sourceArgsBuf = params.claimNext();
      auto destArgsBuf = params.claimNext();
      auto componentArgsBufSize = params.claimNext();
      bindPolymorphicArgumentsFromComponentIndices(IGF, component,
                                     genericEnv, requirements,
                                     sourceArgsBuf,
                                     componentArgsBufSize,
                                     !component.getSubscriptIndices().empty());
      
      // Copy over the index values.
      llvm::Value *offset = nullptr;
      for (auto &component : component.getSubscriptIndices()) {
        auto ty = genericEnv
          ? genericEnv->mapTypeIntoContext(IGM.getSILModule(),
                                           component.LoweredType)
          : component.LoweredType;
        auto &ti = IGM.getTypeInfo(ty);
        if (offset) {
          auto align = ti.getAlignmentMask(IGF, ty);
          auto notAlign = IGF.Builder.CreateNot(align);
          offset = IGF.Builder.CreateAdd(offset, align);
          offset = IGF.Builder.CreateAnd(offset, notAlign);
        } else {
          offset = llvm::ConstantInt::get(IGM.SizeTy, 0);
        }
        auto sourceElt = IGF.Builder.CreateInBoundsGEP(sourceArgsBuf, offset);
        auto destElt = IGF.Builder.CreateInBoundsGEP(destArgsBuf, offset);
        auto sourceEltAddr = ti.getAddressForPointer(
          IGF.Builder.CreateBitCast(sourceElt,
                                    ti.getStorageType()->getPointerTo()));
        auto destEltAddr = ti.getAddressForPointer(
          IGF.Builder.CreateBitCast(destElt,
                                    ti.getStorageType()->getPointerTo()));

        ti.initializeWithCopy(IGF, destEltAddr, sourceEltAddr, ty, false);
        auto size = ti.getSize(IGF, ty);
        offset = IGF.Builder.CreateAdd(offset, size);
      }
      
      // Copy over the generic environment.
      if (genericEnv) {
        auto envAlignMask = llvm::ConstantInt::get(IGM.SizeTy,
          IGM.getPointerAlignment().getMaskValue());
        auto notAlignMask = IGF.Builder.CreateNot(envAlignMask);
        offset = IGF.Builder.CreateAdd(offset, envAlignMask);
        offset = IGF.Builder.CreateAnd(offset, notAlignMask);
        
        auto sourceEnv = IGF.Builder.CreateInBoundsGEP(sourceArgsBuf, offset);
        auto destEnv = IGF.Builder.CreateInBoundsGEP(destArgsBuf, offset);
        
        auto align = IGM.getPointerAlignment().getValue();
        IGF.Builder.CreateMemCpy(destEnv, align, sourceEnv, align,
          IGM.getPointerSize().getValue() * requirements.size());
      }
      
      IGF.Builder.CreateRetVoid();
    }
  }
  
  auto equals = getAccessorForComputedComponent(IGM, component, Equals,
                                      genericEnv, requirements,
                                      !component.getSubscriptIndices().empty());
  auto hash = getAccessorForComputedComponent(IGM, component, Hash,
                                      genericEnv, requirements,
                                      !component.getSubscriptIndices().empty());
  
  auto witnesses = llvm::ConstantStruct::getAnon({destroy, copy, equals, hash});
  return new llvm::GlobalVariable(IGM.Module, witnesses->getType(),
                                  /*constant*/ true,
                                  llvm::GlobalValue::PrivateLinkage,
                                  witnesses,
                                  "keypath_witnesses");
}

/// Information about each index operand for a key path pattern that is used
/// to lay out and consume the argument packet.
struct KeyPathIndexOperand {
  SILType LoweredType;
  const KeyPathPatternComponent *LastUser;
};

static llvm::Constant *
getInitializerForComputedComponent(IRGenModule &IGM,
           const KeyPathPatternComponent &component,
           ArrayRef<KeyPathIndexOperand> operands,
           GenericEnvironment *genericEnv,
           ArrayRef<GenericRequirement> requirements) {
  auto fnTy = llvm::FunctionType::get(IGM.VoidTy,
    { /*src*/ IGM.Int8PtrTy,
      /*dest*/ IGM.Int8PtrTy }, /*vararg*/ false);
      
  auto initFn = llvm::Function::Create(fnTy,
    llvm::GlobalValue::PrivateLinkage, "keypath_arg_init", IGM.getModule());
    
  {
    IRGenFunction IGF(IGM, initFn);
    if (IGM.DebugInfo)
      IGM.DebugInfo->emitArtificialFunction(IGF, initFn);

    auto params = IGF.collectParameters();
    // Pointer to the argument packet passed into swift_getKeyPath
    auto src = params.claimNext();
    // Pointer to the destination component's argument buffer
    auto dest = params.claimNext();
    
    SmallVector<Address, 4> srcAddresses;
    int lastOperandNeeded = -1;
    for (auto &index : component.getSubscriptIndices()) {
      lastOperandNeeded = std::max(lastOperandNeeded, (int)index.Operand);
    }
    
    llvm::Value *offset;
    
    if (genericEnv) {
      // We'll copy over the generic environment after we copy in the indexes.
      offset = llvm::ConstantInt::get(IGM.SizeTy,
        IGM.getPointerSize().getValue() * requirements.size());

      // Bind the generic environment from the argument buffer.
      bindFromGenericRequirementsBuffer(IGF, requirements,
        Address(src, IGF.IGM.getPointerAlignment()),
        MetadataState::Complete,
        [&](CanType t) {
          return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
        });

    } else {
      offset = llvm::ConstantInt::get(IGM.SizeTy, 0);
    }
    
    // Figure out the offsets of the operands in the source buffer.
    for (int i = 0; i <= lastOperandNeeded; ++i) {
      auto ty = genericEnv
        ? genericEnv->mapTypeIntoContext(IGM.getSILModule(),
                                         operands[i].LoweredType)
        : operands[i].LoweredType;
      
      auto &ti = IGM.getTypeInfo(ty);

      if (i != 0 || genericEnv) {
        auto alignMask = ti.getAlignmentMask(IGF, ty);
        auto notAlignMask = IGF.Builder.CreateNot(alignMask);
        offset = IGF.Builder.CreateAdd(offset, alignMask);
        offset = IGF.Builder.CreateAnd(offset, notAlignMask);
      }
      
      auto ptr = IGF.Builder.CreateInBoundsGEP(src, offset);
      auto addr = ti.getAddressForPointer(IGF.Builder.CreateBitCast(
        ptr, ti.getStorageType()->getPointerTo()));
      srcAddresses.push_back(addr);
      
      auto size = ti.getSize(IGF, ty);
      offset = IGF.Builder.CreateAdd(offset, size);
    }
    
    offset = llvm::ConstantInt::get(IGM.SizeTy, 0);
    
    // Transfer the operands we want into the destination buffer.
    for (unsigned i : indices(component.getSubscriptIndices())) {
      auto &index = component.getSubscriptIndices()[i];
      
      auto ty = genericEnv
        ? genericEnv->mapTypeIntoContext(IGM.getSILModule(),
                                         index.LoweredType)
        : index.LoweredType;
      
      auto &ti = IGM.getTypeInfo(ty);
      
      if (i != 0) {
        auto alignMask = ti.getAlignmentMask(IGF, ty);
        auto notAlignMask = IGF.Builder.CreateNot(alignMask);
        offset = IGF.Builder.CreateAdd(offset, alignMask);
        offset = IGF.Builder.CreateAnd(offset, notAlignMask);
      }
      
      auto ptr = IGF.Builder.CreateInBoundsGEP(dest, offset);
      auto destAddr = ti.getAddressForPointer(IGF.Builder.CreateBitCast(
        ptr, ti.getStorageType()->getPointerTo()));
      
      // The last component using an operand can move the value out of the
      // buffer.
      if (&component == operands[index.Operand].LastUser) {
        ti.initializeWithTake(IGF, destAddr, srcAddresses[index.Operand], ty,
                              false);
      } else {
        ti.initializeWithCopy(IGF, destAddr, srcAddresses[index.Operand], ty,
                              false);
      }
      auto size = ti.getSize(IGF, ty);
      offset = IGF.Builder.CreateAdd(offset, size);
    }
    
    // Transfer the generic environment.
    // External components don't need to store the key path environment (and
    // can't), since they need to already have enough information to function
    // independently of any context using the component.
    if (genericEnv) {
      auto destGenericEnv = dest;
      if (!component.getSubscriptIndices().empty()) {
        auto genericEnvAlignMask = llvm::ConstantInt::get(IGM.SizeTy,
          IGM.getPointerAlignment().getMaskValue());
        auto notGenericEnvAlignMask = IGF.Builder.CreateNot(genericEnvAlignMask);
        offset = IGF.Builder.CreateAdd(offset, genericEnvAlignMask);
        offset = IGF.Builder.CreateAnd(offset, notGenericEnvAlignMask);
        destGenericEnv = IGF.Builder.CreateInBoundsGEP(dest, offset);
      }
      
      auto align = IGM.getPointerAlignment().getValue();
      IGF.Builder.CreateMemCpy(destGenericEnv, align, src, align,
                         IGM.getPointerSize().getValue() * requirements.size());
    }
    IGF.Builder.CreateRetVoid();
  }
  return initFn;
}

/// Emit a generator function to produce a reference to a type or
/// protocol conformance metadata record.
/// TODO: It would be much better to emit typeref strings and use runtime
/// demangling here.
static llvm::Constant *
emitGeneratorForKeyPath(IRGenModule &IGM,
                        StringRef name, CanType type, llvm::Type *returnType,
                        GenericEnvironment *genericEnv,
                        ArrayRef<GenericRequirement> requirements,
                        llvm::function_ref<void(IRGenFunction&,CanType)> emit) {

  return IGM.getAddrOfStringForMetadataRef(name, /*alignment=*/2,
      /*shouldSetLowBit=*/true,
      [&](ConstantInitBuilder &B) {
        // Build a stub that loads the necessary bindings from the key path's
        // argument buffer then fetches the metadata.
        auto fnTy = llvm::FunctionType::get(returnType,
                                            {IGM.Int8PtrTy}, /*vararg*/ false);
        auto accessorThunk =
          llvm::Function::Create(fnTy, llvm::GlobalValue::PrivateLinkage,
                                 name, IGM.getModule());
        accessorThunk->setAttributes(IGM.constructInitialAttributes());
        {
          IRGenFunction IGF(IGM, accessorThunk);
          if (IGM.DebugInfo)
            IGM.DebugInfo->emitArtificialFunction(IGF, accessorThunk);

          if (type->hasTypeParameter()) {
            auto bindingsBufPtr = IGF.collectParameters().claimNext();

            bindFromGenericRequirementsBuffer(IGF, requirements,
                Address(bindingsBufPtr, IGM.getPointerAlignment()),
                MetadataState::Complete,
                [&](CanType t) {
                  return genericEnv->mapTypeIntoContext(t)->getCanonicalType();
                });

            type = genericEnv->mapTypeIntoContext(type)->getCanonicalType();
          }
          emit(IGF, type);
        }

        // Form the mangled name with its relative reference.
        auto S = B.beginStruct();
        S.setPacked(true);
        S.add(llvm::ConstantInt::get(IGM.Int8Ty, 255));
        S.add(llvm::ConstantInt::get(IGM.Int8Ty, 9));
        S.addRelativeAddress(accessorThunk);

        // And a null terminator!
        S.addInt(IGM.Int8Ty, 0);

        return S.finishAndCreateFuture();
      });
}

static llvm::Constant *
emitMetadataGeneratorForKeyPath(IRGenModule &IGM,
                                CanType type,
                                GenericEnvironment *genericEnv,
                                ArrayRef<GenericRequirement> requirements) {
  // Produce a mangled name for the type.
  auto constant = IGM.getTypeRef(type, MangledTypeRefRole::Metadata);
  auto bitConstant = llvm::ConstantInt::get(IGM.IntPtrTy, 1);
  return llvm::ConstantExpr::getGetElementPtr(nullptr, constant, bitConstant);
}

static llvm::Constant *
emitWitnessTableGeneratorForKeyPath(IRGenModule &IGM,
                                    CanType type,
                                    ProtocolConformanceRef conformance,
                                    GenericEnvironment *genericEnv,
                                    ArrayRef<GenericRequirement> requirements) {
  CanGenericSignature genericSig;
  if (genericEnv)
    genericSig = genericEnv->getGenericSignature()->getCanonicalSignature();

  IRGenMangler mangler;
  std::string symbolName =
    mangler.mangleSymbolNameForKeyPathMetadata(
      "keypath_get_witness_table", genericSig, type, conformance);

  // TODO: Use the standard conformance accessor when there are no arguments
  // and the conformance accessor is defined.
  return emitGeneratorForKeyPath(IGM, symbolName, type,
    IGM.WitnessTablePtrTy,
    genericEnv, requirements,
    [&](IRGenFunction &IGF, CanType substType) {
      if (type->hasTypeParameter())
        conformance = conformance.subst(type,
          QueryInterfaceTypeSubstitutions(genericEnv),
          LookUpConformanceInSignature(*genericEnv->getGenericSignature()));
      auto ret = emitWitnessTableRef(IGF, substType, conformance);
      IGF.Builder.CreateRet(ret);
    });
}

static unsigned getClassFieldIndex(ClassDecl *classDecl, VarDecl *property) {
  SmallVector<ClassDecl *, 3> superclasses;
  for (auto *superDecl = classDecl; superDecl != nullptr;
       superDecl = superDecl->getSuperclassDecl()) {
    superclasses.push_back(superDecl);
  }

  std::reverse(superclasses.begin(), superclasses.end());

  unsigned index = 0;
  for (auto *superDecl : superclasses) {
    for (auto *other : superDecl->getStoredProperties()) {
      if (other == property)
        return index;
      index++;
    }
  }

  llvm_unreachable("Did not find stored property in class");
}

static void
emitKeyPathComponent(IRGenModule &IGM,
                     ConstantStructBuilder &fields,
                     const KeyPathPatternComponent &component,
                     bool isInstantiableOnce,
                     GenericEnvironment *genericEnv,
                     ArrayRef<GenericRequirement> requirements,
                     CanType baseTy,
                     ArrayRef<KeyPathIndexOperand> operands,
                     bool hasSubscriptIndices) {
  assert(fields.getNextOffsetFromGlobal() % Alignment(4) == Size(0)
         && "must be 32-bit-aligned here");

  SILType loweredBaseTy;
  GenericContextScope scope(IGM,
         genericEnv ? genericEnv->getGenericSignature()->getCanonicalSignature()
                    : nullptr);
  loweredBaseTy = IGM.getLoweredType(AbstractionPattern::getOpaque(),
                                     baseTy->getWithoutSpecifierType());
  switch (auto kind = component.getKind()) {
  case KeyPathPatternComponent::Kind::StoredProperty: {
    auto property = cast<VarDecl>(component.getStoredPropertyDecl());
    
    auto addFixedOffset = [&](bool isStruct, bool isLet,
                              llvm::Constant *offset) {
      if (auto offsetInt = dyn_cast_or_null<llvm::ConstantInt>(offset)) {
        auto offsetValue = offsetInt->getValue().getZExtValue();
        if (KeyPathComponentHeader::offsetCanBeInline(offsetValue)) {
          auto header = isStruct
            ? KeyPathComponentHeader
                ::forStructComponentWithInlineOffset(isLet, offsetValue)
            : KeyPathComponentHeader
                ::forClassComponentWithInlineOffset(isLet, offsetValue);
          fields.addInt32(header.getData());
          return;
        }
      }
      auto header = isStruct
        ? KeyPathComponentHeader::forStructComponentWithOutOfLineOffset(isLet)
        : KeyPathComponentHeader::forClassComponentWithOutOfLineOffset(isLet);
      fields.addInt32(header.getData());
      fields.add(llvm::ConstantExpr::getTruncOrBitCast(offset, IGM.Int32Ty));
    };
    
    // For a struct stored property, we may know the fixed offset of the field,
    // or we may need to fetch it out of the type's metadata at instantiation
    // time.
    if (auto theStruct = loweredBaseTy.getStructOrBoundGenericStruct()) {
      if (auto offset = emitPhysicalStructMemberFixedOffset(IGM,
                                                            loweredBaseTy,
                                                            property)) {
        // We have a known constant fixed offset.
        addFixedOffset(/*struct*/ true, property->isLet(), offset);
        break;
      }

      // If the offset isn't fixed, try instead to get the field offset out
      // of the type metadata at instantiation time.
      auto &metadataLayout = IGM.getMetadataLayout(theStruct);
      auto fieldOffset = metadataLayout.getStaticFieldOffset(property);

      auto header = KeyPathComponentHeader
        ::forStructComponentWithUnresolvedFieldOffset(property->isLet());
      fields.addInt32(header.getData());
      fields.addInt32(fieldOffset.getValue());
      break;
    }
    
    // For a class, we may know the fixed offset of a field at compile time,
    // or we may need to fetch it at instantiation time. Depending on the
    // ObjC-ness and resilience of the class hierarchy, there might be a few
    // different ways we need to go about this.
    if (loweredBaseTy.getClassOrBoundGenericClass()) {

      // Use the property's class type to determine the field access.
      auto propertyBaseDecl = property->getDeclContext()->getSelfClassDecl();
      auto currentBaseTy =
          loweredBaseTy.getASTType()->getSuperclassForDecl(propertyBaseDecl);
      assert(currentBaseTy->getClassOrBoundGenericClass() == propertyBaseDecl);
      loweredBaseTy =
          IGM.getLoweredType(AbstractionPattern::getOpaque(), currentBaseTy);

      switch (getClassFieldAccess(IGM, loweredBaseTy, property)) {
      case FieldAccess::ConstantDirect: {
        // Known constant fixed offset.
        auto offset = tryEmitConstantClassFragilePhysicalMemberOffset(IGM,
                                                                loweredBaseTy,
                                                                property);
        assert(offset && "no constant offset for ConstantDirect field?!");
        addFixedOffset(/*struct*/ false, property->isLet(), offset);
        break;
      }
      case FieldAccess::NonConstantDirect: {
        // A constant offset that's determined at class realization time.
        // We have to load the offset from a global ivar.
        auto header = KeyPathComponentHeader
          ::forClassComponentWithUnresolvedIndirectOffset(property->isLet());
        fields.addInt32(header.getData());
        auto offsetRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
          LinkEntity::forFieldOffset(property));
        fields.addRelativeAddress(offsetRef);
        break;
      }
      case FieldAccess::ConstantIndirect: {
        // An offset that depends on the instance's generic parameterization,
        // but whose field offset is at a known vtable offset.
        auto header = KeyPathComponentHeader
          ::forClassComponentWithUnresolvedFieldOffset(property->isLet());
        fields.addInt32(header.getData());
        auto fieldOffset =
          getClassFieldOffsetOffset(IGM,
                                    loweredBaseTy.getClassOrBoundGenericClass(),
                                    property);
        fields.addInt32(fieldOffset.getValue());
        break;
      }
      }
      break;
    }
    llvm_unreachable("not struct or class");
  }
  case KeyPathPatternComponent::Kind::GettableProperty:
  case KeyPathPatternComponent::Kind::SettableProperty: {
    // If the component references an external property, encode that in a
    // header before the local attempt header, so that we can consult the
    // external descriptor at instantiation time.
    if (auto externalDecl = component.getExternalDecl()) {
      SmallVector<llvm::Constant *, 4> externalSubArgs;
      auto componentSig = externalDecl->getInnermostDeclContext()
        ->getGenericSignatureOfContext();
      auto subs = component.getExternalSubstitutions();
      if (!subs.empty()) {
        enumerateGenericSignatureRequirements(
          componentSig->getCanonicalSignature(),
          [&](GenericRequirement reqt) {
            auto substType = reqt.TypeParameter.subst(subs)
              ->getCanonicalType();
            if (!reqt.Protocol) {
              // Type requirement.
              externalSubArgs.push_back(
                emitMetadataGeneratorForKeyPath(IGM, substType,
                                                genericEnv, requirements));
            } else {
              // Protocol requirement.
              auto conformance = subs.lookupConformance(
                           reqt.TypeParameter->getCanonicalType(), reqt.Protocol);
              externalSubArgs.push_back(
                emitWitnessTableGeneratorForKeyPath(IGM, substType,
                                                    *conformance,
                                                    genericEnv, requirements));
            }
          });
      }
      fields.addInt32(
        KeyPathComponentHeader::forExternalComponent(externalSubArgs.size())
          .getData());
      auto descriptor = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
        LinkEntity::forPropertyDescriptor(externalDecl));
      fields.addRelativeAddress(descriptor);
      for (auto *arg : externalSubArgs)
        fields.addRelativeAddress(arg);
    }
  
    // Encode the settability.
    bool settable = kind == KeyPathPatternComponent::Kind::SettableProperty;
    KeyPathComponentHeader::ComputedPropertyKind componentKind;
    if (settable) {
      componentKind = component.isComputedSettablePropertyMutating()
        ? KeyPathComponentHeader::SettableMutating
        : KeyPathComponentHeader::SettableNonmutating;
    } else {
      componentKind = KeyPathComponentHeader::GetOnly;
    }
    
    // Lower the id reference.
    auto id = component.getComputedPropertyId();
    KeyPathComponentHeader::ComputedPropertyIDKind idKind;
    llvm::Constant *idValue;
    KeyPathComponentHeader::ComputedPropertyIDResolution idResolution;
    switch (id.getKind()) {
    case KeyPathPatternComponent::ComputedPropertyId::Function: {
      idKind = KeyPathComponentHeader::Pointer;
      auto idRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
        LinkEntity::forSILFunction(id.getFunction(), false));
      
      idValue = idRef.getValue();
      // If we got an indirect reference, we'll need to resolve it at
      // instantiation time.
      idResolution = idRef.isIndirect()
        ? KeyPathComponentHeader::IndirectPointer
        : KeyPathComponentHeader::Resolved;
      break;
    }
    case KeyPathPatternComponent::ComputedPropertyId::DeclRef: {
      auto declRef = id.getDeclRef();
    
      // Foreign method refs identify using a selector
      // reference, which is doubly-indirected and filled in with a unique
      // pointer by dyld.
      if (declRef.isForeign) {
        assert(IGM.ObjCInterop && "foreign keypath component w/o objc interop?!");
        idKind = KeyPathComponentHeader::Pointer;
        // FIXME: In non-JIT mode, ideally we would just refer to the selector
        // reference variable here with an indirectpointer resolution,
        // but ld64 section coalescing on the __objc_sel section can break
        // relative references (and on some platforms, mach-o just doesn't
        // support the necessary relocations).
        // As a workaround, generate a stub function to resolve the selector.
        //
        // Note that we'd need to do this anyway in JIT mode because we would
        // need to unique the selector at runtime anyway.
        auto selectorName = IGM.getObjCSelectorName(declRef);
        llvm::Type *fnParams[] = {IGM.Int8PtrTy};
        auto fnTy = llvm::FunctionType::get(IGM.Int8PtrTy, fnParams, false);
        SmallString<32> fnName;
        fnName.append("keypath_get_selector_");
        fnName.append(selectorName);
        auto fn = cast<llvm::Function>(
          IGM.Module.getOrInsertFunction(fnName, fnTy));
        if (fn->empty()) {
          fn->setLinkage(llvm::Function::PrivateLinkage);
          IRGenFunction subIGF(IGM, fn);
          if (IGM.DebugInfo)
            IGM.DebugInfo->emitArtificialFunction(subIGF, fn);
          
          auto selectorValue = subIGF.emitObjCSelectorRefLoad(selectorName);
          subIGF.Builder.CreateRet(selectorValue);
        }
        
        idValue = fn;
        idResolution = KeyPathComponentHeader::FunctionCall;
      } else {
        if (auto overridden = declRef.getOverriddenVTableEntry())
          declRef = overridden;
        if (auto overridden = declRef.getOverriddenWitnessTableEntry())
          declRef = overridden;

        auto dc = declRef.getDecl()->getDeclContext();

        // We can use a method descriptor if we have a class or resilient
        // protocol.
        if (isa<ClassDecl>(dc) ||
            IGM.isResilient(cast<NominalTypeDecl>(dc),
                            ResilienceExpansion::Minimal)) {
          idKind = KeyPathComponentHeader::Pointer;
          auto idRef = IGM.getAddrOfLLVMVariableOrGOTEquivalent(
            LinkEntity::forMethodDescriptor(declRef));

          idValue = idRef.getValue();
          idResolution = idRef.isIndirect()
            ? KeyPathComponentHeader::IndirectPointer
            : KeyPathComponentHeader::Resolved;
          break;
        }
      
        idKind = KeyPathComponentHeader::VTableOffset;
        auto methodProto = cast<ProtocolDecl>(dc);
        auto &protoInfo = IGM.getProtocolInfo(methodProto,
                                              ProtocolInfoKind::Full);
        auto index = protoInfo.getFunctionIndex(
                             cast<AbstractFunctionDecl>(declRef.getDecl()));
        idValue = llvm::ConstantInt::get(IGM.SizeTy, -index.getValue());
        idResolution = KeyPathComponentHeader::Resolved;
      }
      break;
    }
    case KeyPathPatternComponent::ComputedPropertyId::Property:
      // Use the index of the stored property within the aggregate to key
      // the property.
      auto property = id.getProperty();
      idKind = KeyPathComponentHeader::StoredPropertyIndex;
      if (auto struc = baseTy->getStructOrBoundGenericStruct()) {
        // Scan the stored properties of the struct to find the index. We should
        // only ever use a struct field as a uniquing key from inside the
        // struct's own module, so this is OK.
        idResolution = KeyPathComponentHeader::Resolved;
        Optional<unsigned> structIdx;
        unsigned i = 0;
        for (auto storedProp : struc->getStoredProperties()) {
          if (storedProp == property) {
            structIdx = i;
            break;
          }
          ++i;
        }
        assert(structIdx && "not a stored property of the struct?!");
        idValue = llvm::ConstantInt::get(IGM.SizeTy, structIdx.getValue());
      } else if (auto *classDecl = baseTy->getClassOrBoundGenericClass()) {
        // TODO: This field index would require runtime resolution with Swift
        // native class resilience. We never directly access ObjC-imported
        // ivars so we can disregard ObjC ivar resilience for this computation
        // and start counting at the Swift native root.
        switch (getClassFieldAccess(IGM, loweredBaseTy, property)) {
        case FieldAccess::ConstantDirect:
        case FieldAccess::ConstantIndirect:
        case FieldAccess::NonConstantDirect:
          idResolution = KeyPathComponentHeader::Resolved;
          idValue = llvm::ConstantInt::get(IGM.SizeTy,
                                       getClassFieldIndex(classDecl, property));
          break;
        }
        
      } else {
        llvm_unreachable("neither struct nor class");
      }
      break;
    }
    
    auto header = KeyPathComponentHeader::forComputedProperty(componentKind,
                                     idKind, !isInstantiableOnce, idResolution);
    
    fields.addInt32(header.getData());
    switch (idKind) {
    case KeyPathComponentHeader::Pointer:
      // Use a relative offset to the referent.
      fields.addRelativeAddress(idValue);
      break;

    case KeyPathComponentHeader::VTableOffset:
    case KeyPathComponentHeader::StoredPropertyIndex:
      // Store the offset as an i32.
      fields.add(llvm::ConstantExpr::getTruncOrBitCast(idValue, IGM.Int32Ty));
      break;
    }

    // Push the accessors, possibly thunked to marshal generic environment.
    fields.addRelativeAddress(
      getAccessorForComputedComponent(IGM, component, Getter,
                                      genericEnv, requirements,
                                      hasSubscriptIndices));
    if (settable)
      fields.addRelativeAddress(
        getAccessorForComputedComponent(IGM, component, Setter,
                                        genericEnv, requirements,
                                        hasSubscriptIndices));

    if (!isInstantiableOnce) {
      // If there's generic context or subscript indexes, embed as
      // arguments in the component. Thunk the SIL-level accessors to give the
      // runtime implementation a polymorphically-callable interface.

      fields.addRelativeAddress(
        getLayoutFunctionForComputedComponent(IGM, component,
                                              genericEnv, requirements));
      
      // Set up a "witness table" for the component that handles copying,
      // destroying, equating, and hashing the captured contents of the
      // component.
      if (auto witnessTable =
            getWitnessTableForComputedComponent(IGM, component,
                                                genericEnv, requirements)) {
        fields.addRelativeAddress(witnessTable);
      } else {
        // If there are only generic parameters, we can use a prefab witness
        // table from the runtime. Leaving a null reference here will let
        // the runtime fill it in.
        fields.addInt32(0);
      }
      
      // Add an initializer function that copies generic arguments out of the
      // pattern argument buffer into the instantiated object.
      fields.addRelativeAddress(
        getInitializerForComputedComponent(IGM, component, operands,
                                           genericEnv, requirements));
    }
    break;
  }
  case KeyPathPatternComponent::Kind::OptionalChain:
    fields.addInt32(KeyPathComponentHeader::forOptionalChain().getData());
    break;
  case KeyPathPatternComponent::Kind::OptionalForce:
    fields.addInt32(KeyPathComponentHeader::forOptionalForce().getData());
    break;
  case KeyPathPatternComponent::Kind::OptionalWrap:
    fields.addInt32(KeyPathComponentHeader::forOptionalWrap().getData());
    break;
  }
}

llvm::Constant *
IRGenModule::getAddrOfKeyPathPattern(KeyPathPattern *pattern,
                                     SILLocation diagLoc) {
  // See if we already emitted this.
  auto found = KeyPathPatterns.find(pattern);
  if (found != KeyPathPatterns.end())
    return found->second;
  
  // Gather type arguments from the root and leaf types of the key path.
  auto rootTy = pattern->getRootType();
  auto valueTy = pattern->getValueType();

  // Check for parameterization, whether by subscript indexes or by the generic
  // environment. If there isn't any, we can instantiate the pattern in-place.
  bool isInstantiableOnce = pattern->getNumOperands() == 0
    && !pattern->getGenericSignature();

  // Collect the required parameters for the keypath's generic environment.
  SmallVector<GenericRequirement, 4> requirements;
  
  GenericEnvironment *genericEnv = nullptr;
  if (auto sig = pattern->getGenericSignature()) {
    genericEnv = sig->createGenericEnvironment();
    enumerateGenericSignatureRequirements(pattern->getGenericSignature(),
      [&](GenericRequirement reqt) { requirements.push_back(reqt); });
  }

  // Start building the key path pattern.
  ConstantInitBuilder builder(*this);
  ConstantStructBuilder fields = builder.beginStruct();
  fields.setPacked(true);
  // If the pattern has no parameterization, add a pointer to a cache variable
  // that can be used for the one-time initialization of the key path.
  if (isInstantiableOnce) {
    auto onceVar = new llvm::GlobalVariable(Module, OnceTy,
                                            /*constant*/ false,
                                            llvm::GlobalValue::PrivateLinkage,
                                            llvm::ConstantInt::get(OnceTy, 0),
                                            "keypath_once");
    onceVar->setAlignment(getPointerAlignment().getValue());
    fields.addRelativeAddress(onceVar);
  } else {
    fields.addInt32(0);
  }

  // Add the generic environment.
  fields.addRelativeAddressOrNull(
    getAddrOfGenericEnvironment(pattern->getGenericSignature()));
  // Store type references for the root and leaf.
  fields.addRelativeAddress(
    emitMetadataGeneratorForKeyPath(*this, rootTy, genericEnv, requirements));
  fields.addRelativeAddress(
    emitMetadataGeneratorForKeyPath(*this, valueTy, genericEnv, requirements));
  
  // Add a pointer to the ObjC KVC compatibility string, if there is one, or
  // null otherwise.
  if (!pattern->getObjCString().empty()) {
    auto objcString = getAddrOfGlobalString(pattern->getObjCString(),
                                            /*relatively addressed*/ true);
    fields.addRelativeAddress(objcString);
  } else {
    fields.addInt32(0);
  }
  
  // Leave a placeholder for the buffer header, since we need to know the full
  // buffer size to fill it in.
  auto headerPlaceholder = fields.addPlaceholderWithSize(Int32Ty);
  auto startOfKeyPathBuffer = fields.getNextOffsetFromGlobal();
  
  // Build out the components.
  auto baseTy = rootTy;
  
  // Collect the order and types of any captured index operands, which will
  // determine the layout of the buffer that gets passed to the initializer
  // for each component.
  SmallVector<KeyPathIndexOperand, 4> operands;
  operands.resize(pattern->getNumOperands());
  for (auto &component : pattern->getComponents()) {
    switch (component.getKind()) {
    case KeyPathPatternComponent::Kind::GettableProperty:
    case KeyPathPatternComponent::Kind::SettableProperty:
      for (auto &index : component.getSubscriptIndices()) {
        operands[index.Operand].LoweredType = index.LoweredType;
        operands[index.Operand].LastUser = &component;
      }
      break;
    case KeyPathPatternComponent::Kind::StoredProperty:
    case KeyPathPatternComponent::Kind::OptionalChain:
    case KeyPathPatternComponent::Kind::OptionalForce:
    case KeyPathPatternComponent::Kind::OptionalWrap:
      break;
    }
  }
  
  for (unsigned i : indices(pattern->getComponents())) {
    auto &component = pattern->getComponents()[i];
    
    emitKeyPathComponent(*this, fields, component, isInstantiableOnce,
                         genericEnv, requirements,
                         baseTy, operands,
                         !component.getSubscriptIndices().empty());
    
    // For all but the last component, we pack in the type of the component.
    if (i + 1 != pattern->getComponents().size()) {
      fields.addRelativeAddress(
        emitMetadataGeneratorForKeyPath(*this, component.getComponentType(),
                                        genericEnv, requirements));
    }
    baseTy = component.getComponentType();
  }
  
  // Save the total size of the buffer.
  Size componentSize = fields.getNextOffsetFromGlobal()
    - startOfKeyPathBuffer;
  
  // We now have enough info to build the header.
  KeyPathBufferHeader header(componentSize.getValue(), isInstantiableOnce,
                             /*reference prefix*/ false);
  // Add the header, followed by the components.
  fields.fillPlaceholder(headerPlaceholder,
                         llvm::ConstantInt::get(Int32Ty, header.getData()));
  
  // Create the global variable.
  // TODO: The pattern could be immutable if
  // it isn't instantiable in place, and if we made the type metadata accessor
  // references private, it could go in true-const memory.
  auto patternVar = fields.finishAndCreateGlobal("keypath",
                                          getPointerAlignment(),
                                          /*constant*/ false,
                                          llvm::GlobalVariable::PrivateLinkage);
  setTrueConstGlobal(patternVar);
  KeyPathPatterns.insert({pattern, patternVar});
  return patternVar;
}

void IRGenModule::emitSILProperty(SILProperty *prop) {
  if (prop->isTrivial()) {
    ++NumTrivialPropertyDescriptors;
    // All trivial property descriptors can share a single definition in the
    // translation unit.
    if (!TheTrivialPropertyDescriptor) {
      // Emit a definition if we don't have one yet.
      ConstantInitBuilder builder(*this);
      ConstantStructBuilder fields = builder.beginStruct();
      fields.addInt32(
        _SwiftKeyPathComponentHeader_TrivialPropertyDescriptorMarker);
      auto var = cast<llvm::GlobalVariable>(
        getAddrOfPropertyDescriptor(prop->getDecl(),
                                    fields.finishAndCreateFuture()));
      var->setConstant(true);
      var->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
      var->setAlignment(4);
      
      TheTrivialPropertyDescriptor = var;
    } else {
      auto entity = LinkEntity::forPropertyDescriptor(prop->getDecl());
      auto linkInfo = LinkInfo::get(*this, entity, ForDefinition);
      llvm::GlobalAlias::create(linkInfo.getLinkage(),
                                linkInfo.getName(),
                                TheTrivialPropertyDescriptor);
    }
    return;
  }

  ++NumNonTrivialPropertyDescriptors;

  ConstantInitBuilder builder(*this);
  ConstantStructBuilder fields = builder.beginStruct();
  fields.setPacked(true);
  
  bool hasSubscriptIndices = false;
  bool isInstantiableInPlace = true;
  if (prop->getDecl()->getInnermostDeclContext()->isGenericContext()) {
    isInstantiableInPlace = false;
  }
  
  if (auto subscript = dyn_cast<SubscriptDecl>(prop->getDecl())) {
    hasSubscriptIndices = subscript->getIndices()->size() != 0;
    isInstantiableInPlace &= !hasSubscriptIndices;
  }
  
  auto genericEnv = prop->getDecl()->getInnermostDeclContext()
                        ->getGenericEnvironmentOfContext();
  SmallVector<GenericRequirement, 4> requirements;
  CanGenericSignature genericSig;
  if (genericEnv) {
    genericSig = prop->getDecl()->getInnermostDeclContext()
                                ->getGenericSignatureOfContext()
                                ->getCanonicalSignature();
    enumerateGenericSignatureRequirements(genericSig,
      [&](GenericRequirement reqt) { requirements.push_back(reqt); });
  }
  
  emitKeyPathComponent(*this, fields, *prop->getComponent(),
                       isInstantiableInPlace, genericEnv, requirements,
                       prop->getDecl()->getInnermostDeclContext()
                                      ->getInnermostTypeContext()
                                      ->getSelfInterfaceType()
                                      ->getCanonicalType(genericSig),
                       {},
                       hasSubscriptIndices);
  
  auto var = cast<llvm::GlobalVariable>(
    getAddrOfPropertyDescriptor(prop->getDecl(),
                                fields.finishAndCreateFuture()));
  var->setConstant(true);
  var->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
  var->setAlignment(4);
}
