//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This provides Objective-C code generation targeting the Apple runtime.
//
//===----------------------------------------------------------------------===//

#include "CGBlocks.h"
#include "CGCleanup.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/LangOptions.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/ADT/CachedHashString.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ScopedPrinter.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdio>

using namespace clang;
using namespace CodeGen;

namespace {

// FIXME: We should find a nicer way to make the labels for metadata, string
// concatenation is lame.

class ObjCCommonTypesHelper {
protected:
  llvm::LLVMContext &VMContext;

private:
  // The types of these functions don't really matter because we
  // should always bitcast before calling them.

  /// id objc_msgSend (id, SEL, ...)
  ///
  /// The default messenger, used for sends whose ABI is unchanged from
  /// the all-integer/pointer case.
  llvm::FunctionCallee getMessageSendFn() const {
    // Add the non-lazy-bind attribute, since objc_msgSend is likely to
    // be called a lot.
    llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend",
        llvm::AttributeList::get(CGM.getLLVMContext(),
                                 llvm::AttributeList::FunctionIndex,
                                 llvm::Attribute::NonLazyBind));
  }

  /// void objc_msgSend_stret (id, SEL, ...)
  ///
  /// The messenger used when the return value is an aggregate returned
  /// by indirect reference in the first argument, and therefore the
  /// self and selector parameters are shifted over by one.
  llvm::FunctionCallee getMessageSendStretFn() const {
    llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.VoidTy, params, true),
        "objc_msgSend_stret");
  }

  /// [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
  ///
  /// The messenger used when the return value is returned on the x87
  /// floating-point stack; without a special entrypoint, the nil case
  /// would be unbalanced.
  llvm::FunctionCallee getMessageSendFpretFn() const {
    llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.DoubleTy, params, true),
        "objc_msgSend_fpret");
  }

  /// _Complex long double objc_msgSend_fp2ret(id self, SEL op, ...)
  ///
  /// The messenger used when the return value is returned in two values on the
  /// x87 floating point stack; without a special entrypoint, the nil case
  /// would be unbalanced. Only used on 64-bit X86.
  llvm::FunctionCallee getMessageSendFp2retFn() const {
    llvm::Type *params[] = {ObjectPtrTy, SelectorPtrTy};
    llvm::Type *longDoubleType = llvm::Type::getX86_FP80Ty(VMContext);
    llvm::Type *resultType =
        llvm::StructType::get(longDoubleType, longDoubleType);

    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(resultType, params, true),
        "objc_msgSend_fp2ret");
  }

  /// id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
  ///
  /// The messenger used for super calls, which have different dispatch
  /// semantics.  The class passed is the superclass of the current
  /// class.
  llvm::FunctionCallee getMessageSendSuperFn() const {
    llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSendSuper");
  }

  /// id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
  ///
  /// A slightly different messenger used for super calls.  The class
  /// passed is the current class.
  llvm::FunctionCallee getMessageSendSuperFn2() const {
    llvm::Type *params[] = {SuperPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSendSuper2");
  }

  /// void objc_msgSendSuper_stret(void *stretAddr, struct objc_super *super,
  ///                              SEL op, ...)
  ///
  /// The messenger used for super calls which return an aggregate indirectly.
  llvm::FunctionCallee getMessageSendSuperStretFn() const {
    llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.VoidTy, params, true),
        "objc_msgSendSuper_stret");
  }

  /// void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
  ///                               SEL op, ...)
  ///
  /// objc_msgSendSuper_stret with the super2 semantics.
  llvm::FunctionCallee getMessageSendSuperStretFn2() const {
    llvm::Type *params[] = {Int8PtrTy, SuperPtrTy, SelectorPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.VoidTy, params, true),
        "objc_msgSendSuper2_stret");
  }

  llvm::FunctionCallee getMessageSendSuperFpretFn() const {
    // There is no objc_msgSendSuper_fpret? How can that work?
    return getMessageSendSuperFn();
  }

  llvm::FunctionCallee getMessageSendSuperFpretFn2() const {
    // There is no objc_msgSendSuper_fpret? How can that work?
    return getMessageSendSuperFn2();
  }

protected:
  CodeGen::CodeGenModule &CGM;

public:
  llvm::IntegerType *ShortTy, *IntTy, *LongTy;
  llvm::PointerType *Int8PtrTy, *Int8PtrPtrTy;
  llvm::PointerType *Int8PtrProgramASTy;
  llvm::Type *IvarOffsetVarTy;

  /// ObjectPtrTy - LLVM type for object handles (typeof(id))
  llvm::PointerType *ObjectPtrTy;

  /// PtrObjectPtrTy - LLVM type for id *
  llvm::PointerType *PtrObjectPtrTy;

  /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
  llvm::PointerType *SelectorPtrTy;

  // SuperCTy - clang type for struct objc_super.
  QualType SuperCTy;
  // SuperPtrCTy - clang type for struct objc_super *.
  QualType SuperPtrCTy;

  /// SuperTy - LLVM type for struct objc_super.
  llvm::StructType *SuperTy;
  /// SuperPtrTy - LLVM type for struct objc_super *.
  llvm::PointerType *SuperPtrTy;

  /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
  /// in GCC parlance).
  llvm::StructType *PropertyTy;

  /// PropertyListTy - LLVM type for struct objc_property_list
  /// (_prop_list_t in GCC parlance).
  llvm::StructType *PropertyListTy;
  /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
  llvm::PointerType *PropertyListPtrTy;

  // MethodTy - LLVM type for struct objc_method.
  llvm::StructType *MethodTy;

  /// CacheTy - LLVM type for struct objc_cache.
  llvm::Type *CacheTy;
  /// CachePtrTy - LLVM type for struct objc_cache *.
  llvm::PointerType *CachePtrTy;

  llvm::FunctionCallee getGetPropertyFn() {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    // id objc_getProperty (id, SEL, ptrdiff_t, bool)
    CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
    CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
    CanQualType Params[] = {
        IdType, SelType,
        Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(), Ctx.BoolTy};
    llvm::FunctionType *FTy = Types.GetFunctionType(
        Types.arrangeBuiltinFunctionDeclaration(IdType, Params));
    return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
  }

  llvm::FunctionCallee getSetPropertyFn() {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
    CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
    CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
    CanQualType Params[] = {
        IdType,
        SelType,
        Ctx.getPointerDiffType()->getCanonicalTypeUnqualified(),
        IdType,
        Ctx.BoolTy,
        Ctx.BoolTy};
    llvm::FunctionType *FTy = Types.GetFunctionType(
        Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
    return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
  }

  llvm::FunctionCallee getOptimizedSetPropertyFn(bool atomic, bool copy) {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    // void objc_setProperty_atomic(id self, SEL _cmd,
    //                              id newValue, ptrdiff_t offset);
    // void objc_setProperty_nonatomic(id self, SEL _cmd,
    //                                 id newValue, ptrdiff_t offset);
    // void objc_setProperty_atomic_copy(id self, SEL _cmd,
    //                                   id newValue, ptrdiff_t offset);
    // void objc_setProperty_nonatomic_copy(id self, SEL _cmd,
    //                                      id newValue, ptrdiff_t offset);

    SmallVector<CanQualType, 4> Params;
    CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
    CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
    Params.push_back(IdType);
    Params.push_back(SelType);
    Params.push_back(IdType);
    Params.push_back(Ctx.getPointerDiffType()->getCanonicalTypeUnqualified());
    llvm::FunctionType *FTy = Types.GetFunctionType(
        Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
    const char *name;
    if (atomic && copy)
      name = "objc_setProperty_atomic_copy";
    else if (atomic && !copy)
      name = "objc_setProperty_atomic";
    else if (!atomic && copy)
      name = "objc_setProperty_nonatomic_copy";
    else
      name = "objc_setProperty_nonatomic";

    return CGM.CreateRuntimeFunction(FTy, name);
  }

  llvm::FunctionCallee getCopyStructFn() {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    // void objc_copyStruct (void *, const void *, size_t, bool, bool)
    SmallVector<CanQualType, 5> Params;
    Params.push_back(Ctx.VoidPtrTy);
    Params.push_back(Ctx.VoidPtrTy);
    Params.push_back(Ctx.getCanonicalSizeType());
    Params.push_back(Ctx.BoolTy);
    Params.push_back(Ctx.BoolTy);
    llvm::FunctionType *FTy = Types.GetFunctionType(
        Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
    return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
  }

  /// This routine declares and returns address of:
  /// void objc_copyCppObjectAtomic(
  ///         void *dest, const void *src,
  ///         void (*copyHelper) (void *dest, const void *source));
  llvm::FunctionCallee getCppAtomicObjectFunction() {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    /// void objc_copyCppObjectAtomic(void *dest, const void *src, void
    /// *helper);
    SmallVector<CanQualType, 3> Params;
    Params.push_back(Ctx.VoidPtrTy);
    Params.push_back(Ctx.VoidPtrTy);
    Params.push_back(Ctx.VoidPtrTy);
    llvm::FunctionType *FTy = Types.GetFunctionType(
        Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
    return CGM.CreateRuntimeFunction(FTy, "objc_copyCppObjectAtomic");
  }

  llvm::FunctionCallee getEnumerationMutationFn() {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    // void objc_enumerationMutation (id)
    SmallVector<CanQualType, 1> Params;
    Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
    llvm::FunctionType *FTy = Types.GetFunctionType(
        Types.arrangeBuiltinFunctionDeclaration(Ctx.VoidTy, Params));
    return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
  }

  llvm::FunctionCallee getLookUpClassFn() {
    CodeGen::CodeGenTypes &Types = CGM.getTypes();
    ASTContext &Ctx = CGM.getContext();
    // Class objc_lookUpClass (const char *)
    SmallVector<CanQualType, 1> Params;
    Params.push_back(
        Ctx.getCanonicalType(Ctx.getPointerType(Ctx.CharTy.withConst())));
    llvm::FunctionType *FTy =
        Types.GetFunctionType(Types.arrangeBuiltinFunctionDeclaration(
            Ctx.getCanonicalType(Ctx.getObjCClassType()), Params));
    return CGM.CreateRuntimeFunction(FTy, "objc_lookUpClass");
  }

  /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
  llvm::FunctionCallee getGcReadWeakFn() {
    // id objc_read_weak (id *)
    llvm::Type *args[] = {CGM.UnqualPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
  }

  /// GcAssignWeakFn -- LLVM objc_assign_weak function.
  llvm::FunctionCallee getGcAssignWeakFn() {
    // id objc_assign_weak (id, id *)
    llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
  }

  /// GcAssignGlobalFn -- LLVM objc_assign_global function.
  llvm::FunctionCallee getGcAssignGlobalFn() {
    // id objc_assign_global(id, id *)
    llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
  }

  /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
  llvm::FunctionCallee getGcAssignThreadLocalFn() {
    // id objc_assign_threadlocal(id src, id * dest)
    llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
  }

  /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
  llvm::FunctionCallee getGcAssignIvarFn() {
    // id objc_assign_ivar(id, id *, ptrdiff_t)
    llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy, CGM.PtrDiffTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
  }

  /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
  llvm::FunctionCallee GcMemmoveCollectableFn() {
    // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
    llvm::Type *args[] = {Int8PtrTy, Int8PtrTy, LongTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
  }

  /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
  llvm::FunctionCallee getGcAssignStrongCastFn() {
    // id objc_assign_strongCast(id, id *)
    llvm::Type *args[] = {ObjectPtrTy, CGM.UnqualPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(ObjectPtrTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
  }

  /// ExceptionThrowFn - LLVM objc_exception_throw function.
  llvm::FunctionCallee getExceptionThrowFn() {
    // void objc_exception_throw(id)
    llvm::Type *args[] = {ObjectPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
  }

  /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
  llvm::FunctionCallee getExceptionRethrowFn() {
    // void objc_exception_rethrow(void)
    llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.VoidTy, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
  }

  /// SyncEnterFn - LLVM object_sync_enter function.
  llvm::FunctionCallee getSyncEnterFn() {
    // int objc_sync_enter (id)
    llvm::Type *args[] = {ObjectPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
  }

  /// SyncExitFn - LLVM object_sync_exit function.
  llvm::FunctionCallee getSyncExitFn() {
    // int objc_sync_exit (id)
    llvm::Type *args[] = {ObjectPtrTy};
    llvm::FunctionType *FTy = llvm::FunctionType::get(CGM.IntTy, args, false);
    return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
  }

  llvm::FunctionCallee getSendFn(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
  }

  llvm::FunctionCallee getSendFn2(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
  }

  llvm::FunctionCallee getSendStretFn(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
  }

  llvm::FunctionCallee getSendStretFn2(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
  }

  llvm::FunctionCallee getSendFpretFn(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
  }

  llvm::FunctionCallee getSendFpretFn2(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
  }

  llvm::FunctionCallee getSendFp2retFn(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperFn() : getMessageSendFp2retFn();
  }

  llvm::FunctionCallee getSendFp2RetFn2(bool IsSuper) const {
    return IsSuper ? getMessageSendSuperFn2() : getMessageSendFp2retFn();
  }

  ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
};

/// ObjCTypesHelper - Helper class that encapsulates lazy
/// construction of varies types used during ObjC generation.
class ObjCTypesHelper : public ObjCCommonTypesHelper {
public:
  /// SymtabTy - LLVM type for struct objc_symtab.
  llvm::StructType *SymtabTy;
  /// SymtabPtrTy - LLVM type for struct objc_symtab *.
  llvm::PointerType *SymtabPtrTy;
  /// ModuleTy - LLVM type for struct objc_module.
  llvm::StructType *ModuleTy;

  /// ProtocolTy - LLVM type for struct objc_protocol.
  llvm::StructType *ProtocolTy;
  /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
  llvm::PointerType *ProtocolPtrTy;
  /// ProtocolExtensionTy - LLVM type for struct
  /// objc_protocol_extension.
  llvm::StructType *ProtocolExtensionTy;
  /// ProtocolExtensionTy - LLVM type for struct
  /// objc_protocol_extension *.
  llvm::PointerType *ProtocolExtensionPtrTy;
  /// MethodDescriptionTy - LLVM type for struct
  /// objc_method_description.
  llvm::StructType *MethodDescriptionTy;
  /// MethodDescriptionListTy - LLVM type for struct
  /// objc_method_description_list.
  llvm::StructType *MethodDescriptionListTy;
  /// MethodDescriptionListPtrTy - LLVM type for struct
  /// objc_method_description_list *.
  llvm::PointerType *MethodDescriptionListPtrTy;
  /// ProtocolListTy - LLVM type for struct objc_property_list.
  llvm::StructType *ProtocolListTy;
  /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
  llvm::PointerType *ProtocolListPtrTy;
  /// CategoryTy - LLVM type for struct objc_category.
  llvm::StructType *CategoryTy;
  /// ClassTy - LLVM type for struct objc_class.
  llvm::StructType *ClassTy;
  /// ClassPtrTy - LLVM type for struct objc_class *.
  llvm::PointerType *ClassPtrTy;
  /// ClassExtensionTy - LLVM type for struct objc_class_ext.
  llvm::StructType *ClassExtensionTy;
  /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
  llvm::PointerType *ClassExtensionPtrTy;
  // IvarTy - LLVM type for struct objc_ivar.
  llvm::StructType *IvarTy;
  /// IvarListTy - LLVM type for struct objc_ivar_list.
  llvm::StructType *IvarListTy;
  /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
  llvm::PointerType *IvarListPtrTy;
  /// MethodListTy - LLVM type for struct objc_method_list.
  llvm::StructType *MethodListTy;
  /// MethodListPtrTy - LLVM type for struct objc_method_list *.
  llvm::PointerType *MethodListPtrTy;

  /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
  llvm::StructType *ExceptionDataTy;

  /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
  llvm::FunctionCallee getExceptionTryEnterFn() {
    llvm::Type *params[] = {CGM.UnqualPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.VoidTy, params, false),
        "objc_exception_try_enter");
  }

  /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
  llvm::FunctionCallee getExceptionTryExitFn() {
    llvm::Type *params[] = {CGM.UnqualPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.VoidTy, params, false),
        "objc_exception_try_exit");
  }

  /// ExceptionExtractFn - LLVM objc_exception_extract function.
  llvm::FunctionCallee getExceptionExtractFn() {
    llvm::Type *params[] = {CGM.UnqualPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, false),
        "objc_exception_extract");
  }

  /// ExceptionMatchFn - LLVM objc_exception_match function.
  llvm::FunctionCallee getExceptionMatchFn() {
    llvm::Type *params[] = {ClassPtrTy, ObjectPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.Int32Ty, params, false),
        "objc_exception_match");
  }

  /// SetJmpFn - LLVM _setjmp function.
  llvm::FunctionCallee getSetJmpFn() {
    // This is specifically the prototype for x86.
    llvm::Type *params[] = {CGM.UnqualPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp",
        llvm::AttributeList::get(CGM.getLLVMContext(),
                                 llvm::AttributeList::FunctionIndex,
                                 llvm::Attribute::NonLazyBind));
  }

public:
  ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
};

/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
/// modern abi
class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
public:
  // MethodListnfABITy - LLVM for struct _method_list_t
  llvm::StructType *MethodListnfABITy;

  // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
  llvm::PointerType *MethodListnfABIPtrTy;

  // ProtocolnfABITy = LLVM for struct _protocol_t
  llvm::StructType *ProtocolnfABITy;

  // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
  llvm::PointerType *ProtocolnfABIPtrTy;

  // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
  llvm::StructType *ProtocolListnfABITy;

  // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
  llvm::PointerType *ProtocolListnfABIPtrTy;

  // ClassnfABITy - LLVM for struct _class_t
  llvm::StructType *ClassnfABITy;

  // ClassnfABIPtrTy - LLVM for struct _class_t*
  llvm::PointerType *ClassnfABIPtrTy;

  // IvarnfABITy - LLVM for struct _ivar_t
  llvm::StructType *IvarnfABITy;

  // IvarListnfABITy - LLVM for struct _ivar_list_t
  llvm::StructType *IvarListnfABITy;

  // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
  llvm::PointerType *IvarListnfABIPtrTy;

  // ClassRonfABITy - LLVM for struct _class_ro_t
  llvm::StructType *ClassRonfABITy;

  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
  llvm::PointerType *ImpnfABITy;

  // CategorynfABITy - LLVM for struct _category_t
  llvm::StructType *CategorynfABITy;

  // New types for nonfragile abi messaging.

  // MessageRefTy - LLVM for:
  // struct _message_ref_t {
  //   IMP messenger;
  //   SEL name;
  // };
  llvm::StructType *MessageRefTy;
  // MessageRefCTy - clang type for struct _message_ref_t
  QualType MessageRefCTy;

  // MessageRefPtrTy - LLVM for struct _message_ref_t*
  llvm::Type *MessageRefPtrTy;
  // MessageRefCPtrTy - clang type for struct _message_ref_t*
  QualType MessageRefCPtrTy;

  // SuperMessageRefTy - LLVM for:
  // struct _super_message_ref_t {
  //   SUPER_IMP messenger;
  //   SEL name;
  // };
  llvm::StructType *SuperMessageRefTy;

  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
  llvm::PointerType *SuperMessageRefPtrTy;

  llvm::FunctionCallee getMessageSendFixupFn() {
    // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
    llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSend_fixup");
  }

  llvm::FunctionCallee getMessageSendFpretFixupFn() {
    // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
    llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSend_fpret_fixup");
  }

  llvm::FunctionCallee getMessageSendStretFixupFn() {
    // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
    llvm::Type *params[] = {ObjectPtrTy, MessageRefPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSend_stret_fixup");
  }

  llvm::FunctionCallee getMessageSendSuper2FixupFn() {
    // id objc_msgSendSuper2_fixup (struct objc_super *,
    //                              struct _super_message_ref_t*, ...)
    llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSendSuper2_fixup");
  }

  llvm::FunctionCallee getMessageSendSuper2StretFixupFn() {
    // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
    //                                   struct _super_message_ref_t*, ...)
    llvm::Type *params[] = {SuperPtrTy, SuperMessageRefPtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ObjectPtrTy, params, true),
        "objc_msgSendSuper2_stret_fixup");
  }

  llvm::FunctionCallee getObjCEndCatchFn() {
    return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.VoidTy, false),
                                     "objc_end_catch");
  }

  llvm::FunctionCallee getObjCBeginCatchFn() {
    llvm::Type *params[] = {Int8PtrTy};
    return CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(Int8PtrTy, params, false), "objc_begin_catch");
  }

  /// Class objc_loadClassref (void *)
  ///
  /// Loads from a classref. For Objective-C stub classes, this invokes the
  /// initialization callback stored inside the stub. For all other classes
  /// this simply dereferences the pointer.
  llvm::FunctionCallee getLoadClassrefFn() const {
    // Add the non-lazy-bind attribute, since objc_loadClassref is likely to
    // be called a lot.
    //
    // Also it is safe to make it readnone, since we never load or store the
    // classref except by calling this function.
    llvm::Type *params[] = {Int8PtrPtrTy};
    llvm::LLVMContext &C = CGM.getLLVMContext();
    llvm::AttributeSet AS = llvm::AttributeSet::get(
        C, {
               llvm::Attribute::get(C, llvm::Attribute::NonLazyBind),
               llvm::Attribute::getWithMemoryEffects(
                   C, llvm::MemoryEffects::none()),
               llvm::Attribute::get(C, llvm::Attribute::NoUnwind),
           });
    llvm::FunctionCallee F = CGM.CreateRuntimeFunction(
        llvm::FunctionType::get(ClassnfABIPtrTy, params, false),
        "objc_loadClassref",
        llvm::AttributeList::get(CGM.getLLVMContext(),
                                 llvm::AttributeList::FunctionIndex, AS));
    if (!CGM.getTriple().isOSBinFormatCOFF())
      cast<llvm::Function>(F.getCallee())
          ->setLinkage(llvm::Function::ExternalWeakLinkage);

    return F;
  }

  llvm::StructType *EHTypeTy;
  llvm::Type *EHTypePtrTy;

  ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
};

enum class ObjCLabelType {
  ClassName,
  MethodVarName,
  MethodVarType,
  PropertyName,
};

class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
public:
  class SKIP_SCAN {
  public:
    unsigned skip;
    unsigned scan;
    SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
        : skip(_skip), scan(_scan) {}
  };

  // clang-format off
  /// opcode for captured block variables layout 'instructions'.
  /// In the following descriptions, 'I' is the value of the immediate field.
  /// (field following the opcode).
  ///
  enum BLOCK_LAYOUT_OPCODE {
    /// An operator which affects how the following layout should be
    /// interpreted.
    ///   I == 0: Halt interpretation and treat everything else as
    ///           a non-pointer.  Note that this instruction is equal
    ///           to '\0'.
    ///   I != 0: Currently unused.
    BLOCK_LAYOUT_OPERATOR            = 0,

    /// The next I+1 bytes do not contain a value of object pointer type.
    /// Note that this can leave the stream unaligned, meaning that
    /// subsequent word-size instructions do not begin at a multiple of
    /// the pointer size.
    BLOCK_LAYOUT_NON_OBJECT_BYTES    = 1,

    /// The next I+1 words do not contain a value of object pointer type.
    /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for
    /// when the required skip quantity is a multiple of the pointer size.
    BLOCK_LAYOUT_NON_OBJECT_WORDS    = 2,

    /// The next I+1 words are __strong pointers to Objective-C
    /// objects or blocks.
    BLOCK_LAYOUT_STRONG              = 3,

    /// The next I+1 words are pointers to __block variables.
    BLOCK_LAYOUT_BYREF               = 4,

    /// The next I+1 words are __weak pointers to Objective-C
    /// objects or blocks.
    BLOCK_LAYOUT_WEAK                = 5,

    /// The next I+1 words are __unsafe_unretained pointers to
    /// Objective-C objects or blocks.
    BLOCK_LAYOUT_UNRETAINED          = 6

    /// The next I+1 words are block or object pointers with some
    /// as-yet-unspecified ownership semantics.  If we add more
    /// flavors of ownership semantics, values will be taken from
    /// this range.
    ///
    /// This is included so that older tools can at least continue
    /// processing the layout past such things.
    // BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10,

    /// All other opcodes are reserved.  Halt interpretation and
    /// treat everything else as opaque.
  };
  // clang-format on

  class RUN_SKIP {
  public:
    enum BLOCK_LAYOUT_OPCODE opcode;
    CharUnits block_var_bytepos;
    CharUnits block_var_size;
    RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
             CharUnits BytePos = CharUnits::Zero(),
             CharUnits Size = CharUnits::Zero())
        : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}

    // Allow sorting based on byte pos.
    bool operator<(const RUN_SKIP &b) const {
      return block_var_bytepos < b.block_var_bytepos;
    }
  };

protected:
  llvm::LLVMContext &VMContext;
  // FIXME! May not be needing this after all.
  unsigned ObjCABI;

  // arc/mrr layout of captured block literal variables.
  SmallVector<RUN_SKIP, 16> RunSkipBlockVars;

  /// LazySymbols - Symbols to generate a lazy reference for. See
  /// DefinedSymbols and FinishModule().
  llvm::SetVector<IdentifierInfo *> LazySymbols;

  /// DefinedSymbols - External symbols which are defined by this
  /// module. The symbols in this list and LazySymbols are used to add
  /// special linker symbols which ensure that Objective-C modules are
  /// linked properly.
  llvm::SetVector<IdentifierInfo *> DefinedSymbols;

  /// ClassNames - uniqued class names.
  llvm::StringMap<llvm::GlobalVariable *> ClassNames;

  /// MethodVarNames - uniqued method variable names.
  llvm::DenseMap<Selector, llvm::GlobalVariable *> MethodVarNames;

  /// DefinedCategoryNames - list of category names in form Class_Category.
  llvm::SmallSetVector<llvm::CachedHashString, 16> DefinedCategoryNames;

  /// MethodVarTypes - uniqued method type signatures. We have to use
  /// a StringMap here because have no other unique reference.
  llvm::StringMap<llvm::GlobalVariable *> MethodVarTypes;

  /// MethodDefinitions - map of methods which have been defined in
  /// this translation unit.
  llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *> MethodDefinitions;

  /// DirectMethodDefinitions - map of direct methods which have been defined in
  /// this translation unit.
  llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
      DirectMethodDefinitions;

  /// PropertyNames - uniqued method variable names.
  llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> PropertyNames;

  /// ClassReferences - uniqued class references.
  llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> ClassReferences;

  /// SelectorReferences - uniqued selector references.
  llvm::DenseMap<Selector, llvm::GlobalVariable *> SelectorReferences;

  /// Protocols - Protocols for which an objc_protocol structure has
  /// been emitted. Forward declarations are handled by creating an
  /// empty structure whose initializer is filled in when/if defined.
  llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> Protocols;

  /// DefinedProtocols - Protocols which have actually been
  /// defined. We should not need this, see FIXME in GenerateProtocol.
  llvm::DenseSet<IdentifierInfo *> DefinedProtocols;

  /// DefinedClasses - List of defined classes.
  SmallVector<llvm::GlobalValue *, 16> DefinedClasses;

  /// ImplementedClasses - List of @implemented classes.
  SmallVector<const ObjCInterfaceDecl *, 16> ImplementedClasses;

  /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
  SmallVector<llvm::GlobalValue *, 16> DefinedNonLazyClasses;

  /// DefinedCategories - List of defined categories.
  SmallVector<llvm::GlobalValue *, 16> DefinedCategories;

  /// DefinedStubCategories - List of defined categories on class stubs.
  SmallVector<llvm::GlobalValue *, 16> DefinedStubCategories;

  /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
  SmallVector<llvm::GlobalValue *, 16> DefinedNonLazyCategories;

  /// Cached reference to the class for constant strings. This value has type
  /// int * but is actually an Obj-C class pointer.
  llvm::WeakTrackingVH ConstantStringClassRef;

  /// The LLVM type corresponding to NSConstantString.
  llvm::StructType *NSConstantStringType = nullptr;

  llvm::StringMap<llvm::GlobalVariable *> NSConstantStringMap;

  /// GetMethodVarName - Return a unique constant for the given
  /// selector's name. The return value has type char *.
  llvm::Constant *GetMethodVarName(Selector Sel);
  llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);

  /// GetMethodVarType - Return a unique constant for the given
  /// method's type encoding string. The return value has type char *.

  // FIXME: This is a horrible name.
  llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D,
                                   bool Extended = false);
  llvm::Constant *GetMethodVarType(const FieldDecl *D);

  /// GetPropertyName - Return a unique constant for the given
  /// name. The return value has type char *.
  llvm::Constant *GetPropertyName(IdentifierInfo *Ident);

  // FIXME: This can be dropped once string functions are unified.
  llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
                                        const Decl *Container);

  /// GetClassName - Return a unique constant for the given selector's
  /// runtime name (which may change via use of objc_runtime_name attribute on
  /// class or protocol definition. The return value has type char *.
  llvm::Constant *GetClassName(StringRef RuntimeName);

  llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD);

  /// BuildIvarLayout - Builds ivar layout bitmap for the class
  /// implementation for the __strong or __weak case.
  ///
  /// \param hasMRCWeakIvars - Whether we are compiling in MRC and there
  ///   are any weak ivars defined directly in the class.  Meaningless unless
  ///   building a weak layout.  Does not guarantee that the layout will
  ///   actually have any entries, because the ivar might be under-aligned.
  llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
                                  CharUnits beginOffset, CharUnits endOffset,
                                  bool forStrongLayout, bool hasMRCWeakIvars);

  llvm::Constant *BuildStrongIvarLayout(const ObjCImplementationDecl *OI,
                                        CharUnits beginOffset,
                                        CharUnits endOffset) {
    return BuildIvarLayout(OI, beginOffset, endOffset, true, false);
  }

  llvm::Constant *BuildWeakIvarLayout(const ObjCImplementationDecl *OI,
                                      CharUnits beginOffset,
                                      CharUnits endOffset,
                                      bool hasMRCWeakIvars) {
    return BuildIvarLayout(OI, beginOffset, endOffset, false, hasMRCWeakIvars);
  }

  Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT,
                                                   bool ByrefLayout);

  void UpdateRunSkipBlockVars(bool IsByref, Qualifiers::ObjCLifetime LifeTime,
                              CharUnits FieldOffset, CharUnits FieldSize);

  void BuildRCBlockVarRecordLayout(const RecordType *RT, CharUnits BytePos,
                                   bool &HasUnion, bool ByrefLayout = false);

  void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
                           const RecordDecl *RD,
                           ArrayRef<const FieldDecl *> RecFields,
                           CharUnits BytePos, bool &HasUnion, bool ByrefLayout);

  uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);

  llvm::Constant *getBitmapBlockLayout(bool ComputeByrefLayout);

  /// GetIvarLayoutName - Returns a unique constant for the given
  /// ivar layout bitmap.
  llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
                                    const ObjCCommonTypesHelper &ObjCTypes);

  /// EmitPropertyList - Emit the given property list. The return
  /// value has type PropertyListPtrTy.
  llvm::Constant *EmitPropertyList(Twine Name, const Decl *Container,
                                   const ObjCContainerDecl *OCD,
                                   const ObjCCommonTypesHelper &ObjCTypes,
                                   bool IsClassProperty);

  /// EmitProtocolMethodTypes - Generate the array of extended method type
  /// strings. The return value has type Int8PtrPtrTy.
  llvm::Constant *
  EmitProtocolMethodTypes(Twine Name, ArrayRef<llvm::Constant *> MethodTypes,
                          const ObjCCommonTypesHelper &ObjCTypes);

  /// GetProtocolRef - Return a reference to the internal protocol
  /// description, creating an empty one if it has not been
  /// defined. The return value has type ProtocolPtrTy.
  llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);

  /// Return a reference to the given Class using runtime calls rather than
  /// by a symbol reference.
  llvm::Value *EmitClassRefViaRuntime(CodeGenFunction &CGF,
                                      const ObjCInterfaceDecl *ID,
                                      ObjCCommonTypesHelper &ObjCTypes);

  std::string GetSectionName(StringRef Section, StringRef MachOAttributes);

public:
  /// CreateMetadataVar - Create a global variable with internal
  /// linkage for use by the Objective-C runtime.
  ///
  /// This is a convenience wrapper which not only creates the
  /// variable, but also sets the section and alignment and adds the
  /// global to the "llvm.used" list.
  ///
  /// \param Name - The variable name.
  /// \param Init - The variable initializer; this is also used to
  ///   define the type of the variable.
  /// \param Section - The section the variable should go into, or empty.
  /// \param Align - The alignment for the variable, or 0.
  /// \param AddToUsed - Whether the variable should be added to
  ///   "llvm.used".
  llvm::GlobalVariable *CreateMetadataVar(Twine Name,
                                          ConstantStructBuilder &Init,
                                          StringRef Section, CharUnits Align,
                                          bool AddToUsed);
  llvm::GlobalVariable *CreateMetadataVar(Twine Name, llvm::Constant *Init,
                                          StringRef Section, CharUnits Align,
                                          bool AddToUsed);

  llvm::GlobalVariable *CreateCStringLiteral(StringRef Name,
                                             ObjCLabelType LabelType,
                                             bool ForceNonFragileABI = false,
                                             bool NullTerminate = true);

protected:
  CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
                                  ReturnValueSlot Return, QualType ResultType,
                                  Selector Sel, llvm::Value *Arg0,
                                  QualType Arg0Ty, bool IsSuper,
                                  const CallArgList &CallArgs,
                                  const ObjCMethodDecl *OMD,
                                  const ObjCInterfaceDecl *ClassReceiver,
                                  const ObjCCommonTypesHelper &ObjCTypes);

  /// EmitImageInfo - Emit the image info marker used to encode some module
  /// level information.
  void EmitImageInfo();

public:
  CGObjCCommonMac(CodeGen::CodeGenModule &cgm)
      : CGObjCRuntime(cgm), VMContext(cgm.getLLVMContext()) {}

  bool isNonFragileABI() const { return ObjCABI == 2; }

  ConstantAddress GenerateConstantString(const StringLiteral *SL) override;
  ConstantAddress GenerateConstantNSString(const StringLiteral *SL);

  llvm::Function *
  GenerateMethod(const ObjCMethodDecl *OMD,
                 const ObjCContainerDecl *CD = nullptr) override;

  llvm::Function *GenerateDirectMethod(const ObjCMethodDecl *OMD,
                                       const ObjCContainerDecl *CD);

  void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
                                    const ObjCMethodDecl *OMD,
                                    const ObjCContainerDecl *CD) override;

  void GenerateProtocol(const ObjCProtocolDecl *PD) override;

  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
  /// object for the given declaration, emitting it if needed. These
  /// forward references will be filled in with empty bodies if no
  /// definition is seen. The return value has type ProtocolPtrTy.
  virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) = 0;

  virtual llvm::Constant *getNSConstantStringClassRef() = 0;

  llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM,
                                     const CGBlockInfo &blockInfo) override;
  llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM,
                                     const CGBlockInfo &blockInfo) override;
  std::string getRCBlockLayoutStr(CodeGen::CodeGenModule &CGM,
                                  const CGBlockInfo &blockInfo) override;

  llvm::Constant *BuildByrefLayout(CodeGen::CodeGenModule &CGM,
                                   QualType T) override;

private:
  void fillRunSkipBlockVars(CodeGenModule &CGM, const CGBlockInfo &blockInfo);
};

namespace {

enum class MethodListType {
  CategoryInstanceMethods,
  CategoryClassMethods,
  InstanceMethods,
  ClassMethods,
  ProtocolInstanceMethods,
  ProtocolClassMethods,
  OptionalProtocolInstanceMethods,
  OptionalProtocolClassMethods,
};

/// A convenience class for splitting the methods of a protocol into
/// the four interesting groups.
class ProtocolMethodLists {
public:
  enum Kind {
    RequiredInstanceMethods,
    RequiredClassMethods,
    OptionalInstanceMethods,
    OptionalClassMethods
  };
  enum { NumProtocolMethodLists = 4 };

  static MethodListType getMethodListKind(Kind kind) {
    switch (kind) {
    case RequiredInstanceMethods:
      return MethodListType::ProtocolInstanceMethods;
    case RequiredClassMethods:
      return MethodListType::ProtocolClassMethods;
    case OptionalInstanceMethods:
      return MethodListType::OptionalProtocolInstanceMethods;
    case OptionalClassMethods:
      return MethodListType::OptionalProtocolClassMethods;
    }
    llvm_unreachable("bad kind");
  }

  SmallVector<const ObjCMethodDecl *, 4> Methods[NumProtocolMethodLists];

  static ProtocolMethodLists get(const ObjCProtocolDecl *PD) {
    ProtocolMethodLists result;

    for (auto *MD : PD->methods()) {
      size_t index =
          (2 * size_t(MD->isOptional())) + (size_t(MD->isClassMethod()));
      result.Methods[index].push_back(MD);
    }

    return result;
  }

  template <class Self>
  SmallVector<llvm::Constant *, 8> emitExtendedTypesArray(Self *self) const {
    // In both ABIs, the method types list is parallel with the
    // concatenation of the methods arrays in the following order:
    //   instance methods
    //   class methods
    //   optional instance methods
    //   optional class methods
    SmallVector<llvm::Constant *, 8> result;

    // Methods is already in the correct order for both ABIs.
    for (auto &list : Methods) {
      for (auto MD : list) {
        result.push_back(self->GetMethodVarType(MD, true));
      }
    }

    return result;
  }

  template <class Self>
  llvm::Constant *emitMethodList(Self *self, const ObjCProtocolDecl *PD,
                                 Kind kind) const {
    return self->emitMethodList(PD->getObjCRuntimeNameAsString(),
                                getMethodListKind(kind), Methods[kind]);
  }
};

} // end anonymous namespace

class CGObjCMac : public CGObjCCommonMac {
private:
  friend ProtocolMethodLists;

  ObjCTypesHelper ObjCTypes;

  /// EmitModuleInfo - Another marker encoding module level
  /// information.
  void EmitModuleInfo();

  /// EmitModuleSymols - Emit module symbols, the list of defined
  /// classes and categories. The result has type SymtabPtrTy.
  llvm::Constant *EmitModuleSymbols();

  /// FinishModule - Write out global data structures at the end of
  /// processing a translation unit.
  void FinishModule();

  /// EmitClassExtension - Generate the class extension structure used
  /// to store the weak ivar layout and properties. The return value
  /// has type ClassExtensionPtrTy.
  llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID,
                                     CharUnits instanceSize,
                                     bool hasMRCWeakIvars, bool isMetaclass);

  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
  /// for the given class.
  llvm::Value *EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID);

  llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II);

  llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;

  /// EmitSuperClassRef - Emits reference to class's main metadata class.
  llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);

  /// EmitIvarList - Emit the ivar list for the given
  /// implementation. If ForClass is true the list of class ivars
  /// (i.e. metaclass ivars) is emitted, otherwise the list of
  /// interface ivars will be emitted. The return value has type
  /// IvarListPtrTy.
  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID, bool ForClass);

  /// EmitMetaClass - Emit a forward reference to the class structure
  /// for the metaclass of the given interface. The return value has
  /// type ClassPtrTy.
  llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);

  /// EmitMetaClass - Emit a class structure for the metaclass of the
  /// given implementation. The return value has type ClassPtrTy.
  llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
                                llvm::Constant *Protocols,
                                ArrayRef<const ObjCMethodDecl *> Methods);

  void emitMethodConstant(ConstantArrayBuilder &builder,
                          const ObjCMethodDecl *MD);

  void emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
                                     const ObjCMethodDecl *MD);

  /// EmitMethodList - Emit the method list for the given
  /// implementation. The return value has type MethodListPtrTy.
  llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
                                 ArrayRef<const ObjCMethodDecl *> Methods);

  /// GetOrEmitProtocol - Get the protocol object for the given
  /// declaration, emitting it if necessary. The return value has type
  /// ProtocolPtrTy.
  llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;

  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
  /// object for the given declaration, emitting it if needed. These
  /// forward references will be filled in with empty bodies if no
  /// definition is seen. The return value has type ProtocolPtrTy.
  llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;

  /// EmitProtocolExtension - Generate the protocol extension
  /// structure used to store optional instance and class methods, and
  /// protocol properties. The return value has type
  /// ProtocolExtensionPtrTy.
  llvm::Constant *EmitProtocolExtension(const ObjCProtocolDecl *PD,
                                        const ProtocolMethodLists &methodLists);

  /// EmitProtocolList - Generate the list of referenced
  /// protocols. The return value has type ProtocolListPtrTy.
  llvm::Constant *EmitProtocolList(Twine Name,
                                   ObjCProtocolDecl::protocol_iterator begin,
                                   ObjCProtocolDecl::protocol_iterator end);

  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
  /// for the given selector.
  llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
  ConstantAddress EmitSelectorAddr(Selector Sel);

public:
  CGObjCMac(CodeGen::CodeGenModule &cgm);

  llvm::Constant *getNSConstantStringClassRef() override;

  llvm::Function *ModuleInitFunction() override;

  CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                                      ReturnValueSlot Return,
                                      QualType ResultType, Selector Sel,
                                      llvm::Value *Receiver,
                                      const CallArgList &CallArgs,
                                      const ObjCInterfaceDecl *Class,
                                      const ObjCMethodDecl *Method) override;

  CodeGen::RValue GenerateMessageSendSuper(
      CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
      QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class,
      bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage,
      const CallArgList &CallArgs, const ObjCMethodDecl *Method) override;

  llvm::Value *GetClass(CodeGenFunction &CGF,
                        const ObjCInterfaceDecl *ID) override;

  llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
  Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;

  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
  /// untyped one.
  llvm::Value *GetSelector(CodeGenFunction &CGF,
                           const ObjCMethodDecl *Method) override;

  llvm::Constant *GetEHType(QualType T) override;

  void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;

  void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;

  void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}

  llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
                                   const ObjCProtocolDecl *PD) override;

  llvm::FunctionCallee GetPropertyGetFunction() override;
  llvm::FunctionCallee GetPropertySetFunction() override;
  llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
                                                       bool copy) override;
  llvm::FunctionCallee GetGetStructFunction() override;
  llvm::FunctionCallee GetSetStructFunction() override;
  llvm::FunctionCallee GetCppAtomicObjectGetFunction() override;
  llvm::FunctionCallee GetCppAtomicObjectSetFunction() override;
  llvm::FunctionCallee EnumerationMutationFunction() override;

  void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
                   const ObjCAtTryStmt &S) override;
  void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
                            const ObjCAtSynchronizedStmt &S) override;
  void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
  void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
                     bool ClearInsertionPoint = true) override;
  llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
                                Address AddrWeakObj) override;
  void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                          Address dst) override;
  void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                            Address dest, bool threadlocal = false) override;
  void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                          Address dest, llvm::Value *ivarOffset) override;
  void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                                Address dest) override;
  void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest,
                                Address src, llvm::Value *size) override;

  LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
                              llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
                              unsigned CVRQualifiers) override;
  llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                              const ObjCInterfaceDecl *Interface,
                              const ObjCIvarDecl *Ivar) override;
};

class CGObjCNonFragileABIMac : public CGObjCCommonMac {
private:
  friend ProtocolMethodLists;
  ObjCNonFragileABITypesHelper ObjCTypes;
  llvm::GlobalVariable *ObjCEmptyCacheVar;
  llvm::Constant *ObjCEmptyVtableVar;

  /// SuperClassReferences - uniqued super class references.
  llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> SuperClassReferences;

  /// MetaClassReferences - uniqued meta class references.
  llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> MetaClassReferences;

  /// EHTypeReferences - uniqued class ehtype references.
  llvm::DenseMap<IdentifierInfo *, llvm::GlobalVariable *> EHTypeReferences;

  /// VTableDispatchMethods - List of methods for which we generate
  /// vtable-based message dispatch.
  llvm::DenseSet<Selector> VTableDispatchMethods;

  /// DefinedMetaClasses - List of defined meta-classes.
  std::vector<llvm::GlobalValue *> DefinedMetaClasses;

  /// isVTableDispatchedSelector - Returns true if SEL is a
  /// vtable-based selector.
  bool isVTableDispatchedSelector(Selector Sel);

  /// FinishNonFragileABIModule - Write out global data structures at the end of
  /// processing a translation unit.
  void FinishNonFragileABIModule();

  /// AddModuleClassList - Add the given list of class pointers to the
  /// module with the provided symbol and section names.
  void AddModuleClassList(ArrayRef<llvm::GlobalValue *> Container,
                          StringRef SymbolName, StringRef SectionName);

  llvm::GlobalVariable *
  BuildClassRoTInitializer(unsigned flags, unsigned InstanceStart,
                           unsigned InstanceSize,
                           const ObjCImplementationDecl *ID);
  llvm::GlobalVariable *
  BuildClassObject(const ObjCInterfaceDecl *CI, bool isMetaclass,
                   llvm::Constant *IsAGV, llvm::Constant *SuperClassGV,
                   llvm::Constant *ClassRoGV, bool HiddenVisibility);

  void emitMethodConstant(ConstantArrayBuilder &builder,
                          const ObjCMethodDecl *MD, bool forProtocol);

  /// Emit the method list for the given implementation. The return value
  /// has type MethodListnfABITy.
  llvm::Constant *emitMethodList(Twine Name, MethodListType MLT,
                                 ArrayRef<const ObjCMethodDecl *> Methods);

  /// EmitIvarList - Emit the ivar list for the given
  /// implementation. If ForClass is true the list of class ivars
  /// (i.e. metaclass ivars) is emitted, otherwise the list of
  /// interface ivars will be emitted. The return value has type
  /// IvarListnfABIPtrTy.
  llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);

  llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
                                    const ObjCIvarDecl *Ivar,
                                    unsigned long int offset);

  /// GetOrEmitProtocol - Get the protocol object for the given
  /// declaration, emitting it if necessary. The return value has type
  /// ProtocolPtrTy.
  llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override;

  /// GetOrEmitProtocolRef - Get a forward reference to the protocol
  /// object for the given declaration, emitting it if needed. These
  /// forward references will be filled in with empty bodies if no
  /// definition is seen. The return value has type ProtocolPtrTy.
  llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) override;

  /// EmitProtocolList - Generate the list of referenced
  /// protocols. The return value has type ProtocolListPtrTy.
  llvm::Constant *EmitProtocolList(Twine Name,
                                   ObjCProtocolDecl::protocol_iterator begin,
                                   ObjCProtocolDecl::protocol_iterator end);

  CodeGen::RValue EmitVTableMessageSend(
      CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
      QualType ResultType, Selector Sel, llvm::Value *Receiver, QualType Arg0Ty,
      bool IsSuper, const CallArgList &CallArgs, const ObjCMethodDecl *Method);

  /// GetClassGlobal - Return the global variable for the Objective-C
  /// class of the given name.
  llvm::Constant *GetClassGlobal(StringRef Name,
                                 ForDefinition_t IsForDefinition,
                                 bool Weak = false, bool DLLImport = false);
  llvm::Constant *GetClassGlobal(const ObjCInterfaceDecl *ID, bool isMetaclass,
                                 ForDefinition_t isForDefinition);

  llvm::Constant *GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID);

  llvm::Value *EmitLoadOfClassRef(CodeGenFunction &CGF,
                                  const ObjCInterfaceDecl *ID,
                                  llvm::GlobalVariable *Entry);

  /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
  /// for the given class reference.
  llvm::Value *EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID);

  llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II,
                                  const ObjCInterfaceDecl *ID);

  llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;

  /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
  /// for the given super class reference.
  llvm::Value *EmitSuperClassRef(CodeGenFunction &CGF,
                                 const ObjCInterfaceDecl *ID);

  /// EmitMetaClassRef - Return a Value * of the address of _class_t
  /// meta-data
  llvm::Value *EmitMetaClassRef(CodeGenFunction &CGF,
                                const ObjCInterfaceDecl *ID, bool Weak);

  /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
  /// the given ivar.
  ///
  llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
                                               const ObjCIvarDecl *Ivar);

  /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
  /// for the given selector.
  llvm::Value *EmitSelector(CodeGenFunction &CGF, Selector Sel);
  ConstantAddress EmitSelectorAddr(Selector Sel);

  /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
  /// interface. The return value has type EHTypePtrTy.
  llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
                                     ForDefinition_t IsForDefinition);

  StringRef getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; }

  StringRef getClassSymbolPrefix() const { return "OBJC_CLASS_$_"; }

  void GetClassSizeInfo(const ObjCImplementationDecl *OID,
                        uint32_t &InstanceStart, uint32_t &InstanceSize);

  // Shamelessly stolen from Analysis/CFRefCount.cpp
  Selector GetNullarySelector(const char *name) const {
    const IdentifierInfo *II = &CGM.getContext().Idents.get(name);
    return CGM.getContext().Selectors.getSelector(0, &II);
  }

  Selector GetUnarySelector(const char *name) const {
    const IdentifierInfo *II = &CGM.getContext().Idents.get(name);
    return CGM.getContext().Selectors.getSelector(1, &II);
  }

  /// ImplementationIsNonLazy - Check whether the given category or
  /// class implementation is "non-lazy".
  bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;

  bool IsIvarOffsetKnownIdempotent(const CodeGen::CodeGenFunction &CGF,
                                   const ObjCIvarDecl *IV) {
    // Annotate the load as an invariant load iff inside an instance method
    // and ivar belongs to instance method's class and one of its super class.
    // This check is needed because the ivar offset is a lazily
    // initialised value that may depend on objc_msgSend to perform a fixup on
    // the first message dispatch.
    //
    // An additional opportunity to mark the load as invariant arises when the
    // base of the ivar access is a parameter to an Objective C method.
    // However, because the parameters are not available in the current
    // interface, we cannot perform this check.
    //
    // Note that for direct methods, because objc_msgSend is skipped,
    // and that the method may be inlined, this optimization actually
    // can't be performed.
    if (const ObjCMethodDecl *MD =
            dyn_cast_or_null<ObjCMethodDecl>(CGF.CurFuncDecl))
      if (MD->isInstanceMethod() && !MD->isDirectMethod())
        if (const ObjCInterfaceDecl *ID = MD->getClassInterface())
          return IV->getContainingInterface()->isSuperClassOf(ID);
    return false;
  }

  bool isClassLayoutKnownStatically(const ObjCInterfaceDecl *ID) {
    // Test a class by checking its superclasses up to
    // its base class if it has one.
    assert(ID != nullptr && "Passed a null class to check layout");
    for (; ID != nullptr; ID = ID->getSuperClass()) {
      // The layout of base class NSObject
      // is guaranteed to be statically known
      if (ID->getIdentifier()->getName() == "NSObject")
        return true;

      // If we cannot see the @implementation of a class,
      // we cannot statically know the class layout.
      if (!ID->getImplementation())
        return false;
    }

    // We know the layout of all the intermediate classes and superclasses.
    return true;
  }

public:
  CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);

  llvm::Constant *getNSConstantStringClassRef() override;

  llvm::Function *ModuleInitFunction() override;

  CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
                                      ReturnValueSlot Return,
                                      QualType ResultType, Selector Sel,
                                      llvm::Value *Receiver,
                                      const CallArgList &CallArgs,
                                      const ObjCInterfaceDecl *Class,
                                      const ObjCMethodDecl *Method) override;

  CodeGen::RValue GenerateMessageSendSuper(
      CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return,
      QualType ResultType, Selector Sel, const ObjCInterfaceDecl *Class,
      bool isCategoryImpl, llvm::Value *Receiver, bool IsClassMessage,
      const CallArgList &CallArgs, const ObjCMethodDecl *Method) override;

  llvm::Value *GetClass(CodeGenFunction &CGF,
                        const ObjCInterfaceDecl *ID) override;

  llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override {
    return EmitSelector(CGF, Sel);
  }
  Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override {
    return EmitSelectorAddr(Sel);
  }

  /// The NeXT/Apple runtimes do not support typed selectors; just emit an
  /// untyped one.
  llvm::Value *GetSelector(CodeGenFunction &CGF,
                           const ObjCMethodDecl *Method) override {
    return EmitSelector(CGF, Method->getSelector());
  }

  void GenerateCategory(const ObjCCategoryImplDecl *CMD) override;

  void GenerateClass(const ObjCImplementationDecl *ClassDecl) override;

  void RegisterAlias(const ObjCCompatibleAliasDecl *OAD) override {}

  llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
                                   const ObjCProtocolDecl *PD) override;

  llvm::Constant *GetEHType(QualType T) override;

  llvm::FunctionCallee GetPropertyGetFunction() override {
    return ObjCTypes.getGetPropertyFn();
  }
  llvm::FunctionCallee GetPropertySetFunction() override {
    return ObjCTypes.getSetPropertyFn();
  }

  llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
                                                       bool copy) override {
    return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
  }

  llvm::FunctionCallee GetSetStructFunction() override {
    return ObjCTypes.getCopyStructFn();
  }

  llvm::FunctionCallee GetGetStructFunction() override {
    return ObjCTypes.getCopyStructFn();
  }

  llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
    return ObjCTypes.getCppAtomicObjectFunction();
  }

  llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
    return ObjCTypes.getCppAtomicObjectFunction();
  }

  llvm::FunctionCallee EnumerationMutationFunction() override {
    return ObjCTypes.getEnumerationMutationFn();
  }

  void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
                   const ObjCAtTryStmt &S) override;
  void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
                            const ObjCAtSynchronizedStmt &S) override;
  void EmitThrowStmt(CodeGen::CodeGenFunction &CGF, const ObjCAtThrowStmt &S,
                     bool ClearInsertionPoint = true) override;
  llvm::Value *EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
                                Address AddrWeakObj) override;
  void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                          Address edst) override;
  void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                            Address dest, bool threadlocal = false) override;
  void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                          Address dest, llvm::Value *ivarOffset) override;
  void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src,
                                Address dest) override;
  void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF, Address dest,
                                Address src, llvm::Value *size) override;
  LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF, QualType ObjectTy,
                              llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
                              unsigned CVRQualifiers) override;
  llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                              const ObjCInterfaceDecl *Interface,
                              const ObjCIvarDecl *Ivar) override;
};

/// A helper class for performing the null-initialization of a return
/// value.
struct NullReturnState {
  llvm::BasicBlock *NullBB = nullptr;
  NullReturnState() = default;

  /// Perform a null-check of the given receiver.
  void init(CodeGenFunction &CGF, llvm::Value *receiver) {
    // Make blocks for the null-receiver and call edges.
    NullBB = CGF.createBasicBlock("msgSend.null-receiver");
    llvm::BasicBlock *callBB = CGF.createBasicBlock("msgSend.call");

    // Check for a null receiver and, if there is one, jump to the
    // null-receiver block.  There's no point in trying to avoid it:
    // we're always going to put *something* there, because otherwise
    // we shouldn't have done this null-check in the first place.
    llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
    CGF.Builder.CreateCondBr(isNull, NullBB, callBB);

    // Otherwise, start performing the call.
    CGF.EmitBlock(callBB);
  }

  /// Complete the null-return operation.  It is valid to call this
  /// regardless of whether 'init' has been called.
  RValue complete(CodeGenFunction &CGF, ReturnValueSlot returnSlot,
                  RValue result, QualType resultType,
                  const CallArgList &CallArgs, const ObjCMethodDecl *Method) {
    // If we never had to do a null-check, just use the raw result.
    if (!NullBB)
      return result;

    // The continuation block.  This will be left null if we don't have an
    // IP, which can happen if the method we're calling is marked noreturn.
    llvm::BasicBlock *contBB = nullptr;

    // Finish the call path.
    llvm::BasicBlock *callBB = CGF.Builder.GetInsertBlock();
    if (callBB) {
      contBB = CGF.createBasicBlock("msgSend.cont");
      CGF.Builder.CreateBr(contBB);
    }

    // Okay, start emitting the null-receiver block.
    CGF.EmitBlock(NullBB);

    // Destroy any consumed arguments we've got.
    if (Method) {
      CGObjCRuntime::destroyCalleeDestroyedArguments(CGF, Method, CallArgs);
    }

    // The phi code below assumes that we haven't needed any control flow yet.
    assert(CGF.Builder.GetInsertBlock() == NullBB);

    // If we've got a void return, just jump to the continuation block.
    if (result.isScalar() && resultType->isVoidType()) {
      // No jumps required if the message-send was noreturn.
      if (contBB)
        CGF.EmitBlock(contBB);
      return result;
    }

    // If we've got a scalar return, build a phi.
    if (result.isScalar()) {
      // Derive the null-initialization value.
      llvm::Value *null =
          CGF.EmitFromMemory(CGF.CGM.EmitNullConstant(resultType), resultType);

      // If no join is necessary, just flow out.
      if (!contBB)
        return RValue::get(null);

      // Otherwise, build a phi.
      CGF.EmitBlock(contBB);
      llvm::PHINode *phi = CGF.Builder.CreatePHI(null->getType(), 2);
      phi->addIncoming(result.getScalarVal(), callBB);
      phi->addIncoming(null, NullBB);
      return RValue::get(phi);
    }

    // If we've got an aggregate return, null the buffer out.
    // FIXME: maybe we should be doing things differently for all the
    // cases where the ABI has us returning (1) non-agg values in
    // memory or (2) agg values in registers.
    if (result.isAggregate()) {
      assert(result.isAggregate() && "null init of non-aggregate result?");
      if (!returnSlot.isUnused())
        CGF.EmitNullInitialization(result.getAggregateAddress(), resultType);
      if (contBB)
        CGF.EmitBlock(contBB);
      return result;
    }

    // Complex types.
    CGF.EmitBlock(contBB);
    CodeGenFunction::ComplexPairTy callResult = result.getComplexVal();

    // Find the scalar type and its zero value.
    llvm::Type *scalarTy = callResult.first->getType();
    llvm::Constant *scalarZero = llvm::Constant::getNullValue(scalarTy);

    // Build phis for both coordinates.
    llvm::PHINode *real = CGF.Builder.CreatePHI(scalarTy, 2);
    real->addIncoming(callResult.first, callBB);
    real->addIncoming(scalarZero, NullBB);
    llvm::PHINode *imag = CGF.Builder.CreatePHI(scalarTy, 2);
    imag->addIncoming(callResult.second, callBB);
    imag->addIncoming(scalarZero, NullBB);
    return RValue::getComplex(real, imag);
  }
};

} // end anonymous namespace

/* *** Helper Functions *** */

/// getConstantGEP() - Help routine to construct simple GEPs.
static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
                                      llvm::GlobalVariable *C, unsigned idx0,
                                      unsigned idx1) {
  llvm::Value *Idxs[] = {
      llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
      llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)};
  return llvm::ConstantExpr::getGetElementPtr(C->getValueType(), C, Idxs);
}

/// hasObjCExceptionAttribute - Return true if this class or any super
/// class has the __objc_exception__ attribute.
static bool hasObjCExceptionAttribute(ASTContext &Context,
                                      const ObjCInterfaceDecl *OID) {
  if (OID->hasAttr<ObjCExceptionAttr>())
    return true;
  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
    return hasObjCExceptionAttribute(Context, Super);
  return false;
}

static llvm::GlobalValue::LinkageTypes
getLinkageTypeForObjCMetadata(CodeGenModule &CGM, StringRef Section) {
  if (CGM.getTriple().isOSBinFormatMachO() &&
      (Section.empty() || Section.starts_with("__DATA")))
    return llvm::GlobalValue::InternalLinkage;
  return llvm::GlobalValue::PrivateLinkage;
}

/// A helper function to create an internal or private global variable.
static llvm::GlobalVariable *
finishAndCreateGlobal(ConstantInitBuilder::StructBuilder &Builder,
                      const llvm::Twine &Name, CodeGenModule &CGM) {
  std::string SectionName;
  if (CGM.getTriple().isOSBinFormatMachO())
    SectionName = "__DATA, __objc_const";
  auto *GV = Builder.finishAndCreateGlobal(
      Name, CGM.getPointerAlign(), /*constant*/ false,
      getLinkageTypeForObjCMetadata(CGM, SectionName));
  GV->setSection(SectionName);
  return GV;
}

/* *** CGObjCMac Public Interface *** */

CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm)
    : CGObjCCommonMac(cgm), ObjCTypes(cgm) {
  ObjCABI = 1;
  EmitImageInfo();
}

/// GetClass - Return a reference to the class for the given interface
/// decl.
llvm::Value *CGObjCMac::GetClass(CodeGenFunction &CGF,
                                 const ObjCInterfaceDecl *ID) {
  return EmitClassRef(CGF, ID);
}

/// GetSelector - Return the pointer to the unique'd string for this selector.
llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF, Selector Sel) {
  return EmitSelector(CGF, Sel);
}
Address CGObjCMac::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
  return EmitSelectorAddr(Sel);
}
llvm::Value *CGObjCMac::GetSelector(CodeGenFunction &CGF,
                                    const ObjCMethodDecl *Method) {
  return EmitSelector(CGF, Method->getSelector());
}

llvm::Constant *CGObjCMac::GetEHType(QualType T) {
  if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
    return CGM.GetAddrOfRTTIDescriptor(
        CGM.getContext().getObjCIdRedefinitionType(), /*ForEH=*/true);
  }
  if (T->isObjCClassType() || T->isObjCQualifiedClassType()) {
    return CGM.GetAddrOfRTTIDescriptor(
        CGM.getContext().getObjCClassRedefinitionType(), /*ForEH=*/true);
  }
  if (T->isObjCObjectPointerType())
    return CGM.GetAddrOfRTTIDescriptor(T, /*ForEH=*/true);

  llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
}

/// Generate a constant CFString object.
/*
  struct __builtin_CFString {
  const int *isa; // point to __CFConstantStringClassReference
  int flags;
  const char *str;
  long length;
  };
*/

/// or Generate a constant NSString object.
/*
   struct __builtin_NSString {
     const int *isa; // point to __NSConstantStringClassReference
     const char *str;
     unsigned int length;
   };
*/

ConstantAddress
CGObjCCommonMac::GenerateConstantString(const StringLiteral *SL) {
  return (!CGM.getLangOpts().NoConstantCFStrings
              ? CGM.GetAddrOfConstantCFString(SL)
              : GenerateConstantNSString(SL));
}

static llvm::StringMapEntry<llvm::GlobalVariable *> &
GetConstantStringEntry(llvm::StringMap<llvm::GlobalVariable *> &Map,
                       const StringLiteral *Literal, unsigned &StringLength) {
  StringRef String = Literal->getString();
  StringLength = String.size();
  return *Map.insert(std::make_pair(String, nullptr)).first;
}

llvm::Constant *CGObjCMac::getNSConstantStringClassRef() {
  if (llvm::Value *V = ConstantStringClassRef)
    return cast<llvm::Constant>(V);

  auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
  std::string str = StringClass.empty() ? "_NSConstantStringClassReference"
                                        : "_" + StringClass + "ClassReference";

  llvm::Type *PTy = llvm::ArrayType::get(CGM.IntTy, 0);
  auto GV = CGM.CreateRuntimeVariable(PTy, str);
  ConstantStringClassRef = GV;
  return GV;
}

llvm::Constant *CGObjCNonFragileABIMac::getNSConstantStringClassRef() {
  if (llvm::Value *V = ConstantStringClassRef)
    return cast<llvm::Constant>(V);

  auto &StringClass = CGM.getLangOpts().ObjCConstantStringClass;
  std::string str = StringClass.empty() ? "OBJC_CLASS_$_NSConstantString"
                                        : "OBJC_CLASS_$_" + StringClass;
  llvm::Constant *GV = GetClassGlobal(str, NotForDefinition);
  ConstantStringClassRef = GV;
  return GV;
}

ConstantAddress
CGObjCCommonMac::GenerateConstantNSString(const StringLiteral *Literal) {
  unsigned StringLength = 0;
  llvm::StringMapEntry<llvm::GlobalVariable *> &Entry =
      GetConstantStringEntry(NSConstantStringMap, Literal, StringLength);

  if (auto *C = Entry.second)
    return ConstantAddress(C, C->getValueType(),
                           CharUnits::fromQuantity(C->getAlignment()));

  // If we don't already have it, get _NSConstantStringClassReference.
  llvm::Constant *Class = getNSConstantStringClassRef();

  // If we don't already have it, construct the type for a constant NSString.
  if (!NSConstantStringType) {
    NSConstantStringType =
        llvm::StructType::create({CGM.UnqualPtrTy, CGM.Int8PtrTy, CGM.IntTy},
                                 "struct.__builtin_NSString");
  }

  ConstantInitBuilder Builder(CGM);
  auto Fields = Builder.beginStruct(NSConstantStringType);

  // Class pointer.
  Fields.addSignedPointer(Class,
                          CGM.getCodeGenOpts().PointerAuth.ObjCIsaPointers,
                          GlobalDecl(), QualType());

  // String pointer.
  llvm::Constant *C =
      llvm::ConstantDataArray::getString(VMContext, Entry.first());

  llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
  bool isConstant = !CGM.getLangOpts().WritableStrings;

  auto *GV = new llvm::GlobalVariable(CGM.getModule(), C->getType(), isConstant,
                                      Linkage, C, ".str");
  GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
  // Don't enforce the target's minimum global alignment, since the only use
  // of the string is via this class initializer.
  GV->setAlignment(llvm::Align(1));
  Fields.add(GV);

  // String length.
  Fields.addInt(CGM.IntTy, StringLength);

  // The struct.
  CharUnits Alignment = CGM.getPointerAlign();
  GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
                                    /*constant*/ true,
                                    llvm::GlobalVariable::PrivateLinkage);
  const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
  const char *NSStringNonFragileABISection =
      "__DATA,__objc_stringobj,regular,no_dead_strip";
  // FIXME. Fix section.
  GV->setSection(CGM.getLangOpts().ObjCRuntime.isNonFragile()
                     ? NSStringNonFragileABISection
                     : NSStringSection);
  Entry.second = GV;

  return ConstantAddress(GV, GV->getValueType(), Alignment);
}

enum { kCFTaggedObjectID_Integer = (1 << 1) + 1 };

/// Generates a message send where the super is the receiver.  This is
/// a message send to self with special delivery semantics indicating
/// which class's method should be called.
CodeGen::RValue CGObjCMac::GenerateMessageSendSuper(
    CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
    Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl,
    llvm::Value *Receiver, bool IsClassMessage,
    const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) {
  // Create and init a super structure; this is a (receiver, class)
  // pair we will pass to objc_msgSendSuper.
  RawAddress ObjCSuper = CGF.CreateTempAlloca(
      ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super");
  llvm::Value *ReceiverAsObject =
      CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
  CGF.Builder.CreateStore(ReceiverAsObject,
                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));

  // If this is a class message the metaclass is passed as the target.
  llvm::Type *ClassTyPtr = llvm::PointerType::getUnqual(VMContext);
  llvm::Value *Target;
  if (IsClassMessage) {
    if (isCategoryImpl) {
      // Message sent to 'super' in a class method defined in a category
      // implementation requires an odd treatment.
      // If we are in a class method, we must retrieve the
      // _metaclass_ for the current class, pointed at by
      // the class's "isa" pointer.  The following assumes that
      // isa" is the first ivar in a class (which it must be).
      Target = EmitClassRef(CGF, Class->getSuperClass());
      Target = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, Target, 0);
      Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, Target,
                                             CGF.getPointerAlign());
    } else {
      llvm::Constant *MetaClassPtr = EmitMetaClassRef(Class);
      llvm::Value *SuperPtr =
          CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, MetaClassPtr, 1);
      llvm::Value *Super = CGF.Builder.CreateAlignedLoad(ClassTyPtr, SuperPtr,
                                                         CGF.getPointerAlign());
      Target = Super;
    }
  } else if (isCategoryImpl)
    Target = EmitClassRef(CGF, Class->getSuperClass());
  else {
    llvm::Value *ClassPtr = EmitSuperClassRef(Class);
    ClassPtr = CGF.Builder.CreateStructGEP(ObjCTypes.ClassTy, ClassPtr, 1);
    Target = CGF.Builder.CreateAlignedLoad(ClassTyPtr, ClassPtr,
                                           CGF.getPointerAlign());
  }
  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
  // ObjCTypes types.
  llvm::Type *ClassTy =
      CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
  CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));
  return EmitMessageSend(CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
                         ObjCTypes.SuperPtrCTy, true, CallArgs, Method, Class,
                         ObjCTypes);
}

/// Generate code for a message send expression.
CodeGen::RValue CGObjCMac::GenerateMessageSend(
    CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
    Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs,
    const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) {
  return EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
                         CGF.getContext().getObjCIdType(), false, CallArgs,
                         Method, Class, ObjCTypes);
}

CodeGen::RValue CGObjCCommonMac::EmitMessageSend(
    CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
    Selector Sel, llvm::Value *Arg0, QualType Arg0Ty, bool IsSuper,
    const CallArgList &CallArgs, const ObjCMethodDecl *Method,
    const ObjCInterfaceDecl *ClassReceiver,
    const ObjCCommonTypesHelper &ObjCTypes) {
  CodeGenTypes &Types = CGM.getTypes();
  auto selTy = CGF.getContext().getObjCSelType();
  llvm::Value *SelValue = llvm::UndefValue::get(Types.ConvertType(selTy));

  CallArgList ActualArgs;
  if (!IsSuper)
    Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy);
  ActualArgs.add(RValue::get(Arg0), Arg0Ty);
  if (!Method || !Method->isDirectMethod())
    ActualArgs.add(RValue::get(SelValue), selTy);
  ActualArgs.addFrom(CallArgs);

  // If we're calling a method, use the formal signature.
  MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);

  if (Method)
    assert(CGM.getContext().getCanonicalType(Method->getReturnType()) ==
               CGM.getContext().getCanonicalType(ResultType) &&
           "Result type mismatch!");

  bool ReceiverCanBeNull =
      canMessageReceiverBeNull(CGF, Method, IsSuper, ClassReceiver, Arg0);

  bool RequiresNullCheck = false;
  bool RequiresSelValue = true;

  llvm::FunctionCallee Fn = nullptr;
  if (Method && Method->isDirectMethod()) {
    assert(!IsSuper);
    Fn = GenerateDirectMethod(Method, Method->getClassInterface());
    // Direct methods will synthesize the proper `_cmd` internally,
    // so just don't bother with setting the `_cmd` argument.
    RequiresSelValue = false;
  } else if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
    if (ReceiverCanBeNull)
      RequiresNullCheck = true;
    Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
                        : ObjCTypes.getSendStretFn(IsSuper);
  } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
                        : ObjCTypes.getSendFpretFn(IsSuper);
  } else if (CGM.ReturnTypeUsesFP2Ret(ResultType)) {
    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFp2RetFn2(IsSuper)
                        : ObjCTypes.getSendFp2retFn(IsSuper);
  } else {
    // arm64 uses objc_msgSend for stret methods and yet null receiver check
    // must be made for it.
    if (ReceiverCanBeNull && CGM.ReturnTypeUsesSRet(MSI.CallInfo))
      RequiresNullCheck = true;
    Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
                        : ObjCTypes.getSendFn(IsSuper);
  }

  // Cast function to proper signature
  llvm::Constant *BitcastFn = cast<llvm::Constant>(
      CGF.Builder.CreateBitCast(Fn.getCallee(), MSI.MessengerType));

  // We don't need to emit a null check to zero out an indirect result if the
  // result is ignored.
  if (Return.isUnused())
    RequiresNullCheck = false;

  // Emit a null-check if there's a consumed argument other than the receiver.
  if (!RequiresNullCheck && Method && Method->hasParamDestroyedInCallee())
    RequiresNullCheck = true;

  NullReturnState nullReturn;
  if (RequiresNullCheck) {
    nullReturn.init(CGF, Arg0);
  }

  // If a selector value needs to be passed, emit the load before the call.
  if (RequiresSelValue) {
    SelValue = GetSelector(CGF, Sel);
    ActualArgs[1] = CallArg(RValue::get(SelValue), selTy);
  }

  llvm::CallBase *CallSite;
  CGCallee Callee = CGCallee::forDirect(BitcastFn);
  RValue rvalue =
      CGF.EmitCall(MSI.CallInfo, Callee, Return, ActualArgs, &CallSite);

  // Mark the call as noreturn if the method is marked noreturn and the
  // receiver cannot be null.
  if (Method && Method->hasAttr<NoReturnAttr>() && !ReceiverCanBeNull) {
    CallSite->setDoesNotReturn();
  }

  return nullReturn.complete(CGF, Return, rvalue, ResultType, CallArgs,
                             RequiresNullCheck ? Method : nullptr);
}

static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT,
                                           bool pointee = false) {
  // Note that GC qualification applies recursively to C pointer types
  // that aren't otherwise decorated.  This is weird, but it's probably
  // an intentional workaround to the unreliable placement of GC qualifiers.
  if (FQT.isObjCGCStrong())
    return Qualifiers::Strong;

  if (FQT.isObjCGCWeak())
    return Qualifiers::Weak;

  if (auto ownership = FQT.getObjCLifetime()) {
    // Ownership does not apply recursively to C pointer types.
    if (pointee)
      return Qualifiers::GCNone;
    switch (ownership) {
    case Qualifiers::OCL_Weak:
      return Qualifiers::Weak;
    case Qualifiers::OCL_Strong:
      return Qualifiers::Strong;
    case Qualifiers::OCL_ExplicitNone:
      return Qualifiers::GCNone;
    case Qualifiers::OCL_Autoreleasing:
      llvm_unreachable("autoreleasing ivar?");
    case Qualifiers::OCL_None:
      llvm_unreachable("known nonzero");
    }
    llvm_unreachable("bad objc ownership");
  }

  // Treat unqualified retainable pointers as strong.
  if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
    return Qualifiers::Strong;

  // Walk into C pointer types, but only in GC.
  if (Ctx.getLangOpts().getGC() != LangOptions::NonGC) {
    if (const PointerType *PT = FQT->getAs<PointerType>())
      return GetGCAttrTypeForType(Ctx, PT->getPointeeType(), /*pointee*/ true);
  }

  return Qualifiers::GCNone;
}

namespace {
struct IvarInfo {
  CharUnits Offset;
  uint64_t SizeInWords;
  IvarInfo(CharUnits offset, uint64_t sizeInWords)
      : Offset(offset), SizeInWords(sizeInWords) {}

  // Allow sorting based on byte pos.
  bool operator<(const IvarInfo &other) const { return Offset < other.Offset; }
};

/// A helper class for building GC layout strings.
class IvarLayoutBuilder {
  CodeGenModule &CGM;

  /// The start of the layout.  Offsets will be relative to this value,
  /// and entries less than this value will be silently discarded.
  CharUnits InstanceBegin;

  /// The end of the layout.  Offsets will never exceed this value.
  CharUnits InstanceEnd;

  /// Whether we're generating the strong layout or the weak layout.
  bool ForStrongLayout;

  /// Whether the offsets in IvarsInfo might be out-of-order.
  bool IsDisordered = false;

  llvm::SmallVector<IvarInfo, 8> IvarsInfo;

public:
  IvarLayoutBuilder(CodeGenModule &CGM, CharUnits instanceBegin,
                    CharUnits instanceEnd, bool forStrongLayout)
      : CGM(CGM), InstanceBegin(instanceBegin), InstanceEnd(instanceEnd),
        ForStrongLayout(forStrongLayout) {}

  void visitRecord(const RecordType *RT, CharUnits offset);

  template <class Iterator, class GetOffsetFn>
  void visitAggregate(Iterator begin, Iterator end, CharUnits aggrOffset,
                      const GetOffsetFn &getOffset);

  void visitField(const FieldDecl *field, CharUnits offset);

  /// Add the layout of a block implementation.
  void visitBlock(const CGBlockInfo &blockInfo);

  /// Is there any information for an interesting bitmap?
  bool hasBitmapData() const { return !IvarsInfo.empty(); }

  llvm::Constant *buildBitmap(CGObjCCommonMac &CGObjC,
                              llvm::SmallVectorImpl<unsigned char> &buffer);

  static void dump(ArrayRef<unsigned char> buffer) {
    const unsigned char *s = buffer.data();
    for (unsigned i = 0, e = buffer.size(); i < e; i++)
      if (!(s[i] & 0xf0))
        printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
      else
        printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
    printf("\n");
  }
};
} // end anonymous namespace

llvm::Constant *
CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM,
                                    const CGBlockInfo &blockInfo) {

  llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
  if (CGM.getLangOpts().getGC() == LangOptions::NonGC)
    return nullPtr;

  IvarLayoutBuilder builder(CGM, CharUnits::Zero(), blockInfo.BlockSize,
                            /*for strong layout*/ true);

  builder.visitBlock(blockInfo);

  if (!builder.hasBitmapData())
    return nullPtr;

  llvm::SmallVector<unsigned char, 32> buffer;
  llvm::Constant *C = builder.buildBitmap(*this, buffer);
  if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
    printf("\n block variable layout for block: ");
    builder.dump(buffer);
  }

  return C;
}

void IvarLayoutBuilder::visitBlock(const CGBlockInfo &blockInfo) {
  // __isa is the first field in block descriptor and must assume by runtime's
  // convention that it is GC'able.
  IvarsInfo.push_back(IvarInfo(CharUnits::Zero(), 1));

  const BlockDecl *blockDecl = blockInfo.getBlockDecl();

  // Ignore the optional 'this' capture: C++ objects are not assumed
  // to be GC'ed.

  CharUnits lastFieldOffset;

  // Walk the captured variables.
  for (const auto &CI : blockDecl->captures()) {
    const VarDecl *variable = CI.getVariable();
    QualType type = variable->getType();

    const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);

    // Ignore constant captures.
    if (capture.isConstant())
      continue;

    CharUnits fieldOffset = capture.getOffset();

    // Block fields are not necessarily ordered; if we detect that we're
    // adding them out-of-order, make sure we sort later.
    if (fieldOffset < lastFieldOffset)
      IsDisordered = true;
    lastFieldOffset = fieldOffset;

    // __block variables are passed by their descriptor address.
    if (CI.isByRef()) {
      IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
      continue;
    }

    assert(!type->isArrayType() && "array variable should not be caught");
    if (const RecordType *record = type->getAsCanonical<RecordType>()) {
      visitRecord(record, fieldOffset);
      continue;
    }

    Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), type);

    if (GCAttr == Qualifiers::Strong) {
      assert(CGM.getContext().getTypeSize(type) ==
             CGM.getTarget().getPointerWidth(LangAS::Default));
      IvarsInfo.push_back(IvarInfo(fieldOffset, /*size in words*/ 1));
    }
  }
}

/// getBlockCaptureLifetime - This routine returns life time of the captured
/// block variable for the purpose of block layout meta-data generation. FQT is
/// the type of the variable captured in the block.
Qualifiers::ObjCLifetime
CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT, bool ByrefLayout) {
  // If it has an ownership qualifier, we're done.
  if (auto lifetime = FQT.getObjCLifetime())
    return lifetime;

  // If it doesn't, and this is ARC, it has no ownership.
  if (CGM.getLangOpts().ObjCAutoRefCount)
    return Qualifiers::OCL_None;

  // In MRC, retainable pointers are owned by non-__block variables.
  if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
    return ByrefLayout ? Qualifiers::OCL_ExplicitNone : Qualifiers::OCL_Strong;

  return Qualifiers::OCL_None;
}

void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
                                             Qualifiers::ObjCLifetime LifeTime,
                                             CharUnits FieldOffset,
                                             CharUnits FieldSize) {
  // __block variables are passed by their descriptor address.
  if (IsByref)
    RunSkipBlockVars.push_back(
        RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, FieldSize));
  else if (LifeTime == Qualifiers::OCL_Strong)
    RunSkipBlockVars.push_back(
        RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, FieldSize));
  else if (LifeTime == Qualifiers::OCL_Weak)
    RunSkipBlockVars.push_back(
        RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, FieldSize));
  else if (LifeTime == Qualifiers::OCL_ExplicitNone)
    RunSkipBlockVars.push_back(
        RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, FieldSize));
  else
    RunSkipBlockVars.push_back(
        RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, FieldOffset, FieldSize));
}

void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
                                          const RecordDecl *RD,
                                          ArrayRef<const FieldDecl *> RecFields,
                                          CharUnits BytePos, bool &HasUnion,
                                          bool ByrefLayout) {
  bool IsUnion = (RD && RD->isUnion());
  CharUnits MaxUnionSize = CharUnits::Zero();
  const FieldDecl *MaxField = nullptr;
  const FieldDecl *LastFieldBitfieldOrUnnamed = nullptr;
  CharUnits MaxFieldOffset = CharUnits::Zero();
  CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();

  if (RecFields.empty())
    return;
  unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();

  for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
    const FieldDecl *Field = RecFields[i];
    // Note that 'i' here is actually the field index inside RD of Field,
    // although this dependency is hidden.
    const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
    CharUnits FieldOffset =
        CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));

    // Skip over unnamed or bitfields
    if (!Field->getIdentifier() || Field->isBitField()) {
      LastFieldBitfieldOrUnnamed = Field;
      LastBitfieldOrUnnamedOffset = FieldOffset;
      continue;
    }

    LastFieldBitfieldOrUnnamed = nullptr;
    QualType FQT = Field->getType();
    if (FQT->isRecordType() || FQT->isUnionType()) {
      if (FQT->isUnionType())
        HasUnion = true;

      BuildRCBlockVarRecordLayout(FQT->castAsCanonical<RecordType>(),
                                  BytePos + FieldOffset, HasUnion);
      continue;
    }

    if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
      auto *CArray = cast<ConstantArrayType>(Array);
      uint64_t ElCount = CArray->getZExtSize();
      assert(CArray && "only array with known element size is supported");
      FQT = CArray->getElementType();
      while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
        auto *CArray = cast<ConstantArrayType>(Array);
        ElCount *= CArray->getZExtSize();
        FQT = CArray->getElementType();
      }
      if (FQT->isRecordType() && ElCount) {
        int OldIndex = RunSkipBlockVars.size() - 1;
        auto *RT = FQT->castAsCanonical<RecordType>();
        BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, HasUnion);

        // Replicate layout information for each array element. Note that
        // one element is already done.
        uint64_t ElIx = 1;
        for (int FirstIndex = RunSkipBlockVars.size() - 1; ElIx < ElCount;
             ElIx++) {
          CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
          for (int i = OldIndex + 1; i <= FirstIndex; ++i)
            RunSkipBlockVars.push_back(
                RUN_SKIP(RunSkipBlockVars[i].opcode,
                         RunSkipBlockVars[i].block_var_bytepos + Size * ElIx,
                         RunSkipBlockVars[i].block_var_size));
        }
        continue;
      }
    }
    CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
    if (IsUnion) {
      CharUnits UnionIvarSize = FieldSize;
      if (UnionIvarSize > MaxUnionSize) {
        MaxUnionSize = UnionIvarSize;
        MaxField = Field;
        MaxFieldOffset = FieldOffset;
      }
    } else {
      UpdateRunSkipBlockVars(false, getBlockCaptureLifetime(FQT, ByrefLayout),
                             BytePos + FieldOffset, FieldSize);
    }
  }

  if (LastFieldBitfieldOrUnnamed) {
    if (LastFieldBitfieldOrUnnamed->isBitField()) {
      // Last field was a bitfield. Must update the info.
      uint64_t BitFieldSize = LastFieldBitfieldOrUnnamed->getBitWidthValue();
      unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
                         ((BitFieldSize % ByteSizeInBits) != 0);
      CharUnits Size = CharUnits::fromQuantity(UnsSize);
      Size += LastBitfieldOrUnnamedOffset;
      UpdateRunSkipBlockVars(
          false,
          getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
                                  ByrefLayout),
          BytePos + LastBitfieldOrUnnamedOffset, Size);
    } else {
      assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&
             "Expected unnamed");
      // Last field was unnamed. Must update skip info.
      CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(
          LastFieldBitfieldOrUnnamed->getType());
      UpdateRunSkipBlockVars(
          false,
          getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType(),
                                  ByrefLayout),
          BytePos + LastBitfieldOrUnnamedOffset, FieldSize);
    }
  }

  if (MaxField)
    UpdateRunSkipBlockVars(
        false, getBlockCaptureLifetime(MaxField->getType(), ByrefLayout),
        BytePos + MaxFieldOffset, MaxUnionSize);
}

void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
                                                  CharUnits BytePos,
                                                  bool &HasUnion,
                                                  bool ByrefLayout) {
  const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();
  SmallVector<const FieldDecl *, 16> Fields(RD->fields());
  llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
  const llvm::StructLayout *RecLayout =
      CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty));

  BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion, ByrefLayout);
}

/// InlineLayoutInstruction - This routine produce an inline instruction for the
/// block variable layout if it can. If not, it returns 0. Rules are as follow:
/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit
/// world, an inline layout of value 0x0000000000000xyz is interpreted as
/// follows: x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by y
/// captured object of BLOCK_LAYOUT_BYREF. Followed by z captured object of
/// BLOCK_LAYOUT_WEAK. If any of the above is missing, zero replaces it. For
/// example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no BLOCK_LAYOUT_BYREF
/// and no BLOCK_LAYOUT_WEAK objects are captured.
uint64_t CGObjCCommonMac::InlineLayoutInstruction(
    SmallVectorImpl<unsigned char> &Layout) {
  uint64_t Result = 0;
  if (Layout.size() <= 3) {
    unsigned size = Layout.size();
    unsigned strong_word_count = 0, byref_word_count = 0, weak_word_count = 0;
    unsigned char inst;
    enum BLOCK_LAYOUT_OPCODE opcode;
    switch (size) {
    case 3:
      inst = Layout[0];
      opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
      if (opcode == BLOCK_LAYOUT_STRONG)
        strong_word_count = (inst & 0xF) + 1;
      else
        return 0;
      inst = Layout[1];
      opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
      if (opcode == BLOCK_LAYOUT_BYREF)
        byref_word_count = (inst & 0xF) + 1;
      else
        return 0;
      inst = Layout[2];
      opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
      if (opcode == BLOCK_LAYOUT_WEAK)
        weak_word_count = (inst & 0xF) + 1;
      else
        return 0;
      break;

    case 2:
      inst = Layout[0];
      opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
      if (opcode == BLOCK_LAYOUT_STRONG) {
        strong_word_count = (inst & 0xF) + 1;
        inst = Layout[1];
        opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
        if (opcode == BLOCK_LAYOUT_BYREF)
          byref_word_count = (inst & 0xF) + 1;
        else if (opcode == BLOCK_LAYOUT_WEAK)
          weak_word_count = (inst & 0xF) + 1;
        else
          return 0;
      } else if (opcode == BLOCK_LAYOUT_BYREF) {
        byref_word_count = (inst & 0xF) + 1;
        inst = Layout[1];
        opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
        if (opcode == BLOCK_LAYOUT_WEAK)
          weak_word_count = (inst & 0xF) + 1;
        else
          return 0;
      } else
        return 0;
      break;

    case 1:
      inst = Layout[0];
      opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
      if (opcode == BLOCK_LAYOUT_STRONG)
        strong_word_count = (inst & 0xF) + 1;
      else if (opcode == BLOCK_LAYOUT_BYREF)
        byref_word_count = (inst & 0xF) + 1;
      else if (opcode == BLOCK_LAYOUT_WEAK)
        weak_word_count = (inst & 0xF) + 1;
      else
        return 0;
      break;

    default:
      return 0;
    }

    // Cannot inline when any of the word counts is 15. Because this is one less
    // than the actual work count (so 15 means 16 actual word counts),
    // and we can only display 0 thru 15 word counts.
    if (strong_word_count == 16 || byref_word_count == 16 ||
        weak_word_count == 16)
      return 0;

    unsigned count = (strong_word_count != 0) + (byref_word_count != 0) +
                     (weak_word_count != 0);

    if (size == count) {
      if (strong_word_count)
        Result = strong_word_count;
      Result <<= 4;
      if (byref_word_count)
        Result += byref_word_count;
      Result <<= 4;
      if (weak_word_count)
        Result += weak_word_count;
    }
  }
  return Result;
}

llvm::Constant *CGObjCCommonMac::getBitmapBlockLayout(bool ComputeByrefLayout) {
  llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
  if (RunSkipBlockVars.empty())
    return nullPtr;
  unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(LangAS::Default);
  unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
  unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;

  // Sort on byte position; captures might not be allocated in order,
  // and unions can do funny things.
  llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end());
  SmallVector<unsigned char, 16> Layout;

  unsigned size = RunSkipBlockVars.size();
  for (unsigned i = 0; i < size; i++) {
    enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
    CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
    CharUnits end_byte_pos = start_byte_pos;
    unsigned j = i + 1;
    while (j < size) {
      if (opcode == RunSkipBlockVars[j].opcode) {
        end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos;
        i++;
      } else
        break;
    }
    CharUnits size_in_bytes =
        end_byte_pos - start_byte_pos + RunSkipBlockVars[j - 1].block_var_size;
    if (j < size) {
      CharUnits gap = RunSkipBlockVars[j].block_var_bytepos -
                      RunSkipBlockVars[j - 1].block_var_bytepos -
                      RunSkipBlockVars[j - 1].block_var_size;
      size_in_bytes += gap;
    }
    CharUnits residue_in_bytes = CharUnits::Zero();
    if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
      residue_in_bytes = size_in_bytes % WordSizeInBytes;
      size_in_bytes -= residue_in_bytes;
      opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
    }

    unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
    while (size_in_words >= 16) {
      // Note that value in imm. is one less that the actual
      // value. So, 0xf means 16 words follow!
      unsigned char inst = (opcode << 4) | 0xf;
      Layout.push_back(inst);
      size_in_words -= 16;
    }
    if (size_in_words > 0) {
      // Note that value in imm. is one less that the actual
      // value. So, we subtract 1 away!
      unsigned char inst = (opcode << 4) | (size_in_words - 1);
      Layout.push_back(inst);
    }
    if (residue_in_bytes > CharUnits::Zero()) {
      unsigned char inst = (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) |
                           (residue_in_bytes.getQuantity() - 1);
      Layout.push_back(inst);
    }
  }

  while (!Layout.empty()) {
    unsigned char inst = Layout.back();
    enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
    if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES ||
        opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS)
      Layout.pop_back();
    else
      break;
  }

  uint64_t Result = InlineLayoutInstruction(Layout);
  if (Result != 0) {
    // Block variable layout instruction has been inlined.
    if (CGM.getLangOpts().ObjCGCBitmapPrint) {
      if (ComputeByrefLayout)
        printf("\n Inline BYREF variable layout: ");
      else
        printf("\n Inline block variable layout: ");
      printf("0x0%" PRIx64 "", Result);
      if (auto numStrong = (Result & 0xF00) >> 8)
        printf(", BL_STRONG:%d", (int)numStrong);
      if (auto numByref = (Result & 0x0F0) >> 4)
        printf(", BL_BYREF:%d", (int)numByref);
      if (auto numWeak = (Result & 0x00F) >> 0)
        printf(", BL_WEAK:%d", (int)numWeak);
      printf(", BL_OPERATOR:0\n");
    }
    return llvm::ConstantInt::get(CGM.IntPtrTy, Result);
  }

  unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0;
  Layout.push_back(inst);
  std::string BitMap;
  for (unsigned char C : Layout)
    BitMap += C;

  if (CGM.getLangOpts().ObjCGCBitmapPrint) {
    if (ComputeByrefLayout)
      printf("\n Byref variable layout: ");
    else
      printf("\n Block variable layout: ");
    for (unsigned i = 0, e = BitMap.size(); i != e; i++) {
      unsigned char inst = BitMap[i];
      enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE)(inst >> 4);
      unsigned delta = 1;
      switch (opcode) {
      case BLOCK_LAYOUT_OPERATOR:
        printf("BL_OPERATOR:");
        delta = 0;
        break;
      case BLOCK_LAYOUT_NON_OBJECT_BYTES:
        printf("BL_NON_OBJECT_BYTES:");
        break;
      case BLOCK_LAYOUT_NON_OBJECT_WORDS:
        printf("BL_NON_OBJECT_WORD:");
        break;
      case BLOCK_LAYOUT_STRONG:
        printf("BL_STRONG:");
        break;
      case BLOCK_LAYOUT_BYREF:
        printf("BL_BYREF:");
        break;
      case BLOCK_LAYOUT_WEAK:
        printf("BL_WEAK:");
        break;
      case BLOCK_LAYOUT_UNRETAINED:
        printf("BL_UNRETAINED:");
        break;
      }
      // Actual value of word count is one more that what is in the imm.
      // field of the instruction
      printf("%d", (inst & 0xf) + delta);
      if (i < e - 1)
        printf(", ");
      else
        printf("\n");
    }
  }

  auto *Entry = CreateCStringLiteral(BitMap, ObjCLabelType::ClassName,
                                     /*ForceNonFragileABI=*/true,
                                     /*NullTerminate=*/false);
  return getConstantGEP(VMContext, Entry, 0, 0);
}

static std::string getBlockLayoutInfoString(
    const SmallVectorImpl<CGObjCCommonMac::RUN_SKIP> &RunSkipBlockVars,
    bool HasCopyDisposeHelpers) {
  std::string Str;
  for (const CGObjCCommonMac::RUN_SKIP &R : RunSkipBlockVars) {
    if (R.opcode == CGObjCCommonMac::BLOCK_LAYOUT_UNRETAINED) {
      // Copy/dispose helpers don't have any information about
      // __unsafe_unretained captures, so unconditionally concatenate a string.
      Str += "u";
    } else if (HasCopyDisposeHelpers) {
      // Information about __strong, __weak, or byref captures has already been
      // encoded into the names of the copy/dispose helpers. We have to add a
      // string here only when the copy/dispose helpers aren't generated (which
      // happens when the block is non-escaping).
      continue;
    } else {
      switch (R.opcode) {
      case CGObjCCommonMac::BLOCK_LAYOUT_STRONG:
        Str += "s";
        break;
      case CGObjCCommonMac::BLOCK_LAYOUT_BYREF:
        Str += "r";
        break;
      case CGObjCCommonMac::BLOCK_LAYOUT_WEAK:
        Str += "w";
        break;
      default:
        continue;
      }
    }
    Str += llvm::to_string(R.block_var_bytepos.getQuantity());
    Str += "l" + llvm::to_string(R.block_var_size.getQuantity());
  }
  return Str;
}

void CGObjCCommonMac::fillRunSkipBlockVars(CodeGenModule &CGM,
                                           const CGBlockInfo &blockInfo) {
  assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);

  RunSkipBlockVars.clear();
  bool hasUnion = false;

  unsigned WordSizeInBits = CGM.getTarget().getPointerWidth(LangAS::Default);
  unsigned ByteSizeInBits = CGM.getTarget().getCharWidth();
  unsigned WordSizeInBytes = WordSizeInBits / ByteSizeInBits;

  const BlockDecl *blockDecl = blockInfo.getBlockDecl();

  // Calculate the basic layout of the block structure.
  const llvm::StructLayout *layout =
      CGM.getDataLayout().getStructLayout(blockInfo.StructureType);

  // Ignore the optional 'this' capture: C++ objects are not assumed
  // to be GC'ed.
  if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero())
    UpdateRunSkipBlockVars(false, Qualifiers::OCL_None,
                           blockInfo.BlockHeaderForcedGapOffset,
                           blockInfo.BlockHeaderForcedGapSize);
  // Walk the captured variables.
  for (const auto &CI : blockDecl->captures()) {
    const VarDecl *variable = CI.getVariable();
    QualType type = variable->getType();

    const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable);

    // Ignore constant captures.
    if (capture.isConstant())
      continue;

    CharUnits fieldOffset =
        CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));

    assert(!type->isArrayType() && "array variable should not be caught");
    if (!CI.isByRef())
      if (const auto *record = type->getAsCanonical<RecordType>()) {
        BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
        continue;
      }
    CharUnits fieldSize;
    if (CI.isByRef())
      fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
    else
      fieldSize = CGM.getContext().getTypeSizeInChars(type);
    UpdateRunSkipBlockVars(CI.isByRef(), getBlockCaptureLifetime(type, false),
                           fieldOffset, fieldSize);
  }
}

llvm::Constant *
CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
                                    const CGBlockInfo &blockInfo) {
  fillRunSkipBlockVars(CGM, blockInfo);
  return getBitmapBlockLayout(false);
}

std::string CGObjCCommonMac::getRCBlockLayoutStr(CodeGenModule &CGM,
                                                 const CGBlockInfo &blockInfo) {
  fillRunSkipBlockVars(CGM, blockInfo);
  return getBlockLayoutInfoString(RunSkipBlockVars, blockInfo.NeedsCopyDispose);
}

llvm::Constant *CGObjCCommonMac::BuildByrefLayout(CodeGen::CodeGenModule &CGM,
                                                  QualType T) {
  assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);
  assert(!T->isArrayType() && "__block array variable should not be caught");
  CharUnits fieldOffset;
  RunSkipBlockVars.clear();
  bool hasUnion = false;
  if (const auto *record = T->getAsCanonical<RecordType>()) {
    BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion,
                                true /*ByrefLayout */);
    llvm::Constant *Result = getBitmapBlockLayout(true);
    if (isa<llvm::ConstantInt>(Result))
      Result = llvm::ConstantExpr::getIntToPtr(Result, CGM.Int8PtrTy);
    return Result;
  }
  llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
  return nullPtr;
}

llvm::Value *CGObjCMac::GenerateProtocolRef(CodeGenFunction &CGF,
                                            const ObjCProtocolDecl *PD) {
  // FIXME: I don't understand why gcc generates this, or where it is
  // resolved. Investigate. Its also wasteful to look this up over and over.
  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));

  return GetProtocolRef(PD);
}

void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
  // FIXME: We shouldn't need this, the protocol decl should contain enough
  // information to tell us whether this was a declaration or a definition.
  DefinedProtocols.insert(PD->getIdentifier());

  // If we have generated a forward reference to this protocol, emit
  // it now. Otherwise do nothing, the protocol objects are lazily
  // emitted.
  if (Protocols.count(PD->getIdentifier()))
    GetOrEmitProtocol(PD);
}

llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
  if (DefinedProtocols.count(PD->getIdentifier()))
    return GetOrEmitProtocol(PD);

  return GetOrEmitProtocolRef(PD);
}

llvm::Value *
CGObjCCommonMac::EmitClassRefViaRuntime(CodeGenFunction &CGF,
                                        const ObjCInterfaceDecl *ID,
                                        ObjCCommonTypesHelper &ObjCTypes) {
  llvm::FunctionCallee lookUpClassFn = ObjCTypes.getLookUpClassFn();

  llvm::Value *className = CGF.CGM
                               .GetAddrOfConstantCString(std::string(
                                   ID->getObjCRuntimeNameAsString()))
                               .getPointer();
  ASTContext &ctx = CGF.CGM.getContext();
  className = CGF.Builder.CreateBitCast(
      className, CGF.ConvertType(ctx.getPointerType(ctx.CharTy.withConst())));
  llvm::CallInst *call = CGF.Builder.CreateCall(lookUpClassFn, className);
  call->setDoesNotThrow();
  return call;
}

/*
// Objective-C 1.0 extensions
struct _objc_protocol {
struct _objc_protocol_extension *isa;
char *protocol_name;
struct _objc_protocol_list *protocol_list;
struct _objc__method_prototype_list *instance_methods;
struct _objc__method_prototype_list *class_methods
};

See EmitProtocolExtension().
*/
llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
  llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];

  // Early exit if a defining object has already been generated.
  if (Entry && Entry->hasInitializer())
    return Entry;

  // Use the protocol definition, if there is one.
  if (const ObjCProtocolDecl *Def = PD->getDefinition())
    PD = Def;

  // FIXME: I don't understand why gcc generates this, or where it is
  // resolved. Investigate. Its also wasteful to look this up over and over.
  LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));

  // Construct method lists.
  auto methodLists = ProtocolMethodLists::get(PD);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
  values.add(EmitProtocolExtension(PD, methodLists));
  values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
  values.add(EmitProtocolList("OBJC_PROTOCOL_REFS_" + PD->getName(),
                              PD->protocol_begin(), PD->protocol_end()));
  values.add(methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::RequiredInstanceMethods));
  values.add(methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::RequiredClassMethods));

  if (Entry) {
    // Already created, update the initializer.
    assert(Entry->hasPrivateLinkage());
    values.finishAndSetAsInitializer(Entry);
  } else {
    Entry = values.finishAndCreateGlobal(
        "OBJC_PROTOCOL_" + PD->getName(), CGM.getPointerAlign(),
        /*constant*/ false, llvm::GlobalValue::PrivateLinkage);
    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");

    Protocols[PD->getIdentifier()] = Entry;
  }
  CGM.addCompilerUsedGlobal(Entry);

  return Entry;
}

llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];

  if (!Entry) {
    // We use the initializer as a marker of whether this is a forward
    // reference or not. At module finalization we add the empty
    // contents for protocols which were referenced but never defined.
    Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy,
                                     false, llvm::GlobalValue::PrivateLinkage,
                                     nullptr, "OBJC_PROTOCOL_" + PD->getName());
    Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
    // FIXME: Is this necessary? Why only for protocol?
    Entry->setAlignment(llvm::Align(4));
  }

  return Entry;
}

/*
  struct _objc_protocol_extension {
  uint32_t size;
  struct objc_method_description_list *optional_instance_methods;
  struct objc_method_description_list *optional_class_methods;
  struct objc_property_list *instance_properties;
  const char ** extendedMethodTypes;
  struct objc_property_list *class_properties;
  };
*/
llvm::Constant *
CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
                                 const ProtocolMethodLists &methodLists) {
  auto optInstanceMethods = methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::OptionalInstanceMethods);
  auto optClassMethods = methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::OptionalClassMethods);

  auto extendedMethodTypes = EmitProtocolMethodTypes(
      "OBJC_PROTOCOL_METHOD_TYPES_" + PD->getName(),
      methodLists.emitExtendedTypesArray(this), ObjCTypes);

  auto instanceProperties = EmitPropertyList(
      "OBJC_$_PROP_PROTO_LIST_" + PD->getName(), nullptr, PD, ObjCTypes, false);
  auto classProperties =
      EmitPropertyList("OBJC_$_CLASS_PROP_PROTO_LIST_" + PD->getName(), nullptr,
                       PD, ObjCTypes, true);

  // Return null if no extension bits are used.
  if (optInstanceMethods->isNullValue() && optClassMethods->isNullValue() &&
      extendedMethodTypes->isNullValue() && instanceProperties->isNullValue() &&
      classProperties->isNullValue()) {
    return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
  }

  uint64_t size =
      CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ProtocolExtensionTy);
  values.addInt(ObjCTypes.IntTy, size);
  values.add(optInstanceMethods);
  values.add(optClassMethods);
  values.add(instanceProperties);
  values.add(extendedMethodTypes);
  values.add(classProperties);

  // No special section, but goes in llvm.used
  return CreateMetadataVar("_OBJC_PROTOCOLEXT_" + PD->getName(), values,
                           StringRef(), CGM.getPointerAlign(), true);
}

/*
  struct objc_protocol_list {
    struct objc_protocol_list *next;
    long count;
    Protocol *list[];
  };
*/
llvm::Constant *
CGObjCMac::EmitProtocolList(Twine name,
                            ObjCProtocolDecl::protocol_iterator begin,
                            ObjCProtocolDecl::protocol_iterator end) {
  // Just return null for empty protocol lists
  auto PDs = GetRuntimeProtocolList(begin, end);
  if (PDs.empty())
    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct();

  // This field is only used by the runtime.
  values.addNullPointer(ObjCTypes.ProtocolListPtrTy);

  // Reserve a slot for the count.
  auto countSlot = values.addPlaceholder();

  auto refsArray = values.beginArray(ObjCTypes.ProtocolPtrTy);
  for (const auto *Proto : PDs)
    refsArray.add(GetProtocolRef(Proto));

  auto count = refsArray.size();

  // This list is null terminated.
  refsArray.addNullPointer(ObjCTypes.ProtocolPtrTy);

  refsArray.finishAndAddTo(values);
  values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);

  StringRef section;
  if (CGM.getTriple().isOSBinFormatMachO())
    section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";

  llvm::GlobalVariable *GV =
      CreateMetadataVar(name, values, section, CGM.getPointerAlign(), false);
  return GV;
}

static void PushProtocolProperties(
    llvm::SmallPtrSet<const IdentifierInfo *, 16> &PropertySet,
    SmallVectorImpl<const ObjCPropertyDecl *> &Properties,
    const ObjCProtocolDecl *Proto, bool IsClassProperty) {
  for (const auto *PD : Proto->properties()) {
    if (IsClassProperty != PD->isClassProperty())
      continue;
    if (!PropertySet.insert(PD->getIdentifier()).second)
      continue;
    Properties.push_back(PD);
  }

  for (const auto *P : Proto->protocols())
    PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
}

/*
  struct _objc_property {
    const char * const name;
    const char * const attributes;
  };

  struct _objc_property_list {
    uint32_t entsize; // sizeof (struct _objc_property)
    uint32_t prop_count;
    struct _objc_property[prop_count];
  };
*/
llvm::Constant *CGObjCCommonMac::EmitPropertyList(
    Twine Name, const Decl *Container, const ObjCContainerDecl *OCD,
    const ObjCCommonTypesHelper &ObjCTypes, bool IsClassProperty) {
  if (IsClassProperty) {
    // Make this entry NULL for OS X with deployment target < 10.11, for iOS
    // with deployment target < 9.0.
    const llvm::Triple &Triple = CGM.getTarget().getTriple();
    if ((Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 11)) ||
        (Triple.isiOS() && Triple.isOSVersionLT(9)))
      return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
  }

  SmallVector<const ObjCPropertyDecl *, 16> Properties;
  llvm::SmallPtrSet<const IdentifierInfo *, 16> PropertySet;

  if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
    for (const ObjCCategoryDecl *ClassExt : OID->known_extensions())
      for (auto *PD : ClassExt->properties()) {
        if (IsClassProperty != PD->isClassProperty())
          continue;
        if (PD->isDirectProperty())
          continue;
        PropertySet.insert(PD->getIdentifier());
        Properties.push_back(PD);
      }

  for (const auto *PD : OCD->properties()) {
    if (IsClassProperty != PD->isClassProperty())
      continue;
    // Don't emit duplicate metadata for properties that were already in a
    // class extension.
    if (!PropertySet.insert(PD->getIdentifier()).second)
      continue;
    if (PD->isDirectProperty())
      continue;
    Properties.push_back(PD);
  }

  if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
    for (const auto *P : OID->all_referenced_protocols())
      PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
  } else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
    for (const auto *P : CD->protocols())
      PushProtocolProperties(PropertySet, Properties, P, IsClassProperty);
  }

  // Return null for empty list.
  if (Properties.empty())
    return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);

  unsigned propertySize =
      CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct();
  values.addInt(ObjCTypes.IntTy, propertySize);
  values.addInt(ObjCTypes.IntTy, Properties.size());
  auto propertiesArray = values.beginArray(ObjCTypes.PropertyTy);
  for (auto PD : Properties) {
    auto property = propertiesArray.beginStruct(ObjCTypes.PropertyTy);
    property.add(GetPropertyName(PD->getIdentifier()));
    property.add(GetPropertyTypeString(PD, Container));
    property.finishAndAddTo(propertiesArray);
  }
  propertiesArray.finishAndAddTo(values);

  StringRef Section;
  if (CGM.getTriple().isOSBinFormatMachO())
    Section = (ObjCABI == 2) ? "__DATA, __objc_const"
                             : "__OBJC,__property,regular,no_dead_strip";

  llvm::GlobalVariable *GV =
      CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
  return GV;
}

llvm::Constant *CGObjCCommonMac::EmitProtocolMethodTypes(
    Twine Name, ArrayRef<llvm::Constant *> MethodTypes,
    const ObjCCommonTypesHelper &ObjCTypes) {
  // Return null for empty list.
  if (MethodTypes.empty())
    return llvm::Constant::getNullValue(ObjCTypes.Int8PtrPtrTy);

  llvm::ArrayType *AT =
      llvm::ArrayType::get(ObjCTypes.Int8PtrTy, MethodTypes.size());
  llvm::Constant *Init = llvm::ConstantArray::get(AT, MethodTypes);

  StringRef Section;
  if (CGM.getTriple().isOSBinFormatMachO() && ObjCABI == 2)
    Section = "__DATA, __objc_const";

  llvm::GlobalVariable *GV =
      CreateMetadataVar(Name, Init, Section, CGM.getPointerAlign(), true);
  return GV;
}

/*
  struct _objc_category {
  char *category_name;
  char *class_name;
  struct _objc_method_list *instance_methods;
  struct _objc_method_list *class_methods;
  struct _objc_protocol_list *protocols;
  uint32_t size; // sizeof(struct _objc_category)
  struct _objc_property_list *instance_properties;
  struct _objc_property_list *class_properties;
  };
*/
void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
  unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy);

  // FIXME: This is poor design, the OCD should have a pointer to the category
  // decl. Additionally, note that Category can be null for the @implementation
  // w/o an @interface case. Sema should just create one for us as it does for
  // @implementation so everyone else can live life under a clear blue sky.
  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
  const ObjCCategoryDecl *Category =
      Interface->FindCategoryDeclaration(OCD->getIdentifier());

  SmallString<256> ExtName;
  llvm::raw_svector_ostream(ExtName)
      << Interface->getName() << '_' << OCD->getName();

  ConstantInitBuilder Builder(CGM);
  auto Values = Builder.beginStruct(ObjCTypes.CategoryTy);

  enum { InstanceMethods, ClassMethods, NumMethodLists };
  SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
  for (const auto *MD : OCD->methods()) {
    if (!MD->isDirectMethod())
      Methods[unsigned(MD->isClassMethod())].push_back(MD);
  }

  Values.add(GetClassName(OCD->getName()));
  Values.add(GetClassName(Interface->getObjCRuntimeNameAsString()));
  LazySymbols.insert(Interface->getIdentifier());

  Values.add(emitMethodList(ExtName, MethodListType::CategoryInstanceMethods,
                            Methods[InstanceMethods]));
  Values.add(emitMethodList(ExtName, MethodListType::CategoryClassMethods,
                            Methods[ClassMethods]));
  if (Category) {
    Values.add(EmitProtocolList("OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
                                Category->protocol_begin(),
                                Category->protocol_end()));
  } else {
    Values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
  }
  Values.addInt(ObjCTypes.IntTy, Size);

  // If there is no category @interface then there can be no properties.
  if (Category) {
    Values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(), OCD,
                                Category, ObjCTypes, false));
    Values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
                                Category, ObjCTypes, true));
  } else {
    Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
    Values.addNullPointer(ObjCTypes.PropertyListPtrTy);
  }

  llvm::GlobalVariable *GV = CreateMetadataVar(
      "OBJC_CATEGORY_" + ExtName.str(), Values,
      "__OBJC,__category,regular,no_dead_strip", CGM.getPointerAlign(), true);
  DefinedCategories.push_back(GV);
  DefinedCategoryNames.insert(llvm::CachedHashString(ExtName));
  // method definition entries must be clear for next implementation.
  MethodDefinitions.clear();
}

// clang-format off
enum FragileClassFlags {
  /// Apparently: is not a meta-class.
  FragileABI_Class_Factory                 = 0x00001,

  /// Is a meta-class.
  FragileABI_Class_Meta                    = 0x00002,

  /// Has a non-trivial constructor or destructor.
  FragileABI_Class_HasCXXStructors         = 0x02000,

  /// Has hidden visibility.
  FragileABI_Class_Hidden                  = 0x20000,

  /// Class implementation was compiled under ARC.
  FragileABI_Class_CompiledByARC           = 0x04000000,

  /// Class implementation was compiled under MRC and has MRC weak ivars.
  /// Exclusive with CompiledByARC.
  FragileABI_Class_HasMRCWeakIvars         = 0x08000000,
};

enum NonFragileClassFlags {
  /// Is a meta-class.
  NonFragileABI_Class_Meta                 = 0x00001,

  /// Is a root class.
  NonFragileABI_Class_Root                 = 0x00002,

  /// Has a non-trivial constructor or destructor.
  NonFragileABI_Class_HasCXXStructors      = 0x00004,

  /// Has hidden visibility.
  NonFragileABI_Class_Hidden               = 0x00010,

  /// Has the exception attribute.
  NonFragileABI_Class_Exception            = 0x00020,

  /// (Obsolete) ARC-specific: this class has a .release_ivars method
  NonFragileABI_Class_HasIvarReleaser      = 0x00040,

  /// Class implementation was compiled under ARC.
  NonFragileABI_Class_CompiledByARC        = 0x00080,

  /// Class has non-trivial destructors, but zero-initialization is okay.
  NonFragileABI_Class_HasCXXDestructorOnly = 0x00100,

  /// Class implementation was compiled under MRC and has MRC weak ivars.
  /// Exclusive with CompiledByARC.
  NonFragileABI_Class_HasMRCWeakIvars      = 0x00200,
};
// clang-format on

static bool hasWeakMember(QualType type) {
  if (type.getObjCLifetime() == Qualifiers::OCL_Weak) {
    return true;
  }

  if (auto *RD = type->getAsRecordDecl()) {
    for (auto *field : RD->fields()) {
      if (hasWeakMember(field->getType()))
        return true;
    }
  }

  return false;
}

/// For compatibility, we only want to set the "HasMRCWeakIvars" flag
/// (and actually fill in a layout string) if we really do have any
/// __weak ivars.
static bool hasMRCWeakIvars(CodeGenModule &CGM,
                            const ObjCImplementationDecl *ID) {
  if (!CGM.getLangOpts().ObjCWeak)
    return false;
  assert(CGM.getLangOpts().getGC() == LangOptions::NonGC);

  for (const ObjCIvarDecl *ivar =
           ID->getClassInterface()->all_declared_ivar_begin();
       ivar; ivar = ivar->getNextIvar()) {
    if (hasWeakMember(ivar->getType()))
      return true;
  }

  return false;
}

/*
  struct _objc_class {
  Class isa;
  Class super_class;
  const char *name;
  long version;
  long info;
  long instance_size;
  struct _objc_ivar_list *ivars;
  struct _objc_method_list *methods;
  struct _objc_cache *cache;
  struct _objc_protocol_list *protocols;
  // Objective-C 1.0 extensions (<rdr://4585769>)
  const char *ivar_layout;
  struct _objc_class_ext *ext;
  };

  See EmitClassExtension();
*/
void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
  IdentifierInfo *RuntimeName =
      &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
  DefinedSymbols.insert(RuntimeName);

  std::string ClassName = ID->getNameAsString();
  // FIXME: Gross
  ObjCInterfaceDecl *Interface =
      const_cast<ObjCInterfaceDecl *>(ID->getClassInterface());
  llvm::Constant *Protocols =
      EmitProtocolList("OBJC_CLASS_PROTOCOLS_" + ID->getName(),
                       Interface->all_referenced_protocol_begin(),
                       Interface->all_referenced_protocol_end());
  unsigned Flags = FragileABI_Class_Factory;
  if (ID->hasNonZeroConstructors() || ID->hasDestructors())
    Flags |= FragileABI_Class_HasCXXStructors;

  bool hasMRCWeak = false;

  if (CGM.getLangOpts().ObjCAutoRefCount)
    Flags |= FragileABI_Class_CompiledByARC;
  else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
    Flags |= FragileABI_Class_HasMRCWeakIvars;

  CharUnits Size = CGM.getContext()
                       .getASTObjCInterfaceLayout(ID->getClassInterface())
                       .getSize();

  // FIXME: Set CXX-structors flag.
  if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
    Flags |= FragileABI_Class_Hidden;

  enum { InstanceMethods, ClassMethods, NumMethodLists };
  SmallVector<const ObjCMethodDecl *, 16> Methods[NumMethodLists];
  for (const auto *MD : ID->methods()) {
    if (!MD->isDirectMethod())
      Methods[unsigned(MD->isClassMethod())].push_back(MD);
  }

  for (const auto *PID : ID->property_impls()) {
    if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
      if (PID->getPropertyDecl()->isDirectProperty())
        continue;
      if (ObjCMethodDecl *MD = PID->getGetterMethodDecl())
        if (GetMethodDefinition(MD))
          Methods[InstanceMethods].push_back(MD);
      if (ObjCMethodDecl *MD = PID->getSetterMethodDecl())
        if (GetMethodDefinition(MD))
          Methods[InstanceMethods].push_back(MD);
    }
  }

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ClassTy);
  values.add(EmitMetaClass(ID, Protocols, Methods[ClassMethods]));
  if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
    // Record a reference to the super class.
    LazySymbols.insert(Super->getIdentifier());

    values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
  } else {
    values.addNullPointer(ObjCTypes.ClassPtrTy);
  }
  values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
  // Version is always 0.
  values.addInt(ObjCTypes.LongTy, 0);
  values.addInt(ObjCTypes.LongTy, Flags);
  values.addInt(ObjCTypes.LongTy, Size.getQuantity());
  values.add(EmitIvarList(ID, false));
  values.add(emitMethodList(ID->getName(), MethodListType::InstanceMethods,
                            Methods[InstanceMethods]));
  // cache is always NULL.
  values.addNullPointer(ObjCTypes.CachePtrTy);
  values.add(Protocols);
  values.add(BuildStrongIvarLayout(ID, CharUnits::Zero(), Size));
  values.add(EmitClassExtension(ID, Size, hasMRCWeak,
                                /*isMetaclass*/ false));

  std::string Name("OBJC_CLASS_");
  Name += ClassName;
  const char *Section = "__OBJC,__class,regular,no_dead_strip";
  // Check for a forward reference.
  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
  if (GV) {
    assert(GV->getValueType() == ObjCTypes.ClassTy &&
           "Forward metaclass reference has incorrect type.");
    values.finishAndSetAsInitializer(GV);
    GV->setSection(Section);
    GV->setAlignment(CGM.getPointerAlign().getAsAlign());
    CGM.addCompilerUsedGlobal(GV);
  } else
    GV = CreateMetadataVar(Name, values, Section, CGM.getPointerAlign(), true);
  DefinedClasses.push_back(GV);
  ImplementedClasses.push_back(Interface);
  // method definition entries must be clear for next implementation.
  MethodDefinitions.clear();
}

llvm::Constant *
CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
                         llvm::Constant *Protocols,
                         ArrayRef<const ObjCMethodDecl *> Methods) {
  unsigned Flags = FragileABI_Class_Meta;
  unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy);

  if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
    Flags |= FragileABI_Class_Hidden;

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ClassTy);
  // The isa for the metaclass is the root of the hierarchy.
  const ObjCInterfaceDecl *Root = ID->getClassInterface();
  while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
    Root = Super;
  values.add(GetClassName(Root->getObjCRuntimeNameAsString()));
  // The super class for the metaclass is emitted as the name of the
  // super class. The runtime fixes this up to point to the
  // *metaclass* for the super class.
  if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
    values.add(GetClassName(Super->getObjCRuntimeNameAsString()));
  } else {
    values.addNullPointer(ObjCTypes.ClassPtrTy);
  }
  values.add(GetClassName(ID->getObjCRuntimeNameAsString()));
  // Version is always 0.
  values.addInt(ObjCTypes.LongTy, 0);
  values.addInt(ObjCTypes.LongTy, Flags);
  values.addInt(ObjCTypes.LongTy, Size);
  values.add(EmitIvarList(ID, true));
  values.add(
      emitMethodList(ID->getName(), MethodListType::ClassMethods, Methods));
  // cache is always NULL.
  values.addNullPointer(ObjCTypes.CachePtrTy);
  values.add(Protocols);
  // ivar_layout for metaclass is always NULL.
  values.addNullPointer(ObjCTypes.Int8PtrTy);
  // The class extension is used to store class properties for metaclasses.
  values.add(EmitClassExtension(ID, CharUnits::Zero(), false /*hasMRCWeak*/,
                                /*isMetaclass*/ true));

  std::string Name("OBJC_METACLASS_");
  Name += ID->getName();

  // Check for a forward reference.
  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
  if (GV) {
    assert(GV->getValueType() == ObjCTypes.ClassTy &&
           "Forward metaclass reference has incorrect type.");
    values.finishAndSetAsInitializer(GV);
  } else {
    GV = values.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
                                      /*constant*/ false,
                                      llvm::GlobalValue::PrivateLinkage);
  }
  GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
  CGM.addCompilerUsedGlobal(GV);

  return GV;
}

llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
  std::string Name = "OBJC_METACLASS_" + ID->getNameAsString();

  // FIXME: Should we look these up somewhere other than the module. Its a bit
  // silly since we only generate these while processing an implementation, so
  // exactly one pointer would work if know when we entered/exitted an
  // implementation block.

  // Check for an existing forward reference.
  // Previously, metaclass with internal linkage may have been defined.
  // pass 'true' as 2nd argument so it is returned.
  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);
  if (!GV)
    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
                                  llvm::GlobalValue::PrivateLinkage, nullptr,
                                  Name);

  assert(GV->getValueType() == ObjCTypes.ClassTy &&
         "Forward metaclass reference has incorrect type.");
  return GV;
}

llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
  std::string Name = "OBJC_CLASS_" + ID->getNameAsString();
  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name, true);

  if (!GV)
    GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
                                  llvm::GlobalValue::PrivateLinkage, nullptr,
                                  Name);

  assert(GV->getValueType() == ObjCTypes.ClassTy &&
         "Forward class metadata reference has incorrect type.");
  return GV;
}

/*
  Emit a "class extension", which in this specific context means extra
  data that doesn't fit in the normal fragile-ABI class structure, and
  has nothing to do with the language concept of a class extension.

  struct objc_class_ext {
  uint32_t size;
  const char *weak_ivar_layout;
  struct _objc_property_list *properties;
  };
*/
llvm::Constant *CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID,
                                              CharUnits InstanceSize,
                                              bool hasMRCWeakIvars,
                                              bool isMetaclass) {
  // Weak ivar layout.
  llvm::Constant *layout;
  if (isMetaclass) {
    layout = llvm::ConstantPointerNull::get(CGM.Int8PtrTy);
  } else {
    layout = BuildWeakIvarLayout(ID, CharUnits::Zero(), InstanceSize,
                                 hasMRCWeakIvars);
  }

  // Properties.
  llvm::Constant *propertyList =
      EmitPropertyList((isMetaclass ? Twine("_OBJC_$_CLASS_PROP_LIST_")
                                    : Twine("_OBJC_$_PROP_LIST_")) +
                           ID->getName(),
                       ID, ID->getClassInterface(), ObjCTypes, isMetaclass);

  // Return null if no extension bits are used.
  if (layout->isNullValue() && propertyList->isNullValue()) {
    return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
  }

  uint64_t size =
      CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ClassExtensionTy);
  values.addInt(ObjCTypes.IntTy, size);
  values.add(layout);
  values.add(propertyList);

  return CreateMetadataVar("OBJC_CLASSEXT_" + ID->getName(), values,
                           "__OBJC,__class_ext,regular,no_dead_strip",
                           CGM.getPointerAlign(), true);
}

/*
  struct objc_ivar {
    char *ivar_name;
    char *ivar_type;
    int ivar_offset;
  };

  struct objc_ivar_list {
    int ivar_count;
    struct objc_ivar list[count];
  };
*/
llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
                                        bool ForClass) {
  // When emitting the root class GCC emits ivar entries for the
  // actual class structure. It is not clear if we need to follow this
  // behavior; for now lets try and get away with not doing it. If so,
  // the cleanest solution would be to make up an ObjCInterfaceDecl
  // for the class.
  if (ForClass)
    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);

  const ObjCInterfaceDecl *OID = ID->getClassInterface();

  ConstantInitBuilder builder(CGM);
  auto ivarList = builder.beginStruct();
  auto countSlot = ivarList.addPlaceholder();
  auto ivars = ivarList.beginArray(ObjCTypes.IvarTy);

  for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD;
       IVD = IVD->getNextIvar()) {
    // Ignore unnamed bit-fields.
    if (!IVD->getDeclName())
      continue;

    auto ivar = ivars.beginStruct(ObjCTypes.IvarTy);
    ivar.add(GetMethodVarName(IVD->getIdentifier()));
    ivar.add(GetMethodVarType(IVD));
    ivar.addInt(ObjCTypes.IntTy, ComputeIvarBaseOffset(CGM, OID, IVD));
    ivar.finishAndAddTo(ivars);
  }

  // Return null for empty list.
  auto count = ivars.size();
  if (count == 0) {
    ivars.abandon();
    ivarList.abandon();
    return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
  }

  ivars.finishAndAddTo(ivarList);
  ivarList.fillPlaceholderWithInt(countSlot, ObjCTypes.IntTy, count);

  llvm::GlobalVariable *GV;
  GV = CreateMetadataVar("OBJC_INSTANCE_VARIABLES_" + ID->getName(), ivarList,
                         "__OBJC,__instance_vars,regular,no_dead_strip",
                         CGM.getPointerAlign(), true);
  return GV;
}

/// Build a struct objc_method_description constant for the given method.
///
/// struct objc_method_description {
///   SEL method_name;
///   char *method_types;
/// };
void CGObjCMac::emitMethodDescriptionConstant(ConstantArrayBuilder &builder,
                                              const ObjCMethodDecl *MD) {
  auto description = builder.beginStruct(ObjCTypes.MethodDescriptionTy);
  description.add(GetMethodVarName(MD->getSelector()));
  description.add(GetMethodVarType(MD));
  description.finishAndAddTo(builder);
}

/// Build a struct objc_method constant for the given method.
///
/// struct objc_method {
///   SEL method_name;
///   char *method_types;
///   void *method;
/// };
void CGObjCMac::emitMethodConstant(ConstantArrayBuilder &builder,
                                   const ObjCMethodDecl *MD) {
  llvm::Function *fn = GetMethodDefinition(MD);
  assert(fn && "no definition registered for method");

  auto method = builder.beginStruct(ObjCTypes.MethodTy);
  method.add(GetMethodVarName(MD->getSelector()));
  method.add(GetMethodVarType(MD));
  method.add(fn);
  method.finishAndAddTo(builder);
}

/// Build a struct objc_method_list or struct objc_method_description_list,
/// as appropriate.
///
/// struct objc_method_list {
///   struct objc_method_list *obsolete;
///   int count;
///   struct objc_method methods_list[count];
/// };
///
/// struct objc_method_description_list {
///   int count;
///   struct objc_method_description list[count];
/// };
llvm::Constant *
CGObjCMac::emitMethodList(Twine name, MethodListType MLT,
                          ArrayRef<const ObjCMethodDecl *> methods) {
  StringRef prefix;
  StringRef section;
  bool forProtocol = false;
  switch (MLT) {
  case MethodListType::CategoryInstanceMethods:
    prefix = "OBJC_CATEGORY_INSTANCE_METHODS_";
    section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
    forProtocol = false;
    break;
  case MethodListType::CategoryClassMethods:
    prefix = "OBJC_CATEGORY_CLASS_METHODS_";
    section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
    forProtocol = false;
    break;
  case MethodListType::InstanceMethods:
    prefix = "OBJC_INSTANCE_METHODS_";
    section = "__OBJC,__inst_meth,regular,no_dead_strip";
    forProtocol = false;
    break;
  case MethodListType::ClassMethods:
    prefix = "OBJC_CLASS_METHODS_";
    section = "__OBJC,__cls_meth,regular,no_dead_strip";
    forProtocol = false;
    break;
  case MethodListType::ProtocolInstanceMethods:
    prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_";
    section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
    forProtocol = true;
    break;
  case MethodListType::ProtocolClassMethods:
    prefix = "OBJC_PROTOCOL_CLASS_METHODS_";
    section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
    forProtocol = true;
    break;
  case MethodListType::OptionalProtocolInstanceMethods:
    prefix = "OBJC_PROTOCOL_INSTANCE_METHODS_OPT_";
    section = "__OBJC,__cat_inst_meth,regular,no_dead_strip";
    forProtocol = true;
    break;
  case MethodListType::OptionalProtocolClassMethods:
    prefix = "OBJC_PROTOCOL_CLASS_METHODS_OPT_";
    section = "__OBJC,__cat_cls_meth,regular,no_dead_strip";
    forProtocol = true;
    break;
  }

  // Return null for empty list.
  if (methods.empty())
    return llvm::Constant::getNullValue(
        forProtocol ? ObjCTypes.MethodDescriptionListPtrTy
                    : ObjCTypes.MethodListPtrTy);

  // For protocols, this is an objc_method_description_list, which has
  // a slightly different structure.
  if (forProtocol) {
    ConstantInitBuilder builder(CGM);
    auto values = builder.beginStruct();
    values.addInt(ObjCTypes.IntTy, methods.size());
    auto methodArray = values.beginArray(ObjCTypes.MethodDescriptionTy);
    for (auto MD : methods) {
      emitMethodDescriptionConstant(methodArray, MD);
    }
    methodArray.finishAndAddTo(values);

    llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
                                                 CGM.getPointerAlign(), true);
    return GV;
  }

  // Otherwise, it's an objc_method_list.
  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct();
  values.addNullPointer(ObjCTypes.Int8PtrTy);
  values.addInt(ObjCTypes.IntTy, methods.size());
  auto methodArray = values.beginArray(ObjCTypes.MethodTy);
  for (auto MD : methods) {
    if (!MD->isDirectMethod())
      emitMethodConstant(methodArray, MD);
  }
  methodArray.finishAndAddTo(values);

  llvm::GlobalVariable *GV = CreateMetadataVar(prefix + name, values, section,
                                               CGM.getPointerAlign(), true);
  return GV;
}

llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
                                                const ObjCContainerDecl *CD) {
  llvm::Function *Method;

  if (OMD->isDirectMethod()) {
    Method = GenerateDirectMethod(OMD, CD);
  } else {
    auto Name = getSymbolNameForMethod(OMD);

    CodeGenTypes &Types = CGM.getTypes();
    llvm::FunctionType *MethodTy =
        Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
    Method = llvm::Function::Create(
        MethodTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule());
  }

  MethodDefinitions.insert(std::make_pair(OMD, Method));

  return Method;
}

llvm::Function *
CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
                                      const ObjCContainerDecl *CD) {
  auto *COMD = OMD->getCanonicalDecl();
  auto I = DirectMethodDefinitions.find(COMD);
  llvm::Function *OldFn = nullptr, *Fn = nullptr;

  if (I != DirectMethodDefinitions.end()) {
    // Objective-C allows for the declaration and implementation types
    // to differ slightly.
    //
    // If we're being asked for the Function associated for a method
    // implementation, a previous value might have been cached
    // based on the type of the canonical declaration.
    //
    // If these do not match, then we'll replace this function with
    // a new one that has the proper type below.
    if (!OMD->getBody() || COMD->getReturnType() == OMD->getReturnType())
      return I->second;
    OldFn = I->second;
  }

  CodeGenTypes &Types = CGM.getTypes();
  llvm::FunctionType *MethodTy =
      Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));

  if (OldFn) {
    Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
                                "", &CGM.getModule());
    Fn->takeName(OldFn);
    OldFn->replaceAllUsesWith(Fn);
    OldFn->eraseFromParent();

    // Replace the cached function in the map.
    I->second = Fn;
  } else {
    auto Name = getSymbolNameForMethod(OMD, /*include category*/ false);

    Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
                                Name, &CGM.getModule());
    DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
  }

  return Fn;
}

void CGObjCCommonMac::GenerateDirectMethodPrologue(
    CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
    const ObjCContainerDecl *CD) {
  auto &Builder = CGF.Builder;
  bool ReceiverCanBeNull = true;
  auto selfAddr = CGF.GetAddrOfLocalVar(OMD->getSelfDecl());
  auto selfValue = Builder.CreateLoad(selfAddr);

  // Generate:
  //
  // /* for class methods only to force class lazy initialization */
  // self = [self self];
  //
  // /* unless the receiver is never NULL */
  // if (self == nil) {
  //     return (ReturnType){ };
  // }
  //
  // _cmd = @selector(...)
  // ...

  if (OMD->isClassMethod()) {
    const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);
    assert(OID &&
           "GenerateDirectMethod() should be called with the Class Interface");
    Selector SelfSel = GetNullarySelector("self", CGM.getContext());
    auto ResultType = CGF.getContext().getObjCIdType();
    RValue result;
    CallArgList Args;

    // TODO: If this method is inlined, the caller might know that `self` is
    // already initialized; for example, it might be an ordinary Objective-C
    // method which always receives an initialized `self`, or it might have just
    // forced initialization on its own.
    //
    // We should find a way to eliminate this unnecessary initialization in such
    // cases in LLVM.
    result = GeneratePossiblySpecializedMessageSend(
        CGF, ReturnValueSlot(), ResultType, SelfSel, selfValue, Args, OID,
        nullptr, true);
    Builder.CreateStore(result.getScalarVal(), selfAddr);

    // Nullable `Class` expressions cannot be messaged with a direct method
    // so the only reason why the receive can be null would be because
    // of weak linking.
    ReceiverCanBeNull = isWeakLinkedClass(OID);
  }

  if (ReceiverCanBeNull) {
    llvm::BasicBlock *SelfIsNilBlock =
        CGF.createBasicBlock("objc_direct_method.self_is_nil");
    llvm::BasicBlock *ContBlock =
        CGF.createBasicBlock("objc_direct_method.cont");

    // if (self == nil) {
    auto selfTy = cast<llvm::PointerType>(selfValue->getType());
    auto Zero = llvm::ConstantPointerNull::get(selfTy);

    llvm::MDBuilder MDHelper(CGM.getLLVMContext());
    Builder.CreateCondBr(Builder.CreateICmpEQ(selfValue, Zero), SelfIsNilBlock,
                         ContBlock, MDHelper.createUnlikelyBranchWeights());

    CGF.EmitBlock(SelfIsNilBlock);

    //   return (ReturnType){ };
    auto retTy = OMD->getReturnType();
    Builder.SetInsertPoint(SelfIsNilBlock);
    if (!retTy->isVoidType()) {
      CGF.EmitNullInitialization(CGF.ReturnValue, retTy);
    }
    CGF.EmitBranchThroughCleanup(CGF.ReturnBlock);
    // }

    // rest of the body
    CGF.EmitBlock(ContBlock);
    Builder.SetInsertPoint(ContBlock);
  }

  // only synthesize _cmd if it's referenced
  if (OMD->getCmdDecl()->isUsed()) {
    // `_cmd` is not a parameter to direct methods, so storage must be
    // explicitly declared for it.
    CGF.EmitVarDecl(*OMD->getCmdDecl());
    Builder.CreateStore(GetSelector(CGF, OMD),
                        CGF.GetAddrOfLocalVar(OMD->getCmdDecl()));
  }
}

llvm::GlobalVariable *
CGObjCCommonMac::CreateMetadataVar(Twine Name, ConstantStructBuilder &Init,
                                   StringRef Section, CharUnits Align,
                                   bool AddToUsed) {
  llvm::GlobalValue::LinkageTypes LT =
      getLinkageTypeForObjCMetadata(CGM, Section);
  llvm::GlobalVariable *GV =
      Init.finishAndCreateGlobal(Name, Align, /*constant*/ false, LT);
  if (!Section.empty())
    GV->setSection(Section);
  if (AddToUsed)
    CGM.addCompilerUsedGlobal(GV);
  return GV;
}

llvm::GlobalVariable *CGObjCCommonMac::CreateMetadataVar(Twine Name,
                                                         llvm::Constant *Init,
                                                         StringRef Section,
                                                         CharUnits Align,
                                                         bool AddToUsed) {
  llvm::Type *Ty = Init->getType();
  llvm::GlobalValue::LinkageTypes LT =
      getLinkageTypeForObjCMetadata(CGM, Section);
  llvm::GlobalVariable *GV =
      new llvm::GlobalVariable(CGM.getModule(), Ty, false, LT, Init, Name);
  if (!Section.empty())
    GV->setSection(Section);
  GV->setAlignment(Align.getAsAlign());
  if (AddToUsed)
    CGM.addCompilerUsedGlobal(GV);
  return GV;
}

llvm::GlobalVariable *
CGObjCCommonMac::CreateCStringLiteral(StringRef Name, ObjCLabelType Type,
                                      bool ForceNonFragileABI,
                                      bool NullTerminate) {
  StringRef Label;
  switch (Type) {
  case ObjCLabelType::ClassName:
    Label = "OBJC_CLASS_NAME_";
    break;
  case ObjCLabelType::MethodVarName:
    Label = "OBJC_METH_VAR_NAME_";
    break;
  case ObjCLabelType::MethodVarType:
    Label = "OBJC_METH_VAR_TYPE_";
    break;
  case ObjCLabelType::PropertyName:
    Label = "OBJC_PROP_NAME_ATTR_";
    break;
  }

  bool NonFragile = ForceNonFragileABI || isNonFragileABI();

  StringRef Section;
  switch (Type) {
  case ObjCLabelType::ClassName:
    Section = NonFragile ? "__TEXT,__objc_classname,cstring_literals"
                         : "__TEXT,__cstring,cstring_literals";
    break;
  case ObjCLabelType::MethodVarName:
    Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
                         : "__TEXT,__cstring,cstring_literals";
    break;
  case ObjCLabelType::MethodVarType:
    Section = NonFragile ? "__TEXT,__objc_methtype,cstring_literals"
                         : "__TEXT,__cstring,cstring_literals";
    break;
  case ObjCLabelType::PropertyName:
    Section = NonFragile ? "__TEXT,__objc_methname,cstring_literals"
                         : "__TEXT,__cstring,cstring_literals";
    break;
  }

  llvm::Constant *Value =
      llvm::ConstantDataArray::getString(VMContext, Name, NullTerminate);
  llvm::GlobalVariable *GV = new llvm::GlobalVariable(
      CGM.getModule(), Value->getType(),
      /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, Value, Label);
  if (CGM.getTriple().isOSBinFormatMachO())
    GV->setSection(Section);
  GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
  GV->setAlignment(CharUnits::One().getAsAlign());
  CGM.addCompilerUsedGlobal(GV);

  return GV;
}

llvm::Function *CGObjCMac::ModuleInitFunction() {
  // Abuse this interface function as a place to finalize.
  FinishModule();
  return nullptr;
}

llvm::FunctionCallee CGObjCMac::GetPropertyGetFunction() {
  return ObjCTypes.getGetPropertyFn();
}

llvm::FunctionCallee CGObjCMac::GetPropertySetFunction() {
  return ObjCTypes.getSetPropertyFn();
}

llvm::FunctionCallee CGObjCMac::GetOptimizedPropertySetFunction(bool atomic,
                                                                bool copy) {
  return ObjCTypes.getOptimizedSetPropertyFn(atomic, copy);
}

llvm::FunctionCallee CGObjCMac::GetGetStructFunction() {
  return ObjCTypes.getCopyStructFn();
}

llvm::FunctionCallee CGObjCMac::GetSetStructFunction() {
  return ObjCTypes.getCopyStructFn();
}

llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectGetFunction() {
  return ObjCTypes.getCppAtomicObjectFunction();
}

llvm::FunctionCallee CGObjCMac::GetCppAtomicObjectSetFunction() {
  return ObjCTypes.getCppAtomicObjectFunction();
}

llvm::FunctionCallee CGObjCMac::EnumerationMutationFunction() {
  return ObjCTypes.getEnumerationMutationFn();
}

void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
  return EmitTryOrSynchronizedStmt(CGF, S);
}

void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
                                     const ObjCAtSynchronizedStmt &S) {
  return EmitTryOrSynchronizedStmt(CGF, S);
}

namespace {
struct PerformFragileFinally final : EHScopeStack::Cleanup {
  const Stmt &S;
  Address SyncArgSlot;
  Address CallTryExitVar;
  Address ExceptionData;
  ObjCTypesHelper &ObjCTypes;
  PerformFragileFinally(const Stmt *S, Address SyncArgSlot,
                        Address CallTryExitVar, Address ExceptionData,
                        ObjCTypesHelper *ObjCTypes)
      : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
        ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}

  void Emit(CodeGenFunction &CGF, Flags flags) override {
    // Check whether we need to call objc_exception_try_exit.
    // In optimized code, this branch will always be folded.
    llvm::BasicBlock *FinallyCallExit =
        CGF.createBasicBlock("finally.call_exit");
    llvm::BasicBlock *FinallyNoCallExit =
        CGF.createBasicBlock("finally.no_call_exit");
    CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
                             FinallyCallExit, FinallyNoCallExit);

    CGF.EmitBlock(FinallyCallExit);
    CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryExitFn(),
                                ExceptionData.emitRawPointer(CGF));

    CGF.EmitBlock(FinallyNoCallExit);

    if (isa<ObjCAtTryStmt>(S)) {
      if (const ObjCAtFinallyStmt *FinallyStmt =
              cast<ObjCAtTryStmt>(S).getFinallyStmt()) {
        // Don't try to do the @finally if this is an EH cleanup.
        if (flags.isForEHCleanup())
          return;

        // Save the current cleanup destination in case there's
        // control flow inside the finally statement.
        llvm::Value *CurCleanupDest =
            CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot());

        CGF.EmitStmt(FinallyStmt->getFinallyBody());

        if (CGF.HaveInsertPoint()) {
          CGF.Builder.CreateStore(CurCleanupDest,
                                  CGF.getNormalCleanupDestSlot());
        } else {
          // Currently, the end of the cleanup must always exist.
          CGF.EnsureInsertPoint();
        }
      }
    } else {
      // Emit objc_sync_exit(expr); as finally's sole statement for
      // @synchronized.
      llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
      CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncExitFn(), SyncArg);
    }
  }
};

class FragileHazards {
  CodeGenFunction &CGF;
  SmallVector<llvm::Value *, 20> Locals;
  llvm::DenseSet<llvm::BasicBlock *> BlocksBeforeTry;

  llvm::InlineAsm *ReadHazard;
  llvm::InlineAsm *WriteHazard;

  llvm::FunctionType *GetAsmFnType();

  void collectLocals();
  void emitReadHazard(CGBuilderTy &Builder);

public:
  FragileHazards(CodeGenFunction &CGF);

  void emitWriteHazard();
  void emitHazardsInNewBlocks();
};
} // end anonymous namespace

/// Create the fragile-ABI read and write hazards based on the current
/// state of the function, which is presumed to be immediately prior
/// to a @try block.  These hazards are used to maintain correct
/// semantics in the face of optimization and the fragile ABI's
/// cavalier use of setjmp/longjmp.
FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
  collectLocals();

  if (Locals.empty())
    return;

  // Collect all the blocks in the function.
  for (llvm::BasicBlock &BB : *CGF.CurFn)
    BlocksBeforeTry.insert(&BB);

  llvm::FunctionType *AsmFnTy = GetAsmFnType();

  // Create a read hazard for the allocas.  This inhibits dead-store
  // optimizations and forces the values to memory.  This hazard is
  // inserted before any 'throwing' calls in the protected scope to
  // reflect the possibility that the variables might be read from the
  // catch block if the call throws.
  {
    std::string Constraint;
    for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
      if (I)
        Constraint += ',';
      Constraint += "*m";
    }

    ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
  }

  // Create a write hazard for the allocas.  This inhibits folding
  // loads across the hazard.  This hazard is inserted at the
  // beginning of the catch path to reflect the possibility that the
  // variables might have been written within the protected scope.
  {
    std::string Constraint;
    for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
      if (I)
        Constraint += ',';
      Constraint += "=*m";
    }

    WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
  }
}

/// Emit a write hazard at the current location.
void FragileHazards::emitWriteHazard() {
  if (Locals.empty())
    return;

  llvm::CallInst *Call = CGF.EmitNounwindRuntimeCall(WriteHazard, Locals);
  for (auto Pair : llvm::enumerate(Locals))
    Call->addParamAttr(
        Pair.index(),
        llvm::Attribute::get(
            CGF.getLLVMContext(), llvm::Attribute::ElementType,
            cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
}

void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
  assert(!Locals.empty());
  llvm::CallInst *call = Builder.CreateCall(ReadHazard, Locals);
  call->setDoesNotThrow();
  call->setCallingConv(CGF.getRuntimeCC());
  for (auto Pair : llvm::enumerate(Locals))
    call->addParamAttr(
        Pair.index(),
        llvm::Attribute::get(
            Builder.getContext(), llvm::Attribute::ElementType,
            cast<llvm::AllocaInst>(Pair.value())->getAllocatedType()));
}

/// Emit read hazards in all the protected blocks, i.e. all the blocks
/// which have been inserted since the beginning of the try.
void FragileHazards::emitHazardsInNewBlocks() {
  if (Locals.empty())
    return;

  CGBuilderTy Builder(CGF, CGF.getLLVMContext());

  // Iterate through all blocks, skipping those prior to the try.
  for (llvm::BasicBlock &BB : *CGF.CurFn) {
    if (BlocksBeforeTry.count(&BB))
      continue;

    // Walk through all the calls in the block.
    for (llvm::BasicBlock::iterator BI = BB.begin(), BE = BB.end(); BI != BE;
         ++BI) {
      llvm::Instruction &I = *BI;

      // Ignore instructions that aren't non-intrinsic calls.
      // These are the only calls that can possibly call longjmp.
      if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I))
        continue;
      if (isa<llvm::IntrinsicInst>(I))
        continue;

      // Ignore call sites marked nounwind.  This may be questionable,
      // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
      if (cast<llvm::CallBase>(I).doesNotThrow())
        continue;

      // Insert a read hazard before the call.  This will ensure that
      // any writes to the locals are performed before making the
      // call.  If the call throws, then this is sufficient to
      // guarantee correctness as long as it doesn't also write to any
      // locals.
      Builder.SetInsertPoint(&BB, BI);
      emitReadHazard(Builder);
    }
  }
}

static void addIfPresent(llvm::DenseSet<llvm::Value *> &S, Address V) {
  if (V.isValid())
    if (llvm::Value *Ptr = V.getBasePointer())
      S.insert(Ptr);
}

void FragileHazards::collectLocals() {
  // Compute a set of allocas to ignore.
  llvm::DenseSet<llvm::Value *> AllocasToIgnore;
  addIfPresent(AllocasToIgnore, CGF.ReturnValue);
  addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);

  // Collect all the allocas currently in the function.  This is
  // probably way too aggressive.
  llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
  for (llvm::Instruction &I : Entry)
    if (isa<llvm::AllocaInst>(I) && !AllocasToIgnore.count(&I))
      Locals.push_back(&I);
}

llvm::FunctionType *FragileHazards::GetAsmFnType() {
  SmallVector<llvm::Type *, 16> tys(Locals.size());
  for (unsigned i = 0, e = Locals.size(); i != e; ++i)
    tys[i] = Locals[i]->getType();
  return llvm::FunctionType::get(CGF.VoidTy, tys, false);
}

/*

  Objective-C setjmp-longjmp (sjlj) Exception Handling
  --

  A catch buffer is a setjmp buffer plus:
    - a pointer to the exception that was caught
    - a pointer to the previous exception data buffer
    - two pointers of reserved storage
  Therefore catch buffers form a stack, with a pointer to the top
  of the stack kept in thread-local storage.

  objc_exception_try_enter pushes a catch buffer onto the EH stack.
  objc_exception_try_exit pops the given catch buffer, which is
    required to be the top of the EH stack.
  objc_exception_throw pops the top of the EH stack, writes the
    thrown exception into the appropriate field, and longjmps
    to the setjmp buffer.  It crashes the process (with a printf
    and an abort()) if there are no catch buffers on the stack.
  objc_exception_extract just reads the exception pointer out of the
    catch buffer.

  There's no reason an implementation couldn't use a light-weight
  setjmp here --- something like __builtin_setjmp, but API-compatible
  with the heavyweight setjmp.  This will be more important if we ever
  want to implement correct ObjC/C++ exception interactions for the
  fragile ABI.

  Note that for this use of setjmp/longjmp to be correct in the presence of
  optimization, we use inline assembly on the set of local variables to force
  flushing locals to memory immediately before any protected calls and to
  inhibit optimizing locals across the setjmp->catch edge.

  The basic framework for a @try-catch-finally is as follows:
  {
  objc_exception_data d;
  id _rethrow = null;
  bool _call_try_exit = true;

  objc_exception_try_enter(&d);
  if (!setjmp(d.jmp_buf)) {
  ... try body ...
  } else {
  // exception path
  id _caught = objc_exception_extract(&d);

  // enter new try scope for handlers
  if (!setjmp(d.jmp_buf)) {
  ... match exception and execute catch blocks ...

  // fell off end, rethrow.
  _rethrow = _caught;
  ... jump-through-finally to finally_rethrow ...
  } else {
  // exception in catch block
  _rethrow = objc_exception_extract(&d);
  _call_try_exit = false;
  ... jump-through-finally to finally_rethrow ...
  }
  }
  ... jump-through-finally to finally_end ...

  finally:
  if (_call_try_exit)
  objc_exception_try_exit(&d);

  ... finally block ....
  ... dispatch to finally destination ...

  finally_rethrow:
  objc_exception_throw(_rethrow);

  finally_end:
  }

  This framework differs slightly from the one gcc uses, in that gcc
  uses _rethrow to determine if objc_exception_try_exit should be called
  and if the object should be rethrown. This breaks in the face of
  throwing nil and introduces unnecessary branches.

  We specialize this framework for a few particular circumstances:

  - If there are no catch blocks, then we avoid emitting the second
  exception handling context.

  - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
  e)) we avoid emitting the code to rethrow an uncaught exception.

  - FIXME: If there is no @finally block we can do a few more
  simplifications.

  Rethrows and Jumps-Through-Finally
  --

  '@throw;' is supported by pushing the currently-caught exception
  onto ObjCEHStack while the @catch blocks are emitted.

  Branches through the @finally block are handled with an ordinary
  normal cleanup.  We do not register an EH cleanup; fragile-ABI ObjC
  exceptions are not compatible with C++ exceptions, and this is
  hardly the only place where this will go wrong.

  @synchronized(expr) { stmt; } is emitted as if it were:
    id synch_value = expr;
    objc_sync_enter(synch_value);
    @try { stmt; } @finally { objc_sync_exit(synch_value); }
*/

void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
                                          const Stmt &S) {
  bool isTry = isa<ObjCAtTryStmt>(S);

  // A destination for the fall-through edges of the catch handlers to
  // jump to.
  CodeGenFunction::JumpDest FinallyEnd =
      CGF.getJumpDestInCurrentScope("finally.end");

  // A destination for the rethrow edge of the catch handlers to jump
  // to.
  CodeGenFunction::JumpDest FinallyRethrow =
      CGF.getJumpDestInCurrentScope("finally.rethrow");

  // For @synchronized, call objc_sync_enter(sync.expr). The
  // evaluation of the expression must occur before we enter the
  // @synchronized.  We can't avoid a temp here because we need the
  // value to be preserved.  If the backend ever does liveness
  // correctly after setjmp, this will be unnecessary.
  Address SyncArgSlot = Address::invalid();
  if (!isTry) {
    llvm::Value *SyncArg =
        CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
    SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
    CGF.EmitNounwindRuntimeCall(ObjCTypes.getSyncEnterFn(), SyncArg);

    SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(),
                                       CGF.getPointerAlign(), "sync.arg");
    CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
  }

  // Allocate memory for the setjmp buffer.  This needs to be kept
  // live throughout the try and catch blocks.
  Address ExceptionData = CGF.CreateTempAlloca(
      ObjCTypes.ExceptionDataTy, CGF.getPointerAlign(), "exceptiondata.ptr");

  // Create the fragile hazards.  Note that this will not capture any
  // of the allocas required for exception processing, but will
  // capture the current basic block (which extends all the way to the
  // setjmp call) as "before the @try".
  FragileHazards Hazards(CGF);

  // Create a flag indicating whether the cleanup needs to call
  // objc_exception_try_exit.  This is true except when
  //   - no catches match and we're branching through the cleanup
  //     just to rethrow the exception, or
  //   - a catch matched and we're falling out of the catch handler.
  // The setjmp-safety rule here is that we should always store to this
  // variable in a place that dominates the branch through the cleanup
  // without passing through any setjmps.
  Address CallTryExitVar = CGF.CreateTempAlloca(
      CGF.Builder.getInt1Ty(), CharUnits::One(), "_call_try_exit");

  // A slot containing the exception to rethrow.  Only needed when we
  // have both a @catch and a @finally.
  Address PropagatingExnVar = Address::invalid();

  // Push a normal cleanup to leave the try scope.
  CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalAndEHCleanup, &S,
                                                 SyncArgSlot, CallTryExitVar,
                                                 ExceptionData, &ObjCTypes);

  // Enter a try block:
  //  - Call objc_exception_try_enter to push ExceptionData on top of
  //    the EH stack.
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
                              ExceptionData.emitRawPointer(CGF));

  //  - Call setjmp on the exception data buffer.
  llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
  llvm::Value *GEPIndexes[] = {Zero, Zero, Zero};
  llvm::Value *SetJmpBuffer = CGF.Builder.CreateGEP(
      ObjCTypes.ExceptionDataTy, ExceptionData.emitRawPointer(CGF), GEPIndexes,
      "setjmp_buffer");
  llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
      ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
  SetJmpResult->setCanReturnTwice();

  // If setjmp returned 0, enter the protected block; otherwise,
  // branch to the handler.
  llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
  llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
  llvm::Value *DidCatch =
      CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
  CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock);

  // Emit the protected block.
  CGF.EmitBlock(TryBlock);
  CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
  CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
                     : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());

  CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();

  // Emit the exception handler block.
  CGF.EmitBlock(TryHandler);

  // Don't optimize loads of the in-scope locals across this point.
  Hazards.emitWriteHazard();

  // For a @synchronized (or a @try with no catches), just branch
  // through the cleanup to the rethrow block.
  if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
    // Tell the cleanup not to re-pop the exit.
    CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
    CGF.EmitBranchThroughCleanup(FinallyRethrow);

  // Otherwise, we have to match against the caught exceptions.
  } else {
    // Retrieve the exception object.  We may emit multiple blocks but
    // nothing can cross this so the value is already in SSA form.
    llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall(
        ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
        "caught");

    // Push the exception to rethrow onto the EH value stack for the
    // benefit of any @throws in the handlers.
    CGF.ObjCEHValueStack.push_back(Caught);

    const ObjCAtTryStmt *AtTryStmt = cast<ObjCAtTryStmt>(&S);

    bool HasFinally = (AtTryStmt->getFinallyStmt() != nullptr);

    llvm::BasicBlock *CatchBlock = nullptr;
    llvm::BasicBlock *CatchHandler = nullptr;
    if (HasFinally) {
      // Save the currently-propagating exception before
      // objc_exception_try_enter clears the exception slot.
      PropagatingExnVar = CGF.CreateTempAlloca(
          Caught->getType(), CGF.getPointerAlign(), "propagating_exception");
      CGF.Builder.CreateStore(Caught, PropagatingExnVar);

      // Enter a new exception try block (in case a @catch block
      // throws an exception).
      CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionTryEnterFn(),
                                  ExceptionData.emitRawPointer(CGF));

      llvm::CallInst *SetJmpResult = CGF.EmitNounwindRuntimeCall(
          ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp.result");
      SetJmpResult->setCanReturnTwice();

      llvm::Value *Threw =
          CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");

      CatchBlock = CGF.createBasicBlock("catch");
      CatchHandler = CGF.createBasicBlock("catch_for_catch");
      CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);

      CGF.EmitBlock(CatchBlock);
    }

    CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);

    // Handle catch list. As a special case we check if everything is
    // matched and avoid generating code for falling off the end if
    // so.
    bool AllMatched = false;
    for (const ObjCAtCatchStmt *CatchStmt : AtTryStmt->catch_stmts()) {
      const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
      const ObjCObjectPointerType *OPT = nullptr;

      // catch(...) always matches.
      if (!CatchParam) {
        AllMatched = true;
      } else {
        OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();

        // catch(id e) always matches under this ABI, since only
        // ObjC exceptions end up here in the first place.
        // FIXME: For the time being we also match id<X>; this should
        // be rejected by Sema instead.
        if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
          AllMatched = true;
      }

      // If this is a catch-all, we don't need to test anything.
      if (AllMatched) {
        CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);

        if (CatchParam) {
          CGF.EmitAutoVarDecl(*CatchParam);
          assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");

          // These types work out because ConvertType(id) == i8*.
          EmitInitOfCatchParam(CGF, Caught, CatchParam);
        }

        CGF.EmitStmt(CatchStmt->getCatchBody());

        // The scope of the catch variable ends right here.
        CatchVarCleanups.ForceCleanup();

        CGF.EmitBranchThroughCleanup(FinallyEnd);
        break;
      }

      assert(OPT && "Unexpected non-object pointer type in @catch");
      const ObjCObjectType *ObjTy = OPT->getObjectType();

      // FIXME: @catch (Class c) ?
      ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
      assert(IDecl && "Catch parameter must have Objective-C type!");

      // Check if the @catch block matches the exception object.
      llvm::Value *Class = EmitClassRef(CGF, IDecl);

      llvm::Value *matchArgs[] = {Class, Caught};
      llvm::CallInst *Match = CGF.EmitNounwindRuntimeCall(
          ObjCTypes.getExceptionMatchFn(), matchArgs, "match");

      llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
      llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");

      CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
                               MatchedBlock, NextCatchBlock);

      // Emit the @catch block.
      CGF.EmitBlock(MatchedBlock);

      // Collect any cleanups for the catch variable.  The scope lasts until
      // the end of the catch body.
      CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);

      CGF.EmitAutoVarDecl(*CatchParam);
      assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");

      // Initialize the catch variable.
      llvm::Value *Tmp = CGF.Builder.CreateBitCast(
          Caught, CGF.ConvertType(CatchParam->getType()));
      EmitInitOfCatchParam(CGF, Tmp, CatchParam);

      CGF.EmitStmt(CatchStmt->getCatchBody());

      // We're done with the catch variable.
      CatchVarCleanups.ForceCleanup();

      CGF.EmitBranchThroughCleanup(FinallyEnd);

      CGF.EmitBlock(NextCatchBlock);
    }

    CGF.ObjCEHValueStack.pop_back();

    // If nothing wanted anything to do with the caught exception,
    // kill the extract call.
    if (Caught->use_empty())
      Caught->eraseFromParent();

    if (!AllMatched)
      CGF.EmitBranchThroughCleanup(FinallyRethrow);

    if (HasFinally) {
      // Emit the exception handler for the @catch blocks.
      CGF.EmitBlock(CatchHandler);

      // In theory we might now need a write hazard, but actually it's
      // unnecessary because there's no local-accessing code between
      // the try's write hazard and here.
      // Hazards.emitWriteHazard();

      // Extract the new exception and save it to the
      // propagating-exception slot.
      assert(PropagatingExnVar.isValid());
      llvm::CallInst *NewCaught = CGF.EmitNounwindRuntimeCall(
          ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF),
          "caught");
      CGF.Builder.CreateStore(NewCaught, PropagatingExnVar);

      // Don't pop the catch handler; the throw already did.
      CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
      CGF.EmitBranchThroughCleanup(FinallyRethrow);
    }
  }

  // Insert read hazards as required in the new blocks.
  Hazards.emitHazardsInNewBlocks();

  // Pop the cleanup.
  CGF.Builder.restoreIP(TryFallthroughIP);
  if (CGF.HaveInsertPoint())
    CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
  CGF.PopCleanupBlock();
  CGF.EmitBlock(FinallyEnd.getBlock(), true);

  // Emit the rethrow block.
  CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
  CGF.EmitBlock(FinallyRethrow.getBlock(), true);
  if (CGF.HaveInsertPoint()) {
    // If we have a propagating-exception variable, check it.
    llvm::Value *PropagatingExn;
    if (PropagatingExnVar.isValid()) {
      PropagatingExn = CGF.Builder.CreateLoad(PropagatingExnVar);

    // Otherwise, just look in the buffer for the exception to throw.
    } else {
      llvm::CallInst *Caught = CGF.EmitNounwindRuntimeCall(
          ObjCTypes.getExceptionExtractFn(), ExceptionData.emitRawPointer(CGF));
      PropagatingExn = Caught;
    }

    CGF.EmitNounwindRuntimeCall(ObjCTypes.getExceptionThrowFn(),
                                PropagatingExn);
    CGF.Builder.CreateUnreachable();
  }

  CGF.Builder.restoreIP(SavedIP);
}

void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
                              const ObjCAtThrowStmt &S,
                              bool ClearInsertionPoint) {
  llvm::Value *ExceptionAsObject;

  if (const Expr *ThrowExpr = S.getThrowExpr()) {
    llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
    ExceptionAsObject =
        CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
  } else {
    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
           "Unexpected rethrow outside @catch block.");
    ExceptionAsObject = CGF.ObjCEHValueStack.back();
  }

  CGF.EmitRuntimeCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
      ->setDoesNotReturn();
  CGF.Builder.CreateUnreachable();

  // Clear the insertion point to indicate we are in unreachable code.
  if (ClearInsertionPoint)
    CGF.Builder.ClearInsertionPoint();
}

/// EmitObjCWeakRead - Code gen for loading value of a __weak
/// object: objc_read_weak (id *src)
///
llvm::Value *CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
                                         Address AddrWeakObj) {
  llvm::Type *DestTy = AddrWeakObj.getElementType();
  llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
      AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
  llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(
      ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread");
  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
  return read_weak;
}

/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
/// objc_assign_weak (id src, id *dst)
///
void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
                                   llvm::Value *src, Address dst) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
                      : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
                              "weakassign");
}

/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
/// objc_assign_global (id src, id *dst)
///
void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
                                     llvm::Value *src, Address dst,
                                     bool threadlocal) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
                      : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal};
  if (!threadlocal)
    CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
                                "globalassign");
  else
    CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
                                "threadlocalassign");
}

/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
///
void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
                                   llvm::Value *src, Address dst,
                                   llvm::Value *ivarOffset) {
  assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
                      : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal, ivarOffset};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
}

/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
/// objc_assign_strongCast (id src, id *dst)
///
void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
                                         llvm::Value *src, Address dst) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4) ? CGF.Builder.CreateBitCast(src, CGM.Int32Ty)
                      : CGF.Builder.CreateBitCast(src, CGM.Int64Ty);
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
                              "strongassign");
}

void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
                                         Address DestPtr, Address SrcPtr,
                                         llvm::Value *size) {
  llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
                         SrcPtr.emitRawPointer(CGF), size};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
}

/// EmitObjCValueForIvar - Code Gen for ivar reference.
///
LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
                                       QualType ObjectTy,
                                       llvm::Value *BaseValue,
                                       const ObjCIvarDecl *Ivar,
                                       unsigned CVRQualifiers) {
  const ObjCInterfaceDecl *ID =
      ObjectTy->castAs<ObjCObjectType>()->getInterface();
  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
                                  EmitIvarOffset(CGF, ID, Ivar));
}

llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                                       const ObjCInterfaceDecl *Interface,
                                       const ObjCIvarDecl *Ivar) {
  uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
  return llvm::ConstantInt::get(
      CGM.getTypes().ConvertType(CGM.getContext().LongTy), Offset);
}

/* *** Private Interface *** */

std::string CGObjCCommonMac::GetSectionName(StringRef Section,
                                            StringRef MachOAttributes) {
  switch (CGM.getTriple().getObjectFormat()) {
  case llvm::Triple::UnknownObjectFormat:
    llvm_unreachable("unexpected object file format");
  case llvm::Triple::MachO: {
    if (MachOAttributes.empty())
      return ("__DATA," + Section).str();
    return ("__DATA," + Section + "," + MachOAttributes).str();
  }
  case llvm::Triple::ELF:
    assert(Section.starts_with("__") && "expected the name to begin with __");
    return Section.substr(2).str();
  case llvm::Triple::COFF:
    assert(Section.starts_with("__") && "expected the name to begin with __");
    return ("." + Section.substr(2) + "$B").str();
  case llvm::Triple::Wasm:
  case llvm::Triple::GOFF:
  case llvm::Triple::SPIRV:
  case llvm::Triple::XCOFF:
  case llvm::Triple::DXContainer:
    llvm::report_fatal_error(
        "Objective-C support is unimplemented for object file format");
  }

  llvm_unreachable("Unhandled llvm::Triple::ObjectFormatType enum");
}

// clang-format off
/// EmitImageInfo - Emit the image info marker used to encode some module
/// level information.
///
/// See: <rdr://4810609&4810587&4810587>
/// struct IMAGE_INFO {
///   unsigned version;
///   unsigned flags;
/// };
enum ImageInfoFlags {
  eImageInfo_FixAndContinue      = (1 << 0), // This flag is no longer set by clang.
  eImageInfo_GarbageCollected    = (1 << 1),
  eImageInfo_GCOnly              = (1 << 2),
  eImageInfo_OptimizedByDyld     = (1 << 3), // This flag is set by the dyld shared cache.

  eImageInfo_SignedClassRO       = (1 << 4), // Reused (was _CorrectedSynthesize)
  eImageInfo_ImageIsSimulated    = (1 << 5),
  eImageInfo_ClassProperties     = (1 << 6)
};
// clang-format on

void CGObjCCommonMac::EmitImageInfo() {
  unsigned version = 0; // Version is unused?
  std::string Section =
      (ObjCABI == 1)
          ? "__OBJC,__image_info,regular"
          : GetSectionName("__objc_imageinfo", "regular,no_dead_strip");

  // Generate module-level named metadata to convey this information to the
  // linker and code-gen.
  llvm::Module &Mod = CGM.getModule();

  // Add the ObjC ABI version to the module flags.
  Mod.addModuleFlag(llvm::Module::Error, "Objective-C Version", ObjCABI);
  Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Version",
                    version);
  Mod.addModuleFlag(llvm::Module::Error, "Objective-C Image Info Section",
                    llvm::MDString::get(VMContext, Section));

  auto Int8Ty = llvm::Type::getInt8Ty(VMContext);
  if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
    // Non-GC overrides those files which specify GC.
    Mod.addModuleFlag(llvm::Module::Error, "Objective-C Garbage Collection",
                      llvm::ConstantInt::get(Int8Ty, 0));
  } else {
    // Add the ObjC garbage collection value.
    Mod.addModuleFlag(
        llvm::Module::Error, "Objective-C Garbage Collection",
        llvm::ConstantInt::get(Int8Ty, (uint8_t)eImageInfo_GarbageCollected));

    if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
      // Add the ObjC GC Only value.
      Mod.addModuleFlag(llvm::Module::Error, "Objective-C GC Only",
                        eImageInfo_GCOnly);

      // Require that GC be specified and set to eImageInfo_GarbageCollected.
      llvm::Metadata *Ops[2] = {
          llvm::MDString::get(VMContext, "Objective-C Garbage Collection"),
          llvm::ConstantAsMetadata::get(
              llvm::ConstantInt::get(Int8Ty, eImageInfo_GarbageCollected))};
      Mod.addModuleFlag(llvm::Module::Require, "Objective-C GC Only",
                        llvm::MDNode::get(VMContext, Ops));
    }
  }

  // Indicate whether we're compiling this to run on a simulator.
  if (CGM.getTarget().getTriple().isSimulatorEnvironment())
    Mod.addModuleFlag(llvm::Module::Error, "Objective-C Is Simulated",
                      eImageInfo_ImageIsSimulated);

  // Indicate whether we are generating class properties.
  Mod.addModuleFlag(llvm::Module::Error, "Objective-C Class Properties",
                    eImageInfo_ClassProperties);

  // Indicate whether we want enforcement of pointer signing for class_ro_t
  // pointers.
  if (CGM.getLangOpts().PointerAuthObjcClassROPointers)
    Mod.addModuleFlag(llvm::Module::Error,
                      "Objective-C Enforce ClassRO Pointer Signing",
                      eImageInfo_SignedClassRO);
  else
    Mod.addModuleFlag(llvm::Module::Error,
                      "Objective-C Enforce ClassRO Pointer Signing",
                      llvm::ConstantInt::get(Int8Ty, 0));
}

// struct objc_module {
//   unsigned long version;
//   unsigned long size;
//   const char *name;
//   Symtab symtab;
// };

// FIXME: Get from somewhere
static const int ModuleVersion = 7;

void CGObjCMac::EmitModuleInfo() {
  uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ModuleTy);
  values.addInt(ObjCTypes.LongTy, ModuleVersion);
  values.addInt(ObjCTypes.LongTy, Size);
  // This used to be the filename, now it is unused. <rdr://4327263>
  values.add(GetClassName(StringRef("")));
  values.add(EmitModuleSymbols());
  CreateMetadataVar("OBJC_MODULES", values,
                    "__OBJC,__module_info,regular,no_dead_strip",
                    CGM.getPointerAlign(), true);
}

llvm::Constant *CGObjCMac::EmitModuleSymbols() {
  unsigned NumClasses = DefinedClasses.size();
  unsigned NumCategories = DefinedCategories.size();

  // Return null if no symbols were defined.
  if (!NumClasses && !NumCategories)
    return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct();
  values.addInt(ObjCTypes.LongTy, 0);
  values.addNullPointer(ObjCTypes.SelectorPtrTy);
  values.addInt(ObjCTypes.ShortTy, NumClasses);
  values.addInt(ObjCTypes.ShortTy, NumCategories);

  // The runtime expects exactly the list of defined classes followed
  // by the list of defined categories, in a single array.
  auto array = values.beginArray(ObjCTypes.Int8PtrTy);
  for (unsigned i = 0; i < NumClasses; i++) {
    const ObjCInterfaceDecl *ID = ImplementedClasses[i];
    assert(ID);
    if (ObjCImplementationDecl *IMP = ID->getImplementation())
      // We are implementing a weak imported interface. Give it external linkage
      if (ID->isWeakImported() && !IMP->isWeakImported())
        DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);

    array.add(DefinedClasses[i]);
  }
  for (unsigned i = 0; i < NumCategories; i++)
    array.add(DefinedCategories[i]);

  array.finishAndAddTo(values);

  llvm::GlobalVariable *GV = CreateMetadataVar(
      "OBJC_SYMBOLS", values, "__OBJC,__symbols,regular,no_dead_strip",
      CGM.getPointerAlign(), true);
  return GV;
}

llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF,
                                           IdentifierInfo *II) {
  LazySymbols.insert(II);

  llvm::GlobalVariable *&Entry = ClassReferences[II];

  if (!Entry) {
    Entry =
        CreateMetadataVar("OBJC_CLASS_REFERENCES_", GetClassName(II->getName()),
                          "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
                          CGM.getPointerAlign(), true);
  }

  return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry,
                                       CGF.getPointerAlign());
}

llvm::Value *CGObjCMac::EmitClassRef(CodeGenFunction &CGF,
                                     const ObjCInterfaceDecl *ID) {
  // If the class has the objc_runtime_visible attribute, we need to
  // use the Objective-C runtime to get the class.
  if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
    return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);

  IdentifierInfo *RuntimeName =
      &CGM.getContext().Idents.get(ID->getObjCRuntimeNameAsString());
  return EmitClassRefFromId(CGF, RuntimeName);
}

llvm::Value *CGObjCMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
  IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
  return EmitClassRefFromId(CGF, II);
}

llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel) {
  return CGF.Builder.CreateLoad(EmitSelectorAddr(Sel));
}

ConstantAddress CGObjCMac::EmitSelectorAddr(Selector Sel) {
  CharUnits Align = CGM.getPointerAlign();

  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
  if (!Entry) {
    Entry = CreateMetadataVar(
        "OBJC_SELECTOR_REFERENCES_", GetMethodVarName(Sel),
        "__OBJC,__message_refs,literal_pointers,no_dead_strip", Align, true);
    Entry->setExternallyInitialized(true);
  }

  return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
}

llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) {
  llvm::GlobalVariable *&Entry = ClassNames[RuntimeName];
  if (!Entry)
    Entry = CreateCStringLiteral(RuntimeName, ObjCLabelType::ClassName);
  return getConstantGEP(VMContext, Entry, 0, 0);
}

llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) {
  return MethodDefinitions.lookup(MD);
}

/// GetIvarLayoutName - Returns a unique constant for the given
/// ivar layout bitmap.
llvm::Constant *
CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
                                   const ObjCCommonTypesHelper &ObjCTypes) {
  return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
}

void IvarLayoutBuilder::visitRecord(const RecordType *RT, CharUnits offset) {
  const RecordDecl *RD = RT->getOriginalDecl()->getDefinitionOrSelf();

  // If this is a union, remember that we had one, because it might mess
  // up the ordering of layout entries.
  if (RD->isUnion())
    IsDisordered = true;

  const ASTRecordLayout *recLayout = nullptr;
  visitAggregate(RD->field_begin(), RD->field_end(), offset,
                 [&](const FieldDecl *field) -> CharUnits {
                   if (!recLayout)
                     recLayout = &CGM.getContext().getASTRecordLayout(RD);
                   auto offsetInBits =
                       recLayout->getFieldOffset(field->getFieldIndex());
                   return CGM.getContext().toCharUnitsFromBits(offsetInBits);
                 });
}

template <class Iterator, class GetOffsetFn>
void IvarLayoutBuilder::visitAggregate(Iterator begin, Iterator end,
                                       CharUnits aggregateOffset,
                                       const GetOffsetFn &getOffset) {
  for (; begin != end; ++begin) {
    auto field = *begin;

    // Skip over bitfields.
    if (field->isBitField()) {
      continue;
    }

    // Compute the offset of the field within the aggregate.
    CharUnits fieldOffset = aggregateOffset + getOffset(field);

    visitField(field, fieldOffset);
  }
}

/// Collect layout information for the given fields into IvarsInfo.
void IvarLayoutBuilder::visitField(const FieldDecl *field,
                                   CharUnits fieldOffset) {
  QualType fieldType = field->getType();

  // Drill down into arrays.
  uint64_t numElts = 1;
  if (auto arrayType = CGM.getContext().getAsIncompleteArrayType(fieldType)) {
    numElts = 0;
    fieldType = arrayType->getElementType();
  }
  // Unlike incomplete arrays, constant arrays can be nested.
  while (auto arrayType = CGM.getContext().getAsConstantArrayType(fieldType)) {
    numElts *= arrayType->getZExtSize();
    fieldType = arrayType->getElementType();
  }

  assert(!fieldType->isArrayType() && "ivar of non-constant array type?");

  // If we ended up with a zero-sized array, we've done what we can do within
  // the limits of this layout encoding.
  if (numElts == 0)
    return;

  // Recurse if the base element type is a record type.
  if (const auto *recType = fieldType->getAsCanonical<RecordType>()) {
    size_t oldEnd = IvarsInfo.size();

    visitRecord(recType, fieldOffset);

    // If we have an array, replicate the first entry's layout information.
    auto numEltEntries = IvarsInfo.size() - oldEnd;
    if (numElts != 1 && numEltEntries != 0) {
      CharUnits eltSize = CGM.getContext().getTypeSizeInChars(recType);
      for (uint64_t eltIndex = 1; eltIndex != numElts; ++eltIndex) {
        // Copy the last numEltEntries onto the end of the array, adjusting
        // each for the element size.
        for (size_t i = 0; i != numEltEntries; ++i) {
          auto firstEntry = IvarsInfo[oldEnd + i];
          IvarsInfo.push_back(IvarInfo(firstEntry.Offset + eltIndex * eltSize,
                                       firstEntry.SizeInWords));
        }
      }
    }

    return;
  }

  // Classify the element type.
  Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), fieldType);

  // If it matches what we're looking for, add an entry.
  if ((ForStrongLayout && GCAttr == Qualifiers::Strong) ||
      (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
    assert(CGM.getContext().getTypeSizeInChars(fieldType) ==
           CGM.getPointerSize());
    IvarsInfo.push_back(IvarInfo(fieldOffset, numElts));
  }
}

/// buildBitmap - This routine does the horsework of taking the offsets of
/// strong/weak references and creating a bitmap.  The bitmap is also
/// returned in the given buffer, suitable for being passed to \c dump().
llvm::Constant *
IvarLayoutBuilder::buildBitmap(CGObjCCommonMac &CGObjC,
                               llvm::SmallVectorImpl<unsigned char> &buffer) {
  // The bitmap is a series of skip/scan instructions, aligned to word
  // boundaries.  The skip is performed first.
  const unsigned char MaxNibble = 0xF;
  const unsigned char SkipMask = 0xF0, SkipShift = 4;
  const unsigned char ScanMask = 0x0F, ScanShift = 0;

  assert(!IvarsInfo.empty() && "generating bitmap for no data");

  // Sort the ivar info on byte position in case we encounterred a
  // union nested in the ivar list.
  if (IsDisordered) {
    // This isn't a stable sort, but our algorithm should handle it fine.
    llvm::array_pod_sort(IvarsInfo.begin(), IvarsInfo.end());
  } else {
    assert(llvm::is_sorted(IvarsInfo));
  }
  assert(IvarsInfo.back().Offset < InstanceEnd);

  assert(buffer.empty());

  // Skip the next N words.
  auto skip = [&](unsigned numWords) {
    assert(numWords > 0);

    // Try to merge into the previous byte.  Since scans happen second, we
    // can't do this if it includes a scan.
    if (!buffer.empty() && !(buffer.back() & ScanMask)) {
      unsigned lastSkip = buffer.back() >> SkipShift;
      if (lastSkip < MaxNibble) {
        unsigned claimed = std::min(MaxNibble - lastSkip, numWords);
        numWords -= claimed;
        lastSkip += claimed;
        buffer.back() = (lastSkip << SkipShift);
      }
    }

    while (numWords >= MaxNibble) {
      buffer.push_back(MaxNibble << SkipShift);
      numWords -= MaxNibble;
    }
    if (numWords) {
      buffer.push_back(numWords << SkipShift);
    }
  };

  // Scan the next N words.
  auto scan = [&](unsigned numWords) {
    assert(numWords > 0);

    // Try to merge into the previous byte.  Since scans happen second, we can
    // do this even if it includes a skip.
    if (!buffer.empty()) {
      unsigned lastScan = (buffer.back() & ScanMask) >> ScanShift;
      if (lastScan < MaxNibble) {
        unsigned claimed = std::min(MaxNibble - lastScan, numWords);
        numWords -= claimed;
        lastScan += claimed;
        buffer.back() = (buffer.back() & SkipMask) | (lastScan << ScanShift);
      }
    }

    while (numWords >= MaxNibble) {
      buffer.push_back(MaxNibble << ScanShift);
      numWords -= MaxNibble;
    }
    if (numWords) {
      buffer.push_back(numWords << ScanShift);
    }
  };

  // One past the end of the last scan.
  unsigned endOfLastScanInWords = 0;
  const CharUnits WordSize = CGM.getPointerSize();

  // Consider all the scan requests.
  for (auto &request : IvarsInfo) {
    CharUnits beginOfScan = request.Offset - InstanceBegin;

    // Ignore scan requests that don't start at an even multiple of the
    // word size.  We can't encode them.
    if ((beginOfScan % WordSize) != 0)
      continue;

    // Ignore scan requests that start before the instance start.
    // This assumes that scans never span that boundary.  The boundary
    // isn't the true start of the ivars, because in the fragile-ARC case
    // it's rounded up to word alignment, but the test above should leave
    // us ignoring that possibility.
    if (beginOfScan.isNegative()) {
      assert(request.Offset + request.SizeInWords * WordSize <= InstanceBegin);
      continue;
    }

    unsigned beginOfScanInWords = beginOfScan / WordSize;
    unsigned endOfScanInWords = beginOfScanInWords + request.SizeInWords;

    // If the scan starts some number of words after the last one ended,
    // skip forward.
    if (beginOfScanInWords > endOfLastScanInWords) {
      skip(beginOfScanInWords - endOfLastScanInWords);

    // Otherwise, start scanning where the last left off.
    } else {
      beginOfScanInWords = endOfLastScanInWords;

      // If that leaves us with nothing to scan, ignore this request.
      if (beginOfScanInWords >= endOfScanInWords)
        continue;
    }

    // Scan to the end of the request.
    assert(beginOfScanInWords < endOfScanInWords);
    scan(endOfScanInWords - beginOfScanInWords);
    endOfLastScanInWords = endOfScanInWords;
  }

  if (buffer.empty())
    return llvm::ConstantPointerNull::get(CGM.Int8PtrTy);

  // For GC layouts, emit a skip to the end of the allocation so that we
  // have precise information about the entire thing.  This isn't useful
  // or necessary for the ARC-style layout strings.
  if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
    unsigned lastOffsetInWords =
        (InstanceEnd - InstanceBegin + WordSize - CharUnits::One()) / WordSize;
    if (lastOffsetInWords > endOfLastScanInWords) {
      skip(lastOffsetInWords - endOfLastScanInWords);
    }
  }

  // Null terminate the string.
  buffer.push_back(0);

  auto *Entry = CGObjC.CreateCStringLiteral(
      reinterpret_cast<char *>(buffer.data()), ObjCLabelType::ClassName);
  return getConstantGEP(CGM.getLLVMContext(), Entry, 0, 0);
}

/// BuildIvarLayout - Builds ivar layout bitmap for the class
/// implementation for the __strong or __weak case.
/// The layout map displays which words in ivar list must be skipped
/// and which must be scanned by GC (see below). String is built of bytes.
/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
/// of words to skip and right nibble is count of words to scan. So, each
/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
/// represented by a 0x00 byte which also ends the string.
/// 1. when ForStrongLayout is true, following ivars are scanned:
/// - id, Class
/// - object *
/// - __strong anything
///
/// 2. When ForStrongLayout is false, following ivars are scanned:
/// - __weak anything
///
llvm::Constant *
CGObjCCommonMac::BuildIvarLayout(const ObjCImplementationDecl *OMD,
                                 CharUnits beginOffset, CharUnits endOffset,
                                 bool ForStrongLayout, bool HasMRCWeakIvars) {
  // If this is MRC, and we're either building a strong layout or there
  // are no weak ivars, bail out early.
  llvm::Type *PtrTy = CGM.Int8PtrTy;
  if (CGM.getLangOpts().getGC() == LangOptions::NonGC &&
      !CGM.getLangOpts().ObjCAutoRefCount &&
      (ForStrongLayout || !HasMRCWeakIvars))
    return llvm::Constant::getNullValue(PtrTy);

  const ObjCInterfaceDecl *OI = OMD->getClassInterface();
  SmallVector<const ObjCIvarDecl *, 32> ivars;

  // GC layout strings include the complete object layout, possibly
  // inaccurately in the non-fragile ABI; the runtime knows how to fix this
  // up.
  //
  // ARC layout strings only include the class's ivars.  In non-fragile
  // runtimes, that means starting at InstanceStart, rounded up to word
  // alignment.  In fragile runtimes, there's no InstanceStart, so it means
  // starting at the offset of the first ivar, rounded up to word alignment.
  //
  // MRC weak layout strings follow the ARC style.
  CharUnits baseOffset;
  if (CGM.getLangOpts().getGC() == LangOptions::NonGC) {
    for (const ObjCIvarDecl *IVD = OI->all_declared_ivar_begin(); IVD;
         IVD = IVD->getNextIvar())
      ivars.push_back(IVD);

    if (isNonFragileABI()) {
      baseOffset = beginOffset; // InstanceStart
    } else if (!ivars.empty()) {
      baseOffset =
          CharUnits::fromQuantity(ComputeIvarBaseOffset(CGM, OMD, ivars[0]));
    } else {
      baseOffset = CharUnits::Zero();
    }

    baseOffset = baseOffset.alignTo(CGM.getPointerAlign());
  } else {
    CGM.getContext().DeepCollectObjCIvars(OI, true, ivars);

    baseOffset = CharUnits::Zero();
  }

  if (ivars.empty())
    return llvm::Constant::getNullValue(PtrTy);

  IvarLayoutBuilder builder(CGM, baseOffset, endOffset, ForStrongLayout);

  builder.visitAggregate(ivars.begin(), ivars.end(), CharUnits::Zero(),
                         [&](const ObjCIvarDecl *ivar) -> CharUnits {
                           return CharUnits::fromQuantity(
                               ComputeIvarBaseOffset(CGM, OMD, ivar));
                         });

  if (!builder.hasBitmapData())
    return llvm::Constant::getNullValue(PtrTy);

  llvm::SmallVector<unsigned char, 4> buffer;
  llvm::Constant *C = builder.buildBitmap(*this, buffer);

  if (CGM.getLangOpts().ObjCGCBitmapPrint && !buffer.empty()) {
    printf("\n%s ivar layout for class '%s': ",
           ForStrongLayout ? "strong" : "weak",
           OMD->getClassInterface()->getName().str().c_str());
    builder.dump(buffer);
  }
  return C;
}

llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
  llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
  // FIXME: Avoid std::string in "Sel.getAsString()"
  if (!Entry)
    Entry =
        CreateCStringLiteral(Sel.getAsString(), ObjCLabelType::MethodVarName);
  return getConstantGEP(VMContext, Entry, 0, 0);
}

// FIXME: Merge into a single cstring creation function.
llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
  return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
}

llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
  std::string TypeStr;
  CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);

  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
  if (!Entry)
    Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
  return getConstantGEP(VMContext, Entry, 0, 0);
}

llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D,
                                                  bool Extended) {
  std::string TypeStr =
      CGM.getContext().getObjCEncodingForMethodDecl(D, Extended);

  llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
  if (!Entry)
    Entry = CreateCStringLiteral(TypeStr, ObjCLabelType::MethodVarType);
  return getConstantGEP(VMContext, Entry, 0, 0);
}

// FIXME: Merge into a single cstring creation function.
llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
  llvm::GlobalVariable *&Entry = PropertyNames[Ident];
  if (!Entry)
    Entry = CreateCStringLiteral(Ident->getName(), ObjCLabelType::PropertyName);
  return getConstantGEP(VMContext, Entry, 0, 0);
}

// FIXME: Merge into a single cstring creation function.
// FIXME: This Decl should be more precise.
llvm::Constant *
CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
                                       const Decl *Container) {
  std::string TypeStr =
      CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
  return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
}

void CGObjCMac::FinishModule() {
  EmitModuleInfo();

  // Emit the dummy bodies for any protocols which were referenced but
  // never defined.
  for (auto &entry : Protocols) {
    llvm::GlobalVariable *global = entry.second;
    if (global->hasInitializer())
      continue;

    ConstantInitBuilder builder(CGM);
    auto values = builder.beginStruct(ObjCTypes.ProtocolTy);
    values.addNullPointer(ObjCTypes.ProtocolExtensionPtrTy);
    values.add(GetClassName(entry.first->getName()));
    values.addNullPointer(ObjCTypes.ProtocolListPtrTy);
    values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
    values.addNullPointer(ObjCTypes.MethodDescriptionListPtrTy);
    values.finishAndSetAsInitializer(global);
    CGM.addCompilerUsedGlobal(global);
  }

  // Add assembler directives to add lazy undefined symbol references
  // for classes which are referenced but not defined. This is
  // important for correct linker interaction.
  //
  // FIXME: It would be nice if we had an LLVM construct for this.
  if ((!LazySymbols.empty() || !DefinedSymbols.empty()) &&
      CGM.getTriple().isOSBinFormatMachO()) {
    SmallString<256> Asm;
    Asm += CGM.getModule().getModuleInlineAsm();
    if (!Asm.empty() && Asm.back() != '\n')
      Asm += '\n';

    llvm::raw_svector_ostream OS(Asm);
    for (const auto *Sym : DefinedSymbols)
      OS << "\t.objc_class_name_" << Sym->getName() << "=0\n"
         << "\t.globl .objc_class_name_" << Sym->getName() << "\n";
    for (const auto *Sym : LazySymbols)
      OS << "\t.lazy_reference .objc_class_name_" << Sym->getName() << "\n";
    for (const auto &Category : DefinedCategoryNames)
      OS << "\t.objc_category_name_" << Category << "=0\n"
         << "\t.globl .objc_category_name_" << Category << "\n";

    CGM.getModule().setModuleInlineAsm(OS.str());
  }
}

CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
    : CGObjCCommonMac(cgm), ObjCTypes(cgm), ObjCEmptyCacheVar(nullptr),
      ObjCEmptyVtableVar(nullptr) {
  ObjCABI = 2;
}

/* *** */

ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
    : VMContext(cgm.getLLVMContext()), CGM(cgm) {
  CodeGen::CodeGenTypes &Types = CGM.getTypes();
  ASTContext &Ctx = CGM.getContext();
  unsigned ProgramAS = CGM.getDataLayout().getProgramAddressSpace();

  ShortTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.ShortTy));
  IntTy = CGM.IntTy;
  LongTy = cast<llvm::IntegerType>(Types.ConvertType(Ctx.LongTy));
  Int8PtrTy = CGM.Int8PtrTy;
  Int8PtrProgramASTy = llvm::PointerType::get(CGM.getLLVMContext(), ProgramAS);
  Int8PtrPtrTy = CGM.Int8PtrPtrTy;

  // arm64 targets use "int" ivar offset variables. All others,
  // including OS X x86_64 and Windows x86_64, use "long" ivar offsets.
  if (CGM.getTarget().getTriple().getArch() == llvm::Triple::aarch64)
    IvarOffsetVarTy = IntTy;
  else
    IvarOffsetVarTy = LongTy;

  ObjectPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCIdType()));
  PtrObjectPtrTy = llvm::PointerType::getUnqual(VMContext);
  SelectorPtrTy =
      cast<llvm::PointerType>(Types.ConvertType(Ctx.getObjCSelType()));

  // I'm not sure I like this. The implicit coordination is a bit
  // gross. We should solve this in a reasonable fashion because this
  // is a pretty common task (match some runtime data structure with
  // an LLVM data structure).

  // FIXME: This is leaked.
  // FIXME: Merge with rewriter code?

  // struct _objc_super {
  //   id self;
  //   Class cls;
  // }
  RecordDecl *RD = RecordDecl::Create(
      Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
      SourceLocation(), &Ctx.Idents.get("_objc_super"));
  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
                                nullptr, Ctx.getObjCIdType(), nullptr, nullptr,
                                false, ICIS_NoInit));
  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
                                nullptr, Ctx.getObjCClassType(), nullptr,
                                nullptr, false, ICIS_NoInit));
  RD->completeDefinition();

  SuperCTy = Ctx.getCanonicalTagType(RD);
  SuperPtrCTy = Ctx.getPointerType(SuperCTy);

  SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
  SuperPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _prop_t {
  //   char *name;
  //   char *attributes;
  // }
  PropertyTy = llvm::StructType::create("struct._prop_t", Int8PtrTy, Int8PtrTy);

  // struct _prop_list_t {
  //   uint32_t entsize;      // sizeof(struct _prop_t)
  //   uint32_t count_of_properties;
  //   struct _prop_t prop_list[count_of_properties];
  // }
  PropertyListTy = llvm::StructType::create(
      "struct._prop_list_t", IntTy, IntTy, llvm::ArrayType::get(PropertyTy, 0));
  // struct _prop_list_t *
  PropertyListPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _objc_method {
  //   SEL _cmd;
  //   char *method_type;
  //   char *_imp;
  // }
  MethodTy = llvm::StructType::create("struct._objc_method", SelectorPtrTy,
                                      Int8PtrTy, Int8PtrProgramASTy);

  // struct _objc_cache *
  CacheTy = llvm::StructType::create(VMContext, "struct._objc_cache");
  CachePtrTy = llvm::PointerType::getUnqual(VMContext);
}

ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
    : ObjCCommonTypesHelper(cgm) {
  // struct _objc_method_description {
  //   SEL name;
  //   char *types;
  // }
  MethodDescriptionTy = llvm::StructType::create(
      "struct._objc_method_description", SelectorPtrTy, Int8PtrTy);

  // struct _objc_method_description_list {
  //   int count;
  //   struct _objc_method_description[1];
  // }
  MethodDescriptionListTy =
      llvm::StructType::create("struct._objc_method_description_list", IntTy,
                               llvm::ArrayType::get(MethodDescriptionTy, 0));

  // struct _objc_method_description_list *
  MethodDescriptionListPtrTy = llvm::PointerType::getUnqual(VMContext);

  // Protocol description structures

  // struct _objc_protocol_extension {
  //   uint32_t size;  // sizeof(struct _objc_protocol_extension)
  //   struct _objc_method_description_list *optional_instance_methods;
  //   struct _objc_method_description_list *optional_class_methods;
  //   struct _objc_property_list *instance_properties;
  //   const char ** extendedMethodTypes;
  //   struct _objc_property_list *class_properties;
  // }
  ProtocolExtensionTy = llvm::StructType::create(
      "struct._objc_protocol_extension", IntTy, MethodDescriptionListPtrTy,
      MethodDescriptionListPtrTy, PropertyListPtrTy, Int8PtrPtrTy,
      PropertyListPtrTy);

  // struct _objc_protocol_extension *
  ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);

  // Handle construction of Protocol and ProtocolList types

  // struct _objc_protocol {
  //   struct _objc_protocol_extension *isa;
  //   char *protocol_name;
  //   struct _objc_protocol **_objc_protocol_list;
  //   struct _objc_method_description_list *instance_methods;
  //   struct _objc_method_description_list *class_methods;
  // }
  ProtocolTy = llvm::StructType::create(
      {ProtocolExtensionPtrTy, Int8PtrTy,
       llvm::PointerType::getUnqual(VMContext), MethodDescriptionListPtrTy,
       MethodDescriptionListPtrTy},
      "struct._objc_protocol");

  ProtocolListTy =
      llvm::StructType::create({llvm::PointerType::getUnqual(VMContext), LongTy,
                                llvm::ArrayType::get(ProtocolTy, 0)},
                               "struct._objc_protocol_list");

  // struct _objc_protocol_list *
  ProtocolListPtrTy = llvm::PointerType::getUnqual(VMContext);

  ProtocolPtrTy = llvm::PointerType::getUnqual(VMContext);

  // Class description structures

  // struct _objc_ivar {
  //   char *ivar_name;
  //   char *ivar_type;
  //   int  ivar_offset;
  // }
  IvarTy = llvm::StructType::create("struct._objc_ivar", Int8PtrTy, Int8PtrTy,
                                    IntTy);

  // struct _objc_ivar_list *
  IvarListTy = llvm::StructType::create(VMContext, "struct._objc_ivar_list");
  IvarListPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _objc_method_list *
  MethodListTy =
      llvm::StructType::create(VMContext, "struct._objc_method_list");
  MethodListPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _objc_class_extension *
  ClassExtensionTy = llvm::StructType::create(
      "struct._objc_class_extension", IntTy, Int8PtrTy, PropertyListPtrTy);
  ClassExtensionPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _objc_class {
  //   Class isa;
  //   Class super_class;
  //   char *name;
  //   long version;
  //   long info;
  //   long instance_size;
  //   struct _objc_ivar_list *ivars;
  //   struct _objc_method_list *methods;
  //   struct _objc_cache *cache;
  //   struct _objc_protocol_list *protocols;
  //   char *ivar_layout;
  //   struct _objc_class_ext *ext;
  // };
  ClassTy = llvm::StructType::create(
      {llvm::PointerType::getUnqual(VMContext),
       llvm::PointerType::getUnqual(VMContext), Int8PtrTy, LongTy, LongTy,
       LongTy, IvarListPtrTy, MethodListPtrTy, CachePtrTy, ProtocolListPtrTy,
       Int8PtrTy, ClassExtensionPtrTy},
      "struct._objc_class");

  ClassPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _objc_category {
  //   char *category_name;
  //   char *class_name;
  //   struct _objc_method_list *instance_method;
  //   struct _objc_method_list *class_method;
  //   struct _objc_protocol_list *protocols;
  //   uint32_t size;  // sizeof(struct _objc_category)
  //   struct _objc_property_list *instance_properties;// category's @property
  //   struct _objc_property_list *class_properties;
  // }
  CategoryTy = llvm::StructType::create(
      "struct._objc_category", Int8PtrTy, Int8PtrTy, MethodListPtrTy,
      MethodListPtrTy, ProtocolListPtrTy, IntTy, PropertyListPtrTy,
      PropertyListPtrTy);

  // Global metadata structures

  // struct _objc_symtab {
  //   long sel_ref_cnt;
  //   SEL *refs;
  //   short cls_def_cnt;
  //   short cat_def_cnt;
  //   char *defs[cls_def_cnt + cat_def_cnt];
  // }
  SymtabTy = llvm::StructType::create("struct._objc_symtab", LongTy,
                                      SelectorPtrTy, ShortTy, ShortTy,
                                      llvm::ArrayType::get(Int8PtrTy, 0));
  SymtabPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _objc_module {
  //   long version;
  //   long size;   // sizeof(struct _objc_module)
  //   char *name;
  //   struct _objc_symtab* symtab;
  //  }
  ModuleTy = llvm::StructType::create("struct._objc_module", LongTy, LongTy,
                                      Int8PtrTy, SymtabPtrTy);

  // FIXME: This is the size of the setjmp buffer and should be target
  // specific. 18 is what's used on 32-bit X86.
  uint64_t SetJmpBufferSize = 18;

  // Exceptions
  llvm::Type *StackPtrTy = llvm::ArrayType::get(CGM.Int8PtrTy, 4);

  ExceptionDataTy = llvm::StructType::create(
      "struct._objc_exception_data",
      llvm::ArrayType::get(CGM.Int32Ty, SetJmpBufferSize), StackPtrTy);
}

ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(
    CodeGen::CodeGenModule &cgm)
    : ObjCCommonTypesHelper(cgm) {
  // struct _method_list_t {
  //   uint32_t entsize;  // sizeof(struct _objc_method)
  //   uint32_t method_count;
  //   struct _objc_method method_list[method_count];
  // }
  MethodListnfABITy =
      llvm::StructType::create("struct.__method_list_t", IntTy, IntTy,
                               llvm::ArrayType::get(MethodTy, 0));
  // struct method_list_t *
  MethodListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _protocol_t {
  //   id isa;  // NULL
  //   const char * const protocol_name;
  //   const struct _protocol_list_t * protocol_list; // super protocols
  //   const struct method_list_t * const instance_methods;
  //   const struct method_list_t * const class_methods;
  //   const struct method_list_t *optionalInstanceMethods;
  //   const struct method_list_t *optionalClassMethods;
  //   const struct _prop_list_t * properties;
  //   const uint32_t size;  // sizeof(struct _protocol_t)
  //   const uint32_t flags;  // = 0
  //   const char ** extendedMethodTypes;
  //   const char *demangledName;
  //   const struct _prop_list_t * class_properties;
  // }

  ProtocolnfABITy = llvm::StructType::create(
      "struct._protocol_t", ObjectPtrTy, Int8PtrTy,
      llvm::PointerType::getUnqual(VMContext), MethodListnfABIPtrTy,
      MethodListnfABIPtrTy, MethodListnfABIPtrTy, MethodListnfABIPtrTy,
      PropertyListPtrTy, IntTy, IntTy, Int8PtrPtrTy, Int8PtrTy,
      PropertyListPtrTy);

  // struct _protocol_t*
  ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _protocol_list_t {
  //   long protocol_count;   // Note, this is 32/64 bit
  //   struct _protocol_t *[protocol_count];
  // }
  ProtocolListnfABITy = llvm::StructType::create(
      {LongTy, llvm::ArrayType::get(ProtocolnfABIPtrTy, 0)},
      "struct._objc_protocol_list");

  // struct _objc_protocol_list*
  ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _ivar_t {
  //   unsigned [long] int *offset;  // pointer to ivar offset location
  //   char *name;
  //   char *type;
  //   uint32_t alignment;
  //   uint32_t size;
  // }
  IvarnfABITy = llvm::StructType::create(
      "struct._ivar_t", llvm::PointerType::getUnqual(VMContext), Int8PtrTy,
      Int8PtrTy, IntTy, IntTy);

  // struct _ivar_list_t {
  //   uint32 entsize;  // sizeof(struct _ivar_t)
  //   uint32 count;
  //   struct _iver_t list[count];
  // }
  IvarListnfABITy =
      llvm::StructType::create("struct._ivar_list_t", IntTy, IntTy,
                               llvm::ArrayType::get(IvarnfABITy, 0));

  IvarListnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _class_ro_t {
  //   uint32_t const flags;
  //   uint32_t const instanceStart;
  //   uint32_t const instanceSize;
  //   uint32_t const reserved;  // only when building for 64bit targets
  //   const uint8_t * const ivarLayout;
  //   const char *const name;
  //   const struct _method_list_t * const baseMethods;
  //   const struct _objc_protocol_list *const baseProtocols;
  //   const struct _ivar_list_t *const ivars;
  //   const uint8_t * const weakIvarLayout;
  //   const struct _prop_list_t * const properties;
  // }

  // FIXME. Add 'reserved' field in 64bit abi mode!
  ClassRonfABITy = llvm::StructType::create(
      "struct._class_ro_t", IntTy, IntTy, IntTy, Int8PtrTy, Int8PtrTy,
      MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, IvarListnfABIPtrTy,
      Int8PtrTy, PropertyListPtrTy);

  // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
  ImpnfABITy = CGM.UnqualPtrTy;

  // struct _class_t {
  //   struct _class_t *isa;
  //   struct _class_t * const superclass;
  //   void *cache;
  //   IMP *vtable;
  //   struct class_ro_t *ro;
  // }

  ClassnfABITy = llvm::StructType::create(
      {llvm::PointerType::getUnqual(VMContext),
       llvm::PointerType::getUnqual(VMContext), CachePtrTy,
       llvm::PointerType::getUnqual(VMContext),
       llvm::PointerType::getUnqual(VMContext)},
      "struct._class_t");

  // LLVM for struct _class_t *
  ClassnfABIPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct _category_t {
  //   const char * const name;
  //   struct _class_t *const cls;
  //   const struct _method_list_t * const instance_methods;
  //   const struct _method_list_t * const class_methods;
  //   const struct _protocol_list_t * const protocols;
  //   const struct _prop_list_t * const properties;
  //   const struct _prop_list_t * const class_properties;
  //   const uint32_t size;
  // }
  CategorynfABITy = llvm::StructType::create(
      "struct._category_t", Int8PtrTy, ClassnfABIPtrTy, MethodListnfABIPtrTy,
      MethodListnfABIPtrTy, ProtocolListnfABIPtrTy, PropertyListPtrTy,
      PropertyListPtrTy, IntTy);

  // New types for nonfragile abi messaging.
  CodeGen::CodeGenTypes &Types = CGM.getTypes();
  ASTContext &Ctx = CGM.getContext();

  // MessageRefTy - LLVM for:
  // struct _message_ref_t {
  //   IMP messenger;
  //   SEL name;
  // };

  // First the clang type for struct _message_ref_t
  RecordDecl *RD = RecordDecl::Create(
      Ctx, TagTypeKind::Struct, Ctx.getTranslationUnitDecl(), SourceLocation(),
      SourceLocation(), &Ctx.Idents.get("_message_ref_t"));
  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
                                nullptr, Ctx.VoidPtrTy, nullptr, nullptr, false,
                                ICIS_NoInit));
  RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), SourceLocation(),
                                nullptr, Ctx.getObjCSelType(), nullptr, nullptr,
                                false, ICIS_NoInit));
  RD->completeDefinition();

  MessageRefCTy = Ctx.getCanonicalTagType(RD);
  MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
  MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));

  // MessageRefPtrTy - LLVM for struct _message_ref_t*
  MessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);

  // SuperMessageRefTy - LLVM for:
  // struct _super_message_ref_t {
  //   SUPER_IMP messenger;
  //   SEL name;
  // };
  SuperMessageRefTy = llvm::StructType::create("struct._super_message_ref_t",
                                               ImpnfABITy, SelectorPtrTy);

  // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
  SuperMessageRefPtrTy = llvm::PointerType::getUnqual(VMContext);

  // struct objc_typeinfo {
  //   const void** vtable; // objc_ehtype_vtable + 2
  //   const char*  name;    // c++ typeinfo string
  //   Class        cls;
  // };
  EHTypeTy = llvm::StructType::create("struct._objc_typeinfo",
                                      llvm::PointerType::getUnqual(VMContext),
                                      Int8PtrTy, ClassnfABIPtrTy);
  EHTypePtrTy = llvm::PointerType::getUnqual(VMContext);
}

llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
  FinishNonFragileABIModule();

  return nullptr;
}

void CGObjCNonFragileABIMac::AddModuleClassList(
    ArrayRef<llvm::GlobalValue *> Container, StringRef SymbolName,
    StringRef SectionName) {
  unsigned NumClasses = Container.size();

  if (!NumClasses)
    return;

  SmallVector<llvm::Constant *, 8> Symbols(NumClasses);
  for (unsigned i = 0; i < NumClasses; i++)
    Symbols[i] = Container[i];

  llvm::Constant *Init = llvm::ConstantArray::get(
      llvm::ArrayType::get(ObjCTypes.Int8PtrTy, Symbols.size()), Symbols);

  // Section name is obtained by calling GetSectionName, which returns
  // sections in the __DATA segment on MachO.
  assert((!CGM.getTriple().isOSBinFormatMachO() ||
          SectionName.starts_with("__DATA")) &&
         "SectionName expected to start with __DATA on MachO");
  llvm::GlobalVariable *GV = new llvm::GlobalVariable(
      CGM.getModule(), Init->getType(), false,
      llvm::GlobalValue::PrivateLinkage, Init, SymbolName);
  GV->setAlignment(CGM.getDataLayout().getABITypeAlign(Init->getType()));
  GV->setSection(SectionName);
  CGM.addCompilerUsedGlobal(GV);
}

void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
  // nonfragile abi has no module definition.

  // Build list of all implemented class addresses in array
  // L_OBJC_LABEL_CLASS_$.

  for (unsigned i = 0, NumClasses = ImplementedClasses.size(); i < NumClasses;
       i++) {
    const ObjCInterfaceDecl *ID = ImplementedClasses[i];
    assert(ID);
    if (ObjCImplementationDecl *IMP = ID->getImplementation())
      // We are implementing a weak imported interface. Give it external linkage
      if (ID->isWeakImported() && !IMP->isWeakImported()) {
        DefinedClasses[i]->setLinkage(llvm::GlobalVariable::ExternalLinkage);
        DefinedMetaClasses[i]->setLinkage(
            llvm::GlobalVariable::ExternalLinkage);
      }
  }

  AddModuleClassList(
      DefinedClasses, "OBJC_LABEL_CLASS_$",
      GetSectionName("__objc_classlist", "regular,no_dead_strip"));

  AddModuleClassList(
      DefinedNonLazyClasses, "OBJC_LABEL_NONLAZY_CLASS_$",
      GetSectionName("__objc_nlclslist", "regular,no_dead_strip"));

  // Build list of all implemented category addresses in array
  // L_OBJC_LABEL_CATEGORY_$.
  AddModuleClassList(DefinedCategories, "OBJC_LABEL_CATEGORY_$",
                     GetSectionName("__objc_catlist", "regular,no_dead_strip"));
  AddModuleClassList(
      DefinedStubCategories, "OBJC_LABEL_STUB_CATEGORY_$",
      GetSectionName("__objc_catlist2", "regular,no_dead_strip"));
  AddModuleClassList(
      DefinedNonLazyCategories, "OBJC_LABEL_NONLAZY_CATEGORY_$",
      GetSectionName("__objc_nlcatlist", "regular,no_dead_strip"));

  EmitImageInfo();
}

/// isVTableDispatchedSelector - Returns true if SEL is not in the list of
/// VTableDispatchMethods; false otherwise. What this means is that
/// except for the 19 selectors in the list, we generate 32bit-style
/// message dispatch call for all the rest.
bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) {
  // At various points we've experimented with using vtable-based
  // dispatch for all methods.
  switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
  case CodeGenOptions::Legacy:
    return false;
  case CodeGenOptions::NonLegacy:
    return true;
  case CodeGenOptions::Mixed:
    break;
  }

  // If so, see whether this selector is in the white-list of things which must
  // use the new dispatch convention. We lazily build a dense set for this.
  if (VTableDispatchMethods.empty()) {
    VTableDispatchMethods.insert(GetNullarySelector("alloc"));
    VTableDispatchMethods.insert(GetNullarySelector("class"));
    VTableDispatchMethods.insert(GetNullarySelector("self"));
    VTableDispatchMethods.insert(GetNullarySelector("isFlipped"));
    VTableDispatchMethods.insert(GetNullarySelector("length"));
    VTableDispatchMethods.insert(GetNullarySelector("count"));

    // These are vtable-based if GC is disabled.
    // Optimistically use vtable dispatch for hybrid compiles.
    if (CGM.getLangOpts().getGC() != LangOptions::GCOnly) {
      VTableDispatchMethods.insert(GetNullarySelector("retain"));
      VTableDispatchMethods.insert(GetNullarySelector("release"));
      VTableDispatchMethods.insert(GetNullarySelector("autorelease"));
    }

    VTableDispatchMethods.insert(GetUnarySelector("allocWithZone"));
    VTableDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
    VTableDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
    VTableDispatchMethods.insert(GetUnarySelector("objectForKey"));
    VTableDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
    VTableDispatchMethods.insert(GetUnarySelector("isEqualToString"));
    VTableDispatchMethods.insert(GetUnarySelector("isEqual"));

    // These are vtable-based if GC is enabled.
    // Optimistically use vtable dispatch for hybrid compiles.
    if (CGM.getLangOpts().getGC() != LangOptions::NonGC) {
      VTableDispatchMethods.insert(GetNullarySelector("hash"));
      VTableDispatchMethods.insert(GetUnarySelector("addObject"));

      // "countByEnumeratingWithState:objects:count"
      const IdentifierInfo *KeyIdents[] = {
          &CGM.getContext().Idents.get("countByEnumeratingWithState"),
          &CGM.getContext().Idents.get("objects"),
          &CGM.getContext().Idents.get("count")};
      VTableDispatchMethods.insert(
          CGM.getContext().Selectors.getSelector(3, KeyIdents));
    }
  }

  return VTableDispatchMethods.count(Sel);
}

/// BuildClassRoTInitializer - generate meta-data for:
/// struct _class_ro_t {
///   uint32_t const flags;
///   uint32_t const instanceStart;
///   uint32_t const instanceSize;
///   uint32_t const reserved;  // only when building for 64bit targets
///   const uint8_t * const ivarLayout;
///   const char *const name;
///   const struct _method_list_t * const baseMethods;
///   const struct _protocol_list_t *const baseProtocols;
///   const struct _ivar_list_t *const ivars;
///   const uint8_t * const weakIvarLayout;
///   const struct _prop_list_t * const properties;
/// }
///
llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassRoTInitializer(
    unsigned flags, unsigned InstanceStart, unsigned InstanceSize,
    const ObjCImplementationDecl *ID) {
  std::string ClassName = std::string(ID->getObjCRuntimeNameAsString());

  CharUnits beginInstance = CharUnits::fromQuantity(InstanceStart);
  CharUnits endInstance = CharUnits::fromQuantity(InstanceSize);

  bool hasMRCWeak = false;
  if (CGM.getLangOpts().ObjCAutoRefCount)
    flags |= NonFragileABI_Class_CompiledByARC;
  else if ((hasMRCWeak = hasMRCWeakIvars(CGM, ID)))
    flags |= NonFragileABI_Class_HasMRCWeakIvars;

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ClassRonfABITy);

  values.addInt(ObjCTypes.IntTy, flags);
  values.addInt(ObjCTypes.IntTy, InstanceStart);
  values.addInt(ObjCTypes.IntTy, InstanceSize);
  values.add((flags & NonFragileABI_Class_Meta)
                 ? GetIvarLayoutName(nullptr, ObjCTypes)
                 : BuildStrongIvarLayout(ID, beginInstance, endInstance));
  values.add(GetClassName(ID->getObjCRuntimeNameAsString()));

  // const struct _method_list_t * const baseMethods;
  SmallVector<const ObjCMethodDecl *, 16> methods;
  if (flags & NonFragileABI_Class_Meta) {
    for (const auto *MD : ID->class_methods())
      if (!MD->isDirectMethod())
        methods.push_back(MD);
  } else {
    for (const auto *MD : ID->instance_methods())
      if (!MD->isDirectMethod())
        methods.push_back(MD);
  }

  llvm::Constant *MethListPtr = emitMethodList(
      ID->getObjCRuntimeNameAsString(),
      (flags & NonFragileABI_Class_Meta) ? MethodListType::ClassMethods
                                         : MethodListType::InstanceMethods,
      methods);

  const PointerAuthSchema &MethListSchema =
      CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
  if (!MethListPtr->isNullValue())
    values.addSignedPointer(MethListPtr, MethListSchema, GlobalDecl(),
                            QualType());
  else
    values.add(MethListPtr);

  const ObjCInterfaceDecl *OID = ID->getClassInterface();
  assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
  values.add(EmitProtocolList("_OBJC_CLASS_PROTOCOLS_$_" +
                                  OID->getObjCRuntimeNameAsString(),
                              OID->all_referenced_protocol_begin(),
                              OID->all_referenced_protocol_end()));

  if (flags & NonFragileABI_Class_Meta) {
    values.addNullPointer(ObjCTypes.IvarListnfABIPtrTy);
    values.add(GetIvarLayoutName(nullptr, ObjCTypes));
    values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" +
                                    ID->getObjCRuntimeNameAsString(),
                                ID, ID->getClassInterface(), ObjCTypes, true));
  } else {
    values.add(EmitIvarList(ID));
    values.add(BuildWeakIvarLayout(ID, beginInstance, endInstance, hasMRCWeak));
    values.add(EmitPropertyList("_OBJC_$_PROP_LIST_" +
                                    ID->getObjCRuntimeNameAsString(),
                                ID, ID->getClassInterface(), ObjCTypes, false));
  }

  llvm::SmallString<64> roLabel;
  llvm::raw_svector_ostream(roLabel)
      << ((flags & NonFragileABI_Class_Meta) ? "_OBJC_METACLASS_RO_$_"
                                             : "_OBJC_CLASS_RO_$_")
      << ClassName;

  return finishAndCreateGlobal(values, roLabel, CGM);
}

/// Build the metaclass object for a class.
///
/// struct _class_t {
///   struct _class_t *isa;
///   struct _class_t * const superclass;
///   void *cache;
///   IMP *vtable;
///   struct class_ro_t *ro;
/// }
///
llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassObject(
    const ObjCInterfaceDecl *CI, bool isMetaclass, llvm::Constant *IsAGV,
    llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV,
    bool HiddenVisibility) {
  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ClassnfABITy);
  const PointerAuthOptions &PointerAuthOpts = CGM.getCodeGenOpts().PointerAuth;
  values.addSignedPointer(IsAGV, PointerAuthOpts.ObjCIsaPointers, GlobalDecl(),
                          QualType());
  if (SuperClassGV)
    values.addSignedPointer(SuperClassGV, PointerAuthOpts.ObjCSuperPointers,
                            GlobalDecl(), QualType());
  else
    values.addNullPointer(ObjCTypes.ClassnfABIPtrTy);

  values.add(ObjCEmptyCacheVar);
  values.add(ObjCEmptyVtableVar);

  values.addSignedPointer(ClassRoGV, PointerAuthOpts.ObjCClassROPointers,
                          GlobalDecl(), QualType());

  llvm::GlobalVariable *GV = cast<llvm::GlobalVariable>(
      GetClassGlobal(CI, isMetaclass, ForDefinition));
  values.finishAndSetAsInitializer(GV);

  if (CGM.getTriple().isOSBinFormatMachO())
    GV->setSection("__DATA, __objc_data");
  GV->setAlignment(CGM.getDataLayout().getABITypeAlign(ObjCTypes.ClassnfABITy));
  if (!CGM.getTriple().isOSBinFormatCOFF())
    if (HiddenVisibility)
      GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
  return GV;
}

bool CGObjCNonFragileABIMac::ImplementationIsNonLazy(
    const ObjCImplDecl *OD) const {
  return OD->getClassMethod(GetNullarySelector("load")) != nullptr ||
         OD->getClassInterface()->hasAttr<ObjCNonLazyClassAttr>() ||
         OD->hasAttr<ObjCNonLazyClassAttr>();
}

void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
                                              uint32_t &InstanceStart,
                                              uint32_t &InstanceSize) {
  const ASTRecordLayout &RL =
      CGM.getContext().getASTObjCInterfaceLayout(OID->getClassInterface());

  // InstanceSize is really instance end.
  InstanceSize = RL.getDataSize().getQuantity();

  // If there are no fields, the start is the same as the end.
  if (!RL.getFieldCount())
    InstanceStart = InstanceSize;
  else
    InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth();
}

static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM,
                                                          StringRef Name) {
  IdentifierInfo &II = CGM.getContext().Idents.get(Name);
  TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
  DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);

  const VarDecl *VD = nullptr;
  for (const auto *Result : DC->lookup(&II))
    if ((VD = dyn_cast<VarDecl>(Result)))
      break;

  if (!VD)
    return llvm::GlobalValue::DLLImportStorageClass;
  if (VD->hasAttr<DLLExportAttr>())
    return llvm::GlobalValue::DLLExportStorageClass;
  if (VD->hasAttr<DLLImportAttr>())
    return llvm::GlobalValue::DLLImportStorageClass;
  return llvm::GlobalValue::DefaultStorageClass;
}

void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
  if (!ObjCEmptyCacheVar) {
    ObjCEmptyCacheVar = new llvm::GlobalVariable(
        CGM.getModule(), ObjCTypes.CacheTy, false,
        llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_cache");
    if (CGM.getTriple().isOSBinFormatCOFF())
      ObjCEmptyCacheVar->setDLLStorageClass(
          getStorage(CGM, "_objc_empty_cache"));

    // Only OS X with deployment version <10.9 use the empty vtable symbol
    const llvm::Triple &Triple = CGM.getTarget().getTriple();
    if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9))
      ObjCEmptyVtableVar = new llvm::GlobalVariable(
          CGM.getModule(), ObjCTypes.ImpnfABITy, false,
          llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable");
    else
      ObjCEmptyVtableVar = llvm::ConstantPointerNull::get(CGM.UnqualPtrTy);
  }

  // FIXME: Is this correct (that meta class size is never computed)?
  uint32_t InstanceStart =
      CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy);
  uint32_t InstanceSize = InstanceStart;
  uint32_t flags = NonFragileABI_Class_Meta;

  llvm::Constant *SuperClassGV, *IsAGV;

  const auto *CI = ID->getClassInterface();
  assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0");

  // Build the flags for the metaclass.
  bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF())
                           ? !CI->hasAttr<DLLExportAttr>()
                           : CI->getVisibility() == HiddenVisibility;
  if (classIsHidden)
    flags |= NonFragileABI_Class_Hidden;

  // FIXME: why is this flag set on the metaclass?
  // ObjC metaclasses have no fields and don't really get constructed.
  if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
    flags |= NonFragileABI_Class_HasCXXStructors;
    if (!ID->hasNonZeroConstructors())
      flags |= NonFragileABI_Class_HasCXXDestructorOnly;
  }

  if (!CI->getSuperClass()) {
    // class is root
    flags |= NonFragileABI_Class_Root;

    SuperClassGV = GetClassGlobal(CI, /*metaclass*/ false, NotForDefinition);
    IsAGV = GetClassGlobal(CI, /*metaclass*/ true, NotForDefinition);
  } else {
    // Has a root. Current class is not a root.
    const ObjCInterfaceDecl *Root = ID->getClassInterface();
    while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
      Root = Super;

    const auto *Super = CI->getSuperClass();
    IsAGV = GetClassGlobal(Root, /*metaclass*/ true, NotForDefinition);
    SuperClassGV = GetClassGlobal(Super, /*metaclass*/ true, NotForDefinition);
  }

  llvm::GlobalVariable *CLASS_RO_GV =
      BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);

  llvm::GlobalVariable *MetaTClass = BuildClassObject(
      CI, /*metaclass*/ true, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden);
  CGM.setGVProperties(MetaTClass, CI);
  DefinedMetaClasses.push_back(MetaTClass);

  // Metadata for the class
  flags = 0;
  if (classIsHidden)
    flags |= NonFragileABI_Class_Hidden;

  if (ID->hasNonZeroConstructors() || ID->hasDestructors()) {
    flags |= NonFragileABI_Class_HasCXXStructors;

    // Set a flag to enable a runtime optimization when a class has
    // fields that require destruction but which don't require
    // anything except zero-initialization during construction.  This
    // is most notably true of __strong and __weak types, but you can
    // also imagine there being C++ types with non-trivial default
    // constructors that merely set all fields to null.
    if (!ID->hasNonZeroConstructors())
      flags |= NonFragileABI_Class_HasCXXDestructorOnly;
  }

  if (hasObjCExceptionAttribute(CGM.getContext(), CI))
    flags |= NonFragileABI_Class_Exception;

  if (!CI->getSuperClass()) {
    flags |= NonFragileABI_Class_Root;
    SuperClassGV = nullptr;
  } else {
    // Has a root. Current class is not a root.
    const auto *Super = CI->getSuperClass();
    SuperClassGV = GetClassGlobal(Super, /*metaclass*/ false, NotForDefinition);
  }

  GetClassSizeInfo(ID, InstanceStart, InstanceSize);
  CLASS_RO_GV =
      BuildClassRoTInitializer(flags, InstanceStart, InstanceSize, ID);

  llvm::GlobalVariable *ClassMD =
      BuildClassObject(CI, /*metaclass*/ false, MetaTClass, SuperClassGV,
                       CLASS_RO_GV, classIsHidden);
  CGM.setGVProperties(ClassMD, CI);
  DefinedClasses.push_back(ClassMD);
  ImplementedClasses.push_back(CI);

  // Determine if this class is also "non-lazy".
  if (ImplementationIsNonLazy(ID))
    DefinedNonLazyClasses.push_back(ClassMD);

  // Force the definition of the EHType if necessary.
  if (flags & NonFragileABI_Class_Exception)
    (void)GetInterfaceEHType(CI, ForDefinition);
  // Make sure method definition entries are all clear for next implementation.
  MethodDefinitions.clear();
}

/// GenerateProtocolRef - This routine is called to generate code for
/// a protocol reference expression; as in:
/// @code
///   @protocol(Proto1);
/// @endcode
/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
/// which will hold address of the protocol meta-data.
///
llvm::Value *
CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF,
                                            const ObjCProtocolDecl *PD) {

  // This routine is called for @protocol only. So, we must build definition
  // of protocol's meta-data (not a reference to it!)
  assert(!PD->isNonRuntimeProtocol() &&
         "attempting to get a protocol ref to a static protocol.");
  llvm::Constant *Init = GetOrEmitProtocol(PD);

  std::string ProtocolName("_OBJC_PROTOCOL_REFERENCE_$_");
  ProtocolName += PD->getObjCRuntimeNameAsString();

  CharUnits Align = CGF.getPointerAlign();

  llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
  if (PTGV)
    return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
  PTGV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
                                  llvm::GlobalValue::WeakAnyLinkage, Init,
                                  ProtocolName);
  PTGV->setSection(
      GetSectionName("__objc_protorefs", "coalesced,no_dead_strip"));
  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
  PTGV->setAlignment(Align.getAsAlign());
  if (!CGM.getTriple().isOSBinFormatMachO())
    PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolName));
  CGM.addUsedGlobal(PTGV);
  return CGF.Builder.CreateAlignedLoad(PTGV->getValueType(), PTGV, Align);
}

/// GenerateCategory - Build metadata for a category implementation.
/// struct _category_t {
///   const char * const name;
///   struct _class_t *const cls;
///   const struct _method_list_t * const instance_methods;
///   const struct _method_list_t * const class_methods;
///   const struct _protocol_list_t * const protocols;
///   const struct _prop_list_t * const properties;
///   const struct _prop_list_t * const class_properties;
///   const uint32_t size;
/// }
///
void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
  const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
  const char *Prefix = "_OBJC_$_CATEGORY_";

  llvm::SmallString<64> ExtCatName(Prefix);
  ExtCatName += Interface->getObjCRuntimeNameAsString();
  ExtCatName += "_$_";
  ExtCatName += OCD->getNameAsString();

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.CategorynfABITy);
  values.add(GetClassName(OCD->getIdentifier()->getName()));
  // meta-class entry symbol
  values.add(GetClassGlobal(Interface, /*metaclass*/ false, NotForDefinition));
  std::string listName =
      (Interface->getObjCRuntimeNameAsString() + "_$_" + OCD->getName()).str();

  SmallVector<const ObjCMethodDecl *, 16> instanceMethods;
  SmallVector<const ObjCMethodDecl *, 8> classMethods;
  for (const auto *MD : OCD->methods()) {
    if (MD->isDirectMethod())
      continue;
    if (MD->isInstanceMethod()) {
      instanceMethods.push_back(MD);
    } else {
      classMethods.push_back(MD);
    }
  }

  llvm::Constant *InstanceMethodList = emitMethodList(
      listName, MethodListType::CategoryInstanceMethods, instanceMethods);
  const PointerAuthSchema &MethListSchema =
      CGM.getCodeGenOpts().PointerAuth.ObjCMethodListPointer;
  if (!InstanceMethodList->isNullValue())
    values.addSignedPointer(InstanceMethodList, MethListSchema, GlobalDecl(),
                            QualType());
  else
    values.add(InstanceMethodList);

  llvm::Constant *ClassMethodList = emitMethodList(
      listName, MethodListType::CategoryClassMethods, classMethods);
  if (!ClassMethodList->isNullValue())
    values.addSignedPointer(ClassMethodList, MethListSchema, GlobalDecl(),
                            QualType());
  else
    values.add(ClassMethodList);

  // Keep track of whether we have actual metadata to emit.
  bool isEmptyCategory =
      InstanceMethodList->isNullValue() && ClassMethodList->isNullValue();

  const ObjCCategoryDecl *Category =
      Interface->FindCategoryDeclaration(OCD->getIdentifier());
  if (Category) {
    SmallString<256> ExtName;
    llvm::raw_svector_ostream(ExtName)
        << Interface->getObjCRuntimeNameAsString() << "_$_" << OCD->getName();
    auto protocolList =
        EmitProtocolList("_OBJC_CATEGORY_PROTOCOLS_$_" +
                             Interface->getObjCRuntimeNameAsString() + "_$_" +
                             Category->getName(),
                         Category->protocol_begin(), Category->protocol_end());
    auto propertyList = EmitPropertyList("_OBJC_$_PROP_LIST_" + ExtName.str(),
                                         OCD, Category, ObjCTypes, false);
    auto classPropertyList =
        EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" + ExtName.str(), OCD,
                         Category, ObjCTypes, true);
    values.add(protocolList);
    values.add(propertyList);
    values.add(classPropertyList);
    isEmptyCategory &= protocolList->isNullValue() &&
                       propertyList->isNullValue() &&
                       classPropertyList->isNullValue();
  } else {
    values.addNullPointer(ObjCTypes.ProtocolListnfABIPtrTy);
    values.addNullPointer(ObjCTypes.PropertyListPtrTy);
    values.addNullPointer(ObjCTypes.PropertyListPtrTy);
  }

  if (isEmptyCategory) {
    // Empty category, don't emit any metadata.
    values.abandon();
    MethodDefinitions.clear();
    return;
  }

  unsigned Size =
      CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategorynfABITy);
  values.addInt(ObjCTypes.IntTy, Size);

  llvm::GlobalVariable *GCATV =
      finishAndCreateGlobal(values, ExtCatName.str(), CGM);
  CGM.addCompilerUsedGlobal(GCATV);
  if (Interface->hasAttr<ObjCClassStubAttr>())
    DefinedStubCategories.push_back(GCATV);
  else
    DefinedCategories.push_back(GCATV);

  // Determine if this category is also "non-lazy".
  if (ImplementationIsNonLazy(OCD))
    DefinedNonLazyCategories.push_back(GCATV);
  // method definition entries must be clear for next implementation.
  MethodDefinitions.clear();
}

/// emitMethodConstant - Return a struct objc_method constant.  If
/// forProtocol is true, the implementation will be null; otherwise,
/// the method must have a definition registered with the runtime.
///
/// struct _objc_method {
///   SEL _cmd;
///   char *method_type;
///   char *_imp;
/// }
void CGObjCNonFragileABIMac::emitMethodConstant(ConstantArrayBuilder &builder,
                                                const ObjCMethodDecl *MD,
                                                bool forProtocol) {
  auto method = builder.beginStruct(ObjCTypes.MethodTy);
  method.add(GetMethodVarName(MD->getSelector()));
  method.add(GetMethodVarType(MD));

  if (forProtocol) {
    // Protocol methods have no implementation. So, this entry is always NULL.
    method.addNullPointer(ObjCTypes.Int8PtrProgramASTy);
  } else {
    llvm::Function *fn = GetMethodDefinition(MD);
    assert(fn && "no definition for method?");
    if (const PointerAuthSchema &Schema =
            CGM.getCodeGenOpts().PointerAuth.ObjCMethodListFunctionPointers) {
      llvm::Constant *Bitcast =
          llvm::ConstantExpr::getBitCast(fn, ObjCTypes.Int8PtrProgramASTy);
      method.addSignedPointer(Bitcast, Schema, GlobalDecl(), QualType());
    } else
      method.add(fn);
  }

  method.finishAndAddTo(builder);
}

/// Build meta-data for method declarations.
///
/// struct _method_list_t {
///   uint32_t entsize;  // sizeof(struct _objc_method)
///   uint32_t method_count;
///   struct _objc_method method_list[method_count];
/// }
///
llvm::Constant *CGObjCNonFragileABIMac::emitMethodList(
    Twine name, MethodListType kind, ArrayRef<const ObjCMethodDecl *> methods) {
  // Return null for empty list.
  if (methods.empty())
    return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);

  StringRef prefix;
  bool forProtocol;
  switch (kind) {
  case MethodListType::CategoryInstanceMethods:
    prefix = "_OBJC_$_CATEGORY_INSTANCE_METHODS_";
    forProtocol = false;
    break;
  case MethodListType::CategoryClassMethods:
    prefix = "_OBJC_$_CATEGORY_CLASS_METHODS_";
    forProtocol = false;
    break;
  case MethodListType::InstanceMethods:
    prefix = "_OBJC_$_INSTANCE_METHODS_";
    forProtocol = false;
    break;
  case MethodListType::ClassMethods:
    prefix = "_OBJC_$_CLASS_METHODS_";
    forProtocol = false;
    break;

  case MethodListType::ProtocolInstanceMethods:
    prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_";
    forProtocol = true;
    break;
  case MethodListType::ProtocolClassMethods:
    prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_";
    forProtocol = true;
    break;
  case MethodListType::OptionalProtocolInstanceMethods:
    prefix = "_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_";
    forProtocol = true;
    break;
  case MethodListType::OptionalProtocolClassMethods:
    prefix = "_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_";
    forProtocol = true;
    break;
  }

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct();

  // sizeof(struct _objc_method)
  unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy);
  values.addInt(ObjCTypes.IntTy, Size);
  // method_count
  values.addInt(ObjCTypes.IntTy, methods.size());
  auto methodArray = values.beginArray(ObjCTypes.MethodTy);
  for (auto MD : methods)
    emitMethodConstant(methodArray, MD, forProtocol);
  methodArray.finishAndAddTo(values);

  llvm::GlobalVariable *GV = finishAndCreateGlobal(values, prefix + name, CGM);
  CGM.addCompilerUsedGlobal(GV);
  return GV;
}

/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
/// the given ivar.
llvm::GlobalVariable *
CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
                                               const ObjCIvarDecl *Ivar) {
  const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
  llvm::SmallString<64> Name("OBJC_IVAR_$_");
  Name += Container->getObjCRuntimeNameAsString();
  Name += ".";
  Name += Ivar->getName();
  llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name);
  if (!IvarOffsetGV) {
    IvarOffsetGV = new llvm::GlobalVariable(
        CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false,
        llvm::GlobalValue::ExternalLinkage, nullptr, Name.str());
    if (CGM.getTriple().isOSBinFormatCOFF()) {
      bool IsPrivateOrPackage =
          Ivar->getAccessControl() == ObjCIvarDecl::Private ||
          Ivar->getAccessControl() == ObjCIvarDecl::Package;

      const ObjCInterfaceDecl *ContainingID = Ivar->getContainingInterface();

      if (ContainingID->hasAttr<DLLImportAttr>())
        IvarOffsetGV->setDLLStorageClass(
            llvm::GlobalValue::DLLImportStorageClass);
      else if (ContainingID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage)
        IvarOffsetGV->setDLLStorageClass(
            llvm::GlobalValue::DLLExportStorageClass);
    }
  }
  return IvarOffsetGV;
}

llvm::Constant *
CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
                                          const ObjCIvarDecl *Ivar,
                                          unsigned long int Offset) {
  llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
  IvarOffsetGV->setInitializer(
      llvm::ConstantInt::get(ObjCTypes.IvarOffsetVarTy, Offset));
  IvarOffsetGV->setAlignment(
      CGM.getDataLayout().getABITypeAlign(ObjCTypes.IvarOffsetVarTy));

  if (!CGM.getTriple().isOSBinFormatCOFF()) {
    // FIXME: This matches gcc, but shouldn't the visibility be set on the use
    // as well (i.e., in ObjCIvarOffsetVariable).
    if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
        Ivar->getAccessControl() == ObjCIvarDecl::Package ||
        ID->getVisibility() == HiddenVisibility)
      IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
    else
      IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
  }

  // If ID's layout is known, then make the global constant. This serves as a
  // useful assertion: we'll never use this variable to calculate ivar offsets,
  // so if the runtime tries to patch it then we should crash.
  if (isClassLayoutKnownStatically(ID))
    IvarOffsetGV->setConstant(true);

  if (CGM.getTriple().isOSBinFormatMachO())
    IvarOffsetGV->setSection("__DATA, __objc_ivar");
  return IvarOffsetGV;
}

/// EmitIvarList - Emit the ivar list for the given
/// implementation. The return value has type
/// IvarListnfABIPtrTy.
///  struct _ivar_t {
///   unsigned [long] int *offset;  // pointer to ivar offset location
///   char *name;
///   char *type;
///   uint32_t alignment;
///   uint32_t size;
/// }
/// struct _ivar_list_t {
///   uint32 entsize;  // sizeof(struct _ivar_t)
///   uint32 count;
///   struct _iver_t list[count];
/// }
///

llvm::Constant *
CGObjCNonFragileABIMac::EmitIvarList(const ObjCImplementationDecl *ID) {

  ConstantInitBuilder builder(CGM);
  auto ivarList = builder.beginStruct();
  ivarList.addInt(ObjCTypes.IntTy,
                  CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy));
  auto ivarCountSlot = ivarList.addPlaceholder();
  auto ivars = ivarList.beginArray(ObjCTypes.IvarnfABITy);

  const ObjCInterfaceDecl *OID = ID->getClassInterface();
  assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");

  // FIXME. Consolidate this with similar code in GenerateClass.

  for (const ObjCIvarDecl *IVD = OID->all_declared_ivar_begin(); IVD;
       IVD = IVD->getNextIvar()) {
    // Ignore unnamed bit-fields.
    if (!IVD->getDeclName())
      continue;

    auto ivar = ivars.beginStruct(ObjCTypes.IvarnfABITy);
    ivar.add(EmitIvarOffsetVar(ID->getClassInterface(), IVD,
                               ComputeIvarBaseOffset(CGM, ID, IVD)));
    ivar.add(GetMethodVarName(IVD->getIdentifier()));
    ivar.add(GetMethodVarType(IVD));
    llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(IVD->getType());
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy);
    unsigned Align =
        CGM.getContext().getPreferredTypeAlign(IVD->getType().getTypePtr()) >>
        3;
    Align = llvm::Log2_32(Align);
    ivar.addInt(ObjCTypes.IntTy, Align);
    // NOTE. Size of a bitfield does not match gcc's, because of the
    // way bitfields are treated special in each. But I am told that
    // 'size' for bitfield ivars is ignored by the runtime so it does
    // not matter.  If it matters, there is enough info to get the
    // bitfield right!
    ivar.addInt(ObjCTypes.IntTy, Size);
    ivar.finishAndAddTo(ivars);
  }
  // Return null for empty list.
  if (ivars.empty()) {
    ivars.abandon();
    ivarList.abandon();
    return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
  }

  auto ivarCount = ivars.size();
  ivars.finishAndAddTo(ivarList);
  ivarList.fillPlaceholderWithInt(ivarCountSlot, ObjCTypes.IntTy, ivarCount);

  const char *Prefix = "_OBJC_$_INSTANCE_VARIABLES_";
  llvm::GlobalVariable *GV = finishAndCreateGlobal(
      ivarList, Prefix + OID->getObjCRuntimeNameAsString(), CGM);
  CGM.addCompilerUsedGlobal(GV);
  return GV;
}

llvm::Constant *
CGObjCNonFragileABIMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
  llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];

  assert(!PD->isNonRuntimeProtocol() &&
         "attempting to GetOrEmit a non-runtime protocol");
  if (!Entry) {
    // We use the initializer as a marker of whether this is a forward
    // reference or not. At module finalization we add the empty
    // contents for protocols which were referenced but never defined.
    llvm::SmallString<64> Protocol;
    llvm::raw_svector_ostream(Protocol)
        << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();

    Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
                                     false, llvm::GlobalValue::ExternalLinkage,
                                     nullptr, Protocol);
    if (!CGM.getTriple().isOSBinFormatMachO())
      Entry->setComdat(CGM.getModule().getOrInsertComdat(Protocol));
  }

  return Entry;
}

/// GetOrEmitProtocol - Generate the protocol meta-data:
/// @code
/// struct _protocol_t {
///   id isa;  // NULL
///   const char * const protocol_name;
///   const struct _protocol_list_t * protocol_list; // super protocols
///   const struct method_list_t * const instance_methods;
///   const struct method_list_t * const class_methods;
///   const struct method_list_t *optionalInstanceMethods;
///   const struct method_list_t *optionalClassMethods;
///   const struct _prop_list_t * properties;
///   const uint32_t size;  // sizeof(struct _protocol_t)
///   const uint32_t flags;  // = 0
///   const char ** extendedMethodTypes;
///   const char *demangledName;
///   const struct _prop_list_t * class_properties;
/// }
/// @endcode
///

llvm::Constant *
CGObjCNonFragileABIMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
  llvm::GlobalVariable *Entry = Protocols[PD->getIdentifier()];

  // Early exit if a defining object has already been generated.
  if (Entry && Entry->hasInitializer())
    return Entry;

  // Use the protocol definition, if there is one.
  assert(PD->hasDefinition() &&
         "emitting protocol metadata without definition");
  PD = PD->getDefinition();

  auto methodLists = ProtocolMethodLists::get(PD);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.ProtocolnfABITy);

  // isa is NULL
  values.addNullPointer(ObjCTypes.ObjectPtrTy);
  values.add(GetClassName(PD->getObjCRuntimeNameAsString()));
  values.add(EmitProtocolList("_OBJC_$_PROTOCOL_REFS_" +
                                  PD->getObjCRuntimeNameAsString(),
                              PD->protocol_begin(), PD->protocol_end()));
  values.add(methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::RequiredInstanceMethods));
  values.add(methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::RequiredClassMethods));
  values.add(methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::OptionalInstanceMethods));
  values.add(methodLists.emitMethodList(
      this, PD, ProtocolMethodLists::OptionalClassMethods));
  values.add(
      EmitPropertyList("_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(),
                       nullptr, PD, ObjCTypes, false));
  uint32_t Size =
      CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
  values.addInt(ObjCTypes.IntTy, Size);
  values.addInt(ObjCTypes.IntTy, 0);
  values.add(EmitProtocolMethodTypes(
      "_OBJC_$_PROTOCOL_METHOD_TYPES_" + PD->getObjCRuntimeNameAsString(),
      methodLists.emitExtendedTypesArray(this), ObjCTypes));

  // const char *demangledName;
  values.addNullPointer(ObjCTypes.Int8PtrTy);

  values.add(EmitPropertyList("_OBJC_$_CLASS_PROP_LIST_" +
                                  PD->getObjCRuntimeNameAsString(),
                              nullptr, PD, ObjCTypes, true));

  if (Entry) {
    // Already created, fix the linkage and update the initializer.
    Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
    values.finishAndSetAsInitializer(Entry);
  } else {
    llvm::SmallString<64> symbolName;
    llvm::raw_svector_ostream(symbolName)
        << "_OBJC_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();

    Entry = values.finishAndCreateGlobal(symbolName, CGM.getPointerAlign(),
                                         /*constant*/ false,
                                         llvm::GlobalValue::WeakAnyLinkage);
    if (!CGM.getTriple().isOSBinFormatMachO())
      Entry->setComdat(CGM.getModule().getOrInsertComdat(symbolName));

    Protocols[PD->getIdentifier()] = Entry;
  }
  Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
  CGM.addUsedGlobal(Entry);

  // Use this protocol meta-data to build protocol list table in section
  // __DATA, __objc_protolist
  llvm::SmallString<64> ProtocolRef;
  llvm::raw_svector_ostream(ProtocolRef)
      << "_OBJC_LABEL_PROTOCOL_$_" << PD->getObjCRuntimeNameAsString();

  llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(
      CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, false,
      llvm::GlobalValue::WeakAnyLinkage, Entry, ProtocolRef);
  if (!CGM.getTriple().isOSBinFormatMachO())
    PTGV->setComdat(CGM.getModule().getOrInsertComdat(ProtocolRef));
  PTGV->setAlignment(
      CGM.getDataLayout().getABITypeAlign(ObjCTypes.ProtocolnfABIPtrTy));
  PTGV->setSection(
      GetSectionName("__objc_protolist", "coalesced,no_dead_strip"));
  PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
  CGM.addUsedGlobal(PTGV);
  return Entry;
}

/// EmitProtocolList - Generate protocol list meta-data:
/// @code
/// struct _protocol_list_t {
///   long protocol_count;   // Note, this is 32/64 bit
///   struct _protocol_t[protocol_count];
/// }
/// @endcode
///
llvm::Constant *CGObjCNonFragileABIMac::EmitProtocolList(
    Twine Name, ObjCProtocolDecl::protocol_iterator begin,
    ObjCProtocolDecl::protocol_iterator end) {
  // Just return null for empty protocol lists
  auto Protocols = GetRuntimeProtocolList(begin, end);
  if (Protocols.empty())
    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);

  SmallVector<llvm::Constant *, 16> ProtocolRefs;
  ProtocolRefs.reserve(Protocols.size());

  for (const auto *PD : Protocols)
    ProtocolRefs.push_back(GetProtocolRef(PD));

  // If all of the protocols in the protocol list are objc_non_runtime_protocol
  // just return null
  if (ProtocolRefs.size() == 0)
    return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);

  // FIXME: We shouldn't need to do this lookup here, should we?
  SmallString<256> TmpName;
  Name.toVector(TmpName);
  llvm::GlobalVariable *GV =
      CGM.getModule().getGlobalVariable(TmpName.str(), true);
  if (GV)
    return GV;

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct();
  auto countSlot = values.addPlaceholder();

  // A null-terminated array of protocols.
  auto array = values.beginArray(ObjCTypes.ProtocolnfABIPtrTy);
  for (auto const &proto : ProtocolRefs)
    array.add(proto);
  auto count = array.size();
  array.addNullPointer(ObjCTypes.ProtocolnfABIPtrTy);

  array.finishAndAddTo(values);
  values.fillPlaceholderWithInt(countSlot, ObjCTypes.LongTy, count);

  GV = finishAndCreateGlobal(values, Name, CGM);
  CGM.addCompilerUsedGlobal(GV);
  return GV;
}

/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
/// This code gen. amounts to generating code for:
/// @code
/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
/// @encode
///
LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
    CodeGen::CodeGenFunction &CGF, QualType ObjectTy, llvm::Value *BaseValue,
    const ObjCIvarDecl *Ivar, unsigned CVRQualifiers) {
  ObjCInterfaceDecl *ID = ObjectTy->castAs<ObjCObjectType>()->getInterface();
  llvm::Value *Offset = EmitIvarOffset(CGF, ID, Ivar);
  return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
                                  Offset);
}

llvm::Value *
CGObjCNonFragileABIMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
                                       const ObjCInterfaceDecl *Interface,
                                       const ObjCIvarDecl *Ivar) {
  llvm::Value *IvarOffsetValue;
  if (isClassLayoutKnownStatically(Interface)) {
    IvarOffsetValue = llvm::ConstantInt::get(
        ObjCTypes.IvarOffsetVarTy,
        ComputeIvarBaseOffset(CGM, Interface->getImplementation(), Ivar));
  } else {
    llvm::GlobalVariable *GV = ObjCIvarOffsetVariable(Interface, Ivar);
    IvarOffsetValue = CGF.Builder.CreateAlignedLoad(GV->getValueType(), GV,
                                                    CGF.getSizeAlign(), "ivar");
    if (IsIvarOffsetKnownIdempotent(CGF, Ivar))
      cast<llvm::LoadInst>(IvarOffsetValue)
          ->setMetadata(llvm::LLVMContext::MD_invariant_load,
                        llvm::MDNode::get(VMContext, {}));
  }

  // This could be 32bit int or 64bit integer depending on the architecture.
  // Cast it to 64bit integer value, if it is a 32bit integer ivar offset value
  //  as this is what caller always expects.
  if (ObjCTypes.IvarOffsetVarTy == ObjCTypes.IntTy)
    IvarOffsetValue = CGF.Builder.CreateIntCast(
        IvarOffsetValue, ObjCTypes.LongTy, true, "ivar.conv");
  return IvarOffsetValue;
}

static void appendSelectorForMessageRefTable(std::string &buffer,
                                             Selector selector) {
  if (selector.isUnarySelector()) {
    buffer += selector.getNameForSlot(0);
    return;
  }

  for (unsigned i = 0, e = selector.getNumArgs(); i != e; ++i) {
    buffer += selector.getNameForSlot(i);
    buffer += '_';
  }
}

/// Emit a "vtable" message send.  We emit a weak hidden-visibility
/// struct, initially containing the selector pointer and a pointer to
/// a "fixup" variant of the appropriate objc_msgSend.  To call, we
/// load and call the function pointer, passing the address of the
/// struct as the second parameter.  The runtime determines whether
/// the selector is currently emitted using vtable dispatch; if so, it
/// substitutes a stub function which simply tail-calls through the
/// appropriate vtable slot, and if not, it substitues a stub function
/// which tail-calls objc_msgSend.  Both stubs adjust the selector
/// argument to correctly point to the selector.
RValue CGObjCNonFragileABIMac::EmitVTableMessageSend(
    CodeGenFunction &CGF, ReturnValueSlot returnSlot, QualType resultType,
    Selector selector, llvm::Value *arg0, QualType arg0Type, bool isSuper,
    const CallArgList &formalArgs, const ObjCMethodDecl *method) {
  // Compute the actual arguments.
  CallArgList args;

  // First argument: the receiver / super-call structure.
  if (!isSuper)
    arg0 = CGF.Builder.CreateBitCast(arg0, ObjCTypes.ObjectPtrTy);
  args.add(RValue::get(arg0), arg0Type);

  // Second argument: a pointer to the message ref structure.  Leave
  // the actual argument value blank for now.
  args.add(RValue::get(nullptr), ObjCTypes.MessageRefCPtrTy);

  llvm::append_range(args, formalArgs);

  MessageSendInfo MSI = getMessageSendInfo(method, resultType, args);

  NullReturnState nullReturn;

  // Find the function to call and the mangled name for the message
  // ref structure.  Using a different mangled name wouldn't actually
  // be a problem; it would just be a waste.
  //
  // The runtime currently never uses vtable dispatch for anything
  // except normal, non-super message-sends.
  // FIXME: don't use this for that.
  llvm::FunctionCallee fn = nullptr;
  std::string messageRefName("_");
  if (CGM.ReturnSlotInterferesWithArgs(MSI.CallInfo)) {
    if (isSuper) {
      fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
      messageRefName += "objc_msgSendSuper2_stret_fixup";
    } else {
      nullReturn.init(CGF, arg0);
      fn = ObjCTypes.getMessageSendStretFixupFn();
      messageRefName += "objc_msgSend_stret_fixup";
    }
  } else if (!isSuper && CGM.ReturnTypeUsesFPRet(resultType)) {
    fn = ObjCTypes.getMessageSendFpretFixupFn();
    messageRefName += "objc_msgSend_fpret_fixup";
  } else {
    if (isSuper) {
      fn = ObjCTypes.getMessageSendSuper2FixupFn();
      messageRefName += "objc_msgSendSuper2_fixup";
    } else {
      fn = ObjCTypes.getMessageSendFixupFn();
      messageRefName += "objc_msgSend_fixup";
    }
  }
  assert(fn && "CGObjCNonFragileABIMac::EmitMessageSend");
  messageRefName += '_';

  // Append the selector name, except use underscores anywhere we
  // would have used colons.
  appendSelectorForMessageRefTable(messageRefName, selector);

  llvm::GlobalVariable *messageRef =
      CGM.getModule().getGlobalVariable(messageRefName);
  if (!messageRef) {
    // Build the message ref structure.
    ConstantInitBuilder builder(CGM);
    auto values = builder.beginStruct();
    values.add(cast<llvm::Constant>(fn.getCallee()));
    values.add(GetMethodVarName(selector));
    messageRef = values.finishAndCreateGlobal(
        messageRefName, CharUnits::fromQuantity(16),
        /*constant*/ false, llvm::GlobalValue::WeakAnyLinkage);
    messageRef->setVisibility(llvm::GlobalValue::HiddenVisibility);
    messageRef->setSection(GetSectionName("__objc_msgrefs", "coalesced"));
  }

  bool requiresnullCheck = false;
  if (CGM.getLangOpts().ObjCAutoRefCount && method)
    for (const auto *ParamDecl : method->parameters()) {
      if (ParamDecl->isDestroyedInCallee()) {
        if (!nullReturn.NullBB)
          nullReturn.init(CGF, arg0);
        requiresnullCheck = true;
        break;
      }
    }

  Address mref =
      Address(CGF.Builder.CreateBitCast(messageRef, ObjCTypes.MessageRefPtrTy),
              ObjCTypes.MessageRefTy, CGF.getPointerAlign());

  // Update the message ref argument.
  args[1].setRValue(RValue::get(mref, CGF));

  // Load the function to call from the message ref table.
  Address calleeAddr = CGF.Builder.CreateStructGEP(mref, 0);
  llvm::Value *calleePtr = CGF.Builder.CreateLoad(calleeAddr, "msgSend_fn");

  calleePtr = CGF.Builder.CreateBitCast(calleePtr, MSI.MessengerType);
  CGCallee callee(CGCalleeInfo(), calleePtr);

  RValue result = CGF.EmitCall(MSI.CallInfo, callee, returnSlot, args);
  return nullReturn.complete(CGF, returnSlot, result, resultType, formalArgs,
                             requiresnullCheck ? method : nullptr);
}

/// Generate code for a message send expression in the nonfragile abi.
CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSend(
    CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
    Selector Sel, llvm::Value *Receiver, const CallArgList &CallArgs,
    const ObjCInterfaceDecl *Class, const ObjCMethodDecl *Method) {
  return isVTableDispatchedSelector(Sel)
             ? EmitVTableMessageSend(CGF, Return, ResultType, Sel, Receiver,
                                     CGF.getContext().getObjCIdType(), false,
                                     CallArgs, Method)
             : EmitMessageSend(CGF, Return, ResultType, Sel, Receiver,
                               CGF.getContext().getObjCIdType(), false,
                               CallArgs, Method, Class, ObjCTypes);
}

llvm::Constant *
CGObjCNonFragileABIMac::GetClassGlobal(const ObjCInterfaceDecl *ID,
                                       bool metaclass,
                                       ForDefinition_t isForDefinition) {
  auto prefix =
      (metaclass ? getMetaclassSymbolPrefix() : getClassSymbolPrefix());
  return GetClassGlobal((prefix + ID->getObjCRuntimeNameAsString()).str(),
                        isForDefinition, ID->isWeakImported(),
                        !isForDefinition &&
                            CGM.getTriple().isOSBinFormatCOFF() &&
                            ID->hasAttr<DLLImportAttr>());
}

llvm::Constant *
CGObjCNonFragileABIMac::GetClassGlobal(StringRef Name,
                                       ForDefinition_t IsForDefinition,
                                       bool Weak, bool DLLImport) {
  llvm::GlobalValue::LinkageTypes L =
      Weak ? llvm::GlobalValue::ExternalWeakLinkage
           : llvm::GlobalValue::ExternalLinkage;

  llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
  if (!GV || GV->getValueType() != ObjCTypes.ClassnfABITy) {
    auto *NewGV = new llvm::GlobalVariable(ObjCTypes.ClassnfABITy, false, L,
                                           nullptr, Name);

    if (DLLImport)
      NewGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);

    if (GV) {
      GV->replaceAllUsesWith(NewGV);
      GV->eraseFromParent();
    }
    GV = NewGV;
    CGM.getModule().insertGlobalVariable(GV);
  }

  assert(GV->getLinkage() == L);
  return GV;
}

llvm::Constant *
CGObjCNonFragileABIMac::GetClassGlobalForClassRef(const ObjCInterfaceDecl *ID) {
  llvm::Constant *ClassGV =
      GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);

  if (!ID->hasAttr<ObjCClassStubAttr>())
    return ClassGV;

  ClassGV = llvm::ConstantExpr::getPointerCast(ClassGV, ObjCTypes.Int8PtrTy);

  // Stub classes are pointer-aligned. Classrefs pointing at stub classes
  // must set the least significant bit set to 1.
  auto *Idx = llvm::ConstantInt::get(CGM.Int32Ty, 1);
  return llvm::ConstantExpr::getGetElementPtr(CGM.Int8Ty, ClassGV, Idx);
}

llvm::Value *
CGObjCNonFragileABIMac::EmitLoadOfClassRef(CodeGenFunction &CGF,
                                           const ObjCInterfaceDecl *ID,
                                           llvm::GlobalVariable *Entry) {
  if (ID && ID->hasAttr<ObjCClassStubAttr>()) {
    // Classrefs pointing at Objective-C stub classes must be loaded by calling
    // a special runtime function.
    return CGF.EmitRuntimeCall(ObjCTypes.getLoadClassrefFn(), Entry,
                               "load_classref_result");
  }

  CharUnits Align = CGF.getPointerAlign();
  return CGF.Builder.CreateAlignedLoad(Entry->getValueType(), Entry, Align);
}

llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(
    CodeGenFunction &CGF, IdentifierInfo *II, const ObjCInterfaceDecl *ID) {
  llvm::GlobalVariable *&Entry = ClassReferences[II];

  if (!Entry) {
    llvm::Constant *ClassGV;
    if (ID) {
      ClassGV = GetClassGlobalForClassRef(ID);
    } else {
      ClassGV = GetClassGlobal((getClassSymbolPrefix() + II->getName()).str(),
                               NotForDefinition);
      assert(ClassGV->getType() == ObjCTypes.ClassnfABIPtrTy &&
             "classref was emitted with the wrong type?");
    }

    std::string SectionName =
        GetSectionName("__objc_classrefs", "regular,no_dead_strip");
    Entry = new llvm::GlobalVariable(
        CGM.getModule(), ClassGV->getType(), false,
        getLinkageTypeForObjCMetadata(CGM, SectionName), ClassGV,
        "OBJC_CLASSLIST_REFERENCES_$_");
    Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
    if (!ID || !ID->hasAttr<ObjCClassStubAttr>())
      Entry->setSection(SectionName);

    CGM.addCompilerUsedGlobal(Entry);
  }

  return EmitLoadOfClassRef(CGF, ID, Entry);
}

llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF,
                                                  const ObjCInterfaceDecl *ID) {
  // If the class has the objc_runtime_visible attribute, we need to
  // use the Objective-C runtime to get the class.
  if (ID->hasAttr<ObjCRuntimeVisibleAttr>())
    return EmitClassRefViaRuntime(CGF, ID, ObjCTypes);

  return EmitClassRefFromId(CGF, ID->getIdentifier(), ID);
}

llvm::Value *
CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
  IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool");
  return EmitClassRefFromId(CGF, II, nullptr);
}

llvm::Value *
CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF,
                                          const ObjCInterfaceDecl *ID) {
  llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];

  if (!Entry) {
    llvm::Constant *ClassGV = GetClassGlobalForClassRef(ID);
    std::string SectionName =
        GetSectionName("__objc_superrefs", "regular,no_dead_strip");
    Entry = new llvm::GlobalVariable(CGM.getModule(), ClassGV->getType(), false,
                                     llvm::GlobalValue::PrivateLinkage, ClassGV,
                                     "OBJC_CLASSLIST_SUP_REFS_$_");
    Entry->setAlignment(CGF.getPointerAlign().getAsAlign());
    Entry->setSection(SectionName);
    CGM.addCompilerUsedGlobal(Entry);
  }

  return EmitLoadOfClassRef(CGF, ID, Entry);
}

/// EmitMetaClassRef - Return a Value * of the address of _class_t
/// meta-data
///
llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(
    CodeGenFunction &CGF, const ObjCInterfaceDecl *ID, bool Weak) {
  CharUnits Align = CGF.getPointerAlign();
  llvm::GlobalVariable *&Entry = MetaClassReferences[ID->getIdentifier()];
  if (!Entry) {
    auto MetaClassGV = GetClassGlobal(ID, /*metaclass*/ true, NotForDefinition);
    std::string SectionName =
        GetSectionName("__objc_superrefs", "regular,no_dead_strip");
    Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
                                     false, llvm::GlobalValue::PrivateLinkage,
                                     MetaClassGV, "OBJC_CLASSLIST_SUP_REFS_$_");
    Entry->setAlignment(Align.getAsAlign());
    Entry->setSection(SectionName);
    CGM.addCompilerUsedGlobal(Entry);
  }

  return CGF.Builder.CreateAlignedLoad(ObjCTypes.ClassnfABIPtrTy, Entry, Align);
}

/// GetClass - Return a reference to the class for the given interface
/// decl.
llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF,
                                              const ObjCInterfaceDecl *ID) {
  if (ID->isWeakImported()) {
    auto ClassGV = GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition);
    (void)ClassGV;
    assert(!isa<llvm::GlobalVariable>(ClassGV) ||
           cast<llvm::GlobalVariable>(ClassGV)->hasExternalWeakLinkage());
  }

  return EmitClassRef(CGF, ID);
}

/// Generates a message send where the super is the receiver.  This is
/// a message send to self with special delivery semantics indicating
/// which class's method should be called.
CodeGen::RValue CGObjCNonFragileABIMac::GenerateMessageSendSuper(
    CodeGen::CodeGenFunction &CGF, ReturnValueSlot Return, QualType ResultType,
    Selector Sel, const ObjCInterfaceDecl *Class, bool isCategoryImpl,
    llvm::Value *Receiver, bool IsClassMessage,
    const CodeGen::CallArgList &CallArgs, const ObjCMethodDecl *Method) {
  // ...
  // Create and init a super structure; this is a (receiver, class)
  // pair we will pass to objc_msgSendSuper.
  RawAddress ObjCSuper = CGF.CreateTempAlloca(
      ObjCTypes.SuperTy, CGF.getPointerAlign(), "objc_super");

  llvm::Value *ReceiverAsObject =
      CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
  CGF.Builder.CreateStore(ReceiverAsObject,
                          CGF.Builder.CreateStructGEP(ObjCSuper, 0));

  // If this is a class message the metaclass is passed as the target.
  llvm::Value *Target;
  if (IsClassMessage)
    Target = EmitMetaClassRef(CGF, Class, Class->isWeakImported());
  else
    Target = EmitSuperClassRef(CGF, Class);

  // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
  // ObjCTypes types.
  llvm::Type *ClassTy =
      CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
  Target = CGF.Builder.CreateBitCast(Target, ClassTy);
  CGF.Builder.CreateStore(Target, CGF.Builder.CreateStructGEP(ObjCSuper, 1));

  return (isVTableDispatchedSelector(Sel))
             ? EmitVTableMessageSend(
                   CGF, Return, ResultType, Sel, ObjCSuper.getPointer(),
                   ObjCTypes.SuperPtrCTy, true, CallArgs, Method)
             : EmitMessageSend(CGF, Return, ResultType, Sel,
                               ObjCSuper.getPointer(), ObjCTypes.SuperPtrCTy,
                               true, CallArgs, Method, Class, ObjCTypes);
}

llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CodeGenFunction &CGF,
                                                  Selector Sel) {
  Address Addr = EmitSelectorAddr(Sel);

  llvm::LoadInst *LI = CGF.Builder.CreateLoad(Addr);
  LI->setMetadata(llvm::LLVMContext::MD_invariant_load,
                  llvm::MDNode::get(VMContext, {}));
  return LI;
}

ConstantAddress CGObjCNonFragileABIMac::EmitSelectorAddr(Selector Sel) {
  llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
  CharUnits Align = CGM.getPointerAlign();
  if (!Entry) {
    std::string SectionName =
        GetSectionName("__objc_selrefs", "literal_pointers,no_dead_strip");
    Entry = new llvm::GlobalVariable(
        CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
        getLinkageTypeForObjCMetadata(CGM, SectionName), GetMethodVarName(Sel),
        "OBJC_SELECTOR_REFERENCES_");
    Entry->setExternallyInitialized(true);
    Entry->setSection(SectionName);
    Entry->setAlignment(Align.getAsAlign());
    CGM.addCompilerUsedGlobal(Entry);
  }

  return ConstantAddress(Entry, ObjCTypes.SelectorPtrTy, Align);
}

/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
///
void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
                                                llvm::Value *src, Address dst,
                                                llvm::Value *ivarOffset) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
                     : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal, ivarOffset};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignIvarFn(), args);
}

/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
/// objc_assign_strongCast (id src, id *dst)
///
void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
    CodeGen::CodeGenFunction &CGF, llvm::Value *src, Address dst) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
                     : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignStrongCastFn(), args,
                              "weakassign");
}

void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
    CodeGen::CodeGenFunction &CGF, Address DestPtr, Address SrcPtr,
    llvm::Value *Size) {
  llvm::Value *args[] = {DestPtr.emitRawPointer(CGF),
                         SrcPtr.emitRawPointer(CGF), Size};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.GcMemmoveCollectableFn(), args);
}

/// EmitObjCWeakRead - Code gen for loading value of a __weak
/// object: objc_read_weak (id *src)
///
llvm::Value *
CGObjCNonFragileABIMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
                                         Address AddrWeakObj) {
  llvm::Type *DestTy = AddrWeakObj.getElementType();
  llvm::Value *AddrWeakObjVal = CGF.Builder.CreateBitCast(
      AddrWeakObj.emitRawPointer(CGF), ObjCTypes.PtrObjectPtrTy);
  llvm::Value *read_weak = CGF.EmitNounwindRuntimeCall(
      ObjCTypes.getGcReadWeakFn(), AddrWeakObjVal, "weakread");
  read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
  return read_weak;
}

/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
/// objc_assign_weak (id src, id *dst)
///
void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
                                                llvm::Value *src, Address dst) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
                     : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal};
  CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignWeakFn(), args,
                              "weakassign");
}

/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
/// objc_assign_global (id src, id *dst)
///
void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
                                                  llvm::Value *src, Address dst,
                                                  bool threadlocal) {
  llvm::Type *SrcTy = src->getType();
  if (!isa<llvm::PointerType>(SrcTy)) {
    unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy);
    assert(Size <= 8 && "does not support size > 8");
    src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
                     : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
    src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
  }
  src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
  llvm::Value *dstVal = CGF.Builder.CreateBitCast(dst.emitRawPointer(CGF),
                                                  ObjCTypes.PtrObjectPtrTy);
  llvm::Value *args[] = {src, dstVal};
  if (!threadlocal)
    CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignGlobalFn(), args,
                                "globalassign");
  else
    CGF.EmitNounwindRuntimeCall(ObjCTypes.getGcAssignThreadLocalFn(), args,
                                "threadlocalassign");
}

void CGObjCNonFragileABIMac::EmitSynchronizedStmt(
    CodeGen::CodeGenFunction &CGF, const ObjCAtSynchronizedStmt &S) {
  EmitAtSynchronizedStmt(CGF, S, ObjCTypes.getSyncEnterFn(),
                         ObjCTypes.getSyncExitFn());
}

llvm::Constant *CGObjCNonFragileABIMac::GetEHType(QualType T) {
  // There's a particular fixed type info for 'id'.
  if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
    auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
    if (!IDEHType) {
      IDEHType = new llvm::GlobalVariable(
          CGM.getModule(), ObjCTypes.EHTypeTy, false,
          llvm::GlobalValue::ExternalLinkage, nullptr, "OBJC_EHTYPE_id");
      if (CGM.getTriple().isOSBinFormatCOFF())
        IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id"));
    }
    return IDEHType;
  }

  // All other types should be Objective-C interface pointer types.
  const ObjCObjectPointerType *PT = T->getAs<ObjCObjectPointerType>();
  assert(PT && "Invalid @catch type.");

  const ObjCInterfaceType *IT = PT->getInterfaceType();
  assert(IT && "Invalid @catch type.");

  return GetInterfaceEHType(IT->getDecl(), NotForDefinition);
}

void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
                                         const ObjCAtTryStmt &S) {
  EmitTryCatchStmt(CGF, S, ObjCTypes.getObjCBeginCatchFn(),
                   ObjCTypes.getObjCEndCatchFn(),
                   ObjCTypes.getExceptionRethrowFn());
}

/// EmitThrowStmt - Generate code for a throw statement.
void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
                                           const ObjCAtThrowStmt &S,
                                           bool ClearInsertionPoint) {
  if (const Expr *ThrowExpr = S.getThrowExpr()) {
    llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
    Exception = CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy);
    llvm::CallBase *Call =
        CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionThrowFn(), Exception);
    Call->setDoesNotReturn();
  } else {
    llvm::CallBase *Call =
        CGF.EmitRuntimeCallOrInvoke(ObjCTypes.getExceptionRethrowFn());
    Call->setDoesNotReturn();
  }

  CGF.Builder.CreateUnreachable();
  if (ClearInsertionPoint)
    CGF.Builder.ClearInsertionPoint();
}

llvm::Constant *
CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
                                           ForDefinition_t IsForDefinition) {
  llvm::GlobalVariable *&Entry = EHTypeReferences[ID->getIdentifier()];
  StringRef ClassName = ID->getObjCRuntimeNameAsString();

  // If we don't need a definition, return the entry if found or check
  // if we use an external reference.
  if (!IsForDefinition) {
    if (Entry)
      return Entry;

    // If this type (or a super class) has the __objc_exception__
    // attribute, emit an external reference.
    if (hasObjCExceptionAttribute(CGM.getContext(), ID)) {
      std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str();
      Entry = new llvm::GlobalVariable(
          CGM.getModule(), ObjCTypes.EHTypeTy, false,
          llvm::GlobalValue::ExternalLinkage, nullptr, EHTypeName);
      CGM.setGVProperties(Entry, ID);
      return Entry;
    }
  }

  // Otherwise we need to either make a new entry or fill in the initializer.
  assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");

  std::string VTableName = "objc_ehtype_vtable";
  auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName);
  if (!VTableGV) {
    VTableGV = new llvm::GlobalVariable(
        CGM.getModule(), ObjCTypes.Int8PtrTy, false,
        llvm::GlobalValue::ExternalLinkage, nullptr, VTableName);
    if (CGM.getTriple().isOSBinFormatCOFF())
      VTableGV->setDLLStorageClass(getStorage(CGM, VTableName));
  }

  llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2);
  llvm::Constant *VTablePtr = llvm::ConstantExpr::getInBoundsGetElementPtr(
      VTableGV->getValueType(), VTableGV, VTableIdx);

  ConstantInitBuilder builder(CGM);
  auto values = builder.beginStruct(ObjCTypes.EHTypeTy);
  const PointerAuthSchema &TypeInfoSchema =
      CGM.getCodeGenOpts().PointerAuth.CXXTypeInfoVTablePointer;
  values.addSignedPointer(VTablePtr, TypeInfoSchema, GlobalDecl(), QualType());

  values.add(GetClassName(ClassName));
  values.add(GetClassGlobal(ID, /*metaclass*/ false, NotForDefinition));

  llvm::GlobalValue::LinkageTypes L = IsForDefinition
                                          ? llvm::GlobalValue::ExternalLinkage
                                          : llvm::GlobalValue::WeakAnyLinkage;
  if (Entry) {
    values.finishAndSetAsInitializer(Entry);
    Entry->setAlignment(CGM.getPointerAlign().getAsAlign());
  } else {
    Entry = values.finishAndCreateGlobal("OBJC_EHTYPE_$_" + ClassName,
                                         CGM.getPointerAlign(),
                                         /*constant*/ false, L);
    if (hasObjCExceptionAttribute(CGM.getContext(), ID))
      CGM.setGVProperties(Entry, ID);
  }
  assert(Entry->getLinkage() == L);

  if (!CGM.getTriple().isOSBinFormatCOFF())
    if (ID->getVisibility() == HiddenVisibility)
      Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);

  if (IsForDefinition)
    if (CGM.getTriple().isOSBinFormatMachO())
      Entry->setSection("__DATA,__objc_const");

  return Entry;
}

/* *** */

CodeGen::CGObjCRuntime *
CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
  switch (CGM.getLangOpts().ObjCRuntime.getKind()) {
  case ObjCRuntime::FragileMacOSX:
    return new CGObjCMac(CGM);

  case ObjCRuntime::MacOSX:
  case ObjCRuntime::iOS:
  case ObjCRuntime::WatchOS:
    return new CGObjCNonFragileABIMac(CGM);

  case ObjCRuntime::GNUstep:
  case ObjCRuntime::GCC:
  case ObjCRuntime::ObjFW:
    llvm_unreachable("these runtimes are not Mac runtimes");
  }
  llvm_unreachable("bad runtime");
}
