r287437 - Introduce a helper class for building complex constant initializers. NFC.

John McCall via cfe-commits cfe-commits at lists.llvm.org
Sat Nov 19 00:17:25 PST 2016


Author: rjmccall
Date: Sat Nov 19 02:17:24 2016
New Revision: 287437

URL: http://llvm.org/viewvc/llvm-project?rev=287437&view=rev
Log:
Introduce a helper class for building complex constant initializers.  NFC.

I've adopted this in most of the places it makes sense, but v-tables
and CGObjCMac will need a second pass.

Added:
    cfe/trunk/lib/CodeGen/ConstantBuilder.h
Modified:
    cfe/trunk/include/clang/AST/DeclObjC.h
    cfe/trunk/lib/CodeGen/CGBlocks.cpp
    cfe/trunk/lib/CodeGen/CGCUDANV.cpp
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
    cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp

Modified: cfe/trunk/include/clang/AST/DeclObjC.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclObjC.h?rev=287437&r1=287436&r2=287437&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclObjC.h (original)
+++ cfe/trunk/include/clang/AST/DeclObjC.h Sat Nov 19 02:17:24 2016
@@ -870,6 +870,9 @@ public:
   PropertyControl getPropertyImplementation() const {
     return PropertyControl(PropertyImplementation);
   }
+  bool isOptional() const {
+    return getPropertyImplementation() == PropertyControl::Optional;
+  }
 
   void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
     PropertyIvarDecl = Ivar;

Modified: cfe/trunk/lib/CodeGen/CGBlocks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGBlocks.cpp?rev=287437&r1=287436&r2=287437&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGBlocks.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGBlocks.cpp Sat Nov 19 02:17:24 2016
@@ -16,6 +16,7 @@
 #include "CGObjCRuntime.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "ConstantBuilder.h"
 #include "clang/AST/DeclObjC.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/IR/CallSite.h"
@@ -77,63 +78,63 @@ static llvm::Constant *buildBlockDescrip
                                             const CGBlockInfo &blockInfo) {
   ASTContext &C = CGM.getContext();
 
-  llvm::Type *ulong = CGM.getTypes().ConvertType(C.UnsignedLongTy);
-  llvm::Type *i8p = nullptr;
+  llvm::IntegerType *ulong =
+    cast<llvm::IntegerType>(CGM.getTypes().ConvertType(C.UnsignedLongTy));
+  llvm::PointerType *i8p = nullptr;
   if (CGM.getLangOpts().OpenCL)
     i8p = 
       llvm::Type::getInt8PtrTy(
            CGM.getLLVMContext(), C.getTargetAddressSpace(LangAS::opencl_constant));
   else
-    i8p = CGM.getTypes().ConvertType(C.VoidPtrTy);
+    i8p = CGM.VoidPtrTy;
 
-  SmallVector<llvm::Constant*, 6> elements;
+  ConstantBuilder builder(CGM);
+  auto elements = builder.beginStruct();
 
   // reserved
-  elements.push_back(llvm::ConstantInt::get(ulong, 0));
+  elements.addInt(ulong, 0);
 
   // Size
   // FIXME: What is the right way to say this doesn't fit?  We should give
   // a user diagnostic in that case.  Better fix would be to change the
   // API to size_t.
-  elements.push_back(llvm::ConstantInt::get(ulong,
-                                            blockInfo.BlockSize.getQuantity()));
+  elements.addInt(ulong, blockInfo.BlockSize.getQuantity());
 
   // Optional copy/dispose helpers.
   if (blockInfo.NeedsCopyDispose) {
     // copy_func_helper_decl
-    elements.push_back(buildCopyHelper(CGM, blockInfo));
+    elements.add(buildCopyHelper(CGM, blockInfo));
 
     // destroy_func_decl
-    elements.push_back(buildDisposeHelper(CGM, blockInfo));
+    elements.add(buildDisposeHelper(CGM, blockInfo));
   }
 
   // Signature.  Mandatory ObjC-style method descriptor @encode sequence.
   std::string typeAtEncoding =
     CGM.getContext().getObjCEncodingForBlock(blockInfo.getBlockExpr());
-  elements.push_back(llvm::ConstantExpr::getBitCast(
+  elements.add(llvm::ConstantExpr::getBitCast(
     CGM.GetAddrOfConstantCString(typeAtEncoding).getPointer(), i8p));
   
   // GC layout.
   if (C.getLangOpts().ObjC1) {
     if (CGM.getLangOpts().getGC() != LangOptions::NonGC)
-      elements.push_back(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
+      elements.add(CGM.getObjCRuntime().BuildGCBlockLayout(CGM, blockInfo));
     else
-      elements.push_back(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
+      elements.add(CGM.getObjCRuntime().BuildRCBlockLayout(CGM, blockInfo));
   }
   else
-    elements.push_back(llvm::Constant::getNullValue(i8p));
-
-  llvm::Constant *init = llvm::ConstantStruct::getAnon(elements);
+    elements.addNullPointer(i8p);
 
   unsigned AddrSpace = 0;
   if (C.getLangOpts().OpenCL)
     AddrSpace = C.getTargetAddressSpace(LangAS::opencl_constant);
+
   llvm::GlobalVariable *global =
-    new llvm::GlobalVariable(CGM.getModule(), init->getType(), true,
-                             llvm::GlobalValue::InternalLinkage,
-                             init, "__block_descriptor_tmp", nullptr,
-                             llvm::GlobalValue::NotThreadLocal,
-                             AddrSpace);
+    elements.finishAndCreateGlobal("__block_descriptor_tmp",
+                                   CGM.getPointerAlign(),
+                                   /*constant*/ true,
+                                   llvm::GlobalValue::InternalLinkage,
+                                   AddrSpace);
 
   return llvm::ConstantExpr::getBitCast(global, CGM.getBlockDescriptorType());
 }
@@ -1080,36 +1081,31 @@ static llvm::Constant *buildGlobalBlock(
   assert(blockInfo.CanBeGlobal);
 
   // Generate the constants for the block literal initializer.
-  llvm::Constant *fields[BlockHeaderSize];
+  ConstantBuilder builder(CGM);
+  auto fields = builder.beginStruct();
 
   // isa
-  fields[0] = CGM.getNSConcreteGlobalBlock();
+  fields.add(CGM.getNSConcreteGlobalBlock());
 
   // __flags
   BlockFlags flags = BLOCK_IS_GLOBAL | BLOCK_HAS_SIGNATURE;
   if (blockInfo.UsesStret) flags |= BLOCK_USE_STRET;
                                       
-  fields[1] = llvm::ConstantInt::get(CGM.IntTy, flags.getBitMask());
+  fields.addInt(CGM.IntTy, flags.getBitMask());
 
   // Reserved
-  fields[2] = llvm::Constant::getNullValue(CGM.IntTy);
+  fields.addInt(CGM.IntTy, 0);
 
   // Function
-  fields[3] = blockFn;
+  fields.add(blockFn);
 
   // Descriptor
-  fields[4] = buildBlockDescriptor(CGM, blockInfo);
-
-  llvm::Constant *init = llvm::ConstantStruct::getAnon(fields);
+  fields.add(buildBlockDescriptor(CGM, blockInfo));
 
-  llvm::GlobalVariable *literal =
-    new llvm::GlobalVariable(CGM.getModule(),
-                             init->getType(),
-                             /*constant*/ true,
-                             llvm::GlobalVariable::InternalLinkage,
-                             init,
-                             "__block_literal_global");
-  literal->setAlignment(blockInfo.BlockAlign.getQuantity());
+  llvm::Constant *literal =
+    fields.finishAndCreateGlobal("__block_literal_global",
+                                 blockInfo.BlockAlign,
+                                 /*constant*/ true);
 
   // Return a constant of the appropriately-casted type.
   llvm::Type *requiredType =

Modified: cfe/trunk/lib/CodeGen/CGCUDANV.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCUDANV.cpp?rev=287437&r1=287436&r2=287437&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGCUDANV.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGCUDANV.cpp Sat Nov 19 02:17:24 2016
@@ -15,6 +15,7 @@
 #include "CGCUDARuntime.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "ConstantBuilder.h"
 #include "clang/AST/Decl.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CallSite.h"
@@ -29,7 +30,8 @@ namespace {
 class CGNVCUDARuntime : public CGCUDARuntime {
 
 private:
-  llvm::Type *IntTy, *SizeTy, *VoidTy;
+  llvm::IntegerType *IntTy, *SizeTy;
+  llvm::Type *VoidTy;
   llvm::PointerType *CharPtrTy, *VoidPtrTy, *VoidPtrPtrTy;
 
   /// Convenience reference to LLVM Context
@@ -95,9 +97,9 @@ CGNVCUDARuntime::CGNVCUDARuntime(CodeGen
   CodeGen::CodeGenTypes &Types = CGM.getTypes();
   ASTContext &Ctx = CGM.getContext();
 
-  IntTy = Types.ConvertType(Ctx.IntTy);
-  SizeTy = Types.ConvertType(Ctx.getSizeType());
-  VoidTy = llvm::Type::getVoidTy(Context);
+  IntTy = CGM.IntTy;
+  SizeTy = CGM.SizeTy;
+  VoidTy = CGM.VoidTy;
 
   CharPtrTy = llvm::PointerType::getUnqual(Types.ConvertType(Ctx.CharTy));
   VoidPtrTy = cast<llvm::PointerType>(Types.ConvertType(Ctx.VoidPtrTy));
@@ -296,16 +298,21 @@ llvm::Function *CGNVCUDARuntime::makeMod
         CGM.getTriple().isMacOSX() ? "__NV_CUDA,__fatbin" : ".nvFatBinSegment";
 
     // Create initialized wrapper structure that points to the loaded GPU binary
-    llvm::Constant *Values[] = {
-        llvm::ConstantInt::get(IntTy, 0x466243b1), // Fatbin wrapper magic.
-        llvm::ConstantInt::get(IntTy, 1),          // Fatbin version.
-        makeConstantString(GpuBinaryOrErr.get()->getBuffer(), // Data.
-                           "", FatbinConstantName, 8),
-        llvm::ConstantPointerNull::get(VoidPtrTy)}; // Unused in fatbin v1.
-    llvm::GlobalVariable *FatbinWrapper = new llvm::GlobalVariable(
-        TheModule, FatbinWrapperTy, true, llvm::GlobalValue::InternalLinkage,
-        llvm::ConstantStruct::get(FatbinWrapperTy, Values),
-        "__cuda_fatbin_wrapper");
+    ConstantBuilder Builder(CGM);
+    auto Values = Builder.beginStruct(FatbinWrapperTy);
+    // Fatbin wrapper magic.
+    Values.addInt(IntTy, 0x466243b1);
+    // Fatbin version.
+    Values.addInt(IntTy, 1);
+    // Data.
+    Values.add(makeConstantString(GpuBinaryOrErr.get()->getBuffer(), 
+                                  "", FatbinConstantName, 8));
+    // Unused in fatbin v1.
+    Values.add(llvm::ConstantPointerNull::get(VoidPtrTy));
+    llvm::GlobalVariable *FatbinWrapper =
+      Values.finishAndCreateGlobal("__cuda_fatbin_wrapper",
+                                   CGM.getPointerAlign(),
+                                   /*constant*/ true);
     FatbinWrapper->setSection(FatbinSectionName);
 
     // GpuBinaryHandle = __cudaRegisterFatBinary(&FatbinWrapper);

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=287437&r1=287436&r2=287437&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sat Nov 19 02:17:24 2016
@@ -18,6 +18,7 @@
 #include "CGCleanup.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
+#include "ConstantBuilder.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclObjC.h"
@@ -190,47 +191,17 @@ protected:
   /// Generates a global structure, initialized by the elements in the vector.
   /// The element types must match the types of the structure elements in the
   /// first argument.
-  llvm::GlobalVariable *MakeGlobal(llvm::StructType *Ty,
-                                   ArrayRef<llvm::Constant *> V,
+  llvm::GlobalVariable *MakeGlobal(llvm::Constant *C,
                                    CharUnits Align,
                                    StringRef Name="",
                                    llvm::GlobalValue::LinkageTypes linkage
                                          =llvm::GlobalValue::InternalLinkage) {
-    llvm::Constant *C = llvm::ConstantStruct::get(Ty, V);
-    auto GV = new llvm::GlobalVariable(TheModule, Ty, false,
+    auto GV = new llvm::GlobalVariable(TheModule, C->getType(), false,
                                        linkage, C, Name);
     GV->setAlignment(Align.getQuantity());
     return GV;
   }
 
-  /// Generates a global array.  The vector must contain the same number of
-  /// elements that the array type declares, of the type specified as the array
-  /// element type.
-  llvm::GlobalVariable *MakeGlobal(llvm::ArrayType *Ty,
-                                   ArrayRef<llvm::Constant *> V,
-                                   CharUnits Align,
-                                   StringRef Name="",
-                                   llvm::GlobalValue::LinkageTypes linkage
-                                         =llvm::GlobalValue::InternalLinkage) {
-    llvm::Constant *C = llvm::ConstantArray::get(Ty, V);
-    auto GV = new llvm::GlobalVariable(TheModule, Ty, false,
-                                       linkage, C, Name);
-    GV->setAlignment(Align.getQuantity());
-    return GV;
-  }
-
-  /// Generates a global array, inferring the array type from the specified
-  /// element type and the size of the initialiser.  
-  llvm::GlobalVariable *MakeGlobalArray(llvm::Type *Ty,
-                                        ArrayRef<llvm::Constant *> V,
-                                        CharUnits Align,
-                                        StringRef Name="",
-                                        llvm::GlobalValue::LinkageTypes linkage
-                                         =llvm::GlobalValue::InternalLinkage) {
-    llvm::ArrayType *ArrayTy = llvm::ArrayType::get(Ty, V.size());
-    return MakeGlobal(ArrayTy, V, Align, Name, linkage);
-  }
-
   /// Returns a property name and encoding string.
   llvm::Constant *MakePropertyEncodingString(const ObjCPropertyDecl *PD,
                                              const Decl *Container) {
@@ -251,7 +222,7 @@ protected:
   }
 
   /// Push the property attributes into two structure fields. 
-  void PushPropertyAttributes(std::vector<llvm::Constant*> &Fields,
+  void PushPropertyAttributes(ConstantBuilder::StructBuilder &Fields,
       ObjCPropertyDecl *property, bool isSynthesized=true, bool
       isDynamic=true) {
     int attrs = property->getPropertyAttributes();
@@ -263,7 +234,7 @@ protected:
       attrs &= ~ObjCPropertyDecl::OBJC_PR_strong;
     }
     // The first flags field has the same attribute values as clang uses internally
-    Fields.push_back(llvm::ConstantInt::get(Int8Ty, attrs & 0xff));
+    Fields.addInt(Int8Ty, attrs & 0xff);
     attrs >>= 8;
     attrs <<= 2;
     // For protocol properties, synthesized and dynamic have no meaning, so we
@@ -273,10 +244,10 @@ protected:
     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.push_back(llvm::ConstantInt::get(Int8Ty, attrs & 0xff));
+    Fields.addInt(Int8Ty, attrs & 0xff);
     // Two padding fields
-    Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
-    Fields.push_back(llvm::ConstantInt::get(Int8Ty, 0));
+    Fields.addInt(Int8Ty, 0);
+    Fields.addInt(Int8Ty, 0);
   }
 
   /// Ensures that the value has the required type, by inserting a bitcast if
@@ -1233,14 +1204,15 @@ llvm::Constant *CGObjCGNUstep::GetEHType
   llvm::Constant *typeName =
     ExportUniqueString(className, "__objc_eh_typename_");
 
-  std::vector<llvm::Constant*> fields;
-  fields.push_back(BVtable);
-  fields.push_back(typeName);
-  llvm::Constant *TI = 
-      MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty, nullptr),
-                 fields, CGM.getPointerAlign(),
-                 "__objc_eh_typeinfo_" + className,
-          llvm::GlobalValue::LinkOnceODRLinkage);
+  ConstantBuilder 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 llvm::ConstantExpr::getBitCast(TI, PtrToInt8Ty);
 }
 
@@ -1270,13 +1242,13 @@ ConstantAddress CGObjCGNU::GenerateConst
   else if (isa->getType() != PtrToIdTy)
     isa = llvm::ConstantExpr::getBitCast(isa, PtrToIdTy);
 
-  std::vector<llvm::Constant*> Ivars;
-  Ivars.push_back(isa);
-  Ivars.push_back(MakeConstantString(Str));
-  Ivars.push_back(llvm::ConstantInt::get(IntTy, Str.size()));
-  llvm::Constant *ObjCStr = MakeGlobal(
-    llvm::StructType::get(PtrToIdTy, PtrToInt8Ty, IntTy, nullptr),
-    Ivars, Align, ".objc_str");
+  ConstantBuilder 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);
   ObjCStr = llvm::ConstantExpr::getBitCast(ObjCStr, PtrToInt8Ty);
   ObjCStrings[Str] = ObjCStr;
   ConstantStrings.push_back(ObjCStr);
@@ -1551,13 +1523,20 @@ GenerateMethodList(StringRef ClassName,
                    bool isClassMethodList) {
   if (MethodSels.empty())
     return NULLPtr;
+
+  ConstantBuilder Builder(CGM);
+
+  auto MethodList = Builder.beginStruct();
+  MethodList.addNullPointer(CGM.Int8PtrTy);
+  MethodList.addInt(Int32Ty, MethodTypes.size());
+
   // Get the method structure type.
   llvm::StructType *ObjCMethodTy = llvm::StructType::get(
     PtrToInt8Ty, // Really a selector, but the runtime creates it us.
     PtrToInt8Ty, // Method types
     IMPTy, //Method pointer
     nullptr);
-  std::vector<llvm::Constant*> Methods;
+  auto Methods = MethodList.beginArray();
   for (unsigned int i = 0, e = MethodTypes.size(); i < e; ++i) {
     llvm::Constant *Method =
       TheModule.getFunction(SymbolNameForMethod(ClassName, CategoryName,
@@ -1567,34 +1546,14 @@ GenerateMethodList(StringRef ClassName,
     llvm::Constant *C = MakeConstantString(MethodSels[i].getAsString());
     Method = llvm::ConstantExpr::getBitCast(Method,
         IMPTy);
-    Methods.push_back(
+    Methods.add(
         llvm::ConstantStruct::get(ObjCMethodTy, {C, MethodTypes[i], Method}));
   }
-
-  // Array of method structures
-  llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodTy,
-                                                            Methods.size());
-  llvm::Constant *MethodArray = llvm::ConstantArray::get(ObjCMethodArrayTy,
-                                                         Methods);
-
-  // Structure containing list pointer, array and array count
-  llvm::StructType *ObjCMethodListTy = llvm::StructType::create(VMContext);
-  llvm::Type *NextPtrTy = llvm::PointerType::getUnqual(ObjCMethodListTy);
-  ObjCMethodListTy->setBody(
-      NextPtrTy,
-      IntTy,
-      ObjCMethodArrayTy,
-      nullptr);
-
-  Methods.clear();
-  Methods.push_back(llvm::ConstantPointerNull::get(
-        llvm::PointerType::getUnqual(ObjCMethodListTy)));
-  Methods.push_back(llvm::ConstantInt::get(Int32Ty, MethodTypes.size()));
-  Methods.push_back(MethodArray);
+  MethodList.add(Methods.finish());
 
   // Create an instance of the structure
-  return MakeGlobal(ObjCMethodListTy, Methods, CGM.getPointerAlign(),
-                    ".objc_method_list");
+  return MethodList.finishAndCreateGlobal(".objc_method_list",
+                                          CGM.getPointerAlign());
 }
 
 /// Generates an IvarList.  Used in construction of a objc_class.
@@ -1602,35 +1561,36 @@ llvm::Constant *CGObjCGNU::
 GenerateIvarList(ArrayRef<llvm::Constant *> IvarNames,
                  ArrayRef<llvm::Constant *> IvarTypes,
                  ArrayRef<llvm::Constant *> IvarOffsets) {
-  if (IvarNames.size() == 0)
+  if (IvarNames.empty())
     return NULLPtr;
-  // Get the method structure type.
+
+  ConstantBuilder 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,
     nullptr);
-  std::vector<llvm::Constant*> Ivars;
+
+  // Array of ivar structures.
+  auto Ivars = IvarList.beginArray(ObjCIvarTy);
   for (unsigned int i = 0, e = IvarNames.size() ; i < e ; i++) {
-    Ivars.push_back(llvm::ConstantStruct::get(
-        ObjCIvarTy, {IvarNames[i], IvarTypes[i], IvarOffsets[i]}));
+    auto Ivar = Ivars.beginStruct(ObjCIvarTy);
+    Ivar.add(IvarNames[i]);
+    Ivar.add(IvarTypes[i]);
+    Ivar.add(IvarOffsets[i]);
+    Ivars.add(Ivar.finish());
   }
-
-  // Array of method structures
-  llvm::ArrayType *ObjCIvarArrayTy = llvm::ArrayType::get(ObjCIvarTy,
-      IvarNames.size());
-
-  llvm::Constant *Elements[] = {
-      llvm::ConstantInt::get(IntTy, (int)IvarNames.size()),
-      llvm::ConstantArray::get(ObjCIvarArrayTy, Ivars)};
-  // Structure containing array and array count
-  llvm::StructType *ObjCIvarListTy = llvm::StructType::get(IntTy,
-    ObjCIvarArrayTy,
-    nullptr);
+  IvarList.add(Ivars.finish());
 
   // Create an instance of the structure
-  return MakeGlobal(ObjCIvarListTy, Elements, CGM.getPointerAlign(),
-                    ".objc_ivar_list");
+  return IvarList.finishAndCreateGlobal(".objc_ivar_list",
+                                        CGM.getPointerAlign());
 }
 
 /// Generate a class structure
@@ -1678,34 +1638,55 @@ llvm::Constant *CGObjCGNU::GenerateClass
       IntPtrTy,               // strong_pointers
       IntPtrTy,               // weak_pointers
       nullptr);
-  llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
+
+  ConstantBuilder Builder(CGM);
+  auto Elements = Builder.beginStruct(ClassTy);
+
   // Fill in the structure
-  std::vector<llvm::Constant*> Elements;
-  Elements.push_back(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
-  Elements.push_back(SuperClass);
-  Elements.push_back(MakeConstantString(Name, ".class_name"));
-  Elements.push_back(Zero);
-  Elements.push_back(llvm::ConstantInt::get(LongTy, info));
+
+  // isa 
+  Elements.add(llvm::ConstantExpr::getBitCast(MetaClass, PtrToInt8Ty));
+  // 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) {
     llvm::DataLayout td(&TheModule);
-    Elements.push_back(
-        llvm::ConstantInt::get(LongTy,
-                               td.getTypeSizeInBits(ClassTy) /
-                                 CGM.getContext().getCharWidth()));
+    Elements.addInt(LongTy,
+                    td.getTypeSizeInBits(ClassTy) /
+                      CGM.getContext().getCharWidth());
   } else
-    Elements.push_back(InstanceSize);
-  Elements.push_back(IVars);
-  Elements.push_back(Methods);
-  Elements.push_back(NULLPtr);
-  Elements.push_back(NULLPtr);
-  Elements.push_back(NULLPtr);
-  Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
-  Elements.push_back(NULLPtr);
-  Elements.push_back(llvm::ConstantInt::get(LongTy, 1));
-  Elements.push_back(IvarOffsets);
-  Elements.push_back(Properties);
-  Elements.push_back(StrongIvarBitmap);
-  Elements.push_back(WeakIvarBitmap);
+    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(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
+  // gc_object_type
+  Elements.add(NULLPtr);
+  // abi_version
+  Elements.addInt(LongTy, 1);
+  // 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
@@ -1714,13 +1695,13 @@ llvm::Constant *CGObjCGNU::GenerateClass
           std::string(Name));
   llvm::GlobalVariable *ClassRef = TheModule.getNamedGlobal(ClassSym);
   llvm::Constant *Class =
-    MakeGlobal(ClassTy, Elements, CGM.getPointerAlign(), ClassSym,
-               llvm::GlobalValue::ExternalLinkage);
+    Elements.finishAndCreateGlobal(ClassSym, CGM.getPointerAlign(), false,
+                                   llvm::GlobalValue::ExternalLinkage);
   if (ClassRef) {
-      ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class,
+    ClassRef->replaceAllUsesWith(llvm::ConstantExpr::getBitCast(Class,
                   ClassRef->getType()));
-      ClassRef->removeFromParent();
-      Class->setName(ClassSym);
+    ClassRef->removeFromParent();
+    Class->setName(ClassSym);
   }
   return Class;
 }
@@ -1729,38 +1710,33 @@ llvm::Constant *CGObjCGNU::
 GenerateProtocolMethodList(ArrayRef<llvm::Constant *> MethodNames,
                            ArrayRef<llvm::Constant *> MethodTypes) {
   // Get the method structure type.
-  llvm::StructType *ObjCMethodDescTy = llvm::StructType::get(
-    PtrToInt8Ty, // Really a selector, but the runtime does the casting for us.
-    PtrToInt8Ty,
-    nullptr);
-  std::vector<llvm::Constant*> Methods;
+  llvm::StructType *ObjCMethodDescTy =
+    llvm::StructType::get(CGM.getLLVMContext(), { PtrToInt8Ty, PtrToInt8Ty });
+  ConstantBuilder Builder(CGM);
+  auto MethodList = Builder.beginStruct();
+  MethodList.addInt(IntTy, MethodNames.size());
+  auto Methods = MethodList.beginArray(ObjCMethodDescTy);
   for (unsigned int i = 0, e = MethodTypes.size() ; i < e ; i++) {
-    Methods.push_back(llvm::ConstantStruct::get(
-        ObjCMethodDescTy, {MethodNames[i], MethodTypes[i]}));
-  }
-  llvm::ArrayType *ObjCMethodArrayTy = llvm::ArrayType::get(ObjCMethodDescTy,
-      MethodNames.size());
-  llvm::Constant *Array = llvm::ConstantArray::get(ObjCMethodArrayTy,
-                                                   Methods);
-  llvm::StructType *ObjCMethodDescListTy = llvm::StructType::get(
-      IntTy, ObjCMethodArrayTy, nullptr);
-  Methods.clear();
-  Methods.push_back(llvm::ConstantInt::get(IntTy, MethodNames.size()));
-  Methods.push_back(Array);
-  return MakeGlobal(ObjCMethodDescListTy, Methods, CGM.getPointerAlign(),
-                    ".objc_method_list");
+    auto Method = Methods.beginStruct(ObjCMethodDescTy);
+    Method.add(MethodNames[i]);
+    Method.add(MethodTypes[i]);
+    Methods.add(Method.finish());
+  }
+  MethodList.add(Methods.finish());
+  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){
-  llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrToInt8Ty,
-      Protocols.size());
-  llvm::StructType *ProtocolListTy = llvm::StructType::get(
-      PtrTy, //Should be a recurisve pointer, but it's always NULL here.
-      SizeTy,
-      ProtocolArrayTy,
-      nullptr);
-  std::vector<llvm::Constant*> Elements;
+llvm::Constant *
+CGObjCGNU::GenerateProtocolList(ArrayRef<std::string> Protocols) {
+
+  ConstantBuilder Builder(CGM);
+  auto ProtocolList = Builder.beginStruct();
+  ProtocolList.add(NULLPtr);
+  ProtocolList.addInt(LongTy, Protocols.size());
+
+  auto Elements = ProtocolList.beginArray(PtrToInt8Ty);
   for (const std::string *iter = Protocols.begin(), *endIter = Protocols.end();
       iter != endIter ; iter++) {
     llvm::Constant *protocol = nullptr;
@@ -1773,16 +1749,11 @@ llvm::Constant *CGObjCGNU::GenerateProto
     }
     llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(protocol,
                                                            PtrToInt8Ty);
-    Elements.push_back(Ptr);
+    Elements.add(Ptr);
   }
-  llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
-      Elements);
-  Elements.clear();
-  Elements.push_back(NULLPtr);
-  Elements.push_back(llvm::ConstantInt::get(LongTy, Protocols.size()));
-  Elements.push_back(ProtocolArray);
-  return MakeGlobal(ProtocolListTy, Elements, CGM.getPointerAlign(),
-                    ".objc_protocol_list");
+  ProtocolList.add(Elements.finish());
+  return ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
+                                            CGM.getPointerAlign());
 }
 
 llvm::Value *CGObjCGNU::GenerateProtocolRef(CodeGenFunction &CGF,
@@ -1793,33 +1764,28 @@ llvm::Value *CGObjCGNU::GenerateProtocol
   return CGF.Builder.CreateBitCast(protocol, llvm::PointerType::getUnqual(T));
 }
 
-llvm::Constant *CGObjCGNU::GenerateEmptyProtocol(
-  const std::string &ProtocolName) {
-  SmallVector<std::string, 0> EmptyStringVector;
-  SmallVector<llvm::Constant*, 0> EmptyConstantVector;
-
-  llvm::Constant *ProtocolList = GenerateProtocolList(EmptyStringVector);
-  llvm::Constant *MethodList =
-    GenerateProtocolMethodList(EmptyConstantVector, EmptyConstantVector);
+llvm::Constant *
+CGObjCGNU::GenerateEmptyProtocol(const std::string &ProtocolName) {
+  llvm::Constant *ProtocolList = GenerateProtocolList({});
+  llvm::Constant *MethodList = GenerateProtocolMethodList({}, {});
   // Protocols are objects containing lists of the methods implemented and
   // protocols adopted.
-  llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
-      PtrToInt8Ty,
-      ProtocolList->getType(),
-      MethodList->getType(),
-      MethodList->getType(),
-      MethodList->getType(),
-      MethodList->getType(),
-      nullptr);
+  ConstantBuilder 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.
-  llvm::Constant *Elements[] = {
-      llvm::ConstantExpr::getIntToPtr(
-          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy),
-      MakeConstantString(ProtocolName, ".objc_protocol_name"), ProtocolList,
-      MethodList, MethodList, MethodList, MethodList};
-  return MakeGlobal(ProtocolTy, Elements, CGM.getPointerAlign(),
-                    ".objc_protocol");
+  Elements.add(llvm::ConstantExpr::getIntToPtr(
+          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
+
+  Elements.add(MakeConstantString(ProtocolName, ".objc_protocol_name"));
+  Elements.add(ProtocolList);
+  Elements.add(MethodList);
+  Elements.add(MethodList);
+  Elements.add(MethodList);
+  Elements.add(MethodList);
+  return Elements.finishAndCreateGlobal(".objc_protocol",
+                                        CGM.getPointerAlign());
 }
 
 void CGObjCGNU::GenerateProtocol(const ObjCProtocolDecl *PD) {
@@ -1886,142 +1852,143 @@ void CGObjCGNU::GenerateProtocol(const O
   // 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::StructType *PropertyMetadataTy = llvm::StructType::get(
-          PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
-          PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, nullptr);
-  std::vector<llvm::Constant*> Properties;
-  std::vector<llvm::Constant*> OptionalProperties;
 
-  // Add all of the property methods need adding to the method list and to the
-  // property metadata list.
-  for (auto *property : PD->instance_properties()) {
-    std::vector<llvm::Constant*> Fields;
-
-    Fields.push_back(MakePropertyEncodingString(property, nullptr));
-    PushPropertyAttributes(Fields, property);
+  llvm::Constant *PropertyList;
+  llvm::Constant *OptionalPropertyList;
+  {
+    llvm::StructType *propertyMetadataTy =
+      llvm::StructType::get(CGM.getLLVMContext(),
+        { PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
+          PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
+
+    unsigned numReqProperties = 0, numOptProperties = 0;
+    for (auto property : PD->instance_properties()) {
+      if (property->isOptional())
+        numOptProperties++;
+      else
+        numReqProperties++;
+    }
+
+    ConstantBuilder reqPropertyListBuilder(CGM);
+    auto reqPropertiesList = reqPropertyListBuilder.beginStruct();
+    reqPropertiesList.addInt(IntTy, numReqProperties);
+    reqPropertiesList.add(NULLPtr);
+    auto reqPropertiesArray = reqPropertiesList.beginArray(propertyMetadataTy);
+
+    ConstantBuilder optPropertyListBuilder(CGM);
+    auto optPropertiesList = optPropertyListBuilder.beginStruct();
+    optPropertiesList.addInt(IntTy, numOptProperties);
+    optPropertiesList.add(NULLPtr);
+    auto optPropertiesArray = optPropertiesList.beginArray(propertyMetadataTy);
+
+    // Add all of the property methods need adding to the method list and to the
+    // property metadata list.
+    for (auto *property : PD->instance_properties()) {
+      auto &propertiesArray =
+        (property->isOptional() ? optPropertiesArray : reqPropertiesArray);
+      auto fields = propertiesArray.beginStruct(propertyMetadataTy);
+
+      fields.add(MakePropertyEncodingString(property, nullptr));
+      PushPropertyAttributes(fields, property);
+
+      if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
+        std::string typeStr;
+        Context.getObjCEncodingForMethodDecl(getter, typeStr);
+        llvm::Constant *typeEncoding = MakeConstantString(typeStr);
+        InstanceMethodTypes.push_back(typeEncoding);
+        fields.add(MakeConstantString(getter->getSelector().getAsString()));
+        fields.add(typeEncoding);
+      } else {
+        fields.add(NULLPtr);
+        fields.add(NULLPtr);
+      }
+      if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
+        std::string typeStr;
+        Context.getObjCEncodingForMethodDecl(setter, typeStr);
+        llvm::Constant *typeEncoding = MakeConstantString(typeStr);
+        InstanceMethodTypes.push_back(typeEncoding);
+        fields.add(MakeConstantString(setter->getSelector().getAsString()));
+        fields.add(typeEncoding);
+      } else {
+        fields.add(NULLPtr);
+        fields.add(NULLPtr);
+      }
 
-    if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
-      std::string TypeStr;
-      Context.getObjCEncodingForMethodDecl(getter,TypeStr);
-      llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
-      InstanceMethodTypes.push_back(TypeEncoding);
-      Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
-      Fields.push_back(TypeEncoding);
-    } else {
-      Fields.push_back(NULLPtr);
-      Fields.push_back(NULLPtr);
-    }
-    if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
-      std::string TypeStr;
-      Context.getObjCEncodingForMethodDecl(setter,TypeStr);
-      llvm::Constant *TypeEncoding = MakeConstantString(TypeStr);
-      InstanceMethodTypes.push_back(TypeEncoding);
-      Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
-      Fields.push_back(TypeEncoding);
-    } else {
-      Fields.push_back(NULLPtr);
-      Fields.push_back(NULLPtr);
-    }
-    if (property->getPropertyImplementation() == ObjCPropertyDecl::Optional) {
-      OptionalProperties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
-    } else {
-      Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
+      propertiesArray.add(fields.finish());
     }
+
+    reqPropertiesList.add(reqPropertiesArray.finish());
+    PropertyList =
+      reqPropertiesList.finishAndCreateGlobal(".objc_property_list",
+                                              CGM.getPointerAlign());
+
+    optPropertiesList.add(optPropertiesArray.finish());
+    OptionalPropertyList =
+      optPropertiesList.finishAndCreateGlobal(".objc_property_list",
+                                              CGM.getPointerAlign());
   }
-  llvm::Constant *PropertyArray = llvm::ConstantArray::get(
-      llvm::ArrayType::get(PropertyMetadataTy, Properties.size()), Properties);
-  llvm::Constant* PropertyListInitFields[] =
-    {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
-
-  llvm::Constant *PropertyListInit =
-      llvm::ConstantStruct::getAnon(PropertyListInitFields);
-  llvm::Constant *PropertyList = new llvm::GlobalVariable(TheModule,
-      PropertyListInit->getType(), false, llvm::GlobalValue::InternalLinkage,
-      PropertyListInit, ".objc_property_list");
-
-  llvm::Constant *OptionalPropertyArray =
-      llvm::ConstantArray::get(llvm::ArrayType::get(PropertyMetadataTy,
-          OptionalProperties.size()) , OptionalProperties);
-  llvm::Constant* OptionalPropertyListInitFields[] = {
-      llvm::ConstantInt::get(IntTy, OptionalProperties.size()), NULLPtr,
-      OptionalPropertyArray };
-
-  llvm::Constant *OptionalPropertyListInit =
-      llvm::ConstantStruct::getAnon(OptionalPropertyListInitFields);
-  llvm::Constant *OptionalPropertyList = new llvm::GlobalVariable(TheModule,
-          OptionalPropertyListInit->getType(), false,
-          llvm::GlobalValue::InternalLinkage, OptionalPropertyListInit,
-          ".objc_property_list");
 
   // Protocols are objects containing lists of the methods implemented and
   // protocols adopted.
-  llvm::StructType *ProtocolTy = llvm::StructType::get(IdTy,
-      PtrToInt8Ty,
-      ProtocolList->getType(),
-      InstanceMethodList->getType(),
-      ClassMethodList->getType(),
-      OptionalInstanceMethodList->getType(),
-      OptionalClassMethodList->getType(),
-      PropertyList->getType(),
-      OptionalPropertyList->getType(),
-      nullptr);
   // The isa pointer must be set to a magic number so the runtime knows it's
   // the correct layout.
-  llvm::Constant *Elements[] = {
+  ConstantBuilder Builder(CGM);
+  auto Elements = Builder.beginStruct();
+  Elements.add(
       llvm::ConstantExpr::getIntToPtr(
-          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy),
-      MakeConstantString(ProtocolName, ".objc_protocol_name"), ProtocolList,
-      InstanceMethodList, ClassMethodList, OptionalInstanceMethodList,
-      OptionalClassMethodList, PropertyList, OptionalPropertyList};
+          llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
+  Elements.add(
+      MakeConstantString(ProtocolName, ".objc_protocol_name"));
+  Elements.add(ProtocolList);
+  Elements.add(InstanceMethodList);
+  Elements.add(ClassMethodList);
+  Elements.add(OptionalInstanceMethodList);
+  Elements.add(OptionalClassMethodList);
+  Elements.add(PropertyList);
+  Elements.add(OptionalPropertyList);
   ExistingProtocols[ProtocolName] =
-    llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolTy, Elements,
-          CGM.getPointerAlign(), ".objc_protocol"), IdTy);
+    llvm::ConstantExpr::getBitCast(
+      Elements.finishAndCreateGlobal(".objc_protocol", CGM.getPointerAlign()),
+      IdTy);
 }
 void CGObjCGNU::GenerateProtocolHolderCategory() {
   // Collect information about instance methods
   SmallVector<Selector, 1> MethodSels;
   SmallVector<llvm::Constant*, 1> MethodTypes;
 
-  std::vector<llvm::Constant*> Elements;
+  ConstantBuilder Builder(CGM);
+  auto Elements = Builder.beginStruct();
+
   const std::string ClassName = "__ObjC_Protocol_Holder_Ugly_Hack";
   const std::string CategoryName = "AnotherHack";
-  Elements.push_back(MakeConstantString(CategoryName));
-  Elements.push_back(MakeConstantString(ClassName));
+  Elements.add(MakeConstantString(CategoryName));
+  Elements.add(MakeConstantString(ClassName));
   // Instance method list
-  Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
+  Elements.add(llvm::ConstantExpr::getBitCast(GenerateMethodList(
           ClassName, CategoryName, MethodSels, MethodTypes, false), PtrTy));
   // Class method list
-  Elements.push_back(llvm::ConstantExpr::getBitCast(GenerateMethodList(
+  Elements.add(llvm::ConstantExpr::getBitCast(GenerateMethodList(
           ClassName, CategoryName, MethodSels, MethodTypes, true), PtrTy));
+
   // Protocol list
-  llvm::ArrayType *ProtocolArrayTy = llvm::ArrayType::get(PtrTy,
-      ExistingProtocols.size());
-  llvm::StructType *ProtocolListTy = llvm::StructType::get(
-      PtrTy, //Should be a recurisve pointer, but it's always NULL here.
-      SizeTy,
-      ProtocolArrayTy,
-      nullptr);
-  std::vector<llvm::Constant*> ProtocolElements;
-  for (llvm::StringMapIterator<llvm::Constant*> iter =
-       ExistingProtocols.begin(), endIter = ExistingProtocols.end();
+  ConstantBuilder 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++) {
     llvm::Constant *Ptr = llvm::ConstantExpr::getBitCast(iter->getValue(),
             PtrTy);
-    ProtocolElements.push_back(Ptr);
+    ProtocolElements.add(Ptr);
   }
-  llvm::Constant * ProtocolArray = llvm::ConstantArray::get(ProtocolArrayTy,
-      ProtocolElements);
-  ProtocolElements.clear();
-  ProtocolElements.push_back(NULLPtr);
-  ProtocolElements.push_back(llvm::ConstantInt::get(LongTy,
-              ExistingProtocols.size()));
-  ProtocolElements.push_back(ProtocolArray);
-  Elements.push_back(llvm::ConstantExpr::getBitCast(MakeGlobal(ProtocolListTy,
-                  ProtocolElements, CGM.getPointerAlign(),
-                  ".objc_protocol_list"), PtrTy));
+  ProtocolList.add(ProtocolElements.finish());
+  Elements.add(llvm::ConstantExpr::getBitCast(
+                   ProtocolList.finishAndCreateGlobal(".objc_protocol_list",
+                                                      CGM.getPointerAlign()),
+                   PtrTy));
   Categories.push_back(llvm::ConstantExpr::getBitCast(
-        MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
-            PtrTy, PtrTy, PtrTy, nullptr), Elements, CGM.getPointerAlign()),
+        Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
         PtrTy));
 }
 
@@ -2056,13 +2023,16 @@ llvm::Constant *CGObjCGNU::MakeBitField(
     }
     values.push_back(llvm::ConstantInt::get(Int32Ty, word));
   }
-  llvm::ArrayType *arrayTy = llvm::ArrayType::get(Int32Ty, values.size());
-  llvm::Constant *array = llvm::ConstantArray::get(arrayTy, values);
-  llvm::Constant *fields[2] = {
-      llvm::ConstantInt::get(Int32Ty, values.size()),
-      array };
-  llvm::Constant *GS = MakeGlobal(llvm::StructType::get(Int32Ty, arrayTy,
-        nullptr), fields, CharUnits::fromQuantity(4));
+
+  ConstantBuilder builder(CGM);
+  auto fields = builder.beginStruct();
+  fields.addInt(Int32Ty, values.size());
+  auto array = fields.beginArray();
+  for (auto v : values) array.add(v);
+  fields.add(array.finish());
+
+  llvm::Constant *GS =
+    fields.finishAndCreateGlobal("", CharUnits::fromQuantity(4));
   llvm::Constant *ptr = llvm::ConstantExpr::getPtrToInt(GS, IntPtrTy);
   return ptr;
 }
@@ -2098,23 +2068,25 @@ void CGObjCGNU::GenerateCategory(const O
        E = Protos.end(); I != E; ++I)
     Protocols.push_back((*I)->getNameAsString());
 
-  llvm::Constant *Elements[] = {
-      MakeConstantString(CategoryName), MakeConstantString(ClassName),
-      // Instance method list
-      llvm::ConstantExpr::getBitCast(
+  ConstantBuilder Builder(CGM);
+  auto Elements = Builder.beginStruct();
+  Elements.add(MakeConstantString(CategoryName));
+  Elements.add(MakeConstantString(ClassName));
+  // Instance method list
+  Elements.add(llvm::ConstantExpr::getBitCast(
           GenerateMethodList(ClassName, CategoryName, InstanceMethodSels,
                              InstanceMethodTypes, false),
-          PtrTy),
-      // Class method list
-      llvm::ConstantExpr::getBitCast(GenerateMethodList(ClassName, CategoryName,
-                                                        ClassMethodSels,
-                                                        ClassMethodTypes, true),
-                                     PtrTy),
-      // Protocol list
-      llvm::ConstantExpr::getBitCast(GenerateProtocolList(Protocols), PtrTy)};
+          PtrTy));
+  // Class method list
+  Elements.add(llvm::ConstantExpr::getBitCast(
+                 GenerateMethodList(ClassName, CategoryName,
+                                    ClassMethodSels, ClassMethodTypes, true),
+                  PtrTy));
+  // Protocol list
+  Elements.add(llvm::ConstantExpr::getBitCast(
+                 GenerateProtocolList(Protocols), PtrTy));
   Categories.push_back(llvm::ConstantExpr::getBitCast(
-        MakeGlobal(llvm::StructType::get(PtrToInt8Ty, PtrToInt8Ty,
-            PtrTy, PtrTy, PtrTy, nullptr), Elements, CGM.getPointerAlign()),
+        Elements.finishAndCreateGlobal("", CGM.getPointerAlign()),
         PtrTy));
 }
 
@@ -2124,23 +2096,35 @@ llvm::Constant *CGObjCGNU::GeneratePrope
   ASTContext &Context = CGM.getContext();
   // Property metadata: name, attributes, attributes2, padding1, padding2,
   // setter name, setter types, getter name, getter types.
-  llvm::StructType *PropertyMetadataTy = llvm::StructType::get(
-          PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
-          PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty, nullptr);
-  std::vector<llvm::Constant*> Properties;
+  llvm::StructType *propertyMetadataTy =
+    llvm::StructType::get(CGM.getLLVMContext(),
+        { PtrToInt8Ty, Int8Ty, Int8Ty, Int8Ty, Int8Ty, PtrToInt8Ty,
+          PtrToInt8Ty, PtrToInt8Ty, PtrToInt8Ty });
+
+  unsigned numProperties = 0;
+  for (auto *propertyImpl : OID->property_impls()) {
+    (void) propertyImpl;
+    numProperties++;
+  }
+
+  ConstantBuilder builder(CGM);
+  auto propertyList = builder.beginStruct();
+  propertyList.addInt(IntTy, numProperties);
+  propertyList.add(NULLPtr);
+  auto properties = propertyList.beginArray(propertyMetadataTy);
 
   // Add all of the property methods need adding to the method list and to the
   // property metadata list.
   for (auto *propertyImpl : OID->property_impls()) {
-    std::vector<llvm::Constant*> Fields;
+    auto fields = properties.beginStruct(propertyMetadataTy);
     ObjCPropertyDecl *property = propertyImpl->getPropertyDecl();
     bool isSynthesized = (propertyImpl->getPropertyImplementation() == 
         ObjCPropertyImplDecl::Synthesize);
     bool isDynamic = (propertyImpl->getPropertyImplementation() == 
         ObjCPropertyImplDecl::Dynamic);
 
-    Fields.push_back(MakePropertyEncodingString(property, OID));
-    PushPropertyAttributes(Fields, property, isSynthesized, isDynamic);
+    fields.add(MakePropertyEncodingString(property, OID));
+    PushPropertyAttributes(fields, property, isSynthesized, isDynamic);
     if (ObjCMethodDecl *getter = property->getGetterMethodDecl()) {
       std::string TypeStr;
       Context.getObjCEncodingForMethodDecl(getter,TypeStr);
@@ -2149,11 +2133,11 @@ llvm::Constant *CGObjCGNU::GeneratePrope
         InstanceMethodTypes.push_back(TypeEncoding);
         InstanceMethodSels.push_back(getter->getSelector());
       }
-      Fields.push_back(MakeConstantString(getter->getSelector().getAsString()));
-      Fields.push_back(TypeEncoding);
+      fields.add(MakeConstantString(getter->getSelector().getAsString()));
+      fields.add(TypeEncoding);
     } else {
-      Fields.push_back(NULLPtr);
-      Fields.push_back(NULLPtr);
+      fields.add(NULLPtr);
+      fields.add(NULLPtr);
     }
     if (ObjCMethodDecl *setter = property->getSetterMethodDecl()) {
       std::string TypeStr;
@@ -2163,26 +2147,18 @@ llvm::Constant *CGObjCGNU::GeneratePrope
         InstanceMethodTypes.push_back(TypeEncoding);
         InstanceMethodSels.push_back(setter->getSelector());
       }
-      Fields.push_back(MakeConstantString(setter->getSelector().getAsString()));
-      Fields.push_back(TypeEncoding);
+      fields.add(MakeConstantString(setter->getSelector().getAsString()));
+      fields.add(TypeEncoding);
     } else {
-      Fields.push_back(NULLPtr);
-      Fields.push_back(NULLPtr);
+      fields.add(NULLPtr);
+      fields.add(NULLPtr);
     }
-    Properties.push_back(llvm::ConstantStruct::get(PropertyMetadataTy, Fields));
+    properties.add(fields.finish());
   }
-  llvm::ArrayType *PropertyArrayTy =
-      llvm::ArrayType::get(PropertyMetadataTy, Properties.size());
-  llvm::Constant *PropertyArray = llvm::ConstantArray::get(PropertyArrayTy,
-          Properties);
-  llvm::Constant* PropertyListInitFields[] =
-    {llvm::ConstantInt::get(IntTy, Properties.size()), NULLPtr, PropertyArray};
-
-  llvm::Constant *PropertyListInit =
-      llvm::ConstantStruct::getAnon(PropertyListInitFields);
-  return new llvm::GlobalVariable(TheModule, PropertyListInit->getType(), false,
-          llvm::GlobalValue::InternalLinkage, PropertyListInit,
-          ".objc_property_list");
+  propertyList.add(properties.finish());
+
+  return propertyList.finishAndCreateGlobal(".objc_property_list",
+                                            CGM.getPointerAlign());
 }
 
 void CGObjCGNU::RegisterAlias(const ObjCCompatibleAliasDecl *OAD) {
@@ -2231,7 +2207,8 @@ void CGObjCGNU::GenerateClass(const ObjC
   SmallVector<llvm::Constant*, 16> IvarTypes;
   SmallVector<llvm::Constant*, 16> IvarOffsets;
 
-  std::vector<llvm::Constant*> IvarOffsetValues;
+  ConstantBuilder IvarOffsetBuilder(CGM);
+  auto IvarOffsetValues = IvarOffsetBuilder.beginArray(PtrToIntTy);
   SmallVector<bool, 16> WeakIvars;
   SmallVector<bool, 16> StrongIvars;
 
@@ -2275,7 +2252,7 @@ void CGObjCGNU::GenerateClass(const ObjC
           "__objc_ivar_offset_value_" + ClassName +"." +
           IVD->getNameAsString());
       IvarOffsets.push_back(OffsetValue);
-      IvarOffsetValues.push_back(OffsetVar);
+      IvarOffsetValues.add(OffsetVar);
       Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
       switch (lt) {
         case Qualifiers::OCL_Strong:
@@ -2294,8 +2271,8 @@ void CGObjCGNU::GenerateClass(const ObjC
   llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
   llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
   llvm::GlobalVariable *IvarOffsetArray =
-    MakeGlobalArray(PtrToIntTy, IvarOffsetValues, CGM.getPointerAlign(),
-                    ".ivar.offsets");
+    IvarOffsetValues.finishAndCreateGlobal(".ivar.offsets",
+                                           CGM.getPointerAlign());
 
   // Collect information about instance methods
   SmallVector<Selector, 16> InstanceMethodSels;
@@ -2461,21 +2438,18 @@ llvm::Function *CGObjCGNU::ModuleInitFun
     if (StringClass.empty()) StringClass = "NXConstantString";
 
     Elements.push_back(MakeConstantString(StringClass,
-                ".objc_static_class_name"));
+                                          ".objc_static_class_name"));
     Elements.push_back(llvm::ConstantArray::get(StaticsArrayTy,
-       ConstantStrings));
-    llvm::StructType *StaticsListTy =
-      llvm::StructType::get(PtrToInt8Ty, StaticsArrayTy, nullptr);
-    llvm::Type *StaticsListPtrTy =
-      llvm::PointerType::getUnqual(StaticsListTy);
-    Statics = MakeGlobal(StaticsListTy, Elements, CGM.getPointerAlign(),
-                         ".objc_statics");
+                                                ConstantStrings));
+    Statics = MakeGlobal(llvm::ConstantStruct::getAnon(Elements),
+                         CGM.getPointerAlign(), ".objc_statics");
+    llvm::Type *StaticsListPtrTy = Statics->getType();
     llvm::ArrayType *StaticsListArrayTy =
       llvm::ArrayType::get(StaticsListPtrTy, 2);
     Elements.clear();
     Elements.push_back(Statics);
     Elements.push_back(llvm::Constant::getNullValue(StaticsListPtrTy));
-    Statics = MakeGlobal(StaticsListArrayTy, Elements,
+    Statics = MakeGlobal(llvm::ConstantArray::get(StaticsListArrayTy, Elements),
                          CGM.getPointerAlign(), ".objc_statics_ptr");
     Statics = llvm::ConstantExpr::getBitCast(Statics, PtrTy);
   }
@@ -2489,7 +2463,8 @@ llvm::Function *CGObjCGNU::ModuleInitFun
 
   Elements.clear();
   // Pointer to an array of selectors used in this module.
-  std::vector<llvm::Constant*> Selectors;
+  ConstantBuilder SelectorBuilder(CGM);
+  auto Selectors = SelectorBuilder.beginArray(SelStructTy);
   std::vector<llvm::GlobalAlias*> SelectorAliases;
   for (SelectorMap::iterator iter = SelectorTable.begin(),
       iterEnd = SelectorTable.end(); iter != iterEnd ; ++iter) {
@@ -2505,10 +2480,10 @@ llvm::Function *CGObjCGNU::ModuleInitFun
       if (!i->first.empty())
         SelectorTypeEncoding = MakeConstantString(i->first, ".objc_sel_types");
 
-      Elements.push_back(SelName);
-      Elements.push_back(SelectorTypeEncoding);
-      Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
-      Elements.clear();
+      auto SelStruct = Selectors.beginStruct(SelStructTy);
+      SelStruct.add(SelName);
+      SelStruct.add(SelectorTypeEncoding);
+      Selectors.add(SelStruct.finish());
 
       // Store the selector alias for later replacement
       SelectorAliases.push_back(i->second);
@@ -2519,16 +2494,18 @@ llvm::Function *CGObjCGNU::ModuleInitFun
   // 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.
-  Elements.push_back(NULLPtr);
-  Elements.push_back(NULLPtr);
-  Selectors.push_back(llvm::ConstantStruct::get(SelStructTy, Elements));
-  Elements.clear();
+  {
+    auto SelStruct = Selectors.beginStruct(SelStructTy);
+    SelStruct.add(NULLPtr);
+    SelStruct.add(NULLPtr);
+    Selectors.add(SelStruct.finish());
+  }
 
   // Number of static selectors
   Elements.push_back(llvm::ConstantInt::get(LongTy, SelectorCount));
   llvm::GlobalVariable *SelectorList =
-      MakeGlobalArray(SelStructTy, Selectors, CGM.getPointerAlign(),
-                      ".objc_selector_list");
+      Selectors.finishAndCreateGlobal(".objc_selector_list",
+                                      CGM.getPointerAlign());
   Elements.push_back(llvm::ConstantExpr::getBitCast(SelectorList,
     SelStructPtrTy));
 
@@ -2562,7 +2539,8 @@ llvm::Function *CGObjCGNU::ModuleInitFun
   Elements.push_back(ClassList);
   // Construct the symbol table
   llvm::Constant *SymTab =
-    MakeGlobal(SymTabTy, Elements, CGM.getPointerAlign());
+    MakeGlobal(llvm::ConstantStruct::get(SymTabTy, Elements),
+               CGM.getPointerAlign());
 
   // The symbol table is contained in a module which has some version-checking
   // constants
@@ -2603,7 +2581,9 @@ llvm::Function *CGObjCGNU::ModuleInitFun
         break;
     }
 
-  llvm::Value *Module = MakeGlobal(ModuleTy, Elements, CGM.getPointerAlign());
+  llvm::Value *Module =
+    MakeGlobal(llvm::ConstantStruct::get(ModuleTy, Elements),
+               CGM.getPointerAlign());
 
   // Create the load function calling the runtime entry point with the module
   // structure

Modified: cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp?rev=287437&r1=287436&r2=287437&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGOpenMPRuntime.cpp Sat Nov 19 02:17:24 2016
@@ -15,6 +15,7 @@
 #include "CGCleanup.h"
 #include "CGOpenMPRuntime.h"
 #include "CodeGenFunction.h"
+#include "ConstantBuilder.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/StmtOpenMP.h"
 #include "llvm/ADT/ArrayRef.h"
@@ -906,18 +907,19 @@ Address CGOpenMPRuntime::getOrCreateDefa
       DefaultOpenMPPSource =
           llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy);
     }
-    auto DefaultOpenMPLocation = new llvm::GlobalVariable(
-        CGM.getModule(), IdentTy, /*isConstant*/ true,
-        llvm::GlobalValue::PrivateLinkage, /*Initializer*/ nullptr);
+
+    ConstantBuilder builder(CGM);
+    auto fields = builder.beginStruct(IdentTy);
+    fields.addInt(CGM.Int32Ty, 0);
+    fields.addInt(CGM.Int32Ty, Flags);
+    fields.addInt(CGM.Int32Ty, 0);
+    fields.addInt(CGM.Int32Ty, 0);
+    fields.add(DefaultOpenMPPSource);
+    auto DefaultOpenMPLocation =
+      fields.finishAndCreateGlobal("", Align, /*isConstant*/ true,
+                                   llvm::GlobalValue::PrivateLinkage);
     DefaultOpenMPLocation->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
-    DefaultOpenMPLocation->setAlignment(Align.getQuantity());
 
-    llvm::Constant *Zero = llvm::ConstantInt::get(CGM.Int32Ty, 0, true);
-    llvm::Constant *Values[] = {Zero,
-                                llvm::ConstantInt::get(CGM.Int32Ty, Flags),
-                                Zero, Zero, DefaultOpenMPPSource};
-    llvm::Constant *Init = llvm::ConstantStruct::get(IdentTy, Values);
-    DefaultOpenMPLocation->setInitializer(Init);
     OpenMPDefaultLocMap[Flags] = Entry = DefaultOpenMPLocation;
   }
   return Address(Entry, Align);
@@ -2810,9 +2812,10 @@ CGOpenMPRuntime::createOffloadingBinaryD
       ".omp_offloading.entries_end");
 
   // Create all device images
-  llvm::SmallVector<llvm::Constant *, 4> DeviceImagesEntires;
   auto *DeviceImageTy = cast<llvm::StructType>(
       CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy()));
+  ConstantBuilder DeviceImagesBuilder(CGM);
+  auto DeviceImagesEntries = DeviceImagesBuilder.beginArray(DeviceImageTy);
 
   for (unsigned i = 0; i < Devices.size(); ++i) {
     StringRef T = Devices[i].getTriple();
@@ -2824,22 +2827,19 @@ CGOpenMPRuntime::createOffloadingBinaryD
         M, CGM.Int8Ty, /*isConstant=*/true, llvm::GlobalValue::ExternalLinkage,
         /*Initializer=*/nullptr, Twine(".omp_offloading.img_end.") + Twine(T));
 
-    llvm::Constant *Dev =
-        llvm::ConstantStruct::get(DeviceImageTy, ImgBegin, ImgEnd,
-                                  HostEntriesBegin, HostEntriesEnd, nullptr);
-    DeviceImagesEntires.push_back(Dev);
+    auto Dev = DeviceImagesEntries.beginStruct(DeviceImageTy);
+    Dev.add(ImgBegin);
+    Dev.add(ImgEnd);
+    Dev.add(HostEntriesBegin);
+    Dev.add(HostEntriesEnd);
+    DeviceImagesEntries.add(Dev.finish());
   }
 
   // Create device images global array.
-  llvm::ArrayType *DeviceImagesInitTy =
-      llvm::ArrayType::get(DeviceImageTy, DeviceImagesEntires.size());
-  llvm::Constant *DeviceImagesInit =
-      llvm::ConstantArray::get(DeviceImagesInitTy, DeviceImagesEntires);
-
-  llvm::GlobalVariable *DeviceImages = new llvm::GlobalVariable(
-      M, DeviceImagesInitTy, /*isConstant=*/true,
-      llvm::GlobalValue::InternalLinkage, DeviceImagesInit,
-      ".omp_offloading.device_images");
+  llvm::GlobalVariable *DeviceImages =
+    DeviceImagesEntries.finishAndCreateGlobal(".omp_offloading.device_images",
+                                              CGM.getPointerAlign(),
+                                              /*isConstant=*/true);
   DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
 
   // This is a Zero array to be used in the creation of the constant expressions
@@ -2849,16 +2849,18 @@ CGOpenMPRuntime::createOffloadingBinaryD
   // Create the target region descriptor.
   auto *BinaryDescriptorTy = cast<llvm::StructType>(
       CGM.getTypes().ConvertTypeForMem(getTgtBinaryDescriptorQTy()));
-  llvm::Constant *TargetRegionsDescriptorInit = llvm::ConstantStruct::get(
-      BinaryDescriptorTy, llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()),
-      llvm::ConstantExpr::getGetElementPtr(DeviceImagesInitTy, DeviceImages,
-                                           Index),
-      HostEntriesBegin, HostEntriesEnd, nullptr);
-
-  auto *Desc = new llvm::GlobalVariable(
-      M, BinaryDescriptorTy, /*isConstant=*/true,
-      llvm::GlobalValue::InternalLinkage, TargetRegionsDescriptorInit,
-      ".omp_offloading.descriptor");
+  ConstantBuilder DescBuilder(CGM);
+  auto DescInit = DescBuilder.beginStruct(BinaryDescriptorTy);
+  DescInit.addInt(CGM.Int32Ty, Devices.size());
+  DescInit.add(llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(),
+                                                    DeviceImages,
+                                                    Index));
+  DescInit.add(HostEntriesBegin);
+  DescInit.add(HostEntriesEnd);
+
+  auto *Desc = DescInit.finishAndCreateGlobal(".omp_offloading.descriptor",
+                                              CGM.getPointerAlign(),
+                                              /*isConstant=*/true);
 
   // Emit code to register or unregister the descriptor at execution
   // startup or closing, respectively.
@@ -2906,19 +2908,24 @@ void CGOpenMPRuntime::createOffloadEntry
   Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
   llvm::Constant *StrPtr = llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy);
 
+  // We can't have any padding between symbols, so we need to have 1-byte
+  // alignment.
+  auto Align = CharUnits::fromQuantity(1);
+
   // Create the entry struct.
-  llvm::Constant *EntryInit = llvm::ConstantStruct::get(
-      TgtOffloadEntryType, AddrPtr, StrPtr,
-      llvm::ConstantInt::get(CGM.SizeTy, Size), nullptr);
-  llvm::GlobalVariable *Entry = new llvm::GlobalVariable(
-      M, TgtOffloadEntryType, true, llvm::GlobalValue::ExternalLinkage,
-      EntryInit, ".omp_offloading.entry");
+  ConstantBuilder EntryBuilder(CGM);
+  auto EntryInit = EntryBuilder.beginStruct(TgtOffloadEntryType);
+  EntryInit.add(AddrPtr);
+  EntryInit.add(StrPtr);
+  EntryInit.addInt(CGM.SizeTy, Size);
+  llvm::GlobalVariable *Entry =
+    EntryInit.finishAndCreateGlobal(".omp_offloading.entry",
+                                    Align,
+                                    /*constant*/ true,
+                                    llvm::GlobalValue::ExternalLinkage);
 
   // The entry has to be created in the section the linker expects it to be.
   Entry->setSection(".omp_offloading.entries");
-  // We can't have any padding between symbols, so we need to have 1-byte
-  // alignment.
-  Entry->setAlignment(1);
 }
 
 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() {

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=287437&r1=287436&r2=287437&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Sat Nov 19 02:17:24 2016
@@ -24,6 +24,7 @@
 #include "CodeGenFunction.h"
 #include "CodeGenPGO.h"
 #include "CodeGenTBAA.h"
+#include "ConstantBuilder.h"
 #include "CoverageMappingGen.h"
 #include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
@@ -731,6 +732,8 @@ void CodeGenModule::AddGlobalDtor(llvm::
 }
 
 void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
+  if (Fns.empty()) return;
+
   // Ctor function type is void()*.
   llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false);
   llvm::Type *CtorPFTy = llvm::PointerType::getUnqual(CtorFTy);
@@ -740,24 +743,22 @@ void CodeGenModule::EmitCtorList(CtorLis
       Int32Ty, llvm::PointerType::getUnqual(CtorFTy), VoidPtrTy, nullptr);
 
   // Construct the constructor and destructor arrays.
-  SmallVector<llvm::Constant *, 8> Ctors;
+  ConstantBuilder builder(*this);
+  auto ctors = builder.beginArray(CtorStructTy);
   for (const auto &I : Fns) {
-    llvm::Constant *S[] = {
-        llvm::ConstantInt::get(Int32Ty, I.Priority, false),
-        llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy),
-        (I.AssociatedData
-             ? llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy)
-             : llvm::Constant::getNullValue(VoidPtrTy))};
-    Ctors.push_back(llvm::ConstantStruct::get(CtorStructTy, S));
+    auto ctor = ctors.beginStruct(CtorStructTy);
+    ctor.addInt(Int32Ty, I.Priority);
+    ctor.add(llvm::ConstantExpr::getBitCast(I.Initializer, CtorPFTy));
+    if (I.AssociatedData)
+      ctor.add(llvm::ConstantExpr::getBitCast(I.AssociatedData, VoidPtrTy));
+    else
+      ctor.addNullPointer(VoidPtrTy);
+    ctors.add(ctor.finish());
   }
 
-  if (!Ctors.empty()) {
-    llvm::ArrayType *AT = llvm::ArrayType::get(CtorStructTy, Ctors.size());
-    new llvm::GlobalVariable(TheModule, AT, false,
-                             llvm::GlobalValue::AppendingLinkage,
-                             llvm::ConstantArray::get(AT, Ctors),
-                             GlobalName);
-  }
+  (void) ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(),
+                                     /*constant*/ false,
+                                     llvm::GlobalValue::AppendingLinkage);
   Fns.clear();
 }
 
@@ -3190,15 +3191,14 @@ CodeGenModule::GetAddrOfConstantCFString
 
   auto *STy = cast<llvm::StructType>(getTypes().ConvertType(CFTy));
 
-  llvm::Constant *Fields[4];
+  ConstantBuilder Builder(*this);
+  auto Fields = Builder.beginStruct(STy);
 
   // Class pointer.
-  Fields[0] = cast<llvm::ConstantExpr>(CFConstantStringClassRef);
+  Fields.add(cast<llvm::ConstantExpr>(CFConstantStringClassRef));
 
   // Flags.
-  llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
-  Fields[1] = isUTF16 ? llvm::ConstantInt::get(Ty, 0x07d0)
-                      : llvm::ConstantInt::get(Ty, 0x07C8);
+  Fields.addInt(IntTy, isUTF16 ? 0x07d0 : 0x07C8);
 
   // String pointer.
   llvm::Constant *C = nullptr;
@@ -3232,25 +3232,24 @@ CodeGenModule::GetAddrOfConstantCFString
                            : "__TEXT,__cstring,cstring_literals");
 
   // String.
-  Fields[2] =
+  llvm::Constant *Str =
       llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
 
   if (isUTF16)
     // Cast the UTF16 string to the correct type.
-    Fields[2] = llvm::ConstantExpr::getBitCast(Fields[2], Int8PtrTy);
+    Str = llvm::ConstantExpr::getBitCast(Str, Int8PtrTy);
+  Fields.add(Str);
 
   // String length.
-  Ty = getTypes().ConvertType(getContext().LongTy);
-  Fields[3] = llvm::ConstantInt::get(Ty, StringLength);
+  auto Ty = getTypes().ConvertType(getContext().LongTy);
+  Fields.addInt(cast<llvm::IntegerType>(Ty), StringLength);
 
   CharUnits Alignment = getPointerAlign();
 
   // The struct.
-  C = llvm::ConstantStruct::get(STy, Fields);
-  GV = new llvm::GlobalVariable(getModule(), C->getType(), /*isConstant=*/false,
-                                llvm::GlobalVariable::PrivateLinkage, C,
-                                "_unnamed_cfstring_");
-  GV->setAlignment(Alignment.getQuantity());
+  GV = Fields.finishAndCreateGlobal("_unnamed_cfstring_", Alignment,
+                                    /*isConstant=*/false,
+                                    llvm::GlobalVariable::PrivateLinkage);
   switch (getTriple().getObjectFormat()) {
   case llvm::Triple::UnknownObjectFormat:
     llvm_unreachable("unknown file format");
@@ -3338,19 +3337,18 @@ CodeGenModule::GetAddrOfConstantString(c
     NSConstantStringType = cast<llvm::StructType>(getTypes().ConvertType(NSTy));
   }
   
-  llvm::Constant *Fields[3];
+  ConstantBuilder Builder(*this);
+  auto Fields = Builder.beginStruct(NSConstantStringType);
   
   // Class pointer.
-  Fields[0] = cast<llvm::ConstantExpr>(V);
+  Fields.add(cast<llvm::ConstantExpr>(V));
   
   // String pointer.
   llvm::Constant *C =
       llvm::ConstantDataArray::getString(VMContext, Entry.first());
 
-  llvm::GlobalValue::LinkageTypes Linkage;
-  bool isConstant;
-  Linkage = llvm::GlobalValue::PrivateLinkage;
-  isConstant = !LangOpts.WritableStrings;
+  llvm::GlobalValue::LinkageTypes Linkage = llvm::GlobalValue::PrivateLinkage;
+  bool isConstant = !LangOpts.WritableStrings;
 
   auto *GV = new llvm::GlobalVariable(getModule(), C->getType(), isConstant,
                                       Linkage, C, ".str");
@@ -3359,20 +3357,17 @@ CodeGenModule::GetAddrOfConstantString(c
   // of the string is via this class initializer.
   CharUnits Align = getContext().getTypeAlignInChars(getContext().CharTy);
   GV->setAlignment(Align.getQuantity());
-  Fields[1] =
-      llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros);
+  Fields.add(
+      llvm::ConstantExpr::getGetElementPtr(GV->getValueType(), GV, Zeros));
 
   // String length.
-  llvm::Type *Ty = getTypes().ConvertType(getContext().UnsignedIntTy);
-  Fields[2] = llvm::ConstantInt::get(Ty, StringLength);
+  Fields.addInt(IntTy, StringLength);
   
   // The struct.
   CharUnits Alignment = getPointerAlign();
-  C = llvm::ConstantStruct::get(NSConstantStringType, Fields);
-  GV = new llvm::GlobalVariable(getModule(), C->getType(), true,
-                                llvm::GlobalVariable::PrivateLinkage, C,
-                                "_unnamed_nsstring_");
-  GV->setAlignment(Alignment.getQuantity());
+  GV = Fields.finishAndCreateGlobal("_unnamed_nsstring_", Alignment,
+                                    /*constant*/ true,
+                                    llvm::GlobalVariable::PrivateLinkage);
   const char *NSStringSection = "__OBJC,__cstring_object,regular,no_dead_strip";
   const char *NSStringNonFragileABISection =
       "__DATA,__objc_stringobj,regular,no_dead_strip";

Added: cfe/trunk/lib/CodeGen/ConstantBuilder.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ConstantBuilder.h?rev=287437&view=auto
==============================================================================
--- cfe/trunk/lib/CodeGen/ConstantBuilder.h (added)
+++ cfe/trunk/lib/CodeGen/ConstantBuilder.h Sat Nov 19 02:17:24 2016
@@ -0,0 +1,274 @@
+//===----- ConstantBuilder.h - Builder for LLVM IR constants ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class provides a convenient interface for building complex
+// global initializers.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_CODEGEN_CONSTANTBUILDER_H
+#define LLVM_CLANG_LIB_CODEGEN_CONSTANTBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Constants.h"
+
+#include "CodeGenModule.h"
+
+namespace clang {
+namespace CodeGen {
+
+class ConstantBuilder;
+
+/// A convenience builder class for complex constant initializers,
+/// especially for anonymous global structures used by various language
+/// runtimes.
+///
+/// The basic usage pattern is expected to be something like:
+///    ConstantBuilder builder(CGM);
+///    auto toplevel = builder.beginStruct();
+///    toplevel.addInt(CGM.SizeTy, widgets.size());
+///    auto widgetArray = builder.beginArray();
+///    for (auto &widget : widgets) {
+///      auto widgetDesc = widgetArray.beginStruct();
+///      widgetDesc.addInt(CGM.SizeTy, widget.getPower());
+///      widgetDesc.add(CGM.GetAddrOfConstantString(widget.getName()));
+///      widgetDesc.add(CGM.GetAddrOfGlobal(widget.getInitializerDecl()));
+///      widgetArray.add(widgetDesc.finish());
+///    }
+///    toplevel.add(widgetArray.finish());
+///    auto global = toplevel.finishAndCreateGlobal("WIDGET_LIST", Align,
+///                                                 /*constant*/ true);
+class ConstantBuilder {
+  CodeGenModule &CGM;
+  llvm::SmallVector<llvm::Constant*, 16> Buffer;
+  bool Frozen = false;
+
+public:
+  explicit ConstantBuilder(CodeGenModule &CGM) : CGM(CGM) {}
+
+  ~ConstantBuilder() {
+    assert(Buffer.empty() && "didn't claim all values out of buffer");
+  }
+
+  class ArrayBuilder;
+  class StructBuilder;
+
+  class AggregateBuilder {
+  protected:
+    ConstantBuilder &Builder;
+    AggregateBuilder *Parent;
+    size_t Begin;
+    bool Finished = false;
+    bool Frozen = false;
+
+    AggregateBuilder(ConstantBuilder &builder, AggregateBuilder *parent)
+        : Builder(builder), Parent(parent), Begin(builder.Buffer.size()) {
+      if (parent) {
+        assert(!parent->Frozen && "parent already has child builder active");
+        parent->Frozen = true;
+      } else {
+        assert(!builder.Frozen && "builder already has child builder active");
+        builder.Frozen = true;
+      }
+    }
+
+    ~AggregateBuilder() {
+      assert(Finished && "didn't claim value from aggregate builder");
+    }
+
+    void markFinished() {
+      assert(!Frozen && "child builder still active");
+      assert(!Finished && "builder already finished");
+      Finished = true;
+      if (Parent) {
+        assert(Parent->Frozen &&
+               "parent not frozen while child builder active");
+        Parent->Frozen = false;
+      } else {
+        assert(Builder.Frozen &&
+               "builder not frozen while child builder active");
+        Builder.Frozen = false;
+      }
+    }
+
+  public:
+    // Not copyable.
+    AggregateBuilder(const AggregateBuilder &) = delete;
+    AggregateBuilder &operator=(const AggregateBuilder &) = delete;
+
+    // Movable, mostly to allow returning.  But we have to write this out
+    // properly to satisfy the assert in the destructor.
+    AggregateBuilder(AggregateBuilder &&other)
+      : Builder(other.Builder), Parent(other.Parent), Begin(other.Begin),
+        Finished(other.Finished), Frozen(other.Frozen) {
+      other.Finished = false;
+    }
+    AggregateBuilder &operator=(AggregateBuilder &&other) = delete;
+
+    void add(llvm::Constant *value) {
+      assert(!Finished && "cannot add more values after finishing builder");
+      Builder.Buffer.push_back(value);
+    }
+
+    void addSize(CharUnits size) {
+      add(Builder.CGM.getSize(size));
+    }
+
+    void addInt(llvm::IntegerType *intTy, uint64_t value,
+                bool isSigned = false) {
+      add(llvm::ConstantInt::get(intTy, value, isSigned));
+    }
+
+    void addNullPointer(llvm::PointerType *ptrTy) {
+      add(llvm::ConstantPointerNull::get(ptrTy));
+    }
+
+    ArrayRef<llvm::Constant*> getGEPIndicesToCurrentPosition(
+                             llvm::SmallVectorImpl<llvm::Constant*> &indices) {
+      getGEPIndicesTo(indices, Builder.Buffer.size());
+      return indices;
+    }
+
+    ArrayBuilder beginArray(llvm::Type *eltTy = nullptr);
+    StructBuilder beginStruct(llvm::StructType *structTy = nullptr);
+
+  private:
+    void getGEPIndicesTo(llvm::SmallVectorImpl<llvm::Constant*> &indices,
+                         size_t position) const {
+      // Recurse on the parent builder if present.
+      if (Parent) {
+        Parent->getGEPIndicesTo(indices, Begin);
+
+      // Otherwise, add an index to drill into the first level of pointer. 
+      } else {
+        assert(indices.empty());
+        indices.push_back(llvm::ConstantInt::get(Builder.CGM.SizeTy, 0));
+      }
+
+      assert(position >= Begin);
+      indices.push_back(llvm::ConstantInt::get(Builder.CGM.SizeTy,
+                                               position - Begin));
+    }
+  };
+
+  class ArrayBuilder : public AggregateBuilder {
+    llvm::Type *EltTy;
+    friend class ConstantBuilder;
+    ArrayBuilder(ConstantBuilder &builder, AggregateBuilder *parent,
+                 llvm::Type *eltTy)
+      : AggregateBuilder(builder, parent), EltTy(eltTy) {}
+  public:
+    size_t size() const {
+      assert(!Finished);
+      assert(!Frozen);
+      assert(Begin <= Builder.Buffer.size());
+      return Builder.Buffer.size() - Begin;
+    }
+
+    /// Form an array constant from the values that have been added to this
+    /// builder.
+    llvm::Constant *finish() {
+      markFinished();
+
+      auto &buffer = Builder.Buffer;
+      assert((Begin < buffer.size() ||
+              (Begin == buffer.size() && EltTy))
+             && "didn't add any array elements without element type");
+      auto elts = llvm::makeArrayRef(buffer).slice(Begin);
+      auto eltTy = EltTy ? EltTy : elts[0]->getType();
+      auto type = llvm::ArrayType::get(eltTy, elts.size());
+      auto constant = llvm::ConstantArray::get(type, elts);
+      buffer.erase(buffer.begin() + Begin, buffer.end());
+      return constant;
+    }
+
+    template <class... As>
+    llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
+      assert(!Parent && "finishing non-root builder");
+      return Builder.createGlobal(finish(), std::forward<As>(args)...);
+    }
+  };
+
+  ArrayBuilder beginArray(llvm::Type *eltTy = nullptr) {
+    return ArrayBuilder(*this, nullptr, eltTy);
+  }
+
+  class StructBuilder : public AggregateBuilder {
+    llvm::StructType *Ty;
+    friend class ConstantBuilder;
+    StructBuilder(ConstantBuilder &builder, AggregateBuilder *parent,
+                  llvm::StructType *ty)
+      : AggregateBuilder(builder, parent), Ty(ty) {}
+  public:
+    /// Finish the struct.
+    llvm::Constant *finish(bool packed = false) {
+      markFinished();
+
+      auto &buffer = Builder.Buffer;
+      assert(Begin < buffer.size() && "didn't add any struct elements?");
+      auto elts = llvm::makeArrayRef(buffer).slice(Begin);
+
+      llvm::Constant *constant;
+      if (Ty) {
+        constant = llvm::ConstantStruct::get(Ty, elts);
+      } else {
+        constant = llvm::ConstantStruct::getAnon(elts, packed);
+      }
+
+      buffer.erase(buffer.begin() + Begin, buffer.end());
+      return constant;
+    }
+
+    template <class... As>
+    llvm::GlobalVariable *finishAndCreateGlobal(As &&...args) {
+      assert(!Parent && "finishing non-root builder");
+      return Builder.createGlobal(finish(), std::forward<As>(args)...);
+    }
+  };
+
+  StructBuilder beginStruct(llvm::StructType *structTy = nullptr) {
+    return StructBuilder(*this, nullptr, structTy);
+  }
+
+  llvm::GlobalVariable *createGlobal(llvm::Constant *initializer,
+                                     StringRef name,
+                                     CharUnits alignment,
+                                     bool constant = false,
+                                     llvm::GlobalValue::LinkageTypes linkage
+                                       = llvm::GlobalValue::InternalLinkage,
+                                     unsigned addressSpace = 0) {
+    auto GV = new llvm::GlobalVariable(CGM.getModule(),
+                                       initializer->getType(),
+                                       constant,
+                                       linkage,
+                                       initializer,
+                                       name,
+                                       /*insert before*/ nullptr,
+                                       llvm::GlobalValue::NotThreadLocal,
+                                       addressSpace);
+    GV->setAlignment(alignment.getQuantity());
+    return GV;
+  }
+};
+
+inline ConstantBuilder::ArrayBuilder
+ConstantBuilder::AggregateBuilder::beginArray(llvm::Type *eltTy) {
+  return ArrayBuilder(Builder, this, eltTy);
+}
+
+inline ConstantBuilder::StructBuilder
+ConstantBuilder::AggregateBuilder::beginStruct(llvm::StructType *structTy) {
+  return StructBuilder(Builder, this, structTy);
+}
+
+}  // end namespace CodeGen
+}  // end namespace clang
+
+#endif




More information about the cfe-commits mailing list