objective-C blocks: bring back the CharUnit patch for

captured block variable layout meta-data. No intended change
in functionality.

llvm-svn: 167549
This commit is contained in:
Fariborz Jahanian 2012-11-07 20:00:32 +00:00
parent 28e02ec8c1
commit 7778d616e8
1 changed files with 46 additions and 45 deletions

View File

@ -810,10 +810,11 @@ public:
class RUN_SKIP { class RUN_SKIP {
public: public:
enum BLOCK_LAYOUT_OPCODE opcode; enum BLOCK_LAYOUT_OPCODE opcode;
unsigned block_var_bytepos; CharUnits block_var_bytepos;
unsigned block_var_size; CharUnits block_var_size;
RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR, RUN_SKIP(enum BLOCK_LAYOUT_OPCODE Opcode = BLOCK_LAYOUT_OPERATOR,
unsigned BytePos = 0, unsigned Size = 0) CharUnits BytePos = CharUnits::Zero(),
CharUnits Size = CharUnits::Zero())
: opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {} : opcode(Opcode), block_var_bytepos(BytePos), block_var_size(Size) {}
// Allow sorting based on byte pos. // Allow sorting based on byte pos.
@ -946,16 +947,16 @@ protected:
void UpdateRunSkipBlockVars(bool IsByref, void UpdateRunSkipBlockVars(bool IsByref,
Qualifiers::ObjCLifetime LifeTime, Qualifiers::ObjCLifetime LifeTime,
unsigned FieldOffset, CharUnits FieldOffset,
unsigned FieldSize); CharUnits FieldSize);
void BuildRCBlockVarRecordLayout(const RecordType *RT, void BuildRCBlockVarRecordLayout(const RecordType *RT,
unsigned int BytePos, bool &HasUnion); CharUnits BytePos, bool &HasUnion);
void BuildRCRecordLayout(const llvm::StructLayout *RecLayout, void BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
const RecordDecl *RD, const RecordDecl *RD,
ArrayRef<const FieldDecl*> RecFields, ArrayRef<const FieldDecl*> RecFields,
unsigned int BytePos, bool &HasUnion); CharUnits BytePos, bool &HasUnion);
uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout); uint64_t InlineLayoutInstruction(SmallVectorImpl<unsigned char> &Layout);
@ -1980,40 +1981,37 @@ Qualifiers::ObjCLifetime CGObjCCommonMac::getBlockCaptureLifetime(QualType FQT)
void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref, void CGObjCCommonMac::UpdateRunSkipBlockVars(bool IsByref,
Qualifiers::ObjCLifetime LifeTime, Qualifiers::ObjCLifetime LifeTime,
unsigned FieldOffset, CharUnits FieldOffset,
unsigned FieldSize) { CharUnits FieldSize) {
unsigned ByteSizeInBits = CGM.getContext().getTargetInfo().getCharWidth();
unsigned FieldSizeInBytes = FieldSize/ByteSizeInBits;
// __block variables are passed by their descriptor address. // __block variables are passed by their descriptor address.
if (IsByref) if (IsByref)
RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset, RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_BYREF, FieldOffset,
FieldSizeInBytes)); FieldSize));
else if (LifeTime == Qualifiers::OCL_Strong) else if (LifeTime == Qualifiers::OCL_Strong)
RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset, RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_STRONG, FieldOffset,
FieldSizeInBytes)); FieldSize));
else if (LifeTime == Qualifiers::OCL_Weak) else if (LifeTime == Qualifiers::OCL_Weak)
RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset, RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_WEAK, FieldOffset,
FieldSizeInBytes)); FieldSize));
else if (LifeTime == Qualifiers::OCL_ExplicitNone) else if (LifeTime == Qualifiers::OCL_ExplicitNone)
RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset, RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_UNRETAINED, FieldOffset,
FieldSizeInBytes)); FieldSize));
else else
RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES, RunSkipBlockVars.push_back(RUN_SKIP(BLOCK_LAYOUT_NON_OBJECT_BYTES,
FieldOffset, FieldOffset,
FieldSizeInBytes)); FieldSize));
} }
void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout, void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
const RecordDecl *RD, const RecordDecl *RD,
ArrayRef<const FieldDecl*> RecFields, ArrayRef<const FieldDecl*> RecFields,
unsigned int BytePos, bool &HasUnion) { CharUnits BytePos, bool &HasUnion) {
bool IsUnion = (RD && RD->isUnion()); bool IsUnion = (RD && RD->isUnion());
uint64_t MaxUnionSize = 0; CharUnits MaxUnionSize = CharUnits::Zero();
const FieldDecl *MaxField = 0; const FieldDecl *MaxField = 0;
const FieldDecl *LastFieldBitfieldOrUnnamed = 0; const FieldDecl *LastFieldBitfieldOrUnnamed = 0;
uint64_t MaxFieldOffset = 0; CharUnits MaxFieldOffset = CharUnits::Zero();
uint64_t LastBitfieldOrUnnamedOffset = 0; CharUnits LastBitfieldOrUnnamedOffset = CharUnits::Zero();
if (RecFields.empty()) if (RecFields.empty())
return; return;
@ -2021,11 +2019,11 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
for (unsigned i = 0, e = RecFields.size(); i != e; ++i) { for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
const FieldDecl *Field = RecFields[i]; const FieldDecl *Field = RecFields[i];
uint64_t FieldOffset;
// Note that 'i' here is actually the field index inside RD of Field, // Note that 'i' here is actually the field index inside RD of Field,
// although this dependency is hidden. // although this dependency is hidden.
const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD); const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
FieldOffset = (RL.getFieldOffset(i) / ByteSizeInBits); CharUnits FieldOffset =
CGM.getContext().toCharUnitsFromBits(RL.getFieldOffset(i));
// Skip over unnamed or bitfields // Skip over unnamed or bitfields
if (!Field->getIdentifier() || Field->isBitField()) { if (!Field->getIdentifier() || Field->isBitField()) {
@ -2070,7 +2068,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
// one element is already done. // one element is already done.
uint64_t ElIx = 1; uint64_t ElIx = 1;
for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) { for (int FirstIndex = RunSkipBlockVars.size() - 1 ;ElIx < ElCount; ElIx++) {
uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits; CharUnits Size = CGM.getContext().getTypeSizeInChars(RT);
for (int i = OldIndex+1; i <= FirstIndex; ++i) for (int i = OldIndex+1; i <= FirstIndex; ++i)
RunSkipBlockVars.push_back( RunSkipBlockVars.push_back(
RUN_SKIP(RunSkipBlockVars[i].opcode, RUN_SKIP(RunSkipBlockVars[i].opcode,
@ -2080,9 +2078,9 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
continue; continue;
} }
} }
unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType()); CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field->getType());
if (IsUnion) { if (IsUnion) {
uint64_t UnionIvarSize = FieldSize; CharUnits UnionIvarSize = FieldSize;
if (UnionIvarSize > MaxUnionSize) { if (UnionIvarSize > MaxUnionSize) {
MaxUnionSize = UnionIvarSize; MaxUnionSize = UnionIvarSize;
MaxField = Field; MaxField = Field;
@ -2101,18 +2099,19 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
// Last field was a bitfield. Must update the info. // Last field was a bitfield. Must update the info.
uint64_t BitFieldSize uint64_t BitFieldSize
= LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext()); = LastFieldBitfieldOrUnnamed->getBitWidthValue(CGM.getContext());
unsigned Size = (BitFieldSize / ByteSizeInBits) + unsigned UnsSize = (BitFieldSize / ByteSizeInBits) +
((BitFieldSize % ByteSizeInBits) != 0); ((BitFieldSize % ByteSizeInBits) != 0);
CharUnits Size = CharUnits::fromQuantity(UnsSize);
Size += LastBitfieldOrUnnamedOffset; Size += LastBitfieldOrUnnamedOffset;
UpdateRunSkipBlockVars(false, UpdateRunSkipBlockVars(false,
getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType()), getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType()),
BytePos + LastBitfieldOrUnnamedOffset, BytePos + LastBitfieldOrUnnamedOffset,
Size*ByteSizeInBits); Size);
} else { } else {
assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed"); assert(!LastFieldBitfieldOrUnnamed->getIdentifier() &&"Expected unnamed");
// Last field was unnamed. Must update skip info. // Last field was unnamed. Must update skip info.
unsigned FieldSize CharUnits FieldSize
= CGM.getContext().getTypeSize(LastFieldBitfieldOrUnnamed->getType()); = CGM.getContext().getTypeSizeInChars(LastFieldBitfieldOrUnnamed->getType());
UpdateRunSkipBlockVars(false, UpdateRunSkipBlockVars(false,
getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType()), getBlockCaptureLifetime(LastFieldBitfieldOrUnnamed->getType()),
BytePos + LastBitfieldOrUnnamedOffset, BytePos + LastBitfieldOrUnnamedOffset,
@ -2128,7 +2127,7 @@ void CGObjCCommonMac::BuildRCRecordLayout(const llvm::StructLayout *RecLayout,
} }
void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT, void CGObjCCommonMac::BuildRCBlockVarRecordLayout(const RecordType *RT,
unsigned int BytePos, CharUnits BytePos,
bool &HasUnion) { bool &HasUnion) {
const RecordDecl *RD = RT->getDecl(); const RecordDecl *RD = RT->getDecl();
SmallVector<const FieldDecl*, 16> Fields; SmallVector<const FieldDecl*, 16> Fields;
@ -2281,15 +2280,19 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
// Ignore constant captures. // Ignore constant captures.
if (capture.isConstant()) continue; if (capture.isConstant()) continue;
uint64_t fieldOffset = layout->getElementOffset(capture.getIndex()); CharUnits fieldOffset =
CharUnits::fromQuantity(layout->getElementOffset(capture.getIndex()));
assert(!type->isArrayType() && "array variable should not be caught"); assert(!type->isArrayType() && "array variable should not be caught");
if (const RecordType *record = type->getAs<RecordType>()) { if (const RecordType *record = type->getAs<RecordType>()) {
BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion); BuildRCBlockVarRecordLayout(record, fieldOffset, hasUnion);
continue; continue;
} }
unsigned fieldSize = ci->isByRef() ? WordSizeInBits CharUnits fieldSize;
: CGM.getContext().getTypeSize(type); if (ci->isByRef())
fieldSize = CharUnits::fromQuantity(WordSizeInBytes);
else
fieldSize = CGM.getContext().getTypeSizeInChars(type);
UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type), UpdateRunSkipBlockVars(ci->isByRef(), getBlockCaptureLifetime(type),
fieldOffset, fieldSize); fieldOffset, fieldSize);
} }
@ -2303,12 +2306,10 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
SmallVector<unsigned char, 16> Layout; SmallVector<unsigned char, 16> Layout;
unsigned size = RunSkipBlockVars.size(); unsigned size = RunSkipBlockVars.size();
unsigned int shift = (WordSizeInBytes == 8) ? 3 : 2;
unsigned int mask = (WordSizeInBytes == 8) ? 0x7 : 0x3;
for (unsigned i = 0; i < size; i++) { for (unsigned i = 0; i < size; i++) {
enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode; enum BLOCK_LAYOUT_OPCODE opcode = RunSkipBlockVars[i].opcode;
unsigned start_byte_pos = RunSkipBlockVars[i].block_var_bytepos; CharUnits start_byte_pos = RunSkipBlockVars[i].block_var_bytepos;
unsigned end_byte_pos = start_byte_pos; CharUnits end_byte_pos = start_byte_pos;
unsigned j = i+1; unsigned j = i+1;
while (j < size) { while (j < size) {
if (opcode == RunSkipBlockVars[j].opcode) { if (opcode == RunSkipBlockVars[j].opcode) {
@ -2318,22 +2319,22 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
else else
break; break;
} }
unsigned size_in_bytes = CharUnits size_in_bytes =
end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size; end_byte_pos - start_byte_pos + RunSkipBlockVars[j-1].block_var_size;
if (j < size) { if (j < size) {
unsigned gap = CharUnits gap =
RunSkipBlockVars[j].block_var_bytepos - RunSkipBlockVars[j].block_var_bytepos -
RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size; RunSkipBlockVars[j-1].block_var_bytepos - RunSkipBlockVars[j-1].block_var_size;
size_in_bytes += gap; size_in_bytes += gap;
} }
unsigned residue_in_bytes = 0; CharUnits residue_in_bytes = CharUnits::Zero();
if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) { if (opcode == BLOCK_LAYOUT_NON_OBJECT_BYTES) {
residue_in_bytes = size_in_bytes & mask; residue_in_bytes = size_in_bytes % WordSizeInBytes;
size_in_bytes -= residue_in_bytes; size_in_bytes -= residue_in_bytes;
opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS; opcode = BLOCK_LAYOUT_NON_OBJECT_WORDS;
} }
unsigned size_in_words = size_in_bytes >> shift; unsigned size_in_words = size_in_bytes.getQuantity() / WordSizeInBytes;
while (size_in_words >= 16) { while (size_in_words >= 16) {
// Note that value in imm. is one less that the actual // Note that value in imm. is one less that the actual
// value. So, 0xf means 16 words follow! // value. So, 0xf means 16 words follow!
@ -2347,9 +2348,9 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM,
unsigned char inst = (opcode << 4) | (size_in_words-1); unsigned char inst = (opcode << 4) | (size_in_words-1);
Layout.push_back(inst); Layout.push_back(inst);
} }
if (residue_in_bytes > 0) { if (residue_in_bytes > CharUnits::Zero()) {
unsigned char inst = unsigned char inst =
(BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes-1); (BLOCK_LAYOUT_NON_OBJECT_BYTES << 4) | (residue_in_bytes.getQuantity()-1);
Layout.push_back(inst); Layout.push_back(inst);
} }
} }