diff options
author | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2012-12-02 13:20:44 +0000 |
commit | 056abd2059c65a3e908193aeae16fad98017437c (patch) | |
tree | 2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /lib/CodeGen/CGObjCMac.cpp | |
parent | cc73504950eb7b5dff2dded9bedd67bc36d64641 (diff) | |
download | FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz |
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'lib/CodeGen/CGObjCMac.cpp')
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 798 |
1 files changed, 691 insertions, 107 deletions
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index ef802a3..2203f01 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -36,7 +36,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Target/TargetData.h" +#include "llvm/DataLayout.h" #include <cstdio> using namespace clang; @@ -66,7 +66,8 @@ private: return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy, params, true), "objc_msgSend", - llvm::Attribute::NonLazyBind); + llvm::Attributes::get(CGM.getLLVMContext(), + llvm::Attributes::NonLazyBind)); } /// void objc_msgSend_stret (id, SEL, ...) @@ -433,19 +434,19 @@ public: /// SyncEnterFn - LLVM object_sync_enter function. llvm::Constant *getSyncEnterFn() { - // void objc_sync_enter (id) + // int objc_sync_enter (id) llvm::Type *args[] = { ObjectPtrTy }; llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, args, false); + llvm::FunctionType::get(CGM.IntTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter"); } /// SyncExitFn - LLVM object_sync_exit function. llvm::Constant *getSyncExitFn() { - // void objc_sync_exit (id) + // int objc_sync_exit (id) llvm::Type *args[] = { ObjectPtrTy }; llvm::FunctionType *FTy = - llvm::FunctionType::get(CGM.VoidTy, args, false); + llvm::FunctionType::get(CGM.IntTy, args, false); return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit"); } @@ -583,7 +584,8 @@ public: return CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, params, false), "_setjmp", - llvm::Attribute::ReturnsTwice); + llvm::Attributes::get(CGM.getLLVMContext(), + llvm::Attributes::NonLazyBind)); } public: @@ -753,6 +755,74 @@ public: : skip(_skip), scan(_scan) {} }; + /// opcode for captured block variables layout 'instructions'. + /// In the following descriptions, 'I' is the value of the immediate field. + /// (field following the opcode). + /// + enum BLOCK_LAYOUT_OPCODE { + /// An operator which affects how the following layout should be + /// interpreted. + /// I == 0: Halt interpretation and treat everything else as + /// a non-pointer. Note that this instruction is equal + /// to '\0'. + /// I != 0: Currently unused. + BLOCK_LAYOUT_OPERATOR = 0, + + /// The next I+1 bytes do not contain a value of object pointer type. + /// Note that this can leave the stream unaligned, meaning that + /// subsequent word-size instructions do not begin at a multiple of + /// the pointer size. + BLOCK_LAYOUT_NON_OBJECT_BYTES = 1, + + /// The next I+1 words do not contain a value of object pointer type. + /// This is simply an optimized version of BLOCK_LAYOUT_BYTES for + /// when the required skip quantity is a multiple of the pointer size. + BLOCK_LAYOUT_NON_OBJECT_WORDS = 2, + + /// The next I+1 words are __strong pointers to Objective-C + /// objects or blocks. + BLOCK_LAYOUT_STRONG = 3, + + /// The next I+1 words are pointers to __block variables. + BLOCK_LAYOUT_BYREF = 4, + + /// The next I+1 words are __weak pointers to Objective-C + /// objects or blocks. + BLOCK_LAYOUT_WEAK = 5, + + /// The next I+1 words are __unsafe_unretained pointers to + /// Objective-C objects or blocks. + BLOCK_LAYOUT_UNRETAINED = 6 + + /// The next I+1 words are block or object pointers with some + /// as-yet-unspecified ownership semantics. If we add more + /// flavors of ownership semantics, values will be taken from + /// this range. + /// + /// This is included so that older tools can at least continue + /// processing the layout past such things. + //BLOCK_LAYOUT_OWNERSHIP_UNKNOWN = 7..10, + + /// All other opcodes are reserved. Halt interpretation and + /// treat everything else as opaque. + }; + + class RUN_SKIP { + public: + enum BLOCK_LAYOUT_OPCODE opcode; + CharUnits block_var_bytepos; + CharUnits block_var_size; + RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR, + CharUnits BytePos = CharUnits::Zero(), + CharUnits Size = CharUnits::Zero()) + : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} + + // Allow sorting based on byte pos. + bool operator<(const RUN_SKIP &b) const { + return block_var_bytepos < b.block_var_bytepos; + } + }; + protected: llvm::LLVMContext &VMContext; // FIXME! May not be needing this after all. @@ -761,6 +831,9 @@ protected: // gc ivar layout bitmap calculation helper caches. SmallVector<GC_IVAR, 16> SkipIvars; SmallVector<GC_IVAR, 16> IvarsInfo; + + // arc/mrr layout of captured block literal variables. + SmallVector<RUN_SKIP, 16> RunSkipBlockVars; /// LazySymbols - Symbols to generate a lazy reference for. See /// DefinedSymbols and FinishModule(). @@ -869,6 +942,24 @@ protected: ArrayRef<const FieldDecl*> RecFields, unsigned int BytePos, bool ForStrongLayout, bool &HasUnion); + + Qualifiers::ObjCLifetime getBlockCaptureLifetime(QualType QT); + + void UpdateRunSkipBlockVars(bool IsByref, + Qualifiers::ObjCLifetime LifeTime, + CharUnits FieldOffset, + CharUnits FieldSize); + + void BuildRCBlockVarRecordLayout(const RecordType *RT, + CharUnits BytePos, bool &HasUnion); + + void BuildRCRecordLayout(const llvm::StructLayout *RecLayout, + const RecordDecl *RD, + ArrayRef<const FieldDecl*> RecFields, + CharUnits BytePos, bool &HasUnion); + + uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout); + /// GetIvarLayoutName - Returns a unique constant for the given /// ivar layout bitmap. @@ -959,6 +1050,8 @@ public: virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0; virtual llvm::Constant *BuildGCBlockLayout(CodeGen::CodeGenModule &CGM, const CGBlockInfo &blockInfo); + virtual llvm::Constant *BuildRCBlockLayout(CodeGen::CodeGenModule &CGM, + const CGBlockInfo &blockInfo); }; @@ -1787,8 +1880,8 @@ static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) { llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, const CGBlockInfo &blockInfo) { + llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); - if (CGM.getLangOpts().getGC() == LangOptions::NonGC && !CGM.getLangOpts().ObjCAutoRefCount) return nullPtr; @@ -1807,7 +1900,7 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, // Calculate the basic layout of the block structure. const llvm::StructLayout *layout = - CGM.getTargetData().getStructLayout(blockInfo.StructureType); + CGM.getDataLayout().getStructLayout(blockInfo.StructureType); // Ignore the optional 'this' capture: C++ objects are not assumed // to be GC'ed. @@ -1860,7 +1953,7 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, llvm::Constant *C = BuildIvarLayoutBitmap(BitMap); if (CGM.getLangOpts().ObjCGCBitmapPrint) { printf("\n block variable layout for block: "); - const unsigned char *s = (unsigned char*)BitMap.c_str(); + const unsigned char *s = (const unsigned char*)BitMap.c_str(); for (unsigned i = 0, e = BitMap.size(); i < e; i++) if (!(s[i] & 0xf0)) printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); @@ -1872,6 +1965,476 @@ llvm::Constant *CGObjCCommonMac::BuildGCBlockLayout(CodeGenModule &CGM, return C; } +/// getBlockCaptureLifetime - This routine returns life time of the captured +/// block variable for the purpose of block layout meta-data generation. FQT is +/// the type of the variable captured in the block. +Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT) { + if (CGM.getLangOpts().ObjCAutoRefCount) + return FQT.getObjCLifetime(); + + // MRR. + if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType()) + return Qualifiers::OCL_ExplicitNone; + + return Qualifiers::OCL_None; +} + +void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, + Qualifiers::ObjCLifetime LifeTime, + CharUnits FieldOffset, + CharUnits FieldSize) { + // __block variables are passed by their descriptor address. + if (IsByref) + RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, + FieldSize)); + else if (LifeTime == Qualifiers::OCL_Strong) + RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, + FieldSize)); + else if (LifeTime == Qualifiers::OCL_Weak) + RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, + FieldSize)); + else if (LifeTime == Qualifiers::OCL_ExplicitNone) + RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, + FieldSize)); + else + RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, + FieldOffset, + FieldSize)); +} + +void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, + const RecordDecl *RD, + ArrayRef<const FieldDecl*> RecFields, + CharUnits BytePos, bool &HasUnion) { + bool IsUnion = (RD && RD->isUnion()); + CharUnits MaxUnionSize = CharUnits::Zero(); + const FieldDecl *MaxField = 0; + const FieldDecl *LastFieldBitfieldOrUnnamed = 0; + CharUnits MaxFieldOffset = CharUnits::Zero(); + CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero(); + + if (RecFields.empty()) + return; + unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + + for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { + const FieldDecl *Field = RecFields[i]; + // Note that 'i' here is actually the field index inside RD of Field, + // although this dependency is hidden. + const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); + CharUnits FieldOffset = + CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i)); + + // Skip over unnamed or bitfields + if (!Field->getIdentifier() || Field->isBitField()) { + LastFieldBitfieldOrUnnamed = Field; + LastBitfieldOrUnnamedOffset = FieldOffset; + continue; + } + + LastFieldBitfieldOrUnnamed = 0; + QualType FQT = Field->getType(); + if (FQT->isRecordType() || FQT->isUnionType()) { + if (FQT->isUnionType()) + HasUnion = true; + + BuildRCBlockVarRecordLayout(FQT->getAs<RecordType>(), + BytePos + FieldOffset, HasUnion); + continue; + } + + if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { + const ConstantArrayType *CArray = + dyn_cast_or_null<ConstantArrayType>(Array); + uint64_t ElCount = CArray->getSize().getZExtValue(); + assert(CArray && "only array with known element size is supported"); + FQT = CArray->getElementType(); + while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) { + const ConstantArrayType *CArray = + dyn_cast_or_null<ConstantArrayType>(Array); + ElCount *= CArray->getSize().getZExtValue(); + FQT = CArray->getElementType(); + } + + assert(!FQT->isUnionType() && + "layout for array of unions not supported"); + if (FQT->isRecordType() && ElCount) { + int OldIndex = RunSkipBlockVars.size() - 1; + const RecordType *RT = FQT->getAs<RecordType>(); + BuildRCBlockVarRecordLayout(RT, BytePos + FieldOffset, + HasUnion); + + // Replicate layout information for each array element. Note that + // one element is already done. + uint64_t ElIx = 1; + for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) { + CharUnits Size = CGM.getContext().getTypeSizeInChars(RT); + for (int i = OldIndex+1; i <= FirstIndex; ++i) + RunSkipBlockVars.push_back( + RUN_SKIP(RunSkipBlockVars[i].opcode, + RunSkipBlockVars[i].block_var_bytepos + Size*ElIx, + RunSkipBlockVars[i].block_var_size)); + } + continue; + } + } + CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType()); + if (IsUnion) { + CharUnits UnionIvarSize = FieldSize; + if (UnionIvarSize > MaxUnionSize) { + MaxUnionSize = UnionIvarSize; + MaxField = Field; + MaxFieldOffset = FieldOffset; + } + } else { + UpdateRunSkipBlockVars(false, + getBlockCaptureLifetime(FQT), + BytePos + FieldOffset, + FieldSize); + } + } + + if (LastFieldBitfieldOrUnnamed) { + if (LastFieldBitfieldOrUnnamed->isBitField()) { + // Last field was a bitfield. Must update the info. + uint64_t BitFieldSize + = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); + unsigned UnsSize = (BitFieldSize / ByteSizeInBits) + + ((BitFieldSize % ByteSizeInBits) != 0); + CharUnits Size = CharUnits::fromQuantity(UnsSize); + Size += LastBitfieldOrUnnamedOffset; + UpdateRunSkipBlockVars(false, + getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType()), + BytePos + LastBitfieldOrUnnamedOffset, + Size); + } else { + assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); + // Last field was unnamed. Must update skip info. + CharUnits FieldSize + = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType()); + UpdateRunSkipBlockVars(false, + getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType()), + BytePos + LastBitfieldOrUnnamedOffset, + FieldSize); + } + } + + if (MaxField) + UpdateRunSkipBlockVars(false, + getBlockCaptureLifetime(MaxField->getType()), + BytePos + MaxFieldOffset, + MaxUnionSize); +} + +void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, + CharUnits BytePos, + bool &HasUnion) { + const RecordDecl *RD = RT->getDecl(); + SmallVector<const FieldDecl*, 16> Fields; + for (RecordDecl::field_iterator i = RD->field_begin(), + e = RD->field_end(); i != e; ++i) + Fields.push_back(*i); + llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); + const llvm::StructLayout *RecLayout = + CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty)); + + BuildRCRecordLayout(RecLayout, RD, Fields, BytePos, HasUnion); +} + +/// InlineLayoutInstruction - This routine produce an inline instruction for the +/// block variable layout if it can. If not, it returns 0. Rules are as follow: +/// If ((uintptr_t) layout) < (1 << 12), the layout is inline. In the 64bit world, +/// an inline layout of value 0x0000000000000xyz is interpreted as follows: +/// x captured object pointers of BLOCK_LAYOUT_STRONG. Followed by +/// y captured object of BLOCK_LAYOUT_BYREF. Followed by +/// z captured object of BLOCK_LAYOUT_WEAK. If any of the above is missing, zero +/// replaces it. For example, 0x00000x00 means x BLOCK_LAYOUT_STRONG and no +/// BLOCK_LAYOUT_BYREF and no BLOCK_LAYOUT_WEAK objects are captured. +uint64_t CGObjCCommonMac::InlineLayoutInstruction( + SmallVectorImpl<unsigned char> &Layout) { + uint64_t Result = 0; + if (Layout.size() <= 3) { + unsigned size = Layout.size(); + unsigned strong_word_count = 0, byref_word_count=0, weak_word_count=0; + unsigned char inst; + enum BLOCK_LAYOUT_OPCODE opcode ; + switch (size) { + case 3: + inst = Layout[0]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_STRONG) + strong_word_count = (inst & 0xF)+1; + else + return 0; + inst = Layout[1]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_BYREF) + byref_word_count = (inst & 0xF)+1; + else + return 0; + inst = Layout[2]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF)+1; + else + return 0; + break; + + case 2: + inst = Layout[0]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_STRONG) { + strong_word_count = (inst & 0xF)+1; + inst = Layout[1]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_BYREF) + byref_word_count = (inst & 0xF)+1; + else if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF)+1; + else + return 0; + } + else if (opcode == BLOCK_LAYOUT_BYREF) { + byref_word_count = (inst & 0xF)+1; + inst = Layout[1]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF)+1; + else + return 0; + } + else + return 0; + break; + + case 1: + inst = Layout[0]; + opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_STRONG) + strong_word_count = (inst & 0xF)+1; + else if (opcode == BLOCK_LAYOUT_BYREF) + byref_word_count = (inst & 0xF)+1; + else if (opcode == BLOCK_LAYOUT_WEAK) + weak_word_count = (inst & 0xF)+1; + else + return 0; + break; + + default: + return 0; + } + + // Cannot inline when any of the word counts is 15. Because this is one less + // than the actual work count (so 15 means 16 actual word counts), + // and we can only display 0 thru 15 word counts. + if (strong_word_count == 16 || byref_word_count == 16 || weak_word_count == 16) + return 0; + + unsigned count = + (strong_word_count != 0) + (byref_word_count != 0) + (weak_word_count != 0); + + if (size == count) { + if (strong_word_count) + Result = strong_word_count; + Result <<= 4; + if (byref_word_count) + Result += byref_word_count; + Result <<= 4; + if (weak_word_count) + Result += weak_word_count; + } + } + return Result; +} + +llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, + const CGBlockInfo &blockInfo) { + assert(CGM.getLangOpts().getGC() == LangOptions::NonGC); + + llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy); + + RunSkipBlockVars.clear(); + bool hasUnion = false; + + unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0); + unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth(); + unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits; + + const BlockDecl *blockDecl = blockInfo.getBlockDecl(); + + // Calculate the basic layout of the block structure. + const llvm::StructLayout *layout = + CGM.getDataLayout().getStructLayout(blockInfo.StructureType); + + // Ignore the optional 'this' capture: C++ objects are not assumed + // to be GC'ed. + + // Walk the captured variables. + for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), + ce = blockDecl->capture_end(); ci != ce; ++ci) { + const VarDecl *variable = ci->getVariable(); + QualType type = variable->getType(); + + const CGBlockInfo::Capture &capture = blockInfo.getCapture(variable); + + // Ignore constant captures. + if (capture.isConstant()) continue; + + CharUnits fieldOffset = + CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex())); + + assert(!type->isArrayType() && "array variable should not be caught"); + if (const RecordType *record = type->getAs<RecordType>()) { + BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion); + continue; + } + CharUnits fieldSize; + if (ci->isByRef()) + fieldSize = CharUnits::fromQuantity(WordSizeInBytes); + else + fieldSize = CGM.getContext().getTypeSizeInChars(type); + UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type), + fieldOffset, fieldSize); + } + + if (RunSkipBlockVars.empty()) + return nullPtr; + + // Sort on byte position; captures might not be allocated in order, + // and unions can do funny things. + llvm::array_pod_sort(RunSkipBlockVars.begin(), RunSkipBlockVars.end()); + SmallVector<unsigned char, 16> Layout; + + unsigned size = RunSkipBlockVars.size(); + for (unsigned i = 0; i < size; i++) { + enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode; + CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos; + CharUnits end_byte_pos = start_byte_pos; + unsigned j = i+1; + while (j < size) { + if (opcode == RunSkipBlockVars[j].opcode) { + end_byte_pos = RunSkipBlockVars[j++].block_var_bytepos; + i++; + } + else + break; + } + CharUnits size_in_bytes = + end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size; + if (j < size) { + CharUnits gap = + RunSkipBlockVars[j].block_var_bytepos - + RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size; + size_in_bytes += gap; + } + CharUnits residue_in_bytes = CharUnits::Zero(); + if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) { + residue_in_bytes = size_in_bytes % WordSizeInBytes; + size_in_bytes -= residue_in_bytes; + opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS; + } + + unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes; + while (size_in_words >= 16) { + // Note that value in imm. is one less that the actual + // value. So, 0xf means 16 words follow! + unsigned char inst = (opcode << 4) | 0xf; + Layout.push_back(inst); + size_in_words -= 16; + } + if (size_in_words > 0) { + // Note that value in imm. is one less that the actual + // value. So, we subtract 1 away! + unsigned char inst = (opcode << 4) | (size_in_words-1); + Layout.push_back(inst); + } + if (residue_in_bytes > CharUnits::Zero()) { + unsigned char inst = + (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1); + Layout.push_back(inst); + } + } + + int e = Layout.size()-1; + while (e >= 0) { + unsigned char inst = Layout[e--]; + enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES || opcode == BLOCK_LAYOUT_NON_OBJECT_WORDS) + Layout.pop_back(); + else + break; + } + + uint64_t Result = InlineLayoutInstruction(Layout); + if (Result != 0) { + // Block variable layout instruction has been inlined. + if (CGM.getLangOpts().ObjCGCBitmapPrint) { + printf("\n Inline instruction for block variable layout: "); + printf("0x0%llx\n", (unsigned long long)Result); + } + if (WordSizeInBytes == 8) { + const llvm::APInt Instruction(64, Result); + return llvm::Constant::getIntegerValue(CGM.Int64Ty, Instruction); + } + else { + const llvm::APInt Instruction(32, Result); + return llvm::Constant::getIntegerValue(CGM.Int32Ty, Instruction); + } + } + + unsigned char inst = (BLOCK_LAYOUT_OPERATOR << 4) | 0; + Layout.push_back(inst); + std::string BitMap; + for (unsigned i = 0, e = Layout.size(); i != e; i++) + BitMap += Layout[i]; + + if (CGM.getLangOpts().ObjCGCBitmapPrint) { + printf("\n block variable layout: "); + for (unsigned i = 0, e = BitMap.size(); i != e; i++) { + unsigned char inst = BitMap[i]; + enum BLOCK_LAYOUT_OPCODE opcode = (enum BLOCK_LAYOUT_OPCODE) (inst >> 4); + unsigned delta = 1; + switch (opcode) { + case BLOCK_LAYOUT_OPERATOR: + printf("BL_OPERATOR:"); + delta = 0; + break; + case BLOCK_LAYOUT_NON_OBJECT_BYTES: + printf("BL_NON_OBJECT_BYTES:"); + break; + case BLOCK_LAYOUT_NON_OBJECT_WORDS: + printf("BL_NON_OBJECT_WORD:"); + break; + case BLOCK_LAYOUT_STRONG: + printf("BL_STRONG:"); + break; + case BLOCK_LAYOUT_BYREF: + printf("BL_BYREF:"); + break; + case BLOCK_LAYOUT_WEAK: + printf("BL_WEAK:"); + break; + case BLOCK_LAYOUT_UNRETAINED: + printf("BL_UNRETAINED:"); + break; + } + // Actual value of word count is one more that what is in the imm. + // field of the instruction + printf("%d", (inst & 0xf) + delta); + if (i < e-1) + printf(", "); + else + printf("\n"); + } + } + + llvm::GlobalVariable * Entry = + CreateMetadataVar("\01L_OBJC_CLASS_NAME_", + llvm::ConstantDataArray::getString(VMContext, BitMap,false), + "__TEXT,__objc_classname,cstring_literals", 1, true); + return getConstantGEP(VMContext, Entry, 0, 0); +} + llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder, const ObjCProtocolDecl *PD) { // FIXME: I don't understand why gcc generates this, or where it is @@ -2040,7 +2603,7 @@ CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD, ArrayRef<llvm::Constant*> OptClassMethods, ArrayRef<llvm::Constant*> MethodTypesExt) { uint64_t Size = - CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy); llvm::Constant *Values[] = { llvm::ConstantInt::get(ObjCTypes.IntTy, Size), EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_" @@ -2180,7 +2743,7 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(Twine Name, return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); unsigned PropertySize = - CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.PropertyTy); llvm::Constant *Values[3]; Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize); Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size()); @@ -2269,7 +2832,7 @@ CGObjCMac::EmitMethodDescList(Twine Name, const char *Section, }; */ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.CategoryTy); // FIXME: This is poor design, the OCD should have a pointer to the category // decl. Additionally, note that Category can be null for the @implementation @@ -2338,15 +2901,37 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { MethodDefinitions.clear(); } -// FIXME: Get from somewhere? -enum ClassFlags { - eClassFlags_Factory = 0x00001, - eClassFlags_Meta = 0x00002, - // <rdr://5142207> - eClassFlags_HasCXXStructors = 0x02000, - eClassFlags_Hidden = 0x20000, - eClassFlags_ABI2_Hidden = 0x00010, - eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634> +enum FragileClassFlags { + FragileABI_Class_Factory = 0x00001, + FragileABI_Class_Meta = 0x00002, + FragileABI_Class_HasCXXStructors = 0x02000, + FragileABI_Class_Hidden = 0x20000 +}; + +enum NonFragileClassFlags { + /// Is a meta-class. + NonFragileABI_Class_Meta = 0x00001, + + /// Is a root class. + NonFragileABI_Class_Root = 0x00002, + + /// Has a C++ constructor and destructor. + NonFragileABI_Class_HasCXXStructors = 0x00004, + + /// Has hidden visibility. + NonFragileABI_Class_Hidden = 0x00010, + + /// Has the exception attribute. + NonFragileABI_Class_Exception = 0x00020, + + /// (Obsolete) ARC-specific: this class has a .release_ivars method + NonFragileABI_Class_HasIvarReleaser = 0x00040, + + /// Class implementation was compiled under ARC. + NonFragileABI_Class_CompiledByARC = 0x00080, + + /// Class has non-trivial destructors, but zero-initialization is okay. + NonFragileABI_Class_HasCXXDestructorOnly = 0x00100 }; /* @@ -2379,15 +2964,15 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(), Interface->all_referenced_protocol_begin(), Interface->all_referenced_protocol_end()); - unsigned Flags = eClassFlags_Factory; - if (ID->hasCXXStructors()) - Flags |= eClassFlags_HasCXXStructors; + unsigned Flags = FragileABI_Class_Factory; + if (ID->hasNonZeroConstructors() || ID->hasDestructors()) + Flags |= FragileABI_Class_HasCXXStructors; unsigned Size = CGM.getContext().getASTObjCImplementationLayout(ID).getSize().getQuantity(); // FIXME: Set CXX-structors flag. if (ID->getClassInterface()->getVisibility() == HiddenVisibility) - Flags |= eClassFlags_Hidden; + Flags |= FragileABI_Class_Hidden; llvm::SmallVector<llvm::Constant*, 16> InstanceMethods, ClassMethods; for (ObjCImplementationDecl::instmeth_iterator @@ -2470,11 +3055,11 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, llvm::Constant *Protocols, ArrayRef<llvm::Constant*> Methods) { - unsigned Flags = eClassFlags_Meta; - unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy); + unsigned Flags = FragileABI_Class_Meta; + unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassTy); if (ID->getClassInterface()->getVisibility() == HiddenVisibility) - Flags |= eClassFlags_Hidden; + Flags |= FragileABI_Class_Hidden; llvm::Constant *Values[12]; // The isa for the metaclass is the root of the hierarchy. @@ -2588,7 +3173,7 @@ llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) { llvm::Constant * CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) { uint64_t Size = - CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassExtensionTy); llvm::Constant *Values[3]; Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); @@ -3481,7 +4066,7 @@ void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); @@ -3502,7 +4087,7 @@ void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, bool threadlocal) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); @@ -3528,7 +4113,7 @@ void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL"); llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); @@ -3548,7 +4133,7 @@ void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy); @@ -3679,7 +4264,7 @@ void CGObjCCommonMac::EmitImageInfo() { static const int ModuleVersion = 7; void CGObjCMac::EmitModuleInfo() { - uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy); + uint64_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ModuleTy); llvm::Constant *Values[] = { llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion), @@ -3824,7 +4409,7 @@ void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT, Fields.push_back(*i); llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0)); const llvm::StructLayout *RecLayout = - CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty)); + CGM.getDataLayout().getStructLayout(cast<llvm::StructType>(Ty)); BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos, ForStrongLayout, HasUnion); @@ -3951,7 +4536,7 @@ void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI, if (IsUnion) { // FIXME: Why the asymmetry? We divide by word size in bits on other // side. - uint64_t UnionIvarSize = FieldSize; + uint64_t UnionIvarSize = FieldSize / ByteSizeInBits; if (UnionIvarSize > MaxSkippedUnionIvarSize) { MaxSkippedUnionIvarSize = UnionIvarSize; MaxSkippedField = Field; @@ -4005,7 +4590,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayoutBitmap(std::string &BitMap) { // Build the string of skip/scan nibbles SmallVector<SKIP_SCAN, 32> SkipScanIvars; unsigned int WordSize = - CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy); + CGM.getTypes().getDataLayout().getTypeAllocSize(PtrTy); if (IvarsInfo[0].ivar_bytepos == 0) { WordsToSkip = 0; WordsToScan = IvarsInfo[0].ivar_size; @@ -4187,7 +4772,7 @@ llvm::Constant *CGObjCCommonMac::BuildIvarLayout( printf("\n%s ivar layout for class '%s': ", ForStrongLayout ? "strong" : "weak", OMD->getClassInterface()->getName().data()); - const unsigned char *s = (unsigned char*)BitMap.c_str(); + const unsigned char *s = (const unsigned char*)BitMap.c_str(); for (unsigned i = 0, e = BitMap.size(); i < e; i++) if (!(s[i] & 0xf0)) printf("0x0%x%s", s[i], s[i] != 0 ? ", " : ""); @@ -4835,7 +5420,7 @@ AddModuleClassList(ArrayRef<llvm::GlobalValue*> Container, llvm::GlobalValue::InternalLinkage, Init, SymbolName); - GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType())); + GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); GV->setSection(SectionName); CGM.AddUsedGlobal(GV); } @@ -4941,19 +5526,6 @@ bool CGObjCNonFragileABIMac::isVTableDispatchedSelector(Selector Sel) { return VTableDispatchMethods.count(Sel); } -// Metadata flags -enum MetaDataDlags { - CLS = 0x0, - CLS_META = 0x1, - CLS_ROOT = 0x2, - OBJC2_CLS_HIDDEN = 0x10, - CLS_EXCEPTION = 0x20, - - /// (Obsolete) ARC-specific: this class has a .release_ivars method - CLS_HAS_IVAR_RELEASER = 0x40, - /// class was compiled with -fobjc-arr - CLS_COMPILED_BY_ARC = 0x80 // (1<<7) -}; /// BuildClassRoTInitializer - generate meta-data for: /// struct _class_ro_t { /// uint32_t const flags; @@ -4978,19 +5550,20 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( llvm::Constant *Values[10]; // 11 for 64bit targets! if (CGM.getLangOpts().ObjCAutoRefCount) - flags |= CLS_COMPILED_BY_ARC; + flags |= NonFragileABI_Class_CompiledByARC; Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags); Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart); Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize); // FIXME. For 64bit targets add 0 here. - Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) + Values[ 3] = (flags & NonFragileABI_Class_Meta) + ? GetIvarLayoutName(0, ObjCTypes) : BuildIvarLayout(ID, true); Values[ 4] = GetClassName(ID->getIdentifier()); // const struct _method_list_t * const baseMethods; std::vector<llvm::Constant*> Methods; std::string MethodListName("\01l_OBJC_$_"); - if (flags & CLS_META) { + if (flags & NonFragileABI_Class_Meta) { MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); for (ObjCImplementationDecl::classmeth_iterator i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) { @@ -5030,28 +5603,27 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( OID->all_referenced_protocol_begin(), OID->all_referenced_protocol_end()); - if (flags & CLS_META) + if (flags & NonFragileABI_Class_Meta) { Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); - else - Values[ 7] = EmitIvarList(ID); - Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes) - : BuildIvarLayout(ID, false); - if (flags & CLS_META) + Values[ 8] = GetIvarLayoutName(0, ObjCTypes); Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy); - else + } else { + Values[ 7] = EmitIvarList(ID); + Values[ 8] = BuildIvarLayout(ID, false); Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), ID, ID->getClassInterface(), ObjCTypes); + } llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, Values); llvm::GlobalVariable *CLASS_RO_GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false, llvm::GlobalValue::InternalLinkage, Init, - (flags & CLS_META) ? + (flags & NonFragileABI_Class_Meta) ? std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName : std::string("\01l_OBJC_CLASS_RO_$_")+ClassName); CLASS_RO_GV->setAlignment( - CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy)); + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassRonfABITy)); CLASS_RO_GV->setSection("__DATA, __objc_const"); return CLASS_RO_GV; @@ -5088,7 +5660,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData( GV->setInitializer(Init); GV->setSection("__DATA, __objc_data"); GV->setAlignment( - CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy)); + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)); if (HiddenVisibility) GV->setVisibility(llvm::GlobalValue::HiddenVisibility); return GV; @@ -5138,23 +5710,31 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { "CGObjCNonFragileABIMac::GenerateClass - class is 0"); // FIXME: Is this correct (that meta class size is never computed)? uint32_t InstanceStart = - CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); uint32_t InstanceSize = InstanceStart; - uint32_t flags = CLS_META; + uint32_t flags = NonFragileABI_Class_Meta; std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); std::string ObjCClassName(getClassSymbolPrefix()); llvm::GlobalVariable *SuperClassGV, *IsAGV; + // Build the flags for the metaclass. bool classIsHidden = ID->getClassInterface()->getVisibility() == HiddenVisibility; if (classIsHidden) - flags |= OBJC2_CLS_HIDDEN; - if (ID->hasCXXStructors()) - flags |= eClassFlags_ABI2_HasCXXStructors; + flags |= NonFragileABI_Class_Hidden; + + // FIXME: why is this flag set on the metaclass? + // ObjC metaclasses have no fields and don't really get constructed. + if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { + flags |= NonFragileABI_Class_HasCXXStructors; + if (!ID->hasNonZeroConstructors()) + flags |= NonFragileABI_Class_HasCXXDestructorOnly; + } + if (!ID->getClassInterface()->getSuperClass()) { // class is root - flags |= CLS_ROOT; + flags |= NonFragileABI_Class_Root; SuperClassGV = GetClassGlobal(ObjCClassName + ClassName); IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName); } else { @@ -5183,17 +5763,28 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { DefinedMetaClasses.push_back(MetaTClass); // Metadata for the class - flags = CLS; + flags = 0; if (classIsHidden) - flags |= OBJC2_CLS_HIDDEN; - if (ID->hasCXXStructors()) - flags |= eClassFlags_ABI2_HasCXXStructors; + flags |= NonFragileABI_Class_Hidden; + + if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { + flags |= NonFragileABI_Class_HasCXXStructors; + + // Set a flag to enable a runtime optimization when a class has + // fields that require destruction but which don't require + // anything except zero-initialization during construction. This + // is most notably true of __strong and __weak types, but you can + // also imagine there being C++ types with non-trivial default + // constructors that merely set all fields to null. + if (!ID->hasNonZeroConstructors()) + flags |= NonFragileABI_Class_HasCXXDestructorOnly; + } if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface())) - flags |= CLS_EXCEPTION; + flags |= NonFragileABI_Class_Exception; if (!ID->getClassInterface()->getSuperClass()) { - flags |= CLS_ROOT; + flags |= NonFragileABI_Class_Root; SuperClassGV = 0; } else { // Has a root. Current class is not a root. @@ -5220,7 +5811,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { DefinedNonLazyClasses.push_back(ClassMD); // Force the definition of the EHType if necessary. - if (flags & CLS_EXCEPTION) + if (flags & NonFragileABI_Class_Exception) GetInterfaceEHType(ID->getClassInterface(), true); // Make sure method definition entries are all clear for next implementation. MethodDefinitions.clear(); @@ -5344,7 +5935,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { Init, ExtCatName); GCATV->setAlignment( - CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy)); + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy)); GCATV->setSection("__DATA, __objc_const"); CGM.AddUsedGlobal(GCATV); DefinedCategories.push_back(GCATV); @@ -5391,7 +5982,7 @@ CGObjCNonFragileABIMac::EmitMethodList(Twine Name, llvm::Constant *Values[3]; // sizeof(struct _objc_method) - unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.MethodTy); Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); // method_count Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size()); @@ -5403,7 +5994,7 @@ CGObjCNonFragileABIMac::EmitMethodList(Twine Name, llvm::GlobalVariable *GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::InternalLinkage, Init, Name); - GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType())); + GV->setAlignment(CGM.getDataLayout().getABITypeAlignment(Init->getType())); GV->setSection(Section); CGM.AddUsedGlobal(GV); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.MethodListnfABIPtrTy); @@ -5437,7 +6028,7 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID, IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy, Offset)); IvarOffsetGV->setAlignment( - CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy)); + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.LongTy)); // FIXME: This matches gcc, but shouldn't the visibility be set on the use as // well (i.e., in ObjCIvarOffsetVariable). @@ -5490,7 +6081,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( Ivar[2] = GetMethodVarType(IVD); llvm::Type *FieldTy = CGM.getTypes().ConvertTypeForMem(IVD->getType()); - unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(FieldTy); unsigned Align = CGM.getContext().getPreferredTypeAlign( IVD->getType().getTypePtr()) >> 3; Align = llvm::Log2_32(Align); @@ -5508,7 +6099,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy); llvm::Constant *Values[3]; - unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.IvarnfABITy); Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size()); llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy, @@ -5522,7 +6113,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( Init, Prefix + OID->getName()); GV->setAlignment( - CGM.getTargetData().getABITypeAlignment(Init->getType())); + CGM.getDataLayout().getABITypeAlignment(Init->getType())); GV->setSection("__DATA, __objc_const"); CGM.AddUsedGlobal(GV); @@ -5644,7 +6235,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(), 0, PD, ObjCTypes); uint32_t Size = - CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); + CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_" @@ -5663,7 +6254,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( false, llvm::GlobalValue::WeakAnyLinkage, Init, "\01l_OBJC_PROTOCOL_$_" + PD->getName()); Entry->setAlignment( - CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy)); + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy)); Entry->setSection("__DATA,__datacoal_nt,coalesced"); Protocols[PD->getIdentifier()] = Entry; @@ -5678,7 +6269,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( false, llvm::GlobalValue::WeakAnyLinkage, Entry, "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName()); PTGV->setAlignment( - CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); + CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility); CGM.AddUsedGlobal(PTGV); @@ -5732,7 +6323,7 @@ CGObjCNonFragileABIMac::EmitProtocolList(Twine Name, Init, Name); GV->setSection("__DATA, __objc_const"); GV->setAlignment( - CGM.getTargetData().getABITypeAlignment(Init->getType())); + CGM.getDataLayout().getABITypeAlignment(Init->getType())); CGM.AddUsedGlobal(GV); return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy); @@ -5970,7 +6561,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CGBuilderTy &Builder, ClassGV, "\01L_OBJC_CLASSLIST_REFERENCES_$_"); Entry->setAlignment( - CGM.getTargetData().getABITypeAlignment( + CGM.getDataLayout().getABITypeAlignment( ObjCTypes.ClassnfABIPtrTy)); Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip"); CGM.AddUsedGlobal(Entry); @@ -6004,7 +6595,7 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder, ClassGV, "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment( - CGM.getTargetData().getABITypeAlignment( + CGM.getDataLayout().getABITypeAlignment( ObjCTypes.ClassnfABIPtrTy)); Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); CGM.AddUsedGlobal(Entry); @@ -6030,7 +6621,7 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder, MetaClassGV, "\01L_OBJC_CLASSLIST_SUP_REFS_$_"); Entry->setAlignment( - CGM.getTargetData().getABITypeAlignment( + CGM.getDataLayout().getABITypeAlignment( ObjCTypes.ClassnfABIPtrTy)); Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip"); @@ -6079,16 +6670,9 @@ CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF, // If this is a class message the metaclass is passed as the target. llvm::Value *Target; - if (IsClassMessage) { - if (isCategoryImpl) { - // Message sent to "super' in a class method defined in - // a category implementation. - Target = EmitClassRef(CGF.Builder, Class); - Target = CGF.Builder.CreateStructGEP(Target, 0); - Target = CGF.Builder.CreateLoad(Target); - } else + if (IsClassMessage) Target = EmitMetaClassRef(CGF.Builder, Class); - } else + else Target = EmitSuperClassRef(CGF.Builder, Class); // FIXME: We shouldn't need to do this cast, rectify the ASTContext and @@ -6143,7 +6727,7 @@ void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *ivarOffset) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); @@ -6164,7 +6748,7 @@ void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign( llvm::Value *src, llvm::Value *dst) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); @@ -6211,7 +6795,7 @@ void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF, llvm::Value *src, llvm::Value *dst) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); @@ -6232,7 +6816,7 @@ void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF, bool threadlocal) { llvm::Type * SrcTy = src->getType(); if (!isa<llvm::PointerType>(SrcTy)) { - unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy); + unsigned Size = CGM.getDataLayout().getTypeAllocSize(SrcTy); assert(Size <= 8 && "does not support size > 8"); src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy) : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy)); @@ -6364,7 +6948,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, if (CGM.getLangOpts().getVisibilityMode() == HiddenVisibility) Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); - Entry->setAlignment(CGM.getTargetData().getABITypeAlignment( + Entry->setAlignment(CGM.getDataLayout().getABITypeAlignment( ObjCTypes.EHTypeTy)); if (ForDefinition) { |