diff options
Diffstat (limited to 'clang/lib/CodeGen/CGBlocks.h')
-rw-r--r-- | clang/lib/CodeGen/CGBlocks.h | 61 |
1 files changed, 55 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CGBlocks.h b/clang/lib/CodeGen/CGBlocks.h index c4eed0d0e8e..6be47c55b8e 100644 --- a/clang/lib/CodeGen/CGBlocks.h +++ b/clang/lib/CodeGen/CGBlocks.h @@ -140,6 +140,43 @@ inline BlockFieldFlags operator|(BlockFieldFlag_t l, BlockFieldFlag_t r) { return BlockFieldFlags(l) | BlockFieldFlags(r); } +/// Information about the layout of a __block variable. +class BlockByrefInfo { +public: + llvm::StructType *Type; + unsigned FieldIndex; + CharUnits ByrefAlignment; + CharUnits FieldOffset; +}; + +/// A pair of helper functions for a __block variable. +class BlockByrefHelpers : public llvm::FoldingSetNode { +public: + llvm::Constant *CopyHelper; + llvm::Constant *DisposeHelper; + + /// The alignment of the field. This is important because + /// different offsets to the field within the byref struct need to + /// have different helper functions. + CharUnits Alignment; + + BlockByrefHelpers(CharUnits alignment) : Alignment(alignment) {} + BlockByrefHelpers(const BlockByrefHelpers &) = default; + virtual ~BlockByrefHelpers(); + + void Profile(llvm::FoldingSetNodeID &id) const { + id.AddInteger(Alignment.getQuantity()); + profileImpl(id); + } + virtual void profileImpl(llvm::FoldingSetNodeID &id) const = 0; + + virtual bool needsCopy() const { return true; } + virtual void emitCopy(CodeGenFunction &CGF, Address dest, Address src) = 0; + + virtual bool needsDispose() const { return true; } + virtual void emitDispose(CodeGenFunction &CGF, Address field) = 0; +}; + /// CGBlockInfo - Information to generate a block literal. class CGBlockInfo { public: @@ -152,14 +189,19 @@ public: class Capture { uintptr_t Data; EHScopeStack::stable_iterator Cleanup; + CharUnits::QuantityType Offset; public: bool isIndex() const { return (Data & 1) != 0; } bool isConstant() const { return !isIndex(); } - unsigned getIndex() const { assert(isIndex()); return Data >> 1; } - llvm::Value *getConstant() const { - assert(isConstant()); - return reinterpret_cast<llvm::Value*>(Data); + + unsigned getIndex() const { + assert(isIndex()); + return Data >> 1; + } + CharUnits getOffset() const { + assert(isIndex()); + return CharUnits::fromQuantity(Offset); } EHScopeStack::stable_iterator getCleanup() const { assert(isIndex()); @@ -170,9 +212,15 @@ public: Cleanup = cleanup; } - static Capture makeIndex(unsigned index) { + llvm::Value *getConstant() const { + assert(isConstant()); + return reinterpret_cast<llvm::Value*>(Data); + } + + static Capture makeIndex(unsigned index, CharUnits offset) { Capture v; v.Data = (index << 1) | 1; + v.Offset = offset.getQuantity(); return v; } @@ -205,12 +253,13 @@ public: /// The mapping of allocated indexes within the block. llvm::DenseMap<const VarDecl*, Capture> Captures; - llvm::AllocaInst *Address; + Address LocalAddress; llvm::StructType *StructureType; const BlockDecl *Block; const BlockExpr *BlockExpression; CharUnits BlockSize; CharUnits BlockAlign; + CharUnits CXXThisOffset; // Offset of the gap caused by block header having a smaller // alignment than the alignment of the block descriptor. This |