forked from OSchip/llvm-project
initial layout support for structures and unions. This isn't actually
hooked up to anything, so it's not very useful yet. llvm-svn: 40006
This commit is contained in:
parent
b5d3f84459
commit
53cfe80407
|
@ -145,6 +145,9 @@ void ASTContext::InitBuiltinTypes() {
|
|||
LongDoubleComplexTy = getComplexType(LongDoubleTy);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type Sizing and Analysis
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// getTypeSize - Return the size of the specified type, in bits. This method
|
||||
/// does not work on incomplete types.
|
||||
|
@ -197,9 +200,76 @@ ASTContext::getTypeInfo(QualType T, SourceLocation L) {
|
|||
return getTypeInfo(cast<ReferenceType>(T)->getReferenceeType(), L);
|
||||
}
|
||||
|
||||
assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2");
|
||||
return std::make_pair(Size, Align);
|
||||
}
|
||||
|
||||
/// getRecordLayout - Get or compute information about the layout of the
|
||||
/// specified record (struct/union/class), which indicates its size and field
|
||||
/// position information.
|
||||
const RecordLayout &ASTContext::getRecordLayout(const RecordDecl *D,
|
||||
SourceLocation L) {
|
||||
assert(D->isDefinition() && "Cannot get layout of forward declarations!");
|
||||
|
||||
// Look up this layout, if already laid out, return what we have.
|
||||
const RecordLayout *&Entry = RecordLayoutInfo[D];
|
||||
if (Entry) return *Entry;
|
||||
|
||||
// Allocate and assign into RecordLayoutInfo here. The "Entry" reference can
|
||||
// be invalidated (dangle) if the RecordLayoutInfo hashtable is inserted into.
|
||||
RecordLayout *NewEntry = new RecordLayout();
|
||||
Entry = NewEntry;
|
||||
|
||||
uint64_t *FieldOffsets = new uint64_t[D->getNumMembers()];
|
||||
uint64_t RecordSize = 0;
|
||||
unsigned RecordAlign = 8; // Default alignment = 1 byte = 8 bits.
|
||||
|
||||
if (D->getKind() != Decl::Union) {
|
||||
// Layout each field, for now, just sequentially, respecting alignment. In
|
||||
// the future, this will need to be tweakable by targets.
|
||||
for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
|
||||
const FieldDecl *FD = D->getMember(i);
|
||||
std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType(), L);
|
||||
uint64_t FieldSize = FieldInfo.first;
|
||||
unsigned FieldAlign = FieldInfo.second;
|
||||
|
||||
// Round up the current record size to the field's alignment boundary.
|
||||
RecordSize = (RecordSize+FieldAlign-1) & ~(FieldAlign-1);
|
||||
|
||||
// Place this field at the current location.
|
||||
FieldOffsets[i] = RecordSize;
|
||||
|
||||
// Reserve space for this field.
|
||||
RecordSize += FieldSize;
|
||||
|
||||
// Remember max struct/class alignment.
|
||||
RecordAlign = std::max(RecordAlign, FieldAlign);
|
||||
}
|
||||
|
||||
// Finally, round the size of the total struct up to the alignment of the
|
||||
// struct itself.
|
||||
RecordSize = (RecordSize+RecordAlign-1) & ~(RecordAlign-1);
|
||||
} else {
|
||||
// Union layout just puts each member at the start of the record.
|
||||
for (unsigned i = 0, e = D->getNumMembers(); i != e; ++i) {
|
||||
const FieldDecl *FD = D->getMember(i);
|
||||
std::pair<uint64_t, unsigned> FieldInfo = getTypeInfo(FD->getType(), L);
|
||||
uint64_t FieldSize = FieldInfo.first;
|
||||
unsigned FieldAlign = FieldInfo.second;
|
||||
|
||||
// Round up the current record size to the field's alignment boundary.
|
||||
RecordSize = std::max(RecordSize, FieldSize);
|
||||
|
||||
// Place this field at the start of the record.
|
||||
FieldOffsets[i] = 0;
|
||||
|
||||
// Remember max struct/class alignment.
|
||||
RecordAlign = std::max(RecordAlign, FieldAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Type creation/memoization methods
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -58,6 +58,7 @@
|
|||
DE67E7170C020EE400F66BC5 /* Sema.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7160C020EE400F66BC5 /* Sema.cpp */; };
|
||||
DE67E71A0C020F4F00F66BC5 /* ASTStreamer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */; };
|
||||
DE67E7280C02109800F66BC5 /* ASTStreamer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE67E7270C02109800F66BC5 /* ASTStreamer.h */; };
|
||||
DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE6951C60C4D1F5D00A5826B /* RecordLayout.h */; };
|
||||
DE75ED290B044DC90020CF81 /* ASTContext.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = DE75ED280B044DC90020CF81 /* ASTContext.h */; };
|
||||
DE75EDF10B06880E0020CF81 /* Type.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE75EDF00B06880E0020CF81 /* Type.cpp */; };
|
||||
DE927FFD0C055DE900231DA4 /* LLVMCodegen.cpp in Sources */ = {isa = PBXBuildFile; fileRef = DE927FFC0C055DE900231DA4 /* LLVMCodegen.cpp */; };
|
||||
|
@ -178,6 +179,7 @@
|
|||
DEB0AEB90C2087A700718A22 /* TextDiagnostics.h in CopyFiles */,
|
||||
DEEBC3BA0C2363B800A9FE82 /* CodeGenTypes.h in CopyFiles */,
|
||||
DEEBCBE30C33702C00A9FE82 /* TextDiagnosticBuffer.h in CopyFiles */,
|
||||
DE6951C70C4D1F5D00A5826B /* RecordLayout.h in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
};
|
||||
|
@ -236,6 +238,7 @@
|
|||
DE67E7160C020EE400F66BC5 /* Sema.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Sema.cpp; path = Sema/Sema.cpp; sourceTree = "<group>"; };
|
||||
DE67E7190C020F4F00F66BC5 /* ASTStreamer.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ASTStreamer.cpp; path = Sema/ASTStreamer.cpp; sourceTree = "<group>"; };
|
||||
DE67E7270C02109800F66BC5 /* ASTStreamer.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTStreamer.h; path = clang/Sema/ASTStreamer.h; sourceTree = "<group>"; };
|
||||
DE6951C60C4D1F5D00A5826B /* RecordLayout.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = RecordLayout.h; path = clang/AST/RecordLayout.h; sourceTree = "<group>"; };
|
||||
DE75ED280B044DC90020CF81 /* ASTContext.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ASTContext.h; path = clang/AST/ASTContext.h; sourceTree = "<group>"; };
|
||||
DE75EDF00B06880E0020CF81 /* Type.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = Type.cpp; path = AST/Type.cpp; sourceTree = "<group>"; };
|
||||
DE927FFC0C055DE900231DA4 /* LLVMCodegen.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = LLVMCodegen.cpp; path = Driver/LLVMCodegen.cpp; sourceTree = "<group>"; };
|
||||
|
@ -459,6 +462,7 @@
|
|||
DEC8D9900A9433CD00353FCA /* Decl.h */,
|
||||
DE0FCA620A95859D00248FD5 /* Expr.h */,
|
||||
1A30A9E80B93A4C800201A91 /* ExprCXX.h */,
|
||||
DE6951C60C4D1F5D00A5826B /* RecordLayout.h */,
|
||||
DE3452800AEF1B1800DBC861 /* Stmt.h */,
|
||||
DE345F210AFD347900DBC861 /* StmtNodes.def */,
|
||||
DE345C190AFC658B00DBC861 /* StmtVisitor.h */,
|
||||
|
|
|
@ -15,8 +15,10 @@
|
|||
#define LLVM_CLANG_AST_ASTCONTEXT_H
|
||||
|
||||
#include "clang/AST/Builtins.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/RecordLayout.h"
|
||||
#include "clang/AST/Type.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
@ -33,6 +35,7 @@ class ASTContext {
|
|||
llvm::FoldingSet<VectorType> VectorTypes;
|
||||
llvm::FoldingSet<FunctionTypeNoProto> FunctionTypeNoProtos;
|
||||
llvm::FoldingSet<FunctionTypeProto> FunctionTypeProtos;
|
||||
llvm::DenseMap<const RecordDecl*, const RecordLayout*> RecordLayoutInfo;
|
||||
public:
|
||||
TargetInfo &Target;
|
||||
Builtin::Context BuiltinInfo;
|
||||
|
@ -55,21 +58,9 @@ public:
|
|||
|
||||
void PrintStats() const;
|
||||
|
||||
/// getTypeInfo - Get the size and alignment of the specified complete type in
|
||||
/// bits.
|
||||
std::pair<uint64_t, unsigned> getTypeInfo(QualType T, SourceLocation L);
|
||||
|
||||
/// getTypeSize - Return the size of the specified type, in bits. This method
|
||||
/// does not work on incomplete types.
|
||||
uint64_t getTypeSize(QualType T, SourceLocation L) {
|
||||
return getTypeInfo(T, L).first;
|
||||
}
|
||||
|
||||
/// getTypeAlign - Return the alignment of the specified type, in bits. This
|
||||
/// method does not work on incomplete types.
|
||||
unsigned getTypeAlign(QualType T, SourceLocation L) {
|
||||
return getTypeInfo(T, L).second;
|
||||
}
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Constructors
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// getComplexType - Return the uniqued reference to the type for a complex
|
||||
/// number with the specified element type.
|
||||
|
@ -118,21 +109,50 @@ public:
|
|||
/// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9).
|
||||
QualType getPointerDiffType() const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Sizing and Analysis
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// getTypeInfo - Get the size and alignment of the specified complete type in
|
||||
/// bits.
|
||||
std::pair<uint64_t, unsigned> getTypeInfo(QualType T, SourceLocation L);
|
||||
|
||||
/// getTypeSize - Return the size of the specified type, in bits. This method
|
||||
/// does not work on incomplete types.
|
||||
uint64_t getTypeSize(QualType T, SourceLocation L) {
|
||||
return getTypeInfo(T, L).first;
|
||||
}
|
||||
|
||||
/// getTypeAlign - Return the alignment of the specified type, in bits. This
|
||||
/// method does not work on incomplete types.
|
||||
unsigned getTypeAlign(QualType T, SourceLocation L) {
|
||||
return getTypeInfo(T, L).second;
|
||||
}
|
||||
|
||||
/// getRecordLayout - Get or compute information about the layout of the
|
||||
/// specified record (struct/union/class), which indicates its size and field
|
||||
/// position information.
|
||||
const RecordLayout &getRecordLayout(const RecordDecl *D, SourceLocation L);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Type Operators
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// getIntegerBitwidth - Return the bitwidth of the specified integer type
|
||||
/// according to the target. 'Loc' specifies the source location that
|
||||
/// requires evaluation of this property.
|
||||
unsigned getIntegerBitwidth(QualType T, SourceLocation Loc);
|
||||
|
||||
// maxIntegerType - Returns the highest ranked integer type. Handles 3
|
||||
// different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
|
||||
|
||||
/// maxIntegerType - Returns the highest ranked integer type. Handles 3
|
||||
/// different type combos: unsigned/unsigned, signed/signed, signed/unsigned.
|
||||
static QualType maxIntegerType(QualType lhs, QualType rhs);
|
||||
|
||||
// maxFloatingType - Returns the highest ranked float type. Both input
|
||||
// types are required to be floats.
|
||||
/// maxFloatingType - Returns the highest ranked float type. Both input
|
||||
/// types are required to be floats.
|
||||
static QualType maxFloatingType(QualType lt, QualType rt);
|
||||
|
||||
// maxComplexType - Returns the highest ranked complex type. Handles 3
|
||||
// different type combos: complex/complex, complex/float, float/complex.
|
||||
/// maxComplexType - Returns the highest ranked complex type. Handles 3
|
||||
/// different type combos: complex/complex, complex/float, float/complex.
|
||||
QualType maxComplexType(QualType lt, QualType rt) const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
//===--- RecordLayout.h - Layout information for a struct/union -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Chris Lattner and is distributed under
|
||||
// the University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file defines the RecordLayout interface.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_AST_LAYOUTINFO_H
|
||||
#define LLVM_CLANG_AST_LAYOUTINFO_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
class RecordDecl;
|
||||
|
||||
/// RecordLayout - This class contains layout information for one RecordDecl,
|
||||
/// which is a struct/union/class. The decl represented must be a definition,
|
||||
/// not a forward declaration. These objects are managed by ASTContext.
|
||||
class RecordLayout {
|
||||
uint64_t Size; // Size of record in bits.
|
||||
unsigned Alignment; // Alignment of record in bits.
|
||||
uint64_t *FieldOffsets;
|
||||
friend class ASTContext;
|
||||
|
||||
RecordLayout() {}
|
||||
~RecordLayout() {
|
||||
delete [] FieldOffsets;
|
||||
}
|
||||
|
||||
void SetLayout(uint64_t size, unsigned alignment, uint64_t *fieldOffsets) {
|
||||
Size = Size; Alignment = alignment;
|
||||
FieldOffsets = fieldOffsets;
|
||||
}
|
||||
|
||||
RecordLayout(const RecordLayout&); // DO NOT IMPLEMENT
|
||||
void operator=(const RecordLayout&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
|
||||
unsigned getAlignment() const { return Alignment; }
|
||||
uint64_t getSize() const { return Size; }
|
||||
|
||||
uint64_t getFieldOffset(unsigned FieldNo) const {
|
||||
return FieldOffsets[FieldNo];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue