[cfe-commits] r167047 - /cfe/trunk/lib/CodeGen/CGObjCMac.cpp
Fariborz Jahanian
fjahanian at apple.com
Tue Oct 30 13:05:29 PDT 2012
Author: fjahanian
Date: Tue Oct 30 15:05:29 2012
New Revision: 167047
URL: http://llvm.org/viewvc/llvm-project?rev=167047&view=rev
Log:
objective-C arc/mrr: Another patch for the new captured block variable
layout meta-data. It is currently off (so no tests). This is wip.
Modified:
cfe/trunk/lib/CodeGen/CGObjCMac.cpp
Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=167047&r1=167046&r2=167047&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Tue Oct 30 15:05:29 2012
@@ -941,6 +941,20 @@
ArrayRef<const FieldDecl*> RecFields,
unsigned int BytePos, bool ForStrongLayout,
bool &HasUnion);
+
+ void UpdateRunSkipBlockVars(bool IsByref,
+ Qualifiers::ObjCLifetime LifeTime,
+ unsigned FieldOffset,
+ unsigned FieldSize);
+
+ void BuildRCBlockVarRecordLayout(const RecordType *RT,
+ unsigned int BytePos, bool &HasUnion);
+
+ void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
+ const RecordDecl *RD,
+ ArrayRef<const FieldDecl*> RecFields,
+ unsigned int BytePos, bool &HasUnion);
+
/// GetIvarLayoutName - Returns a unique constant for the given
/// ivar layout bitmap.
@@ -1946,6 +1960,170 @@
return C;
}
+void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
+ Qualifiers::ObjCLifetime LifeTime,
+ unsigned FieldOffset,
+ unsigned FieldSize) {
+ unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
+ unsigned FieldSizeInBytes = FieldSize/ByteSizeInBits;
+
+ // __block variables are passed by their descriptor address.
+ if (IsByref)
+ RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
+ FieldSizeInBytes));
+ else if (LifeTime == Qualifiers::OCL_Strong)
+ RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
+ FieldSizeInBytes));
+ else if (LifeTime == Qualifiers::OCL_Weak)
+ RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
+ FieldSizeInBytes));
+ else if (LifeTime == Qualifiers::OCL_ExplicitNone)
+ RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
+ FieldSizeInBytes));
+ else
+ RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
+ FieldOffset,
+ FieldSizeInBytes));
+}
+
+void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
+ const RecordDecl *RD,
+ ArrayRef<const FieldDecl*> RecFields,
+ unsigned int BytePos, bool &HasUnion) {
+ bool IsUnion = (RD && RD->isUnion());
+ uint64_t MaxUnionSize = 0;
+ const FieldDecl *MaxField = 0;
+ const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
+ uint64_t MaxFieldOffset = 0;
+ uint64_t LastBitfieldOrUnnamedOffset = 0;
+
+ 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];
+ uint64_t FieldOffset;
+ // 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);
+ FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits);
+
+ // 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++) {
+ uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
+ 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;
+ }
+ }
+ unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
+ if (IsUnion) {
+ uint64_t UnionIvarSize = FieldSize;
+ if (UnionIvarSize > MaxUnionSize) {
+ MaxUnionSize = UnionIvarSize;
+ MaxField = Field;
+ MaxFieldOffset = FieldOffset;
+ }
+ } else {
+ UpdateRunSkipBlockVars(false,
+ Field->getType().getObjCLifetime(),
+ 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 Size = (BitFieldSize / ByteSizeInBits) +
+ ((BitFieldSize % ByteSizeInBits) != 0);
+ Size += LastBitfieldOrUnnamedOffset;
+ UpdateRunSkipBlockVars(false,
+ LastFieldBitfieldOrUnnamed->getType().getObjCLifetime(),
+ BytePos + LastBitfieldOrUnnamedOffset,
+ Size*ByteSizeInBits);
+ } else {
+ assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
+ // Last field was unnamed. Must update skip info.
+ unsigned FieldSize
+ = CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType());
+ UpdateRunSkipBlockVars(false,
+ LastFieldBitfieldOrUnnamed->getType().getObjCLifetime(),
+ BytePos + LastBitfieldOrUnnamedOffset,
+ FieldSize);
+ }
+ }
+
+ if (MaxField)
+ UpdateRunSkipBlockVars(false,
+ MaxField->getType().getObjCLifetime(),
+ BytePos + MaxFieldOffset,
+ MaxUnionSize);
+}
+
+void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
+ unsigned int 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);
+}
+
llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
const CGBlockInfo &blockInfo) {
// FIXME. Temporary call the GC layout routine.
@@ -1956,7 +2134,8 @@
llvm::Constant *nullPtr = llvm::Constant::getNullValue(CGM.Int8PtrTy);
RunSkipBlockVars.clear();
- // bool hasUnion = false;
+ bool hasUnion = false;
+
unsigned WordSizeInBits = CGM.getContext().getTargetInfo().getPointerWidth(0);
unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
unsigned WordSizeInBytes = WordSizeInBits/ByteSizeInBits;
@@ -1983,31 +2162,14 @@
uint64_t fieldOffset = layout->getElementOffset(capture.getIndex());
- // __block variables are passed by their descriptor address.
- if (ci->isByRef()) {
- RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, fieldOffset,
- WordSizeInBytes));
+ assert(!type->isArrayType() && "array variable should not be caught");
+ if (const RecordType *record = type->getAs<RecordType>()) {
+ BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
continue;
}
-
- assert(!type->isArrayType() && "array variable should not be caught");
- assert(!type->getAs<RecordType>() &&
- "BuildRCBlockLayout - captured records NYI");
-
unsigned fieldSize = CGM.getContext().getTypeSize(type);
-
- if (type.getObjCLifetime() == Qualifiers::OCL_Strong)
- RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, fieldOffset,
- WordSizeInBytes));
- else if (type.getObjCLifetime() == Qualifiers::OCL_Weak)
- RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, fieldOffset,
- WordSizeInBytes));
- else if (type.getObjCLifetime() == Qualifiers::OCL_ExplicitNone)
- RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, fieldOffset,
- WordSizeInBytes));
- else
- RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, fieldOffset,
- fieldSize/ByteSizeInBits));
+ UpdateRunSkipBlockVars(ci->isByRef(), type.getObjCLifetime(),
+ fieldOffset, fieldSize);
}
if (RunSkipBlockVars.empty())
@@ -2036,6 +2198,12 @@
}
unsigned size_in_bytes =
end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
+ if (j < size) {
+ unsigned gap =
+ RunSkipBlockVars[j].block_var_bytepos -
+ RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
+ size_in_bytes += gap;
+ }
unsigned residue_in_bytes = 0;
if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
residue_in_bytes = size_in_bytes & mask;
More information about the cfe-commits
mailing list