From: Anders Carlsson Date: Fri, 24 Jul 2009 15:20:52 +0000 (+0000) Subject: Check in a half finished new constant struct builder (Obviously not used yet). X-Git-Tag: llvmorg-2.6.0~2446 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e1d5ca583f6a4c614802f6d40ef5930fff7a459b;p=platform%2Fupstream%2Fllvm.git Check in a half finished new constant struct builder (Obviously not used yet). llvm-svn: 76969 --- diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 61b217bc6661..648dbde3f783 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -16,6 +16,7 @@ #include "CGObjCRuntime.h" #include "clang/AST/APValue.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" #include "clang/AST/StmtVisitor.h" #include "clang/Basic/Builtins.h" #include "llvm/Constants.h" @@ -27,6 +28,149 @@ using namespace clang; using namespace CodeGen; namespace { + +class VISIBILITY_HIDDEN ConstStructBuilder { + CodeGenModule &CGM; + CodeGenFunction *CGF; + + bool Packed; + unsigned NextFieldOffsetInBytes; + + std::vector 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 : public StmtVisitor { CodeGenModule &CGM; @@ -186,6 +330,8 @@ public: } llvm::Constant *EmitStructInitialization(InitListExpr *ILE) { + ConstStructBuilder::BuildStruct(CGM, CGF, ILE); + const llvm::StructType *SType = cast(ConvertType(ILE->getType())); RecordDecl *RD = ILE->getType()->getAsRecordType()->getDecl(); diff --git a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp index 4528fc0a9684..74051383f1dd 100644 --- a/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp +++ b/clang/lib/CodeGen/CGRecordLayoutBuilder.cpp @@ -208,7 +208,7 @@ bool CGRecordLayoutBuilder::LayoutFields(const RecordDecl *D) { // Append tail padding if necessary. if (Layout.getSize() / 8 > getNextFieldOffsetInBytes()) - AppendPadding(Layout.getSize() / 8, AlignmentAsLLVMStruct); + AppendPadding(getNextFieldOffsetInBytes(), AlignmentAsLLVMStruct); return true; } @@ -290,7 +290,7 @@ CGRecordLayoutBuilder::ComputeLayout(CodeGenTypes &Types, CGRecordLayoutBuilder Builder(Types); Builder.Layout(D); - + // FIXME: Once this works well enough, enable it. return 0;