//===--- GenObjC.cpp - Objective-C interaction ----------------------------===//
//
// 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 bridging to Objective-C.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/InlineAsm.h"

#include "clang/AST/ASTContext.h"
#include "clang/Basic/CharInfo.h"
#include "clang/CodeGen/CGFunctionInfo.h"

#include "swift/AST/Decl.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/Types.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/Demangling/ManglingMacros.h"
#include "swift/IRGen/Linking.h"
#include "swift/SIL/SILModule.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"

#include "CallEmission.h"
#include "ConstantBuilder.h"
#include "Explosion.h"
#include "GenCall.h"
#include "GenClass.h"
#include "GenFunc.h"
#include "GenHeap.h"
#include "GenMeta.h"
#include "GenProto.h"
#include "GenType.h"
#include "HeapTypeInfo.h"
#include "IRGenDebugInfo.h"
#include "IRGenFunction.h"
#include "IRGenModule.h"
#include "NativeConventionSchema.h"
#include "ScalarTypeInfo.h"
#include "StructLayout.h"

#include "GenObjC.h"

using namespace swift;
using namespace irgen;

void IRGenFunction::emitObjCStrongRelease(llvm::Value *value) {
  // Get an appropriately-cast function pointer.
  auto fn = IGM.getObjCReleaseFn();
  auto cc = IGM.C_CC;
  if (auto fun = dyn_cast<llvm::Function>(fn))
    cc = fun->getCallingConv();

  if (value->getType() != IGM.ObjCPtrTy) {
    auto fnTy = llvm::FunctionType::get(IGM.VoidTy, value->getType(),
                                        false)->getPointerTo();
    fn = llvm::ConstantExpr::getBitCast(fn, fnTy);
  }

  auto call = Builder.CreateCall(fn, value);
  call->setCallingConv(cc);
  call->setDoesNotThrow();
}

/// Given a function of type %objc* (%objc*)*, cast it as appropriate
/// to be used with values of type T.
static llvm::Constant *getCastOfRetainFn(IRGenModule &IGM,
                                         llvm::Constant *fn,
                                         llvm::Type *valueTy) {
#ifndef NDEBUG
  auto origFnTy = cast<llvm::FunctionType>(fn->getType()->getPointerElementType());
  assert(origFnTy->getReturnType() == IGM.ObjCPtrTy);
  assert(origFnTy->getNumParams() == 1);
  assert(origFnTy->getParamType(0) == IGM.ObjCPtrTy);
  assert(isa<llvm::PointerType>(valueTy) ||
         valueTy == IGM.IntPtrTy); // happens with optional types
#endif
  if (valueTy == IGM.ObjCPtrTy)
    return fn;

  auto fnTy = llvm::FunctionType::get(valueTy, valueTy, false);
  return llvm::ConstantExpr::getBitCast(fn, fnTy->getPointerTo(0));
}

void IRGenFunction::emitObjCStrongRetain(llvm::Value *v) {
  emitObjCRetainCall(v);
}

llvm::Value *IRGenFunction::emitObjCRetainCall(llvm::Value *value) {
  // Get an appropriately cast function pointer.
  auto fn = IGM.getObjCRetainFn();
  auto cc = IGM.C_CC;
  if (auto fun = dyn_cast<llvm::Function>(fn))
    cc = fun->getCallingConv();
  fn = getCastOfRetainFn(IGM, fn, value->getType());

  auto call = Builder.CreateCall(fn, value);
  call->setCallingConv(cc);
  call->setDoesNotThrow();
  return call;
}

llvm::Value *IRGenFunction::emitObjCAutoreleaseCall(llvm::Value *val) {
  if (val->getType()->isPointerTy())
    val = Builder.CreateBitCast(val, IGM.ObjCPtrTy);
  else
    val = Builder.CreateIntToPtr(val, IGM.ObjCPtrTy);
  
  auto call = Builder.CreateCall(IGM.getObjCAutoreleaseFn(), val);
  call->setDoesNotThrow();
  return call;
}

llvm::InlineAsm *IRGenModule::getObjCRetainAutoreleasedReturnValueMarker() {
  // Check to see if we've already computed the market.  Note that we
  // might have cached a null marker, and that's fine.
  auto &cache = ObjCRetainAutoreleasedReturnValueMarker;
  if (cache.hasValue())
    return cache.getValue();

  // Ask the target for the string.
  StringRef asmString = TargetInfo.ObjCRetainAutoreleasedReturnValueMarker;

  // If the string is empty, just leave, remembering that we did all this.
  if (asmString.empty()) {
    cache = nullptr;
    return nullptr;
  }

  // If we're emitting optimized code, record the string in the module
  // and let the late ARC pass insert it, but don't generate any calls
  // right now.
  if (IRGen.Opts.shouldOptimize()) {
    llvm::NamedMDNode *metadata =
      Module.getOrInsertNamedMetadata(
                            "clang.arc.retainAutoreleasedReturnValueMarker");
    assert(metadata->getNumOperands() <= 1);
    if (metadata->getNumOperands() == 0) {
      auto *string = llvm::MDString::get(LLVMContext, asmString);
      metadata->addOperand(llvm::MDNode::get(LLVMContext, string));
    }

    cache = nullptr;

  // Otherwise, create the module
  } else {
    llvm::FunctionType *type =
      llvm::FunctionType::get(VoidTy, /*variadic*/false);
    cache = llvm::InlineAsm::get(type, asmString, "", /*sideeffects*/ true);
  }

  return cache.getValue();
}

/// Reclaim an autoreleased return value.
llvm::Value *irgen::emitObjCRetainAutoreleasedReturnValue(IRGenFunction &IGF,
                                                          llvm::Value *value) {
  // Call the inline-assembly marker if we need one.
  if (auto marker = IGF.IGM.getObjCRetainAutoreleasedReturnValueMarker()) {
    IGF.Builder.CreateAsmCall(marker, {});
  }

  auto fn = IGF.IGM.getObjCRetainAutoreleasedReturnValueFn();

  // We don't want to cast the function here because it interferes with
  // LLVM's ability to recognize and special-case this function.
  // Note that the parameter and result must also have type i8*.
  llvm::Type *valueType = value->getType();
  if (isa<llvm::PointerType>(valueType)) {
    value = IGF.Builder.CreateBitCast(value, IGF.IGM.Int8PtrTy);
  } else {
    value = IGF.Builder.CreateIntToPtr(value, IGF.IGM.Int8PtrTy);
  }

  auto call = IGF.Builder.CreateCall(fn, value);
  call->setDoesNotThrow();

  const llvm::Triple &triple = IGF.IGM.Context.LangOpts.Target;
  if (triple.getArch() == llvm::Triple::x86_64) {
    // Don't tail call objc_retainAutoreleasedReturnValue. This blocks the
    // autoreleased return optimization.
    // callq  0x01ec08 ; symbol stub for: objc_msgSend
    // movq   %rax, %rdi
    // popq   %rbp  ;<== Blocks the handshake from objc_autoreleaseReturnValue
    // jmp    0x01ec20 ; symbol stub for: objc_retainAutoreleasedReturnValue
    call->setTailCallKind(llvm::CallInst::TCK_NoTail);
  }

  llvm::Value *result = call;
  if (isa<llvm::PointerType>(valueType)) {
    result = IGF.Builder.CreateBitCast(result, valueType);
  } else {
    result = IGF.Builder.CreatePtrToInt(result, valueType);
  }
  return result;
}

/// Autorelease a return value.
llvm::Value *irgen::emitObjCAutoreleaseReturnValue(IRGenFunction &IGF,
                                                   llvm::Value *value) {
  auto fn = IGF.IGM.getObjCAutoreleaseReturnValueFn();
  fn = getCastOfRetainFn(IGF.IGM, fn, value->getType());

  auto call = IGF.Builder.CreateCall(fn, value);
  call->setDoesNotThrow();
  call->setTailCall(); // force tail calls at -O0
  return call;
}

namespace {
  /// A type-info implementation suitable for Builtin.UnknownObject.
  class UnknownTypeInfo : public HeapTypeInfo<UnknownTypeInfo> {
  public:
    UnknownTypeInfo(llvm::PointerType *storageType, Size size,
                 SpareBitVector spareBits, Alignment align)
      : HeapTypeInfo(storageType, size, spareBits, align) {
    }

    /// Builtin.UnknownObject requires ObjC reference-counting.
    ReferenceCounting getReferenceCounting() const {
      return ReferenceCounting::Unknown;
    }
  };
} // end anonymous namespace

const LoadableTypeInfo *TypeConverter::convertBuiltinUnknownObject() {
  // UnknownObject is only interestingly different from NativeObject on
  // platforms with ObjC interop.
  if (IGM.Context.LangOpts.EnableObjCInterop) {
    return new UnknownTypeInfo(IGM.ObjCPtrTy, IGM.getPointerSize(),
                               IGM.getHeapObjectSpareBits(),
                               IGM.getPointerAlignment());
  }
  
  // Without ObjC interop, UnknownObject handles just like a NativeObject.
  return convertBuiltinNativeObject();
}

namespace {
  /// A type info implementation for BridgeObject
  class BridgeObjectTypeInfo : public HeapTypeInfo<BridgeObjectTypeInfo> {
  public:
    BridgeObjectTypeInfo(llvm::PointerType *storageType, Size size,
                 SpareBitVector spareBits, Alignment align)
      : HeapTypeInfo(storageType, size, spareBits, align) {
    }

    /// Builtin.BridgeObject uses its own specialized refcounting implementation.
    ReferenceCounting getReferenceCounting() const {
      return ReferenceCounting::Bridge;
    }
    
    // BridgeObject exposes only null as an extra inhabitant for enum layout.
    // Other representations are reserved for future use by the stdlib.
    
    bool mayHaveExtraInhabitants(IRGenModule &IGM) const override {
      return true;
    }
    unsigned getFixedExtraInhabitantCount(IRGenModule &IGM) const override {
      return 1;
    }
    APInt getFixedExtraInhabitantValue(IRGenModule &IGM,
                                       unsigned bits,
                                       unsigned index) const override {
      return APInt(bits, 0);
    }
    llvm::Value *getExtraInhabitantIndex(IRGenFunction &IGF, Address src,
                                         SILType T) const override {
      src = IGF.Builder.CreateBitCast(src, IGF.IGM.SizeTy->getPointerTo());
      auto val = IGF.Builder.CreateLoad(src);
      auto isNonzero = IGF.Builder.CreateICmpNE(val,
                                    llvm::ConstantInt::get(IGF.IGM.SizeTy, 0));
      // We either have extra inhabitant 0 or no extra inhabitant (-1).
      // Conveniently, this is just a sext i1 -> i32 away.
      return IGF.Builder.CreateSExt(isNonzero, IGF.IGM.Int32Ty);
    }
    void storeExtraInhabitant(IRGenFunction &IGF, llvm::Value *index,
                              Address dest, SILType T) const override {
      // There's only one extra inhabitant, 0.
      dest = IGF.Builder.CreateBitCast(dest, IGF.IGM.SizeTy->getPointerTo());
      IGF.Builder.CreateStore(llvm::ConstantInt::get(IGF.IGM.SizeTy, 0), dest);
    }
  };
} // end anonymous namespace


const LoadableTypeInfo *TypeConverter::convertBuiltinBridgeObject() {
  return new BridgeObjectTypeInfo(IGM.BridgeObjectPtrTy, IGM.getPointerSize(),
      SpareBitVector::getConstant(IGM.getPointerSize().getValueInBits(), false),
                                  IGM.getPointerAlignment());
}

const TypeInfo &IRGenModule::getObjCClassPtrTypeInfo() {
  return Types.getObjCClassPtrTypeInfo();
}

const LoadableTypeInfo &TypeConverter::getObjCClassPtrTypeInfo() {
  // ObjC class pointers look like unmanaged (untagged) object references.
  if (ObjCClassPtrTI) return *ObjCClassPtrTI;
  ObjCClassPtrTI =
    createUnmanagedStorageType(IGM.ObjCClassPtrTy);
  ObjCClassPtrTI->NextConverted = FirstType;
  FirstType = ObjCClassPtrTI;
  return *ObjCClassPtrTI;
}

/// Get or create a global Objective-C method name.  Always returns an i8*.
llvm::Constant *IRGenModule::getAddrOfObjCMethodName(StringRef selector) {
  // Check whether this selector already exists.
  auto &entry = ObjCMethodNames[selector];
  if (entry) return entry;

  // If not, create it.  This implicitly adds a trailing null.
  auto init = llvm::ConstantDataArray::getString(LLVMContext, selector);
  auto global = new llvm::GlobalVariable(Module, init->getType(), false,
                                         llvm::GlobalValue::PrivateLinkage,
                                         init,
                          llvm::Twine("\01L_selector_data(") + selector + ")");
  SetCStringLiteralSection(global, ObjCLabelType::MethodVarName);
  global->setAlignment(1);
  addCompilerUsedGlobal(global);

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

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

/// Get or create an Objective-C selector reference.  Always returns
/// an i8**.  The design is that the compiler will emit a load of this
/// pointer, and the linker will ensure that that pointer is unique.
llvm::Constant *IRGenModule::getAddrOfObjCSelectorRef(StringRef selector) {
  // Check whether a reference for this selector already exists.
  auto &entry = ObjCSelectorRefs[selector];
  if (entry) return entry;

  // If not, create it.  The initializer is just a pointer to the
  // method name.  Note that the label here is unimportant, so we
  // choose something descriptive to make the IR readable.
  auto init = getAddrOfObjCMethodName(selector);
  auto global = new llvm::GlobalVariable(Module, init->getType(), false,
                                         llvm::GlobalValue::PrivateLinkage,
                                         init,
                                llvm::Twine("\01L_selector(") + selector + ")");
  global->setExternallyInitialized(true);
  global->setAlignment(getPointerAlignment().getValue());

  // This section name is magical for the Darwin static and dynamic linkers.
  global->setSection(GetObjCSectionName("__objc_selrefs",
                                        "literal_pointers,no_dead_strip"));

  // Make sure that this reference does not get optimized away.
  addCompilerUsedGlobal(global);

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

/// Get or create an ObjC protocol record. Always returns an i8*. We lazily
/// create ObjC protocol_t records for protocols, storing references to the
/// record into the __objc_protolist and __objc_protorefs sections to be
/// fixed up by the runtime.
///
/// It is not correct to use this value as a Protocol* reference directly. The
/// ObjC runtime requires protocol references to be loaded from an
/// indirect variable, the address of which is given by
/// getAddrOfObjCProtocolRef.
llvm::Constant *
IRGenModule::getAddrOfObjCProtocolRecord(ProtocolDecl *proto,
                                         ForDefinition_t forDefinition) {
  return const_cast<llvm::Constant*>
    (cast<llvm::Constant>(getObjCProtocolGlobalVars(proto).record));
}

/// Get or create an ObjC protocol reference. Always returns an i8**. We lazily
/// create ObjC protocol_t records for protocols, storing references to the
/// record into the __objc_protolist and __objc_protorefs sections to be
/// fixed up by the runtime.
llvm::Constant *IRGenModule::getAddrOfObjCProtocolRef(ProtocolDecl *proto,
                                               ForDefinition_t forDefinition) {
  return const_cast<llvm::Constant*>
    (cast<llvm::Constant>(getObjCProtocolGlobalVars(proto).ref));
}

IRGenModule::ObjCProtocolPair
IRGenModule::getObjCProtocolGlobalVars(ProtocolDecl *proto) {
  // See whether we already emitted this protocol reference.
  auto found = ObjCProtocols.find(proto);
  if (found != ObjCProtocols.end()) {
    return found->second;
  }
  
  // Create a placeholder protocol record.
  llvm::Constant *protocolRecord =
    new llvm::GlobalVariable(Module, Int8Ty, /*constant*/ false,
                             llvm::GlobalValue::PrivateLinkage, nullptr);
  LazyObjCProtocolDefinitions.push_back(proto);

  // Introduce a variable to label the protocol.
  llvm::SmallString<64> nameBuffer;
  StringRef protocolName = proto->getObjCRuntimeName(nameBuffer);
  auto *protocolLabel
    = new llvm::GlobalVariable(Module, Int8PtrTy,
                               /*constant*/ false,
                               llvm::GlobalValue::WeakAnyLinkage,
                               protocolRecord,
                               llvm::Twine("\01l_OBJC_LABEL_PROTOCOL_$_")
                                 + protocolName);
  protocolLabel->setAlignment(getPointerAlignment().getValue());
  protocolLabel->setVisibility(llvm::GlobalValue::HiddenVisibility);
  protocolLabel->setSection(GetObjCSectionName("__objc_protolist",
                                               "coalesced,no_dead_strip"));

  // Introduce a variable to reference the protocol.
  auto *protocolRef =
      new llvm::GlobalVariable(Module, Int8PtrTy, /*constant*/ false,
                               llvm::GlobalValue::WeakAnyLinkage,
                               protocolRecord,
                               llvm::Twine("\01l_OBJC_PROTOCOL_REFERENCE_$_") + protocolName);
  protocolRef->setAlignment(getPointerAlignment().getValue());
  protocolRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
  protocolRef->setSection(GetObjCSectionName("__objc_protorefs",
                                             "coalesced,no_dead_strip"));

  ObjCProtocolPair pair{protocolRecord, protocolRef};
  ObjCProtocols.insert({proto, pair});
  
  return pair;
}

void IRGenModule::emitLazyObjCProtocolDefinition(ProtocolDecl *proto) {
  // Emit the real definition.
  auto record = cast<llvm::GlobalVariable>(emitObjCProtocolData(*this, proto));

  // Find the placeholder.  It should always still be a placeholder,
  // because it was created as an anonymous symbol and nobody should
  // ever be randomly messing with those.
  auto placeholder =
    cast<llvm::GlobalVariable>(ObjCProtocols.find(proto)->second.record);

  // Move the new record to the placeholder's position.
  Module.getGlobalList().remove(record);
  Module.getGlobalList().insertAfter(placeholder->getIterator(), record);

  // Replace and destroy the placeholder.
  placeholder->replaceAllUsesWith(
                            llvm::ConstantExpr::getBitCast(record, Int8PtrTy));
  placeholder->eraseFromParent();
}

void IRGenModule::emitLazyObjCProtocolDefinitions() {
  // Emit any lazy ObjC protocol definitions we require.  Try to do
  // this in the order in which we needed them, since they can require
  // other protocol definitions recursively.
  for (size_t i = 0; i != LazyObjCProtocolDefinitions.size(); ++i) {
    ProtocolDecl *protocol = LazyObjCProtocolDefinitions[i];
    emitLazyObjCProtocolDefinition(protocol);
  }
}

namespace {
  class Selector {
    
    llvm::SmallString<80> Buffer;
    StringRef Text;

  public:

    static constexpr struct ForGetter_t { } ForGetter{};
    static constexpr struct ForSetter_t { } ForSetter{};

#define FOREACH_FAMILY(FAMILY)         \
    FAMILY(Alloc, "alloc")             \
    FAMILY(Copy, "copy")               \
    FAMILY(Init, "init")               \
    FAMILY(MutableCopy, "mutableCopy") \
    FAMILY(New, "new")

    // Note that these are in parallel with 'prefixes', below.
    enum class Family {
      None,
#define GET_LABEL(LABEL, PREFIX) LABEL,
      FOREACH_FAMILY(GET_LABEL)
#undef GET_LABEL
    };
    
    Selector() = default;

    Selector(FuncDecl *method) {
      Text = method->getObjCSelector().getString(Buffer);
    }
    
    Selector(ConstructorDecl *ctor) {
      Text = ctor->getObjCSelector().getString(Buffer);
    }
    
    Selector(ValueDecl *methodOrCtorOrDtor) {
      if (auto *method = dyn_cast<FuncDecl>(methodOrCtorOrDtor)) {
        Text = method->getObjCSelector().getString(Buffer);
      } else if (auto *ctor = dyn_cast<ConstructorDecl>(methodOrCtorOrDtor)) {
        Text = ctor->getObjCSelector().getString(Buffer);
      } else if (isa<DestructorDecl>(methodOrCtorOrDtor)) {
        Text = "dealloc";
      } else {
        llvm_unreachable("property or subscript selector should be generated "
                         "using ForGetter or ForSetter constructors");
      }
    }
    
    Selector(AbstractStorageDecl *asd, ForGetter_t) {
      Text = asd->getObjCGetterSelector().getString(Buffer);
    }

    Selector(AbstractStorageDecl *asd, ForSetter_t) {
      Text = asd->getObjCSetterSelector().getString(Buffer);
    }

    Selector(SILDeclRef ref) {
      switch (ref.kind) {
      case SILDeclRef::Kind::DefaultArgGenerator:
      case SILDeclRef::Kind::StoredPropertyInitializer:
      case SILDeclRef::Kind::EnumElement:
      case SILDeclRef::Kind::GlobalAccessor:
      case SILDeclRef::Kind::GlobalGetter:
        llvm_unreachable("Method does not have a selector");

      case SILDeclRef::Kind::Destroyer:
      case SILDeclRef::Kind::Deallocator:
        Text = "dealloc";
        break;
          
      case SILDeclRef::Kind::Func:
        Text = cast<FuncDecl>(ref.getDecl())->getObjCSelector()
                 .getString(Buffer);
        break;

      case SILDeclRef::Kind::Allocator:
      case SILDeclRef::Kind::Initializer:
        Text = cast<ConstructorDecl>(ref.getDecl())->getObjCSelector()
                 .getString(Buffer);
        break;

      case SILDeclRef::Kind::IVarInitializer:
        Text = ".cxx_construct";
        break;

      case SILDeclRef::Kind::IVarDestroyer:
        Text = ".cxx_destruct";
        break;
      }
    }

    StringRef str() const {
      return Text;
    }

    /// Return the family string of this selector.
    Family getFamily() const {
      StringRef text = str();
      while (!text.empty() && text[0] == '_') text = text.substr(1);

#define CHECK_PREFIX(LABEL, PREFIX) \
      if (hasPrefix(text, PREFIX)) return Family::LABEL;
      FOREACH_FAMILY(CHECK_PREFIX)
#undef CHECK_PREFIX

      return Family::None;
    }

  private:
    /// Does the given selector start with the given string as a
    /// prefix, in the sense of the selector naming conventions?
    static bool hasPrefix(StringRef text, StringRef prefix) {
      if (!text.startswith(prefix)) return false;
      if (text.size() == prefix.size()) return true;
      assert(text.size() > prefix.size());
      return !clang::isLowercase(text[prefix.size()]);
    }

#undef FOREACH_FAMILY
  };
} // end anonymous namespace

llvm::Constant *IRGenModule::getAddrOfObjCSelectorRef(SILDeclRef method) {
  assert(method.isForeign);
  return getAddrOfObjCSelectorRef(Selector(method).str());
}

static llvm::Value *emitSuperArgument(IRGenFunction &IGF,
                                      bool isInstanceMethod,
                                      llvm::Value *selfValue,
                                      CanType searchClass) {
  // Allocate an objc_super struct.
  Address super = IGF.createAlloca(IGF.IGM.ObjCSuperStructTy,
                                   IGF.IGM.getPointerAlignment(),
                                   "objc_super");
  // TODO: Track lifetime markers for function args.
  llvm::Value *self = IGF.Builder.CreateBitCast(selfValue,
                                                IGF.IGM.ObjCPtrTy);
  
  // Generate the search class object reference.
  llvm::Value *searchValue;
  if (isInstanceMethod) {
    searchValue = emitClassHeapMetadataRef(IGF, searchClass,
                                           MetadataValueType::ObjCClass,
                                           /*allow uninitialized*/ true);
  } else {
    searchClass = cast<MetatypeType>(searchClass).getInstanceType();
    ClassDecl *searchClassDecl = searchClass.getClassOrBoundGenericClass();
    if (doesClassMetadataRequireDynamicInitialization(IGF.IGM, searchClassDecl)) {
      searchValue = emitClassHeapMetadataRef(IGF, searchClass,
                                             MetadataValueType::ObjCClass,
                                             /*allow uninitialized*/ true);
      searchValue = emitLoadOfObjCHeapMetadataRef(IGF, searchValue);
      searchValue = IGF.Builder.CreateBitCast(searchValue, IGF.IGM.ObjCClassPtrTy);
    } else {
      searchValue = IGF.IGM.getAddrOfMetaclassObject(searchClassDecl,
                                                     NotForDefinition);
    }
  }
  
  // Store the receiver and class to the struct.
  Address selfAddr = IGF.Builder.CreateStructGEP(super, 0, Size(0));
  IGF.Builder.CreateStore(self, selfAddr);

  Address searchAddr =
    IGF.Builder.CreateStructGEP(super, 1, IGF.IGM.getPointerSize());
  IGF.Builder.CreateStore(searchValue, searchAddr);
  
  // Pass a pointer to the objc_super struct to the messenger.
  // Project the ownership semantics of 'self' to the super argument.
  return super.getAddress();
}

static llvm::FunctionType *getMsgSendSuperTy(IRGenModule &IGM,
                                             llvm::FunctionType *fnTy,
                                             bool indirectResult) {
  SmallVector<llvm::Type*, 4> args(fnTy->param_begin(), fnTy->param_end());
  if (indirectResult)
    args[1] = IGM.ObjCSuperPtrTy;
  else
    args[0] = IGM.ObjCSuperPtrTy;
  return llvm::FunctionType::get(fnTy->getReturnType(), args, fnTy->isVarArg());
}

Callee irgen::getObjCMethodCallee(IRGenFunction &IGF,
                                  const ObjCMethod &methodInfo,
                                  llvm::Value *selfValue,
                                  CalleeInfo &&info) {
  SILDeclRef method = methodInfo.getMethod();
  assert((method.kind == SILDeclRef::Kind::Initializer
          || method.kind == SILDeclRef::Kind::Allocator
          || method.kind == SILDeclRef::Kind::Func
          || method.kind == SILDeclRef::Kind::Destroyer
          || method.kind == SILDeclRef::Kind::Deallocator) &&
         "objc method call must be to a func/initializer/getter/setter/dtor");

  auto kind = methodInfo.getMessageKind();

  Signature sig = IGF.IGM.getSignature(info.OrigFnType);
  bool indirectResult =
    sig.getForeignInfo().ClangInfo->getReturnInfo().isIndirect();
  if (kind != ObjCMessageKind::Normal) {
    sig.setType(getMsgSendSuperTy(IGF.IGM, sig.getType(), indirectResult));
  }

  // Create the appropriate messenger function.
  // FIXME: this needs to be target-specific.  Ask Clang for it!
  llvm::Constant *messenger = [&]() -> llvm::Constant* {
    if (indirectResult && IGF.IGM.TargetInfo.ObjCUseStret) {
      switch (kind) {
      case ObjCMessageKind::Normal:
        return IGF.IGM.getObjCMsgSendStretFn();

      case ObjCMessageKind::Peer:
        return IGF.IGM.getObjCMsgSendSuperStretFn();

      case ObjCMessageKind::Super:
        return IGF.IGM.getObjCMsgSendSuperStret2Fn();
      }
    } else {
      switch (kind) {
      case ObjCMessageKind::Normal:
        return IGF.IGM.getObjCMsgSendFn();

      case ObjCMessageKind::Peer:
        return IGF.IGM.getObjCMsgSendSuperFn();

      case ObjCMessageKind::Super:
        return IGF.IGM.getObjCMsgSendSuper2Fn();
      }
    }
  }();

  messenger = llvm::ConstantExpr::getBitCast(messenger,
                                             sig.getType()->getPointerTo());

  // super.constructor references an instance method (even though the
  // decl is really a 'static' member). Similarly, destructors refer
  // to the instance method -dealloc.
  bool isInstanceMethod
    = method.kind == SILDeclRef::Kind::Initializer
      || method.kind == SILDeclRef::Kind::Deallocator
      || method.getDecl()->isInstanceMember();

  llvm::Value *receiverValue;
  if (auto searchType = methodInfo.getSearchType()) {
    receiverValue =
      emitSuperArgument(IGF, isInstanceMethod, selfValue,
                        searchType.getSwiftRValueType());
  } else {
    receiverValue = selfValue;
  }

  // Compute the selector.
  Selector selector(method);
  llvm::Value *selectorValue = IGF.emitObjCSelectorRefLoad(selector.str());

  auto fn = FunctionPointer::forDirect(messenger, sig);
  return Callee(std::move(info), fn, receiverValue, selectorValue);
}

/// Call [self allocWithZone: nil].
llvm::Value *irgen::emitObjCAllocObjectCall(IRGenFunction &IGF,
                                            llvm::Value *self,
                                            SILType selfType) {
  // Get an appropriately-cast function pointer.
  auto fn = IGF.IGM.getObjCAllocWithZoneFn();

  if (self->getType() != IGF.IGM.ObjCClassPtrTy) {
    auto fnTy = llvm::FunctionType::get(self->getType(), self->getType(),
                                        false)->getPointerTo();
    fn = llvm::ConstantExpr::getBitCast(fn, fnTy);
  }
  
  auto call = IGF.Builder.CreateCall(fn, self);

  // Cast the returned pointer to the right type.
  auto &classTI = IGF.getTypeInfo(selfType);
  llvm::Type *destType = classTI.getStorageType();
  return IGF.Builder.CreateBitCast(call, destType);
}

static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
                                                           ObjCMethod method,
                                            CanSILFunctionType origMethodType,
                                            CanSILFunctionType resultType,
                                            const HeapLayout &layout,
                                            SILType selfType) {
  auto &selfTI = IGM.getTypeInfo(selfType);
 
  assert(resultType->getRepresentation()
           == SILFunctionType::Representation::Thick);

  llvm::AttributeList attrs;
  llvm::FunctionType *fwdTy = IGM.getFunctionType(resultType, attrs);
  // FIXME: Give the thunk a real name.
  // FIXME: Maybe cache the thunk by function and closure types?
  llvm::Function *fwd =
    llvm::Function::Create(fwdTy, llvm::Function::InternalLinkage,
                           MANGLE_AS_STRING(OBJC_PARTIAL_APPLY_THUNK_SYM),
                           &IGM.Module);
  fwd->setCallingConv(
      expandCallingConv(IGM, SILFunctionTypeRepresentation::Thick));

  fwd->setAttributes(attrs);
  // Merge initial attributes with attrs.
  llvm::AttrBuilder b;
  IGM.constructInitialFnAttributes(b);
  fwd->addAttributes(llvm::AttributeList::FunctionIndex, b);
  
  IRGenFunction subIGF(IGM, fwd);
  if (IGM.DebugInfo)
    IGM.DebugInfo->emitArtificialFunction(subIGF, fwd);
  
  // Do we need to lifetime-extend self?
  bool lifetimeExtendsSelf;
  auto results = origMethodType->getResults();
  if (results.size() == 1) {
    switch (results[0].getConvention()) {
    case ResultConvention::UnownedInnerPointer:
      lifetimeExtendsSelf = true;
      break;

    case ResultConvention::Indirect:
    case ResultConvention::Unowned:
    case ResultConvention::Owned:
    case ResultConvention::Autoreleased:
      lifetimeExtendsSelf = false;
      break;
    }
  } else {
    lifetimeExtendsSelf = false;
  }
  
  // Do we need to retain self before calling, and/or release it after?
  bool retainsSelf;
  switch (origMethodType->getParameters().back().getConvention()) {
  case ParameterConvention::Direct_Unowned:
    retainsSelf = false;
    break;
  case ParameterConvention::Direct_Guaranteed:
  case ParameterConvention::Direct_Owned:
    retainsSelf = true;
    break;
  case ParameterConvention::Indirect_In_Guaranteed:
  case ParameterConvention::Indirect_In:
  case ParameterConvention::Indirect_In_Constant:
  case ParameterConvention::Indirect_Inout:
  case ParameterConvention::Indirect_InoutAliasable:
    llvm_unreachable("self passed indirectly?!");
  }
  
  // Recover 'self' from the context.
  Explosion params = subIGF.collectParameters();
  llvm::Value *context = params.takeLast();
  Address dataAddr = layout.emitCastTo(subIGF, context);
  auto &fieldLayout = layout.getElement(0);
  Address selfAddr = fieldLayout.project(subIGF, dataAddr, None);
  Explosion selfParams;
  if (retainsSelf)
    cast<LoadableTypeInfo>(selfTI).loadAsCopy(subIGF, selfAddr, selfParams);
  else
    cast<LoadableTypeInfo>(selfTI).loadAsTake(subIGF, selfAddr, selfParams);
  llvm::Value *self = selfParams.claimNext();
  
  // Save off the forwarded indirect return address if we have one.
  llvm::Value *formalIndirectResult = nullptr;
  llvm::Value *indirectedDirectResult = nullptr;
  const LoadableTypeInfo *indirectedResultTI = nullptr;
  if (origMethodType->hasIndirectFormalResults()) {
    // We should never import an ObjC method as returning a tuple which
    // would get broken up into multiple results like this.
    assert(origMethodType->getNumIndirectFormalResults() == 1);
    formalIndirectResult = params.claimNext();
  } else {
    SILType appliedResultTy = origMethodType->getDirectFormalResultsType();
    indirectedResultTI =
      &cast<LoadableTypeInfo>(IGM.getTypeInfo(appliedResultTy));
    auto &nativeSchema = indirectedResultTI->nativeReturnValueSchema(IGM);
    if (nativeSchema.requiresIndirect()) {
      indirectedDirectResult = params.claimNext();
    }
  }

  // Translate direct parameters passed indirectly.
  Explosion translatedParams;

  // Add the formal indirect return here.
  if (formalIndirectResult)
    translatedParams.add(formalIndirectResult);

  // We already handled self.
  assert(origMethodType->hasSelfParam());
  auto origParamInfos = origMethodType->getParameters();
  origParamInfos = origParamInfos.drop_back();

  for (auto info : origParamInfos) {
    // Addresses consist of a single pointer argument.
    if (isIndirectFormalParameter(info.getConvention())) {
      translatedParams.add(params.claimNext());
      continue;
    }
    // Otherwise, we have a loadable type that can either be passed directly or
    // indirectly.
    assert(info.getSILStorageType().isObject());
    auto curSILType = info.getSILStorageType();
    auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(curSILType));

    // Load the indirectly passed parameter.
    auto &nativeSchema = ti.nativeParameterValueSchema(IGM);
    if (nativeSchema.requiresIndirect()) {
      Address paramAddr = ti.getAddressForPointer(params.claimNext());
      ti.loadAsTake(subIGF, paramAddr, translatedParams);
      continue;
    }
    // Map from the native calling convention into the explosion schema.
    auto &nativeParamSchema = ti.nativeParameterValueSchema(IGM);
    Explosion nativeParam;
    params.transferInto(nativeParam, nativeParamSchema.size());
    Explosion nonNativeParam = nativeParamSchema.mapFromNative(
        subIGF.IGM, subIGF, nativeParam, curSILType);
    assert(nativeParam.empty());

    // Pass along the value.
    ti.reexplode(subIGF, nonNativeParam, translatedParams);
  }

  // Prepare the call to the underlying method.
  CallEmission emission(subIGF,
                        getObjCMethodCallee(subIGF, method, self,
                          CalleeInfo(origMethodType, origMethodType, {})));

  emission.setArgs(translatedParams, false);

  // Cleanup that always has to occur after the function call.
  auto cleanup = [&]{
    // Lifetime-extend 'self' by sending it to the autorelease pool if need be.
    if (lifetimeExtendsSelf) {
      subIGF.emitObjCRetainCall(self);
      subIGF.emitObjCAutoreleaseCall(self);
    }
    // Release the context.
    if (!resultType->isCalleeGuaranteed())
      subIGF.emitNativeStrongRelease(context, subIGF.getDefaultAtomicity());
  };
  
   // Emit the call and produce the return value.
  if (indirectedDirectResult) {
    Address addr =
      indirectedResultTI->getAddressForPointer(indirectedDirectResult);
    emission.emitToMemory(addr, *indirectedResultTI, false);
    cleanup();
    subIGF.Builder.CreateRetVoid();
  } else {
    Explosion result;
    emission.emitToExplosion(result, false);
    cleanup();
    auto &callee = emission.getCallee();
    auto resultType =
        callee.getOrigFunctionType()->getDirectFormalResultsType();
    subIGF.emitScalarReturn(resultType, result, true /*isSwiftCCReturn*/,
                            false);
  }
  
  return fwd;
}

void irgen::emitObjCPartialApplication(IRGenFunction &IGF,
                                       ObjCMethod method,
                                       CanSILFunctionType origMethodType,
                                       CanSILFunctionType resultType,
                                       llvm::Value *self,
                                       SILType selfType,
                                       Explosion &out) {
  // Create a heap object to contain the self argument.
  // TODO: If function context arguments were given objc retain counts,
  // we wouldn't need to create a separate heap object here.
  auto *selfTypeInfo = &IGF.getTypeInfo(selfType);
  HeapLayout layout(IGF.IGM, LayoutStrategy::Optimal,
                    selfType, selfTypeInfo);

  // FIXME: Either emit a descriptor for this or create a metadata kind
  // that indicates its trivial layout.
  auto Descriptor
    = llvm::ConstantPointerNull::get(IGF.IGM.CaptureDescriptorPtrTy);
  llvm::Value *data = IGF.emitUnmanagedAlloc(layout, "closure",
                                             Descriptor);
  // FIXME: non-fixed offsets
  NonFixedOffsets offsets = None;
  Address dataAddr = layout.emitCastTo(IGF, data);
  auto &fieldLayout = layout.getElement(0);
  auto &fieldType = layout.getElementTypes()[0];
  Address fieldAddr = fieldLayout.project(IGF, dataAddr, offsets);
  Explosion selfParams;
  selfParams.add(self);
  fieldLayout.getType().initializeFromParams(IGF, selfParams, fieldAddr,
                                             fieldType, false);

  // Create the forwarding stub.
  llvm::Function *forwarder = emitObjCPartialApplicationForwarder(IGF.IGM,
                                                                method,
                                                                origMethodType,
                                                                resultType,
                                                                layout,
                                                                selfType);
  llvm::Value *forwarderValue = IGF.Builder.CreateBitCast(forwarder,
                                                          IGF.IGM.Int8PtrTy);
  
  // Emit the result explosion.
  out.add(forwarderValue);
  out.add(data);
}

/// Create the LLVM function declaration for a thunk that acts like
/// an Objective-C method for a Swift method implementation.
static llvm::Constant *findSwiftAsObjCThunk(IRGenModule &IGM, SILDeclRef ref) {
  SILFunction *SILFn = IGM.getSILModule().lookUpFunction(ref);
  assert(SILFn && "no IR function for swift-as-objc thunk");
  auto fn = IGM.getAddrOfSILFunction(SILFn, NotForDefinition);
  fn->setVisibility(llvm::GlobalValue::DefaultVisibility);
  fn->setLinkage(llvm::GlobalValue::InternalLinkage);
  fn->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);

  return llvm::ConstantExpr::getBitCast(fn, IGM.Int8PtrTy);
}

/// Produce a function pointer, suitable for invocation by
/// objc_msgSend, for the given property's getter method implementation.
///
/// Returns a value of type i8*.
static llvm::Constant *getObjCGetterPointer(IRGenModule &IGM,
                                            AbstractStorageDecl *property) {
  // Protocol properties have no impl.
  if (isa<ProtocolDecl>(property->getDeclContext()))
    return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);

  SILDeclRef getter = SILDeclRef(property->getGetter(), SILDeclRef::Kind::Func)
    .asForeign();

  return findSwiftAsObjCThunk(IGM, getter);
}

/// Produce a function pointer, suitable for invocation by
/// objc_msgSend, for the given property's setter method implementation.
///
/// Returns a value of type i8*.
static llvm::Constant *getObjCSetterPointer(IRGenModule &IGM,
                                            AbstractStorageDecl *property) {
  // Protocol properties have no impl.
  if (isa<ProtocolDecl>(property->getDeclContext()))
    return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);

  assert(property->isSettable(property->getDeclContext()) &&
         "property is not settable?!");
  
  SILDeclRef setter = SILDeclRef(property->getSetter(), SILDeclRef::Kind::Func)
    .asForeign();

  return findSwiftAsObjCThunk(IGM, setter);
}

/// Produce a function pointer, suitable for invocation by
/// objc_msgSend, for the given method implementation.
///
/// Returns a value of type i8*.
static llvm::Constant *getObjCMethodPointer(IRGenModule &IGM,
                                            FuncDecl *method) {
  // Protocol methods have no impl.
  if (isa<ProtocolDecl>(method->getDeclContext()))
    return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);

  SILDeclRef declRef = SILDeclRef(method, SILDeclRef::Kind::Func)
    .asForeign();

  return findSwiftAsObjCThunk(IGM, declRef);
}

/// Produce a function pointer, suitable for invocation by
/// objc_msgSend, for the given constructor implementation.
///
/// Returns a value of type i8*.
static llvm::Constant *getObjCMethodPointer(IRGenModule &IGM,
                                            ConstructorDecl *constructor) {
  // Protocol methods have no impl.
  if (isa<ProtocolDecl>(constructor->getDeclContext()))
    return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);

  SILDeclRef declRef = SILDeclRef(constructor, SILDeclRef::Kind::Initializer)
    .asForeign();

  return findSwiftAsObjCThunk(IGM, declRef);
}

/// Produce a function pointer, suitable for invocation by
/// objc_msgSend, for the given destructor implementation.
///
/// Returns a value of type i8*.
static llvm::Constant *getObjCMethodPointer(IRGenModule &IGM,
                                            DestructorDecl *destructor) {
  SILDeclRef declRef = SILDeclRef(destructor, SILDeclRef::Kind::Deallocator)
    .asForeign();

  return findSwiftAsObjCThunk(IGM, declRef);
}

static SILDeclRef getObjCMethodRef(AbstractFunctionDecl *method) {
  if (isa<ConstructorDecl>(method))
    return SILDeclRef(method, SILDeclRef::Kind::Initializer).asForeign();
  if (isa<DestructorDecl>(method))
    return SILDeclRef(method, SILDeclRef::Kind::Deallocator).asForeign();
  return SILDeclRef(method, SILDeclRef::Kind::Func).asForeign();
}

static CanSILFunctionType getObjCMethodType(IRGenModule &IGM,
                                            AbstractFunctionDecl *method) {  
  return IGM.getSILTypes().getConstantFunctionType(getObjCMethodRef(method));
}

static clang::CanQualType getObjCPropertyType(IRGenModule &IGM,
                                              VarDecl *property) {
  // Use the lowered return type of the foreign getter.
  auto getter = property->getGetter();
  assert(getter);
  CanSILFunctionType methodTy = getObjCMethodType(IGM, getter);
  return IGM.getClangType(
      methodTy->getFormalCSemanticResult().getSwiftRValueType());
}

void irgen::getObjCEncodingForPropertyType(IRGenModule &IGM,
                                           VarDecl *property, std::string &s) {
  // FIXME: Property encoding differs in slight ways that aren't publicly
  // exposed from Clang.
  IGM.getClangASTContext()
    .getObjCEncodingForPropertyType(getObjCPropertyType(IGM, property), s);
}

static void
HelperGetObjCEncodingForType(const clang::ASTContext &Context,
                             clang::CanQualType T,
                             std::string &S, bool Extended) {
  
  Context.getObjCEncodingForMethodParameter(clang::Decl::OBJC_TQ_None,
                                            T, S, Extended);
}

static llvm::Constant *getObjCEncodingForTypes(IRGenModule &IGM,
                                               SILType resultType,
                                               ArrayRef<SILParameterInfo> params,
                                               StringRef fixedParamsString,
                                               Size::int_type parmOffset,
                                               bool useExtendedEncoding) {
  auto &clangASTContext = IGM.getClangASTContext();
  
  std::string encodingString;

  // Return type.
  {
    auto clangType = IGM.getClangType(resultType.getSwiftRValueType());
    if (clangType.isNull())
      return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
    HelperGetObjCEncodingForType(clangASTContext, clangType, encodingString,
                                 useExtendedEncoding);
  }

  // Parameter types.
  // TODO. Encode type qualifier, 'in', 'inout', etc. for the parameter.
  std::string paramsString;
  for (auto param : params) {
    auto clangType = IGM.getClangType(param.getType());
    if (clangType.isNull())
      return llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
    
    // TODO. Some stuff related to Array and Function type is missing.
    // TODO. Encode type qualifier, 'in', 'inout', etc. for the parameter.
    HelperGetObjCEncodingForType(clangASTContext, clangType, paramsString,
                                 useExtendedEncoding);
    paramsString += llvm::itostr(parmOffset);
    clang::CharUnits sz = clangASTContext.getObjCEncodingTypeSize(clangType);
    parmOffset += sz.getQuantity();
  }
  
  encodingString += llvm::itostr(parmOffset);
  encodingString += fixedParamsString;
  encodingString += paramsString;
  return IGM.getAddrOfGlobalString(encodingString);
}

static llvm::Constant *getObjCEncodingForMethodType(IRGenModule &IGM,
                                                    CanSILFunctionType fnType,
                                                    bool useExtendedEncoding) {
  SILType resultType = fnType->getFormalCSemanticResult();

  // Get the inputs without 'self'.
  auto inputs = fnType->getParameters().drop_back();

  // Include the encoding for 'self' and '_cmd'.
  llvm::SmallString<8> specialParams;
  specialParams += "@0:";
  auto ptrSize = IGM.getPointerSize().getValue();
  specialParams += llvm::itostr(ptrSize);
  GenericContextScope scope(IGM, fnType->getGenericSignature());
  return getObjCEncodingForTypes(IGM, resultType, inputs, specialParams,
                                 ptrSize * 2, useExtendedEncoding);
}

/// Emit the components of an Objective-C method descriptor: its selector,
/// type encoding, and IMP pointer.
void irgen::emitObjCMethodDescriptorParts(IRGenModule &IGM,
                                          AbstractFunctionDecl *method,
                                          bool extendedEncoding,
                                          bool concrete,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  Selector selector(method);
  
  /// The first element is the selector.
  selectorRef = IGM.getAddrOfObjCMethodName(selector.str());
  
  /// The second element is the type @encoding.
  CanSILFunctionType methodType = getObjCMethodType(IGM, method);
  atEncoding = getObjCEncodingForMethodType(IGM, methodType, extendedEncoding);
  
  /// The third element is the method implementation pointer.
  if (!concrete) {
    impl = nullptr;
    return;
  }
  
  if (auto func = dyn_cast<FuncDecl>(method))
    impl = getObjCMethodPointer(IGM, func);
  else if (auto ctor = dyn_cast<ConstructorDecl>(method))
    impl = getObjCMethodPointer(IGM, ctor);
  else
    impl = getObjCMethodPointer(IGM, cast<DestructorDecl>(method));
}

/// Emit the components of an Objective-C method descriptor for a
/// property getter method.
void irgen::emitObjCGetterDescriptorParts(IRGenModule &IGM,
                                          VarDecl *property,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  Selector getterSel(property, Selector::ForGetter);
  selectorRef = IGM.getAddrOfObjCMethodName(getterSel.str());
  
  auto clangType = getObjCPropertyType(IGM, property);
  if (clangType.isNull()) {
    atEncoding = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
    return;
  }

  auto &clangASTContext = IGM.getClangASTContext();
  std::string TypeStr;
  clangASTContext.getObjCEncodingForType(clangType, TypeStr);
  
  Size PtrSize = IGM.getPointerSize();
  Size::int_type ParmOffset = 2 * PtrSize.getValue();
  
  TypeStr += llvm::itostr(ParmOffset);
  TypeStr += "@0:";
  TypeStr += llvm::itostr(PtrSize.getValue());
  atEncoding = IGM.getAddrOfGlobalString(TypeStr.c_str());
  impl = getObjCGetterPointer(IGM, property);
}

/// Emit the components of an Objective-C method descriptor for a
/// subscript getter method.
void irgen::emitObjCGetterDescriptorParts(IRGenModule &IGM,
                                          SubscriptDecl *subscript,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  Selector getterSel(subscript, Selector::ForGetter);
  selectorRef = IGM.getAddrOfObjCMethodName(getterSel.str());
  atEncoding = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
  impl = getObjCGetterPointer(IGM, subscript);
}

void irgen::emitObjCGetterDescriptorParts(IRGenModule &IGM,
                                          AbstractStorageDecl *decl,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  if (auto sub = dyn_cast<SubscriptDecl>(decl)) {
    return emitObjCGetterDescriptorParts(IGM, sub,
                                         selectorRef, atEncoding, impl);
  }
  if (auto var = dyn_cast<VarDecl>(decl)) {
    return emitObjCGetterDescriptorParts(IGM, var,
                                         selectorRef, atEncoding, impl);
  }
  llvm_unreachable("unknown storage!");
}

/// Emit the components of an Objective-C method descriptor for a
/// property getter method.
void irgen::emitObjCSetterDescriptorParts(IRGenModule &IGM,
                                          VarDecl *property,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  assert(property->isSettable(property->getDeclContext()) &&
         "not a settable property?!");

  Selector setterSel(property, Selector::ForSetter);
  selectorRef = IGM.getAddrOfObjCMethodName(setterSel.str());
  
  auto &clangASTContext = IGM.getClangASTContext();
  std::string TypeStr;
  auto clangType = clangASTContext.VoidTy;
  clangASTContext.getObjCEncodingForType(clangType, TypeStr);
  
  Size PtrSize = IGM.getPointerSize();
  Size::int_type ParmOffset = 2 * PtrSize.getValue();

  clangType = getObjCPropertyType(IGM, property);
  if (clangType.isNull()) {
    atEncoding = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
    return;
  }
  clang::CharUnits sz = clangASTContext.getObjCEncodingTypeSize(clangType);
  if (!sz.isZero())
    ParmOffset += sz.getQuantity();
  TypeStr += llvm::itostr(ParmOffset);
  TypeStr += "@0:";
  TypeStr += llvm::itostr(PtrSize.getValue());
  ParmOffset = 2 * PtrSize.getValue();
  clangASTContext.getObjCEncodingForType(clangType, TypeStr);
  TypeStr += llvm::itostr(ParmOffset);
  atEncoding = IGM.getAddrOfGlobalString(TypeStr.c_str());

  impl = getObjCSetterPointer(IGM, property);
}

/// Emit the components of an Objective-C method descriptor for a
/// subscript getter method.
void irgen::emitObjCSetterDescriptorParts(IRGenModule &IGM,
                                          SubscriptDecl *subscript,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  assert(subscript->isSettable() && "not a settable subscript?!");

  Selector setterSel(subscript, Selector::ForSetter);
  selectorRef = IGM.getAddrOfObjCMethodName(setterSel.str());
  atEncoding = llvm::ConstantPointerNull::get(IGM.Int8PtrTy);
  impl = getObjCSetterPointer(IGM, subscript);
}

void irgen::emitObjCSetterDescriptorParts(IRGenModule &IGM,
                                          AbstractStorageDecl *decl,
                                          llvm::Constant *&selectorRef,
                                          llvm::Constant *&atEncoding,
                                          llvm::Constant *&impl) {
  if (auto sub = dyn_cast<SubscriptDecl>(decl)) {
    return emitObjCSetterDescriptorParts(IGM, sub,
                                         selectorRef, atEncoding, impl);
  }
  if (auto var = dyn_cast<VarDecl>(decl)) {
    return emitObjCSetterDescriptorParts(IGM, var,
                                         selectorRef, atEncoding, impl);
  }
  llvm_unreachable("unknown storage!");
}

static void buildMethodDescriptor(ConstantArrayBuilder &descriptors,
                                  llvm::Constant *selectorRef,
                                  llvm::Constant *atEncoding,
                                  llvm::Constant *impl) {
  auto descriptor = descriptors.beginStruct();
  descriptor.add(selectorRef);
  descriptor.add(atEncoding);
  descriptor.add(impl);
  descriptor.finishAndAddTo(descriptors);
}

/// Emit an Objective-C method descriptor for the given method.
/// struct method_t {
///   SEL name;
///   const char *types;
///   IMP imp;
/// };
void irgen::emitObjCMethodDescriptor(IRGenModule &IGM,
                                     ConstantArrayBuilder &descriptors,
                                     AbstractFunctionDecl *method) {
  llvm::Constant *selectorRef, *atEncoding, *impl;
  emitObjCMethodDescriptorParts(IGM, method,
                                /*extended*/ false,
                                /*concrete*/ true,
                                selectorRef, atEncoding, impl);
  buildMethodDescriptor(descriptors, selectorRef, atEncoding, impl);
}

void irgen::emitObjCIVarInitDestroyDescriptor(IRGenModule &IGM,
                                              ConstantArrayBuilder &descriptors,
                                              ClassDecl *cd,
                                              llvm::Function *objcImpl,
                                              bool isDestroyer) {
  /// The first element is the selector.
  SILDeclRef declRef = SILDeclRef(cd, 
                                  isDestroyer? SILDeclRef::Kind::IVarDestroyer
                                             : SILDeclRef::Kind::IVarInitializer,
                                  ResilienceExpansion::Minimal,
                                  1, 
                                  /*foreign*/ true);
  Selector selector(declRef);
  auto selectorRef = IGM.getAddrOfObjCMethodName(selector.str());
  
  /// The second element is the type @encoding, which is always "@?"
  /// for a function type.
  auto atEncoding = IGM.getAddrOfGlobalString("@?");

  /// The third element is the method implementation pointer.
  auto impl = llvm::ConstantExpr::getBitCast(objcImpl, IGM.Int8PtrTy);

  // Form the method_t instance.
  buildMethodDescriptor(descriptors, selectorRef, atEncoding, impl);
}

llvm::Constant *
irgen::getMethodTypeExtendedEncoding(IRGenModule &IGM,
                                     AbstractFunctionDecl *method) {
  CanSILFunctionType methodType = getObjCMethodType(IGM, method);
  return getObjCEncodingForMethodType(IGM, methodType, true/*Extended*/);
}

llvm::Constant *
irgen::getBlockTypeExtendedEncoding(IRGenModule &IGM,
                                    CanSILFunctionType invokeTy) {
  SILType resultType = invokeTy->getFormalCSemanticResult();

  // Skip the storage pointer, which is encoded as '@?' to avoid the infinite
  // recursion of the usual '@?<...>' rule for blocks.
  auto paramTypes = invokeTy->getParameters().slice(1);
  
  return getObjCEncodingForTypes(IGM, resultType, paramTypes,
                                 "@?0", IGM.getPointerSize().getValue(),
                                 /*extended*/ true);
}

void irgen::emitObjCGetterDescriptor(IRGenModule &IGM,
                                     ConstantArrayBuilder &descriptors,
                                     AbstractStorageDecl *storage) {
  llvm::Constant *selectorRef, *atEncoding, *impl;
  emitObjCGetterDescriptorParts(IGM, storage,
                                selectorRef, atEncoding, impl);
  buildMethodDescriptor(descriptors, selectorRef, atEncoding, impl);
}

void irgen::emitObjCSetterDescriptor(IRGenModule &IGM,
                                     ConstantArrayBuilder &descriptors,
                                     AbstractStorageDecl *storage) {
  llvm::Constant *selectorRef, *atEncoding, *impl;
  emitObjCSetterDescriptorParts(IGM, storage,
                                selectorRef, atEncoding, impl);
  buildMethodDescriptor(descriptors, selectorRef, atEncoding, impl);
}

bool irgen::requiresObjCMethodDescriptor(FuncDecl *method) {
  // Property accessors should be generated alongside the property.
  if (method->isAccessor())
    return false;

  return method->isObjC() || method->getAttrs().hasAttribute<IBActionAttr>();
}

bool irgen::requiresObjCMethodDescriptor(ConstructorDecl *constructor) {
  return constructor->isObjC();
}

bool irgen::requiresObjCPropertyDescriptor(IRGenModule &IGM,
                                           VarDecl *property) {
  // Don't generate a descriptor for a property without any accessors.
  // This is only possible in SIL files because Sema will normally
  // implicitly synthesize accessors for @objc properties.
  return property->isObjC() && property->getGetter();
}

bool irgen::requiresObjCSubscriptDescriptor(IRGenModule &IGM,
                                            SubscriptDecl *subscript) {
  return subscript->isObjC();
}

llvm::Value *IRGenFunction::emitBlockCopyCall(llvm::Value *value) {
  // Get an appropriately-cast function pointer.
  auto fn = IGM.getBlockCopyFn();
  if (value->getType() != IGM.ObjCBlockPtrTy) {
    auto fnTy = llvm::FunctionType::get(value->getType(), value->getType(),
                                        false)->getPointerTo();
    fn = llvm::ConstantExpr::getBitCast(fn, fnTy);
  }
  
  auto call = Builder.CreateCall(fn, value);
  return call;
}

void IRGenFunction::emitBlockRelease(llvm::Value *value) {
  // Get an appropriately-cast function pointer.
  auto fn = IGM.getBlockReleaseFn();
  if (value->getType() != IGM.ObjCBlockPtrTy) {
    auto fnTy = llvm::FunctionType::get(IGM.VoidTy, value->getType(),
                                        false)->getPointerTo();
    fn = llvm::ConstantExpr::getBitCast(fn, fnTy);
  }
  auto call = Builder.CreateCall(fn, value);
  call->setDoesNotThrow();
}
