diff options
author | Devang Patel <dpatel@apple.com> | 2007-10-23 02:10:49 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2007-10-23 02:10:49 +0000 |
commit | b84a06e68ffd71da22e3c75b6e4bbdba37816413 (patch) | |
tree | 1d218863bb30d46284d0c652b491f65d0b2131b3 | |
parent | 9f0a1cb8cf741d8ccd86beb15b50867b0758750f (diff) |
Begin struct layout work.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@43236 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | CodeGen/CodeGenFunction.cpp | 11 | ||||
-rw-r--r-- | CodeGen/CodeGenFunction.h | 9 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.cpp | 82 | ||||
-rw-r--r-- | CodeGen/CodeGenTypes.h | 71 |
4 files changed, 167 insertions, 6 deletions
diff --git a/CodeGen/CodeGenFunction.cpp b/CodeGen/CodeGenFunction.cpp index 1457ec5606..9e3f1cef38 100644 --- a/CodeGen/CodeGenFunction.cpp +++ b/CodeGen/CodeGenFunction.cpp @@ -126,3 +126,14 @@ void CodeGenFunction::StartBlock(const char *N) { BB->setName(N); } +/// getRecordLayoutInfo - Return record layout info. +RecordLayoutInfo *CodeGenFunction::getRecordLayoutInfo(CodeGenTypes &CGT, + QualType RTy) { + assert (isa<RecordType>(RTy) + && "Unexpected type. RecordType expected here."); + + const llvm::Type *Ty = ConvertType(RTy); + assert (Ty && "Unable to find llvm::Type"); + + return CGT.getRecordLayoutInfo(Ty); +} diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h index 3e08461efa..c14687e07e 100644 --- a/CodeGen/CodeGenFunction.h +++ b/CodeGen/CodeGenFunction.h @@ -65,13 +65,15 @@ namespace clang { class ChooseExpr; class PreDefinedExpr; class ObjCStringLiteral; - + class MemberExpr; + class BlockVarDecl; class EnumConstantDecl; class ParmVarDecl; namespace CodeGen { class CodeGenModule; - + class CodeGenTypes; + class RecordLayoutInfo; /// RValue - This trivial value class is used to represent the result of an /// expression that is evaluated. It can be one of three things: either a @@ -296,6 +298,8 @@ public: /// then reuse it. void StartBlock(const char *N); + /// getRecordLayoutInfo - Return record layout info. + RecordLayoutInfo *getRecordLayoutInfo(CodeGenTypes &CGT, QualType RTy); //===--------------------------------------------------------------------===// // Declaration Emission //===--------------------------------------------------------------------===// @@ -370,6 +374,7 @@ public: LValue EmitUnaryOpLValue(const UnaryOperator *E); LValue EmitArraySubscriptExpr(const ArraySubscriptExpr *E); LValue EmitOCUVectorElementExpr(const OCUVectorElementExpr *E); + LValue EmitMemberExpr(const MemberExpr *E); //===--------------------------------------------------------------------===// // Scalar Expression Emission diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp index d8174bec4e..35ed348a7b 100644 --- a/CodeGen/CodeGenTypes.cpp +++ b/CodeGen/CodeGenTypes.cpp @@ -24,6 +24,14 @@ CodeGenTypes::CodeGenTypes(ASTContext &Ctx, llvm::Module& M) : Context(Ctx), Target(Ctx.Target), TheModule(M) { } +CodeGenTypes::~CodeGenTypes() { + for(llvm::DenseMap<const llvm::Type *, RecordLayoutInfo *>::iterator + I = RecordLayouts.begin(), E = RecordLayouts.end(); + I != E; ++I) + delete I->second; + RecordLayouts.clear(); +} + /// ConvertType - Convert the specified type to its LLVM form. const llvm::Type *CodeGenTypes::ConvertType(QualType T) { // FIXME: Cache these, move the CodeGenModule, expand, etc. @@ -159,10 +167,14 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) { return ConvertType(cast<EnumDecl>(TD)->getIntegerType()); } else if (TD->getKind() == Decl::Struct) { const RecordDecl *RD = cast<const RecordDecl>(TD); - std::vector<const llvm::Type*> Fields; + RecordOrganizer *RO = new RecordOrganizer(); for (unsigned i = 0, e = RD->getNumMembers(); i != e; ++i) - Fields.push_back(ConvertType(RD->getMember(i)->getType())); - ResultType = llvm::StructType::get(Fields); + RO->addField(RD->getMember(i)); + RO->layoutFields(*this); + RecordLayoutInfo *RLI = new RecordLayoutInfo(RO); + ResultType = RLI->getLLVMType(); + RecordLayouts[ResultType] = RLI; + delete RO; } else if (TD->getKind() == Decl::Union) { const RecordDecl *RD = cast<const RecordDecl>(TD); // Just use the largest element of the union, breaking ties with the @@ -214,3 +226,67 @@ void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP, } } +/// getLLVMFieldNo - Return llvm::StructType element number +/// that corresponds to the field FD. +unsigned CodeGenTypes::getLLVMFieldNo(const FieldDecl *FD) { + llvm::DenseMap<const FieldDecl *, unsigned>::iterator + I = FieldInfo.find(FD); + if (I != FieldInfo.end() && "Unable to find field info"); + return I->second; +} + + /// addFieldInfo - Assign field number to field FD. +void CodeGenTypes::addFieldInfo(const FieldDecl *FD, unsigned No) { + FieldInfo[FD] = No; +} + +/// getRecordLayoutInfo - Return record layout info for the given llvm::Type. +RecordLayoutInfo *CodeGenTypes::getRecordLayoutInfo(const llvm::Type* Ty) { + llvm::DenseMap<const llvm::Type*, RecordLayoutInfo *>::iterator I + = RecordLayouts.find(Ty); + assert (I != RecordLayouts.end() + && "Unable to find record layout information for type"); + return I->second; +} + +/// RecordLayoutInfo - Construct record layout info object using layout +/// organized by record organizer. +RecordLayoutInfo::RecordLayoutInfo(RecordOrganizer *RO) { + STy = RO->getLLVMType(); + assert (STy && "Record layout is incomplete to determine llvm::Type"); + // FIXME : Collect info about fields that requires adjustments + // (i.e. fields that do not directly map to llvm struct fields.) +} + + +/// addField - Add new field. +void RecordOrganizer::addField(const FieldDecl *FD) { + assert (!STy && "Record fields are already laid out"); + FieldDecls.push_back(FD); +} + +/// layoutFields - Do the actual work and lay out all fields. Create +/// corresponding llvm struct type. This should be invoked only after +/// all fields are added. +/// FIXME : At the moment assume +/// - one to one mapping between AST FieldDecls and +/// llvm::StructType elements. +/// - Ignore bit fields +/// - Ignore field aligments +/// - Ignore packed structs +void RecordOrganizer::layoutFields(CodeGenTypes &CGT) { + // FIXME : Use SmallVector + std::vector<const llvm::Type*> Fields; + unsigned FieldNo = 0; + for (llvm::SmallVector<const FieldDecl *, 8>::iterator I = FieldDecls.begin(), + E = FieldDecls.end(); I != E; ++I) { + const FieldDecl *FD = *I; + const llvm::Type *Ty = CGT.ConvertType(FD->getType()); + + // FIXME : Layout FieldDecl FD + + Fields.push_back(Ty); + CGT.addFieldInfo(FD, FieldNo++); + } + STy = llvm::StructType::get(Fields); +} diff --git a/CodeGen/CodeGenTypes.h b/CodeGen/CodeGenTypes.h index 1f6cbd8701..998175537b 100644 --- a/CodeGen/CodeGenTypes.h +++ b/CodeGen/CodeGenTypes.h @@ -15,6 +15,7 @@ #define CODEGEN_CODEGENTYPES_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include <vector> namespace llvm { @@ -28,8 +29,57 @@ namespace clang { class TargetInfo; class QualType; class FunctionTypeProto; - + class FieldDecl; + namespace CodeGen { + class CodeGenTypes; + + /// RecordOrganizer - This helper class, used by RecordLayoutInfo, layouts + /// structs and unions. It manages transient information used during layout. + /// FIXME : At the moment assume + /// - one to one mapping between AST FieldDecls and + /// llvm::StructType elements. + /// - Ignore bit fields + /// - Ignore field aligments + /// - Ignore packed structs + class RecordOrganizer { + public: + RecordOrganizer() : STy(NULL) {} + + /// addField - Add new field. + void addField(const FieldDecl *FD); + + /// layoutFields - Do the actual work and lay out all fields. Create + /// corresponding llvm struct type. This should be invoked only after + /// all fields are added. + void layoutFields(CodeGenTypes &CGT); + + /// getLLVMType - Return associated llvm struct type. This may be NULL + /// if fields are not laid out. + llvm::Type *getLLVMType() { + return STy; + } + + private: + llvm::Type *STy; + llvm::SmallVector<const FieldDecl *, 8> FieldDecls; + }; + + /// RecordLayoutInfo - This class handles struct and union layout info while + /// lowering AST types to LLVM types. + class RecordLayoutInfo { + RecordLayoutInfo(); // DO NOT IMPLEMENT + public: + RecordLayoutInfo(RecordOrganizer *RO); + + /// getLLVMType - Return llvm type associated with this record. + llvm::Type *getLLVMType() { + return STy; + } + + private: + llvm::Type *STy; + }; /// CodeGenTypes - This class organizes the cross-module state that is used /// while lowering AST types to LLVM types. @@ -39,14 +89,33 @@ class CodeGenTypes { llvm::Module& TheModule; llvm::DenseMap<const TagDecl*, llvm::Type*> TagDeclTypes; + + /// RecordLayouts - This maps llvm struct type with corresponding + /// record layout info. + llvm::DenseMap<const llvm::Type*, RecordLayoutInfo *> RecordLayouts; + + /// FieldInfo - This maps struct field with corresponding llvm struct type + /// field no. This info is populated by record organizer. + llvm::DenseMap<const FieldDecl *, unsigned> FieldInfo; + public: CodeGenTypes(ASTContext &Ctx, llvm::Module &M); + ~CodeGenTypes(); TargetInfo &getTarget() const { return Target; } const llvm::Type *ConvertType(QualType T); void DecodeArgumentTypes(const FunctionTypeProto &FTP, std::vector<const llvm::Type*> &ArgTys); + + RecordLayoutInfo *getRecordLayoutInfo(const llvm::Type*); + + /// getLLVMFieldNo - Return llvm::StructType element number + /// that corresponds to the field FD. + unsigned getLLVMFieldNo(const FieldDecl *FD); + + /// addFieldInfo - Assign field number to field FD. + void addFieldInfo(const FieldDecl *FD, unsigned No); }; } // end namespace CodeGen |