зеркало из https://github.com/microsoft/clang-1.git
Check in CGRecordLayoutBuilder which is a reimplementation of the record layout code. (Yay, no more packed structs unless absolutely necessary). We currently don't use the layouts being built but that will change when the new code is mature enough :)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76845 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
f1c8380d26
Коммит
45372a6fdc
|
@ -43,6 +43,7 @@
|
||||||
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
|
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
|
||||||
1ADF47AF0F782C3200E48A8A /* SemaTemplateInstantiateDecl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ADF47AE0F782C3200E48A8A /* SemaTemplateInstantiateDecl.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 */; };
|
1AFEF4070F8A6B2300476F2B /* clang-cc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFEF4050F8A6B2300476F2B /* clang-cc.cpp */; };
|
||||||
|
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
|
||||||
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
|
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
|
||||||
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
|
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
|
||||||
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; };
|
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; };
|
||||||
|
@ -368,6 +369,8 @@
|
||||||
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; };
|
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; };
|
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; };
|
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; };
|
||||||
|
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; name = CGRecordLayoutBuilder.cpp; path = lib/CodeGen/CGRecordLayoutBuilder.cpp; sourceTree = "<group>"; tabWidth = 2; };
|
||||||
|
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.c.h; name = CGRecordLayoutBuilder.h; path = lib/CodeGen/CGRecordLayoutBuilder.h; sourceTree = "<group>"; tabWidth = 2; };
|
||||||
3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckObjCInstMethSignature.cpp; path = lib/Analysis/CheckObjCInstMethSignature.cpp; sourceTree = "<group>"; };
|
3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CheckObjCInstMethSignature.cpp; path = lib/Analysis/CheckObjCInstMethSignature.cpp; sourceTree = "<group>"; };
|
||||||
352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLDiagnostics.cpp; path = lib/Frontend/HTMLDiagnostics.cpp; sourceTree = "<group>"; };
|
352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = HTMLDiagnostics.cpp; path = lib/Frontend/HTMLDiagnostics.cpp; sourceTree = "<group>"; };
|
||||||
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitHeaderSearch.cpp; path = lib/Frontend/InitHeaderSearch.cpp; sourceTree = "<group>"; };
|
352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = InitHeaderSearch.cpp; path = lib/Frontend/InitHeaderSearch.cpp; sourceTree = "<group>"; };
|
||||||
|
@ -1110,6 +1113,8 @@
|
||||||
DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */,
|
DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */,
|
||||||
DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */,
|
DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */,
|
||||||
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */,
|
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */,
|
||||||
|
1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */,
|
||||||
|
1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */,
|
||||||
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
|
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
|
||||||
35475B230E7997680000BFE4 /* CGValue.h */,
|
35475B230E7997680000BFE4 /* CGValue.h */,
|
||||||
DE928B800C0A615B00231DA4 /* CodeGenFunction.h */,
|
DE928B800C0A615B00231DA4 /* CodeGenFunction.h */,
|
||||||
|
@ -1697,6 +1702,7 @@
|
||||||
1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
|
1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
|
||||||
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
|
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
|
||||||
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */,
|
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */,
|
||||||
|
1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,272 @@
|
||||||
|
//===--- CGRecordLayoutBuilder.cpp - Record builder helper ------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This is a helper class used to build CGRecordLayout objects and LLVM types.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "CGRecordLayoutBuilder.h"
|
||||||
|
|
||||||
|
#include "clang/AST/ASTContext.h"
|
||||||
|
#include "clang/AST/Attr.h"
|
||||||
|
#include "clang/AST/DeclCXX.h"
|
||||||
|
#include "clang/AST/Expr.h"
|
||||||
|
#include "clang/AST/RecordLayout.h"
|
||||||
|
#include "CodeGenTypes.h"
|
||||||
|
#include "llvm/DerivedTypes.h"
|
||||||
|
#include "llvm/Target/TargetData.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace clang;
|
||||||
|
using namespace CodeGen;
|
||||||
|
|
||||||
|
void CGRecordLayoutBuilder::Layout(const RecordDecl *D) {
|
||||||
|
if (const PackedAttr* PA = D->getAttr<PackedAttr>())
|
||||||
|
StructPacking = PA->getAlignment();
|
||||||
|
|
||||||
|
if (LayoutFields(D))
|
||||||
|
return;
|
||||||
|
|
||||||
|
assert(!StructPacking &&
|
||||||
|
"FIXME: Were not able to lay out a struct with #pragma pack!");
|
||||||
|
|
||||||
|
// We weren't able to layout the struct. Try again with a packed struct
|
||||||
|
StructPacking = 1;
|
||||||
|
AlignmentAsLLVMStruct = 1;
|
||||||
|
FieldTypes.clear();
|
||||||
|
FieldInfos.clear();
|
||||||
|
LLVMFields.clear();
|
||||||
|
LLVMBitFields.clear();
|
||||||
|
|
||||||
|
LayoutFields(D);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGRecordLayoutBuilder::LayoutBitField(const FieldDecl *D,
|
||||||
|
uint64_t FieldOffset) {
|
||||||
|
uint64_t FieldSize =
|
||||||
|
D->getBitWidth()->EvaluateAsInt(Types.getContext()).getZExtValue();
|
||||||
|
|
||||||
|
if (FieldSize == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint64_t NextFieldOffset = getNextFieldOffsetInBytes() * 8;
|
||||||
|
unsigned NumBytesToAppend;
|
||||||
|
|
||||||
|
if (FieldOffset < NextFieldOffset) {
|
||||||
|
assert(BitsAvailableInLastField && "Bitfield size mismatch!");
|
||||||
|
assert(!FieldInfos.empty() && "Field infos can't be empty!");
|
||||||
|
|
||||||
|
// The bitfield begins in the previous bit-field.
|
||||||
|
NumBytesToAppend =
|
||||||
|
llvm::RoundUpToAlignment(FieldSize - BitsAvailableInLastField, 8) / 8;
|
||||||
|
} else {
|
||||||
|
assert(FieldOffset % 8 == 0 && "Field offset not aligned correctly");
|
||||||
|
|
||||||
|
// Append padding if necessary.
|
||||||
|
AppendBytes((FieldOffset - NextFieldOffset) / 8);
|
||||||
|
|
||||||
|
NumBytesToAppend =
|
||||||
|
llvm::RoundUpToAlignment(FieldSize, 8) / 8;
|
||||||
|
|
||||||
|
assert(NumBytesToAppend && "No bytes to append!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
|
||||||
|
uint64_t TypeSizeInBits = getTypeSizeInBytes(Ty) * 8;
|
||||||
|
|
||||||
|
LLVMFields.push_back(LLVMFieldInfo(D, FieldOffset / TypeSizeInBits));
|
||||||
|
LLVMBitFields.push_back(LLVMBitFieldInfo(D, FieldOffset % TypeSizeInBits,
|
||||||
|
FieldSize));
|
||||||
|
|
||||||
|
AppendBytes(NumBytesToAppend);
|
||||||
|
|
||||||
|
if (!NumBytesToAppend)
|
||||||
|
BitsAvailableInLastField -= FieldSize;
|
||||||
|
else
|
||||||
|
BitsAvailableInLastField = NumBytesToAppend * 8 - FieldSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGRecordLayoutBuilder::LayoutField(const FieldDecl *D,
|
||||||
|
uint64_t FieldOffset) {
|
||||||
|
unsigned FieldPacking = StructPacking;
|
||||||
|
|
||||||
|
// FIXME: Should this override struct packing? Probably we want to
|
||||||
|
// take the minimum?
|
||||||
|
if (const PackedAttr *PA = D->getAttr<PackedAttr>())
|
||||||
|
FieldPacking = PA->getAlignment();
|
||||||
|
|
||||||
|
// If the field is packed, then we need a packed struct.
|
||||||
|
if (!StructPacking && FieldPacking)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (D->isBitField()) {
|
||||||
|
// We must use packed structs for unnamed bit fields since they
|
||||||
|
// don't affect the struct alignment.
|
||||||
|
if (!StructPacking && !D->getDeclName())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LayoutBitField(D, FieldOffset);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm::Type *Ty = Types.ConvertTypeForMemRecursive(D->getType());
|
||||||
|
|
||||||
|
// Check if the field is aligned.
|
||||||
|
if (const AlignedAttr *PA = D->getAttr<AlignedAttr>()) {
|
||||||
|
unsigned FieldAlign = PA->getAlignment();
|
||||||
|
|
||||||
|
if (!StructPacking && getTypeAlignment(Ty) > FieldAlign)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(FieldOffset % 8 == 0 && "FieldOffset is not on a byte boundary!");
|
||||||
|
|
||||||
|
uint64_t FieldOffsetInBytes = FieldOffset / 8;
|
||||||
|
|
||||||
|
// Append padding if necessary.
|
||||||
|
AppendPadding(FieldOffsetInBytes, Ty);
|
||||||
|
|
||||||
|
uint64_t FieldSizeInBytes = getTypeSizeInBytes(Ty);
|
||||||
|
|
||||||
|
// Now append the field.
|
||||||
|
LLVMFields.push_back(LLVMFieldInfo(D, FieldTypes.size()));
|
||||||
|
AppendField(FieldOffsetInBytes, FieldSizeInBytes, Ty);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
|
||||||
|
assert(!D->isUnion() && "Can't call LayoutFields on a union!");
|
||||||
|
|
||||||
|
const ASTRecordLayout &Layout =
|
||||||
|
Types.getContext().getASTRecordLayout(D);
|
||||||
|
|
||||||
|
unsigned FieldNo = 0;
|
||||||
|
for (RecordDecl::field_iterator Field = D->field_begin(),
|
||||||
|
FieldEnd = D->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
|
||||||
|
if (!LayoutField(*Field, Layout.getFieldOffset(FieldNo))) {
|
||||||
|
assert(!StructPacking &&
|
||||||
|
"Could not layout fields even with a packed LLVM struct!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append tail padding if necessary.
|
||||||
|
if (Layout.getSize() / 8 > getNextFieldOffsetInBytes())
|
||||||
|
AppendPadding(Layout.getSize() / 8, AlignmentAsLLVMStruct);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGRecordLayoutBuilder::AppendField(uint64_t FieldOffsetInBytes,
|
||||||
|
uint64_t FieldSizeInBytes,
|
||||||
|
const llvm::Type *FieldTy) {
|
||||||
|
AlignmentAsLLVMStruct = std::max(AlignmentAsLLVMStruct,
|
||||||
|
getTypeAlignment(FieldTy));
|
||||||
|
|
||||||
|
FieldTypes.push_back(FieldTy);
|
||||||
|
FieldInfos.push_back(FieldInfo(FieldOffsetInBytes, FieldSizeInBytes));
|
||||||
|
|
||||||
|
BitsAvailableInLastField = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes,
|
||||||
|
const llvm::Type *FieldTy) {
|
||||||
|
AppendPadding(FieldOffsetInBytes, getTypeAlignment(FieldTy));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGRecordLayoutBuilder::AppendPadding(uint64_t FieldOffsetInBytes,
|
||||||
|
unsigned FieldAlignment) {
|
||||||
|
uint64_t NextFieldOffsetInBytes = getNextFieldOffsetInBytes();
|
||||||
|
assert(NextFieldOffsetInBytes <= FieldOffsetInBytes &&
|
||||||
|
"Incorrect field layout!");
|
||||||
|
|
||||||
|
// Round up the field offset to the alignment of the field type.
|
||||||
|
uint64_t AlignedNextFieldOffsetInBytes =
|
||||||
|
llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
|
||||||
|
|
||||||
|
if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
|
||||||
|
// Even with alignment, the field offset is not at the right place,
|
||||||
|
// insert padding.
|
||||||
|
uint64_t PaddingInBytes = FieldOffsetInBytes - NextFieldOffsetInBytes;
|
||||||
|
|
||||||
|
AppendBytes(PaddingInBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGRecordLayoutBuilder::AppendBytes(uint64_t NumBytes) {
|
||||||
|
if (NumBytes == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const llvm::Type *Ty = llvm::Type::Int8Ty;
|
||||||
|
if (NumBytes > 1) {
|
||||||
|
// FIXME: Use a VMContext.
|
||||||
|
Ty = llvm::ArrayType::get(Ty, NumBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append the padding field
|
||||||
|
AppendField(getNextFieldOffsetInBytes(), NumBytes, Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t CGRecordLayoutBuilder::getNextFieldOffsetInBytes() const {
|
||||||
|
if (FieldInfos.empty())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const FieldInfo &LastInfo = FieldInfos.back();
|
||||||
|
return LastInfo.OffsetInBytes + LastInfo.SizeInBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned CGRecordLayoutBuilder::getTypeAlignment(const llvm::Type *Ty) const {
|
||||||
|
if (StructPacking) {
|
||||||
|
assert(StructPacking == 1 && "FIXME: What if StructPacking is not 1 here");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Types.getTargetData().getABITypeAlignment(Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t CGRecordLayoutBuilder::getTypeSizeInBytes(const llvm::Type *Ty) const {
|
||||||
|
return Types.getTargetData().getTypeAllocSize(Ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
CGRecordLayout *
|
||||||
|
CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types,
|
||||||
|
const RecordDecl *D) {
|
||||||
|
CGRecordLayoutBuilder Builder(Types);
|
||||||
|
|
||||||
|
if (D->isUnion())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
Builder.Layout(D);
|
||||||
|
|
||||||
|
// FIXME: Once this works well enough, enable it.
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// FIXME: Use a VMContext.
|
||||||
|
const llvm::Type *Ty = llvm::StructType::get(Builder.FieldTypes,
|
||||||
|
Builder.StructPacking);
|
||||||
|
|
||||||
|
// Add all the field numbers.
|
||||||
|
for (unsigned i = 0, e = Builder.LLVMFields.size(); i != e; ++i) {
|
||||||
|
const FieldDecl *FD = Builder.LLVMFields[i].first;
|
||||||
|
unsigned FieldNo = Builder.LLVMFields[i].second;
|
||||||
|
|
||||||
|
Types.addFieldInfo(FD, FieldNo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add bitfield info.
|
||||||
|
for (unsigned i = 0, e = Builder.LLVMBitFields.size(); i != e; ++i) {
|
||||||
|
const LLVMBitFieldInfo &Info = Builder.LLVMBitFields[i];
|
||||||
|
|
||||||
|
Types.addBitFieldInfo(Info.FD, Info.Start, Info.Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CGRecordLayout(Ty, llvm::SmallSet<unsigned, 8>());
|
||||||
|
}
|
|
@ -0,0 +1,128 @@
|
||||||
|
//===--- CGRecordLayoutBuilder.h - Record builder helper --------*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// The LLVM Compiler Infrastructure
|
||||||
|
//
|
||||||
|
// This file is distributed under the University of Illinois Open Source
|
||||||
|
// License. See LICENSE.TXT for details.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
//
|
||||||
|
// This is a helper class used to build CGRecordLayout objects and LLVM types.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H
|
||||||
|
#define CLANG_CODEGEN_CGRECORDLAYOUTBUILDER_H
|
||||||
|
|
||||||
|
#include "llvm/ADT/SmallVector.h"
|
||||||
|
#include "llvm/Support/DataTypes.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class Type;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace clang {
|
||||||
|
class FieldDecl;
|
||||||
|
class RecordDecl;
|
||||||
|
|
||||||
|
namespace CodeGen {
|
||||||
|
class CGRecordLayout;
|
||||||
|
class CodeGenTypes;
|
||||||
|
|
||||||
|
class CGRecordLayoutBuilder {
|
||||||
|
CodeGenTypes &Types;
|
||||||
|
|
||||||
|
/// StructPacking - Will be 0 if this struct is not packed. If it is packed,
|
||||||
|
/// it will have the packing alignment in bits.
|
||||||
|
///
|
||||||
|
unsigned StructPacking;
|
||||||
|
|
||||||
|
/// AlignmentAsLLVMStruct - Will contain the maximum alignment of all the
|
||||||
|
/// LLVM types.
|
||||||
|
unsigned AlignmentAsLLVMStruct;
|
||||||
|
|
||||||
|
/// BitsAvailableInLastField - If a bit field spans only part of a LLVM field,
|
||||||
|
/// this will have the number of bits still available in the field.
|
||||||
|
char BitsAvailableInLastField;
|
||||||
|
|
||||||
|
/// FieldTypes - Holds the LLVM types that the struct is created from.
|
||||||
|
std::vector<const llvm::Type *> FieldTypes;
|
||||||
|
|
||||||
|
/// FieldInfo - Holds size and offset information about a field.
|
||||||
|
/// FIXME: I think we can get rid of this.
|
||||||
|
struct FieldInfo {
|
||||||
|
FieldInfo(uint64_t OffsetInBytes, uint64_t SizeInBytes)
|
||||||
|
: OffsetInBytes(OffsetInBytes), SizeInBytes(SizeInBytes) { }
|
||||||
|
|
||||||
|
const uint64_t OffsetInBytes;
|
||||||
|
const uint64_t SizeInBytes;
|
||||||
|
};
|
||||||
|
llvm::SmallVector<FieldInfo, 16> FieldInfos;
|
||||||
|
|
||||||
|
/// LLVMFieldInfo - Holds a field and its corresponding LLVM field number.
|
||||||
|
typedef std::pair<const FieldDecl *, unsigned> LLVMFieldInfo;
|
||||||
|
llvm::SmallVector<LLVMFieldInfo, 16> LLVMFields;
|
||||||
|
|
||||||
|
/// LLVMBitFieldInfo - Holds location and size information about a bit field.
|
||||||
|
struct LLVMBitFieldInfo {
|
||||||
|
LLVMBitFieldInfo(const FieldDecl *FD, unsigned Start, unsigned Size)
|
||||||
|
: FD(FD), Start(Start), Size(Size) { }
|
||||||
|
|
||||||
|
const FieldDecl *FD;
|
||||||
|
|
||||||
|
unsigned Start;
|
||||||
|
unsigned Size;
|
||||||
|
};
|
||||||
|
llvm::SmallVector<LLVMBitFieldInfo, 16> LLVMBitFields;
|
||||||
|
|
||||||
|
CGRecordLayoutBuilder(CodeGenTypes &Types)
|
||||||
|
: Types(Types), StructPacking(0), AlignmentAsLLVMStruct(1)
|
||||||
|
, BitsAvailableInLastField(0) { }
|
||||||
|
|
||||||
|
/// Layout - Will layout a RecordDecl.
|
||||||
|
void Layout(const RecordDecl *D);
|
||||||
|
|
||||||
|
/// LayoutField - try to layout all fields in the record decl.
|
||||||
|
/// Returns false if the operation failed because the struct is not packed.
|
||||||
|
bool LayoutFields(const RecordDecl *D);
|
||||||
|
|
||||||
|
/// LayoutField - layout a single field. Returns false if the operation failed
|
||||||
|
/// because the current struct is not packed.
|
||||||
|
bool LayoutField(const FieldDecl *D, uint64_t FieldOffset);
|
||||||
|
|
||||||
|
/// LayoutBitField - layout a single bit field.
|
||||||
|
void LayoutBitField(const FieldDecl *D, uint64_t FieldOffset);
|
||||||
|
|
||||||
|
/// AppendField - Appends a field with the given offset size and type.
|
||||||
|
void AppendField(uint64_t FieldOffsetInBytes, uint64_t FieldSizeInBytes,
|
||||||
|
const llvm::Type *FieldTy);
|
||||||
|
|
||||||
|
/// AppendPadding - Appends enough padding bytes so that the total struct
|
||||||
|
/// size matches the alignment of the passed in type.
|
||||||
|
void AppendPadding(uint64_t FieldOffsetInBytes, const llvm::Type *FieldTy);
|
||||||
|
|
||||||
|
/// AppendPadding - Appends enough padding bytes so that the total
|
||||||
|
/// struct size is a multiple of the field alignment.
|
||||||
|
void AppendPadding(uint64_t FieldOffsetInBytes, unsigned FieldAlignment);
|
||||||
|
|
||||||
|
/// AppendBytes - Append a given number of bytes to the record.
|
||||||
|
void AppendBytes(uint64_t NumBytes);
|
||||||
|
|
||||||
|
/// getNextFieldOffsetInBytes - returns where the next field offset is.
|
||||||
|
uint64_t getNextFieldOffsetInBytes() const;
|
||||||
|
|
||||||
|
unsigned getTypeAlignment(const llvm::Type *Ty) const;
|
||||||
|
uint64_t getTypeSizeInBytes(const llvm::Type *Ty) const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/// ComputeLayout - Return the right record layout for a given record decl.
|
||||||
|
static CGRecordLayout *ComputeLayout(CodeGenTypes &Types,
|
||||||
|
const RecordDecl *D);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // end namespace CodeGen
|
||||||
|
} // end namespace clang
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -21,6 +21,7 @@
|
||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
|
|
||||||
#include "CGCall.h"
|
#include "CGCall.h"
|
||||||
|
#include "CGRecordLayoutBuilder.h"
|
||||||
|
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
using namespace CodeGen;
|
using namespace CodeGen;
|
||||||
|
@ -456,21 +457,30 @@ const llvm::Type *CodeGenTypes::ConvertTagDeclType(const TagDecl *TD) {
|
||||||
ResultType = llvm::StructType::get(std::vector<const llvm::Type*>());
|
ResultType = llvm::StructType::get(std::vector<const llvm::Type*>());
|
||||||
} else {
|
} else {
|
||||||
// Layout fields.
|
// Layout fields.
|
||||||
RecordOrganizer RO(*this, *RD);
|
CGRecordLayout *Layout =
|
||||||
|
CGRecordLayoutBuilder::ComputeLayout(*this, RD);
|
||||||
|
|
||||||
if (TD->isStruct() || TD->isClass())
|
if (!Layout) {
|
||||||
RO.layoutStructFields(Context.getASTRecordLayout(RD));
|
// Layout fields.
|
||||||
else {
|
RecordOrganizer RO(*this, *RD);
|
||||||
assert(TD->isUnion() && "unknown tag decl kind!");
|
|
||||||
RO.layoutUnionFields(Context.getASTRecordLayout(RD));
|
if (TD->isStruct() || TD->isClass())
|
||||||
|
RO.layoutStructFields(Context.getASTRecordLayout(RD));
|
||||||
|
else {
|
||||||
|
assert(TD->isUnion() && "unknown tag decl kind!");
|
||||||
|
RO.layoutUnionFields(Context.getASTRecordLayout(RD));
|
||||||
|
}
|
||||||
|
|
||||||
|
Layout = new CGRecordLayout(RO.getLLVMType(),
|
||||||
|
RO.getPaddingFields());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get llvm::StructType.
|
// Get llvm::StructType.
|
||||||
const Type *Key =
|
const Type *Key =
|
||||||
Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr();
|
Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr();
|
||||||
CGRecordLayouts[Key] = new CGRecordLayout(RO.getLLVMType(),
|
|
||||||
RO.getPaddingFields());
|
CGRecordLayouts[Key] = Layout;
|
||||||
ResultType = RO.getLLVMType();
|
ResultType = Layout->getLLVMType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refine our Opaque type to ResultType. This can invalidate ResultType, so
|
// Refine our Opaque type to ResultType. This can invalidate ResultType, so
|
||||||
|
|
|
@ -52,14 +52,15 @@ namespace CodeGen {
|
||||||
class CGRecordLayout {
|
class CGRecordLayout {
|
||||||
CGRecordLayout(); // DO NOT IMPLEMENT
|
CGRecordLayout(); // DO NOT IMPLEMENT
|
||||||
public:
|
public:
|
||||||
CGRecordLayout(llvm::Type *T, llvm::SmallSet<unsigned, 8> &PF)
|
CGRecordLayout(const llvm::Type *T,
|
||||||
|
const llvm::SmallSet<unsigned, 8> &PF)
|
||||||
: STy(T), PaddingFields(PF) {
|
: STy(T), PaddingFields(PF) {
|
||||||
// FIXME : Collect info about fields that requires adjustments
|
// FIXME : Collect info about fields that requires adjustments
|
||||||
// (i.e. fields that do not directly map to llvm struct fields.)
|
// (i.e. fields that do not directly map to llvm struct fields.)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// getLLVMType - Return llvm type associated with this record.
|
/// getLLVMType - Return llvm type associated with this record.
|
||||||
llvm::Type *getLLVMType() const {
|
const llvm::Type *getLLVMType() const {
|
||||||
return STy;
|
return STy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ namespace CodeGen {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
llvm::Type *STy;
|
const llvm::Type *STy;
|
||||||
llvm::SmallSet<unsigned, 8> PaddingFields;
|
llvm::SmallSet<unsigned, 8> PaddingFields;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче