From 2cebe6408c4a4d515ae4dc28043d3d52abf63702 Mon Sep 17 00:00:00 2001 From: David Nadlinger Date: Wed, 12 Jun 2013 14:51:22 +0200 Subject: [PATCH] Divided ir/irtypestruct.* in general aggregate and struct specific part. This is just to improve clarity, as it was rather non-obvious what of the code also applied to classes before. IrTypeAggr::createInitializerConstant would currently belong in IrTypeStruct, but this will be refactored anyway. --- gen/arrays.cpp | 1 - gen/declarations.cpp | 1 - gen/structs.cpp | 1 - gen/tollvm.cpp | 1 + ir/iraggr.cpp | 1 + ir/irtypeaggr.cpp | 139 +++++++++++++++++++++++++++++++++++++++++++ ir/irtypeaggr.h | 76 +++++++++++++++++++++++ ir/irtypeclass.h | 2 +- ir/irtypestruct.cpp | 118 +----------------------------------- ir/irtypestruct.h | 78 ++---------------------- 10 files changed, 225 insertions(+), 193 deletions(-) create mode 100644 ir/irtypeaggr.cpp create mode 100644 ir/irtypeaggr.h diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 780d9f55..278aa762 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -22,7 +22,6 @@ #include "gen/runtime.h" #include "gen/tollvm.h" #include "ir/irmodule.h" -#include "ir/irtypestruct.h" ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/declarations.cpp b/gen/declarations.cpp index dc0f07ed..237bbc95 100644 --- a/gen/declarations.cpp +++ b/gen/declarations.cpp @@ -22,7 +22,6 @@ #include "gen/tollvm.h" #include "ir/ir.h" #include "ir/irtype.h" -#include "ir/irtypestruct.h" #include "ir/irvar.h" /* ================================================================== */ diff --git a/gen/structs.cpp b/gen/structs.cpp index 519fc343..118e70d7 100644 --- a/gen/structs.cpp +++ b/gen/structs.cpp @@ -22,7 +22,6 @@ #include "gen/tollvm.h" #include "gen/utils.h" #include "ir/iraggr.h" -#include "ir/irtypestruct.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/ManagedStatic.h" #include diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 049cc2de..11fa2f1a 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -31,6 +31,7 @@ #include "ir/irtype.h" #include "ir/irtypeclass.h" #include "ir/irtypefunction.h" +#include "ir/irtypestruct.h" bool DtoIsPassedByRef(Type* type) { diff --git a/ir/iraggr.cpp b/ir/iraggr.cpp index f4e0417f..4a73adcd 100644 --- a/ir/iraggr.cpp +++ b/ir/iraggr.cpp @@ -19,6 +19,7 @@ #include "gen/utils.h" #include "ir/iraggr.h" #include "ir/irtypeclass.h" +#include "ir/irtypestruct.h" #include ////////////////////////////////////////////////////////////////////////////// diff --git a/ir/irtypeaggr.cpp b/ir/irtypeaggr.cpp new file mode 100644 index 00000000..4a0af88b --- /dev/null +++ b/ir/irtypeaggr.cpp @@ -0,0 +1,139 @@ +//===-- irtypeaggr.cpp ----------------------------------------------------===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#include "ir/irtypeaggr.h" + +#if LDC_LLVM_VER >= 303 +#include "llvm/IR/DerivedTypes.h" +#else +#include "llvm/DerivedTypes.h" +#endif + +#include "aggregate.h" +#include "declaration.h" +#include "init.h" +#include "mtype.h" + +#include "gen/irstate.h" +#include "gen/tollvm.h" +#include "gen/logger.h" +#include "gen/utils.h" +#include "gen/llvmhelpers.h" + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// + +IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad) +: IrType(ad->type, LLStructType::create(gIR->context(), ad->toPrettyChars())), + aggr(ad) +{ +} + +////////////////////////////////////////////////////////////////////////////// + +static bool struct_init_data_sort(const IrTypeAggr::VarInitConst& a, + const IrTypeAggr::VarInitConst& b) +{ + return (a.first && b.first) + ? a.first->offset < b.first->offset + : false; +} + +extern size_t add_zeros(std::vector& constants, size_t diff); + +// return a constant array of type arrTypeD initialized with a constant value, or that constant value +static llvm::Constant* FillSArrayDims(Type* arrTypeD, llvm::Constant* init) +{ + if (arrTypeD->ty == Tsarray) + { + init = FillSArrayDims(arrTypeD->nextOf(), init); + size_t dim = static_cast(arrTypeD)->dim->toUInteger(); + llvm::ArrayType* arrty = llvm::ArrayType::get(init->getType(), dim); + return llvm::ConstantArray::get(arrty, + std::vector(dim, init)); + } + return init; +} + +llvm::Constant* IrTypeAggr::createInitializerConstant( + llvm::ArrayRef initializers, + llvm::StructType* initializerType) +{ + const bool packed = (dtype->ty == Tstruct) + ? dtype->alignsize() == 1 + : false; + + const size_t n = initializers.size(); + + // sort data array by offset + llvm::SmallVector data( + initializers.begin(), initializers.end()); + std::sort(data.begin(), data.end(), struct_init_data_sort); + + // build array of constants and make sure explicit zero padding is inserted when necessary. + size_t offset = 0; + std::vector constants; + constants.reserve(n); + + for (size_t i = 0; i < n; i++) + { + VarDeclaration* vd = data[i].first; + if (vd == NULL) + continue; + + // get next aligned offset for this field + size_t alignedoffset = offset; + if (!packed) + { + alignedoffset = realignOffset(alignedoffset, vd->type); + } + + // insert explicit padding? + if (alignedoffset < vd->offset) + { + size_t diff = vd->offset - alignedoffset; + IF_LOG Logger::println("adding %zu bytes zero padding", diff); + add_zeros(constants, diff); + } + + IF_LOG Logger::println("adding field %s", vd->toChars()); + + constants.push_back(FillSArrayDims(vd->type, data[i].second)); + offset = vd->offset + vd->type->size(); + } + + // tail padding? + const size_t structsize = getTypePaddedSize(type); + if (offset < structsize) + { + size_t diff = structsize - offset; + IF_LOG Logger::println("adding %zu bytes zero padding", diff); + add_zeros(constants, diff); + } + + // get initializer type + if (!initializerType || initializerType->isOpaque()) + { + std::vector::iterator itr, end = constants.end(); + std::vector types; + types.reserve(constants.size()); + for (itr = constants.begin(); itr != end; ++itr) + types.push_back((*itr)->getType()); + if (!initializerType) + initializerType = LLStructType::get(gIR->context(), types, packed); + else + initializerType->setBody(types, packed); + } + + // build constant + assert(!constants.empty()); + llvm::Constant* c = LLConstantStruct::get(initializerType, constants); + IF_LOG Logger::cout() << "final struct initializer: " << *c << std::endl; + return c; +} diff --git a/ir/irtypeaggr.h b/ir/irtypeaggr.h new file mode 100644 index 00000000..ccccea04 --- /dev/null +++ b/ir/irtypeaggr.h @@ -0,0 +1,76 @@ +//===-- ir/irtypeaggr.h - IrType subclasses for aggregates ------*- C++ -*-===// +// +// LDC – the LLVM D compiler +// +// This file is distributed under the BSD-style LDC license. See the LICENSE +// file for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LDC_IR_IRTYPEAGGR_H +#define LDC_IR_IRTYPEAGGR_H + +#include "ir/irtype.h" +#include "llvm/ADT/ArrayRef.h" +#include +#include + +namespace llvm { + class Constant; + class StructType; +} + +struct AggregateDeclaration; +struct VarDeclaration; + +/// Base class of IrTypes for aggregate types. +class IrTypeAggr : public IrType +{ +public: + /// + IrTypeAggr* isAggr() { return this; } + + /// + typedef std::vector::iterator iterator; + + /// + iterator def_begin() { return default_fields.begin(); } + + /// + iterator def_end() { return default_fields.end(); } + + /// A pair of a member variable declaration and an associated initializer + /// constant. + typedef std::pair VarInitConst; + + /// Creates an initializer constant for the struct type with the given + /// fields set to the provided constants. The remaining space (not + /// explicitly specified fields, padding) is default-initialized. + /// + /// The optional initializerType parmeter can be used to specify the exact + /// LLVM type to use for the initializer. If non-null and non-opaque, the + /// type must exactly match the generated constant. This parameter is used + /// mainly for supporting legacy code. + /// + /// Note that in the general case (if e.g. unions are involved), the + /// returned type is not necessarily the same as getLLType(). + llvm::Constant* createInitializerConstant( + llvm::ArrayRef initializers, + llvm::StructType* initializerType = 0); + +protected: + /// + IrTypeAggr(AggregateDeclaration* ad); + + /// AggregateDeclaration this type represents. + AggregateDeclaration* aggr; + + /// Sorted list of all default fields. + /// A default field is a field that contributes to the default initializer + /// and the default type, and thus it has it's own unique GEP index into + /// the aggregate. + /// For classes, field of any super classes are not included. + std::vector default_fields; +}; + +#endif diff --git a/ir/irtypeclass.h b/ir/irtypeclass.h index 3a6adc77..9b5fbf8e 100644 --- a/ir/irtypeclass.h +++ b/ir/irtypeclass.h @@ -14,7 +14,7 @@ #ifndef __LDC_IR_IRTYPECLASS_H__ #define __LDC_IR_IRTYPECLASS_H__ -#include "ir/irtypestruct.h" +#include "ir/irtypeaggr.h" #if LDC_LLVM_VER >= 303 #include "llvm/IR/DerivedTypes.h" #else diff --git a/ir/irtypestruct.cpp b/ir/irtypestruct.cpp index b9db9293..9812986e 100644 --- a/ir/irtypestruct.cpp +++ b/ir/irtypestruct.cpp @@ -7,6 +7,8 @@ // //===----------------------------------------------------------------------===// +#include "ir/irtypestruct.h" + #if LDC_LLVM_VER >= 303 #include "llvm/IR/DerivedTypes.h" #else @@ -23,120 +25,6 @@ #include "gen/logger.h" #include "gen/utils.h" #include "gen/llvmhelpers.h" -#include "ir/irtypestruct.h" - -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// -////////////////////////////////////////////////////////////////////////////// - -IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad) -: IrType(ad->type, LLStructType::create(gIR->context(), ad->toPrettyChars())), - aggr(ad) -{ -} - -////////////////////////////////////////////////////////////////////////////// - -static bool struct_init_data_sort(const IrTypeAggr::VarInitConst& a, - const IrTypeAggr::VarInitConst& b) -{ - return (a.first && b.first) - ? a.first->offset < b.first->offset - : false; -} - -extern size_t add_zeros(std::vector& constants, size_t diff); - -// return a constant array of type arrTypeD initialized with a constant value, or that constant value -static llvm::Constant* FillSArrayDims(Type* arrTypeD, llvm::Constant* init) -{ - if (arrTypeD->ty == Tsarray) - { - init = FillSArrayDims(arrTypeD->nextOf(), init); - size_t dim = static_cast(arrTypeD)->dim->toUInteger(); - llvm::ArrayType* arrty = llvm::ArrayType::get(init->getType(), dim); - return llvm::ConstantArray::get(arrty, - std::vector(dim, init)); - } - return init; -} - -llvm::Constant* IrTypeAggr::createInitializerConstant( - llvm::ArrayRef initializers, - llvm::StructType* initializerType) -{ - const bool packed = (dtype->ty == Tstruct) - ? dtype->alignsize() == 1 - : false; - - const size_t n = initializers.size(); - - // sort data array by offset - llvm::SmallVector data( - initializers.begin(), initializers.end()); - std::sort(data.begin(), data.end(), struct_init_data_sort); - - // build array of constants and make sure explicit zero padding is inserted when necessary. - size_t offset = 0; - std::vector constants; - constants.reserve(n); - - for (size_t i = 0; i < n; i++) - { - VarDeclaration* vd = data[i].first; - if (vd == NULL) - continue; - - // get next aligned offset for this field - size_t alignedoffset = offset; - if (!packed) - { - alignedoffset = realignOffset(alignedoffset, vd->type); - } - - // insert explicit padding? - if (alignedoffset < vd->offset) - { - size_t diff = vd->offset - alignedoffset; - IF_LOG Logger::println("adding %zu bytes zero padding", diff); - add_zeros(constants, diff); - } - - IF_LOG Logger::println("adding field %s", vd->toChars()); - - constants.push_back(FillSArrayDims(vd->type, data[i].second)); - offset = vd->offset + vd->type->size(); - } - - // tail padding? - const size_t structsize = getTypePaddedSize(type); - if (offset < structsize) - { - size_t diff = structsize - offset; - IF_LOG Logger::println("adding %zu bytes zero padding", diff); - add_zeros(constants, diff); - } - - // get initializer type - if (!initializerType || initializerType->isOpaque()) - { - std::vector::iterator itr, end = constants.end(); - std::vector types; - types.reserve(constants.size()); - for (itr = constants.begin(); itr != end; ++itr) - types.push_back((*itr)->getType()); - if (!initializerType) - initializerType = LLStructType::get(gIR->context(), types, packed); - else - initializerType->setBody(types, packed); - } - - // build constant - assert(!constants.empty()); - llvm::Constant* c = LLConstantStruct::get(initializerType, constants); - IF_LOG Logger::cout() << "final struct initializer: " << *c << std::endl; - return c; -} ////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////// @@ -344,5 +232,3 @@ IrTypeStruct* IrTypeStruct::get(StructDeclaration* sd) return t; } - -////////////////////////////////////////////////////////////////////////////// diff --git a/ir/irtypestruct.h b/ir/irtypestruct.h index 1b745985..8c32dc5b 100644 --- a/ir/irtypestruct.h +++ b/ir/irtypestruct.h @@ -1,4 +1,4 @@ -//===-- ir/irtypestruct.h - IrType subclasses for aggregates ----*- C++ -*-===// +//===-- ir/irtypestruct.h - IrType for structs and unions -------*- C++ -*-===// // // LDC – the LLVM D compiler // @@ -6,82 +6,16 @@ // file for details. // //===----------------------------------------------------------------------===// -// -// Provides the IrType subclasses used to represent D struct types -// (see irtypeclass.h for the class version). -// -//===----------------------------------------------------------------------===// -#ifndef __LDC_IR_IRTYPESTRUCT_H__ -#define __LDC_IR_IRTYPESTRUCT_H__ +#ifndef LDC_IR_IRTYPESTRUCT_H +#define LDC_IR_IRTYPESTRUCT_H -#include "ir/irtype.h" -#include "llvm/ADT/ArrayRef.h" -#include +#include "ir/irtypeaggr.h" -////////////////////////////////////////////////////////////////////////////// - -namespace llvm { - class StructType; -} - -struct AggregateDeclaration; struct StructDeclaration; struct TypeStruct; -////////////////////////////////////////////////////////////////////////////// - -class IrTypeAggr : public IrType -{ -public: - /// - IrTypeAggr* isAggr() { return this; } - - /// - typedef std::vector::iterator iterator; - - /// - iterator def_begin() { return default_fields.begin(); } - - /// - iterator def_end() { return default_fields.end(); } - - /// A pair of a member variable declaration and an associated initializer - /// constant. - typedef std::pair VarInitConst; - - /// Creates an initializer constant for the struct type with the given - /// fields set to the provided constants. The remaining space (not - /// explicitly specified fields, padding) is default-initialized. - /// - /// The optional initializerType parmeter can be used to specify the exact - /// LLVM type to use for the initializer. If non-null and non-opaque, the - /// type must exactly match the generated constant. This parameter is used - /// mainly for supporting legacy code. - /// - /// Note that in the general case (if e.g. unions are involved), the - /// returned type is not necessarily the same as getLLType(). - llvm::Constant* createInitializerConstant( - llvm::ArrayRef initializers, - llvm::StructType* initializerType = 0); - -protected: - /// - IrTypeAggr(AggregateDeclaration* ad); - - /// AggregateDeclaration this type represents. - AggregateDeclaration* aggr; - - /// Sorted list of all default fields. - /// A default field is a field that contributes to the default initializer - /// and the default type, and thus it has it's own unique GEP index into - /// the aggregate. - /// For classes, field of any super classes are not included. - std::vector default_fields; -}; - -////////////////////////////////////////////////////////////////////////////// - +/// IrType for struct/union types. class IrTypeStruct : public IrTypeAggr { public: @@ -102,6 +36,4 @@ protected: TypeStruct* ts; }; -////////////////////////////////////////////////////////////////////////////// - #endif