forked from OSchip/llvm-project
parent
7a9c47480d
commit
ad175428c6
|
@ -32,26 +32,29 @@ namespace {
|
||||||
/// - Ignore packed structs
|
/// - Ignore packed structs
|
||||||
class RecordOrganizer {
|
class RecordOrganizer {
|
||||||
public:
|
public:
|
||||||
RecordOrganizer() : STy(NULL), FieldNo(0), Cursor(0) {}
|
explicit RecordOrganizer(CodeGenTypes &Types) :
|
||||||
|
CGT(Types), STy(NULL), FieldNo(0), Cursor(0) {}
|
||||||
|
|
||||||
/// addField - Add new field.
|
/// addField - Add new field.
|
||||||
void addField(const FieldDecl *FD);
|
void addField(const FieldDecl *FD);
|
||||||
|
|
||||||
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty. Update
|
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty. Update
|
||||||
/// cursor and increment field count.
|
/// cursor and increment field count.
|
||||||
void addLLVMField(const llvm::Type *Ty, CodeGenTypes &CGT,
|
void addLLVMField(const llvm::Type *Ty, const FieldDecl *FD = NULL);
|
||||||
const FieldDecl *FD = NULL);
|
|
||||||
|
|
||||||
|
/// addPaddingFields - Current cursor is not suitable place to add next field.
|
||||||
|
/// Add required padding fields.
|
||||||
|
void addPaddingFields(unsigned RequiredBits);
|
||||||
|
|
||||||
/// layoutStructFields - Do the actual work and lay out all fields. Create
|
/// layoutStructFields - Do the actual work and lay out all fields. Create
|
||||||
/// corresponding llvm struct type. This should be invoked only after
|
/// corresponding llvm struct type. This should be invoked only after
|
||||||
/// all fields are added.
|
/// all fields are added.
|
||||||
void layoutStructFields(CodeGenTypes &CGT, const RecordLayout &RL);
|
void layoutStructFields(const RecordLayout &RL);
|
||||||
|
|
||||||
/// layoutUnionFields - Do the actual work and lay out all fields. Create
|
/// layoutUnionFields - Do the actual work and lay out all fields. Create
|
||||||
/// corresponding llvm struct type. This should be invoked only after
|
/// corresponding llvm struct type. This should be invoked only after
|
||||||
/// all fields are added.
|
/// all fields are added.
|
||||||
void layoutUnionFields(CodeGenTypes &CGT);
|
void layoutUnionFields();
|
||||||
|
|
||||||
/// getLLVMType - Return associated llvm struct type. This may be NULL
|
/// getLLVMType - Return associated llvm struct type. This may be NULL
|
||||||
/// if fields are not laid out.
|
/// if fields are not laid out.
|
||||||
|
@ -62,6 +65,7 @@ namespace {
|
||||||
/// Clear private data so that this object can be reused.
|
/// Clear private data so that this object can be reused.
|
||||||
void clear();
|
void clear();
|
||||||
private:
|
private:
|
||||||
|
CodeGenTypes &CGT;
|
||||||
llvm::Type *STy;
|
llvm::Type *STy;
|
||||||
unsigned FieldNo;
|
unsigned FieldNo;
|
||||||
uint64_t Cursor;
|
uint64_t Cursor;
|
||||||
|
@ -253,11 +257,11 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
||||||
llvm::PATypeHolder(OpaqueTy)));
|
llvm::PATypeHolder(OpaqueTy)));
|
||||||
|
|
||||||
// Layout fields.
|
// Layout fields.
|
||||||
RecordOrganizer RO;
|
RecordOrganizer RO(*this);
|
||||||
for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
|
for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
|
||||||
RO.addField(RD->getMember(i));
|
RO.addField(RD->getMember(i));
|
||||||
const RecordLayout &RL = Context.getRecordLayout(RD, SourceLocation());
|
const RecordLayout &RL = Context.getRecordLayout(RD, SourceLocation());
|
||||||
RO.layoutStructFields(*this, RL);
|
RO.layoutStructFields(RL);
|
||||||
|
|
||||||
// Get llvm::StructType.
|
// Get llvm::StructType.
|
||||||
RecordLayoutInfo *RLI = new RecordLayoutInfo(RO.getLLVMType());
|
RecordLayoutInfo *RLI = new RecordLayoutInfo(RO.getLLVMType());
|
||||||
|
@ -278,10 +282,10 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
|
||||||
// highest aligned member.
|
// highest aligned member.
|
||||||
|
|
||||||
if (RD->getNumMembers() != 0) {
|
if (RD->getNumMembers() != 0) {
|
||||||
RecordOrganizer RO;
|
RecordOrganizer RO(*this);
|
||||||
for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
|
for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i)
|
||||||
RO.addField(RD->getMember(i));
|
RO.addField(RD->getMember(i));
|
||||||
RO.layoutUnionFields(*this);
|
RO.layoutUnionFields();
|
||||||
|
|
||||||
// Get llvm::StructType.
|
// Get llvm::StructType.
|
||||||
RecordLayoutInfo *RLI = new RecordLayoutInfo(RO.getLLVMType());
|
RecordLayoutInfo *RLI = new RecordLayoutInfo(RO.getLLVMType());
|
||||||
|
@ -364,10 +368,9 @@ void RecordOrganizer::addField(const FieldDecl *FD) {
|
||||||
/// - Ignore bit fields
|
/// - Ignore bit fields
|
||||||
/// - Ignore field aligments
|
/// - Ignore field aligments
|
||||||
/// - Ignore packed structs
|
/// - Ignore packed structs
|
||||||
void RecordOrganizer::layoutStructFields(CodeGenTypes &CGT,
|
void RecordOrganizer::layoutStructFields(const RecordLayout &RL) {
|
||||||
const RecordLayout &RL) {
|
|
||||||
// FIXME : Use SmallVector
|
// FIXME : Use SmallVector
|
||||||
uint64_t Cursor = 0;
|
Cursor = 0;
|
||||||
FieldNo = 0;
|
FieldNo = 0;
|
||||||
LLVMFields.clear();
|
LLVMFields.clear();
|
||||||
for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(),
|
for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(),
|
||||||
|
@ -375,22 +378,32 @@ void RecordOrganizer::layoutStructFields(CodeGenTypes &CGT,
|
||||||
const FieldDecl *FD = *I;
|
const FieldDecl *FD = *I;
|
||||||
const llvm::Type *Ty = CGT.ConvertType(FD->getType());
|
const llvm::Type *Ty = CGT.ConvertType(FD->getType());
|
||||||
|
|
||||||
uint64_t Offset = RL.getFieldOffset(FieldNo);
|
|
||||||
unsigned AlignmentInBits = CGT.getTargetData().getABITypeAlignment(Ty) * 8;
|
unsigned AlignmentInBits = CGT.getTargetData().getABITypeAlignment(Ty) * 8;
|
||||||
if (Cursor % AlignmentInBits != 0)
|
if (Cursor % AlignmentInBits != 0)
|
||||||
assert (Offset == Cursor && "FIXME Invalid struct layout");
|
// At the moment, insert padding fields even if target specific llvm
|
||||||
|
// type alignment enforces implict padding fields for FD. Later on,
|
||||||
|
// optimize llvm fields by removing implicit padding fields and
|
||||||
|
// combining consequetive padding fields.
|
||||||
|
addPaddingFields(Cursor % AlignmentInBits);
|
||||||
|
|
||||||
addLLVMField(Ty, CGT, FD);
|
addLLVMField(Ty, FD);
|
||||||
}
|
}
|
||||||
STy = llvm::StructType::get(LLVMFields);
|
STy = llvm::StructType::get(LLVMFields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// addPaddingFields - Current cursor is not suitable place to add next field.
|
||||||
|
/// Add required padding fields.
|
||||||
|
void RecordOrganizer::addPaddingFields(unsigned RequiredBits) {
|
||||||
|
assert ((RequiredBits % 8) == 0 && "FIXME Invalid struct layout");
|
||||||
|
unsigned RequiredBytes = RequiredBits / 8;
|
||||||
|
for (unsigned i = 0; i != RequiredBytes; ++i)
|
||||||
|
addLLVMField(llvm::Type::Int8Ty);
|
||||||
|
}
|
||||||
|
|
||||||
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty. Update
|
/// addLLVMField - Add llvm struct field that corresponds to llvm type Ty. Update
|
||||||
/// cursor and increment field count. If field decl FD is available than update
|
/// cursor and increment field count. If field decl FD is available than update
|
||||||
/// update field info at CodeGenTypes level.
|
/// update field info at CodeGenTypes level.
|
||||||
void RecordOrganizer::addLLVMField(const llvm::Type *Ty,
|
void RecordOrganizer::addLLVMField(const llvm::Type *Ty, const FieldDecl *FD) {
|
||||||
CodeGenTypes &CGT,
|
|
||||||
const FieldDecl *FD) {
|
|
||||||
Cursor += CGT.getTargetData().getTypeSizeInBits(Ty);
|
Cursor += CGT.getTargetData().getTypeSizeInBits(Ty);
|
||||||
LLVMFields.push_back(Ty);
|
LLVMFields.push_back(Ty);
|
||||||
if (FD)
|
if (FD)
|
||||||
|
@ -401,7 +414,7 @@ void RecordOrganizer::addLLVMField(const llvm::Type *Ty,
|
||||||
/// layoutUnionFields - Do the actual work and lay out all fields. Create
|
/// layoutUnionFields - Do the actual work and lay out all fields. Create
|
||||||
/// corresponding llvm struct type. This should be invoked only after
|
/// corresponding llvm struct type. This should be invoked only after
|
||||||
/// all fields are added.
|
/// all fields are added.
|
||||||
void RecordOrganizer::layoutUnionFields(CodeGenTypes &CGT) {
|
void RecordOrganizer::layoutUnionFields() {
|
||||||
|
|
||||||
unsigned PrimaryEltNo = 0;
|
unsigned PrimaryEltNo = 0;
|
||||||
std::pair<uint64_t, unsigned> PrimaryElt =
|
std::pair<uint64_t, unsigned> PrimaryElt =
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
// RUN: clang %s -emit-llvm | grep "STest1 = type { i32, \[4 x i16\], double }"
|
// RUN: clang %s -emit-llvm > %t1
|
||||||
|
// RUN grep "STest1 = type { i32, \[4 x i16\], double }" %t1
|
||||||
|
// RUN: grep "STest2 = type { i16, i16, i32, i32 }" %t1
|
||||||
|
// RUN: grep "STest3 = type { i8, i8, i16, i32 }" %t1
|
||||||
// Test struct layout for x86-darwin target
|
// Test struct layout for x86-darwin target
|
||||||
// FIXME : Enable this test for x86-darwin only. At the moment clang hard codes
|
// FIXME : Enable this test for x86-darwin only. At the moment clang hard codes
|
||||||
// x86-darwin as the target
|
// x86-darwin as the target
|
||||||
|
|
||||||
struct STest1 {int x; short y[4]; double z; } st1;
|
struct STest1 {int x; short y[4]; double z; } st1;
|
||||||
|
struct STest2 {short a,b; int c,d; } st2;
|
||||||
|
struct STest3 {char a; short b; int c; } st3;
|
||||||
|
|
||||||
|
// Bitfields struct STestB1 {int a:1; char b; int c:13 } stb1;
|
||||||
|
// Packed struct STestP1 {char a; short b; int c; } __attribute__((__packed__)) stp1;
|
||||||
|
|
Loading…
Reference in New Issue