diff options
| author | Fariborz Jahanian <fjahanian@apple.com> | 2012-12-04 17:20:57 +0000 |
|---|---|---|
| committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-12-04 17:20:57 +0000 |
| commit | 4cf177e238bea0d79d98a7d18e70ab07a6f07525 (patch) | |
| tree | fad6306c6bb05a78dad418bab4bf50d3a852e2d4 /clang/lib/CodeGen | |
| parent | 22d61dd4ce15e953ede25981ec65a79f98cc728b (diff) | |
| download | bcm5719-llvm-4cf177e238bea0d79d98a7d18e70ab07a6f07525.tar.gz bcm5719-llvm-4cf177e238bea0d79d98a7d18e70ab07a6f07525.zip | |
objective-c blocks: Consider padding due to alignment
after the fixed size block header when generating
captured block variable info. // rdar://12773256
llvm-svn: 169285
Diffstat (limited to 'clang/lib/CodeGen')
| -rw-r--r-- | clang/lib/CodeGen/CGBlocks.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGBlocks.h | 8 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGObjCMac.cpp | 5 |
3 files changed, 25 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index 1d8b326d207..d181da2de66 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -428,7 +428,11 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, // to get reproducible results. There should probably be an // llvm::array_pod_stable_sort. std::stable_sort(layout.begin(), layout.end()); - + + // Needed for blocks layout info. + info.BlockHeaderForcedGapOffset = info.BlockSize; + info.BlockHeaderForcedGapSize = CharUnits::Zero(); + CharUnits &blockSize = info.BlockSize; info.BlockAlign = std::max(maxFieldAlign, info.BlockAlign); @@ -469,17 +473,22 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, endAlign = getLowBit(blockSize); // ...until we get to the alignment of the maximum field. - if (endAlign >= maxFieldAlign) + if (endAlign >= maxFieldAlign) { + if (li == first) { + // No user field was appended. So, a gap was added. + // Save total gap size for use in block layout bit map. + info.BlockHeaderForcedGapSize = li->Size; + } break; + } } - // Don't re-append everything we just appended. layout.erase(first, li); } } assert(endAlign == getLowBit(blockSize)); - + // At this point, we just have to add padding if the end align still // isn't aligned right. if (endAlign < maxFieldAlign) { @@ -494,7 +503,6 @@ static void computeBlockInfo(CodeGenModule &CGM, CodeGenFunction *CGF, assert(endAlign >= maxFieldAlign); assert(endAlign == getLowBit(blockSize)); - // Slam everything else on now. This works because they have // strictly decreasing alignment and we expect that size is always a // multiple of alignment. diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index e63d4b6b1f0..0e40478fad7 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -211,6 +211,14 @@ public: const BlockExpr *BlockExpression; CharUnits BlockSize; CharUnits BlockAlign; + + // Offset of the gap caused by block header having a smaller + // alignment than the alignment of the block descriptor. This + // is the gap offset before the first capturued field. + CharUnits BlockHeaderForcedGapOffset; + // Gap size caused by aligning first field after block header. + // This could be zero if no forced alignment is required. + CharUnits BlockHeaderForcedGapSize; /// An instruction which dominates the full-expression that the /// block is inside. diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index f4b42bb9b7d..d84875bfd51 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -2424,7 +2424,10 @@ llvm::Constant *CGObjCCommonMac::BuildRCBlockLayout(CodeGenModule &CGM, // Ignore the optional 'this' capture: C++ objects are not assumed // to be GC'ed. - + if (blockInfo.BlockHeaderForcedGapSize != CharUnits::Zero()) + UpdateRunSkipBlockVars(false, Qualifiers::OCL_None, + blockInfo.BlockHeaderForcedGapOffset, + blockInfo.BlockHeaderForcedGapSize); // Walk the captured variables. for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), ce = blockDecl->capture_end(); ci != ce; ++ci) { |

