Removed KDevelop3 project files, CMake can generate them just fine!

Fixed function literals in static initializers.
Changed alignment of delegates from 2*PTRSIZE to just PTRSIZE.
Changed errors to go to stderr instead of stdout.
Fairly major rewriting of struct/union/class handling, STILL A BIT BUGGY !!!
This commit is contained in:
Tomas Lindquist Olsen
2008-11-29 21:25:43 +01:00
parent 049e24cef8
commit f46f865375
47 changed files with 2101 additions and 2396 deletions
+36 -20
View File
@@ -208,6 +208,9 @@ void DtoSetArray(LLValue* arr, LLValue* dim, LLValue* ptr)
}
//////////////////////////////////////////////////////////////////////////////////////////
// FIXME: this looks like it could use a cleanup
LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
{
Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
@@ -241,6 +244,9 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
Type* arrnext = arrinittype->nextOf();
const LLType* elemty = DtoType(arrinittype->nextOf());
// true if there is a mismatch with one of the initializers
bool mismatch = false;
assert(arrinit->index.dim == arrinit->value.dim);
for (unsigned i=0,j=0; i < tdim; ++i)
{
@@ -292,23 +298,51 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
v = DtoConstInitializer(arrinit->loc, t->nextOf(), init);
assert(v);
// global arrays of unions might have type mismatch for each element
// if there is any mismatch at all, we need to use a struct instead :/
if (v->getType() != elemty)
mismatch = true;
inits[i] = v;
if (Logger::enabled())
Logger::cout() << "llval: " << *v << '\n';
}
Logger::println("building constant array");
LLConstant* constarr;
const LLArrayType* arrty = LLArrayType::get(elemty,tdim);
LLConstant* constarr = LLConstantArray::get(arrty, inits);
if (mismatch)
{
constarr = LLConstantStruct::get(inits);
}
else
{
constarr = LLConstantArray::get(arrty, inits);
}
#if 0
if (Logger::enabled())
{
Logger::cout() << "array type: " << *arrty << '\n';
size_t n = inits.size();
for (size_t i=0; i<n; i++)
Logger::cout() << " init " << i << " = " << *inits[i] << '\n';
}
#endif
if (arrinittype->ty == Tsarray)
return constarr;
else
assert(arrinittype->ty == Tarray);
LLGlobalVariable* gvar = new LLGlobalVariable(arrty,true,LLGlobalValue::InternalLinkage,constarr,".constarray",gIR->module);
LLGlobalVariable* gvar = new LLGlobalVariable(constarr->getType(),true,LLGlobalValue::InternalLinkage,constarr,".constarray",gIR->module);
LLConstant* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
gep = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(elemty));
return DtoConstSlice(DtoConstSize_t(tdim),gep);
}
@@ -794,24 +828,6 @@ LLValue* DtoDynArrayIs(TOK op, DValue* l, DValue* r)
return (op == TOKnotidentity) ? gIR->ir->CreateNot(res) : res;
}
//////////////////////////////////////////////////////////////////////////////////////////
LLConstant* DtoConstStaticArray(const LLType* t, LLConstant* c)
{
const LLArrayType* at = isaArray(t);
assert(at);
if (isaArray(at->getElementType()))
{
c = DtoConstStaticArray(at->getElementType(), c);
}
else {
assert(at->getElementType() == c->getType());
}
std::vector<LLConstant*> initvals;
initvals.resize(at->getNumElements(), c);
return llvm::ConstantArray::get(at, initvals);
}
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoArrayLen(DValue* v)
{
-1
View File
@@ -9,7 +9,6 @@ const llvm::ArrayType* DtoStaticArrayType(Type* sarrayTy);
LLConstant* DtoConstArrayInitializer(ArrayInitializer* si);
LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr);
LLConstant* DtoConstStaticArray(const LLType* t, LLConstant* c);
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);
+800 -684
View File
File diff suppressed because it is too large Load Diff
+17 -22
View File
@@ -97,16 +97,8 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, co
}
if (dVararg) {
ClassDeclaration* ti = Type::typeinfo;
ti->toObjFile(0); // TODO: multiobj
DtoForceConstInitDsymbol(ti);
assert(ti->ir.irStruct->constInit);
std::vector<const LLType*> types;
types.push_back(DtoSize_t());
types.push_back(getPtrToType(getPtrToType(ti->ir.irStruct->constInit->getType())));
const LLType* t1 = llvm::StructType::get(types);
paramvec.push_back(t1);
paramvec.push_back(getPtrToType(LLType::Int8Ty));
paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
paramvec.push_back(getVoidPtrType()); // _argptr
}
// number of formal params
@@ -286,7 +278,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
Logger::println("isMember = this is: %s", ad->type->toChars());
thisty = DtoType(ad->type);
//Logger::cout() << "this llvm type: " << *thisty << '\n';
if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get()))
if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->type->ir.type->get()))
thisty = getPtrToType(thisty);
}
else {
@@ -547,35 +539,36 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
}
// we never reference parameters of function prototypes
std::string str;
if (!declareOnly)
{
// name parameters
llvm::Function::arg_iterator iarg = func->arg_begin();
if (f->retInPtr) {
iarg->setName(".sretarg");
iarg->setName(".sret_arg");
fdecl->ir.irFunc->retArg = iarg;
++iarg;
}
if (f->usesThis) {
iarg->setName("this");
iarg->setName(".this_arg");
fdecl->ir.irFunc->thisArg = iarg;
assert(fdecl->ir.irFunc->thisArg);
++iarg;
}
else if (f->usesNest) {
iarg->setName(".nest");
iarg->setName(".nest_arg");
fdecl->ir.irFunc->nestArg = iarg;
assert(fdecl->ir.irFunc->nestArg);
++iarg;
}
if (f->linkage == LINKd && f->varargs == 1) {
iarg->setName("_arguments");
iarg->setName("._arguments");
fdecl->ir.irFunc->_arguments = iarg;
++iarg;
iarg->setName("_argptr");
iarg->setName("._argptr");
fdecl->ir.irFunc->_argptr = iarg;
++iarg;
}
@@ -597,7 +590,10 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
assert(!argvd->ir.irLocal);
argvd->ir.irLocal = new IrLocal(argvd);
argvd->ir.irLocal->value = iarg;
iarg->setName(argvd->ident->toChars());
str = argvd->ident->toChars();
str.append("_arg");
iarg->setName(str);
k++;
}
@@ -671,8 +667,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
if (fd->isMain())
gIR->emitMain = true;
std::string entryname("entry_");
entryname.append(fd->toPrettyChars());
std::string entryname("entry");
llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(entryname,func);
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endentry",func);
@@ -710,7 +705,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
LLValue* thisvar = irfunction->thisArg;
assert(thisvar);
LLValue* thismem = DtoAlloca(thisvar->getType(), ".this");
LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
DtoStore(thisvar, thismem);
irfunction->thisArg = thismem;
@@ -760,7 +755,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
if (!refout && (!DtoIsPassedByRef(vd->type) || lazy))
{
LLValue* a = irloc->value;
LLValue* v = DtoAlloca(a->getType(), "."+a->getName());
LLValue* v = DtoAlloca(a->getType(), vd->ident->toChars());
DtoStore(a,v);
irloc->value = v;
}
@@ -822,7 +817,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
assert(cd);
assert(cd->vthis);
src = DtoLoad(DtoGEPi(thisval, 0,2+cd->vthis->ir.irField->index, ".vthis"));
src = DtoLoad(DtoGEPi(thisval, 0,cd->vthis->ir.irField->index, ".vthis"));
}
DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
}
+1 -4
View File
@@ -23,6 +23,7 @@ struct FuncDeclaration;
struct Module;
struct TypeStruct;
struct BaseClass;
struct AnonDeclaration;
struct EnclosingHandler;
struct IrModule;
@@ -147,10 +148,6 @@ struct IRState
StructVector structs;
IrStruct* topstruct();
// classes TODO move into IRClass
typedef std::vector<ClassDeclaration*> ClassDeclVec;
ClassDeclVec classes;
// D main function
bool emitMain;
llvm::Function* mainFunc;
+73 -68
View File
@@ -338,7 +338,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
{
ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
LLValue* val = DtoLoad(irfunc->thisArg);
ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
ctx = DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
}
else
ctx = irfunc->nestArg;
@@ -374,7 +374,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
if (!cd || !cd->vthis)
return getNullPtr(getVoidPtrType());
LLValue* val = DtoLoad(irfunc->thisArg);
return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
return DtoLoad(DtoGEPi(val, 0,cd->vthis->ir.irField->index, ".vthis"));
}
else
{
@@ -964,73 +964,68 @@ void DtoConstInitGlobal(VarDeclaration* vd)
if (vd->ir.initialized) return;
vd->ir.initialized = gIR->dmodule;
Logger::println("* DtoConstInitGlobal(%s)", vd->toChars());
Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->locToChars());
LOG_SCOPE;
bool emitRTstaticInit = false;
// if the variable is a function local static variable with a runtime initializer
// we must do lazy initialization, which involves a boolean flag to make sure it happens only once
// FIXME: I don't think it's thread safe ...
LLConstant* _init = 0;
if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) {
_init = DtoConstInitializer(vd->loc, vd->type, NULL);
emitRTstaticInit = true;
}
else {
_init = DtoConstInitializer(vd->loc, vd->type, vd->init);
}
bool doLazyInit = false;
Dsymbol* par = vd->toParent2();
const LLType* _type = DtoType(vd->type);
Type* t = vd->type->toBasetype();
//Logger::cout() << "initializer: " << *_init << '\n';
if (_type != _init->getType()) {
if (Logger::enabled())
Logger::cout() << "got type '" << *_init->getType() << "' expected '" << *_type << "'\n";
// zero initalizer
if (_init->isNullValue())
_init = llvm::Constant::getNullValue(_type);
// pointer to global constant (struct.init)
else if (llvm::isa<llvm::GlobalVariable>(_init))
if (par && par->isFuncDeclaration() && vd->init)
{
if (ExpInitializer* einit = vd->init->isExpInitializer())
{
assert(_init->getType()->getContainedType(0) == _type);
llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init);
assert(t->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)t;
assert(ts->sym->ir.irStruct->constInit);
_init = ts->sym->ir.irStruct->constInit;
}
// array single value init
else if (isaArray(_type))
{
_init = DtoConstStaticArray(_type, _init);
}
else {
if (Logger::enabled())
Logger::cout() << "Unexpected initializer type: " << *_type << '\n';
//assert(0);
if (!einit->exp->isConst())
{
// mark as needing lazy now
doLazyInit = true;
}
}
}
// if we do lazy init, we start out with an undefined initializer
LLConstant* initVal;
if (doLazyInit)
{
initVal = llvm::UndefValue::get(DtoType(vd->type));
}
// otherwise we build it
else
{
initVal = DtoConstInitializer(vd->loc, vd->type, vd->init);
}
// set the initializer if appropriate
IrGlobal* glob = vd->ir.irGlobal;
llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(glob->value);
// refine the global's opaque type to the type of the initializer
llvm::cast<LLOpaqueType>(glob->type.get())->refineAbstractTypeTo(initVal->getType());
glob->constInit = initVal;
bool istempl = false;
if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) {
istempl = true;
}
if (_init && _init->getType() != _type)
_type = _init->getType();
llvm::cast<LLOpaqueType>(vd->ir.irGlobal->type.get())->refineAbstractTypeTo(_type);
_type = vd->ir.irGlobal->type.get();
// assign the initializer
llvm::GlobalVariable* globalvar = llvm::cast<llvm::GlobalVariable>(glob->value);
llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->ir.irGlobal->value);
if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
{
if (Logger::enabled())
{
Logger::println("setting initializer");
Logger::cout() << "global: " << *gvar << '\n';
Logger::cout() << "init: " << *_init << '\n';
Logger::cout() << "init: " << *initVal << '\n';
}
gvar->setInitializer(_init);
gvar->setInitializer(initVal);
// do debug info
if (global.params.symdebug)
{
@@ -1040,8 +1035,8 @@ void DtoConstInitGlobal(VarDeclaration* vd)
}
}
if (emitRTstaticInit)
DtoLazyStaticInit(istempl, gvar, vd->init, t);
if (doLazyInit)
DtoLazyStaticInit(istempl, gvar, vd->init, vd->type);
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1396,18 +1391,18 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var)
// INITIALIZER HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/
LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init)
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
{
LLConstant* _init = 0; // may return zero
if (!init)
{
Logger::println("const default initializer for %s", type->toChars());
_init = DtoDefaultInit(loc, type);
_init = DtoConstExpInit(loc, type, type->defaultInit());
}
else if (ExpInitializer* ex = init->isExpInitializer())
{
Logger::println("const expression initializer");
_init = ex->exp->toConstElem(gIR);
_init = DtoConstExpInit(loc, type, ex->exp);;
}
else if (StructInitializer* si = init->isStructInitializer())
{
@@ -1433,7 +1428,7 @@ LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init)
//////////////////////////////////////////////////////////////////////////////////////////
LLConstant* DtoConstFieldInitializer(Loc& loc, Type* t, Initializer* init)
LLConstant* DtoConstFieldInitializer(Loc loc, Type* t, Initializer* init)
{
Logger::println("DtoConstFieldInitializer");
LOG_SCOPE;
@@ -1530,20 +1525,33 @@ DValue* DtoInitializer(LLValue* target, Initializer* init)
static LLConstant* expand_to_sarray(Type *base, Expression* exp)
{
Logger::println("building type %s to expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
Logger::println("building type %s from expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars());
const LLType* dstTy = DtoType(base);
if (Logger::enabled())
Logger::cout() << "final llvm type requested: " << *dstTy << '\n';
LLConstant* val = exp->toConstElem(gIR);
Type* expbase = exp->type->toBasetype();
Type* t = base;
Logger::println("expbase: %s", expbase->toChars());
Type* t = base->toBasetype();
LLSmallVector<size_t, 4> dims;
// handle zero initializers
if (expbase->isintegral() && exp->isConst())
{
if (!exp->toInteger())
return LLConstant::getNullValue(dstTy);
}
else if (exp->op == TOKnull)
{
return LLConstant::getNullValue(dstTy);
}
while(1)
{
Logger::println("t: %s", t->toChars());
if (t->equals(expbase))
break;
assert(t->ty == Tsarray);
@@ -1552,7 +1560,7 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
assert(t->nextOf());
t = t->nextOf()->toBasetype();
}
size_t i = dims.size();
assert(i);
@@ -1564,17 +1572,15 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
inits.insert(inits.end(), dims[i], val);
val = LLConstantArray::get(arrty, inits);
}
return val;
}
LLConstant* DtoDefaultInit(Loc& loc, Type* type)
LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp)
{
Expression* exp = type->defaultInit();
Type* expbase = exp->type->toBasetype();
Type* base = type->toBasetype();
// if not the same basetypes, we won't get the same llvm types either
if (!expbase->equals(base))
{
@@ -1584,7 +1590,6 @@ LLConstant* DtoDefaultInit(Loc& loc, Type* type)
error(loc, "static arrays of voids have no default initializer");
fatal();
}
Logger::println("type is a static array, building constant array initializer to single value");
return expand_to_sarray(base, exp);
}
@@ -1594,9 +1599,8 @@ LLConstant* DtoDefaultInit(Loc& loc, Type* type)
fatal();
}
assert(0);
}
return exp->toConstElem(gIR);
}
@@ -1615,6 +1619,7 @@ void DtoAnnotation(const char* str)
++p;
}
// create a noop with the code as the result name!
// FIXME: this is const folded and eliminated immediately ... :/
gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str());
}
+3 -5
View File
@@ -86,8 +86,9 @@ DValue* DtoDeclarationExp(Dsymbol* declaration);
LLValue* DtoRawVarDeclaration(VarDeclaration* var);
// initializer helpers
LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init);
LLConstant* DtoConstFieldInitializer(Loc& loc, Type* type, Initializer* init);
LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
LLConstant* DtoConstFieldInitializer(Loc loc, Type* type, Initializer* init);
LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp);
DValue* DtoInitializer(LLValue* target, Initializer* init);
// annotation generator
@@ -108,9 +109,6 @@ DValue* DtoBinRem(Type* resulttype, DValue* lhs, DValue* rhs);
// target stuff
void findDefaultTarget();
/// get the default initializer of the type
LLConstant* DtoDefaultInit(Loc& loc, Type* t);
// fixup an overloaded intrinsic name string
void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name);
+13 -3
View File
@@ -134,8 +134,10 @@ static const LLType* rt_dg2()
static void LLVM_D_BuildRuntimeModule()
{
Logger::println("building module");
M = new llvm::Module("ldc internal runtime");
Logger::println("building basic types");
const LLType* voidTy = LLType::VoidTy;
const LLType* boolTy = LLType::Int1Ty;
const LLType* byteTy = LLType::Int8Ty;
@@ -144,6 +146,7 @@ static void LLVM_D_BuildRuntimeModule()
const LLType* longTy = LLType::Int64Ty;
const LLType* sizeTy = DtoSize_t();
Logger::println("building float types");
const LLType* floatTy = LLType::FloatTy;
const LLType* doubleTy = LLType::DoubleTy;
const LLType* realTy;
@@ -156,15 +159,22 @@ static void LLVM_D_BuildRuntimeModule()
const LLType* cdoubleTy = llvm::StructType::get(doubleTy, doubleTy, NULL);
const LLType* crealTy = llvm::StructType::get(realTy, realTy, NULL);
Logger::println("building aggr types");
const LLType* voidPtrTy = rt_ptr(byteTy);
const LLType* stringTy = rt_array(byteTy);
const LLType* wstringTy = rt_array(shortTy);
const LLType* dstringTy = rt_array(intTy);
const LLType* objectTy = rt_ptr(ClassDeclaration::object->type->ir.type->get());
const LLType* classInfoTy = rt_ptr(ClassDeclaration::classinfo->type->ir.type->get());
const LLType* typeInfoTy = rt_ptr(Type::typeinfo->type->ir.type->get());
Logger::println("building class types");
const LLType* objectTy = DtoType(ClassDeclaration::object->type);
const LLType* classInfoTy = DtoType(ClassDeclaration::classinfo->type);
const LLType* typeInfoTy = DtoType(Type::typeinfo->type);
Logger::println("building aa type");
const LLType* aaTy = rt_ptr(llvm::OpaqueType::get());
Logger::println("building functions");
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
+1 -1
View File
@@ -897,7 +897,7 @@ void UnrolledLoopStatement::toIR(IRState* p)
DtoDwarfStopPoint(loc.linnum);
// DMD doesn't fold stuff like continue/break, and since this isn't really a loop
// we have to keep track of each statement and jump to next the next/end on continue/break
// we have to keep track of each statement and jump to the next/end on continue/break
llvm::BasicBlock* oldend = gIR->scopeend();
+335 -346
View File
@@ -18,36 +18,279 @@
#include "ir/irstruct.h"
//////////////////////////////////////////////////////////////////////////////////////////
void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset); // defined in irstruct.cpp
// pair of var and its init
typedef std::pair<VarDeclaration*,Initializer*> VarInitPair;
// comparison func for qsort
static int varinit_offset_cmp_func(const void* p1, const void* p2)
{
VarDeclaration* v1 = ((VarInitPair*)p1)->first;
VarDeclaration* v2 = ((VarInitPair*)p2)->first;
if (v1->offset < v2->offset)
return -1;
else if (v1->offset > v2->offset)
return 1;
else
return 0;
}
/*
this uses a simple algorithm to build the correct constant
(1) first sort the explicit initializers by offset... well, DMD doesn't :)
(2) if there is NO space before the next explicit initializeer, goto (9)
(3) find the next default initializer that fits before it, if NOT found goto (7)
(4) insert zero padding up to the next default initializer
(5) insert the next default initializer
(6) goto (2)
(7) insert zero padding up to the next explicit initializer
(9) insert the next explicit initializer
(10) goto (2)
(11) done
(next can be the end too)
*/
// return the next default initializer to use or null
static VarDeclaration* nextDefault(IrStruct* irstruct, size_t& idx, size_t pos, size_t offset)
{
IrStruct::VarDeclVector& defaults = irstruct->defVars;
size_t ndefaults = defaults.size();
// for each valid index
while(idx < ndefaults)
{
VarDeclaration* v = defaults[idx];
// skip defaults before pos
if (v->offset < pos)
{
idx++;
continue;
}
// this var default fits
if (v->offset >= pos && v->offset + v->type->size() <= offset)
return v;
// not usable
break;
}
// not usable
return NULL;
}
LLConstant* DtoConstStructInitializer(StructInitializer* si)
{
Logger::println("DtoConstStructInitializer: %s", si->toChars());
LOG_SCOPE;
// get TypeStruct
assert(si->ad);
TypeStruct* ts = (TypeStruct*)si->ad->type;
DtoResolveDsymbol(si->ad);
// force constant initialization of the symbol
DtoForceConstInitDsymbol(si->ad);
// get formal type
const llvm::StructType* structtype = isaStruct(ts->ir.type->get());
// log it
if (Logger::enabled())
Logger::cout() << "llvm struct type: " << *structtype << '\n';
// sanity check
assert(si->value.dim > 0);
assert(si->value.dim == si->vars.dim);
std::vector<DUnionIdx> inits;
for (int i = 0; i < si->value.dim; ++i)
// vector of final initializer constants
std::vector<LLConstant*> inits;
// get the ir struct
IrStruct* irstruct = si->ad->ir.irStruct;
// get default fields
IrStruct::VarDeclVector& defaults = irstruct->defVars;
size_t ndefaults = defaults.size();
// make sure si->vars is sorted by offset
std::vector<VarInitPair> vars;
size_t nvars = si->vars.dim;
vars.resize(nvars);
// fill pair vector
for (size_t i = 0; i < nvars; i++)
{
VarDeclaration* var = (VarDeclaration*)si->vars.data[i];
Initializer* ini = (Initializer*)si->value.data[i];
assert(var);
assert(ini);
VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
assert(vd);
LLConstant* v = DtoConstInitializer(vd->loc, vd->type, ini);
inits.push_back(DUnionIdx(vd->ir.irField->index, vd->ir.irField->indexOffset, v));
vars[i] = std::make_pair(var, ini);
}
// sort it
qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
// check integrity
// and do error checking, since the frontend does verify static struct initializers
size_t lastoffset = 0;
size_t lastsize = 0;
bool overlap = false;
for (size_t i=0; i < nvars; i++)
{
// next explicit init var
VarDeclaration* var = vars[i].first;
Logger::println("var = %s : +%u", var->toChars(), var->offset);
// I would have thought this to be a frontend check
for (size_t j=i+1; j<nvars; j++)
{
if (j == i)
continue;
VarDeclaration* var2 = vars[j].first;
if (var2->offset >= var->offset && var2->offset < var->offset + var->type->size())
{
fprintf(stdmsg, "Error: %s: initializer '%s' overlaps with '%s'\n", si->loc.toChars(), var->toChars(), var2->toChars());
overlap = true;
}
}
// update offsets
lastoffset = var->offset;
lastsize = var->type->size();
}
DtoConstInitStruct((StructDeclaration*)si->ad);
return si->ad->ir.irStruct->dunion->getConst(inits);
// error handling, report all overlaps before aborting
if (overlap)
{
error("%s: overlapping union initializers", si->loc.toChars());
}
// go through each explicit initalizer, falling back to defaults or zeros when necessary
lastoffset = 0;
lastsize = 0;
size_t j=0; // defaults
for (size_t i=0; i < nvars; i++)
{
// get var and init
VarDeclaration* var = vars[i].first;
Initializer* ini = vars[i].second;
size_t offset = var->offset;
size_t size = var->type->size();
// if there is space before the next explicit initializer
Lpadding:
size_t pos = lastoffset+lastsize;
if (offset > pos)
{
// find the the next default initializer that fits in this space
VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, offset);
// found
if (nextdef)
{
// need zeros before the default
if (nextdef->offset > pos)
{
Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
addZeros(inits, pos, nextdef->offset);
}
// do the default
Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
LLConstant* c = nextdef->ir.irField->constInit;
inits.push_back(c);
// update offsets
lastoffset = nextdef->offset;
lastsize = nextdef->type->size();
// check if more defaults would fit
goto Lpadding;
}
// not found, pad with zeros
else
{
Logger::println("inserting %lu byte padding at %lu", offset - pos, pos);
addZeros(inits, pos, offset);
// offsets are updated by the explicit initializer
}
}
// insert next explicit
Logger::println("adding explicit field: %s : +%lu", var->toChars(), offset);
LOG_SCOPE;
LLConstant* c = DtoConstInitializer(var->loc, var->type, ini);
inits.push_back(c);
lastoffset = offset;
lastsize = size;
}
// there might still be padding after the last one, make sure that is defaulted/zeroed as well
size_t structsize = getABITypeSize(structtype);
// if there is space before the next explicit initializer
// FIXME: this should be handled in the loop above as well
Lpadding2:
size_t pos = lastoffset+lastsize;
if (structsize > pos)
{
// find the the next default initializer that fits in this space
VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, structsize);
// found
if (nextdef)
{
// need zeros before the default
if (nextdef->offset > pos)
{
Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
addZeros(inits, pos, nextdef->offset);
}
// do the default
Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
LLConstant* c = nextdef->ir.irField->constInit;
inits.push_back(c);
// update offsets
lastoffset = nextdef->offset;
lastsize = nextdef->type->size();
// check if more defaults would fit
goto Lpadding2;
}
// not found, pad with zeros
else
{
Logger::println("inserting %lu byte padding at %lu", structsize - pos, pos);
addZeros(inits, pos, structsize);
lastoffset = pos;
lastsize = structsize - pos;
}
}
assert(lastoffset+lastsize == structsize);
// make the constant struct
LLConstant* c = LLConstantStruct::get(inits, si->ad->ir.irStruct->packed);
if (Logger::enabled())
{
Logger::cout() << "constant struct initializer: " << *c << '\n';
}
assert(getABITypeSize(c->getType()) == structsize);
return c;
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -61,17 +304,26 @@ LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
IrField* field = vd->ir.irField;
assert(field);
unsigned idx = field->index;
unsigned off = field->indexOffset;
// get the start pointer
const LLType* st = getPtrToType(DtoType(sd->type));
// cast to the formal struct type
src = DtoBitCast(src, st);
LLValue* val = DtoGEPi(src, 0,idx);
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
// gep to the index
LLValue* val = DtoGEPi(src, 0, field->index);
if (off)
val = DtoGEPi1(val, off);
// do we need to offset further? (union area)
if (field->unionOffset)
{
// cast to void*
val = DtoBitCast(val, getVoidPtrType());
// offset
val = DtoGEPi1(val, field->unionOffset);
}
// cast it to the right type
val = DtoBitCast(val, getPtrToType(DtoType(vd->type)));
if (Logger::enabled())
Logger::cout() << "value: " << *val << '\n';
@@ -79,46 +331,46 @@ LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
return val;
}
//////////////////////////////////////////////////////////////////////////////////////////
void DtoResolveStruct(StructDeclaration* sd)
{
// don't do anything if already been here
if (sd->ir.resolved) return;
// make sure above works :P
sd->ir.resolved = true;
Logger::println("DtoResolveStruct(%s): %s", sd->toChars(), sd->loc.toChars());
// log what we're doing
Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
LOG_SCOPE;
TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
// get the DMD TypeStruct
TypeStruct* ts = (TypeStruct*)sd->type;
// this struct is a forward declaration
// create the IrStruct
IrStruct* irstruct = new IrStruct(sd);
sd->ir.irStruct = irstruct;
// create the type
ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
// handle forward declaration structs (opaques)
// didn't even know D had those ...
if (sd->sizeok != 1)
{
sd->ir.irStruct = new IrStruct(ts);
ts->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
// nothing more to do
return;
}
bool ispacked = (ts->alignsize() == 1);
// create the IrStruct
IrStruct* irstruct = new IrStruct(ts);
sd->ir.irStruct = irstruct;
// make this struct current
gIR->structs.push_back(irstruct);
// add fields
Array* fields = &sd->fields;
for (int k=0; k < fields->dim; k++)
{
VarDeclaration* v = (VarDeclaration*)fields->data[k];
Logger::println("Adding field: %s %s", v->type->toChars(), v->toChars());
// init fields, used to happen in VarDeclaration::toObjFile
irstruct->addField(v);
}
// get some info
bool ispacked = (ts->alignsize() == 1);
bool isunion = sd->isUnionDeclaration();
// set irstruct info
irstruct->packed = ispacked;
// defined in this module?
bool thisModule = false;
if (sd->getModule() == gIR->dmodule)
thisModule = true;
@@ -127,21 +379,29 @@ void DtoResolveStruct(StructDeclaration* sd)
Array* arr = sd->members;
for (int k=0; k < arr->dim; k++) {
Dsymbol* s = (Dsymbol*)arr->data[k];
if (FuncDeclaration* fd = s->isFuncDeclaration()) {
if (thisModule || (fd->prot() != PROTprivate)) {
fd->toObjFile(0); // TODO: multiobj
}
}
else if (s->isAttribDeclaration() ||
s->isVarDeclaration() ||
s->isTemplateMixin()) {
s->toObjFile(0); // TODO: multiobj
}
else {
Logger::println("Ignoring dsymbol '%s' in this->members of kind '%s'", s->toPrettyChars(), s->kind());
}
s->toObjFile(0);
}
const LLType* ST = irstruct->build();
#if 0
std::cout << sd->kind() << ' ' << sd->toPrettyChars() << " type: " << *ST << '\n';
// add fields
for (int k=0; k < fields->dim; k++)
{
VarDeclaration* v = (VarDeclaration*)fields->data[k];
printf(" field: %s %s\n", v->type->toChars(), v->toChars());
printf(" index: %u offset: %u\n", v->ir.irField->index, v->ir.irField->unionOffset);
}
unsigned llvmSize = (unsigned)getABITypeSize(ST);
unsigned dmdSize = (unsigned)sd->type->size();
printf(" llvm size: %u dmd size: %u\n", llvmSize, dmdSize);
assert(llvmSize == dmdSize);
#endif
/*for (int k=0; k < sd->members->dim; k++) {
Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
dsym->toObjFile();
@@ -149,98 +409,13 @@ void DtoResolveStruct(StructDeclaration* sd)
Logger::println("doing struct fields");
const llvm::StructType* structtype = 0;
std::vector<const LLType*> fieldtypes;
if (irstruct->offsets.empty())
{
Logger::println("has no fields");
fieldtypes.push_back(LLType::Int8Ty);
structtype = llvm::StructType::get(fieldtypes, ispacked);
}
else
{
Logger::println("has fields");
unsigned prevsize = (unsigned)-1;
unsigned lastoffset = (unsigned)-1;
const LLType* fieldtype = NULL;
VarDeclaration* fieldinit = NULL;
size_t fieldpad = 0;
int idx = 0;
for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
// first iteration
if (lastoffset == (unsigned)-1) {
lastoffset = i->first;
assert(lastoffset == 0);
fieldtype = i->second.type;
fieldinit = i->second.var;
prevsize = fieldinit->type->size();
i->second.var->ir.irField->index = idx;
}
// colliding offset?
else if (lastoffset == i->first) {
size_t s = i->second.var->type->size();
if (s > prevsize) {
fieldpad += s - prevsize;
prevsize = s;
}
sd->ir.irStruct->hasUnions = true;
i->second.var->ir.irField->index = idx;
}
// intersecting offset?
else if (i->first < (lastoffset + prevsize)) {
size_t s = i->second.var->type->size();
assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size
sd->ir.irStruct->hasUnions = true;
i->second.var->ir.irField->index = idx;
i->second.var->ir.irField->indexOffset = (i->first - lastoffset) / s;
}
// fresh offset
else {
// commit the field
fieldtypes.push_back(fieldtype);
irstruct->defaultFields.push_back(fieldinit);
if (fieldpad) {
fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
irstruct->defaultFields.push_back(NULL);
idx++;
}
idx++;
// start new
lastoffset = i->first;
fieldtype = i->second.type;
fieldinit = i->second.var;
prevsize = fieldinit->type->size();
i->second.var->ir.irField->index = idx;
fieldpad = 0;
}
}
fieldtypes.push_back(fieldtype);
irstruct->defaultFields.push_back(fieldinit);
if (fieldpad) {
fieldtypes.push_back(llvm::ArrayType::get(LLType::Int8Ty, fieldpad));
irstruct->defaultFields.push_back(NULL);
}
Logger::println("creating struct type");
structtype = llvm::StructType::get(fieldtypes, ispacked);
}
// refine abstract types for stuff like: struct S{S* next;}
if (irstruct->recty != 0)
{
llvm::PATypeHolder& pa = irstruct->recty;
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(structtype);
structtype = isaStruct(pa.get());
}
assert(ts->ir.type == 0);
ts->ir.type = new llvm::PATypeHolder(structtype);
llvm::cast<llvm::OpaqueType>(ts->ir.type->get())->refineAbstractTypeTo(ST);
ST = ts->ir.type->get();
// name type
if (sd->parent->isModule()) {
gIR->module->addTypeName(sd->mangle(),structtype);
gIR->module->addTypeName(sd->mangle(),ST);
}
gIR->structs.pop_back();
@@ -265,7 +440,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
initname.append("6__initZ");
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->ir.type->get(), true, _linkage, NULL, initname, gIR->module);
llvm::GlobalVariable* initvar = new llvm::GlobalVariable(sd->ir.irStruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
sd->ir.irStruct->init = initvar;
gIR->constInitList.push_back(sd);
@@ -286,59 +461,33 @@ void DtoConstInitStruct(StructDeclaration* sd)
IrStruct* irstruct = sd->ir.irStruct;
gIR->structs.push_back(irstruct);
// make sure each offset knows its default initializer
for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i)
{
IrStruct::Offset* so = &i->second;
LLConstant* finit = DtoConstFieldInitializer(so->var->loc, so->var->type, so->var->init);
so->init = finit;
so->var->ir.irField->constInit = finit;
}
const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
// go through the field inits and build the default initializer
std::vector<LLConstant*> fieldinits_ll;
size_t nfi = irstruct->defaultFields.size();
for (size_t i=0; i<nfi; ++i) {
LLConstant* c;
if (irstruct->defaultFields[i] != NULL) {
c = irstruct->defaultFields[i]->ir.irField->constInit;
assert(c);
}
else {
const llvm::ArrayType* arrty = isaArray(structtype->getElementType(i));
std::vector<LLConstant*> vals(arrty->getNumElements(), llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
c = llvm::ConstantArray::get(arrty, vals);
}
fieldinits_ll.push_back(c);
// make sure each offset knows its default initializer
Array* fields = &sd->fields;
for (int k=0; k < fields->dim; k++)
{
VarDeclaration* v = (VarDeclaration*)fields->data[k];
LLConstant* finit = DtoConstFieldInitializer(v->loc, v->type, v->init);
v->ir.irField->constInit = finit;
}
// generate the union mapper
sd->ir.irStruct->dunion = new DUnion(); // uses gIR->topstruct()
// always generate the constant initalizer
if (!sd->zeroInit) {
Logger::println("Not zero initialized");
#if 0
//assert(tk == gIR->gIR->topstruct()().size());
#ifndef LLVMD_NO_LOGGER
Logger::cout() << "struct type: " << *structtype << '\n';
for (size_t k=0; k<fieldinits_ll.size(); ++k) {
Logger::cout() << "Type:" << '\n';
Logger::cout() << *fieldinits_ll[k]->getType() << '\n';
Logger::cout() << "Value:" << '\n';
Logger::cout() << *fieldinits_ll[k] << '\n';
}
Logger::cout() << "Initializer printed" << '\n';
#endif
#endif
sd->ir.irStruct->constInit = llvm::ConstantStruct::get(structtype,fieldinits_ll);
}
else {
if (sd->zeroInit)
{
Logger::println("Zero initialized");
sd->ir.irStruct->constInit = llvm::ConstantAggregateZero::get(structtype);
irstruct->constInit = llvm::ConstantAggregateZero::get(structtype);
}
else
{
Logger::println("Not zero initialized");
LLConstant* c = irstruct->buildDefaultConstInit();
irstruct->constInit = c;
}
// refine __initZ global type to the one of the initializer
llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
gIR->structs.pop_back();
@@ -385,163 +534,3 @@ LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs)
LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp");
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////// D UNION HELPER CLASS ////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
DUnion::DUnion()
{
DUnionField* f = NULL;
IrStruct* topstruct = gIR->topstruct();
bool unions = false;
for (IrStruct::OffsetMap::iterator i=topstruct->offsets.begin(); i!=topstruct->offsets.end(); ++i)
{
unsigned o = i->first;
IrStruct::Offset* so = &i->second;
const LLType* ft = so->init->getType();
size_t sz = getABITypeSize(ft);
if (f == NULL) { // new field
fields.push_back(DUnionField());
f = &fields.back();
f->size = sz;
f->offset = o;
f->init = so->init;
f->initsize = sz;
f->types.push_back(ft);
}
else if (o == f->offset) { // same offset
if (sz > f->size)
f->size = sz;
f->types.push_back(ft);
unions = true;
}
else if (o < f->offset+f->size) {
assert((o+sz) <= (f->offset+f->size));
unions = true;
}
else {
fields.push_back(DUnionField());
f = &fields.back();
f->size = sz;
f->offset = o;
f->init = so->init;
f->initsize = sz;
f->types.push_back(ft);
}
}
ispacked = topstruct->packed;
/*{
LOG_SCOPE;
Logger::println("******** DUnion BEGIN");
size_t n = fields.size();
for (size_t i=0; i<n; ++i) {
Logger::cout()<<"field #"<<i<<" offset: "<<fields[i].offset<<" size: "<<fields[i].size<<'('<<fields[i].initsize<<")\n";
LOG_SCOPE;
size_t nt = fields[i].types.size();
for (size_t j=0; j<nt; ++j) {
Logger::cout()<<*fields[i].types[j]<<'\n';
}
}
Logger::println("******** DUnion END");
}*/
}
static void push_nulls(size_t nbytes, std::vector<LLConstant*>& out)
{
assert(nbytes > 0);
std::vector<LLConstant*> i(nbytes, llvm::ConstantInt::get(LLType::Int8Ty, 0, false));
out.push_back(llvm::ConstantArray::get(llvm::ArrayType::get(LLType::Int8Ty, nbytes), i));
}
LLConstant* DUnion::getConst(std::vector<DUnionIdx>& in)
{
std::sort(in.begin(), in.end());
std::vector<LLConstant*> out;
size_t nin = in.size();
size_t nfields = fields.size();
size_t fi = 0;
size_t last = 0;
size_t ii = 0;
size_t os = 0;
for(;;)
{
if (fi == nfields) break;
bool nextSame = (ii+1 < nin) && (in[ii+1].idx == fi);
if (ii < nin && fi == in[ii].idx)
{
size_t s = getABITypeSize(in[ii].c->getType());
if (in[ii].idx == last)
{
size_t nos = in[ii].idxos * s;
if (nos && nos-os) {
assert(nos >= os);
push_nulls(nos-os, out);
}
os = nos + s;
}
else
{
os = s;
}
out.push_back(in[ii].c);
ii++;
if (!nextSame)
{
if (os < fields[fi].size)
push_nulls(fields[fi].size - os, out);
os = 0;
last = fi++;
}
continue;
}
// default initialize if necessary
if (ii == nin || fi < in[ii].idx)
{
DUnionField& f = fields[fi];
out.push_back(f.init);
if (f.initsize < f.size)
push_nulls(f.size - f.initsize, out);
last = fi++;
os = 0;
continue;
}
}
std::vector<const LLType*> tys;
size_t nout = out.size();
for (size_t i=0; i<nout; ++i)
tys.push_back(out[i]->getType());
const llvm::StructType* st = llvm::StructType::get(tys, ispacked);
return llvm::ConstantStruct::get(st, out);
}
-39
View File
@@ -33,43 +33,4 @@ LLValue* DtoStructEquals(TOK op, DValue* lhs, DValue* rhs);
// index a struct one level
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd);
struct DUnionField
{
unsigned offset;
size_t size;
std::vector<const LLType*> types;
LLConstant* init;
size_t initsize;
DUnionField() {
offset = 0;
size = 0;
init = NULL;
initsize = 0;
}
};
struct DUnionIdx
{
unsigned idx,idxos;
LLConstant* c;
DUnionIdx()
: idx(0), c(0) {}
DUnionIdx(unsigned _idx, unsigned _idxos, LLConstant* _c)
: idx(_idx), idxos(_idxos), c(_c) {}
bool operator<(const DUnionIdx& i) const {
return (idx < i.idx) || (idx == i.idx && idxos < i.idxos);
}
};
class DUnion
{
std::vector<DUnionField> fields;
bool ispacked;
public:
DUnion();
LLConstant* getConst(std::vector<DUnionIdx>& in);
};
#endif
+3 -3
View File
@@ -41,11 +41,12 @@ unsigned DtoCallingConv(LINK l)
{
//TODO: StdCall is not a good base on Windows due to extra name mangling
// applied there
if (global.params.cpu == ARCHx86 && global.params.os != OSWindows)
return llvm::CallingConv::X86_StdCall;
if (global.params.cpu == ARCHx86)
return (global.params.os != OSWindows) ? llvm::CallingConv::X86_StdCall : llvm::CallingConv::C;
else
return llvm::CallingConv::Fast;
}
// on the other hand, here, it's exactly what we want!!! TODO: right?
else if (l == LINKwindows)
return llvm::CallingConv::X86_StdCall;
else
@@ -155,7 +156,6 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::Attribut
}
// build type info array
assert(Type::typeinfo->ir.irStruct->constInit);
const LLType* typeinfotype = DtoType(Type::typeinfo->type);
const LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype,vtype->getNumElements());
+11 -6
View File
@@ -452,14 +452,19 @@ static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* co
definedCU = DtoDwarfCompileUnit(sd->getModule());
std::vector<LLConstant*> elems;
elems.reserve(ir->offsets.size());
for (IrStruct::OffsetMap::iterator i=ir->offsets.begin(); i!=ir->offsets.end(); ++i)
if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
{
unsigned offset = i->first;
IrStruct::Offset& o = i->second;
std::vector<VarDeclaration*>& arr = ir->varDecls;
size_t narr = arr.size();
elems.reserve(narr);
for (int k=0; k<narr; k++)
{
VarDeclaration* vd = arr[k];
assert(vd);
LLGlobalVariable* ptr = dwarfMemberType(o.var->loc.linnum, o.var->type, compileUnit, definedCU, o.var->toChars(), offset);
elems.push_back(DBG_CAST(ptr));
LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset);
elems.push_back(DBG_CAST(ptr));
}
}
const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size());
+148 -67
View File
@@ -135,20 +135,27 @@ DValue* VarExp::toElem(IRState* p)
}
else {
Logger::println("a normal variable");
// take care of forward references of global variables
if (vd->isDataseg() || (vd->storage_class & STCextern)) {
vd->toObjFile(0); // TODO: multiobj
}
if (!vd->ir.isSet() || !vd->ir.getIrValue()) {
LLValue* val;
if (!vd->ir.isSet() || !(val = vd->ir.getIrValue())) {
error("variable %s not resolved", vd->toChars());
if (Logger::enabled())
Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n';
fatal();
}
if (vd->isDataseg() || (vd->storage_class & STCextern)) {
DtoConstInitGlobal(vd);
val = DtoBitCast(val, DtoType(type->pointerTo()));
}
return new DVarValue(type, vd, vd->ir.getIrValue());
return new DVarValue(type, vd, val);
}
}
else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
@@ -369,7 +376,7 @@ DValue* StringExp::toElem(IRState* p)
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
if (Logger::enabled())
Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n';
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".stringliteral",gIR->module);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,".str",gIR->module);
llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
LLConstant* idxs[2] = { zero, zero };
@@ -443,7 +450,7 @@ LLConstant* StringExp::toConstElem(IRState* p)
}
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".stringliteral",gIR->module);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_init->getType(),true,_linkage,_init,".str",gIR->module);
llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
LLConstant* idxs[2] = { zero, zero };
@@ -1008,19 +1015,21 @@ DValue* DotVarExp::toElem(IRState* p)
assert(fdecl->vtblIndex > 0);
assert(e1type->ty == Tclass);
LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false);
LLValue* zero = DtoConstUint(0);
size_t vtblidx = fdecl->vtblIndex;
if (Logger::enabled())
Logger::cout() << "vthis: " << *vthis << '\n';
funcval = DtoGEP(vthis, zero, zero);
funcval = vthis;
if (!fdecl->isMember2()->isInterfaceDeclaration())
funcval = DtoGEP(funcval, zero, zero);
funcval = DtoLoad(funcval);
funcval = DtoGEP(funcval, zero, vtblidx, toChars());
Logger::println("vtblidx = %lu", vtblidx);
funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
funcval = DtoLoad(funcval);
#if OPAQUE_VTBLS
funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
if (Logger::enabled())
Logger::cout() << "funcval casted: " << *funcval << '\n';
#endif
}
// static call
else {
@@ -2143,6 +2152,22 @@ DValue* FuncExp::toElem(IRState* p)
//////////////////////////////////////////////////////////////////////////////////////////
LLConstant* FuncExp::toConstElem(IRState* p)
{
Logger::print("FuncExp::toConstElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
assert(fd);
assert(fd->tok == TOKfunction);
DtoForceDefineDsymbol(fd);
assert(fd->ir.irFunc->func);
return fd->ir.irFunc->func;
}
//////////////////////////////////////////////////////////////////////////////////////////
DValue* ArrayLiteralExp::toElem(IRState* p)
{
Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
@@ -2252,91 +2277,147 @@ LLConstant* ArrayLiteralExp::toConstElem(IRState* p)
//////////////////////////////////////////////////////////////////////////////////////////
void addZeros(std::vector<llvm::Value*>& inits, unsigned pos, unsigned offset);
DValue* StructLiteralExp::toElem(IRState* p)
{
Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
const LLType* llt = DtoType(type);
// get arrays
size_t n = elements->dim;
Expression** exprs = (Expression**)elements->data;
LLValue* mem = 0;
assert(sd->fields.dim == n);
VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
LLValue* sptr = DtoAlloca(llt,"tmpstructliteral");
// vector of values to build aggregate from
std::vector<llvm::Value*> values;
// default init the struct to take care of padding
// and unspecified members
TypeStruct* ts = (TypeStruct*)type->toBasetype();
assert(ts->sym);
DtoForceConstInitDsymbol(ts->sym);
assert(ts->sym->ir.irStruct->init);
DtoAggrCopy(sptr, ts->sym->ir.irStruct->init);
// trackers
size_t lastoffset = 0;
size_t lastsize = 0;
// num elements in literal
unsigned n = elements->dim;
// unions might have different types for each literal
if (sd->ir.irStruct->hasUnions) {
// build the type of the literal
std::vector<const LLType*> tys;
for (unsigned i=0; i<n; ++i) {
Expression* vx = (Expression*)elements->data[i];
if (!vx) continue;
tys.push_back(DtoType(vx->type));
}
const LLStructType* t = LLStructType::get(tys, sd->ir.irStruct->packed);
if (t != llt) {
if (getABITypeSize(t) != getABITypeSize(llt)) {
if (Logger::enabled())
Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n';
assert(0 && "type size mismatch");
}
sptr = DtoBitCast(sptr, getPtrToType(t));
if (Logger::enabled())
Logger::cout() << "sptr type is now: " << *t << '\n';
}
}
// build
unsigned j = 0;
for (unsigned i=0; i<n; ++i)
// for through each field and build up the struct, padding with zeros
for (size_t i=0; i<n; i++)
{
Expression* vx = (Expression*)elements->data[i];
if (!vx) continue;
Expression* e = exprs[i];
VarDeclaration* var = vars[i];
if (Logger::enabled())
Logger::cout() << "getting index " << j << " of " << *sptr << '\n';
LLValue* arrptr = DtoGEPi(sptr,0,j);
DValue* darrptr = new DVarValue(vx->type, arrptr);
// field is skipped
if (!e)
continue;
DValue* ve = vx->toElem(p);
DtoAssign(loc, darrptr, ve);
// add any 0 padding needed before this field
if (var->offset > lastoffset + lastsize)
{
addZeros(values, lastoffset + lastsize, var->offset);
}
j++;
// add the expression value
DValue* v = e->toElem(p);
values.push_back(v->getRVal());
// update offsets
lastoffset = var->offset;
lastsize = var->type->size();
}
return new DImValue(type, sptr);
// add any 0 padding needed at the end of the literal
const LLType* structtype = DtoType(sd->type);
size_t structsize = getABITypeSize(structtype);
if (structsize > lastoffset+lastsize)
{
addZeros(values, lastoffset + lastsize, structsize);
}
// get the struct type from the values
n = values.size();
std::vector<const LLType*> types(n, NULL);
for (size_t i=0; i<n; i++)
{
types[i] = values[i]->getType();
}
const LLStructType* sty = LLStructType::get(types, sd->ir.irStruct->packed);
// allocate storage for the struct literal on the stack
LLValue* mem = DtoAlloca(sty, "tmpstructliteral");
// put all the values into the storage
for (size_t i=0; i<n; i++)
{
LLValue* ptr = DtoGEPi(mem, 0, i);
DtoStore(values[i], ptr);
}
// cast the alloca pointer to the "formal" struct type
mem = DtoBitCast(mem, getPtrToType(structtype));
// return as a var
return new DVarValue(type, mem);
}
//////////////////////////////////////////////////////////////////////////////////////////
void addZeros(std::vector<llvm::Constant*>& inits, unsigned pos, unsigned offset);
LLConstant* StructLiteralExp::toConstElem(IRState* p)
{
Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
unsigned n = elements->dim;
std::vector<LLConstant*> vals(n, NULL);
// get arrays
size_t n = elements->dim;
Expression** exprs = (Expression**)elements->data;
for (unsigned i=0; i<n; ++i)
assert(sd->fields.dim == n);
VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
// vector of values to build aggregate from
std::vector<llvm::Constant*> values;
// trackers
size_t lastoffset = 0;
size_t lastsize = 0;
// for through each field and build up the struct, padding with zeros
for (size_t i=0; i<n; i++)
{
Expression* vx = (Expression*)elements->data[i];
vals[i] = vx->toConstElem(p);
Expression* e = exprs[i];
VarDeclaration* var = vars[i];
// field is skipped
if (!e)
continue;
// add any 0 padding needed before this field
if (var->offset > lastoffset + lastsize)
{
addZeros(values, lastoffset + lastsize, var->offset);
}
// add the expression value
values.push_back(e->toConstElem(p));
// update offsets
lastoffset = var->offset;
lastsize = var->type->size();
}
assert(type->toBasetype()->ty == Tstruct);
const LLType* t = DtoType(type);
const LLStructType* st = isaStruct(t);
return llvm::ConstantStruct::get(st,vals);
// add any 0 padding needed at the end of the literal
const LLType* structtype = DtoType(sd->type);
size_t structsize = getABITypeSize(structtype);
if (structsize > lastoffset+lastsize)
{
addZeros(values, lastoffset + lastsize, structsize);
}
// return constant struct
return LLConstantStruct::get(values, sd->ir.irStruct->packed);
}
//////////////////////////////////////////////////////////////////////////////////////////
+36 -2
View File
@@ -119,14 +119,14 @@ const LLType* DtoType(Type* t)
TypeStruct* ts = (TypeStruct*)t;
assert(ts->sym);
DtoResolveDsymbol(ts->sym);
return ts->sym->ir.irStruct->recty.get(); // t->ir.type->get();
return ts->ir.type->get();
}
case Tclass: {
TypeClass* tc = (TypeClass*)t;
assert(tc->sym);
DtoResolveDsymbol(tc->sym);
return getPtrToType(tc->sym->ir.irStruct->recty.get()); // t->ir.type->get());
return getPtrToType(tc->ir.type->get());
}
// functions
@@ -584,6 +584,13 @@ LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name)
return gIR->ir->CreateBitCast(v, t, name ? name : "tmp");
}
LLConstant* DtoBitCast(LLConstant* v, const LLType* t)
{
if (v->getType() == t)
return v;
return llvm::ConstantExpr::getBitCast(v, t);
}
//////////////////////////////////////////////////////////////////////////////////////////
const LLPointerType* isaPointer(LLValue* v)
@@ -695,6 +702,33 @@ unsigned char getPrefTypeAlign(const LLType* t)
return gTargetData->getPrefTypeAlignment(t);
}
const LLType* getBiggestType(const LLType** begin, size_t n)
{
const LLType* bigTy = 0;
size_t bigSize = 0;
size_t bigAlign = 0;
const LLType** end = begin+n;
while (begin != end)
{
const LLType* T = *begin;
size_t sz = getABITypeSize(T);
size_t ali = getABITypeAlign(T);
if (sz > bigSize || (sz == bigSize && ali > bigAlign))
{
bigTy = T;
bigSize = sz;
bigAlign = ali;
}
++begin;
}
// will be null for n==0
return bigTy;
}
//////////////////////////////////////////////////////////////////////////////////////////
const LLStructType* DtoInterfaceInfoType()
+4
View File
@@ -67,6 +67,7 @@ LLConstant* DtoConstBool(bool);
LLValue* DtoLoad(LLValue* src, const char* name=0);
void DtoStore(LLValue* src, LLValue* dst);
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
LLConstant* DtoBitCast(LLConstant* v, const LLType* t);
// llvm::dyn_cast wrappers
const LLPointerType* isaPointer(LLValue* v);
@@ -96,6 +97,9 @@ size_t getABITypeSize(const LLType* t);
unsigned char getABITypeAlign(const LLType* t);
unsigned char getPrefTypeAlign(const LLType* t);
// get biggest type, for unions ...
const LLType* getBiggestType(const LLType** begin, size_t n);
// pair type helpers
LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name = 0);
LLValue* DtoAggrPair(LLValue* V1, LLValue* V2, const char* name = 0);
+54 -25
View File
@@ -77,6 +77,8 @@ void Module::genobjfile(int multiobj, char** envp)
//printf("codegen: %s\n", srcfile->toChars());
assert(!global.errors);
// start by deleting the old object file
deleteObjFile();
@@ -156,16 +158,6 @@ void Module::genobjfile(int multiobj, char** envp)
fatal();
}
// start out by providing opaque for the built-in class types
if (!ClassDeclaration::object->type->ir.type)
ClassDeclaration::object->type->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
if (!Type::typeinfo->type->ir.type)
Type::typeinfo->type->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
if (!ClassDeclaration::classinfo->type->ir.type)
ClassDeclaration::classinfo->type->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
// process module members
for (int k=0; k < members->dim; k++) {
Dsymbol* dsym = (Dsymbol*)(members->data[k]);
@@ -638,7 +630,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
const LLStructType* modulerefTy = DtoModuleReferenceType();
std::vector<LLConstant*> mrefvalues;
mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0)));
mrefvalues.push_back(moduleinfo);
mrefvalues.push_back(llvm::ConstantExpr::getBitCast(moduleinfo, modulerefTy->getContainedType(1)));
LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues);
// create the ModuleReference node for this module
@@ -704,6 +696,13 @@ void Module::genmoduleinfo()
assert(moduleinfo);
DtoForceConstInitDsymbol(moduleinfo);
// check for patch
if (moduleinfo->ir.irStruct->constInit->getNumOperands() != 11)
{
error("unpatched object.d detected, ModuleInfo incorrect");
fatal();
}
// moduleinfo llvm struct type
const llvm::StructType* moduleinfoTy = isaStruct(moduleinfo->type->ir.type->get());
@@ -783,9 +782,15 @@ void Module::genmoduleinfo()
Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars());
continue;
}
else if (cd->sizeok != 1)
{
Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars());
continue;
}
Logger::println("class: %s", cd->toPrettyChars());
assert(cd->ir.irStruct->classInfo);
classInits.push_back(cd->ir.irStruct->classInfo);
c = llvm::ConstantExpr::getBitCast(cd->ir.irStruct->classInfo, getPtrToType(classinfoTy));
classInits.push_back(c);
}
// has class array?
if (!classInits.empty())
@@ -842,7 +847,7 @@ void Module::genmoduleinfo()
}*/
// create initializer
LLConstant* constMI = llvm::ConstantStruct::get(moduleinfoTy, initVec);
LLConstant* constMI = llvm::ConstantStruct::get(initVec);
// create name
std::string MIname("_D");
@@ -853,7 +858,8 @@ void Module::genmoduleinfo()
// flags will be modified at runtime so can't make it constant
llvm::GlobalVariable* gvar = gIR->module->getGlobalVariable(MIname);
if (!gvar) gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, MIname, gIR->module);
if (!gvar) gvar = new llvm::GlobalVariable(constMI->getType(), false, llvm::GlobalValue::ExternalLinkage, NULL, MIname, gIR->module);
else assert(gvar->getType()->getContainedType(0) == constMI->getType());
gvar->setInitializer(constMI);
// build the modulereference and ctor for registering it
@@ -988,7 +994,8 @@ void VarDeclaration::toObjFile(int multiobj)
#else
bool _isconst = isConst();
#endif
if (parent && parent->isFuncDeclaration())
Dsymbol* par = toParent2();
if (par && par->isFuncDeclaration())
{
static_local = true;
if (init && init->isExpInitializer()) {
@@ -1015,20 +1022,17 @@ void VarDeclaration::toObjFile(int multiobj)
}
else
{
#if DMDV2
#if 0
// might already have its irField, as classes derive each other without getting copies of the VarDeclaration
if (!ir.irField)
{
printf("dataseg: %d\n", isDataseg());
printf("parent: %s %s\n", parent->kind(), parent->toPrettyChars());
printf("this: %s %s\n", this->kind(), this->toPrettyChars());
assert(!ir.isSet());
ir.irField = new IrField(this);
}
#endif
#else
assert(ir.irField != 0);
#endif
IrStruct* irstruct = gIR->topstruct();
irstruct->addVar(this);
Logger::println("added offset %u", offset);
}
Logger::println("VarDeclaration::toObjFile is done");
}
/* ================================================================== */
@@ -1056,3 +1060,28 @@ void FuncDeclaration::toObjFile(int multiobj)
{
gIR->resolveList.push_back(this);
}
/* ================================================================== */
void AnonDeclaration::toObjFile(int multiobj)
{
Array *d = include(NULL, NULL);
if (d)
{
// get real aggregate parent
IrStruct* irstruct = gIR->topstruct();
// push a block on the stack
irstruct->pushAnon(isunion);
// go over children
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = (Dsymbol *)d->data[i];
s->toObjFile(multiobj);
}
// finish
irstruct->popAnon();
}
}
+80 -77
View File
@@ -379,7 +379,7 @@ void TypeInfoTypedefDeclaration::llvmDeclare()
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoTypedefDeclaration::llvmDefine()
@@ -390,10 +390,6 @@ void TypeInfoTypedefDeclaration::llvmDefine()
ClassDeclaration* base = Type::typeinfotypedef;
DtoForceConstInitDsymbol(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
if (Logger::enabled())
Logger::cout() << "got stype: " << *stype << '\n';
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
@@ -408,13 +404,11 @@ void TypeInfoTypedefDeclaration::llvmDefine()
// TypeInfo base
sd->basetype = sd->basetype->merge(); // DMD does this!
LLConstant* castbase = DtoTypeInfoOf(sd->basetype, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase);
// char[] name
char *name = sd->toPrettyChars();
sinits.push_back(DtoConstString(name));
assert(sinits.back()->getType() == stype->getElementType(3));
// void[] init
const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
@@ -433,9 +427,14 @@ void TypeInfoTypedefDeclaration::llvmDefine()
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
}
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
@@ -453,10 +452,8 @@ void TypeInfoEnumDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfoenum;
DtoResolveClass(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoEnumDeclaration::llvmDefine()
@@ -467,8 +464,6 @@ void TypeInfoEnumDeclaration::llvmDefine()
ClassDeclaration* base = Type::typeinfoenum;
DtoForceConstInitDsymbol(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
@@ -482,13 +477,11 @@ void TypeInfoEnumDeclaration::llvmDefine()
// TypeInfo base
LLConstant* castbase = DtoTypeInfoOf(sd->memtype, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase);
// char[] name
char *name = sd->toPrettyChars();
sinits.push_back(DtoConstString(name));
assert(sinits.back()->getType() == stype->getElementType(3));
// void[] init
const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
@@ -512,9 +505,14 @@ void TypeInfoEnumDeclaration::llvmDefine()
#endif
}
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
@@ -529,10 +527,8 @@ static LLConstant* LLVM_D_Declare_TypeInfoBase(TypeInfoDeclaration* tid, ClassDe
ClassDeclaration* base = cd;
DtoResolveClass(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
tid->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,tid->toChars(),gIR->module);
tid->ir.irGlobal->value = new llvm::GlobalVariable(tid->ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,tid->toChars(),gIR->module);
}
static LLConstant* LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd)
@@ -540,8 +536,6 @@ static LLConstant* LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaratio
ClassDeclaration* base = cd;
DtoForceConstInitDsymbol(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
@@ -551,11 +545,15 @@ static LLConstant* LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaratio
// TypeInfo base
LLConstant* castbase = DtoTypeInfoOf(basetype, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase);
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(tid->ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(tid->ir.irGlobal->value)->setInitializer(tiInit);
}
@@ -628,11 +626,8 @@ void TypeInfoStaticArrayDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfostaticarray;
DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoStaticArrayDeclaration::llvmDefine()
@@ -665,9 +660,14 @@ void TypeInfoStaticArrayDeclaration::llvmDefine()
// length
sinits.push_back(DtoConstSize_t(tc->dim->toInteger()));
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
@@ -686,11 +686,8 @@ void TypeInfoAssociativeArrayDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfoassociativearray;
DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoAssociativeArrayDeclaration::llvmDefine()
@@ -702,9 +699,6 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
ClassDeclaration* base = Type::typeinfoassociativearray;
DtoForceConstInitDsymbol(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
@@ -719,17 +713,20 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
// value typeinfo
LLConstant* castbase = DtoTypeInfoOf(tc->next, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase);
// key typeinfo
castbase = DtoTypeInfoOf(tc->index, true);
assert(castbase->getType() == stype->getElementType(3));
sinits.push_back(castbase);
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
@@ -810,10 +807,8 @@ void TypeInfoStructDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfostruct;
DtoResolveClass(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoStructDeclaration::llvmDefine()
@@ -1001,9 +996,14 @@ void TypeInfoStructDeclaration::llvmDefine()
#endif
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoStructDeclaration::toDt(dt_t **pdt)
@@ -1023,11 +1023,8 @@ void TypeInfoClassDeclaration::llvmDeclare()
assert(base);
DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true, llvm::GlobalValue::WeakLinkage, NULL, toChars(), gIR->module);
}
void TypeInfoClassDeclaration::llvmDefine()
@@ -1040,9 +1037,6 @@ void TypeInfoClassDeclaration::llvmDefine()
assert(base);
DtoForceConstInitDsymbol(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
@@ -1058,9 +1052,14 @@ void TypeInfoClassDeclaration::llvmDefine()
assert(tc->sym->ir.irStruct->classInfo);
sinits.push_back(tc->sym->ir.irStruct->classInfo);
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoClassDeclaration::toDt(dt_t **pdt)
@@ -1080,11 +1079,8 @@ void TypeInfoInterfaceDeclaration::llvmDeclare()
assert(base);
DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoInterfaceDeclaration::llvmDefine()
@@ -1114,9 +1110,14 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
assert(tc->sym->ir.irStruct->classInfo);
sinits.push_back(tc->sym->ir.irStruct->classInfo);
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
@@ -1136,11 +1137,8 @@ void TypeInfoTupleDeclaration::llvmDeclare()
assert(base);
DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol
this->ir.irGlobal->value = new llvm::GlobalVariable(stype,true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
ir.irGlobal->value = new llvm::GlobalVariable(ir.irGlobal->type.get(), true,llvm::GlobalValue::WeakLinkage,NULL,toChars(),gIR->module);
}
void TypeInfoTupleDeclaration::llvmDefine()
@@ -1199,9 +1197,14 @@ void TypeInfoTupleDeclaration::llvmDefine()
LLConstant* slice = DtoConstSlice(DtoConstSize_t(dim), arrptr);
sinits.push_back(slice);
// create the symbol
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
// refine global type
llvm::cast<llvm::OpaqueType>(ir.irGlobal->type.get())->refineAbstractTypeTo(tiInit->getType());
// set the initializer
isaGlobalVar(ir.irGlobal->value)->setInitializer(tiInit);
}
void TypeInfoTupleDeclaration::toDt(dt_t **pdt)