forked from OSchip/llvm-project
Add a new ASTRecordLayoutBuilder class. Not used yet.
llvm-svn: 76330
This commit is contained in:
parent
d476720341
commit
7947433411
|
@ -39,6 +39,7 @@
|
|||
1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; };
|
||||
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
|
||||
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
|
||||
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */; };
|
||||
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
|
||||
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */; };
|
||||
1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */; };
|
||||
|
@ -188,7 +189,6 @@
|
|||
DEB076CF0F3A222200F5A2BE /* DeclTemplate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB076CE0F3A222200F5A2BE /* DeclTemplate.cpp */; };
|
||||
DEB077990F44F97800F5A2BE /* TokenConcatenation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */; };
|
||||
DEB07AC80F4A427E00F5A2BE /* SemaAttr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */; };
|
||||
DEC63B1A0C7B940200DBF169 /* CFG.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DEC63B190C7B940200DBF169 /* CFG.cpp */; };
|
||||
DEC63B1C0C7B940600DBF169 /* CFG.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC63B1B0C7B940600DBF169 /* CFG.h */; };
|
||||
DEC8D9910A9433CD00353FCA /* Decl.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9900A9433CD00353FCA /* Decl.h */; };
|
||||
DEC8D9A40A94346E00353FCA /* AST.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DEC8D9A30A94346E00353FCA /* AST.h */; };
|
||||
|
@ -363,6 +363,8 @@
|
|||
1A7342470C7B57D500122F56 /* CGObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjC.cpp; path = lib/CodeGen/CGObjC.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
|
||||
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
|
||||
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = RecordLayoutBuilder.cpp; path = lib/AST/RecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = RecordLayoutBuilder.h; path = lib/AST/RecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = lib/CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaTemplateInstantiateDecl.cpp; path = lib/Sema/SemaTemplateInstantiateDecl.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = "clang-cc.cpp"; path = "tools/clang-cc/clang-cc.cpp"; sourceTree = "<group>"; tabWidth = 2; };
|
||||
|
@ -603,7 +605,6 @@
|
|||
DEB077980F44F97800F5A2BE /* TokenConcatenation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TokenConcatenation.cpp; sourceTree = "<group>"; };
|
||||
DEB07AC70F4A427E00F5A2BE /* SemaAttr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = SemaAttr.cpp; path = lib/Sema/SemaAttr.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
DEB089EE0F12F1D900522C07 /* TypeTraits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeTraits.h; sourceTree = "<group>"; };
|
||||
DEC63B190C7B940200DBF169 /* CFG.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CFG.cpp; path = lib/AST/CFG.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||
DEC63B1B0C7B940600DBF169 /* CFG.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CFG.h; path = clang/AST/CFG.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
DEC8D9900A9433CD00353FCA /* Decl.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = Decl.h; path = clang/AST/Decl.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
DEC8D9A30A94346E00353FCA /* AST.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = AST.h; path = clang/AST/AST.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||
|
@ -1182,7 +1183,6 @@
|
|||
DE8823CA0ED0046600CBC30A /* APValue.cpp */,
|
||||
35BB2D7E0D19954000944DB5 /* ASTConsumer.cpp */,
|
||||
DE1732FF0B068B700080B521 /* ASTContext.cpp */,
|
||||
DEC63B190C7B940200DBF169 /* CFG.cpp */,
|
||||
35FE6BCE0DF6EE1F00739712 /* DeclBase.cpp */,
|
||||
DED62ABA0AE2EDF1001E80A4 /* Decl.cpp */,
|
||||
3538FDB70ED24A4E005EC283 /* DeclarationName.cpp */,
|
||||
|
@ -1197,6 +1197,8 @@
|
|||
3557D1A80EB136B100C59739 /* InheritViz.cpp */,
|
||||
DEDFE5CE0F7206E40035BD10 /* NestedNameSpecifier.cpp */,
|
||||
35EE48B00E0C4CCA00715C54 /* ParentMap.cpp */,
|
||||
1AA1D91610125DE30078DEBC /* RecordLayoutBuilder.cpp */,
|
||||
1AA1D91710125DE30078DEBC /* RecordLayoutBuilder.h */,
|
||||
DE3452400AEF1A2D00DBC861 /* Stmt.cpp */,
|
||||
DEF2EDA60C6A4252000C4259 /* StmtDumper.cpp */,
|
||||
DE34621C0AFEB19B00DBC861 /* StmtPrinter.cpp */,
|
||||
|
@ -1545,7 +1547,6 @@
|
|||
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */,
|
||||
DE224FF80C7AA98800D370A5 /* CGExprComplex.cpp in Sources */,
|
||||
1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */,
|
||||
DEC63B1A0C7B940200DBF169 /* CFG.cpp in Sources */,
|
||||
DE2252700C7E82D000D370A5 /* CGExprScalar.cpp in Sources */,
|
||||
35260CA50C7F75C000D66CE9 /* ExprCXX.cpp in Sources */,
|
||||
DE2255FC0C8004E600D370A5 /* ParseDeclCXX.cpp in Sources */,
|
||||
|
@ -1695,6 +1696,7 @@
|
|||
BDF87CF70FD746F300BBF872 /* SemaTemplateDeduction.cpp in Sources */,
|
||||
1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
|
||||
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
|
||||
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class FieldDecl;
|
||||
class RecordDecl;
|
||||
|
||||
/// ASTRecordLayout -
|
||||
|
@ -34,6 +35,7 @@ class ASTRecordLayout {
|
|||
unsigned Alignment; // Alignment of record in bits.
|
||||
unsigned FieldCount; // Number of fields
|
||||
friend class ASTContext;
|
||||
friend class ASTRecordLayoutBuilder;
|
||||
|
||||
ASTRecordLayout(uint64_t S = 0, unsigned A = 8)
|
||||
: Size(S), NextOffset(S), Alignment(A), FieldCount(0) {}
|
||||
|
@ -41,6 +43,16 @@ class ASTRecordLayout {
|
|||
delete [] FieldOffsets;
|
||||
}
|
||||
|
||||
ASTRecordLayout(uint64_t Size, unsigned Alignment,
|
||||
const uint64_t *fieldoffsets, unsigned fieldcount)
|
||||
: Size(Size), FieldOffsets(0), Alignment(Alignment), FieldCount(fieldcount) {
|
||||
if (FieldCount > 0) {
|
||||
FieldOffsets = new uint64_t[FieldCount];
|
||||
for (unsigned i = 0; i < FieldCount; ++i)
|
||||
FieldOffsets[i] = fieldoffsets[i];
|
||||
}
|
||||
}
|
||||
|
||||
/// Initialize record layout. N is the number of fields in this record.
|
||||
void InitializeLayout(unsigned N) {
|
||||
FieldCount = N;
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
//=== ASTRecordLayoutBuilder.cpp - Helper class for building record layouts ==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "RecordLayoutBuilder.h"
|
||||
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include <llvm/Support/MathExtras.h>
|
||||
|
||||
using namespace clang;
|
||||
|
||||
ASTRecordLayoutBuilder::ASTRecordLayoutBuilder(ASTContext &Ctx)
|
||||
: Ctx(Ctx), Size(0), Alignment(8), StructPacking(0), NextOffset(0),
|
||||
IsUnion(false) {}
|
||||
|
||||
void ASTRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
||||
IsUnion = D->isUnion();
|
||||
|
||||
if (const PackedAttr* PA = D->getAttr<PackedAttr>())
|
||||
StructPacking = PA->getAlignment();
|
||||
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
UpdateAlignment(AA->getAlignment());
|
||||
|
||||
// Layout each field, for now, just sequentially, respecting alignment. In
|
||||
// the future, this will need to be tweakable by targets.
|
||||
for (RecordDecl::field_iterator Field = D->field_begin(),
|
||||
FieldEnd = D->field_end(); Field != FieldEnd; ++Field)
|
||||
LayoutField(*Field);
|
||||
|
||||
// Finally, round the size of the total struct up to the alignment of the
|
||||
// struct itself.
|
||||
FinishLayout();
|
||||
}
|
||||
|
||||
void ASTRecordLayoutBuilder::LayoutField(const FieldDecl *D) {
|
||||
unsigned FieldPacking = StructPacking;
|
||||
uint64_t FieldOffset = IsUnion ? 0 : Size;
|
||||
uint64_t FieldSize;
|
||||
unsigned FieldAlign;
|
||||
|
||||
// FIXME: Should this override struct packing? Probably we want to
|
||||
// take the minimum?
|
||||
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
|
||||
FieldPacking = PA->getAlignment();
|
||||
|
||||
if (const Expr *BitWidthExpr = D->getBitWidth()) {
|
||||
// TODO: Need to check this algorithm on other targets!
|
||||
// (tested on Linux-X86)
|
||||
FieldSize = BitWidthExpr->EvaluateAsInt(Ctx).getZExtValue();
|
||||
|
||||
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
|
||||
uint64_t TypeSize = FieldInfo.first;
|
||||
|
||||
// Determine the alignment of this bitfield. The packing
|
||||
// attributes define a maximum and the alignment attribute defines
|
||||
// a minimum.
|
||||
// FIXME: What is the right behavior when the specified alignment
|
||||
// is smaller than the specified packing?
|
||||
FieldAlign = FieldInfo.second;
|
||||
if (FieldPacking)
|
||||
FieldAlign = std::min(FieldAlign, FieldPacking);
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
FieldAlign = std::max(FieldAlign, AA->getAlignment());
|
||||
|
||||
// Check if we need to add padding to give the field the correct
|
||||
// alignment.
|
||||
if (FieldSize == 0 || (FieldOffset & (FieldAlign-1)) + FieldSize > TypeSize)
|
||||
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
|
||||
|
||||
// Padding members don't affect overall alignment
|
||||
if (!D->getIdentifier())
|
||||
FieldAlign = 1;
|
||||
} else {
|
||||
if (D->getType()->isIncompleteArrayType()) {
|
||||
// This is a flexible array member; we can't directly
|
||||
// query getTypeInfo about these, so we figure it out here.
|
||||
// Flexible array members don't have any size, but they
|
||||
// have to be aligned appropriately for their element type.
|
||||
FieldSize = 0;
|
||||
const ArrayType* ATy = Ctx.getAsArrayType(D->getType());
|
||||
FieldAlign = Ctx.getTypeAlign(ATy->getElementType());
|
||||
} else if (const ReferenceType *RT = D->getType()->getAsReferenceType()) {
|
||||
unsigned AS = RT->getPointeeType().getAddressSpace();
|
||||
FieldSize = Ctx.Target.getPointerWidth(AS);
|
||||
FieldAlign = Ctx.Target.getPointerAlign(AS);
|
||||
} else {
|
||||
std::pair<uint64_t, unsigned> FieldInfo = Ctx.getTypeInfo(D->getType());
|
||||
FieldSize = FieldInfo.first;
|
||||
FieldAlign = FieldInfo.second;
|
||||
}
|
||||
|
||||
// Determine the alignment of this bitfield. The packing
|
||||
// attributes define a maximum and the alignment attribute defines
|
||||
// a minimum. Additionally, the packing alignment must be at least
|
||||
// a byte for non-bitfields.
|
||||
//
|
||||
// FIXME: What is the right behavior when the specified alignment
|
||||
// is smaller than the specified packing?
|
||||
if (FieldPacking)
|
||||
FieldAlign = std::min(FieldAlign, std::max(8U, FieldPacking));
|
||||
if (const AlignedAttr *AA = D->getAttr<AlignedAttr>())
|
||||
FieldAlign = std::max(FieldAlign, AA->getAlignment());
|
||||
|
||||
// Round up the current record size to the field's alignment boundary.
|
||||
FieldOffset = (FieldOffset + (FieldAlign-1)) & ~(FieldAlign-1);
|
||||
}
|
||||
|
||||
// Place this field at the current location.
|
||||
FieldOffsets.push_back(FieldOffset);
|
||||
|
||||
// Reserve space for this field.
|
||||
if (IsUnion)
|
||||
Size = std::max(Size, FieldSize);
|
||||
else
|
||||
Size = FieldOffset + FieldSize;
|
||||
|
||||
// Remember the next available offset.
|
||||
NextOffset = Size;
|
||||
|
||||
// Remember max struct/class alignment.
|
||||
UpdateAlignment(FieldAlign);
|
||||
}
|
||||
|
||||
void ASTRecordLayoutBuilder::FinishLayout() {
|
||||
// In C++, records cannot be of size 0.
|
||||
if (Ctx.getLangOptions().CPlusPlus && Size == 0)
|
||||
Size = 8;
|
||||
// Finally, round the size of the record up to the alignment of the
|
||||
// record itself.
|
||||
Size = (Size + (Alignment-1)) & ~(Alignment-1);
|
||||
}
|
||||
|
||||
void ASTRecordLayoutBuilder::UpdateAlignment(unsigned NewAlignment) {
|
||||
if (NewAlignment <= Alignment)
|
||||
return;
|
||||
|
||||
assert(llvm::isPowerOf2_32(NewAlignment && "Alignment not a power of 2"));
|
||||
|
||||
Alignment = NewAlignment;
|
||||
}
|
||||
|
||||
const ASTRecordLayout *
|
||||
ASTRecordLayoutBuilder::ComputeLayout(ASTContext &Ctx,
|
||||
const RecordDecl *D) {
|
||||
ASTRecordLayoutBuilder Builder(Ctx);
|
||||
|
||||
Builder.Layout(D);
|
||||
|
||||
return new ASTRecordLayout(Builder.Size, Builder.Alignment,
|
||||
Builder.FieldOffsets.data(),
|
||||
Builder.FieldOffsets.size());
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
//===- ASTRecordLayoutBuilder.h - Helper class for building record layouts ===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
|
||||
#define LLVM_CLANG_AST_RECORDLAYOUTBUILDER_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class ASTRecordLayout;
|
||||
class FieldDecl;
|
||||
class RecordDecl;
|
||||
|
||||
class ASTRecordLayoutBuilder {
|
||||
ASTContext &Ctx;
|
||||
|
||||
uint64_t Size;
|
||||
uint64_t Alignment;
|
||||
llvm::SmallVector<uint64_t, 16> FieldOffsets;
|
||||
|
||||
unsigned StructPacking;
|
||||
unsigned NextOffset;
|
||||
bool IsUnion;
|
||||
|
||||
ASTRecordLayoutBuilder(ASTContext &Ctx);
|
||||
|
||||
void Layout(const RecordDecl *D);
|
||||
void LayoutField(const FieldDecl *D);
|
||||
void FinishLayout();
|
||||
|
||||
void UpdateAlignment(unsigned NewAlignment);
|
||||
|
||||
ASTRecordLayoutBuilder(const ASTRecordLayoutBuilder&); // DO NOT IMPLEMENT
|
||||
void operator=(const ASTRecordLayoutBuilder&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
static const ASTRecordLayout *ComputeLayout(ASTContext &Ctx,
|
||||
const RecordDecl *RD);
|
||||
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue