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