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 */; };
+ 1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */; };
3507E4C20E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3507E4C10E27FE2D00FB7B57 /* CheckObjCInstMethSignature.cpp */; };
352246E70F5C6BE000D0D279 /* HTMLDiagnostics.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E10F5C6BE000D0D279 /* HTMLDiagnostics.cpp */; };
352246E80F5C6BE000D0D279 /* InitHeaderSearch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 352246E20F5C6BE000D0D279 /* InitHeaderSearch.cpp */; };
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; };
+ 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>"; };
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>"; };
DE38CD4E0D794CF900A273B6 /* CGObjCRuntime.h */,
DE38CD4F0D794D0100A273B6 /* CGObjCGNU.cpp */,
3552E7580E520DD7003A8CA5 /* CGObjCMac.cpp */,
+ 1AFF8AE11012BFC900D248DA /* CGRecordLayoutBuilder.cpp */,
+ 1AFF8AE21012BFC900D248DA /* CGRecordLayoutBuilder.h */,
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
35475B230E7997680000BFE4 /* CGValue.h */,
DE928B800C0A615B00231DA4 /* CodeGenFunction.h */,
1A14D3A70FD78A3F00DA2835 /* DeclPrinter.cpp in Sources */,
DE37252E0FE481AD00CF2CC2 /* Builtins.cpp in Sources */,
1AA1D91810125DE30078DEBC /* RecordLayoutBuilder.cpp in Sources */,
+ 1AFF8AE31012BFC900D248DA /* CGRecordLayoutBuilder.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
--- /dev/null
+//===--- 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>());
+}
--- /dev/null
+//===--- 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
#include "llvm/Target/TargetData.h"
#include "CGCall.h"
+#include "CGRecordLayoutBuilder.h"
using namespace clang;
using namespace CodeGen;
ResultType = llvm::StructType::get(std::vector<const llvm::Type*>());
} else {
// Layout fields.
- RecordOrganizer RO(*this, *RD);
+ CGRecordLayout *Layout =
+ CGRecordLayoutBuilder::ComputeLayout(*this, RD);
- if (TD->isStruct() || TD->isClass())
- RO.layoutStructFields(Context.getASTRecordLayout(RD));
- else {
- assert(TD->isUnion() && "unknown tag decl kind!");
- RO.layoutUnionFields(Context.getASTRecordLayout(RD));
+ if (!Layout) {
+ // Layout fields.
+ RecordOrganizer RO(*this, *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.
const Type *Key =
Context.getTagDeclType(const_cast<TagDecl*>(TD)).getTypePtr();
- CGRecordLayouts[Key] = new CGRecordLayout(RO.getLLVMType(),
- RO.getPaddingFields());
- ResultType = RO.getLLVMType();
+
+ CGRecordLayouts[Key] = Layout;
+ ResultType = Layout->getLLVMType();
}
// Refine our Opaque type to ResultType. This can invalidate ResultType, so
class CGRecordLayout {
CGRecordLayout(); // DO NOT IMPLEMENT
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) {
// FIXME : Collect info about fields that requires adjustments
// (i.e. fields that do not directly map to llvm struct fields.)
}
/// getLLVMType - Return llvm type associated with this record.
- llvm::Type *getLLVMType() const {
+ const llvm::Type *getLLVMType() const {
return STy;
}
}
private:
- llvm::Type *STy;
+ const llvm::Type *STy;
llvm::SmallSet<unsigned, 8> PaddingFields;
};