Check in a half finished new constant struct builder (Obviously not used yet).

llvm-svn: 76969
This commit is contained in:
Anders Carlsson 2009-07-24 15:20:52 +00:00
parent 555d1001d5
commit e1d5ca583f
2 changed files with 148 additions and 2 deletions

View File

@ -16,6 +16,7 @@
#include "CGObjCRuntime.h" #include "CGObjCRuntime.h"
#include "clang/AST/APValue.h" #include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h" #include "clang/AST/ASTContext.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h" #include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h" #include "clang/Basic/Builtins.h"
#include "llvm/Constants.h" #include "llvm/Constants.h"
@ -27,6 +28,149 @@ using namespace clang;
using namespace CodeGen; using namespace CodeGen;
namespace { namespace {
class VISIBILITY_HIDDEN ConstStructBuilder {
CodeGenModule &CGM;
CodeGenFunction *CGF;
bool Packed;
unsigned NextFieldOffsetInBytes;
std::vector<llvm::Constant *> Elements;
ConstStructBuilder(CodeGenModule &CGM, CodeGenFunction *CGF)
: CGM(CGM), CGF(CGF), Packed(false), NextFieldOffsetInBytes(0) { }
bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
const Expr *InitExpr) {
uint64_t FieldOffsetInBytes = FieldOffset / 8;
assert(NextFieldOffsetInBytes <= FieldOffsetInBytes
&& "Field offset mismatch!");
// Emit the field.
llvm::Constant *C = CGM.EmitConstantExpr(InitExpr, Field->getType(), CGF);
if (!C)
return false;
unsigned FieldAlignment = getAlignment(C);
// Round up the field offset to the alignment of the field type.
uint64_t AlignedNextFieldOffsetInBytes =
llvm::RoundUpToAlignment(NextFieldOffsetInBytes, FieldAlignment);
if (AlignedNextFieldOffsetInBytes > FieldOffsetInBytes) {
// FIXME: Must convert the struct to a packed struct.
return false;
}
if (AlignedNextFieldOffsetInBytes < FieldOffsetInBytes) {
// We need to append padding.
AppendPadding(FieldOffsetInBytes - AlignedNextFieldOffsetInBytes);
assert(NextFieldOffsetInBytes == FieldOffsetInBytes &&
"Did not add enough padding!");
AlignedNextFieldOffsetInBytes = NextFieldOffsetInBytes;
}
// Add the field.
Elements.push_back(C);
NextFieldOffsetInBytes = AlignedNextFieldOffsetInBytes + getSizeInBytes(C);
return true;
}
void AppendPadding(uint64_t NumBytes) {
if (!NumBytes)
return;
const llvm::Type *Ty = llvm::Type::Int8Ty;
if (NumBytes > 1)
Ty = CGM.getLLVMContext().getArrayType(Ty, NumBytes);
llvm::Constant *C = CGM.getLLVMContext().getNullValue(Ty);
Elements.push_back(C);
assert(getAlignment(C) == 1 && "Padding must have 1 byte alignment!");
NextFieldOffsetInBytes += getSizeInBytes(C);
}
void AppendTailPadding(uint64_t RecordSize) {
assert(RecordSize % 8 == 0 && "Invalid record size!");
uint64_t RecordSizeInBytes = RecordSize / 8;
assert(NextFieldOffsetInBytes <= RecordSizeInBytes && "Size mismatch!");
unsigned NumPadBytes = RecordSizeInBytes - NextFieldOffsetInBytes;
AppendPadding(NumPadBytes);
}
bool Build(const InitListExpr *ILE) {
RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();
const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
unsigned FieldNo = 0;
unsigned ElementNo = 0;
for (RecordDecl::field_iterator Field = RD->field_begin(),
FieldEnd = RD->field_end();
ElementNo < ILE->getNumInits() && Field != FieldEnd;
++Field, ++FieldNo) {
if (Field->isBitField()) {
if (!Field->getIdentifier())
continue;
// FIXME: Bitfield support.
return false;
} else {
if (!AppendField(*Field, Layout.getFieldOffset(FieldNo),
ILE->getInit(ElementNo)))
return false;
}
ElementNo++;
}
// Append tail padding if necessary.
AppendTailPadding(Layout.getSize());
assert(Layout.getSize() / 8 == NextFieldOffsetInBytes &&
"Tail padding mismatch!");
return true;
}
unsigned getAlignment(const llvm::Constant *C) const {
if (Packed)
return 1;
return CGM.getTargetData().getABITypeAlignment(C->getType());
}
uint64_t getSizeInBytes(const llvm::Constant *C) const {
return CGM.getTargetData().getTypeAllocSize(C->getType());
}
public:
static llvm::Constant *BuildStruct(CodeGenModule &CGM, CodeGenFunction *CGF,
const InitListExpr *ILE) {
ConstStructBuilder Builder(CGM, CGF);
// FIXME: Use this when it works well enough.
return 0;
if (!Builder.Build(ILE))
return 0;
llvm::Constant *Result =
CGM.getLLVMContext().getConstantStruct(Builder.Elements, Builder.Packed);
assert(Builder.NextFieldOffsetInBytes == Builder.getSizeInBytes(Result));
return 0;
}
};
class VISIBILITY_HIDDEN ConstExprEmitter : class VISIBILITY_HIDDEN ConstExprEmitter :
public StmtVisitor<ConstExprEmitter, llvm::Constant*> { public StmtVisitor<ConstExprEmitter, llvm::Constant*> {
CodeGenModule &CGM; CodeGenModule &CGM;
@ -186,6 +330,8 @@ public:
} }
llvm::Constant *EmitStructInitialization(InitListExpr *ILE) { llvm::Constant *EmitStructInitialization(InitListExpr *ILE) {
ConstStructBuilder::BuildStruct(CGM, CGF, ILE);
const llvm::StructType *SType = const llvm::StructType *SType =
cast<llvm::StructType>(ConvertType(ILE->getType())); cast<llvm::StructType>(ConvertType(ILE->getType()));
RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl();

View File

@ -208,7 +208,7 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) {
// Append tail padding if necessary. // Append tail padding if necessary.
if (Layout.getSize() / 8 > getNextFieldOffsetInBytes()) if (Layout.getSize() / 8 > getNextFieldOffsetInBytes())
AppendPadding(Layout.getSize() / 8, AlignmentAsLLVMStruct); AppendPadding(getNextFieldOffsetInBytes(), AlignmentAsLLVMStruct);
return true; return true;
} }