[cfe-commits] r141085 - /cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
David Chisnall
csdavec at swan.ac.uk
Tue Oct 4 08:35:31 PDT 2011
Author: theraven
Date: Tue Oct 4 10:35:30 2011
New Revision: 141085
URL: http://llvm.org/viewvc/llvm-project?rev=141085&view=rev
Log:
Add bitmaps for strong / weak ivar layout (GNUstep runtime).
Modified:
cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=141085&r1=141084&r2=141085&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Tue Oct 4 10:35:30 2011
@@ -160,6 +160,10 @@
llvm::PointerType *PtrToIntTy;
/// LLVM type for Objective-C BOOL type.
llvm::Type *BoolTy;
+ /// 32-bit integer type, to save us needing to look it up every time it's used.
+ llvm::IntegerType *Int32Ty;
+ /// 64-bit integer type, to save us needing to look it up every time it's used.
+ llvm::IntegerType *Int64Ty;
/// Metadata kind used to tie method lookups to message sends. The GNUstep
/// runtime provides some LLVM passes that can use this to do things like
/// automatic IMP caching and speculative inlining.
@@ -191,7 +195,7 @@
/// The element types must match the types of the structure elements in the
/// first argument.
llvm::GlobalVariable *MakeGlobal(llvm::StructType *Ty,
- std::vector<llvm::Constant*> &V,
+ llvm::ArrayRef<llvm::Constant*> V,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
@@ -203,7 +207,7 @@
/// elements that the array type declares, of the type specified as the array
/// element type.
llvm::GlobalVariable *MakeGlobal(llvm::ArrayType *Ty,
- std::vector<llvm::Constant*> &V,
+ llvm::ArrayRef<llvm::Constant*> V,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
@@ -214,7 +218,7 @@
/// 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,
- std::vector<llvm::Constant*> &V,
+ llvm::ArrayRef<llvm::Constant*> V,
StringRef Name="",
llvm::GlobalValue::LinkageTypes linkage
=llvm::GlobalValue::InternalLinkage) {
@@ -375,6 +379,8 @@
llvm::Constant *Protocols,
llvm::Constant *IvarOffsets,
llvm::Constant *Properties,
+ llvm::Constant *StrongIvarBitmap,
+ llvm::Constant *WeakIvarBitmap,
bool isMeta=false);
/// Generates a method list. This is used by protocols to define the required
/// and optional methods.
@@ -402,12 +408,24 @@
llvm::Value *&Receiver,
llvm::Value *cmd,
llvm::MDNode *node) = 0;
- /// Looks up the method for sending a message to a superclass. This mechanism
- /// differs between the GCC and GNU runtimes, so this method must be
- /// overridden in subclasses.
+ /// Looks up the method for sending a message to a superclass. This
+ /// mechanism differs between the GCC and GNU runtimes, so this method must
+ /// be overridden in subclasses.
virtual llvm::Value *LookupIMPSuper(CodeGenFunction &CGF,
llvm::Value *ObjCSuper,
llvm::Value *cmd) = 0;
+ /// Libobjc2 uses a bitfield representation where small(ish) bitfields are
+ /// stored in a 64-bit value with the low bit set to 1 and the remaining 63
+ /// bits set to their values, LSB first, while larger ones are stored in a
+ /// structure of this / form:
+ ///
+ /// struct { int32_t length; int32_t values[length]; };
+ ///
+ /// The values in the array are stored in host-endian format, with the least
+ /// significant bit being assumed to come first in the bitfield. Therefore,
+ /// a bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] },
+ /// while a bitfield / with the 63rd bit set will be 1<<64.
+ llvm::Constant *MakeBitField(llvm::SmallVectorImpl<bool> &bits);
public:
CGObjCGNU(CodeGenModule &cgm, unsigned runtimeABIVersion,
unsigned protocolClassVersion);
@@ -696,6 +714,9 @@
PtrToIntTy = llvm::PointerType::getUnqual(IntTy);
PtrTy = PtrToInt8Ty;
+ Int32Ty = llvm::Type::getInt32Ty(VMContext);
+ Int64Ty = llvm::Type::getInt64Ty(VMContext);
+
// Object type
QualType UnqualIdTy = CGM.getContext().getObjCIdType();
ASTIdTy = CanQualType();
@@ -1246,8 +1267,7 @@
Methods.clear();
Methods.push_back(llvm::ConstantPointerNull::get(
llvm::PointerType::getUnqual(ObjCMethodListTy)));
- Methods.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- MethodTypes.size()));
+ Methods.push_back(llvm::ConstantInt::get(Int32Ty, MethodTypes.size()));
Methods.push_back(MethodArray);
// Create an instance of the structure
@@ -1307,6 +1327,8 @@
llvm::Constant *Protocols,
llvm::Constant *IvarOffsets,
llvm::Constant *Properties,
+ llvm::Constant *StrongIvarBitmap,
+ llvm::Constant *WeakIvarBitmap,
bool isMeta) {
// Set up the class structure
// Note: Several of these are char*s when they should be ids. This is
@@ -1334,6 +1356,8 @@
LongTy, // abi_version
IvarOffsets->getType(), // ivar_offsets
Properties->getType(), // properties
+ Int64Ty, // strong_pointers
+ Int64Ty, // weak_pointers
NULL);
llvm::Constant *Zero = llvm::ConstantInt::get(LongTy, 0);
// Fill in the structure
@@ -1358,9 +1382,11 @@
Elements.push_back(NULLPtr);
Elements.push_back(llvm::ConstantExpr::getBitCast(Protocols, PtrTy));
Elements.push_back(NULLPtr);
- Elements.push_back(Zero);
+ Elements.push_back(llvm::ConstantInt::get(LongTy, 1));
Elements.push_back(IvarOffsets);
Elements.push_back(Properties);
+ Elements.push_back(StrongIvarBitmap);
+ Elements.push_back(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.
@@ -1460,8 +1486,7 @@
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
Elements.push_back(llvm::ConstantExpr::getIntToPtr(
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- ProtocolVersion), IdTy));
+ llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
Elements.push_back(ProtocolList);
Elements.push_back(MethodList);
@@ -1621,8 +1646,7 @@
// The isa pointer must be set to a magic number so the runtime knows it's
// the correct layout.
Elements.push_back(llvm::ConstantExpr::getIntToPtr(
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext),
- ProtocolVersion), IdTy));
+ llvm::ConstantInt::get(Int32Ty, ProtocolVersion), IdTy));
Elements.push_back(MakeConstantString(ProtocolName, ".objc_protocol_name"));
Elements.push_back(ProtocolList);
Elements.push_back(InstanceMethodList);
@@ -1681,6 +1705,46 @@
PtrTy, PtrTy, PtrTy, NULL), Elements), PtrTy));
}
+/// Libobjc2 uses a bitfield representation where small(ish) bitfields are
+/// stored in a 64-bit value with the low bit set to 1 and the remaining 63
+/// bits set to their values, LSB first, while larger ones are stored in a
+/// structure of this / form:
+///
+/// struct { int32_t length; int32_t values[length]; };
+///
+/// The values in the array are stored in host-endian format, with the least
+/// significant bit being assumed to come first in the bitfield. Therefore, a
+/// bitfield with the 64th bit set will be (int64_t)&{ 2, [0, 1<<31] }, while a
+/// bitfield / with the 63rd bit set will be 1<<64.
+llvm::Constant *CGObjCGNU::MakeBitField(llvm::SmallVectorImpl<bool> &bits) {
+ int bitCount = bits.size();
+ if (bitCount < 64) {
+ uint64_t val = 1;
+ for (int i=0 ; i<bitCount ; ++i) {
+ if (bits[i]) val |= 1<<(i+1);
+ }
+ return llvm::ConstantInt::get(Int64Ty, val);
+ }
+ llvm::SmallVector<llvm::Constant*, 8> values;
+ int v=0;
+ while (v < bitCount) {
+ int32_t word = 0;
+ for (int i=0 ; (i<32) && (v<bitCount) ; ++i) {
+ if (bits[v]) word |= 1<<i;
+ v++;
+ }
+ values.push_back(llvm::ConstantInt::get(Int32Ty, word));
+ }
+ 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,
+ NULL), fields);
+ return llvm::ConstantExpr::getPtrToInt(GS, Int64Ty);
+}
+
void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
std::string ClassName = OCD->getClassInterface()->getNameAsString();
std::string CategoryName = OCD->getNameAsString();
@@ -1845,6 +1909,8 @@
SmallVector<llvm::Constant*, 16> IvarOffsets;
std::vector<llvm::Constant*> IvarOffsetValues;
+ SmallVector<bool, 16> WeakIvars;
+ SmallVector<bool, 16> StrongIvars;
int superInstanceSize = !SuperClassDecl ? 0 :
Context.getASTObjCInterfaceLayout(SuperClassDecl).getSize().getQuantity();
@@ -1887,7 +1953,23 @@
IVD->getNameAsString());
IvarOffsets.push_back(OffsetValue);
IvarOffsetValues.push_back(OffsetVar);
+ Qualifiers::ObjCLifetime lt = IVD->getType().getQualifiers().getObjCLifetime();
+ switch (lt) {
+ case Qualifiers::OCL_Strong:
+ StrongIvars.push_back(true);
+ WeakIvars.push_back(false);
+ break;
+ case Qualifiers::OCL_Weak:
+ StrongIvars.push_back(false);
+ WeakIvars.push_back(true);
+ break;
+ default:
+ StrongIvars.push_back(false);
+ WeakIvars.push_back(false);
+ }
}
+ llvm::Constant *StrongIvarBitmap = MakeBitField(StrongIvars);
+ llvm::Constant *WeakIvarBitmap = MakeBitField(WeakIvars);
llvm::GlobalVariable *IvarOffsetArray =
MakeGlobalArray(PtrToIntTy, IvarOffsetValues, ".ivar.offsets");
@@ -1954,7 +2036,7 @@
// setting up the alias. These are: The base address for the global, the
// ivar array (second field), the ivar in this list (set for each ivar), and
// the offset (third field in ivar structure)
- llvm::Type *IndexTy = llvm::Type::getInt32Ty(VMContext);
+ llvm::Type *IndexTy = Int32Ty;
llvm::Constant *offsetPointerIndexes[] = {Zeros[0],
llvm::ConstantInt::get(IndexTy, 1), 0,
llvm::ConstantInt::get(IndexTy, 2) };
@@ -1983,10 +2065,12 @@
}
++ivarIndex;
}
+ llvm::Constant *Zero64 = llvm::ConstantInt::get(Int64Ty, 0);
//Generate metaclass for class methods
llvm::Constant *MetaClassStruct = GenerateClassStructure(NULLPtr,
NULLPtr, 0x12L, ClassName.c_str(), 0, Zeros[0], GenerateIvarList(
- empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr, true);
+ empty, empty, empty), ClassMethodList, NULLPtr,
+ NULLPtr, NULLPtr, Zero64, Zero64, true);
// Generate the class structure
llvm::Constant *ClassStruct =
@@ -1994,7 +2078,7 @@
ClassName.c_str(), 0,
llvm::ConstantInt::get(LongTy, instanceSize), IvarList,
MethodList, GenerateProtocolList(Protocols), IvarOffsetArray,
- Properties);
+ Properties, StrongIvarBitmap, WeakIvarBitmap);
// Resolve the class aliases, if they exist.
if (ClassPtrAlias) {
@@ -2118,7 +2202,7 @@
for (unsigned int i=0 ; i<SelectorCount ; i++) {
llvm::Constant *Idxs[] = {Zeros[0],
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), i), Zeros[0]};
+ llvm::ConstantInt::get(Int32Ty, i), Zeros[0]};
// FIXME: We're generating redundant loads and stores here!
llvm::Constant *SelPtr = llvm::ConstantExpr::getGetElementPtr(SelectorList,
makeArrayRef(Idxs, 2));
@@ -2396,7 +2480,7 @@
// GCC-compiled class.
if (CGM.getLangOptions().PICLevel) {
llvm::GlobalVariable *IvarOffsetGV = new llvm::GlobalVariable(TheModule,
- llvm::Type::getInt32Ty(VMContext), false,
+ Int32Ty, false,
llvm::GlobalValue::PrivateLinkage, OffsetGuess, Name+".guess");
IvarOffsetPointer = new llvm::GlobalVariable(TheModule,
IvarOffsetGV->getType(), false, llvm::GlobalValue::LinkOnceAnyLinkage,
More information about the cfe-commits
mailing list