//===------- CGObjCGNU.cpp - Emit LLVM Code from ASTs for a Module --------===//
//
// 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 GNU runtime.  The
// class in this file generates structures used by the GNU Objective-C runtime
// library.  These structures are defined in objc/objc.h and objc/objc-api.h in
// the GNU runtime distribution.
//
//===----------------------------------------------------------------------===//

#include "CGCXXABI.h"
#include "CGCleanup.h"
#include "CGObjCRuntime.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "CodeGenTypes.h"
#include "SanitizerMetadata.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtObjC.h"
#include "clang/Basic/SourceManager.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ConvertUTF.h"
#include <cctype>

using namespace clang;
using namespace CodeGen;

namespace {

/// Class that lazily initialises the runtime function.  Avoids inserting the
/// types and the function declaration into a module if they're not used, and
/// avoids constructing the type more than once if it's used more than once.
class LazyRuntimeFunction {
  CodeGenModule *CGM = nullptr;
  llvm::FunctionType *FTy = nullptr;
  const char *FunctionName = nullptr;
  llvm::FunctionCallee Function = nullptr;

public:
  LazyRuntimeFunction() = default;

  /// Initialises the lazy function with the name, return type, and the types
  /// of the arguments.
  template <typename... Tys>
  void init(CodeGenModule *Mod, const char *name, llvm::Type *RetTy,
            Tys *... Types) {
    CGM = Mod;
    FunctionName = name;
    Function = nullptr;
    if(sizeof...(Tys)) {
      SmallVector<llvm::Type *, 8> ArgTys({Types...});
      FTy = llvm::FunctionType::get(RetTy, ArgTys, false);
    }
    else {
      FTy = llvm::FunctionType::get(RetTy, {}, false);
    }
  }

  llvm::FunctionType *getType() { return FTy; }

  /// Overloaded cast operator, allows the class to be implicitly cast to an
  /// LLVM constant.
  operator llvm::FunctionCallee() {
    if (!Function) {
      if (!FunctionName)
        return nullptr;
      Function = CGM->CreateRuntimeFunction(FTy, FunctionName);
    }
    return Function;
  }
};


/// GNU Objective-C runtime code generation.  This class implements the parts of
/// Objective-C support that are specific to the GNU family of runtimes (GCC,
/// GNUstep and ObjFW).
class CGObjCGNU : public CGObjCRuntime {
protected:
  /// The LLVM module into which output is inserted
  llvm::Module &TheModule;
  /// strut objc_super.  Used for sending messages to super.  This structure
  /// contains the receiver (object) and the expected class.
  llvm::StructType *ObjCSuperTy;
  /// struct objc_super*.  The type of the argument to the superclass message
  /// lookup functions.
  llvm::PointerType *PtrToObjCSuperTy;
  /// LLVM type for selectors.  Opaque pointer (i8*) unless a header declaring
  /// SEL is included in a header somewhere, in which case it will be whatever
  /// type is declared in that header, most likely {i8*, i8*}.
  llvm::PointerType *SelectorTy;
  /// Element type of SelectorTy.
  llvm::Type *SelectorElemTy;
  /// LLVM i8 type.  Cached here to avoid repeatedly getting it in all of the
  /// places where it's used
  llvm::IntegerType *Int8Ty;
  /// Pointer to i8 - LLVM type of char*, for all of the places where the
  /// runtime needs to deal with C strings.
  llvm::PointerType *PtrToInt8Ty;
  /// struct objc_protocol type
  llvm::StructType *ProtocolTy;
  /// Protocol * type.
  llvm::PointerType *ProtocolPtrTy;
  /// Instance Method Pointer type.  This is a pointer to a function that takes,
  /// at a minimum, an object and a selector, and is the generic type for
  /// Objective-C methods.  Due to differences between variadic / non-variadic
  /// calling conventions, it must always be cast to the correct type before
  /// actually being used.
  llvm::PointerType *IMPTy;
  /// Type of an untyped Objective-C object.  Clang treats id as a built-in type
  /// when compiling Objective-C code, so this may be an opaque pointer (i8*),
  /// but if the runtime header declaring it is included then it may be a
  /// pointer to a structure.
  llvm::PointerType *IdTy;
  /// Element type of IdTy.
  llvm::Type *IdElemTy;
  /// Pointer to a pointer to an Objective-C object.  Used in the new ABI
  /// message lookup function and some GC-related functions.
  llvm::PointerType *PtrToIdTy;
  /// The clang type of id.  Used when using the clang CGCall infrastructure to
  /// call Objective-C methods.
  CanQualType ASTIdTy;
  /// LLVM type for C int type.
  llvm::IntegerType *IntTy;
  /// LLVM type for an opaque pointer.  This is identical to PtrToInt8Ty, but is
  /// used in the code to document the difference between i8* meaning a pointer
  /// to a C string and i8* meaning a pointer to some opaque type.
  llvm::PointerType *PtrTy;
  /// LLVM type for C long type.  The runtime uses this in a lot of places where
  /// it should be using intptr_t, but we can't fix this without breaking
  /// compatibility with GCC...
  llvm::IntegerType *LongTy;
  /// LLVM type for C size_t.  Used in various runtime data structures.
  llvm::IntegerType *SizeTy;
  /// LLVM type for C intptr_t.
  llvm::IntegerType *IntPtrTy;
  /// LLVM type for C ptrdiff_t.  Mainly used in property accessor functions.
  llvm::IntegerType *PtrDiffTy;
  /// LLVM type for C int*.  Used for GCC-ABI-compatible non-fragile instance
  /// variables.
  llvm::PointerType *PtrToIntTy;
  /// LLVM type for Objective-C BOOL type.
  llvm::Type *BoolTy;
  /// 32-bit integer type, to save us needing to look it up every time it's used.
  llvm::IntegerType *Int32Ty;
  /// 64-bit integer type, to save us needing to look it up every time it's used.
  llvm::IntegerType *Int64Ty;
  /// The type of struct objc_property.
  llvm::StructType *PropertyMetadataTy;
  /// Metadata kind used to tie method lookups to message sends.  The GNUstep
  /// runtime provides some LLVM passes that can use this to do things like
  /// automatic IMP caching and speculative inlining.
  unsigned msgSendMDKind;
  /// Does the current target use SEH-based exceptions? False implies
  /// Itanium-style DWARF unwinding.
  bool usesSEHExceptions;
  /// Does the current target uses C++-based exceptions?
  bool usesCxxExceptions;

  /// Helper to check if we are targeting a specific runtime version or later.
  bool isRuntime(ObjCRuntime::Kind kind, unsigned major, unsigned minor=0) {
    const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;
    return (R.getKind() == kind) &&
      (R.getVersion() >= VersionTuple(major, minor));
  }

  std::string ManglePublicSymbol(StringRef Name) {
    return (StringRef(CGM.getTriple().isOSBinFormatCOFF() ? "$_" : "._") + Name).str();
  }

  std::string SymbolForProtocol(Twine Name) {
    return (ManglePublicSymbol("OBJC_PROTOCOL_") + Name).str();
  }

  std::string SymbolForProtocolRef(StringRef Name) {
    return (ManglePublicSymbol("OBJC_REF_PROTOCOL_") + Name).str();
  }


  /// Helper function that generates a constant string and returns a pointer to
  /// the start of the string.  The result of this function can be used anywhere
  /// where the C code specifies const char*.
  llvm::Constant *MakeConstantString(StringRef Str, StringRef Name = "") {
    ConstantAddress Array =
        CGM.GetAddrOfConstantCString(std::string(Str), Name);
    return Array.getPointer();
  }

  /// Emits a linkonce_odr string, whose name is the prefix followed by the
  /// string value.  This allows the linker to combine the strings between
  /// different modules.  Used for EH typeinfo names, selector strings, and a
  /// few other things.
  llvm::Constant *ExportUniqueString(const std::string &Str,
                                     const std::string &prefix,
                                     bool Private=false) {
    std::string name = prefix + Str;
    auto *ConstStr = TheModule.getGlobalVariable(name);
    if (!ConstStr) {
      llvm::Constant *value = llvm::ConstantDataArray::getString(VMContext,Str);
      auto *GV = new llvm::GlobalVariable(TheModule, value->getType(), true,
              llvm::GlobalValue::LinkOnceODRLinkage, value, name);
      GV->setComdat(TheModule.getOrInsertComdat(name));
      if (Private)
        GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
      ConstStr = GV;
    }
    return ConstStr;
  }

  /// Returns a property name and encoding string.
  llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
                                             const Decl *Container) {
    assert(!isRuntime(ObjCRuntime::GNUstep, 2));
    if (isRuntime(ObjCRuntime::GNUstep, 1, 6)) {
      std::string NameAndAttributes;
      std::string TypeStr =
        CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container);
      NameAndAttributes += '\0';
      NameAndAttributes += TypeStr.length() + 3;
      NameAndAttributes += TypeStr;
      NameAndAttributes += '\0';
      NameAndAttributes += PD->getNameAsString();
      return MakeConstantString(NameAndAttributes);
    }
    return MakeConstantString(PD->getNameAsString());
  }

  /// Push the property attributes into two structure fields.
  void PushPropertyAttributes(ConstantStructBuilder &Fields,
      const ObjCPropertyDecl *property, bool isSynthesized=true, bool
      isDynamic=true) {
    int attrs = property->getPropertyAttributes();
    // For read-only properties, clear the copy and retain flags
    if (attrs & ObjCPropertyAttribute::kind_readonly) {
      attrs &= ~ObjCPropertyAttribute::kind_copy;
      attrs &= ~ObjCPropertyAttribute::kind_retain;
      attrs &= ~ObjCPropertyAttribute::kind_weak;
      attrs &= ~ObjCPropertyAttribute::kind_strong;
    }
    // The first flags field has the same attribute values as clang uses internally
    Fields.addInt(Int8Ty, attrs & 0xff);
    attrs >>= 8;
    attrs <<= 2;
    // For protocol properties, synthesized and dynamic have no meaning, so we
    // reuse these flags to indicate that this is a protocol property (both set
    // has no meaning, as a property can't be both synthesized and dynamic)
    attrs |= isSynthesized ? (1<<0) : 0;
    attrs |= isDynamic ? (1<<1) : 0;
    // The second field is the next four fields left shifted by two, with the
    // low bit set to indicate whether the field is synthesized or dynamic.
    Fields.addInt(Int8Ty, attrs & 0xff);
    // Two padding fields
    Fields.addInt(Int8Ty, 0);
    Fields.addInt(Int8Ty, 0);
  }

  virtual llvm::Constant *GenerateCategoryProtocolList(const
      ObjCCategoryDecl *OCD);
  virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
      int count) {
      // int count;
      Fields.addInt(IntTy, count);
      // int size; (only in GNUstep v2 ABI.
      if (isRuntime(ObjCRuntime::GNUstep, 2)) {
        const llvm::DataLayout &DL = TheModule.getDataLayout();
        Fields.addInt(IntTy, DL.getTypeSizeInBits(PropertyMetadataTy) /
                                 CGM.getContext().getCharWidth());
      }
      // struct objc_property_list *next;
      Fields.add(NULLPtr);
      // struct objc_property properties[]
      return Fields.beginArray(PropertyMetadataTy);
  }
  virtual void PushProperty(ConstantArrayBuilder &PropertiesArray,
            const ObjCPropertyDecl *property,
            const Decl *OCD,
            bool isSynthesized=true, bool
            isDynamic=true) {
    auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
    ASTContext &Context = CGM.getContext();
    Fields.add(MakePropertyEncodingString(property, OCD));
    PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
    auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
      if (accessor) {
        std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
        llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
        Fields.add(MakeConstantString(accessor->getSelector().getAsString()));
        Fields.add(TypeEncoding);
      } else {
        Fields.add(NULLPtr);
        Fields.add(NULLPtr);
      }
    };
    addPropertyMethod(property->getGetterMethodDecl());
    addPropertyMethod(property->getSetterMethodDecl());
    Fields.finishAndAddTo(PropertiesArray);
  }

  /// Ensures that the value has the required type, by inserting a bitcast if
  /// required.  This function lets us avoid inserting bitcasts that are
  /// redundant.
  llvm::Value *EnforceType(CGBuilderTy &B, llvm::Value *V, llvm::Type *Ty) {
    if (V->getType() == Ty)
      return V;
    return B.CreateBitCast(V, Ty);
  }

  // Some zeros used for GEPs in lots of places.
  llvm::Constant *Zeros[2];
  /// Null pointer value.  Mainly used as a terminator in various arrays.
  llvm::Constant *NULLPtr;
  /// LLVM context.
  llvm::LLVMContext &VMContext;

protected:

  /// Placeholder for the class.  Lots of things refer to the class before we've
  /// actually emitted it.  We use this alias as a placeholder, and then replace
  /// it with a pointer to the class structure before finally emitting the
  /// module.
  llvm::GlobalAlias *ClassPtrAlias;
  /// Placeholder for the metaclass.  Lots of things refer to the class before
  /// we've / actually emitted it.  We use this alias as a placeholder, and then
  /// replace / it with a pointer to the metaclass structure before finally
  /// emitting the / module.
  llvm::GlobalAlias *MetaClassPtrAlias;
  /// All of the classes that have been generated for this compilation units.
  std::vector<llvm::Constant*> Classes;
  /// All of the categories that have been generated for this compilation units.
  std::vector<llvm::Constant*> Categories;
  /// All of the Objective-C constant strings that have been generated for this
  /// compilation units.
  std::vector<llvm::Constant*> ConstantStrings;
  /// Map from string values to Objective-C constant strings in the output.
  /// Used to prevent emitting Objective-C strings more than once.  This should
  /// not be required at all - CodeGenModule should manage this list.
  llvm::StringMap<llvm::Constant*> ObjCStrings;
  /// All of the protocols that have been declared.
  llvm::StringMap<llvm::Constant*> ExistingProtocols;
  /// For each variant of a selector, we store the type encoding and a
  /// placeholder value.  For an untyped selector, the type will be the empty
  /// string.  Selector references are all done via the module's selector table,
  /// so we create an alias as a placeholder and then replace it with the real
  /// value later.
  typedef std::pair<std::string, llvm::GlobalAlias*> TypedSelector;
  /// Type of the selector map.  This is roughly equivalent to the structure
  /// used in the GNUstep runtime, which maintains a list of all of the valid
  /// types for a selector in a table.
  typedef llvm::DenseMap<Selector, SmallVector<TypedSelector, 2> >
    SelectorMap;
  /// A map from selectors to selector types.  This allows us to emit all
  /// selectors of the same name and type together.
  SelectorMap SelectorTable;

  /// Selectors related to memory management.  When compiling in GC mode, we
  /// omit these.
  Selector RetainSel, ReleaseSel, AutoreleaseSel;
  /// Runtime functions used for memory management in GC mode.  Note that clang
  /// supports code generation for calling these functions, but neither GNU
  /// runtime actually supports this API properly yet.
  LazyRuntimeFunction IvarAssignFn, StrongCastAssignFn, MemMoveFn, WeakReadFn,
    WeakAssignFn, GlobalAssignFn;

  typedef std::pair<std::string, std::string> ClassAliasPair;
  /// All classes that have aliases set for them.
  std::vector<ClassAliasPair> ClassAliases;

protected:
  /// Function used for throwing Objective-C exceptions.
  LazyRuntimeFunction ExceptionThrowFn;
  /// Function used for rethrowing exceptions, used at the end of \@finally or
  /// \@synchronize blocks.
  LazyRuntimeFunction ExceptionReThrowFn;
  /// Function called when entering a catch function.  This is required for
  /// differentiating Objective-C exceptions and foreign exceptions.
  LazyRuntimeFunction EnterCatchFn;
  /// Function called when exiting from a catch block.  Used to do exception
  /// cleanup.
  LazyRuntimeFunction ExitCatchFn;
  /// Function called when entering an \@synchronize block.  Acquires the lock.
  LazyRuntimeFunction SyncEnterFn;
  /// Function called when exiting an \@synchronize block.  Releases the lock.
  LazyRuntimeFunction SyncExitFn;

private:
  /// Function called if fast enumeration detects that the collection is
  /// modified during the update.
  LazyRuntimeFunction EnumerationMutationFn;
  /// Function for implementing synthesized property getters that return an
  /// object.
  LazyRuntimeFunction GetPropertyFn;
  /// Function for implementing synthesized property setters that return an
  /// object.
  LazyRuntimeFunction SetPropertyFn;
  /// Function used for non-object declared property getters.
  LazyRuntimeFunction GetStructPropertyFn;
  /// Function used for non-object declared property setters.
  LazyRuntimeFunction SetStructPropertyFn;

protected:
  /// The version of the runtime that this class targets.  Must match the
  /// version in the runtime.
  int RuntimeVersion;
  /// The version of the protocol class.  Used to differentiate between ObjC1
  /// and ObjC2 protocols.  Objective-C 1 protocols can not contain optional
  /// components and can not contain declared properties.  We always emit
  /// Objective-C 2 property structures, but we have to pretend that they're
  /// Objective-C 1 property structures when targeting the GCC runtime or it
  /// will abort.
  const int ProtocolVersion;
  /// The version of the class ABI.  This value is used in the class structure
  /// and indicates how various fields should be interpreted.
  const int ClassABIVersion;
  /// Generates an instance variable list structure.  This is a structure
  /// containing a size and an array of structures containing instance variable
  /// metadata.  This is used purely for introspection in the fragile ABI.  In
  /// the non-fragile ABI, it's used for instance variable fixup.
  virtual llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
                             ArrayRef<llvm::Constant *> IvarTypes,
                             ArrayRef<llvm::Constant *> IvarOffsets,
                             ArrayRef<llvm::Constant *> IvarAlign,
                             ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership);

  /// Generates a method list structure.  This is a structure containing a size
  /// and an array of structures containing method metadata.
  ///
  /// This structure is used by both classes and categories, and contains a next
  /// pointer allowing them to be chained together in a linked list.
  llvm::Constant *GenerateMethodList(StringRef ClassName,
      StringRef CategoryName,
      ArrayRef<const ObjCMethodDecl*> Methods,
      bool isClassMethodList);

  /// Emits an empty protocol.  This is used for \@protocol() where no protocol
  /// is found.  The runtime will (hopefully) fix up the pointer to refer to the
  /// real protocol.
  virtual llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName);

  /// Generates a list of property metadata structures.  This follows the same
  /// pattern as method and instance variable metadata lists.
  llvm::Constant *GeneratePropertyList(const Decl *Container,
      const ObjCContainerDecl *OCD,
      bool isClassProperty=false,
      bool protocolOptionalProperties=false);

  /// Generates a list of referenced protocols.  Classes, categories, and
  /// protocols all use this structure.
  llvm::Constant *GenerateProtocolList(ArrayRef<std::string> Protocols);

  /// To ensure that all protocols are seen by the runtime, we add a category on
  /// a class defined in the runtime, declaring no methods, but adopting the
  /// protocols.  This is a horribly ugly hack, but it allows us to collect all
  /// of the protocols without changing the ABI.
  void GenerateProtocolHolderCategory();

  /// Generates a class structure.
  llvm::Constant *GenerateClassStructure(
      llvm::Constant *MetaClass,
      llvm::Constant *SuperClass,
      unsigned info,
      const char *Name,
      llvm::Constant *Version,
      llvm::Constant *InstanceSize,
      llvm::Constant *IVars,
      llvm::Constant *Methods,
      llvm::Constant *Protocols,
      llvm::Constant *IvarOffsets,
      llvm::Constant *Properties,
      llvm::Constant *StrongIvarBitmap,
      llvm::Constant *WeakIvarBitmap,
      bool isMeta=false);

  /// Generates a method list.  This is used by protocols to define the required
  /// and optional methods.
  virtual llvm::Constant *GenerateProtocolMethodList(
      ArrayRef<const ObjCMethodDecl*> Methods);
  /// Emits optional and required method lists.
  template<class T>
  void EmitProtocolMethodList(T &&Methods, llvm::Constant *&Required,
      llvm::Constant *&Optional) {
    SmallVector<const ObjCMethodDecl*, 16> RequiredMethods;
    SmallVector<const ObjCMethodDecl*, 16> OptionalMethods;
    for (const auto *I : Methods)
      if (I->isOptional())
        OptionalMethods.push_back(I);
      else
        RequiredMethods.push_back(I);
    Required = GenerateProtocolMethodList(RequiredMethods);
    Optional = GenerateProtocolMethodList(OptionalMethods);
  }

  /// Returns a selector with the specified type encoding.  An empty string is
  /// used to return an untyped selector (with the types field set to NULL).
  virtual llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
                                        const std::string &TypeEncoding);

  /// Returns the name of ivar offset variables.  In the GNUstep v1 ABI, this
  /// contains the class and ivar names, in the v2 ABI this contains the type
  /// encoding as well.
  virtual std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
                                                const ObjCIvarDecl *Ivar) {
    const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
      + '.' + Ivar->getNameAsString();
    return Name;
  }
  /// Returns the variable used to store the offset of an instance variable.
  llvm::GlobalVariable *ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
      const ObjCIvarDecl *Ivar);
  /// Emits a reference to a class.  This allows the linker to object if there
  /// is no class of the matching name.
  void EmitClassRef(const std::string &className);

  /// Emits a pointer to the named class
  virtual llvm::Value *GetClassNamed(CodeGenFunction &CGF,
                                     const std::string &Name, bool isWeak);

  /// Looks up the method for sending a message to the specified object.  This
  /// mechanism differs between the GCC and GNU runtimes, so this method must be
  /// overridden in subclasses.
  virtual llvm::Value *LookupIMP(CodeGenFunction &CGF,
                                 llvm::Value *&Receiver,
                                 llvm::Value *cmd,
                                 llvm::MDNode *node,
                                 MessageSendInfo &MSI) = 0;

  /// Looks up the method for sending a message to a superclass.  This
  /// mechanism differs between the GCC and GNU runtimes, so this method must
  /// be overridden in subclasses.
  virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
                                      Address ObjCSuper,
                                      llvm::Value *cmd,
                                      MessageSendInfo &MSI) = 0;

  /// Libobjc2 uses a bitfield representation where small(ish) bitfields are
  /// stored in a 64-bit value with the low bit set to 1 and the remaining 63
  /// bits set to their values, LSB first, while larger ones are stored in a
  /// structure of this / form:
  ///
  /// struct { int32_t length; int32_t values[length]; };
  ///
  /// The values in the array are stored in host-endian format, with the least
  /// significant bit being assumed to come first in the bitfield.  Therefore,
  /// a bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] },
  /// while a bitfield / with the 63rd bit set will be 1<<64.
  llvm::Constant *MakeBitField(ArrayRef<bool> bits);

public:
  CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
      unsigned protocolClassVersion, unsigned classABI=1);

  ConstantAddress GenerateConstantString(const StringLiteral *) override;

  RValue
  GenerateMessageSend(CodeGenFunction &CGF, ReturnValueSlot Return,
                      QualType ResultType, Selector Sel,
                      llvm::Value *Receiver, const CallArgList &CallArgs,
                      const ObjCInterfaceDecl *Class,
                      const ObjCMethodDecl *Method) override;
  RValue
  GenerateMessageSendSuper(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 *OID) override;
  llvm::Value *GetSelector(CodeGenFunction &CGF, Selector Sel) override;
  Address GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) override;
  llvm::Value *GetSelector(CodeGenFunction &CGF,
                           const ObjCMethodDecl *Method) override;
  virtual llvm::Constant *GetConstantSelector(Selector Sel,
                                              const std::string &TypeEncoding) {
    llvm_unreachable("Runtime unable to generate constant selector");
  }
  llvm::Constant *GetConstantSelector(const ObjCMethodDecl *M) {
    return GetConstantSelector(M->getSelector(),
        CGM.getContext().getObjCEncodingForMethodDecl(M));
  }
  llvm::Constant *GetEHType(QualType T) override;

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

  // Map to unify direct method definitions.
  llvm::DenseMap<const ObjCMethodDecl *, llvm::Function *>
      DirectMethodDefinitions;
  void GenerateDirectMethodPrologue(CodeGenFunction &CGF, llvm::Function *Fn,
                                    const ObjCMethodDecl *OMD,
                                    const ObjCContainerDecl *CD) 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;
  void GenerateProtocol(const ObjCProtocolDecl *PD) override;

  virtual llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD);

  llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD) override {
    return GenerateProtocolRef(PD);
  }

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

  void EmitTryStmt(CodeGenFunction &CGF,
                   const ObjCAtTryStmt &S) override;
  void EmitSynchronizedStmt(CodeGenFunction &CGF,
                            const ObjCAtSynchronizedStmt &S) override;
  void EmitThrowStmt(CodeGenFunction &CGF,
                     const ObjCAtThrowStmt &S,
                     bool ClearInsertionPoint=true) override;
  llvm::Value * EmitObjCWeakRead(CodeGenFunction &CGF,
                                 Address AddrWeakObj) override;
  void EmitObjCWeakAssign(CodeGenFunction &CGF,
                          llvm::Value *src, Address dst) override;
  void EmitObjCGlobalAssign(CodeGenFunction &CGF,
                            llvm::Value *src, Address dest,
                            bool threadlocal=false) override;
  void EmitObjCIvarAssign(CodeGenFunction &CGF, llvm::Value *src,
                          Address dest, llvm::Value *ivarOffset) override;
  void EmitObjCStrongCastAssign(CodeGenFunction &CGF,
                                llvm::Value *src, Address dest) override;
  void EmitGCMemmoveCollectable(CodeGenFunction &CGF, Address DestPtr,
                                Address SrcPtr,
                                llvm::Value *Size) override;
  LValue EmitObjCValueForIvar(CodeGenFunction &CGF, QualType ObjectTy,
                              llvm::Value *BaseValue, const ObjCIvarDecl *Ivar,
                              unsigned CVRQualifiers) override;
  llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
                              const ObjCInterfaceDecl *Interface,
                              const ObjCIvarDecl *Ivar) override;
  llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override;
  llvm::Constant *BuildGCBlockLayout(CodeGenModule &CGM,
                                     const CGBlockInfo &blockInfo) override {
    return NULLPtr;
  }
  llvm::Constant *BuildRCBlockLayout(CodeGenModule &CGM,
                                     const CGBlockInfo &blockInfo) override {
    return NULLPtr;
  }

  llvm::Constant *BuildByrefLayout(CodeGenModule &CGM, QualType T) override {
    return NULLPtr;
  }
};

/// Class representing the legacy GCC Objective-C ABI.  This is the default when
/// -fobjc-nonfragile-abi is not specified.
///
/// The GCC ABI target actually generates code that is approximately compatible
/// with the new GNUstep runtime ABI, but refrains from using any features that
/// would not work with the GCC runtime.  For example, clang always generates
/// the extended form of the class structure, and the extra fields are simply
/// ignored by GCC libobjc.
class CGObjCGCC : public CGObjCGNU {
  /// The GCC ABI message lookup function.  Returns an IMP pointing to the
  /// method implementation for this message.
  LazyRuntimeFunction MsgLookupFn;
  /// The GCC ABI superclass message lookup function.  Takes a pointer to a
  /// structure describing the receiver and the class, and a selector as
  /// arguments.  Returns the IMP for the corresponding method.
  LazyRuntimeFunction MsgLookupSuperFn;

protected:
  llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
                         llvm::Value *cmd, llvm::MDNode *node,
                         MessageSendInfo &MSI) override {
    CGBuilderTy &Builder = CGF.Builder;
    llvm::Value *args[] = {
            EnforceType(Builder, Receiver, IdTy),
            EnforceType(Builder, cmd, SelectorTy) };
    llvm::CallBase *imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args);
    imp->setMetadata(msgSendMDKind, node);
    return imp;
  }

  llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
                              llvm::Value *cmd, MessageSendInfo &MSI) override {
    CGBuilderTy &Builder = CGF.Builder;
    llvm::Value *lookupArgs[] = {
        EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy),
        cmd};
    return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
  }

public:
  CGObjCGCC(CodeGenModule &Mod) : CGObjCGNU(Mod, 8, 2) {
    // IMP objc_msg_lookup(id, SEL);
    MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy);
    // IMP objc_msg_lookup_super(struct objc_super*, SEL);
    MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
                          PtrToObjCSuperTy, SelectorTy);
  }
};

/// Class used when targeting the new GNUstep runtime ABI.
class CGObjCGNUstep : public CGObjCGNU {
    /// The slot lookup function.  Returns a pointer to a cacheable structure
    /// that contains (among other things) the IMP.
    LazyRuntimeFunction SlotLookupFn;
    /// The GNUstep ABI superclass message lookup function.  Takes a pointer to
    /// a structure describing the receiver and the class, and a selector as
    /// arguments.  Returns the slot for the corresponding method.  Superclass
    /// message lookup rarely changes, so this is a good caching opportunity.
    LazyRuntimeFunction SlotLookupSuperFn;
    /// Specialised function for setting atomic retain properties
    LazyRuntimeFunction SetPropertyAtomic;
    /// Specialised function for setting atomic copy properties
    LazyRuntimeFunction SetPropertyAtomicCopy;
    /// Specialised function for setting nonatomic retain properties
    LazyRuntimeFunction SetPropertyNonAtomic;
    /// Specialised function for setting nonatomic copy properties
    LazyRuntimeFunction SetPropertyNonAtomicCopy;
    /// Function to perform atomic copies of C++ objects with nontrivial copy
    /// constructors from Objective-C ivars.
    LazyRuntimeFunction CxxAtomicObjectGetFn;
    /// Function to perform atomic copies of C++ objects with nontrivial copy
    /// constructors to Objective-C ivars.
    LazyRuntimeFunction CxxAtomicObjectSetFn;
    /// Type of a slot structure pointer.  This is returned by the various
    /// lookup functions.
    llvm::Type *SlotTy;
    /// Type of a slot structure.
    llvm::Type *SlotStructTy;

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

  protected:
    llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
                           llvm::Value *cmd, llvm::MDNode *node,
                           MessageSendInfo &MSI) override {
      CGBuilderTy &Builder = CGF.Builder;
      llvm::FunctionCallee LookupFn = SlotLookupFn;

      // Store the receiver on the stack so that we can reload it later
      RawAddress ReceiverPtr =
          CGF.CreateTempAlloca(Receiver->getType(), CGF.getPointerAlign());
      Builder.CreateStore(Receiver, ReceiverPtr);

      llvm::Value *self;

      if (isa<ObjCMethodDecl>(CGF.CurCodeDecl)) {
        self = CGF.LoadObjCSelf();
      } else {
        self = llvm::ConstantPointerNull::get(IdTy);
      }

      // The lookup function is guaranteed not to capture the receiver pointer.
      if (auto *LookupFn2 = dyn_cast<llvm::Function>(LookupFn.getCallee()))
        LookupFn2->addParamAttr(
            0, llvm::Attribute::getWithCaptureInfo(CGF.getLLVMContext(),
                                                   llvm::CaptureInfo::none()));

      llvm::Value *args[] = {
          EnforceType(Builder, ReceiverPtr.getPointer(), PtrToIdTy),
          EnforceType(Builder, cmd, SelectorTy),
          EnforceType(Builder, self, IdTy)};
      llvm::CallBase *slot = CGF.EmitRuntimeCallOrInvoke(LookupFn, args);
      slot->setOnlyReadsMemory();
      slot->setMetadata(msgSendMDKind, node);

      // Load the imp from the slot
      llvm::Value *imp = Builder.CreateAlignedLoad(
          IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
          CGF.getPointerAlign());

      // The lookup function may have changed the receiver, so make sure we use
      // the new one.
      Receiver = Builder.CreateLoad(ReceiverPtr, true);
      return imp;
    }

    llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
                                llvm::Value *cmd,
                                MessageSendInfo &MSI) override {
      CGBuilderTy &Builder = CGF.Builder;
      llvm::Value *lookupArgs[] = {ObjCSuper.emitRawPointer(CGF), cmd};

      llvm::CallInst *slot =
        CGF.EmitNounwindRuntimeCall(SlotLookupSuperFn, lookupArgs);
      slot->setOnlyReadsMemory();

      return Builder.CreateAlignedLoad(
          IMPTy, Builder.CreateStructGEP(SlotStructTy, slot, 4),
          CGF.getPointerAlign());
    }

  public:
    CGObjCGNUstep(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 9, 3, 1) {}
    CGObjCGNUstep(CodeGenModule &Mod, unsigned ABI, unsigned ProtocolABI,
        unsigned ClassABI) :
      CGObjCGNU(Mod, ABI, ProtocolABI, ClassABI) {
      const ObjCRuntime &R = CGM.getLangOpts().ObjCRuntime;

      SlotStructTy = llvm::StructType::get(PtrTy, PtrTy, PtrTy, IntTy, IMPTy);
      SlotTy = PtrTy;
      // Slot_t objc_msg_lookup_sender(id *receiver, SEL selector, id sender);
      SlotLookupFn.init(&CGM, "objc_msg_lookup_sender", SlotTy, PtrToIdTy,
                        SelectorTy, IdTy);
      // Slot_t objc_slot_lookup_super(struct objc_super*, SEL);
      SlotLookupSuperFn.init(&CGM, "objc_slot_lookup_super", SlotTy,
                             PtrToObjCSuperTy, SelectorTy);
      // If we're in ObjC++ mode, then we want to make
      llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);
      if (usesCxxExceptions) {
        // void *__cxa_begin_catch(void *e)
        EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
        // void __cxa_end_catch(void)
        ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy);
        // void objc_exception_rethrow(void*)
        ExceptionReThrowFn.init(&CGM, "__cxa_rethrow", PtrTy);
      } else if (usesSEHExceptions) {
        // void objc_exception_rethrow(void)
        ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy);
      } else if (CGM.getLangOpts().CPlusPlus) {
        // void *__cxa_begin_catch(void *e)
        EnterCatchFn.init(&CGM, "__cxa_begin_catch", PtrTy, PtrTy);
        // void __cxa_end_catch(void)
        ExitCatchFn.init(&CGM, "__cxa_end_catch", VoidTy);
        // void _Unwind_Resume_or_Rethrow(void*)
        ExceptionReThrowFn.init(&CGM, "_Unwind_Resume_or_Rethrow", VoidTy,
                                PtrTy);
      } else if (R.getVersion() >= VersionTuple(1, 7)) {
        // id objc_begin_catch(void *e)
        EnterCatchFn.init(&CGM, "objc_begin_catch", IdTy, PtrTy);
        // void objc_end_catch(void)
        ExitCatchFn.init(&CGM, "objc_end_catch", VoidTy);
        // void _Unwind_Resume_or_Rethrow(void*)
        ExceptionReThrowFn.init(&CGM, "objc_exception_rethrow", VoidTy, PtrTy);
      }
      SetPropertyAtomic.init(&CGM, "objc_setProperty_atomic", VoidTy, IdTy,
                             SelectorTy, IdTy, PtrDiffTy);
      SetPropertyAtomicCopy.init(&CGM, "objc_setProperty_atomic_copy", VoidTy,
                                 IdTy, SelectorTy, IdTy, PtrDiffTy);
      SetPropertyNonAtomic.init(&CGM, "objc_setProperty_nonatomic", VoidTy,
                                IdTy, SelectorTy, IdTy, PtrDiffTy);
      SetPropertyNonAtomicCopy.init(&CGM, "objc_setProperty_nonatomic_copy",
                                    VoidTy, IdTy, SelectorTy, IdTy, PtrDiffTy);
      // void objc_setCppObjectAtomic(void *dest, const void *src, void
      // *helper);
      CxxAtomicObjectSetFn.init(&CGM, "objc_setCppObjectAtomic", VoidTy, PtrTy,
                                PtrTy, PtrTy);
      // void objc_getCppObjectAtomic(void *dest, const void *src, void
      // *helper);
      CxxAtomicObjectGetFn.init(&CGM, "objc_getCppObjectAtomic", VoidTy, PtrTy,
                                PtrTy, PtrTy);
    }

    llvm::FunctionCallee GetCppAtomicObjectGetFunction() override {
      // The optimised functions were added in version 1.7 of the GNUstep
      // runtime.
      assert (CGM.getLangOpts().ObjCRuntime.getVersion() >=
          VersionTuple(1, 7));
      return CxxAtomicObjectGetFn;
    }

    llvm::FunctionCallee GetCppAtomicObjectSetFunction() override {
      // The optimised functions were added in version 1.7 of the GNUstep
      // runtime.
      assert (CGM.getLangOpts().ObjCRuntime.getVersion() >=
          VersionTuple(1, 7));
      return CxxAtomicObjectSetFn;
    }

    llvm::FunctionCallee GetOptimizedPropertySetFunction(bool atomic,
                                                         bool copy) override {
      // The optimised property functions omit the GC check, and so are not
      // safe to use in GC mode.  The standard functions are fast in GC mode,
      // so there is less advantage in using them.
      assert ((CGM.getLangOpts().getGC() == LangOptions::NonGC));
      // The optimised functions were added in version 1.7 of the GNUstep
      // runtime.
      assert (CGM.getLangOpts().ObjCRuntime.getVersion() >=
          VersionTuple(1, 7));

      if (atomic) {
        if (copy) return SetPropertyAtomicCopy;
        return SetPropertyAtomic;
      }

      return copy ? SetPropertyNonAtomicCopy : SetPropertyNonAtomic;
    }
};

/// GNUstep Objective-C ABI version 2 implementation.
/// This is the ABI that provides a clean break with the legacy GCC ABI and
/// cleans up a number of things that were added to work around 1980s linkers.
class CGObjCGNUstep2 : public CGObjCGNUstep {
  enum SectionKind
  {
    SelectorSection = 0,
    ClassSection,
    ClassReferenceSection,
    CategorySection,
    ProtocolSection,
    ProtocolReferenceSection,
    ClassAliasSection,
    ConstantStringSection
  };
  /// The subset of `objc_class_flags` used at compile time.
  enum ClassFlags {
    /// This is a metaclass
    ClassFlagMeta = (1 << 0),
    /// This class has been initialised by the runtime (+initialize has been
    /// sent if necessary).
    ClassFlagInitialized = (1 << 8),
  };
  static const char *const SectionsBaseNames[8];
  static const char *const PECOFFSectionsBaseNames[8];
  template<SectionKind K>
  std::string sectionName() {
    if (CGM.getTriple().isOSBinFormatCOFF()) {
      std::string name(PECOFFSectionsBaseNames[K]);
      name += "$m";
      return name;
    }
    return SectionsBaseNames[K];
  }
  /// The GCC ABI superclass message lookup function.  Takes a pointer to a
  /// structure describing the receiver and the class, and a selector as
  /// arguments.  Returns the IMP for the corresponding method.
  LazyRuntimeFunction MsgLookupSuperFn;
  /// Function to ensure that +initialize is sent to a class.
  LazyRuntimeFunction SentInitializeFn;
  /// A flag indicating if we've emitted at least one protocol.
  /// If we haven't, then we need to emit an empty protocol, to ensure that the
  /// __start__objc_protocols and __stop__objc_protocols sections exist.
  bool EmittedProtocol = false;
  /// A flag indicating if we've emitted at least one protocol reference.
  /// If we haven't, then we need to emit an empty protocol, to ensure that the
  /// __start__objc_protocol_refs and __stop__objc_protocol_refs sections
  /// exist.
  bool EmittedProtocolRef = false;
  /// A flag indicating if we've emitted at least one class.
  /// If we haven't, then we need to emit an empty protocol, to ensure that the
  /// __start__objc_classes and __stop__objc_classes sections / exist.
  bool EmittedClass = false;
  /// Generate the name of a symbol for a reference to a class.  Accesses to
  /// classes should be indirected via this.

  typedef std::pair<std::string, std::pair<llvm::GlobalVariable*, int>>
      EarlyInitPair;
  std::vector<EarlyInitPair> EarlyInitList;

  std::string SymbolForClassRef(StringRef Name, bool isWeak) {
    if (isWeak)
      return (ManglePublicSymbol("OBJC_WEAK_REF_CLASS_") + Name).str();
    else
      return (ManglePublicSymbol("OBJC_REF_CLASS_") + Name).str();
  }
  /// Generate the name of a class symbol.
  std::string SymbolForClass(StringRef Name) {
    return (ManglePublicSymbol("OBJC_CLASS_") + Name).str();
  }
  void CallRuntimeFunction(CGBuilderTy &B, StringRef FunctionName,
      ArrayRef<llvm::Value*> Args) {
    SmallVector<llvm::Type *,8> Types;
    for (auto *Arg : Args)
      Types.push_back(Arg->getType());
    llvm::FunctionType *FT = llvm::FunctionType::get(B.getVoidTy(), Types,
        false);
    llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FT, FunctionName);
    B.CreateCall(Fn, Args);
  }

  ConstantAddress GenerateConstantString(const StringLiteral *SL) override {

    auto Str = SL->getString();
    CharUnits Align = CGM.getPointerAlign();

    // Look for an existing one
    llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
    if (old != ObjCStrings.end())
      return ConstantAddress(old->getValue(), IdElemTy, Align);

    bool isNonASCII = SL->containsNonAscii();

    auto LiteralLength = SL->getLength();

    if ((CGM.getTarget().getPointerWidth(LangAS::Default) == 64) &&
        (LiteralLength < 9) && !isNonASCII) {
      // Tiny strings are only used on 64-bit platforms.  They store 8 7-bit
      // ASCII characters in the high 56 bits, followed by a 4-bit length and a
      // 3-bit tag (which is always 4).
      uint64_t str = 0;
      // Fill in the characters
      for (unsigned i=0 ; i<LiteralLength ; i++)
        str |= ((uint64_t)SL->getCodeUnit(i)) << ((64 - 4 - 3) - (i*7));
      // Fill in the length
      str |= LiteralLength << 3;
      // Set the tag
      str |= 4;
      auto *ObjCStr = llvm::ConstantExpr::getIntToPtr(
          llvm::ConstantInt::get(Int64Ty, str), IdTy);
      ObjCStrings[Str] = ObjCStr;
      return ConstantAddress(ObjCStr, IdElemTy, Align);
    }

    StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;

    if (StringClass.empty()) StringClass = "NSConstantString";

    std::string Sym = SymbolForClass(StringClass);

    llvm::Constant *isa = TheModule.getNamedGlobal(Sym);

    if (!isa) {
      isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */false,
              llvm::GlobalValue::ExternalLinkage, nullptr, Sym);
      if (CGM.getTriple().isOSBinFormatCOFF()) {
        cast<llvm::GlobalValue>(isa)->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
      }
    }

    //  struct
    //  {
    //    Class isa;
    //    uint32_t flags;
    //    uint32_t length; // Number of codepoints
    //    uint32_t size; // Number of bytes
    //    uint32_t hash;
    //    const char *data;
    //  };

    ConstantInitBuilder Builder(CGM);
    auto Fields = Builder.beginStruct();
    if (!CGM.getTriple().isOSBinFormatCOFF()) {
      Fields.add(isa);
    } else {
      Fields.addNullPointer(PtrTy);
    }
    // For now, all non-ASCII strings are represented as UTF-16.  As such, the
    // number of bytes is simply double the number of UTF-16 codepoints.  In
    // ASCII strings, the number of bytes is equal to the number of non-ASCII
    // codepoints.
    if (isNonASCII) {
      unsigned NumU8CodeUnits = Str.size();
      // A UTF-16 representation of a unicode string contains at most the same
      // number of code units as a UTF-8 representation.  Allocate that much
      // space, plus one for the final null character.
      SmallVector<llvm::UTF16, 128> ToBuf(NumU8CodeUnits + 1);
      const llvm::UTF8 *FromPtr = (const llvm::UTF8 *)Str.data();
      llvm::UTF16 *ToPtr = &ToBuf[0];
      (void)llvm::ConvertUTF8toUTF16(&FromPtr, FromPtr + NumU8CodeUnits,
          &ToPtr, ToPtr + NumU8CodeUnits, llvm::strictConversion);
      uint32_t StringLength = ToPtr - &ToBuf[0];
      // Add null terminator
      *ToPtr = 0;
      // Flags: 2 indicates UTF-16 encoding
      Fields.addInt(Int32Ty, 2);
      // Number of UTF-16 codepoints
      Fields.addInt(Int32Ty, StringLength);
      // Number of bytes
      Fields.addInt(Int32Ty, StringLength * 2);
      // Hash.  Not currently initialised by the compiler.
      Fields.addInt(Int32Ty, 0);
      // pointer to the data string.
      auto Arr = llvm::ArrayRef(&ToBuf[0], ToPtr + 1);
      auto *C = llvm::ConstantDataArray::get(VMContext, Arr);
      auto *Buffer = new llvm::GlobalVariable(TheModule, C->getType(),
          /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, C, ".str");
      Buffer->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
      Fields.add(Buffer);
    } else {
      // Flags: 0 indicates ASCII encoding
      Fields.addInt(Int32Ty, 0);
      // Number of UTF-16 codepoints, each ASCII byte is a UTF-16 codepoint
      Fields.addInt(Int32Ty, Str.size());
      // Number of bytes
      Fields.addInt(Int32Ty, Str.size());
      // Hash.  Not currently initialised by the compiler.
      Fields.addInt(Int32Ty, 0);
      // Data pointer
      Fields.add(MakeConstantString(Str));
    }
    std::string StringName;
    bool isNamed = !isNonASCII;
    if (isNamed) {
      StringName = ".objc_str_";
      for (unsigned char c : Str) {
        if (isalnum(c))
          StringName += c;
        else if (c == ' ')
          StringName += '_';
        else {
          isNamed = false;
          break;
        }
      }
    }
    llvm::GlobalVariable *ObjCStrGV =
      Fields.finishAndCreateGlobal(
          isNamed ? StringRef(StringName) : ".objc_string",
          Align, false, isNamed ? llvm::GlobalValue::LinkOnceODRLinkage
                                : llvm::GlobalValue::PrivateLinkage);
    ObjCStrGV->setSection(sectionName<ConstantStringSection>());
    if (isNamed) {
      ObjCStrGV->setComdat(TheModule.getOrInsertComdat(StringName));
      ObjCStrGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
    }
    if (CGM.getTriple().isOSBinFormatCOFF()) {
      std::pair<llvm::GlobalVariable*, int> v{ObjCStrGV, 0};
      EarlyInitList.emplace_back(Sym, v);
    }
    ObjCStrings[Str] = ObjCStrGV;
    ConstantStrings.push_back(ObjCStrGV);
    return ConstantAddress(ObjCStrGV, IdElemTy, Align);
  }

  void PushProperty(ConstantArrayBuilder &PropertiesArray,
            const ObjCPropertyDecl *property,
            const Decl *OCD,
            bool isSynthesized=true, bool
            isDynamic=true) override {
    // struct objc_property
    // {
    //   const char *name;
    //   const char *attributes;
    //   const char *type;
    //   SEL getter;
    //   SEL setter;
    // };
    auto Fields = PropertiesArray.beginStruct(PropertyMetadataTy);
    ASTContext &Context = CGM.getContext();
    Fields.add(MakeConstantString(property->getNameAsString()));
    std::string TypeStr =
      CGM.getContext().getObjCEncodingForPropertyDecl(property, OCD);
    Fields.add(MakeConstantString(TypeStr));
    std::string typeStr;
    Context.getObjCEncodingForType(property->getType(), typeStr);
    Fields.add(MakeConstantString(typeStr));
    auto addPropertyMethod = [&](const ObjCMethodDecl *accessor) {
      if (accessor) {
        std::string TypeStr = Context.getObjCEncodingForMethodDecl(accessor);
        Fields.add(GetConstantSelector(accessor->getSelector(), TypeStr));
      } else {
        Fields.add(NULLPtr);
      }
    };
    addPropertyMethod(property->getGetterMethodDecl());
    addPropertyMethod(property->getSetterMethodDecl());
    Fields.finishAndAddTo(PropertiesArray);
  }

  llvm::Constant *
  GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) override {
    // struct objc_protocol_method_description
    // {
    //   SEL selector;
    //   const char *types;
    // };
    llvm::StructType *ObjCMethodDescTy =
      llvm::StructType::get(CGM.getLLVMContext(),
          { PtrToInt8Ty, PtrToInt8Ty });
    ASTContext &Context = CGM.getContext();
    ConstantInitBuilder Builder(CGM);
    // struct objc_protocol_method_description_list
    // {
    //   int count;
    //   int size;
    //   struct objc_protocol_method_description methods[];
    // };
    auto MethodList = Builder.beginStruct();
    // int count;
    MethodList.addInt(IntTy, Methods.size());
    // int size; // sizeof(struct objc_method_description)
    const llvm::DataLayout &DL = TheModule.getDataLayout();
    MethodList.addInt(IntTy, DL.getTypeSizeInBits(ObjCMethodDescTy) /
                                 CGM.getContext().getCharWidth());
    // struct objc_method_description[]
    auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
    for (auto *M : Methods) {
      auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
      Method.add(CGObjCGNU::GetConstantSelector(M));
      Method.add(GetTypeString(Context.getObjCEncodingForMethodDecl(M, true)));
      Method.finishAndAddTo(MethodArray);
    }
    MethodArray.finishAndAddTo(MethodList);
    return MethodList.finishAndCreateGlobal(".objc_protocol_method_list",
                                            CGM.getPointerAlign());
  }
  llvm::Constant *GenerateCategoryProtocolList(const ObjCCategoryDecl *OCD)
    override {
    const auto &ReferencedProtocols = OCD->getReferencedProtocols();
    auto RuntimeProtocols = GetRuntimeProtocolList(ReferencedProtocols.begin(),
                                                   ReferencedProtocols.end());
    SmallVector<llvm::Constant *, 16> Protocols;
    for (const auto *PI : RuntimeProtocols)
      Protocols.push_back(GenerateProtocolRef(PI));
    return GenerateProtocolList(Protocols);
  }

  llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
                              llvm::Value *cmd, MessageSendInfo &MSI) override {
    // Don't access the slot unless we're trying to cache the result.
    CGBuilderTy &Builder = CGF.Builder;
    llvm::Value *lookupArgs[] = {
        CGObjCGNU::EnforceType(Builder, ObjCSuper.emitRawPointer(CGF),
                               PtrToObjCSuperTy),
        cmd};
    return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
  }

  llvm::GlobalVariable *GetClassVar(StringRef Name, bool isWeak=false) {
    std::string SymbolName = SymbolForClassRef(Name, isWeak);
    auto *ClassSymbol = TheModule.getNamedGlobal(SymbolName);
    if (ClassSymbol)
      return ClassSymbol;
    ClassSymbol = new llvm::GlobalVariable(TheModule,
        IdTy, false, llvm::GlobalValue::ExternalLinkage,
        nullptr, SymbolName);
    // If this is a weak symbol, then we are creating a valid definition for
    // the symbol, pointing to a weak definition of the real class pointer.  If
    // this is not a weak reference, then we are expecting another compilation
    // unit to provide the real indirection symbol.
    if (isWeak)
      ClassSymbol->setInitializer(new llvm::GlobalVariable(TheModule,
          Int8Ty, false, llvm::GlobalValue::ExternalWeakLinkage,
          nullptr, SymbolForClass(Name)));
    else {
      if (CGM.getTriple().isOSBinFormatCOFF()) {
        IdentifierInfo &II = CGM.getContext().Idents.get(Name);
        TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl();
        DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl);

        const ObjCInterfaceDecl *OID = nullptr;
        for (const auto *Result : DC->lookup(&II))
          if ((OID = dyn_cast<ObjCInterfaceDecl>(Result)))
            break;

        // The first Interface we find may be a @class,
        // which should only be treated as the source of
        // truth in the absence of a true declaration.
        assert(OID && "Failed to find ObjCInterfaceDecl");
        const ObjCInterfaceDecl *OIDDef = OID->getDefinition();
        if (OIDDef != nullptr)
          OID = OIDDef;

        auto Storage = llvm::GlobalValue::DefaultStorageClass;
        if (OID->hasAttr<DLLImportAttr>())
          Storage = llvm::GlobalValue::DLLImportStorageClass;
        else if (OID->hasAttr<DLLExportAttr>())
          Storage = llvm::GlobalValue::DLLExportStorageClass;

        cast<llvm::GlobalValue>(ClassSymbol)->setDLLStorageClass(Storage);
      }
    }
    assert(ClassSymbol->getName() == SymbolName);
    return ClassSymbol;
  }
  llvm::Value *GetClassNamed(CodeGenFunction &CGF,
                             const std::string &Name,
                             bool isWeak) override {
    return CGF.Builder.CreateLoad(
        Address(GetClassVar(Name, isWeak), IdTy, CGM.getPointerAlign()));
  }
  int32_t FlagsForOwnership(Qualifiers::ObjCLifetime Ownership) {
    // typedef enum {
    //   ownership_invalid = 0,
    //   ownership_strong  = 1,
    //   ownership_weak    = 2,
    //   ownership_unsafe  = 3
    // } ivar_ownership;
    int Flag;
    switch (Ownership) {
      case Qualifiers::OCL_Strong:
          Flag = 1;
          break;
      case Qualifiers::OCL_Weak:
          Flag = 2;
          break;
      case Qualifiers::OCL_ExplicitNone:
          Flag = 3;
          break;
      case Qualifiers::OCL_None:
      case Qualifiers::OCL_Autoreleasing:
        assert(Ownership != Qualifiers::OCL_Autoreleasing);
        Flag = 0;
    }
    return Flag;
  }
  llvm::Constant *GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
                   ArrayRef<llvm::Constant *> IvarTypes,
                   ArrayRef<llvm::Constant *> IvarOffsets,
                   ArrayRef<llvm::Constant *> IvarAlign,
                   ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) override {
    llvm_unreachable("Method should not be called!");
  }

  llvm::Constant *GenerateEmptyProtocol(StringRef ProtocolName) override {
    std::string Name = SymbolForProtocol(ProtocolName);
    auto *GV = TheModule.getGlobalVariable(Name);
    if (!GV) {
      // Emit a placeholder symbol.
      GV = new llvm::GlobalVariable(TheModule, ProtocolTy, false,
          llvm::GlobalValue::ExternalLinkage, nullptr, Name);
      GV->setAlignment(CGM.getPointerAlign().getAsAlign());
    }
    return GV;
  }

  /// Existing protocol references.
  llvm::StringMap<llvm::Constant*> ExistingProtocolRefs;

  llvm::Value *GenerateProtocolRef(CodeGenFunction &CGF,
                                   const ObjCProtocolDecl *PD) override {
    auto Name = PD->getNameAsString();
    auto *&Ref = ExistingProtocolRefs[Name];
    if (!Ref) {
      auto *&Protocol = ExistingProtocols[Name];
      if (!Protocol)
        Protocol = GenerateProtocolRef(PD);
      std::string RefName = SymbolForProtocolRef(Name);
      assert(!TheModule.getGlobalVariable(RefName));
      // Emit a reference symbol.
      auto GV = new llvm::GlobalVariable(TheModule, ProtocolPtrTy, false,
                                         llvm::GlobalValue::LinkOnceODRLinkage,
                                         Protocol, RefName);
      GV->setComdat(TheModule.getOrInsertComdat(RefName));
      GV->setSection(sectionName<ProtocolReferenceSection>());
      GV->setAlignment(CGM.getPointerAlign().getAsAlign());
      Ref = GV;
    }
    EmittedProtocolRef = true;
    return CGF.Builder.CreateAlignedLoad(ProtocolPtrTy, Ref,
                                         CGM.getPointerAlign());
  }

  llvm::Constant *GenerateProtocolList(ArrayRef<llvm::Constant*> Protocols) {
    llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(ProtocolPtrTy,
        Protocols.size());
    llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
        Protocols);
    ConstantInitBuilder builder(CGM);
    auto ProtocolBuilder = builder.beginStruct();
    ProtocolBuilder.addNullPointer(PtrTy);
    ProtocolBuilder.addInt(SizeTy, Protocols.size());
    ProtocolBuilder.add(ProtocolArray);
    return ProtocolBuilder.finishAndCreateGlobal(".objc_protocol_list",
        CGM.getPointerAlign(), false, llvm::GlobalValue::InternalLinkage);
  }

  void GenerateProtocol(const ObjCProtocolDecl *PD) override {
    // Do nothing - we only emit referenced protocols.
  }
  llvm::Constant *GenerateProtocolRef(const ObjCProtocolDecl *PD) override {
    std::string ProtocolName = PD->getNameAsString();
    auto *&Protocol = ExistingProtocols[ProtocolName];
    if (Protocol)
      return Protocol;

    EmittedProtocol = true;

    auto SymName = SymbolForProtocol(ProtocolName);
    auto *OldGV = TheModule.getGlobalVariable(SymName);

    // Use the protocol definition, if there is one.
    if (const ObjCProtocolDecl *Def = PD->getDefinition())
      PD = Def;
    else {
      // If there is no definition, then create an external linkage symbol and
      // hope that someone else fills it in for us (and fail to link if they
      // don't).
      assert(!OldGV);
      Protocol = new llvm::GlobalVariable(TheModule, ProtocolTy,
        /*isConstant*/false,
        llvm::GlobalValue::ExternalLinkage, nullptr, SymName);
      return Protocol;
    }

    SmallVector<llvm::Constant*, 16> Protocols;
    auto RuntimeProtocols =
        GetRuntimeProtocolList(PD->protocol_begin(), PD->protocol_end());
    for (const auto *PI : RuntimeProtocols)
      Protocols.push_back(GenerateProtocolRef(PI));
    llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);

    // Collect information about methods
    llvm::Constant *InstanceMethodList, *OptionalInstanceMethodList;
    llvm::Constant *ClassMethodList, *OptionalClassMethodList;
    EmitProtocolMethodList(PD->instance_methods(), InstanceMethodList,
        OptionalInstanceMethodList);
    EmitProtocolMethodList(PD->class_methods(), ClassMethodList,
        OptionalClassMethodList);

    // The isa pointer must be set to a magic number so the runtime knows it's
    // the correct layout.
    ConstantInitBuilder builder(CGM);
    auto ProtocolBuilder = builder.beginStruct();
    ProtocolBuilder.add(llvm::ConstantExpr::getIntToPtr(
          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
    ProtocolBuilder.add(MakeConstantString(ProtocolName));
    ProtocolBuilder.add(ProtocolList);
    ProtocolBuilder.add(InstanceMethodList);
    ProtocolBuilder.add(ClassMethodList);
    ProtocolBuilder.add(OptionalInstanceMethodList);
    ProtocolBuilder.add(OptionalClassMethodList);
    // Required instance properties
    ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, false));
    // Optional instance properties
    ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, false, true));
    // Required class properties
    ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, false));
    // Optional class properties
    ProtocolBuilder.add(GeneratePropertyList(nullptr, PD, true, true));

    auto *GV = ProtocolBuilder.finishAndCreateGlobal(SymName,
        CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);
    GV->setSection(sectionName<ProtocolSection>());
    GV->setComdat(TheModule.getOrInsertComdat(SymName));
    if (OldGV) {
      OldGV->replaceAllUsesWith(GV);
      OldGV->removeFromParent();
      GV->setName(SymName);
    }
    Protocol = GV;
    return GV;
  }
  llvm::Value *GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
                                const std::string &TypeEncoding) override {
    return GetConstantSelector(Sel, TypeEncoding);
  }
  std::string GetSymbolNameForTypeEncoding(const std::string &TypeEncoding) {
    std::string MangledTypes = std::string(TypeEncoding);
    // @ is used as a special character in ELF symbol names (used for symbol
    // versioning), so mangle the name to not include it.  Replace it with a
    // character that is not a valid type encoding character (and, being
    // non-printable, never will be!)
    if (CGM.getTriple().isOSBinFormatELF())
      llvm::replace(MangledTypes, '@', '\1');
    // = in dll exported names causes lld to fail when linking on Windows.
    if (CGM.getTriple().isOSWindows())
      llvm::replace(MangledTypes, '=', '\2');
    return MangledTypes;
  }
  llvm::Constant  *GetTypeString(llvm::StringRef TypeEncoding) {
    if (TypeEncoding.empty())
      return NULLPtr;
    std::string MangledTypes =
        GetSymbolNameForTypeEncoding(std::string(TypeEncoding));
    std::string TypesVarName = ".objc_sel_types_" + MangledTypes;
    auto *TypesGlobal = TheModule.getGlobalVariable(TypesVarName);
    if (!TypesGlobal) {
      llvm::Constant *Init = llvm::ConstantDataArray::getString(VMContext,
          TypeEncoding);
      auto *GV = new llvm::GlobalVariable(TheModule, Init->getType(),
          true, llvm::GlobalValue::LinkOnceODRLinkage, Init, TypesVarName);
      GV->setComdat(TheModule.getOrInsertComdat(TypesVarName));
      GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
      TypesGlobal = GV;
    }
    return TypesGlobal;
  }
  llvm::Constant *GetConstantSelector(Selector Sel,
                                      const std::string &TypeEncoding) override {
    std::string MangledTypes = GetSymbolNameForTypeEncoding(TypeEncoding);
    auto SelVarName = (StringRef(".objc_selector_") + Sel.getAsString() + "_" +
      MangledTypes).str();
    if (auto *GV = TheModule.getNamedGlobal(SelVarName))
      return GV;
    ConstantInitBuilder builder(CGM);
    auto SelBuilder = builder.beginStruct();
    SelBuilder.add(ExportUniqueString(Sel.getAsString(), ".objc_sel_name_",
          true));
    SelBuilder.add(GetTypeString(TypeEncoding));
    auto *GV = SelBuilder.finishAndCreateGlobal(SelVarName,
        CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
    GV->setComdat(TheModule.getOrInsertComdat(SelVarName));
    GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
    GV->setSection(sectionName<SelectorSection>());
    return GV;
  }
  llvm::StructType *emptyStruct = nullptr;

  /// Return pointers to the start and end of a section.  On ELF platforms, we
  /// use the __start_ and __stop_ symbols that GNU-compatible linkers will set
  /// to the start and end of section names, as long as those section names are
  /// valid identifiers and the symbols are referenced but not defined.  On
  /// Windows, we use the fact that MSVC-compatible linkers will lexically sort
  /// by subsections and place everything that we want to reference in a middle
  /// subsection and then insert zero-sized symbols in subsections a and z.
  std::pair<llvm::Constant*,llvm::Constant*>
  GetSectionBounds(StringRef Section) {
    if (CGM.getTriple().isOSBinFormatCOFF()) {
      if (emptyStruct == nullptr) {
        emptyStruct = llvm::StructType::create(
            VMContext, {}, ".objc_section_sentinel", /*isPacked=*/true);
      }
      auto ZeroInit = llvm::Constant::getNullValue(emptyStruct);
      auto Sym = [&](StringRef Prefix, StringRef SecSuffix) {
        auto *Sym = new llvm::GlobalVariable(TheModule, emptyStruct,
            /*isConstant*/false,
            llvm::GlobalValue::LinkOnceODRLinkage, ZeroInit, Prefix +
            Section);
        Sym->setVisibility(llvm::GlobalValue::HiddenVisibility);
        Sym->setSection((Section + SecSuffix).str());
        Sym->setComdat(TheModule.getOrInsertComdat((Prefix +
            Section).str()));
        Sym->setAlignment(CGM.getPointerAlign().getAsAlign());
        return Sym;
      };
      return { Sym("__start_", "$a"), Sym("__stop", "$z") };
    }
    auto *Start = new llvm::GlobalVariable(TheModule, PtrTy,
        /*isConstant*/false,
        llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__start_") +
        Section);
    Start->setVisibility(llvm::GlobalValue::HiddenVisibility);
    auto *Stop = new llvm::GlobalVariable(TheModule, PtrTy,
        /*isConstant*/false,
        llvm::GlobalValue::ExternalLinkage, nullptr, StringRef("__stop_") +
        Section);
    Stop->setVisibility(llvm::GlobalValue::HiddenVisibility);
    return { Start, Stop };
  }
  CatchTypeInfo getCatchAllTypeInfo() override {
    return CGM.getCXXABI().getCatchAllTypeInfo();
  }
  llvm::Function *ModuleInitFunction() override {
    llvm::Function *LoadFunction = llvm::Function::Create(
      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
      llvm::GlobalValue::LinkOnceODRLinkage, ".objcv2_load_function",
      &TheModule);
    LoadFunction->setVisibility(llvm::GlobalValue::HiddenVisibility);
    LoadFunction->setComdat(TheModule.getOrInsertComdat(".objcv2_load_function"));

    llvm::BasicBlock *EntryBB =
        llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
    CGBuilderTy B(CGM, VMContext);
    B.SetInsertPoint(EntryBB);
    ConstantInitBuilder builder(CGM);
    auto InitStructBuilder = builder.beginStruct();
    InitStructBuilder.addInt(Int64Ty, 0);
    auto &sectionVec = CGM.getTriple().isOSBinFormatCOFF() ? PECOFFSectionsBaseNames : SectionsBaseNames;
    for (auto *s : sectionVec) {
      auto bounds = GetSectionBounds(s);
      InitStructBuilder.add(bounds.first);
      InitStructBuilder.add(bounds.second);
    }
    auto *InitStruct = InitStructBuilder.finishAndCreateGlobal(".objc_init",
        CGM.getPointerAlign(), false, llvm::GlobalValue::LinkOnceODRLinkage);
    InitStruct->setVisibility(llvm::GlobalValue::HiddenVisibility);
    InitStruct->setComdat(TheModule.getOrInsertComdat(".objc_init"));

    CallRuntimeFunction(B, "__objc_load", {InitStruct});;
    B.CreateRetVoid();
    // Make sure that the optimisers don't delete this function.
    CGM.addCompilerUsedGlobal(LoadFunction);
    // FIXME: Currently ELF only!
    // We have to do this by hand, rather than with @llvm.ctors, so that the
    // linker can remove the duplicate invocations.
    auto *InitVar = new llvm::GlobalVariable(TheModule, LoadFunction->getType(),
        /*isConstant*/false, llvm::GlobalValue::LinkOnceAnyLinkage,
        LoadFunction, ".objc_ctor");
    // Check that this hasn't been renamed.  This shouldn't happen, because
    // this function should be called precisely once.
    assert(InitVar->getName() == ".objc_ctor");
    // In Windows, initialisers are sorted by the suffix.  XCL is for library
    // initialisers, which run before user initialisers.  We are running
    // Objective-C loads at the end of library load.  This means +load methods
    // will run before any other static constructors, but that static
    // constructors can see a fully initialised Objective-C state.
    if (CGM.getTriple().isOSBinFormatCOFF())
        InitVar->setSection(".CRT$XCLz");
    else
    {
      if (CGM.getCodeGenOpts().UseInitArray)
        InitVar->setSection(".init_array");
      else
        InitVar->setSection(".ctors");
    }
    InitVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
    InitVar->setComdat(TheModule.getOrInsertComdat(".objc_ctor"));
    CGM.addUsedGlobal(InitVar);
    for (auto *C : Categories) {
      auto *Cat = cast<llvm::GlobalVariable>(C->stripPointerCasts());
      Cat->setSection(sectionName<CategorySection>());
      CGM.addUsedGlobal(Cat);
    }
    auto createNullGlobal = [&](StringRef Name, ArrayRef<llvm::Constant*> Init,
        StringRef Section) {
      auto nullBuilder = builder.beginStruct();
      for (auto *F : Init)
        nullBuilder.add(F);
      auto GV = nullBuilder.finishAndCreateGlobal(Name, CGM.getPointerAlign(),
          false, llvm::GlobalValue::LinkOnceODRLinkage);
      GV->setSection(Section);
      GV->setComdat(TheModule.getOrInsertComdat(Name));
      GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
      CGM.addUsedGlobal(GV);
      return GV;
    };
    for (auto clsAlias : ClassAliases)
      createNullGlobal(std::string(".objc_class_alias") +
          clsAlias.second, { MakeConstantString(clsAlias.second),
          GetClassVar(clsAlias.first) }, sectionName<ClassAliasSection>());
    // On ELF platforms, add a null value for each special section so that we
    // can always guarantee that the _start and _stop symbols will exist and be
    // meaningful.  This is not required on COFF platforms, where our start and
    // stop symbols will create the section.
    if (!CGM.getTriple().isOSBinFormatCOFF()) {
      createNullGlobal(".objc_null_selector", {NULLPtr, NULLPtr},
          sectionName<SelectorSection>());
      if (Categories.empty())
        createNullGlobal(".objc_null_category", {NULLPtr, NULLPtr,
                      NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr},
            sectionName<CategorySection>());
      if (!EmittedClass) {
        createNullGlobal(".objc_null_cls_init_ref", NULLPtr,
            sectionName<ClassSection>());
        createNullGlobal(".objc_null_class_ref", { NULLPtr, NULLPtr },
            sectionName<ClassReferenceSection>());
      }
      if (!EmittedProtocol)
        createNullGlobal(".objc_null_protocol", {NULLPtr, NULLPtr, NULLPtr,
            NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr, NULLPtr,
            NULLPtr}, sectionName<ProtocolSection>());
      if (!EmittedProtocolRef)
        createNullGlobal(".objc_null_protocol_ref", {NULLPtr},
            sectionName<ProtocolReferenceSection>());
      if (ClassAliases.empty())
        createNullGlobal(".objc_null_class_alias", { NULLPtr, NULLPtr },
            sectionName<ClassAliasSection>());
      if (ConstantStrings.empty()) {
        auto i32Zero = llvm::ConstantInt::get(Int32Ty, 0);
        createNullGlobal(".objc_null_constant_string", { NULLPtr, i32Zero,
            i32Zero, i32Zero, i32Zero, NULLPtr },
            sectionName<ConstantStringSection>());
      }
    }
    ConstantStrings.clear();
    Categories.clear();
    Classes.clear();

    if (EarlyInitList.size() > 0) {
      auto *Init = llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy,
            {}), llvm::GlobalValue::InternalLinkage, ".objc_early_init",
          &CGM.getModule());
      llvm::IRBuilder<> b(llvm::BasicBlock::Create(CGM.getLLVMContext(), "entry",
            Init));
      for (const auto &lateInit : EarlyInitList) {
        auto *global = TheModule.getGlobalVariable(lateInit.first);
        if (global) {
          llvm::GlobalVariable *GV = lateInit.second.first;
          b.CreateAlignedStore(
              global,
              b.CreateStructGEP(GV->getValueType(), GV, lateInit.second.second),
              CGM.getPointerAlign().getAsAlign());
        }
      }
      b.CreateRetVoid();
      // We can't use the normal LLVM global initialisation array, because we
      // need to specify that this runs early in library initialisation.
      auto *InitVar = new llvm::GlobalVariable(CGM.getModule(), Init->getType(),
          /*isConstant*/true, llvm::GlobalValue::InternalLinkage,
          Init, ".objc_early_init_ptr");
      InitVar->setSection(".CRT$XCLb");
      CGM.addUsedGlobal(InitVar);
    }
    return nullptr;
  }
  /// In the v2 ABI, ivar offset variables use the type encoding in their name
  /// to trigger linker failures if the types don't match.
  std::string GetIVarOffsetVariableName(const ObjCInterfaceDecl *ID,
                                        const ObjCIvarDecl *Ivar) override {
    std::string TypeEncoding;
    CGM.getContext().getObjCEncodingForType(Ivar->getType(), TypeEncoding);
    TypeEncoding = GetSymbolNameForTypeEncoding(TypeEncoding);
    const std::string Name = "__objc_ivar_offset_" + ID->getNameAsString()
      + '.' + Ivar->getNameAsString() + '.' + TypeEncoding;
    return Name;
  }
  llvm::Value *EmitIvarOffset(CodeGenFunction &CGF,
                              const ObjCInterfaceDecl *Interface,
                              const ObjCIvarDecl *Ivar) override {
    const ObjCInterfaceDecl *ContainingInterface =
        Ivar->getContainingInterface();
    const std::string Name =
        GetIVarOffsetVariableName(ContainingInterface, Ivar);
    llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
    if (!IvarOffsetPointer) {
      IvarOffsetPointer = new llvm::GlobalVariable(TheModule, IntTy, false,
              llvm::GlobalValue::ExternalLinkage, nullptr, Name);
      if (Ivar->getAccessControl() != ObjCIvarDecl::Private &&
          Ivar->getAccessControl() != ObjCIvarDecl::Package)
        CGM.setGVProperties(IvarOffsetPointer, ContainingInterface);
    }
    CharUnits Align = CGM.getIntAlign();
    llvm::Value *Offset =
        CGF.Builder.CreateAlignedLoad(IntTy, IvarOffsetPointer, Align);
    if (Offset->getType() != PtrDiffTy)
      Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
    return Offset;
  }
  void GenerateClass(const ObjCImplementationDecl *OID) override {
    ASTContext &Context = CGM.getContext();
    bool IsCOFF = CGM.getTriple().isOSBinFormatCOFF();

    // Get the class name
    ObjCInterfaceDecl *classDecl =
        const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
    std::string className = classDecl->getNameAsString();
    auto *classNameConstant = MakeConstantString(className);

    ConstantInitBuilder builder(CGM);
    auto metaclassFields = builder.beginStruct();
    // struct objc_class *isa;
    metaclassFields.addNullPointer(PtrTy);
    // struct objc_class *super_class;
    metaclassFields.addNullPointer(PtrTy);
    // const char *name;
    metaclassFields.add(classNameConstant);
    // long version;
    metaclassFields.addInt(LongTy, 0);
    // unsigned long info;
    // objc_class_flag_meta
    metaclassFields.addInt(LongTy, ClassFlags::ClassFlagMeta);
    // long instance_size;
    // Setting this to zero is consistent with the older ABI, but it might be
    // more sensible to set this to sizeof(struct objc_class)
    metaclassFields.addInt(LongTy, 0);
    // struct objc_ivar_list *ivars;
    metaclassFields.addNullPointer(PtrTy);
    // struct objc_method_list *methods
    // FIXME: Almost identical code is copied and pasted below for the
    // class, but refactoring it cleanly requires C++14 generic lambdas.
    if (OID->class_methods().empty())
      metaclassFields.addNullPointer(PtrTy);
    else {
      SmallVector<ObjCMethodDecl*, 16> ClassMethods;
      ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
          OID->classmeth_end());
      metaclassFields.add(
          GenerateMethodList(className, "", ClassMethods, true));
    }
    // void *dtable;
    metaclassFields.addNullPointer(PtrTy);
    // IMP cxx_construct;
    metaclassFields.addNullPointer(PtrTy);
    // IMP cxx_destruct;
    metaclassFields.addNullPointer(PtrTy);
    // struct objc_class *subclass_list
    metaclassFields.addNullPointer(PtrTy);
    // struct objc_class *sibling_class
    metaclassFields.addNullPointer(PtrTy);
    // struct objc_protocol_list *protocols;
    metaclassFields.addNullPointer(PtrTy);
    // struct reference_list *extra_data;
    metaclassFields.addNullPointer(PtrTy);
    // long abi_version;
    metaclassFields.addInt(LongTy, 0);
    // struct objc_property_list *properties
    metaclassFields.add(GeneratePropertyList(OID, classDecl, /*isClassProperty*/true));

    auto *metaclass = metaclassFields.finishAndCreateGlobal(
        ManglePublicSymbol("OBJC_METACLASS_") + className,
        CGM.getPointerAlign());

    auto classFields = builder.beginStruct();
    // struct objc_class *isa;
    classFields.add(metaclass);
    // struct objc_class *super_class;
    // Get the superclass name.
    const ObjCInterfaceDecl * SuperClassDecl =
      OID->getClassInterface()->getSuperClass();
    llvm::Constant *SuperClass = nullptr;
    if (SuperClassDecl) {
      auto SuperClassName = SymbolForClass(SuperClassDecl->getNameAsString());
      SuperClass = TheModule.getNamedGlobal(SuperClassName);
      if (!SuperClass)
      {
        SuperClass = new llvm::GlobalVariable(TheModule, PtrTy, false,
            llvm::GlobalValue::ExternalLinkage, nullptr, SuperClassName);
        if (IsCOFF) {
          auto Storage = llvm::GlobalValue::DefaultStorageClass;
          if (SuperClassDecl->hasAttr<DLLImportAttr>())
            Storage = llvm::GlobalValue::DLLImportStorageClass;
          else if (SuperClassDecl->hasAttr<DLLExportAttr>())
            Storage = llvm::GlobalValue::DLLExportStorageClass;

          cast<llvm::GlobalValue>(SuperClass)->setDLLStorageClass(Storage);
        }
      }
      if (!IsCOFF)
        classFields.add(SuperClass);
      else
        classFields.addNullPointer(PtrTy);
    } else
      classFields.addNullPointer(PtrTy);
    // const char *name;
    classFields.add(classNameConstant);
    // long version;
    classFields.addInt(LongTy, 0);
    // unsigned long info;
    // !objc_class_flag_meta
    classFields.addInt(LongTy, 0);
    // long instance_size;
    int superInstanceSize = !SuperClassDecl ? 0 :
      Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
    // Instance size is negative for classes that have not yet had their ivar
    // layout calculated.
    classFields.addInt(
        LongTy, 0 - (Context.getASTObjCInterfaceLayout(OID->getClassInterface())
                         .getSize()
                         .getQuantity() -
                     superInstanceSize));

    if (classDecl->all_declared_ivar_begin() == nullptr)
      classFields.addNullPointer(PtrTy);
    else {
      int ivar_count = 0;
      for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
           IVD = IVD->getNextIvar()) ivar_count++;
      const llvm::DataLayout &DL = TheModule.getDataLayout();
      // struct objc_ivar_list *ivars;
      ConstantInitBuilder b(CGM);
      auto ivarListBuilder = b.beginStruct();
      // int count;
      ivarListBuilder.addInt(IntTy, ivar_count);
      // size_t size;
      llvm::StructType *ObjCIvarTy = llvm::StructType::get(
        PtrToInt8Ty,
        PtrToInt8Ty,
        PtrToInt8Ty,
        Int32Ty,
        Int32Ty);
      ivarListBuilder.addInt(SizeTy, DL.getTypeSizeInBits(ObjCIvarTy) /
                                         CGM.getContext().getCharWidth());
      // struct objc_ivar ivars[]
      auto ivarArrayBuilder = ivarListBuilder.beginArray();
      for (const ObjCIvarDecl *IVD = classDecl->all_declared_ivar_begin(); IVD;
           IVD = IVD->getNextIvar()) {
        auto ivarTy = IVD->getType();
        auto ivarBuilder = ivarArrayBuilder.beginStruct();
        // const char *name;
        ivarBuilder.add(MakeConstantString(IVD->getNameAsString()));
        // const char *type;
        std::string TypeStr;
        //Context.getObjCEncodingForType(ivarTy, TypeStr, IVD, true);
        Context.getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, ivarTy, TypeStr, true);
        ivarBuilder.add(MakeConstantString(TypeStr));
        // int *offset;
        uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
        uint64_t Offset = BaseOffset - superInstanceSize;
        llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
        std::string OffsetName = GetIVarOffsetVariableName(classDecl, IVD);
        llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
        if (OffsetVar)
          OffsetVar->setInitializer(OffsetValue);
        else
          OffsetVar = new llvm::GlobalVariable(TheModule, IntTy,
            false, llvm::GlobalValue::ExternalLinkage,
            OffsetValue, OffsetName);
        auto ivarVisibility =
            (IVD->getAccessControl() == ObjCIvarDecl::Private ||
             IVD->getAccessControl() == ObjCIvarDecl::Package ||
             classDecl->getVisibility() == HiddenVisibility) ?
                    llvm::GlobalValue::HiddenVisibility :
                    llvm::GlobalValue::DefaultVisibility;
        OffsetVar->setVisibility(ivarVisibility);
        if (ivarVisibility != llvm::GlobalValue::HiddenVisibility)
          CGM.setGVProperties(OffsetVar, OID->getClassInterface());
        ivarBuilder.add(OffsetVar);
        // Ivar size
        ivarBuilder.addInt(Int32Ty,
            CGM.getContext().getTypeSizeInChars(ivarTy).getQuantity());
        // Alignment will be stored as a base-2 log of the alignment.
        unsigned align =
            llvm::Log2_32(Context.getTypeAlignInChars(ivarTy).getQuantity());
        // Objects that require more than 2^64-byte alignment should be impossible!
        assert(align < 64);
        // uint32_t flags;
        // Bits 0-1 are ownership.
        // Bit 2 indicates an extended type encoding
        // Bits 3-8 contain log2(aligment)
        ivarBuilder.addInt(Int32Ty,
            (align << 3) | (1<<2) |
            FlagsForOwnership(ivarTy.getQualifiers().getObjCLifetime()));
        ivarBuilder.finishAndAddTo(ivarArrayBuilder);
      }
      ivarArrayBuilder.finishAndAddTo(ivarListBuilder);
      auto ivarList = ivarListBuilder.finishAndCreateGlobal(".objc_ivar_list",
          CGM.getPointerAlign(), /*constant*/ false,
          llvm::GlobalValue::PrivateLinkage);
      classFields.add(ivarList);
    }
    // struct objc_method_list *methods
    SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
    InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
        OID->instmeth_end());
    for (auto *propImpl : OID->property_impls())
      if (propImpl->getPropertyImplementation() ==
          ObjCPropertyImplDecl::Synthesize) {
        auto addIfExists = [&](const ObjCMethodDecl *OMD) {
          if (OMD && OMD->hasBody())
            InstanceMethods.push_back(OMD);
        };
        addIfExists(propImpl->getGetterMethodDecl());
        addIfExists(propImpl->getSetterMethodDecl());
      }

    if (InstanceMethods.size() == 0)
      classFields.addNullPointer(PtrTy);
    else
      classFields.add(
          GenerateMethodList(className, "", InstanceMethods, false));

    // void *dtable;
    classFields.addNullPointer(PtrTy);
    // IMP cxx_construct;
    classFields.addNullPointer(PtrTy);
    // IMP cxx_destruct;
    classFields.addNullPointer(PtrTy);
    // struct objc_class *subclass_list
    classFields.addNullPointer(PtrTy);
    // struct objc_class *sibling_class
    classFields.addNullPointer(PtrTy);
    // struct objc_protocol_list *protocols;
    auto RuntimeProtocols =
        GetRuntimeProtocolList(classDecl->all_referenced_protocol_begin(),
                               classDecl->all_referenced_protocol_end());
    SmallVector<llvm::Constant *, 16> Protocols;
    for (const auto *I : RuntimeProtocols)
      Protocols.push_back(GenerateProtocolRef(I));

    if (Protocols.empty())
      classFields.addNullPointer(PtrTy);
    else
      classFields.add(GenerateProtocolList(Protocols));
    // struct reference_list *extra_data;
    classFields.addNullPointer(PtrTy);
    // long abi_version;
    classFields.addInt(LongTy, 0);
    // struct objc_property_list *properties
    classFields.add(GeneratePropertyList(OID, classDecl));

    llvm::GlobalVariable *classStruct =
      classFields.finishAndCreateGlobal(SymbolForClass(className),
        CGM.getPointerAlign(), false, llvm::GlobalValue::ExternalLinkage);

    auto *classRefSymbol = GetClassVar(className);
    classRefSymbol->setSection(sectionName<ClassReferenceSection>());
    classRefSymbol->setInitializer(classStruct);

    if (IsCOFF) {
      // we can't import a class struct.
      if (OID->getClassInterface()->hasAttr<DLLExportAttr>()) {
        classStruct->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
        cast<llvm::GlobalValue>(classRefSymbol)->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
      }

      if (SuperClass) {
        std::pair<llvm::GlobalVariable*, int> v{classStruct, 1};
        EarlyInitList.emplace_back(std::string(SuperClass->getName()),
                                   std::move(v));
      }

    }


    // Resolve the class aliases, if they exist.
    // FIXME: Class pointer aliases shouldn't exist!
    if (ClassPtrAlias) {
      ClassPtrAlias->replaceAllUsesWith(classStruct);
      ClassPtrAlias->eraseFromParent();
      ClassPtrAlias = nullptr;
    }
    if (auto Placeholder =
        TheModule.getNamedGlobal(SymbolForClass(className)))
      if (Placeholder != classStruct) {
        Placeholder->replaceAllUsesWith(classStruct);
        Placeholder->eraseFromParent();
        classStruct->setName(SymbolForClass(className));
      }
    if (MetaClassPtrAlias) {
      MetaClassPtrAlias->replaceAllUsesWith(metaclass);
      MetaClassPtrAlias->eraseFromParent();
      MetaClassPtrAlias = nullptr;
    }
    assert(classStruct->getName() == SymbolForClass(className));

    auto classInitRef = new llvm::GlobalVariable(TheModule,
        classStruct->getType(), false, llvm::GlobalValue::ExternalLinkage,
        classStruct, ManglePublicSymbol("OBJC_INIT_CLASS_") + className);
    classInitRef->setSection(sectionName<ClassSection>());
    CGM.addUsedGlobal(classInitRef);

    EmittedClass = true;
  }
  public:
    CGObjCGNUstep2(CodeGenModule &Mod) : CGObjCGNUstep(Mod, 10, 4, 2) {
      MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
                            PtrToObjCSuperTy, SelectorTy);
      SentInitializeFn.init(&CGM, "objc_send_initialize",
                            llvm::Type::getVoidTy(VMContext), IdTy);
      // struct objc_property
      // {
      //   const char *name;
      //   const char *attributes;
      //   const char *type;
      //   SEL getter;
      //   SEL setter;
      // }
      PropertyMetadataTy =
        llvm::StructType::get(CGM.getLLVMContext(),
            { PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
    }

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

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

      if (OMD->isClassMethod()) {
        const ObjCInterfaceDecl *OID = cast<ObjCInterfaceDecl>(CD);

        // 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);
      }

      llvm::MDBuilder MDHelper(CGM.getLLVMContext());
      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);

        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);
      }

      if (OMD->isClassMethod()) {
        // Prefix of the class type.
        auto *classStart =
            llvm::StructType::get(PtrTy, PtrTy, PtrTy, LongTy, LongTy);
        auto &astContext = CGM.getContext();
        // FIXME: The following few lines up to and including the call to
        // `CreateLoad` were known to miscompile when MSVC 19.40.33813 is used
        // to build Clang. When the bug is fixed in future MSVC releases, we
        // should revert these lines to their previous state. See discussion in
        // https://github.com/llvm/llvm-project/pull/102681
        llvm::Value *Val = Builder.CreateStructGEP(classStart, selfValue, 4);
        auto Align = CharUnits::fromQuantity(
            astContext.getTypeAlign(astContext.UnsignedLongTy));
        auto flags = Builder.CreateLoad(Address{Val, LongTy, Align});
        auto isInitialized =
            Builder.CreateAnd(flags, ClassFlags::ClassFlagInitialized);
        llvm::BasicBlock *notInitializedBlock =
            CGF.createBasicBlock("objc_direct_method.class_uninitialized");
        llvm::BasicBlock *initializedBlock =
            CGF.createBasicBlock("objc_direct_method.class_initialized");
        Builder.CreateCondBr(Builder.CreateICmpEQ(isInitialized, Zeros[0]),
                             notInitializedBlock, initializedBlock,
                             MDHelper.createUnlikelyBranchWeights());
        CGF.EmitBlock(notInitializedBlock);
        Builder.SetInsertPoint(notInitializedBlock);
        CGF.EmitRuntimeCall(SentInitializeFn, selfValue);
        Builder.CreateBr(initializedBlock);
        CGF.EmitBlock(initializedBlock);
        Builder.SetInsertPoint(initializedBlock);
      }

      // 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()));
      }
    }
};

const char *const CGObjCGNUstep2::SectionsBaseNames[8] =
{
"__objc_selectors",
"__objc_classes",
"__objc_class_refs",
"__objc_cats",
"__objc_protocols",
"__objc_protocol_refs",
"__objc_class_aliases",
"__objc_constant_string"
};

const char *const CGObjCGNUstep2::PECOFFSectionsBaseNames[8] =
{
".objcrt$SEL",
".objcrt$CLS",
".objcrt$CLR",
".objcrt$CAT",
".objcrt$PCL",
".objcrt$PCR",
".objcrt$CAL",
".objcrt$STR"
};

/// Support for the ObjFW runtime.
class CGObjCObjFW: public CGObjCGNU {
protected:
  /// The GCC ABI message lookup function.  Returns an IMP pointing to the
  /// method implementation for this message.
  LazyRuntimeFunction MsgLookupFn;
  /// stret lookup function.  While this does not seem to make sense at the
  /// first look, this is required to call the correct forwarding function.
  LazyRuntimeFunction MsgLookupFnSRet;
  /// The GCC ABI superclass message lookup function.  Takes a pointer to a
  /// structure describing the receiver and the class, and a selector as
  /// arguments.  Returns the IMP for the corresponding method.
  LazyRuntimeFunction MsgLookupSuperFn, MsgLookupSuperFnSRet;

  llvm::Value *LookupIMP(CodeGenFunction &CGF, llvm::Value *&Receiver,
                         llvm::Value *cmd, llvm::MDNode *node,
                         MessageSendInfo &MSI) override {
    CGBuilderTy &Builder = CGF.Builder;
    llvm::Value *args[] = {
            EnforceType(Builder, Receiver, IdTy),
            EnforceType(Builder, cmd, SelectorTy) };

    llvm::CallBase *imp;
    if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
      imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFnSRet, args);
    else
      imp = CGF.EmitRuntimeCallOrInvoke(MsgLookupFn, args);

    imp->setMetadata(msgSendMDKind, node);
    return imp;
  }

  llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
                              llvm::Value *cmd, MessageSendInfo &MSI) override {
    CGBuilderTy &Builder = CGF.Builder;
    llvm::Value *lookupArgs[] = {
        EnforceType(Builder, ObjCSuper.emitRawPointer(CGF), PtrToObjCSuperTy),
        cmd,
    };

    if (CGM.ReturnTypeUsesSRet(MSI.CallInfo))
      return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFnSRet, lookupArgs);
    else
      return CGF.EmitNounwindRuntimeCall(MsgLookupSuperFn, lookupArgs);
  }

  llvm::Value *GetClassNamed(CodeGenFunction &CGF, const std::string &Name,
                             bool isWeak) override {
    if (isWeak)
      return CGObjCGNU::GetClassNamed(CGF, Name, isWeak);

    EmitClassRef(Name);
    std::string SymbolName = "_OBJC_CLASS_" + Name;
    llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(SymbolName);
    if (!ClassSymbol)
      ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
                                             llvm::GlobalValue::ExternalLinkage,
                                             nullptr, SymbolName);
    return ClassSymbol;
  }

  void GenerateDirectMethodPrologue(
      CodeGenFunction &CGF, llvm::Function *Fn, const ObjCMethodDecl *OMD,
      const ObjCContainerDecl *CD) override {
    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()));
    }
  }

public:
  CGObjCObjFW(CodeGenModule &Mod): CGObjCGNU(Mod, 9, 3) {
    // IMP objc_msg_lookup(id, SEL);
    MsgLookupFn.init(&CGM, "objc_msg_lookup", IMPTy, IdTy, SelectorTy);
    MsgLookupFnSRet.init(&CGM, "objc_msg_lookup_stret", IMPTy, IdTy,
                         SelectorTy);
    // IMP objc_msg_lookup_super(struct objc_super*, SEL);
    MsgLookupSuperFn.init(&CGM, "objc_msg_lookup_super", IMPTy,
                          PtrToObjCSuperTy, SelectorTy);
    MsgLookupSuperFnSRet.init(&CGM, "objc_msg_lookup_super_stret", IMPTy,
                              PtrToObjCSuperTy, SelectorTy);
  }
};
} // end anonymous namespace

/// Emits a reference to a dummy variable which is emitted with each class.
/// This ensures that a linker error will be generated when trying to link
/// together modules where a referenced class is not defined.
void CGObjCGNU::EmitClassRef(const std::string &className) {
  std::string symbolRef = "__objc_class_ref_" + className;
  // Don't emit two copies of the same symbol
  if (TheModule.getGlobalVariable(symbolRef))
    return;
  std::string symbolName = "__objc_class_name_" + className;
  llvm::GlobalVariable *ClassSymbol = TheModule.getGlobalVariable(symbolName);
  if (!ClassSymbol) {
    ClassSymbol = new llvm::GlobalVariable(TheModule, LongTy, false,
                                           llvm::GlobalValue::ExternalLinkage,
                                           nullptr, symbolName);
  }
  new llvm::GlobalVariable(TheModule, ClassSymbol->getType(), true,
    llvm::GlobalValue::WeakAnyLinkage, ClassSymbol, symbolRef);
}

CGObjCGNU::CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
                     unsigned protocolClassVersion, unsigned classABI)
  : CGObjCRuntime(cgm), TheModule(CGM.getModule()),
    VMContext(cgm.getLLVMContext()), ClassPtrAlias(nullptr),
    MetaClassPtrAlias(nullptr), RuntimeVersion(runtimeABIVersion),
    ProtocolVersion(protocolClassVersion), ClassABIVersion(classABI) {

  msgSendMDKind = VMContext.getMDKindID("GNUObjCMessageSend");
  usesSEHExceptions =
      cgm.getContext().getTargetInfo().getTriple().isWindowsMSVCEnvironment();
  usesCxxExceptions =
      cgm.getContext().getTargetInfo().getTriple().isOSCygMing() &&
      isRuntime(ObjCRuntime::GNUstep, 2);

  CodeGenTypes &Types = CGM.getTypes();
  IntTy = cast<llvm::IntegerType>(
      Types.ConvertType(CGM.getContext().IntTy));
  LongTy = cast<llvm::IntegerType>(
      Types.ConvertType(CGM.getContext().LongTy));
  SizeTy = cast<llvm::IntegerType>(
      Types.ConvertType(CGM.getContext().getSizeType()));
  PtrDiffTy = cast<llvm::IntegerType>(
      Types.ConvertType(CGM.getContext().getPointerDiffType()));
  BoolTy = CGM.getTypes().ConvertType(CGM.getContext().BoolTy);

  Int8Ty = llvm::Type::getInt8Ty(VMContext);

  PtrTy = llvm::PointerType::getUnqual(cgm.getLLVMContext());
  PtrToIntTy = PtrTy;
  // C string type.  Used in lots of places.
  PtrToInt8Ty = PtrTy;
  ProtocolPtrTy = PtrTy;

  Zeros[0] = llvm::ConstantInt::get(LongTy, 0);
  Zeros[1] = Zeros[0];
  NULLPtr = llvm::ConstantPointerNull::get(PtrToInt8Ty);
  // Get the selector Type.
  QualType selTy = CGM.getContext().getObjCSelType();
  if (QualType() == selTy) {
    SelectorTy = PtrToInt8Ty;
    SelectorElemTy = Int8Ty;
  } else {
    SelectorTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(selTy));
    SelectorElemTy = CGM.getTypes().ConvertTypeForMem(selTy->getPointeeType());
  }

  Int32Ty = llvm::Type::getInt32Ty(VMContext);
  Int64Ty = llvm::Type::getInt64Ty(VMContext);

  IntPtrTy =
      CGM.getDataLayout().getPointerSizeInBits() == 32 ? Int32Ty : Int64Ty;

  // Object type
  QualType UnqualIdTy = CGM.getContext().getObjCIdType();
  ASTIdTy = CanQualType();
  if (UnqualIdTy != QualType()) {
    ASTIdTy = CGM.getContext().getCanonicalType(UnqualIdTy);
    IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
    IdElemTy = CGM.getTypes().ConvertTypeForMem(
        ASTIdTy.getTypePtr()->getPointeeType());
  } else {
    IdTy = PtrToInt8Ty;
    IdElemTy = Int8Ty;
  }
  PtrToIdTy = PtrTy;
  ProtocolTy = llvm::StructType::get(IdTy,
      PtrToInt8Ty, // name
      PtrToInt8Ty, // protocols
      PtrToInt8Ty, // instance methods
      PtrToInt8Ty, // class methods
      PtrToInt8Ty, // optional instance methods
      PtrToInt8Ty, // optional class methods
      PtrToInt8Ty, // properties
      PtrToInt8Ty);// optional properties

  // struct objc_property_gsv1
  // {
  //   const char *name;
  //   char attributes;
  //   char attributes2;
  //   char unused1;
  //   char unused2;
  //   const char *getter_name;
  //   const char *getter_types;
  //   const char *setter_name;
  //   const char *setter_types;
  // }
  PropertyMetadataTy = llvm::StructType::get(CGM.getLLVMContext(), {
      PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty, PtrToInt8Ty,
      PtrToInt8Ty, PtrToInt8Ty });

  ObjCSuperTy = llvm::StructType::get(IdTy, IdTy);
  PtrToObjCSuperTy = PtrTy;

  llvm::Type *VoidTy = llvm::Type::getVoidTy(VMContext);

  // void objc_exception_throw(id);
  ExceptionThrowFn.init(&CGM, "objc_exception_throw", VoidTy, IdTy);
  ExceptionReThrowFn.init(&CGM,
                          usesCxxExceptions ? "objc_exception_rethrow"
                                            : "objc_exception_throw",
                          VoidTy, IdTy);
  // int objc_sync_enter(id);
  SyncEnterFn.init(&CGM, "objc_sync_enter", IntTy, IdTy);
  // int objc_sync_exit(id);
  SyncExitFn.init(&CGM, "objc_sync_exit", IntTy, IdTy);

  // void objc_enumerationMutation (id)
  EnumerationMutationFn.init(&CGM, "objc_enumerationMutation", VoidTy, IdTy);

  // id objc_getProperty(id, SEL, ptrdiff_t, BOOL)
  GetPropertyFn.init(&CGM, "objc_getProperty", IdTy, IdTy, SelectorTy,
                     PtrDiffTy, BoolTy);
  // void objc_setProperty(id, SEL, ptrdiff_t, id, BOOL, BOOL)
  SetPropertyFn.init(&CGM, "objc_setProperty", VoidTy, IdTy, SelectorTy,
                     PtrDiffTy, IdTy, BoolTy, BoolTy);
  // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL)
  GetStructPropertyFn.init(&CGM, "objc_getPropertyStruct", VoidTy, PtrTy, PtrTy,
                           PtrDiffTy, BoolTy, BoolTy);
  // void objc_setPropertyStruct(void*, void*, ptrdiff_t, BOOL, BOOL)
  SetStructPropertyFn.init(&CGM, "objc_setPropertyStruct", VoidTy, PtrTy, PtrTy,
                           PtrDiffTy, BoolTy, BoolTy);

  // IMP type
  IMPTy = PtrTy;

  const LangOptions &Opts = CGM.getLangOpts();
  if ((Opts.getGC() != LangOptions::NonGC) || Opts.ObjCAutoRefCount)
    RuntimeVersion = 10;

  // Don't bother initialising the GC stuff unless we're compiling in GC mode
  if (Opts.getGC() != LangOptions::NonGC) {
    // This is a bit of an hack.  We should sort this out by having a proper
    // CGObjCGNUstep subclass for GC, but we may want to really support the old
    // ABI and GC added in ObjectiveC2.framework, so we fudge it a bit for now
    // Get selectors needed in GC mode
    RetainSel = GetNullarySelector("retain", CGM.getContext());
    ReleaseSel = GetNullarySelector("release", CGM.getContext());
    AutoreleaseSel = GetNullarySelector("autorelease", CGM.getContext());

    // Get functions needed in GC mode

    // id objc_assign_ivar(id, id, ptrdiff_t);
    IvarAssignFn.init(&CGM, "objc_assign_ivar", IdTy, IdTy, IdTy, PtrDiffTy);
    // id objc_assign_strongCast (id, id*)
    StrongCastAssignFn.init(&CGM, "objc_assign_strongCast", IdTy, IdTy,
                            PtrToIdTy);
    // id objc_assign_global(id, id*);
    GlobalAssignFn.init(&CGM, "objc_assign_global", IdTy, IdTy, PtrToIdTy);
    // id objc_assign_weak(id, id*);
    WeakAssignFn.init(&CGM, "objc_assign_weak", IdTy, IdTy, PtrToIdTy);
    // id objc_read_weak(id*);
    WeakReadFn.init(&CGM, "objc_read_weak", IdTy, PtrToIdTy);
    // void *objc_memmove_collectable(void*, void *, size_t);
    MemMoveFn.init(&CGM, "objc_memmove_collectable", PtrTy, PtrTy, PtrTy,
                   SizeTy);
  }
}

llvm::Value *CGObjCGNU::GetClassNamed(CodeGenFunction &CGF,
                                      const std::string &Name, bool isWeak) {
  llvm::Constant *ClassName = MakeConstantString(Name);
  // With the incompatible ABI, this will need to be replaced with a direct
  // reference to the class symbol.  For the compatible nonfragile ABI we are
  // still performing this lookup at run time but emitting the symbol for the
  // class externally so that we can make the switch later.
  //
  // Libobjc2 contains an LLVM pass that replaces calls to objc_lookup_class
  // with memoized versions or with static references if it's safe to do so.
  if (!isWeak)
    EmitClassRef(Name);

  llvm::FunctionCallee ClassLookupFn = CGM.CreateRuntimeFunction(
      llvm::FunctionType::get(IdTy, PtrToInt8Ty, true), "objc_lookup_class");
  return CGF.EmitNounwindRuntimeCall(ClassLookupFn, ClassName);
}

// This has to perform the lookup every time, since posing and related
// techniques can modify the name -> class mapping.
llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF,
                                 const ObjCInterfaceDecl *OID) {
  auto *Value =
      GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported());
  if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value))
    CGM.setGVProperties(ClassSymbol, OID);
  return Value;
}

llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) {
  auto *Value  = GetClassNamed(CGF, "NSAutoreleasePool", false);
  if (CGM.getTriple().isOSBinFormatCOFF()) {
    if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) {
      IdentifierInfo &II = CGF.CGM.getContext().Idents.get("NSAutoreleasePool");
      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;

      CGM.setGVProperties(ClassSymbol, VD);
    }
  }
  return Value;
}

llvm::Value *CGObjCGNU::GetTypedSelector(CodeGenFunction &CGF, Selector Sel,
                                         const std::string &TypeEncoding) {
  SmallVectorImpl<TypedSelector> &Types = SelectorTable[Sel];
  llvm::GlobalAlias *SelValue = nullptr;

  for (const TypedSelector &Type : Types) {
    if (Type.first == TypeEncoding) {
      SelValue = Type.second;
      break;
    }
  }
  if (!SelValue) {
    SelValue = llvm::GlobalAlias::create(SelectorElemTy, 0,
                                         llvm::GlobalValue::PrivateLinkage,
                                         ".objc_selector_" + Sel.getAsString(),
                                         &TheModule);
    Types.emplace_back(TypeEncoding, SelValue);
  }

  return SelValue;
}

Address CGObjCGNU::GetAddrOfSelector(CodeGenFunction &CGF, Selector Sel) {
  llvm::Value *SelValue = GetSelector(CGF, Sel);

  // Store it to a temporary.  Does this satisfy the semantics of
  // GetAddrOfSelector?  Hopefully.
  Address tmp = CGF.CreateTempAlloca(SelValue->getType(),
                                     CGF.getPointerAlign());
  CGF.Builder.CreateStore(SelValue, tmp);
  return tmp;
}

llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel) {
  return GetTypedSelector(CGF, Sel, std::string());
}

llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF,
                                    const ObjCMethodDecl *Method) {
  std::string SelTypes = CGM.getContext().getObjCEncodingForMethodDecl(Method);
  return GetTypedSelector(CGF, Method->getSelector(), SelTypes);
}

llvm::Constant *CGObjCGNU::GetEHType(QualType T) {
  if (T->isObjCIdType() || T->isObjCQualifiedIdType()) {
    // With the old ABI, there was only one kind of catchall, which broke
    // foreign exceptions.  With the new ABI, we use __objc_id_typeinfo as
    // a pointer indicating object catchalls, and NULL to indicate real
    // catchalls
    if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
      return MakeConstantString("@id");
    } else {
      return nullptr;
    }
  }

  // All other types should be Objective-C interface pointer types.
  const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>();
  assert(OPT && "Invalid @catch type.");
  const ObjCInterfaceDecl *IDecl = OPT->getObjectType()->getInterface();
  assert(IDecl && "Invalid @catch type.");
  return MakeConstantString(IDecl->getIdentifier()->getName());
}

llvm::Constant *CGObjCGNUstep::GetEHType(QualType T) {
  if (usesSEHExceptions)
    return CGM.getCXXABI().getAddrOfRTTIDescriptor(T);

  if (!CGM.getLangOpts().CPlusPlus && !usesCxxExceptions)
    return CGObjCGNU::GetEHType(T);

  // For Objective-C++, we want to provide the ability to catch both C++ and
  // Objective-C objects in the same function.

  // There's a particular fixed type info for 'id'.
  if (T->isObjCIdType() ||
      T->isObjCQualifiedIdType()) {
    llvm::Constant *IDEHType =
      CGM.getModule().getGlobalVariable("__objc_id_type_info");
    if (!IDEHType)
      IDEHType =
        new llvm::GlobalVariable(CGM.getModule(), PtrToInt8Ty,
                                 false,
                                 llvm::GlobalValue::ExternalLinkage,
                                 nullptr, "__objc_id_type_info");
    return IDEHType;
  }

  const ObjCObjectPointerType *PT =
    T->getAs<ObjCObjectPointerType>();
  assert(PT && "Invalid @catch type.");
  const ObjCInterfaceType *IT = PT->getInterfaceType();
  assert(IT && "Invalid @catch type.");
  std::string className =
      std::string(IT->getDecl()->getIdentifier()->getName());

  std::string typeinfoName = "__objc_eh_typeinfo_" + className;

  // Return the existing typeinfo if it exists
  if (llvm::Constant *typeinfo = TheModule.getGlobalVariable(typeinfoName))
    return typeinfo;

  // Otherwise create it.

  // vtable for gnustep::libobjc::__objc_class_type_info
  // It's quite ugly hard-coding this.  Ideally we'd generate it using the host
  // platform's name mangling.
  const char *vtableName = "_ZTVN7gnustep7libobjc22__objc_class_type_infoE";
  auto *Vtable = TheModule.getGlobalVariable(vtableName);
  if (!Vtable) {
    Vtable = new llvm::GlobalVariable(TheModule, PtrToInt8Ty, true,
                                      llvm::GlobalValue::ExternalLinkage,
                                      nullptr, vtableName);
  }
  llvm::Constant *Two = llvm::ConstantInt::get(IntTy, 2);
  auto *BVtable =
      llvm::ConstantExpr::getGetElementPtr(Vtable->getValueType(), Vtable, Two);

  llvm::Constant *typeName =
    ExportUniqueString(className, "__objc_eh_typename_");

  ConstantInitBuilder builder(CGM);
  auto fields = builder.beginStruct();
  fields.add(BVtable);
  fields.add(typeName);
  llvm::Constant *TI =
    fields.finishAndCreateGlobal("__objc_eh_typeinfo_" + className,
                                 CGM.getPointerAlign(),
                                 /*constant*/ false,
                                 llvm::GlobalValue::LinkOnceODRLinkage);
  return TI;
}

/// Generate an NSConstantString object.
ConstantAddress CGObjCGNU::GenerateConstantString(const StringLiteral *SL) {

  std::string Str = SL->getString().str();
  CharUnits Align = CGM.getPointerAlign();

  // Look for an existing one
  llvm::StringMap<llvm::Constant*>::iterator old = ObjCStrings.find(Str);
  if (old != ObjCStrings.end())
    return ConstantAddress(old->getValue(), Int8Ty, Align);

  StringRef StringClass = CGM.getLangOpts().ObjCConstantStringClass;

  if (StringClass.empty()) StringClass = "NSConstantString";

  std::string Sym = "_OBJC_CLASS_";
  Sym += StringClass;

  llvm::Constant *isa = TheModule.getNamedGlobal(Sym);

  if (!isa)
    isa = new llvm::GlobalVariable(TheModule, IdTy, /* isConstant */ false,
                                   llvm::GlobalValue::ExternalWeakLinkage,
                                   nullptr, Sym);

  ConstantInitBuilder Builder(CGM);
  auto Fields = Builder.beginStruct();
  Fields.add(isa);
  Fields.add(MakeConstantString(Str));
  Fields.addInt(IntTy, Str.size());
  llvm::Constant *ObjCStr = Fields.finishAndCreateGlobal(".objc_str", Align);
  ObjCStrings[Str] = ObjCStr;
  ConstantStrings.push_back(ObjCStr);
  return ConstantAddress(ObjCStr, Int8Ty, Align);
}

///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.
RValue
CGObjCGNU::GenerateMessageSendSuper(CodeGenFunction &CGF,
                                    ReturnValueSlot Return,
                                    QualType ResultType,
                                    Selector Sel,
                                    const ObjCInterfaceDecl *Class,
                                    bool isCategoryImpl,
                                    llvm::Value *Receiver,
                                    bool IsClassMessage,
                                    const CallArgList &CallArgs,
                                    const ObjCMethodDecl *Method) {
  CGBuilderTy &Builder = CGF.Builder;
  if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
    if (Sel == RetainSel || Sel == AutoreleaseSel) {
      return RValue::get(EnforceType(Builder, Receiver,
                  CGM.getTypes().ConvertType(ResultType)));
    }
    if (Sel == ReleaseSel) {
      return RValue::get(nullptr);
    }
  }

  llvm::Value *cmd = GetSelector(CGF, Sel);
  CallArgList ActualArgs;

  ActualArgs.add(RValue::get(EnforceType(Builder, Receiver, IdTy)), ASTIdTy);
  ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
  ActualArgs.addFrom(CallArgs);

  MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);

  llvm::Value *ReceiverClass = nullptr;
  bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
  if (isV2ABI) {
    ReceiverClass = GetClassNamed(CGF,
        Class->getSuperClass()->getNameAsString(), /*isWeak*/false);
    if (IsClassMessage)  {
      // Load the isa pointer of the superclass is this is a class method.
      ReceiverClass =
        Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.getPointerAlign());
    }
    ReceiverClass = EnforceType(Builder, ReceiverClass, IdTy);
  } else {
    if (isCategoryImpl) {
      llvm::FunctionCallee classLookupFunction = nullptr;
      if (IsClassMessage)  {
        classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
              IdTy, PtrTy, true), "objc_get_meta_class");
      } else {
        classLookupFunction = CGM.CreateRuntimeFunction(llvm::FunctionType::get(
              IdTy, PtrTy, true), "objc_get_class");
      }
      ReceiverClass = Builder.CreateCall(classLookupFunction,
          MakeConstantString(Class->getNameAsString()));
    } else {
      // Set up global aliases for the metaclass or class pointer if they do not
      // already exist.  These will are forward-references which will be set to
      // pointers to the class and metaclass structure created for the runtime
      // load function.  To send a message to super, we look up the value of the
      // super_class pointer from either the class or metaclass structure.
      if (IsClassMessage)  {
        if (!MetaClassPtrAlias) {
          MetaClassPtrAlias = llvm::GlobalAlias::create(
              IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
              ".objc_metaclass_ref" + Class->getNameAsString(), &TheModule);
        }
        ReceiverClass = MetaClassPtrAlias;
      } else {
        if (!ClassPtrAlias) {
          ClassPtrAlias = llvm::GlobalAlias::create(
              IdElemTy, 0, llvm::GlobalValue::InternalLinkage,
              ".objc_class_ref" + Class->getNameAsString(), &TheModule);
        }
        ReceiverClass = ClassPtrAlias;
      }
    }
    // Cast the pointer to a simplified version of the class structure
    llvm::Type *CastTy = llvm::StructType::get(IdTy, IdTy);
    // Get the superclass pointer
    ReceiverClass = Builder.CreateStructGEP(CastTy, ReceiverClass, 1);
    // Load the superclass pointer
    ReceiverClass =
      Builder.CreateAlignedLoad(IdTy, ReceiverClass, CGF.getPointerAlign());
  }
  // Construct the structure used to look up the IMP
  llvm::StructType *ObjCSuperTy =
      llvm::StructType::get(Receiver->getType(), IdTy);

  Address ObjCSuper = CGF.CreateTempAlloca(ObjCSuperTy,
                              CGF.getPointerAlign());

  Builder.CreateStore(Receiver, Builder.CreateStructGEP(ObjCSuper, 0));
  Builder.CreateStore(ReceiverClass, Builder.CreateStructGEP(ObjCSuper, 1));

  // Get the IMP
  llvm::Value *imp = LookupIMPSuper(CGF, ObjCSuper, cmd, MSI);
  imp = EnforceType(Builder, imp, MSI.MessengerType);

  llvm::Metadata *impMD[] = {
      llvm::MDString::get(VMContext, Sel.getAsString()),
      llvm::MDString::get(VMContext, Class->getSuperClass()->getNameAsString()),
      llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
          llvm::Type::getInt1Ty(VMContext), IsClassMessage))};
  llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);

  CGCallee callee(CGCalleeInfo(), imp);

  llvm::CallBase *call;
  RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
  call->setMetadata(msgSendMDKind, node);
  return msgRet;
}

/// Generate code for a message send expression.
RValue
CGObjCGNU::GenerateMessageSend(CodeGenFunction &CGF,
                               ReturnValueSlot Return,
                               QualType ResultType,
                               Selector Sel,
                               llvm::Value *Receiver,
                               const CallArgList &CallArgs,
                               const ObjCInterfaceDecl *Class,
                               const ObjCMethodDecl *Method) {
  CGBuilderTy &Builder = CGF.Builder;

  // Strip out message sends to retain / release in GC mode
  if (CGM.getLangOpts().getGC() == LangOptions::GCOnly) {
    if (Sel == RetainSel || Sel == AutoreleaseSel) {
      return RValue::get(EnforceType(Builder, Receiver,
                  CGM.getTypes().ConvertType(ResultType)));
    }
    if (Sel == ReleaseSel) {
      return RValue::get(nullptr);
    }
  }

  bool isDirect = Method && Method->isDirectMethod();

  IdTy = cast<llvm::PointerType>(CGM.getTypes().ConvertType(ASTIdTy));
  llvm::Value *cmd;
  if (!isDirect) {
    if (Method)
      cmd = GetSelector(CGF, Method);
    else
      cmd = GetSelector(CGF, Sel);
    cmd = EnforceType(Builder, cmd, SelectorTy);
  }

  Receiver = EnforceType(Builder, Receiver, IdTy);

  llvm::Metadata *impMD[] = {
      llvm::MDString::get(VMContext, Sel.getAsString()),
      llvm::MDString::get(VMContext, Class ? Class->getNameAsString() : ""),
      llvm::ConstantAsMetadata::get(llvm::ConstantInt::get(
          llvm::Type::getInt1Ty(VMContext), Class != nullptr))};
  llvm::MDNode *node = llvm::MDNode::get(VMContext, impMD);

  CallArgList ActualArgs;
  ActualArgs.add(RValue::get(Receiver), ASTIdTy);
  if (!isDirect)
    ActualArgs.add(RValue::get(cmd), CGF.getContext().getObjCSelType());
  ActualArgs.addFrom(CallArgs);

  MessageSendInfo MSI = getMessageSendInfo(Method, ResultType, ActualArgs);

  // Message sends are expected to return a zero value when the
  // receiver is nil.  At one point, this was only guaranteed for
  // simple integer and pointer types, but expectations have grown
  // over time.
  //
  // Given a nil receiver, the GNU runtime's message lookup will
  // return a stub function that simply sets various return-value
  // registers to zero and then returns.  That's good enough for us
  // if and only if (1) the calling conventions of that stub are
  // compatible with the signature we're using and (2) the registers
  // it sets are sufficient to produce a zero value of the return type.
  // Rather than doing a whole target-specific analysis, we assume it
  // only works for void, integer, and pointer types, and in all
  // other cases we do an explicit nil check is emitted code.  In
  // addition to ensuring we produce a zero value for other types, this
  // sidesteps the few outright CC incompatibilities we know about that
  // could otherwise lead to crashes, like when a method is expected to
  // return on the x87 floating point stack or adjust the stack pointer
  // because of an indirect return.
  bool hasParamDestroyedInCallee = false;
  bool requiresExplicitZeroResult = false;
  bool requiresNilReceiverCheck = [&] {
    // We never need a check if we statically know the receiver isn't nil.
    if (!canMessageReceiverBeNull(CGF, Method, /*IsSuper*/ false,
                                  Class, Receiver))
      return false;

    // If there's a consumed argument, we need a nil check.
    if (Method && Method->hasParamDestroyedInCallee()) {
      hasParamDestroyedInCallee = true;
    }

    // If the return value isn't flagged as unused, and the result
    // type isn't in our narrow set where we assume compatibility,
    // we need a nil check to ensure a nil value.
    if (!Return.isUnused()) {
      if (ResultType->isVoidType()) {
        // void results are definitely okay.
      } else if (ResultType->hasPointerRepresentation() &&
                 CGM.getTypes().isZeroInitializable(ResultType)) {
        // Pointer types should be fine as long as they have
        // bitwise-zero null pointers.  But do we need to worry
        // about unusual address spaces?
      } else if (ResultType->isIntegralOrEnumerationType()) {
        // Bitwise zero should always be zero for integral types.
        // FIXME: we probably need a size limit here, but we've
        // never imposed one before
      } else {
        // Otherwise, use an explicit check just to be sure, unless we're
        // calling a direct method, where the implementation does this for us.
        requiresExplicitZeroResult = !isDirect;
      }
    }

    return hasParamDestroyedInCallee || requiresExplicitZeroResult;
  }();

  // We will need to explicitly zero-initialize an aggregate result slot
  // if we generally require explicit zeroing and we have an aggregate
  // result.
  bool requiresExplicitAggZeroing =
    requiresExplicitZeroResult && CGF.hasAggregateEvaluationKind(ResultType);

  // The block we're going to end up in after any message send or nil path.
  llvm::BasicBlock *continueBB = nullptr;
  // The block that eventually branched to continueBB along the nil path.
  llvm::BasicBlock *nilPathBB = nullptr;
  // The block to do explicit work in along the nil path, if necessary.
  llvm::BasicBlock *nilCleanupBB = nullptr;

  // Emit the nil-receiver check.
  if (requiresNilReceiverCheck) {
    llvm::BasicBlock *messageBB = CGF.createBasicBlock("msgSend");
    continueBB = CGF.createBasicBlock("continue");

    // If we need to zero-initialize an aggregate result or destroy
    // consumed arguments, we'll need a separate cleanup block.
    // Otherwise we can just branch directly to the continuation block.
    if (requiresExplicitAggZeroing || hasParamDestroyedInCallee) {
      nilCleanupBB = CGF.createBasicBlock("nilReceiverCleanup");
    } else {
      nilPathBB = Builder.GetInsertBlock();
    }

    llvm::Value *isNil = Builder.CreateICmpEQ(Receiver,
            llvm::Constant::getNullValue(Receiver->getType()));
    Builder.CreateCondBr(isNil, nilCleanupBB ? nilCleanupBB : continueBB,
                         messageBB);
    CGF.EmitBlock(messageBB);
  }

  // Get the IMP to call
  llvm::Value *imp;

  // If this is a direct method, just emit it here.
  if (isDirect)
    imp = GenerateMethod(Method, Method->getClassInterface());
  else
    // If we have non-legacy dispatch specified, we try using the
    // objc_msgSend() functions.  These are not supported on all platforms
    // (or all runtimes on a given platform), so we
    switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
    case CodeGenOptions::Legacy:
      imp = LookupIMP(CGF, Receiver, cmd, node, MSI);
      break;
    case CodeGenOptions::Mixed:
    case CodeGenOptions::NonLegacy:
      StringRef name = "objc_msgSend";
      if (CGM.ReturnTypeUsesFPRet(ResultType)) {
        name = "objc_msgSend_fpret";
      } else if (CGM.ReturnTypeUsesSRet(MSI.CallInfo)) {
        name = "objc_msgSend_stret";

        // The address of the memory block is be passed in x8 for POD type,
        // or in x0 for non-POD type (marked as inreg).
        bool shouldCheckForInReg =
            CGM.getContext()
                .getTargetInfo()
                .getTriple()
                .isWindowsMSVCEnvironment() &&
            CGM.getContext().getTargetInfo().getTriple().isAArch64();
        if (shouldCheckForInReg && CGM.ReturnTypeHasInReg(MSI.CallInfo)) {
          name = "objc_msgSend_stret2";
        }
      }
      // The actual types here don't matter - we're going to bitcast the
      // function anyway
      imp = CGM.CreateRuntimeFunction(llvm::FunctionType::get(IdTy, IdTy, true),
                                      name)
                .getCallee();
    }

  // Reset the receiver in case the lookup modified it
  ActualArgs[0] = CallArg(RValue::get(Receiver), ASTIdTy);

  imp = EnforceType(Builder, imp, MSI.MessengerType);

  llvm::CallBase *call;
  CGCallee callee(CGCalleeInfo(), imp);
  RValue msgRet = CGF.EmitCall(MSI.CallInfo, callee, Return, ActualArgs, &call);
  if (!isDirect)
    call->setMetadata(msgSendMDKind, node);

  if (requiresNilReceiverCheck) {
    llvm::BasicBlock *nonNilPathBB = CGF.Builder.GetInsertBlock();
    CGF.Builder.CreateBr(continueBB);

    // Emit the nil path if we decided it was necessary above.
    if (nilCleanupBB) {
      CGF.EmitBlock(nilCleanupBB);

      if (hasParamDestroyedInCallee) {
        destroyCalleeDestroyedArguments(CGF, Method, CallArgs);
      }

      if (requiresExplicitAggZeroing) {
        assert(msgRet.isAggregate());
        Address addr = msgRet.getAggregateAddress();
        CGF.EmitNullInitialization(addr, ResultType);
      }

      nilPathBB = CGF.Builder.GetInsertBlock();
      CGF.Builder.CreateBr(continueBB);
    }

    // Enter the continuation block and emit a phi if required.
    CGF.EmitBlock(continueBB);
    if (msgRet.isScalar()) {
      // If the return type is void, do nothing
      if (llvm::Value *v = msgRet.getScalarVal()) {
        llvm::PHINode *phi = Builder.CreatePHI(v->getType(), 2);
        phi->addIncoming(v, nonNilPathBB);
        phi->addIncoming(CGM.EmitNullConstant(ResultType), nilPathBB);
        msgRet = RValue::get(phi);
      }
    } else if (msgRet.isAggregate()) {
      // Aggregate zeroing is handled in nilCleanupBB when it's required.
    } else /* isComplex() */ {
      std::pair<llvm::Value*,llvm::Value*> v = msgRet.getComplexVal();
      llvm::PHINode *phi = Builder.CreatePHI(v.first->getType(), 2);
      phi->addIncoming(v.first, nonNilPathBB);
      phi->addIncoming(llvm::Constant::getNullValue(v.first->getType()),
                       nilPathBB);
      llvm::PHINode *phi2 = Builder.CreatePHI(v.second->getType(), 2);
      phi2->addIncoming(v.second, nonNilPathBB);
      phi2->addIncoming(llvm::Constant::getNullValue(v.second->getType()),
                        nilPathBB);
      msgRet = RValue::getComplex(phi, phi2);
    }
  }
  return msgRet;
}

/// Generates a MethodList.  Used in construction of a objc_class and
/// objc_category structures.
llvm::Constant *CGObjCGNU::
GenerateMethodList(StringRef ClassName,
                   StringRef CategoryName,
                   ArrayRef<const ObjCMethodDecl*> Methods,
                   bool isClassMethodList) {
  if (Methods.empty())
    return NULLPtr;

  ConstantInitBuilder Builder(CGM);

  auto MethodList = Builder.beginStruct();
  MethodList.addNullPointer(CGM.Int8PtrTy);
  MethodList.addInt(Int32Ty, Methods.size());

  // Get the method structure type.
  llvm::StructType *ObjCMethodTy =
    llvm::StructType::get(CGM.getLLVMContext(), {
      PtrToInt8Ty, // Really a selector, but the runtime creates it us.
      PtrToInt8Ty, // Method types
      IMPTy        // Method pointer
    });
  bool isV2ABI = isRuntime(ObjCRuntime::GNUstep, 2);
  if (isV2ABI) {
    // size_t size;
    const llvm::DataLayout &DL = TheModule.getDataLayout();
    MethodList.addInt(SizeTy, DL.getTypeSizeInBits(ObjCMethodTy) /
                                  CGM.getContext().getCharWidth());
    ObjCMethodTy =
      llvm::StructType::get(CGM.getLLVMContext(), {
        IMPTy,       // Method pointer
        PtrToInt8Ty, // Selector
        PtrToInt8Ty  // Extended type encoding
      });
  } else {
    ObjCMethodTy =
      llvm::StructType::get(CGM.getLLVMContext(), {
        PtrToInt8Ty, // Really a selector, but the runtime creates it us.
        PtrToInt8Ty, // Method types
        IMPTy        // Method pointer
      });
  }
  auto MethodArray = MethodList.beginArray();
  ASTContext &Context = CGM.getContext();
  for (const auto *OMD : Methods) {
    llvm::Constant *FnPtr =
      TheModule.getFunction(getSymbolNameForMethod(OMD));
    assert(FnPtr && "Can't generate metadata for method that doesn't exist");
    auto Method = MethodArray.beginStruct(ObjCMethodTy);
    if (isV2ABI) {
      Method.add(FnPtr);
      Method.add(GetConstantSelector(OMD->getSelector(),
          Context.getObjCEncodingForMethodDecl(OMD)));
      Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD, true)));
    } else {
      Method.add(MakeConstantString(OMD->getSelector().getAsString()));
      Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(OMD)));
      Method.add(FnPtr);
    }
    Method.finishAndAddTo(MethodArray);
  }
  MethodArray.finishAndAddTo(MethodList);

  // Create an instance of the structure
  return MethodList.finishAndCreateGlobal(".objc_method_list",
                                          CGM.getPointerAlign());
}

/// Generates an IvarList.  Used in construction of a objc_class.
llvm::Constant *CGObjCGNU::
GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
                 ArrayRef<llvm::Constant *> IvarTypes,
                 ArrayRef<llvm::Constant *> IvarOffsets,
                 ArrayRef<llvm::Constant *> IvarAlign,
                 ArrayRef<Qualifiers::ObjCLifetime> IvarOwnership) {
  if (IvarNames.empty())
    return NULLPtr;

  ConstantInitBuilder Builder(CGM);

  // Structure containing array count followed by array.
  auto IvarList = Builder.beginStruct();
  IvarList.addInt(IntTy, (int)IvarNames.size());

  // Get the ivar structure type.
  llvm::StructType *ObjCIvarTy =
      llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, IntTy);

  // Array of ivar structures.
  auto Ivars = IvarList.beginArray(ObjCIvarTy);
  for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
    auto Ivar = Ivars.beginStruct(ObjCIvarTy);
    Ivar.add(IvarNames[i]);
    Ivar.add(IvarTypes[i]);
    Ivar.add(IvarOffsets[i]);
    Ivar.finishAndAddTo(Ivars);
  }
  Ivars.finishAndAddTo(IvarList);

  // Create an instance of the structure
  return IvarList.finishAndCreateGlobal(".objc_ivar_list",
                                        CGM.getPointerAlign());
}

/// Generate a class structure
llvm::Constant *CGObjCGNU::GenerateClassStructure(
    llvm::Constant *MetaClass,
    llvm::Constant *SuperClass,
    unsigned info,
    const char *Name,
    llvm::Constant *Version,
    llvm::Constant *InstanceSize,
    llvm::Constant *IVars,
    llvm::Constant *Methods,
    llvm::Constant *Protocols,
    llvm::Constant *IvarOffsets,
    llvm::Constant *Properties,
    llvm::Constant *StrongIvarBitmap,
    llvm::Constant *WeakIvarBitmap,
    bool isMeta) {
  // Set up the class structure
  // Note:  Several of these are char*s when they should be ids.  This is
  // because the runtime performs this translation on load.
  //
  // Fields marked New ABI are part of the GNUstep runtime.  We emit them
  // anyway; the classes will still work with the GNU runtime, they will just
  // be ignored.
  llvm::StructType *ClassTy = llvm::StructType::get(
      PtrToInt8Ty,        // isa
      PtrToInt8Ty,        // super_class
      PtrToInt8Ty,        // name
      LongTy,             // version
      LongTy,             // info
      LongTy,             // instance_size
      IVars->getType(),   // ivars
      Methods->getType(), // methods
      // These are all filled in by the runtime, so we pretend
      PtrTy, // dtable
      PtrTy, // subclass_list
      PtrTy, // sibling_class
      PtrTy, // protocols
      PtrTy, // gc_object_type
      // New ABI:
      LongTy,                 // abi_version
      IvarOffsets->getType(), // ivar_offsets
      Properties->getType(),  // properties
      IntPtrTy,               // strong_pointers
      IntPtrTy                // weak_pointers
      );

  ConstantInitBuilder Builder(CGM);
  auto Elements = Builder.beginStruct(ClassTy);

  // Fill in the structure

  // isa
  Elements.add(MetaClass);
  // super_class
  Elements.add(SuperClass);
  // name
  Elements.add(MakeConstantString(Name, ".class_name"));
  // version
  Elements.addInt(LongTy, 0);
  // info
  Elements.addInt(LongTy, info);
  // instance_size
  if (isMeta) {
    const llvm::DataLayout &DL = TheModule.getDataLayout();
    Elements.addInt(LongTy, DL.getTypeSizeInBits(ClassTy) /
                                CGM.getContext().getCharWidth());
  } else
    Elements.add(InstanceSize);
  // ivars
  Elements.add(IVars);
  // methods
  Elements.add(Methods);
  // These are all filled in by the runtime, so we pretend
  // dtable
  Elements.add(NULLPtr);
  // subclass_list
  Elements.add(NULLPtr);
  // sibling_class
  Elements.add(NULLPtr);
  // protocols
  Elements.add(Protocols);
  // gc_object_type
  Elements.add(NULLPtr);
  // abi_version
  Elements.addInt(LongTy, ClassABIVersion);
  // ivar_offsets
  Elements.add(IvarOffsets);
  // properties
  Elements.add(Properties);
  // strong_pointers
  Elements.add(StrongIvarBitmap);
  // weak_pointers
  Elements.add(WeakIvarBitmap);
  // Create an instance of the structure
  // This is now an externally visible symbol, so that we can speed up class
  // messages in the next ABI.  We may already have some weak references to
  // this, so check and fix them properly.
  std::string ClassSym((isMeta ? "_OBJC_METACLASS_": "_OBJC_CLASS_") +
          std::string(Name));
  llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
  llvm::Constant *Class =
    Elements.finishAndCreateGlobal(ClassSym, CGM.getPointerAlign(), false,
                                   llvm::GlobalValue::ExternalLinkage);
  if (ClassRef) {
    ClassRef->replaceAllUsesWith(Class);
    ClassRef->removeFromParent();
    Class->setName(ClassSym);
  }
  return Class;
}

llvm::Constant *CGObjCGNU::
GenerateProtocolMethodList(ArrayRef<const ObjCMethodDecl*> Methods) {
  // Get the method structure type.
  llvm::StructType *ObjCMethodDescTy =
    llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
  ASTContext &Context = CGM.getContext();
  ConstantInitBuilder Builder(CGM);
  auto MethodList = Builder.beginStruct();
  MethodList.addInt(IntTy, Methods.size());
  auto MethodArray = MethodList.beginArray(ObjCMethodDescTy);
  for (auto *M : Methods) {
    auto Method = MethodArray.beginStruct(ObjCMethodDescTy);
    Method.add(MakeConstantString(M->getSelector().getAsString()));
    Method.add(MakeConstantString(Context.getObjCEncodingForMethodDecl(M)));
    Method.finishAndAddTo(MethodArray);
  }
  MethodArray.finishAndAddTo(MethodList);
  return MethodList.finishAndCreateGlobal(".objc_method_list",
                                          CGM.getPointerAlign());
}

// Create the protocol list structure used in classes, categories and so on
llvm::Constant *
CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {

  ConstantInitBuilder Builder(CGM);
  auto ProtocolList = Builder.beginStruct();
  ProtocolList.add(NULLPtr);
  ProtocolList.addInt(LongTy, Protocols.size());

  auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
  for (const std::string &Protocol : Protocols) {
    llvm::Constant *protocol = nullptr;
    llvm::StringMap<llvm::Constant *>::iterator value =
        ExistingProtocols.find(Protocol);
    if (value == ExistingProtocols.end()) {
      protocol = GenerateEmptyProtocol(Protocol);
    } else {
      protocol = value->getValue();
    }
    Elements.add(protocol);
  }
  Elements.finishAndAddTo(ProtocolList);
  return ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
                                            CGM.getPointerAlign());
}

llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
                                            const ObjCProtocolDecl *PD) {
  return GenerateProtocolRef(PD);
}

llvm::Constant *CGObjCGNU::GenerateProtocolRef(const ObjCProtocolDecl *PD) {
  llvm::Constant *&protocol = ExistingProtocols[PD->getNameAsString()];
  if (!protocol)
    GenerateProtocol(PD);
  assert(protocol && "Unknown protocol");
  return protocol;
}

llvm::Constant *
CGObjCGNU::GenerateEmptyProtocol(StringRef ProtocolName) {
  llvm::Constant *ProtocolList = GenerateProtocolList({});
  llvm::Constant *MethodList = GenerateProtocolMethodList({});
  // Protocols are objects containing lists of the methods implemented and
  // protocols adopted.
  ConstantInitBuilder Builder(CGM);
  auto Elements = Builder.beginStruct();

  // The isa pointer must be set to a magic number so the runtime knows it's
  // the correct layout.
  Elements.add(llvm::ConstantExpr::getIntToPtr(
          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));

  Elements.add(MakeConstantString(ProtocolName, ".objc_protocol_name"));
  Elements.add(ProtocolList); /* .protocol_list */
  Elements.add(MethodList);   /* .instance_methods */
  Elements.add(MethodList);   /* .class_methods */
  Elements.add(MethodList);   /* .optional_instance_methods */
  Elements.add(MethodList);   /* .optional_class_methods */
  Elements.add(NULLPtr);      /* .properties */
  Elements.add(NULLPtr);      /* .optional_properties */
  return Elements.finishAndCreateGlobal(SymbolForProtocol(ProtocolName),
                                        CGM.getPointerAlign());
}

void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
  if (PD->isNonRuntimeProtocol())
    return;

  std::string ProtocolName = PD->getNameAsString();

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

  SmallVector<std::string, 16> Protocols;
  for (const auto *PI : PD->protocols())
    Protocols.push_back(PI->getNameAsString());
  SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
  SmallVector<const ObjCMethodDecl*, 16> OptionalInstanceMethods;
  for (const auto *I : PD->instance_methods())
    if (I->isOptional())
      OptionalInstanceMethods.push_back(I);
    else
      InstanceMethods.push_back(I);
  // Collect information about class methods:
  SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
  SmallVector<const ObjCMethodDecl*, 16> OptionalClassMethods;
  for (const auto *I : PD->class_methods())
    if (I->isOptional())
      OptionalClassMethods.push_back(I);
    else
      ClassMethods.push_back(I);

  llvm::Constant *ProtocolList = GenerateProtocolList(Protocols);
  llvm::Constant *InstanceMethodList =
    GenerateProtocolMethodList(InstanceMethods);
  llvm::Constant *ClassMethodList =
    GenerateProtocolMethodList(ClassMethods);
  llvm::Constant *OptionalInstanceMethodList =
    GenerateProtocolMethodList(OptionalInstanceMethods);
  llvm::Constant *OptionalClassMethodList =
    GenerateProtocolMethodList(OptionalClassMethods);

  // Property metadata: name, attributes, isSynthesized, setter name, setter
  // types, getter name, getter types.
  // The isSynthesized value is always set to 0 in a protocol.  It exists to
  // simplify the runtime library by allowing it to use the same data
  // structures for protocol metadata everywhere.

  llvm::Constant *PropertyList =
    GeneratePropertyList(nullptr, PD, false, false);
  llvm::Constant *OptionalPropertyList =
    GeneratePropertyList(nullptr, PD, false, true);

  // Protocols are objects containing lists of the methods implemented and
  // protocols adopted.
  // The isa pointer must be set to a magic number so the runtime knows it's
  // the correct layout.
  ConstantInitBuilder Builder(CGM);
  auto Elements = Builder.beginStruct();
  Elements.add(
      llvm::ConstantExpr::getIntToPtr(
          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
  Elements.add(MakeConstantString(ProtocolName));
  Elements.add(ProtocolList);
  Elements.add(InstanceMethodList);
  Elements.add(ClassMethodList);
  Elements.add(OptionalInstanceMethodList);
  Elements.add(OptionalClassMethodList);
  Elements.add(PropertyList);
  Elements.add(OptionalPropertyList);
  ExistingProtocols[ProtocolName] =
      Elements.finishAndCreateGlobal(".objc_protocol", CGM.getPointerAlign());
}
void CGObjCGNU::GenerateProtocolHolderCategory() {
  // Collect information about instance methods

  ConstantInitBuilder Builder(CGM);
  auto Elements = Builder.beginStruct();

  const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
  const std::string CategoryName = "AnotherHack";
  Elements.add(MakeConstantString(CategoryName));
  Elements.add(MakeConstantString(ClassName));
  // Instance method list
  Elements.add(GenerateMethodList(ClassName, CategoryName, {}, false));
  // Class method list
  Elements.add(GenerateMethodList(ClassName, CategoryName, {}, true));

  // Protocol list
  ConstantInitBuilder ProtocolListBuilder(CGM);
  auto ProtocolList = ProtocolListBuilder.beginStruct();
  ProtocolList.add(NULLPtr);
  ProtocolList.addInt(LongTy, ExistingProtocols.size());
  auto ProtocolElements = ProtocolList.beginArray(PtrTy);
  for (auto iter = ExistingProtocols.begin(), endIter = ExistingProtocols.end();
       iter != endIter ; iter++) {
    ProtocolElements.add(iter->getValue());
  }
  ProtocolElements.finishAndAddTo(ProtocolList);
  Elements.add(ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
                                                  CGM.getPointerAlign()));
  Categories.push_back(
      Elements.finishAndCreateGlobal("", CGM.getPointerAlign()));
}

/// Libobjc2 uses a bitfield representation where small(ish) bitfields are
/// stored in a 64-bit value with the low bit set to 1 and the remaining 63
/// bits set to their values, LSB first, while larger ones are stored in a
/// structure of this / form:
///
/// struct { int32_t length; int32_t values[length]; };
///
/// The values in the array are stored in host-endian format, with the least
/// significant bit being assumed to come first in the bitfield.  Therefore, a
/// bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, while a
/// bitfield / with the 63rd bit set will be 1<<64.
llvm::Constant *CGObjCGNU::MakeBitField(ArrayRef<bool> bits) {
  int bitCount = bits.size();
  int ptrBits = CGM.getDataLayout().getPointerSizeInBits();
  if (bitCount < ptrBits) {
    uint64_t val = 1;
    for (int i=0 ; i<bitCount ; ++i) {
      if (bits[i]) val |= 1ULL<<(i+1);
    }
    return llvm::ConstantInt::get(IntPtrTy, val);
  }
  SmallVector<llvm::Constant *, 8> values;
  int v=0;
  while (v < bitCount) {
    int32_t word = 0;
    for (int i=0 ; (i<32) && (v<bitCount)  ; ++i) {
      if (bits[v]) word |= 1<<i;
      v++;
    }
    values.push_back(llvm::ConstantInt::get(Int32Ty, word));
  }

  ConstantInitBuilder builder(CGM);
  auto fields = builder.beginStruct();
  fields.addInt(Int32Ty, values.size());
  auto array = fields.beginArray();
  for (auto *v : values) array.add(v);
  array.finishAndAddTo(fields);

  llvm::Constant *GS =
    fields.finishAndCreateGlobal("", CharUnits::fromQuantity(4));
  llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
  return ptr;
}

llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(const
    ObjCCategoryDecl *OCD) {
  const auto &RefPro = OCD->getReferencedProtocols();
  const auto RuntimeProtos =
      GetRuntimeProtocolList(RefPro.begin(), RefPro.end());
  SmallVector<std::string, 16> Protocols;
  for (const auto *PD : RuntimeProtos)
    Protocols.push_back(PD->getNameAsString());
  return GenerateProtocolList(Protocols);
}

void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
  const ObjCInterfaceDecl *Class = OCD->getClassInterface();
  std::string ClassName = Class->getNameAsString();
  std::string CategoryName = OCD->getNameAsString();

  // Collect the names of referenced protocols
  const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();

  ConstantInitBuilder Builder(CGM);
  auto Elements = Builder.beginStruct();
  Elements.add(MakeConstantString(CategoryName));
  Elements.add(MakeConstantString(ClassName));
  // Instance method list
  SmallVector<ObjCMethodDecl*, 16> InstanceMethods;
  InstanceMethods.insert(InstanceMethods.begin(), OCD->instmeth_begin(),
      OCD->instmeth_end());
  Elements.add(
      GenerateMethodList(ClassName, CategoryName, InstanceMethods, false));

  // Class method list

  SmallVector<ObjCMethodDecl*, 16> ClassMethods;
  ClassMethods.insert(ClassMethods.begin(), OCD->classmeth_begin(),
      OCD->classmeth_end());
  Elements.add(GenerateMethodList(ClassName, CategoryName, ClassMethods, true));

  // Protocol list
  Elements.add(GenerateCategoryProtocolList(CatDecl));
  if (isRuntime(ObjCRuntime::GNUstep, 2)) {
    const ObjCCategoryDecl *Category =
      Class->FindCategoryDeclaration(OCD->getIdentifier());
    if (Category) {
      // Instance properties
      Elements.add(GeneratePropertyList(OCD, Category, false));
      // Class properties
      Elements.add(GeneratePropertyList(OCD, Category, true));
    } else {
      Elements.addNullPointer(PtrTy);
      Elements.addNullPointer(PtrTy);
    }
  }

  Categories.push_back(Elements.finishAndCreateGlobal(
      std::string(".objc_category_") + ClassName + CategoryName,
      CGM.getPointerAlign()));
}

llvm::Constant *CGObjCGNU::GeneratePropertyList(const Decl *Container,
    const ObjCContainerDecl *OCD,
    bool isClassProperty,
    bool protocolOptionalProperties) {

  SmallVector<const ObjCPropertyDecl *, 16> Properties;
  llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
  bool isProtocol = isa<ObjCProtocolDecl>(OCD);
  ASTContext &Context = CGM.getContext();

  std::function<void(const ObjCProtocolDecl *Proto)> collectProtocolProperties
    = [&](const ObjCProtocolDecl *Proto) {
      for (const auto *P : Proto->protocols())
        collectProtocolProperties(P);
      for (const auto *PD : Proto->properties()) {
        if (isClassProperty != PD->isClassProperty())
          continue;
        // Skip any properties that are declared in protocols that this class
        // conforms to but are not actually implemented by this class.
        if (!isProtocol && !Context.getObjCPropertyImplDeclForPropertyDecl(PD, Container))
          continue;
        if (!PropertySet.insert(PD->getIdentifier()).second)
          continue;
        Properties.push_back(PD);
      }
    };

  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;
        PropertySet.insert(PD->getIdentifier());
        Properties.push_back(PD);
      }

  for (const auto *PD : OCD->properties()) {
    if (isClassProperty != PD->isClassProperty())
      continue;
    // If we're generating a list for a protocol, skip optional / required ones
    // when generating the other list.
    if (isProtocol && (protocolOptionalProperties != PD->isOptional()))
      continue;
    // Don't emit duplicate metadata for properties that were already in a
    // class extension.
    if (!PropertySet.insert(PD->getIdentifier()).second)
      continue;

    Properties.push_back(PD);
  }

  if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
    for (const auto *P : OID->all_referenced_protocols())
      collectProtocolProperties(P);
  else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD))
    for (const auto *P : CD->protocols())
      collectProtocolProperties(P);

  auto numProperties = Properties.size();

  if (numProperties == 0)
    return NULLPtr;

  ConstantInitBuilder builder(CGM);
  auto propertyList = builder.beginStruct();
  auto properties = PushPropertyListHeader(propertyList, numProperties);

  // Add all of the property methods need adding to the method list and to the
  // property metadata list.
  for (auto *property : Properties) {
    bool isSynthesized = false;
    bool isDynamic = false;
    if (!isProtocol) {
      auto *propertyImpl = Context.getObjCPropertyImplDeclForPropertyDecl(property, Container);
      if (propertyImpl) {
        isSynthesized = (propertyImpl->getPropertyImplementation() ==
            ObjCPropertyImplDecl::Synthesize);
        isDynamic = (propertyImpl->getPropertyImplementation() ==
            ObjCPropertyImplDecl::Dynamic);
      }
    }
    PushProperty(properties, property, Container, isSynthesized, isDynamic);
  }
  properties.finishAndAddTo(propertyList);

  return propertyList.finishAndCreateGlobal(".objc_property_list",
                                            CGM.getPointerAlign());
}

void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {
  // Get the class declaration for which the alias is specified.
  ObjCInterfaceDecl *ClassDecl =
    const_cast<ObjCInterfaceDecl *>(OAD->getClassInterface());
  ClassAliases.emplace_back(ClassDecl->getNameAsString(),
                            OAD->getNameAsString());
}

void CGObjCGNU::GenerateClass(const ObjCImplementationDecl *OID) {
  ASTContext &Context = CGM.getContext();

  // Get the superclass name.
  const ObjCInterfaceDecl * SuperClassDecl =
    OID->getClassInterface()->getSuperClass();
  std::string SuperClassName;
  if (SuperClassDecl) {
    SuperClassName = SuperClassDecl->getNameAsString();
    EmitClassRef(SuperClassName);
  }

  // Get the class name
  ObjCInterfaceDecl *ClassDecl =
      const_cast<ObjCInterfaceDecl *>(OID->getClassInterface());
  std::string ClassName = ClassDecl->getNameAsString();

  // Emit the symbol that is used to generate linker errors if this class is
  // referenced in other modules but not declared.
  std::string classSymbolName = "__objc_class_name_" + ClassName;
  if (auto *symbol = TheModule.getGlobalVariable(classSymbolName)) {
    symbol->setInitializer(llvm::ConstantInt::get(LongTy, 0));
  } else {
    new llvm::GlobalVariable(TheModule, LongTy, false,
                             llvm::GlobalValue::ExternalLinkage,
                             llvm::ConstantInt::get(LongTy, 0),
                             classSymbolName);
  }

  // Get the size of instances.
  int instanceSize = Context.getASTObjCInterfaceLayout(OID->getClassInterface())
                         .getSize()
                         .getQuantity();

  // Collect information about instance variables.
  SmallVector<llvm::Constant*, 16> IvarNames;
  SmallVector<llvm::Constant*, 16> IvarTypes;
  SmallVector<llvm::Constant*, 16> IvarOffsets;
  SmallVector<llvm::Constant*, 16> IvarAligns;
  SmallVector<Qualifiers::ObjCLifetime, 16> IvarOwnership;

  ConstantInitBuilder IvarOffsetBuilder(CGM);
  auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
  SmallVector<bool, 16> WeakIvars;
  SmallVector<bool, 16> StrongIvars;

  int superInstanceSize = !SuperClassDecl ? 0 :
    Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
  // For non-fragile ivars, set the instance size to 0 - {the size of just this
  // class}.  The runtime will then set this to the correct value on load.
  if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
    instanceSize = 0 - (instanceSize - superInstanceSize);
  }

  for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD;
       IVD = IVD->getNextIvar()) {
      // Store the name
      IvarNames.push_back(MakeConstantString(IVD->getNameAsString()));
      // Get the type encoding for this ivar
      std::string TypeStr;
      Context.getObjCEncodingForType(IVD->getType(), TypeStr, IVD);
      IvarTypes.push_back(MakeConstantString(TypeStr));
      IvarAligns.push_back(llvm::ConstantInt::get(IntTy,
            Context.getTypeSize(IVD->getType())));
      // Get the offset
      uint64_t BaseOffset = ComputeIvarBaseOffset(CGM, OID, IVD);
      uint64_t Offset = BaseOffset;
      if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
        Offset = BaseOffset - superInstanceSize;
      }
      llvm::Constant *OffsetValue = llvm::ConstantInt::get(IntTy, Offset);
      // Create the direct offset value
      std::string OffsetName = "__objc_ivar_offset_value_" + ClassName +"." +
          IVD->getNameAsString();

      llvm::GlobalVariable *OffsetVar = TheModule.getGlobalVariable(OffsetName);
      if (OffsetVar) {
        OffsetVar->setInitializer(OffsetValue);
        // If this is the real definition, change its linkage type so that
        // different modules will use this one, rather than their private
        // copy.
        OffsetVar->setLinkage(llvm::GlobalValue::ExternalLinkage);
      } else
        OffsetVar = new llvm::GlobalVariable(TheModule, Int32Ty,
          false, llvm::GlobalValue::ExternalLinkage,
          OffsetValue, OffsetName);
      IvarOffsets.push_back(OffsetValue);
      IvarOffsetValues.add(OffsetVar);
      Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
      IvarOwnership.push_back(lt);
      switch (lt) {
        case Qualifiers::OCL_Strong:
          StrongIvars.push_back(true);
          WeakIvars.push_back(false);
          break;
        case Qualifiers::OCL_Weak:
          StrongIvars.push_back(false);
          WeakIvars.push_back(true);
          break;
        default:
          StrongIvars.push_back(false);
          WeakIvars.push_back(false);
      }
  }
  llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
  llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
  llvm::GlobalVariable *IvarOffsetArray =
    IvarOffsetValues.finishAndCreateGlobal(".ivar.offsets",
                                           CGM.getPointerAlign());

  // Collect information about instance methods
  SmallVector<const ObjCMethodDecl*, 16> InstanceMethods;
  InstanceMethods.insert(InstanceMethods.begin(), OID->instmeth_begin(),
      OID->instmeth_end());

  SmallVector<const ObjCMethodDecl*, 16> ClassMethods;
  ClassMethods.insert(ClassMethods.begin(), OID->classmeth_begin(),
      OID->classmeth_end());

  llvm::Constant *Properties = GeneratePropertyList(OID, ClassDecl);

  // Collect the names of referenced protocols
  auto RefProtocols = ClassDecl->protocols();
  auto RuntimeProtocols =
      GetRuntimeProtocolList(RefProtocols.begin(), RefProtocols.end());
  SmallVector<std::string, 16> Protocols;
  for (const auto *I : RuntimeProtocols)
    Protocols.push_back(I->getNameAsString());

  // Get the superclass pointer.
  llvm::Constant *SuperClass;
  if (!SuperClassName.empty()) {
    SuperClass = MakeConstantString(SuperClassName, ".super_class_name");
  } else {
    SuperClass = llvm::ConstantPointerNull::get(PtrToInt8Ty);
  }
  // Generate the method and instance variable lists
  llvm::Constant *MethodList = GenerateMethodList(ClassName, "",
      InstanceMethods, false);
  llvm::Constant *ClassMethodList = GenerateMethodList(ClassName, "",
      ClassMethods, true);
  llvm::Constant *IvarList = GenerateIvarList(IvarNames, IvarTypes,
      IvarOffsets, IvarAligns, IvarOwnership);
  // Irrespective of whether we are compiling for a fragile or non-fragile ABI,
  // we emit a symbol containing the offset for each ivar in the class.  This
  // allows code compiled for the non-Fragile ABI to inherit from code compiled
  // for the legacy ABI, without causing problems.  The converse is also
  // possible, but causes all ivar accesses to be fragile.

  // Offset pointer for getting at the correct field in the ivar list when
  // setting up the alias.  These are: The base address for the global, the
  // ivar array (second field), the ivar in this list (set for each ivar), and
  // the offset (third field in ivar structure)
  llvm::Type *IndexTy = Int32Ty;
  llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
      llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 2 : 1), nullptr,
      llvm::ConstantInt::get(IndexTy, ClassABIVersion > 1 ? 3 : 2) };

  unsigned ivarIndex = 0;
  for (const ObjCIvarDecl *IVD = ClassDecl->all_declared_ivar_begin(); IVD;
       IVD = IVD->getNextIvar()) {
      const std::string Name = GetIVarOffsetVariableName(ClassDecl, IVD);
      offsetPointerIndexes[2] = llvm::ConstantInt::get(IndexTy, ivarIndex);
      // Get the correct ivar field
      llvm::Constant *offsetValue = llvm::ConstantExpr::getGetElementPtr(
          cast<llvm::GlobalVariable>(IvarList)->getValueType(), IvarList,
          offsetPointerIndexes);
      // Get the existing variable, if one exists.
      llvm::GlobalVariable *offset = TheModule.getNamedGlobal(Name);
      if (offset) {
        offset->setInitializer(offsetValue);
        // If this is the real definition, change its linkage type so that
        // different modules will use this one, rather than their private
        // copy.
        offset->setLinkage(llvm::GlobalValue::ExternalLinkage);
      } else
        // Add a new alias if there isn't one already.
        new llvm::GlobalVariable(TheModule, offsetValue->getType(),
                false, llvm::GlobalValue::ExternalLinkage, offsetValue, Name);
      ++ivarIndex;
  }
  llvm::Constant *ZeroPtr = llvm::ConstantInt::get(IntPtrTy, 0);

  //Generate metaclass for class methods
  llvm::Constant *MetaClassStruct = GenerateClassStructure(
      NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0],
      NULLPtr, ClassMethodList, NULLPtr, NULLPtr,
      GeneratePropertyList(OID, ClassDecl, true), ZeroPtr, ZeroPtr, true);
  CGM.setGVProperties(cast<llvm::GlobalValue>(MetaClassStruct),
                      OID->getClassInterface());

  // Generate the class structure
  llvm::Constant *ClassStruct = GenerateClassStructure(
      MetaClassStruct, SuperClass, 0x11L, ClassName.c_str(), nullptr,
      llvm::ConstantInt::get(LongTy, instanceSize), IvarList, MethodList,
      GenerateProtocolList(Protocols), IvarOffsetArray, Properties,
      StrongIvarBitmap, WeakIvarBitmap);
  CGM.setGVProperties(cast<llvm::GlobalValue>(ClassStruct),
                      OID->getClassInterface());

  // Resolve the class aliases, if they exist.
  if (ClassPtrAlias) {
    ClassPtrAlias->replaceAllUsesWith(ClassStruct);
    ClassPtrAlias->eraseFromParent();
    ClassPtrAlias = nullptr;
  }
  if (MetaClassPtrAlias) {
    MetaClassPtrAlias->replaceAllUsesWith(MetaClassStruct);
    MetaClassPtrAlias->eraseFromParent();
    MetaClassPtrAlias = nullptr;
  }

  // Add class structure to list to be added to the symtab later
  Classes.push_back(ClassStruct);
}

llvm::Function *CGObjCGNU::ModuleInitFunction() {
  // Only emit an ObjC load function if no Objective-C stuff has been called
  if (Classes.empty() && Categories.empty() && ConstantStrings.empty() &&
      ExistingProtocols.empty() && SelectorTable.empty())
    return nullptr;

  // Add all referenced protocols to a category.
  GenerateProtocolHolderCategory();

  llvm::StructType *selStructTy = dyn_cast<llvm::StructType>(SelectorElemTy);
  if (!selStructTy) {
    selStructTy = llvm::StructType::get(CGM.getLLVMContext(),
                                        { PtrToInt8Ty, PtrToInt8Ty });
  }

  // Generate statics list:
  llvm::Constant *statics = NULLPtr;
  if (!ConstantStrings.empty()) {
    llvm::GlobalVariable *fileStatics = [&] {
      ConstantInitBuilder builder(CGM);
      auto staticsStruct = builder.beginStruct();

      StringRef stringClass = CGM.getLangOpts().ObjCConstantStringClass;
      if (stringClass.empty()) stringClass = "NXConstantString";
      staticsStruct.add(MakeConstantString(stringClass,
                                           ".objc_static_class_name"));

      auto array = staticsStruct.beginArray();
      array.addAll(ConstantStrings);
      array.add(NULLPtr);
      array.finishAndAddTo(staticsStruct);

      return staticsStruct.finishAndCreateGlobal(".objc_statics",
                                                 CGM.getPointerAlign());
    }();

    ConstantInitBuilder builder(CGM);
    auto allStaticsArray = builder.beginArray(fileStatics->getType());
    allStaticsArray.add(fileStatics);
    allStaticsArray.addNullPointer(fileStatics->getType());

    statics = allStaticsArray.finishAndCreateGlobal(".objc_statics_ptr",
                                                    CGM.getPointerAlign());
  }

  // Array of classes, categories, and constant objects.

  SmallVector<llvm::GlobalAlias*, 16> selectorAliases;
  unsigned selectorCount;

  // Pointer to an array of selectors used in this module.
  llvm::GlobalVariable *selectorList = [&] {
    ConstantInitBuilder builder(CGM);
    auto selectors = builder.beginArray(selStructTy);
    auto &table = SelectorTable; // MSVC workaround
    std::vector<Selector> allSelectors;
    for (auto &entry : table)
      allSelectors.push_back(entry.first);
    llvm::sort(allSelectors);

    for (auto &untypedSel : allSelectors) {
      std::string selNameStr = untypedSel.getAsString();
      llvm::Constant *selName = ExportUniqueString(selNameStr, ".objc_sel_name");

      for (TypedSelector &sel : table[untypedSel]) {
        llvm::Constant *selectorTypeEncoding = NULLPtr;
        if (!sel.first.empty())
          selectorTypeEncoding =
            MakeConstantString(sel.first, ".objc_sel_types");

        auto selStruct = selectors.beginStruct(selStructTy);
        selStruct.add(selName);
        selStruct.add(selectorTypeEncoding);
        selStruct.finishAndAddTo(selectors);

        // Store the selector alias for later replacement
        selectorAliases.push_back(sel.second);
      }
    }

    // Remember the number of entries in the selector table.
    selectorCount = selectors.size();

    // NULL-terminate the selector list.  This should not actually be required,
    // because the selector list has a length field.  Unfortunately, the GCC
    // runtime decides to ignore the length field and expects a NULL terminator,
    // and GCC cooperates with this by always setting the length to 0.
    auto selStruct = selectors.beginStruct(selStructTy);
    selStruct.add(NULLPtr);
    selStruct.add(NULLPtr);
    selStruct.finishAndAddTo(selectors);

    return selectors.finishAndCreateGlobal(".objc_selector_list",
                                           CGM.getPointerAlign());
  }();

  // Now that all of the static selectors exist, create pointers to them.
  for (unsigned i = 0; i < selectorCount; ++i) {
    llvm::Constant *idxs[] = {
      Zeros[0],
      llvm::ConstantInt::get(Int32Ty, i)
    };
    // FIXME: We're generating redundant loads and stores here!
    llvm::Constant *selPtr = llvm::ConstantExpr::getGetElementPtr(
        selectorList->getValueType(), selectorList, idxs);
    selectorAliases[i]->replaceAllUsesWith(selPtr);
    selectorAliases[i]->eraseFromParent();
  }

  llvm::GlobalVariable *symtab = [&] {
    ConstantInitBuilder builder(CGM);
    auto symtab = builder.beginStruct();

    // Number of static selectors
    symtab.addInt(LongTy, selectorCount);

    symtab.add(selectorList);

    // Number of classes defined.
    symtab.addInt(CGM.Int16Ty, Classes.size());
    // Number of categories defined
    symtab.addInt(CGM.Int16Ty, Categories.size());

    // Create an array of classes, then categories, then static object instances
    auto classList = symtab.beginArray(PtrToInt8Ty);
    classList.addAll(Classes);
    classList.addAll(Categories);
    //  NULL-terminated list of static object instances (mainly constant strings)
    classList.add(statics);
    classList.add(NULLPtr);
    classList.finishAndAddTo(symtab);

    // Construct the symbol table.
    return symtab.finishAndCreateGlobal("", CGM.getPointerAlign());
  }();

  // The symbol table is contained in a module which has some version-checking
  // constants
  llvm::Constant *module = [&] {
    llvm::Type *moduleEltTys[] = {
      LongTy, LongTy, PtrToInt8Ty, symtab->getType(), IntTy
    };
    llvm::StructType *moduleTy = llvm::StructType::get(
        CGM.getLLVMContext(),
        ArrayRef(moduleEltTys).drop_back(unsigned(RuntimeVersion < 10)));

    ConstantInitBuilder builder(CGM);
    auto module = builder.beginStruct(moduleTy);
    // Runtime version, used for ABI compatibility checking.
    module.addInt(LongTy, RuntimeVersion);
    // sizeof(ModuleTy)
    module.addInt(LongTy, CGM.getDataLayout().getTypeStoreSize(moduleTy));

    // The path to the source file where this module was declared
    SourceManager &SM = CGM.getContext().getSourceManager();
    OptionalFileEntryRef mainFile = SM.getFileEntryRefForID(SM.getMainFileID());
    std::string path =
        (mainFile->getDir().getName() + "/" + mainFile->getName()).str();
    module.add(MakeConstantString(path, ".objc_source_file_name"));
    module.add(symtab);

    if (RuntimeVersion >= 10) {
      switch (CGM.getLangOpts().getGC()) {
      case LangOptions::GCOnly:
        module.addInt(IntTy, 2);
        break;
      case LangOptions::NonGC:
        if (CGM.getLangOpts().ObjCAutoRefCount)
          module.addInt(IntTy, 1);
        else
          module.addInt(IntTy, 0);
        break;
      case LangOptions::HybridGC:
        module.addInt(IntTy, 1);
        break;
      }
    }

    return module.finishAndCreateGlobal("", CGM.getPointerAlign());
  }();

  // Create the load function calling the runtime entry point with the module
  // structure
  llvm::Function * LoadFunction = llvm::Function::Create(
      llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), false),
      llvm::GlobalValue::InternalLinkage, ".objc_load_function",
      &TheModule);
  llvm::BasicBlock *EntryBB =
      llvm::BasicBlock::Create(VMContext, "entry", LoadFunction);
  CGBuilderTy Builder(CGM, VMContext);
  Builder.SetInsertPoint(EntryBB);

  llvm::FunctionType *FT =
    llvm::FunctionType::get(Builder.getVoidTy(), module->getType(), true);
  llvm::FunctionCallee Register =
      CGM.CreateRuntimeFunction(FT, "__objc_exec_class");
  Builder.CreateCall(Register, module);

  if (!ClassAliases.empty()) {
    llvm::Type *ArgTypes[2] = {PtrTy, PtrToInt8Ty};
    llvm::FunctionType *RegisterAliasTy =
      llvm::FunctionType::get(Builder.getVoidTy(),
                              ArgTypes, false);
    llvm::Function *RegisterAlias = llvm::Function::Create(
      RegisterAliasTy,
      llvm::GlobalValue::ExternalWeakLinkage, "class_registerAlias_np",
      &TheModule);
    llvm::BasicBlock *AliasBB =
      llvm::BasicBlock::Create(VMContext, "alias", LoadFunction);
    llvm::BasicBlock *NoAliasBB =
      llvm::BasicBlock::Create(VMContext, "no_alias", LoadFunction);

    // Branch based on whether the runtime provided class_registerAlias_np()
    llvm::Value *HasRegisterAlias = Builder.CreateICmpNE(RegisterAlias,
            llvm::Constant::getNullValue(RegisterAlias->getType()));
    Builder.CreateCondBr(HasRegisterAlias, AliasBB, NoAliasBB);

    // The true branch (has alias registration function):
    Builder.SetInsertPoint(AliasBB);
    // Emit alias registration calls:
    for (std::vector<ClassAliasPair>::iterator iter = ClassAliases.begin();
       iter != ClassAliases.end(); ++iter) {
       llvm::Constant *TheClass =
          TheModule.getGlobalVariable("_OBJC_CLASS_" + iter->first, true);
       if (TheClass) {
         Builder.CreateCall(RegisterAlias,
                            {TheClass, MakeConstantString(iter->second)});
       }
    }
    // Jump to end:
    Builder.CreateBr(NoAliasBB);

    // Missing alias registration function, just return from the function:
    Builder.SetInsertPoint(NoAliasBB);
  }
  Builder.CreateRetVoid();

  return LoadFunction;
}

llvm::Function *CGObjCGNU::GenerateMethod(const ObjCMethodDecl *OMD,
                                          const ObjCContainerDecl *CD) {
  CodeGenTypes &Types = CGM.getTypes();
  llvm::FunctionType *MethodTy =
    Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));

  bool isDirect = OMD->isDirectMethod();
  std::string FunctionName =
      getSymbolNameForMethod(OMD, /*include category*/ !isDirect);

  if (!isDirect)
    return llvm::Function::Create(MethodTy,
                                  llvm::GlobalVariable::InternalLinkage,
                                  FunctionName, &TheModule);

  auto *COMD = OMD->getCanonicalDecl();
  auto I = DirectMethodDefinitions.find(COMD);
  llvm::Function *OldFn = nullptr, *Fn = nullptr;

  if (I == DirectMethodDefinitions.end()) {
    auto *F =
        llvm::Function::Create(MethodTy, llvm::GlobalVariable::ExternalLinkage,
                               FunctionName, &TheModule);
    DirectMethodDefinitions.insert(std::make_pair(COMD, F));
    return F;
  }

  // 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;
  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;
  return Fn;
}

void CGObjCGNU::GenerateDirectMethodPrologue(CodeGenFunction &CGF,
                                             llvm::Function *Fn,
                                             const ObjCMethodDecl *OMD,
                                             const ObjCContainerDecl *CD) {
  // GNU runtime doesn't support direct calls at this time
}

llvm::FunctionCallee CGObjCGNU::GetPropertyGetFunction() {
  return GetPropertyFn;
}

llvm::FunctionCallee CGObjCGNU::GetPropertySetFunction() {
  return SetPropertyFn;
}

llvm::FunctionCallee CGObjCGNU::GetOptimizedPropertySetFunction(bool atomic,
                                                                bool copy) {
  return nullptr;
}

llvm::FunctionCallee CGObjCGNU::GetGetStructFunction() {
  return GetStructPropertyFn;
}

llvm::FunctionCallee CGObjCGNU::GetSetStructFunction() {
  return SetStructPropertyFn;
}

llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectGetFunction() {
  return nullptr;
}

llvm::FunctionCallee CGObjCGNU::GetCppAtomicObjectSetFunction() {
  return nullptr;
}

llvm::FunctionCallee CGObjCGNU::EnumerationMutationFunction() {
  return EnumerationMutationFn;
}

void CGObjCGNU::EmitSynchronizedStmt(CodeGenFunction &CGF,
                                     const ObjCAtSynchronizedStmt &S) {
  EmitAtSynchronizedStmt(CGF, S, SyncEnterFn, SyncExitFn);
}


void CGObjCGNU::EmitTryStmt(CodeGenFunction &CGF,
                            const ObjCAtTryStmt &S) {
  // Unlike the Apple non-fragile runtimes, which also uses
  // unwind-based zero cost exceptions, the GNU Objective C runtime's
  // EH support isn't a veneer over C++ EH.  Instead, exception
  // objects are created by objc_exception_throw and destroyed by
  // the personality function; this avoids the need for bracketing
  // catch handlers with calls to __blah_begin_catch/__blah_end_catch
  // (or even _Unwind_DeleteException), but probably doesn't
  // interoperate very well with foreign exceptions.
  //
  // In Objective-C++ mode, we actually emit something equivalent to the C++
  // exception handler.
  EmitTryCatchStmt(CGF, S, EnterCatchFn, ExitCatchFn, ExceptionReThrowFn);
}

void CGObjCGNU::EmitThrowStmt(CodeGenFunction &CGF,
                              const ObjCAtThrowStmt &S,
                              bool ClearInsertionPoint) {
  llvm::Value *ExceptionAsObject;
  bool isRethrow = false;

  if (const Expr *ThrowExpr = S.getThrowExpr()) {
    llvm::Value *Exception = CGF.EmitObjCThrowOperand(ThrowExpr);
    ExceptionAsObject = Exception;
  } else {
    assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
           "Unexpected rethrow outside @catch block.");
    ExceptionAsObject = CGF.ObjCEHValueStack.back();
    isRethrow = true;
  }
  if (isRethrow && (usesSEHExceptions || usesCxxExceptions)) {
    // For SEH, ExceptionAsObject may be undef, because the catch handler is
    // not passed it for catchalls and so it is not visible to the catch
    // funclet.  The real thrown object will still be live on the stack at this
    // point and will be rethrown.  If we are explicitly rethrowing the object
    // that was passed into the `@catch` block, then this code path is not
    // reached and we will instead call `objc_exception_throw` with an explicit
    // argument.
    llvm::CallBase *Throw = CGF.EmitRuntimeCallOrInvoke(ExceptionReThrowFn);
    Throw->setDoesNotReturn();
  } else {
    ExceptionAsObject = CGF.Builder.CreateBitCast(ExceptionAsObject, IdTy);
    llvm::CallBase *Throw =
        CGF.EmitRuntimeCallOrInvoke(ExceptionThrowFn, ExceptionAsObject);
    Throw->setDoesNotReturn();
  }
  CGF.Builder.CreateUnreachable();
  if (ClearInsertionPoint)
    CGF.Builder.ClearInsertionPoint();
}

llvm::Value * CGObjCGNU::EmitObjCWeakRead(CodeGenFunction &CGF,
                                          Address AddrWeakObj) {
  CGBuilderTy &B = CGF.Builder;
  return B.CreateCall(
      WeakReadFn, EnforceType(B, AddrWeakObj.emitRawPointer(CGF), PtrToIdTy));
}

void CGObjCGNU::EmitObjCWeakAssign(CodeGenFunction &CGF,
                                   llvm::Value *src, Address dst) {
  CGBuilderTy &B = CGF.Builder;
  src = EnforceType(B, src, IdTy);
  llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy);
  B.CreateCall(WeakAssignFn, {src, dstVal});
}

void CGObjCGNU::EmitObjCGlobalAssign(CodeGenFunction &CGF,
                                     llvm::Value *src, Address dst,
                                     bool threadlocal) {
  CGBuilderTy &B = CGF.Builder;
  src = EnforceType(B, src, IdTy);
  llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy);
  // FIXME. Add threadloca assign API
  assert(!threadlocal && "EmitObjCGlobalAssign - Threal Local API NYI");
  B.CreateCall(GlobalAssignFn, {src, dstVal});
}

void CGObjCGNU::EmitObjCIvarAssign(CodeGenFunction &CGF,
                                   llvm::Value *src, Address dst,
                                   llvm::Value *ivarOffset) {
  CGBuilderTy &B = CGF.Builder;
  src = EnforceType(B, src, IdTy);
  llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), IdTy);
  B.CreateCall(IvarAssignFn, {src, dstVal, ivarOffset});
}

void CGObjCGNU::EmitObjCStrongCastAssign(CodeGenFunction &CGF,
                                         llvm::Value *src, Address dst) {
  CGBuilderTy &B = CGF.Builder;
  src = EnforceType(B, src, IdTy);
  llvm::Value *dstVal = EnforceType(B, dst.emitRawPointer(CGF), PtrToIdTy);
  B.CreateCall(StrongCastAssignFn, {src, dstVal});
}

void CGObjCGNU::EmitGCMemmoveCollectable(CodeGenFunction &CGF,
                                         Address DestPtr,
                                         Address SrcPtr,
                                         llvm::Value *Size) {
  CGBuilderTy &B = CGF.Builder;
  llvm::Value *DestPtrVal = EnforceType(B, DestPtr.emitRawPointer(CGF), PtrTy);
  llvm::Value *SrcPtrVal = EnforceType(B, SrcPtr.emitRawPointer(CGF), PtrTy);

  B.CreateCall(MemMoveFn, {DestPtrVal, SrcPtrVal, Size});
}

llvm::GlobalVariable *CGObjCGNU::ObjCIvarOffsetVariable(
                              const ObjCInterfaceDecl *ID,
                              const ObjCIvarDecl *Ivar) {
  const std::string Name = GetIVarOffsetVariableName(ID, Ivar);
  // Emit the variable and initialize it with what we think the correct value
  // is.  This allows code compiled with non-fragile ivars to work correctly
  // when linked against code which isn't (most of the time).
  llvm::GlobalVariable *IvarOffsetPointer = TheModule.getNamedGlobal(Name);
  if (!IvarOffsetPointer)
    IvarOffsetPointer = new llvm::GlobalVariable(
        TheModule, llvm::PointerType::getUnqual(VMContext), false,
        llvm::GlobalValue::ExternalLinkage, nullptr, Name);
  return IvarOffsetPointer;
}

LValue CGObjCGNU::EmitObjCValueForIvar(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));
}

static const ObjCInterfaceDecl *FindIvarInterface(ASTContext &Context,
                                                  const ObjCInterfaceDecl *OID,
                                                  const ObjCIvarDecl *OIVD) {
  for (const ObjCIvarDecl *next = OID->all_declared_ivar_begin(); next;
       next = next->getNextIvar()) {
    if (OIVD == next)
      return OID;
  }

  // Otherwise check in the super class.
  if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
    return FindIvarInterface(Context, Super, OIVD);

  return nullptr;
}

llvm::Value *CGObjCGNU::EmitIvarOffset(CodeGenFunction &CGF,
                         const ObjCInterfaceDecl *Interface,
                         const ObjCIvarDecl *Ivar) {
  if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) {
    Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar);

    // The MSVC linker cannot have a single global defined as LinkOnceAnyLinkage
    // and ExternalLinkage, so create a reference to the ivar global and rely on
    // the definition being created as part of GenerateClass.
    if (RuntimeVersion < 10 ||
        CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment())
      return CGF.Builder.CreateZExtOrBitCast(
          CGF.Builder.CreateAlignedLoad(
              Int32Ty,
              CGF.Builder.CreateAlignedLoad(
                  llvm::PointerType::getUnqual(VMContext),
                  ObjCIvarOffsetVariable(Interface, Ivar),
                  CGF.getPointerAlign(), "ivar"),
              CharUnits::fromQuantity(4)),
          PtrDiffTy);
    std::string name = "__objc_ivar_offset_value_" +
      Interface->getNameAsString() +"." + Ivar->getNameAsString();
    CharUnits Align = CGM.getIntAlign();
    llvm::Value *Offset = TheModule.getGlobalVariable(name);
    if (!Offset) {
      auto GV = new llvm::GlobalVariable(TheModule, IntTy,
          false, llvm::GlobalValue::LinkOnceAnyLinkage,
          llvm::Constant::getNullValue(IntTy), name);
      GV->setAlignment(Align.getAsAlign());
      Offset = GV;
    }
    Offset = CGF.Builder.CreateAlignedLoad(IntTy, Offset, Align);
    if (Offset->getType() != PtrDiffTy)
      Offset = CGF.Builder.CreateZExtOrBitCast(Offset, PtrDiffTy);
    return Offset;
  }
  uint64_t Offset = ComputeIvarBaseOffset(CGF.CGM, Interface, Ivar);
  return llvm::ConstantInt::get(PtrDiffTy, Offset, /*isSigned*/true);
}

CGObjCRuntime *
clang::CodeGen::CreateGNUObjCRuntime(CodeGenModule &CGM) {
  auto Runtime = CGM.getLangOpts().ObjCRuntime;
  switch (Runtime.getKind()) {
  case ObjCRuntime::GNUstep:
    if (Runtime.getVersion() >= VersionTuple(2, 0))
      return new CGObjCGNUstep2(CGM);
    return new CGObjCGNUstep(CGM);

  case ObjCRuntime::GCC:
    return new CGObjCGCC(CGM);

  case ObjCRuntime::ObjFW:
    return new CGObjCObjFW(CGM);

  case ObjCRuntime::FragileMacOSX:
  case ObjCRuntime::MacOSX:
  case ObjCRuntime::iOS:
  case ObjCRuntime::WatchOS:
    llvm_unreachable("these runtimes are not GNU runtimes");
  }
  llvm_unreachable("bad runtime");
}
