mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 18:33:14 +01:00
Rewritten initialization of global variables.
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ StructInitializer::StructInitializer(Loc loc)
|
||||
: Initializer(loc)
|
||||
{
|
||||
ad = NULL;
|
||||
#if IN_LLVM
|
||||
ltype = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
Initializer *StructInitializer::syntaxCopy()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -114,6 +114,9 @@ StructInitializer::StructInitializer(Loc loc)
|
||||
: Initializer(loc)
|
||||
{
|
||||
ad = NULL;
|
||||
#if IN_LLVM
|
||||
ltype = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
Initializer *StructInitializer::syntaxCopy()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
15
gen/toir.cpp
15
gen/toir.cpp
@@ -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));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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* <ype = 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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user