Rewritten initialization of global variables.

This commit is contained in:
Alexey Prokhin
2011-10-24 21:45:50 +04:00
parent 66a30803f3
commit 7431d58702
18 changed files with 219 additions and 29 deletions

View File

@@ -3117,6 +3117,9 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *
#endif
this->soffset = 0;
this->fillHoles = 1;
#if IN_LLVM
constType = NULL;
#endif
}
Expression *StructLiteralExp::syntaxCopy()

View File

@@ -66,6 +66,7 @@ struct DValue;
namespace llvm {
class Constant;
class ConstantInt;
class StructType;
}
#endif
@@ -537,6 +538,7 @@ struct StructLiteralExp : Expression
#elif IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
llvm::StructType *constType;
#endif
};

View File

@@ -114,6 +114,9 @@ StructInitializer::StructInitializer(Loc loc)
: Initializer(loc)
{
ad = NULL;
#if IN_LLVM
ltype = NULL;
#endif
}
Initializer *StructInitializer::syntaxCopy()

View File

@@ -30,6 +30,12 @@ struct ExpInitializer;
struct HdrGenState;
#endif
#if IN_LLVM
namespace llvm {
class StructType;
}
#endif
struct Initializer : Object
{
Loc loc;
@@ -91,6 +97,9 @@ struct StructInitializer : Initializer
#endif
StructInitializer *isStructInitializer() { return this; }
#if IN_LLVM
llvm::StructType *ltype;
#endif
};
struct ArrayInitializer : Initializer

View File

@@ -3737,6 +3737,9 @@ StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *
#endif
this->soffset = 0;
this->fillHoles = 1;
#if IN_LLVM
constType = NULL;
#endif
}
Expression *StructLiteralExp::syntaxCopy()

View File

@@ -74,6 +74,7 @@ struct DValue;
namespace llvm {
class Constant;
class ConstantInt;
class StructType;
}
#endif
@@ -590,6 +591,7 @@ struct StructLiteralExp : Expression
#elif IN_LLVM
DValue* toElem(IRState* irs);
llvm::Constant *toConstElem(IRState *irs);
llvm::StructType *constType;
#endif
};

View File

@@ -114,6 +114,9 @@ StructInitializer::StructInitializer(Loc loc)
: Initializer(loc)
{
ad = NULL;
#if IN_LLVM
ltype = NULL;
#endif
}
Initializer *StructInitializer::syntaxCopy()

View File

@@ -28,6 +28,12 @@ struct ArrayInitializer;
struct ExpInitializer;
struct HdrGenState;
#if IN_LLVM
namespace llvm {
class StructType;
}
#endif
struct Initializer : Object
{
@@ -91,6 +97,9 @@ struct StructInitializer : Initializer
#endif
StructInitializer *isStructInitializer() { return this; }
#if IN_LLVM
llvm::StructType *ltype;
#endif
};
struct ArrayInitializer : Initializer

View File

@@ -15,6 +15,7 @@
#include "gen/logger.h"
#include "gen/dvalue.h"
#include "ir/irmodule.h"
#include "ir/irtypestruct.h"
#include "gen/cl_options.h"
@@ -361,6 +362,85 @@ void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr)
//////////////////////////////////////////////////////////////////////////////////////////
// The function is almost identical copy of DtoConstArrayInitializer but it returns
// initializer type not the initializer itself.
// FIXME: is there any way to merge this next two functions?
LLType* DtoConstArrayInitializerType(ArrayInitializer* arrinit)
{
Type* arrty = arrinit->type->toBasetype();
if (arrty->ty != Tsarray)
return DtoType(arrinit->type);
TypeSArray* tsa = (TypeSArray*)arrty;
size_t arrlen = (size_t)tsa->dim->toInteger();
// get elem type
Type* elemty = arrty->nextOf();
LLType* llelemty = DtoTypeNotVoid(elemty);
// make sure the number of initializers is sane
if (arrinit->index.dim > arrlen || arrinit->dim > arrlen)
{
error(arrinit->loc, "too many initializers, %u, for array[%zu]", arrinit->index.dim, arrlen);
fatal();
}
// true if array elements differ in type, can happen with array of unions
bool mismatch = false;
// allocate room for types
std::vector<LLType*> types(arrlen, NULL);
// go through each initializer, they're not sorted by index by the frontend
size_t j = 0;
for (size_t i = 0; i < arrinit->index.dim; i++)
{
// get index
Expression* idx = (Expression*)arrinit->index.data[i];
// idx can be null, then it's just the next element
if (idx)
j = idx->toInteger();
assert(j < arrlen);
// get value
Initializer* val = (Initializer*)arrinit->value.data[i];
assert(val);
LLType* c = DtoConstInitializerType(elemty, val);
assert(c);
if (c != llelemty)
mismatch = true;
types[j] = c;
j++;
}
// fill out any null entries still left with default type
// element default types
LLType* deftype = DtoConstInitializerType(elemty, 0);
bool mismatch2 = (deftype != llelemty);
for (size_t i = 0; i < arrlen; i++)
{
if (types[i] != NULL)
continue;
types[i] = deftype;
if (mismatch2)
mismatch = true;
}
if (mismatch)
return LLStructType::get(gIR->context(), types); // FIXME should this pack?
else
return LLArrayType::get(deftype, arrlen);
}
//////////////////////////////////////////////////////////////////////////////////////////
LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
{
Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
@@ -469,7 +549,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
#if DMDV2
if (arrty->ty == Tpointer)
// we need to return pointer to the static array.
return gvar;
return DtoBitCast(gvar, DtoType(arrty));
#endif
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
@@ -477,7 +557,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
gep = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(llelemty));
return DtoConstSlice(DtoConstSize_t(arrlen),gep);
return DtoConstSlice(DtoConstSize_t(arrlen), gep, arrty);
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -9,6 +9,7 @@ llvm::StructType* DtoArrayType(Type* arrayTy);
llvm::StructType* DtoArrayType(LLType* elemTy);
llvm::ArrayType* DtoStaticArrayType(Type* sarrayTy);
LLType* DtoConstArrayInitializerType(ArrayInitializer* arrinit);
LLConstant* DtoConstArrayInitializer(ArrayInitializer* si);
LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr, Type *type = 0);

View File

@@ -6,6 +6,7 @@
#include "id.h"
#include "mem.h"
#include "template.h"
#include "init.h"
#include "gen/irstate.h"
#include "gen/tollvm.h"
@@ -136,12 +137,10 @@ void VarDeclaration::codegen(Ir* p)
ir.initialized = gIR->dmodule;
std::string _name(mangle());
// build the initializer
LLConstant* initVal = DtoConstInitializer(loc, type, init);
ir.irGlobal->type = initVal->getType();
LLType *_type = DtoConstInitializerType(type, init);
// create the global variable
LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, initVal->getType(), _isconst,
LLGlobalVariable* gvar = new LLGlobalVariable(*gIR->module, _type, _isconst,
DtoLinkage(this), NULL, _name, 0, isThreadlocal());
this->ir.irGlobal->value = gvar;
@@ -156,10 +155,6 @@ void VarDeclaration::codegen(Ir* p)
if (nakedUse)
gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
// set the initializer if appropriate
assert(!ir.irGlobal->constInit);
ir.irGlobal->constInit = initVal;
// assign the initializer
if (!(storage_class & STCextern) && mustDefineSymbol(this))
{
@@ -171,7 +166,12 @@ void VarDeclaration::codegen(Ir* p)
Logger::cout() << "init: " << *initVal << '\n';
#endif
}
// build the initializer
LLConstant *initVal = DtoConstInitializer(loc, type, init);
// set the initializer
assert(!ir.irGlobal->constInit);
ir.irGlobal->constInit = initVal;
gvar->setInitializer(initVal);
#ifndef DISABLE_DEBUG_INFO

View File

@@ -1255,6 +1255,60 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr)
// INITIALIZER HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/
LLType* DtoConstInitializerType(Type* type, Initializer* init)
{
if (type->ty == Ttypedef) {
TypeTypedef *td = (TypeTypedef*)type;
if (td->sym->init)
return DtoConstInitializerType(td->sym->basetype, td->sym->init);
}
type = type->toBasetype();
if (type->ty == Tsarray)
{
if (!init)
{
TypeSArray *tsa = (TypeSArray*)type;
LLType *llnext = DtoConstInitializerType(type->nextOf(), init);
return LLArrayType::get(llnext, tsa->dim->toUInteger());
}
else if (ArrayInitializer* ai = init->isArrayInitializer())
{
return DtoConstArrayInitializerType(ai);
}
}
else if (type->ty == Tstruct)
{
if (!init)
{
LdefaultInit:
TypeStruct *ts = (TypeStruct*)type;
DtoResolveStruct(ts->sym);
return ts->sym->ir.irStruct->getDefaultInit()->getType();
}
else if (ExpInitializer* ex = init->isExpInitializer())
{
if (ex->exp->op == TOKstructliteral) {
StructLiteralExp* le = (StructLiteralExp*)ex->exp;
if (!le->constType)
le->constType = LLStructType::create(gIR->context(), std::string(type->toChars()) + "_init");
return le->constType;
} else if (ex->exp->op == TOKvar) {
if (((VarExp*)ex->exp)->var->isStaticStructInitDeclaration())
goto LdefaultInit;
}
}
else if (StructInitializer* si = init->isStructInitializer())
{
if (!si->ltype)
si->ltype = LLStructType::create(gIR->context(), std::string(type->toChars()) + "_init");
return si->ltype;
}
}
return DtoTypeNotVoid(type);
}
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
{
LLConstant* _init = 0; // may return zero
@@ -1266,7 +1320,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
else if (ExpInitializer* ex = init->isExpInitializer())
{
Logger::println("const expression initializer");
_init = DtoConstExpInit(loc, type, ex->exp);;
_init = DtoConstExpInit(loc, type, ex->exp);
}
else if (StructInitializer* si = init->isStructInitializer())
{
@@ -1282,7 +1336,7 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
else if (init->isVoidInitializer())
{
Logger::println("const void initializer");
LLType* ty = DtoType(type);
LLType* ty = DtoTypeNotVoid(type);
_init = LLConstant::getNullValue(ty);
}
else {
@@ -1797,4 +1851,3 @@ void callPostblit(Loc &loc, Expression *exp, LLValue *val)
}
}
#endif

View File

@@ -102,6 +102,7 @@ DValue* DtoDeclarationExp(Dsymbol* declaration);
LLValue* DtoRawVarDeclaration(VarDeclaration* var, LLValue* addr = 0);
// initializer helpers
LLType* DtoConstInitializerType(Type* type, Initializer* init);
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp);
DValue* DtoInitializer(LLValue* target, Initializer* init);

View File

@@ -184,7 +184,9 @@ size_t add_zeros(std::vector<llvm::Value*>& values, size_t diff)
return values.size() - n;
}
std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits)
std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd,
const std::vector<llvm::Value*>& inits,
bool isConst)
{
// get arrays
size_t nvars = sd->fields.dim;
@@ -268,7 +270,7 @@ std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, co
assert(nextVar == var);
// add any 0 padding needed before this field
if (os > lastoffset + lastsize)
if (!isConst && os > lastoffset + lastsize)
{
//printf("added %lu zeros\n", os - lastoffset - lastsize);
add_zeros(values, os - lastoffset - lastsize);

View File

@@ -10,7 +10,9 @@ void DtoResolveStruct(StructDeclaration* sd);
LLConstant* DtoConstStructInitializer(StructInitializer* si);
/// Build values for a struct literal.
std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits);
std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd,
const std::vector<llvm::Value*>& inits,
bool isConst = false);
/// Returns a boolean=true if the two structs are equal.
LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs);

View File

@@ -1168,7 +1168,7 @@ LLConstant* AddrExp::toConstElem(IRState* p)
vd->codegen(Type::sir);
LLConstant* llc = llvm::dyn_cast<LLConstant>(vd->ir.getIrValue());
assert(llc);
return llc;
return DtoBitCast(llc, DtoType(type));
}
// static function
else if (FuncDeclaration* fd = vexp->var->isFuncDeclaration())
@@ -2883,15 +2883,22 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
inits[i] = exprs[i]->toConstElem(p);
// vector of values to build aggregate from
std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits);
std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits, true);
// we know those values are constants.. cast them
std::vector<LLConstant*> constvals(values.size(), NULL);
for (size_t i = 0; i < values.size(); ++i)
std::vector<LLType*> types(values.size(), NULL);
for (size_t i = 0; i < values.size(); ++i) {
constvals[i] = llvm::cast<LLConstant>(values[i]);
types[i] = values[i]->getType();
}
// return constant struct
return LLConstantStruct::getAnon(gIR->context(), llvm::makeArrayRef(constvals), sd->ir.irStruct->packed);
if (!constType)
constType = LLStructType::get(gIR->context(), types);
else
constType->setBody(types);
return LLConstantStruct::get(constType, llvm::makeArrayRef(constvals));
}
//////////////////////////////////////////////////////////////////////////////////////////

View File

@@ -308,13 +308,6 @@ void IrStruct::addBaseClassInits(
inter_idx++;
}
}
// tail padding?
if (offset < base->structsize)
{
add_zeros(constants, base->structsize - offset);
offset = base->structsize;
}
}
//////////////////////////////////////////////////////////////////////////////
@@ -346,6 +339,10 @@ std::vector<llvm::Constant*> IrStruct::createClassDefaultInitializer()
// add data members recursively
addBaseClassInits(constants, cd, offset, field_index);
// tail padding?
if (offset < cd->structsize)
add_zeros(constants, cd->structsize - offset);
return constants;
}

View File

@@ -20,7 +20,7 @@
IrStruct::IrStruct(AggregateDeclaration* aggr)
: diCompositeType(NULL),
init_type(LLStructType::create(gIR->context(), std::string(aggr->toChars()) + "_init"))
init_type(LLStructType::create(gIR->context(), std::string(aggr->toPrettyChars()) + "_init"))
{
aggrdecl = aggr;
@@ -380,9 +380,22 @@ LLConstant * IrStruct::createStructInitializer(StructInitializer * si)
add_zeros(constants, diff);
}
// get initializer type
LLStructType* &ltype = si->ltype;
if (!ltype || ltype->isOpaque()) {
std::vector<LLConstant*>::iterator itr, end = constants.end();
std::vector<LLType*> types;
for (itr = constants.begin(); itr != end; ++itr)
types.push_back((*itr)->getType());
if (!ltype)
ltype = LLStructType::get(gIR->context(), types);
else
ltype->setBody(types);
}
// build constant
assert(!constants.empty());
llvm::Constant* c = LLConstantStruct::getAnon(gIR->context(), constants, packed);
llvm::Constant* c = LLConstantStruct::get(ltype, constants);
IF_LOG Logger::cout() << "final struct initializer: " << *c << std::endl;
return c;
}