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 2103 additions and 2398 deletions

View file

@ -45,7 +45,6 @@ namespace llvm
class ConstantStruct;
class GlobalVariable;
}
struct DUnion;
struct AggregateDeclaration : ScopeDsymbol
{
@ -258,9 +257,6 @@ struct ClassDeclaration : AggregateDeclaration
Symbol *vtblsym;
// llvm
void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
};

View file

@ -616,7 +616,6 @@ void AnonDeclaration::semantic(Scope *sc)
sc->flags = 0;
aad.structalign = sc->structalign;
aad.parent = ad;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
@ -672,6 +671,9 @@ void AnonDeclaration::semantic(Scope *sc)
{
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
// LDC
v->offset2 = sc->offset;
v->offset += sc->offset;
// LDC

View file

@ -50,7 +50,7 @@ struct AttribDeclaration : Dsymbol
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AttribDeclaration *isAttribDeclaration() { return this; }
void toObjFile(int multiobj); // compile to .obj file
virtual void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
};
@ -107,6 +107,9 @@ struct AnonDeclaration : AttribDeclaration
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
const char *kind();
// LDC
void toObjFile(int multiobj); // compile to .obj file
};
struct PragmaDeclaration : AttribDeclaration

View file

@ -624,6 +624,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
// LDC
anonDecl = NULL;
offset2 = 0;
}
Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)

View file

@ -273,6 +273,7 @@ struct VarDeclaration : Declaration
// LDC
AnonDeclaration* anonDecl;
unsigned offset2;
};
/**************************************************************/

View file

@ -628,6 +628,9 @@ struct FuncExp : Expression
int inlineCost(InlineCostState *ics);
//Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
// LDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
// Declaration of a symbol

View file

@ -1196,9 +1196,9 @@ int main(int argc, char *argv[], char** envp)
m->inlineScan();
}
}
#endif
if (global.errors)
fatal();
#endif
// Generate output files
for (i = 0; i < modules.dim; i++)

View file

@ -345,7 +345,7 @@ void inifile(char *argv0, char *inifile);
void halt();
/*** Where to send error messages ***/
#if IN_GCC
#if IN_GCC || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stdout

View file

@ -3186,6 +3186,14 @@ d_uns64 TypeDelegate::size(Loc loc)
return PTRSIZE * 2;
}
// LDC added, no reason to align to 2*PTRSIZE
unsigned TypeDelegate::alignsize()
{
// A Delegate consists of two ptr values, so align it on pointer size
// boundary
return PTRSIZE;
}
void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
if (mod != this->mod)

View file

@ -451,6 +451,7 @@ struct TypeDelegate : Type
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
unsigned alignsize(); // added in LDC
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *defaultInit(Loc loc);
int isZeroInit();

View file

@ -45,7 +45,6 @@ namespace llvm
class ConstantStruct;
class GlobalVariable;
}
struct DUnion;
struct AggregateDeclaration : ScopeDsymbol
{
@ -264,9 +263,6 @@ struct ClassDeclaration : AggregateDeclaration
Symbol *vtblsym;
// llvm
void offsetToIndex(Type* t, unsigned os, std::vector<unsigned>& result);
ClassDeclaration *isClassDeclaration() { return (ClassDeclaration *)this; }
};

View file

@ -629,7 +629,6 @@ void AnonDeclaration::semantic(Scope *sc)
sc->flags = 0;
aad.structalign = sc->structalign;
aad.parent = ad;
for (unsigned i = 0; i < decl->dim; i++)
{
Dsymbol *s = (Dsymbol *)decl->data[i];
@ -685,6 +684,9 @@ void AnonDeclaration::semantic(Scope *sc)
{
VarDeclaration *v = (VarDeclaration *)aad.fields.data[i];
// LDC
v->offset2 = sc->offset;
v->offset += sc->offset;
// LDC

View file

@ -50,7 +50,7 @@ struct AttribDeclaration : Dsymbol
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AttribDeclaration *isAttribDeclaration() { return this; }
void toObjFile(int multiobj); // compile to .obj file
virtual void toObjFile(int multiobj); // compile to .obj file
int cvMember(unsigned char *p);
};

View file

@ -618,6 +618,7 @@ VarDeclaration::VarDeclaration(Loc loc, Type *type, Identifier *id, Initializer
// LDC
anonDecl = NULL;
offset2 = 0;
}
Dsymbol *VarDeclaration::syntaxCopy(Dsymbol *s)

View file

@ -279,6 +279,7 @@ struct VarDeclaration : Declaration
// LDC
AnonDeclaration* anonDecl;
unsigned offset2;
};
/**************************************************************/

View file

@ -653,6 +653,9 @@ struct FuncExp : Expression
int inlineCost(InlineCostState *ics);
//Expression *doInline(InlineDoState *ids);
//Expression *inlineScan(InlineScanState *iss);
// LDC
virtual llvm::Constant *toConstElem(IRState *irs);
};
// Declaration of a symbol

View file

@ -1220,9 +1220,9 @@ int main(int argc, char *argv[], char** envp)
m->inlineScan();
}
}
#endif
if (global.errors)
fatal();
#endif
// Generate output files
for (i = 0; i < modules.dim; i++)

View file

@ -350,7 +350,7 @@ void inifile(const char *argv0, const char *inifile);
void halt();
/*** Where to send error messages ***/
#if IN_GCC
#if IN_GCC || IN_LLVM
#define stdmsg stderr
#else
#define stdmsg stdout

View file

@ -3694,6 +3694,14 @@ d_uns64 TypeDelegate::size(Loc loc)
return PTRSIZE * 2;
}
// LDC added, no reason to align to 2*PTRSIZE
unsigned TypeDelegate::alignsize()
{
// A Delegate consists of two ptr values, so align it on pointer size
// boundary
return PTRSIZE;
}
void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
if (mod != this->mod)

View file

@ -516,6 +516,7 @@ struct TypeDelegate : TypeNext
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
unsigned alignsize(); // added in LDC
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *defaultInit(Loc loc);
int isZeroInit();

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)
{

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);

File diff suppressed because it is too large Load diff

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));
}

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;

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,7 +1525,7 @@ 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';
@ -1538,12 +1533,25 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
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);
@ -1568,10 +1576,8 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
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();
@ -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,7 +1599,6 @@ 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());
}

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);

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");
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////

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();

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);
}

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

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());

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());

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);
}
//////////////////////////////////////////////////////////////////////////////////////////

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()

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);

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();
}
}

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)

View file

@ -3,54 +3,57 @@
#include "mtype.h"
#include "aggregate.h"
#include "declaration.h"
#include "init.h"
#include "ir/irstruct.h"
#include "gen/irstate.h"
#include "gen/tollvm.h"
#include "gen/logger.h"
IrInterface::IrInterface(BaseClass* b)
: vtblInitTy(llvm::OpaqueType::get())
{
base = b;
decl = b->base;
vtblTy = NULL;
vtblInit = NULL;
vtbl = NULL;
infoTy = NULL;
infoInit = NULL;
info = NULL;
index = -1;
}
IrInterface::~IrInterface()
{
delete vtblTy;
index = 0;
}
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
IrStruct::IrStruct(Type* t)
: recty((t->ir.type) ? *t->ir.type : llvm::OpaqueType::get())
IrStruct::IrStruct(AggregateDeclaration* aggr)
: initOpaque(llvm::OpaqueType::get()),
classInfoOpaque(llvm::OpaqueType::get()),
vtblTy(llvm::OpaqueType::get()),
vtblInitTy(llvm::OpaqueType::get())
{
type = t;
aggrdecl = aggr;
defaultFound = false;
anon = NULL;
index = 0;
type = aggr->type;
defined = false;
constinited = false;
interfaceInfosTy = NULL;
interfaceInfos = NULL;
interfaceInfos = NULL;
vtbl = NULL;
constVtbl = NULL;
init = NULL;
constInit = NULL;
classInfo = NULL;
constClassInfo = NULL;
hasUnions = false;
dunion = NULL;
classDeclared = false;
classDefined = false;
classInfoDeclared = false;
classInfoDefined = false;
packed = false;
@ -61,14 +64,294 @@ IrStruct::~IrStruct()
{
}
void IrStruct::addField(VarDeclaration* v)
//////////////////////////////////////////
void IrStruct::pushAnon(bool isunion)
{
// might already have its irField, as classes derive each other without getting copies of the VarDeclaration
if (!v->ir.irField)
{
assert(!v->ir.isSet());
v->ir.irField = new IrField(v);
}
const LLType* _type = DtoType(v->type);
offsets.insert(std::make_pair(v->offset, IrStruct::Offset(v, _type)));
anon = new Anon(isunion, anon);
}
//////////////////////////////////////////
void IrStruct::popAnon()
{
assert(anon);
const LLType* BT;
// get the anon type
if (anon->isunion)
{
// get biggest type in block
const LLType* biggest = getBiggestType(&anon->types[0], anon->types.size());
std::vector<const LLType*> vec(1, biggest);
BT = LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
}
else
{
// build a struct from the types
BT = LLStructType::get(anon->types, aggrdecl->ir.irStruct->packed);
}
// pop anon
Anon* tmp = anon;
anon = anon->parent;
delete tmp;
// is there a parent anon?
if (anon)
{
// make sure type gets pushed in the anon, not the main
anon->types.push_back(BT);
// index is only manipulated at the top level, anons use raw offsets
}
// no parent anon, finally add to aggrdecl
else
{
types.push_back(BT);
// only advance to next position if main is not a union
if (!aggrdecl->isUnionDeclaration())
{
index++;
}
}
}
//////////////////////////////////////////
void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset);
void IrStruct::addVar(VarDeclaration * var)
{
TypeVector* tvec = &types;
if (anon)
{
// make sure type gets pushed in the anon, not the main
tvec = &anon->types;
// set but don't advance index
var->ir.irField->index = index;
// set offset in bytes from start of anon block
var->ir.irField->unionOffset = var->offset - var->offset2;
}
else if (aggrdecl->isUnionDeclaration())
{
// set but don't advance index
var->ir.irField->index = index;
}
else
{
// set and advance index
var->ir.irField->index = index++;
}
// add type
tvec->push_back(DtoType(var->type));
// add var
varDecls.push_back(var);
}
//////////////////////////////////////////
const LLType* IrStruct::build()
{
// if types is empty, add a byte
if (types.empty())
{
types.push_back(LLType::Int8Ty);
}
// union type
if (aggrdecl->isUnionDeclaration())
{
const LLType* biggest = getBiggestType(&types[0], types.size());
std::vector<const LLType*> vec(1, biggest);
return LLStructType::get(vec, aggrdecl->ir.irStruct->packed);
}
// struct/class type
else
{
return LLStructType::get(types, aggrdecl->ir.irStruct->packed);
}
}
void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset)
{
assert(offset > pos);
size_t diff = offset - pos;
size_t sz;
do
{
if (pos%8 == 0 && diff >= 8)
sz = 8;
else if (pos%4 == 0 && diff >= 4)
sz = 4;
else if (pos%2 == 0 && diff >= 2)
sz = 2;
else // if (pos % 1 == 0)
sz = 1;
inits.push_back(LLIntegerType::get(sz*8));
pos += sz;
diff -= sz;
} while (pos < offset);
assert(pos == offset);
}
void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset)
{
assert(offset > pos);
size_t diff = offset - pos;
size_t sz;
do
{
if (pos%8 == 0 && diff >= 8)
sz = 8;
else if (pos%4 == 0 && diff >= 4)
sz = 4;
else if (pos%2 == 0 && diff >= 2)
sz = 2;
else // if (pos % 1 == 0)
sz = 1;
inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
pos += sz;
diff -= sz;
} while (pos < offset);
assert(pos == offset);
}
// FIXME: body is exact copy of above
void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset)
{
assert(offset > pos);
size_t diff = offset - pos;
size_t sz;
do
{
if (pos%8 == 0 && diff >= 8)
sz = 8;
else if (pos%4 == 0 && diff >= 4)
sz = 4;
else if (pos%2 == 0 && diff >= 2)
sz = 2;
else // if (pos % 1 == 0)
sz = 1;
inits.push_back(LLConstant::getNullValue(LLIntegerType::get(sz*8)));
pos += sz;
diff -= sz;
} while (pos < offset);
assert(pos == offset);
}
void IrStruct::buildDefaultConstInit(std::vector<llvm::Constant*>& inits)
{
assert(!defaultFound);
defaultFound = true;
const llvm::StructType* structtype = isaStruct(aggrdecl->type->ir.type->get());
Logger::cout() << "struct type: " << *structtype << '\n';
size_t lastoffset = 0;
size_t lastsize = 0;
{
Logger::println("Find the default fields");
LOG_SCOPE;
// go through all vars and find the ones that contribute to the default
size_t nvars = varDecls.size();
for (size_t i=0; i<nvars; i++)
{
VarDeclaration* var = varDecls[i];
Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
// only add vars that don't overlap
size_t offset = var->offset;
size_t size = var->type->size();
if (offset >= lastoffset+lastsize)
{
Logger::println(" added");
lastoffset = offset;
lastsize = size;
defVars.push_back(var);
}
}
}
{
Logger::println("Build the default initializer");
LOG_SCOPE;
lastoffset = 0;
lastsize = 0;
// go through the default vars and build the default constant initializer
// adding zeros along the way to live up to alignment expectations
size_t nvars = defVars.size();
for (size_t i=0; i<nvars; i++)
{
VarDeclaration* var = defVars[i];
Logger::println("field %s %s = %s : +%u", var->type->toChars(), var->toChars(), var->init ? var->init->toChars() : var->type->defaultInit(var->loc)->toChars(), var->offset);
// get offset and size
size_t offset = var->offset;
size_t size = var->type->size();
// is there space in between last last offset and this one?
// if so, fill it with zeros
if (offset > lastoffset+lastsize)
{
size_t pos = lastoffset + lastsize;
addZeros(inits, pos, offset);
}
// add the field
assert(var->ir.irField->constInit);
inits.push_back(var->ir.irField->constInit);
lastoffset = offset;
lastsize = var->type->size();
}
// there might still be padding after the last one, make sure that is zeroed as well
// is there space in between last last offset and this one?
size_t structsize = getABITypeSize(structtype);
if (structsize > lastoffset+lastsize)
{
size_t pos = lastoffset + lastsize;
addZeros(inits, pos, structsize);
}
}
}
LLConstant* IrStruct::buildDefaultConstInit()
{
// doesn't work for classes, they add stuff before and maybe after data fields
assert(!aggrdecl->isClassDeclaration());
// initializer llvm constant list
std::vector<LLConstant*> inits;
// just start with an empty list
buildDefaultConstInit(inits);
// build the constant
// note that the type matches the initializer, not the aggregate in cases with unions
LLConstant* c = LLConstantStruct::get(inits, aggrdecl->ir.irStruct->packed);
Logger::cout() << "llvm constant: " << *c << '\n';
// assert(0);
return c;
}

View file

@ -6,86 +6,168 @@
#include <vector>
#include <map>
struct IrInterface : IrBase
{
BaseClass* base;
ClassDeclaration* decl;
llvm::PATypeHolder* vtblTy;
LLConstant* vtblInit;
LLGlobalVariable* vtbl;
const LLStructType* infoTy;
LLConstantStruct* infoInit;
LLConstant* info;
int index;
IrInterface(BaseClass* b);
~IrInterface();
};
struct IrInterface;
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// represents a struct or class
// it is used during codegen to hold all the vital info we need
struct IrStruct : IrBase
{
struct Offset
{
VarDeclaration* var;
const LLType* type;
LLConstant* init;
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
Offset(VarDeclaration* v, const LLType* ty)
: var(v), type(ty), init(NULL) {}
};
typedef std::multimap<unsigned, Offset> OffsetMap;
typedef std::vector<VarDeclaration*> VarDeclVector;
typedef std::map<ClassDeclaration*, IrInterface*> InterfaceMap;
typedef InterfaceMap::iterator InterfaceMapIter;
typedef std::map<ClassDeclaration*, IrInterface*> InterfaceMap;
typedef InterfaceMap::iterator InterfaceMapIter;
typedef std::vector<IrInterface*> InterfaceVector;
typedef InterfaceVector::iterator InterfaceVectorIter;
public:
IrStruct(Type*);
// vector of LLVM types
typedef std::vector<const llvm::Type*> TypeVector;
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// Anon represents an anonymous struct union block inside an aggregate
// during LLVM type construction.
struct Anon
{
bool isunion;
Anon* parent;
TypeVector types;
Anon(bool IsUnion, Anon* par) : isunion(IsUnion), parent(par) {}
};
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/// ctor
IrStruct(AggregateDeclaration* agg);
/// dtor
virtual ~IrStruct();
void addField(VarDeclaration* v);
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/// push an anonymous struct/union
void pushAnon(bool isunion);
/// pops an anonymous struct/union
void popAnon();
/// adds field
void addVar(VarDeclaration* var);
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/// build the aggr type
const LLType* build();
/// put the aggr initializers in a vector
void buildDefaultConstInit(std::vector<llvm::Constant*>& inits);
/// ditto - but also builds the constant struct, for convenience
LLConstant* buildDefaultConstInit();
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
// the D aggregate
AggregateDeclaration* aggrdecl;
// vector of VarDeclarations in this aggregate
VarDeclVector varDecls;
// vector of VarDeclarations that contribute to the default initializer
VarDeclVector defVars;
// true if the default initializer has been built
bool defaultFound;
// top element
Anon* anon;
// toplevel types in this aggr
TypeVector types;
// current index
// always the same as types.size()
size_t index;
// aggregate D type
Type* type;
llvm::PATypeHolder recty;
OffsetMap offsets;
VarDeclVector defaultFields;
// class vtable type
llvm::PATypeHolder vtblTy;
llvm::PATypeHolder vtblInitTy;
// initializer type opaque (type of global matches initializer, not formal type)
llvm::PATypeHolder initOpaque;
llvm::PATypeHolder classInfoOpaque;
// map/vector of interfaces implemented
InterfaceMap interfaceMap;
InterfaceVector interfaceVec;
const llvm::ArrayType* interfaceInfosTy;
// interface info array global
LLGlobalVariable* interfaceInfos;
// ...
bool defined;
bool constinited;
// vtbl global and initializer
LLGlobalVariable* vtbl;
#if OPAQUE_VTBLS
LLConstant* constVtbl;
#else
LLConstantStruct* constVtbl;
#endif
// static initializers global and constant
LLGlobalVariable* init;
LLConstant* constInit;
// classinfo global and initializer constant
LLGlobalVariable* classInfo;
LLConstant* constClassInfo;
bool hasUnions;
DUnion* dunion;
bool classDeclared;
bool classDefined;
bool classInfoDeclared;
bool classInfoDefined;
bool packed; // true for: align(1) struct S { ... }
// align(1) struct S { ... }
bool packed;
// dwarf composite global
LLGlobalVariable* dwarfComposite;
};
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// represents interface implemented by a class
struct IrInterface : IrBase
{
BaseClass* base;
ClassDeclaration* decl;
llvm::PATypeHolder vtblInitTy;
LLConstant* vtblInit;
LLGlobalVariable* vtbl;
const LLStructType* infoTy;
LLConstant* infoInit;
LLConstant* info;
size_t index;
IrInterface(BaseClass* b);
};
#endif

View file

@ -21,9 +21,6 @@ IrType::IrType(const IrType& s)
{
assert(list.insert(this).second);
type = s.type;
#if OPAQUE_VTBLS
vtblType = s.type;
#endif
}
IrType::~IrType()
@ -34,7 +31,4 @@ IrType::~IrType()
void IrType::reset()
{
type = NULL;
#if OPAQUE_VTBLS
vtblType = NULL;
#endif
}

View file

@ -21,7 +21,6 @@ struct IrType
void reset();
llvm::PATypeHolder* type;
llvm::PATypeHolder* vtblType;
};
#endif

View file

@ -1,4 +1,4 @@
#include "llvm/DerivedTypes.h"
#include "gen/llvm.h"
#include "declaration.h"
#include "ir/irvar.h"
@ -38,8 +38,8 @@ IrLocal::IrLocal(VarDeclaration* v) : IrVar(v)
IrField::IrField(VarDeclaration* v) : IrVar(v)
{
index = -1;
indexOffset = 0;
index = 0;
unionOffset = 0;
constInit = NULL;
}

View file

@ -34,8 +34,9 @@ struct IrField : IrVar
{
IrField(VarDeclaration* v);
int index;
size_t indexOffset;
unsigned index;
unsigned unionOffset;
llvm::Constant* constInit;
};

View file

@ -1,684 +0,0 @@
<?xml version = '1.0'?>
<kdevelop>
<general>
<author>Tomas Lindquist Olsen</author>
<email>tomas.l.olsen@gmail.com</email>
<version>0.1</version>
<projectmanagement>KDevCustomProject</projectmanagement>
<primarylanguage>C++</primarylanguage>
<keywords>
<keyword>C++</keyword>
<keyword>Code</keyword>
</keywords>
<ignoreparts/>
<projectname>llvmdc</projectname>
<projectdirectory>.</projectdirectory>
<absoluteprojectpath>false</absoluteprojectpath>
<description/>
<defaultencoding/>
<versioncontrol>kdevsubversion</versioncontrol>
</general>
<kdevautoproject>
<general/>
<run/>
<configurations>
<optimized>
<builddir>optimized</builddir>
<ccompiler>kdevgccoptions</ccompiler>
<cxxcompiler>kdevgppoptions</cxxcompiler>
<f77compiler>kdevg77options</f77compiler>
<cxxflags>-O2 -g0</cxxflags>
</optimized>
<debug>
<configargs>--enable-debug=full</configargs>
<builddir>debug</builddir>
<ccompiler>kdevgccoptions</ccompiler>
<cxxcompiler>kdevgppoptions</cxxcompiler>
<f77compiler>kdevg77options</f77compiler>
<cxxflags>-O0 -g3</cxxflags>
</debug>
</configurations>
</kdevautoproject>
<kdevdoctreeview>
<ignoretocs>
<toc>ada</toc>
<toc>ada_bugs_gcc</toc>
<toc>bash</toc>
<toc>bash_bugs</toc>
<toc>clanlib</toc>
<toc>w3c-dom-level2-html</toc>
<toc>fortran_bugs_gcc</toc>
<toc>gnome1</toc>
<toc>gnustep</toc>
<toc>gtk</toc>
<toc>gtk_bugs</toc>
<toc>haskell</toc>
<toc>haskell_bugs_ghc</toc>
<toc>java_bugs_gcc</toc>
<toc>java_bugs_sun</toc>
<toc>kde2book</toc>
<toc>opengl</toc>
<toc>pascal_bugs_fp</toc>
<toc>php</toc>
<toc>php_bugs</toc>
<toc>perl</toc>
<toc>perl_bugs</toc>
<toc>python</toc>
<toc>python_bugs</toc>
<toc>qt-kdev3</toc>
<toc>ruby</toc>
<toc>ruby_bugs</toc>
<toc>sdl</toc>
<toc>w3c-svg</toc>
<toc>sw</toc>
<toc>w3c-uaag10</toc>
<toc>wxwidgets_bugs</toc>
</ignoretocs>
<ignoreqt_xml>
<toc>Guide to the Qt Translation Tools</toc>
<toc>Qt Assistant Manual</toc>
<toc>Qt Designer Manual</toc>
<toc>Qt Reference Documentation</toc>
<toc>qmake User Guide</toc>
</ignoreqt_xml>
<ignoredoxygen>
<toc>KDE Libraries (Doxygen)</toc>
</ignoredoxygen>
</kdevdoctreeview>
<kdevfilecreate>
<filetypes/>
<useglobaltypes>
<type ext="cpp" />
<type ext="h" />
</useglobaltypes>
</kdevfilecreate>
<kdevfileview>
<groups>
<group pattern="*.h" name="Header files" />
<group pattern="*.cpp" name="Source files" />
<hidenonprojectfiles>true</hidenonprojectfiles>
<hidenonlocation>false</hidenonlocation>
</groups>
<tree>
<hidepatterns>*.bc</hidepatterns>
<hidenonprojectfiles>false</hidenonprojectfiles>
<showvcsfields>false</showvcsfields>
</tree>
</kdevfileview>
<kdevdocumentation>
<projectdoc>
<docsystem>Doxygen Documentation Collection</docsystem>
<docurl>llvmdc.tag</docurl>
</projectdoc>
</kdevdocumentation>
<substmap>
<APPNAME>llvmdc</APPNAME>
<APPNAMELC>llvmdc</APPNAMELC>
<APPNAMESC>Llvmdc</APPNAMESC>
<APPNAMEUC>LLVMDC</APPNAMEUC>
<AUTHOR>Tomas Lindquist Olsen</AUTHOR>
<EMAIL>tomas.l.olsen@gmail.com</EMAIL>
<LICENSE>GPL</LICENSE>
<LICENSEFILE>COPYING</LICENSEFILE>
<VERSION>0.1</VERSION>
<YEAR>2007</YEAR>
<dest>/home/tomas/projects/llvmdc</dest>
</substmap>
<kdevcppsupport>
<qt>
<used>false</used>
<version>3</version>
<includestyle>3</includestyle>
<root>/opt/qt</root>
<designerintegration>EmbeddedKDevDesigner</designerintegration>
<qmake>/opt/qt/bin/qmake</qmake>
<designer>/opt/qt/bin/designer</designer>
<designerpluginpaths/>
</qt>
<codecompletion>
<automaticCodeCompletion>false</automaticCodeCompletion>
<automaticArgumentsHint>true</automaticArgumentsHint>
<automaticHeaderCompletion>true</automaticHeaderCompletion>
<codeCompletionDelay>250</codeCompletionDelay>
<argumentsHintDelay>400</argumentsHintDelay>
<headerCompletionDelay>250</headerCompletionDelay>
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
<completionBoxItemOrder>0</completionBoxItemOrder>
<howEvaluationContextMenu>true</howEvaluationContextMenu>
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
<processPrimaryTypes>true</processPrimaryTypes>
<processFunctionArguments>false</processFunctionArguments>
<preProcessAllHeaders>true</preProcessAllHeaders>
<parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
<resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
<alwaysParseInBackground>true</alwaysParseInBackground>
<usePermanentCaching>true</usePermanentCaching>
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
<includePaths>.;</includePaths>
</codecompletion>
<creategettersetter>
<prefixGet/>
<prefixSet>set</prefixSet>
<prefixVariable>m_,_</prefixVariable>
<parameterName>theValue</parameterName>
<inlineGet>true</inlineGet>
<inlineSet>true</inlineSet>
</creategettersetter>
<splitheadersource>
<enabled>false</enabled>
<synchronize>true</synchronize>
<orientation>Vertical</orientation>
</splitheadersource>
<references/>
</kdevcppsupport>
<kdevcustomproject>
<run>
<directoryradio>executable</directoryradio>
<mainprogram>/home/tomas/kdevprojects/llvmdc</mainprogram>
<programargs/>
<globaldebugarguments/>
<globalcwd>/home/tomas/kdevprojects/llvmdc</globalcwd>
<useglobalprogram>false</useglobalprogram>
<terminal>false</terminal>
<autocompile>false</autocompile>
<autoinstall>false</autoinstall>
<autokdesu>false</autokdesu>
<envvars/>
</run>
<filetypes>
<filetype>*.h</filetype>
<filetype>*.c</filetype>
<filetype>*.cpp</filetype>
<filetype>build.sh</filetype>
</filetypes>
<blacklist>
<path>demos</path>
<path>demos/ray.cpp</path>
<path>dmdorig</path>
<path>dmdorig/dmd</path>
<path>dmdorig/dmd/access.c</path>
<path>dmdorig/dmd/aggregate.h</path>
<path>dmdorig/dmd/array.c</path>
<path>dmdorig/dmd/arraytypes.h</path>
<path>dmdorig/dmd/attrib.c</path>
<path>dmdorig/dmd/attrib.h</path>
<path>dmdorig/dmd/bit.c</path>
<path>dmdorig/dmd/cast.c</path>
<path>dmdorig/dmd/class.c</path>
<path>dmdorig/dmd/complex_t.h</path>
<path>dmdorig/dmd/cond.c</path>
<path>dmdorig/dmd/cond.h</path>
<path>dmdorig/dmd/constfold.c</path>
<path>dmdorig/dmd/dchar.c</path>
<path>dmdorig/dmd/dchar.h</path>
<path>dmdorig/dmd/declaration.c</path>
<path>dmdorig/dmd/declaration.h</path>
<path>dmdorig/dmd/delegatize.c</path>
<path>dmdorig/dmd/doc.c</path>
<path>dmdorig/dmd/doc.h</path>
<path>dmdorig/dmd/dsymbol.c</path>
<path>dmdorig/dmd/dsymbol.h</path>
<path>dmdorig/dmd/dump.c</path>
<path>dmdorig/dmd/entity.c</path>
<path>dmdorig/dmd/enum.c</path>
<path>dmdorig/dmd/enum.h</path>
<path>dmdorig/dmd/expression.c</path>
<path>dmdorig/dmd/expression.h</path>
<path>dmdorig/dmd/func.c</path>
<path>dmdorig/dmd/gnuc.c</path>
<path>dmdorig/dmd/gnuc.h</path>
<path>dmdorig/dmd/hdrgen.c</path>
<path>dmdorig/dmd/hdrgen.h</path>
<path>dmdorig/dmd/html.c</path>
<path>dmdorig/dmd/html.h</path>
<path>dmdorig/dmd/identifier.c</path>
<path>dmdorig/dmd/identifier.h</path>
<path>dmdorig/dmd/idgen.c</path>
<path>dmdorig/dmd/impcnvgen.c</path>
<path>dmdorig/dmd/import.c</path>
<path>dmdorig/dmd/import.h</path>
<path>dmdorig/dmd/inifile.c</path>
<path>dmdorig/dmd/init.c</path>
<path>dmdorig/dmd/init.h</path>
<path>dmdorig/dmd/inline.c</path>
<path>dmdorig/dmd/interpret.c</path>
<path>dmdorig/dmd/lexer.c</path>
<path>dmdorig/dmd/lexer.h</path>
<path>dmdorig/dmd/link.c</path>
<path>dmdorig/dmd/lstring.c</path>
<path>dmdorig/dmd/lstring.h</path>
<path>dmdorig/dmd/macro.c</path>
<path>dmdorig/dmd/macro.h</path>
<path>dmdorig/dmd/mangle.c</path>
<path>dmdorig/dmd/mars.c</path>
<path>dmdorig/dmd/mars.h</path>
<path>dmdorig/dmd/mem.c</path>
<path>dmdorig/dmd/mem.h</path>
<path>dmdorig/dmd/module.c</path>
<path>dmdorig/dmd/module.h</path>
<path>dmdorig/dmd/mtype.c</path>
<path>dmdorig/dmd/mtype.h</path>
<path>dmdorig/dmd/opover.c</path>
<path>dmdorig/dmd/optimize.c</path>
<path>dmdorig/dmd/parse.c</path>
<path>dmdorig/dmd/parse.h</path>
<path>dmdorig/dmd/port.h</path>
<path>dmdorig/dmd/root.c</path>
<path>dmdorig/dmd/root.h</path>
<path>dmdorig/dmd/scope.c</path>
<path>dmdorig/dmd/scope.h</path>
<path>dmdorig/dmd/statement.c</path>
<path>dmdorig/dmd/statement.h</path>
<path>dmdorig/dmd/staticassert.c</path>
<path>dmdorig/dmd/staticassert.h</path>
<path>dmdorig/dmd/stringtable.c</path>
<path>dmdorig/dmd/stringtable.h</path>
<path>dmdorig/dmd/struct.c</path>
<path>dmdorig/dmd/template.c</path>
<path>dmdorig/dmd/template.h</path>
<path>dmdorig/dmd/tocsym.c</path>
<path>dmdorig/dmd/todt.c</path>
<path>dmdorig/dmd/toir.c</path>
<path>dmdorig/dmd/toir.h</path>
<path>dmdorig/dmd/toobj.c</path>
<path>dmdorig/dmd/total.h</path>
<path>dmdorig/dmd/typinf.c</path>
<path>dmdorig/dmd/unialpha.c</path>
<path>dmdorig/dmd/utf.c</path>
<path>dmdorig/dmd/utf.h</path>
<path>dmdorig/dmd/version.c</path>
<path>dmdorig/dmd/version.h</path>
<path>dmdorig/phobos</path>
<path>dmdorig/phobos/errno.c</path>
<path>dmdorig/phobos/etc</path>
<path>dmdorig/phobos/etc/c</path>
<path>dmdorig/phobos/etc/c/zlib</path>
<path>dmdorig/phobos/etc/c/zlib/adler32.c</path>
<path>dmdorig/phobos/etc/c/zlib/compress.c</path>
<path>dmdorig/phobos/etc/c/zlib/crc32.c</path>
<path>dmdorig/phobos/etc/c/zlib/crc32.h</path>
<path>dmdorig/phobos/etc/c/zlib/deflate.c</path>
<path>dmdorig/phobos/etc/c/zlib/deflate.h</path>
<path>dmdorig/phobos/etc/c/zlib/example.c</path>
<path>dmdorig/phobos/etc/c/zlib/gzio.c</path>
<path>dmdorig/phobos/etc/c/zlib/infback.c</path>
<path>dmdorig/phobos/etc/c/zlib/inffast.c</path>
<path>dmdorig/phobos/etc/c/zlib/inffast.h</path>
<path>dmdorig/phobos/etc/c/zlib/inffixed.h</path>
<path>dmdorig/phobos/etc/c/zlib/inflate.c</path>
<path>dmdorig/phobos/etc/c/zlib/inflate.h</path>
<path>dmdorig/phobos/etc/c/zlib/inftrees.c</path>
<path>dmdorig/phobos/etc/c/zlib/inftrees.h</path>
<path>dmdorig/phobos/etc/c/zlib/minigzip.c</path>
<path>dmdorig/phobos/etc/c/zlib/trees.c</path>
<path>dmdorig/phobos/etc/c/zlib/trees.h</path>
<path>dmdorig/phobos/etc/c/zlib/uncompr.c</path>
<path>dmdorig/phobos/etc/c/zlib/zconf.h</path>
<path>dmdorig/phobos/etc/c/zlib/zconf.in.h</path>
<path>dmdorig/phobos/etc/c/zlib/zlib.h</path>
<path>dmdorig/phobos/etc/c/zlib/zutil.c</path>
<path>dmdorig/phobos/etc/c/zlib/zutil.h</path>
<path>dmdorig/phobos/internal</path>
<path>dmdorig/phobos/internal/complex.c</path>
<path>dmdorig/phobos/internal/critical.c</path>
<path>dmdorig/phobos/internal/deh.c</path>
<path>dmdorig/phobos/internal/mars.h</path>
<path>dmdorig/phobos/internal/monitor.c</path>
<path>lphobos</path>
<path>lphobos/build.sh</path>
<path>suite</path>
<path>suite/dwarfdebug</path>
<path>suite/dwarfdebug/dwarf1</path>
<path>suite/dwarfdebug/dwarf1/build.sh</path>
<path>suite/dwarfdebug/dwarf2</path>
<path>suite/dwarfdebug/dwarf2/build.sh</path>
<path>tango</path>
<path>tango/lib</path>
<path>tango/lib/common</path>
<path>tango/lib/common/tango</path>
<path>tango/lib/common/tango/stdc</path>
<path>tango/lib/common/tango/stdc/wrap.c</path>
<path>tango/lib/compiler</path>
<path>tango/lib/compiler/llvmdc</path>
<path>tango/lib/compiler/llvmdc/critical.c</path>
<path>tango/lib/compiler/llvmdc/mars.h</path>
<path>tango/lib/compiler/llvmdc/monitor.c</path>
<path>tests</path>
<path>tests/dstress</path>
<path>tests/dstress/benchmark</path>
<path>tests/dstress/benchmark/ackermann</path>
<path>tests/dstress/benchmark/ackermann/ackermann_c.c</path>
<path>tests/dstress/benchmark/cowell-shah</path>
<path>tests/dstress/benchmark/cowell-shah/benchmark.c</path>
<path>tests/dstress/benchmark/known_gcc_problems</path>
<path>tests/dstress/benchmark/known_gcc_problems/common_subexpressions_01_c.c</path>
<path>tests/dstress/benchmark/oopack</path>
<path>tests/dstress/benchmark/oopack/oopack_v1p8_cpp.cpp</path>
<path>tests/dstress/crashRun.c</path>
<path>tests/dstress/dstress.c</path>
<path>tests/dstress/extract__.c</path>
<path>tests/dstress/ifeq__.c</path>
<path>tests/dstress/return__.c</path>
<path>e2ir.c</path>
<path>tango-llvmdc</path>
<path>tango-llvmdc/lib</path>
<path>tango-llvmdc/lib/common</path>
<path>tango-llvmdc/lib/common/tango</path>
<path>tango-llvmdc/lib/common/tango/stdc</path>
<path>tango-llvmdc/lib/common/tango/stdc/wrap.c</path>
<path>tango-llvmdc/lib/compiler</path>
<path>tango-llvmdc/lib/compiler/dmd</path>
<path>tango-llvmdc/lib/compiler/dmd/complex.c</path>
<path>tango-llvmdc/lib/compiler/dmd/critical.c</path>
<path>tango-llvmdc/lib/compiler/dmd/deh.c</path>
<path>tango-llvmdc/lib/compiler/dmd/mars.h</path>
<path>tango-llvmdc/lib/compiler/dmd/monitor.c</path>
<path>tango-llvmdc/lib/compiler/gdc</path>
<path>tango-llvmdc/lib/compiler/gdc/config</path>
<path>tango-llvmdc/lib/compiler/gdc/config/gen_config1.c</path>
<path>tango-llvmdc/lib/compiler/gdc/config/gen_math.c</path>
<path>tango-llvmdc/lib/compiler/gdc/config/gen_unix.c</path>
<path>tango-llvmdc/lib/compiler/gdc/config/makestruct.h</path>
<path>tango-llvmdc/lib/compiler/gdc/critical.c</path>
<path>tango-llvmdc/lib/compiler/gdc/deh.c</path>
<path>tango-llvmdc/lib/compiler/gdc/gcc</path>
<path>tango-llvmdc/lib/compiler/gdc/gcc/aix_float.h</path>
<path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_fdset.c</path>
<path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_math.c</path>
<path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_stdio.c</path>
<path>tango-llvmdc/lib/compiler/gdc/gcc/cbridge_time.c</path>
<path>tango-llvmdc/lib/compiler/gdc/mars.h</path>
<path>tango-llvmdc/lib/compiler/gdc/memory_dyld.c</path>
<path>tango-llvmdc/lib/compiler/gdc/memory_freebsd.c</path>
<path>tango-llvmdc/lib/compiler/gdc/monitor.c</path>
<path>tango-llvmdc/lib/compiler/llvmdc</path>
<path>tango-llvmdc/lib/compiler/llvmdc/critical.c</path>
<path>tango-llvmdc/lib/compiler/llvmdc/mars.h</path>
<path>tango-llvmdc/lib/compiler/llvmdc/monitor.c</path>
<path>tango-llvmdc/patches</path>
<path>tango-llvmdc/patches/proposals</path>
<path>tango-llvmdc/patches/proposals/integrated_locks</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/dmd/monitor.c</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc</path>
<path>tango-llvmdc/patches/proposals/integrated_locks/lib/compiler/gdc/monitor.c</path>
<path>runtime/build.sh</path>
<path>runtime/internal</path>
<path>runtime/internal/critical.c</path>
<path>runtime/internal/mars.h</path>
<path>runtime/internal/monitor.c</path>
<path>build</path>
<path>build/CMakeFiles</path>
<path>build/CMakeFiles/CompilerIdC</path>
<path>build/CMakeFiles/CompilerIdC/CMakeCCompilerId.c</path>
<path>build/CMakeFiles/CompilerIdCXX</path>
<path>build/CMakeFiles/CompilerIdCXX/CMakeCXXCompilerId.cpp</path>
<path>build/dmd</path>
<path>build/dmd/id.c</path>
<path>build/dmd/id.h</path>
<path>build/dmd/impcnvtab.c</path>
<path>dmd2.020</path>
<path>dmd2.020/access.c</path>
<path>dmd2.020/aggregate.h</path>
<path>dmd2.020/array.c</path>
<path>dmd2.020/arrayop.c</path>
<path>dmd2.020/arraytypes.h</path>
<path>dmd2.020/attrib.c</path>
<path>dmd2.020/attrib.h</path>
<path>dmd2.020/bit.c</path>
<path>dmd2.020/builtin.c</path>
<path>dmd2.020/cast.c</path>
<path>dmd2.020/class.c</path>
<path>dmd2.020/clone.c</path>
<path>dmd2.020/complex_t.h</path>
<path>dmd2.020/cond.c</path>
<path>dmd2.020/cond.h</path>
<path>dmd2.020/constfold.c</path>
<path>dmd2.020/dchar.c</path>
<path>dmd2.020/dchar.h</path>
<path>dmd2.020/declaration.c</path>
<path>dmd2.020/declaration.h</path>
<path>dmd2.020/delegatize.c</path>
<path>dmd2.020/doc.c</path>
<path>dmd2.020/doc.h</path>
<path>dmd2.020/dsymbol.c</path>
<path>dmd2.020/dsymbol.h</path>
<path>dmd2.020/dump.c</path>
<path>dmd2.020/e2ir.c</path>
<path>dmd2.020/entity.c</path>
<path>dmd2.020/enum.c</path>
<path>dmd2.020/enum.h</path>
<path>dmd2.020/expression.c</path>
<path>dmd2.020/expression.h</path>
<path>dmd2.020/func.c</path>
<path>dmd2.020/gnuc.c</path>
<path>dmd2.020/gnuc.h</path>
<path>dmd2.020/hdrgen.c</path>
<path>dmd2.020/hdrgen.h</path>
<path>dmd2.020/html.c</path>
<path>dmd2.020/html.h</path>
<path>dmd2.020/identifier.c</path>
<path>dmd2.020/identifier.h</path>
<path>dmd2.020/idgen.c</path>
<path>dmd2.020/impcnvgen.c</path>
<path>dmd2.020/import.c</path>
<path>dmd2.020/import.h</path>
<path>dmd2.020/inifile.c</path>
<path>dmd2.020/init.c</path>
<path>dmd2.020/init.h</path>
<path>dmd2.020/inline.c</path>
<path>dmd2.020/interpret.c</path>
<path>dmd2.020/lexer.c</path>
<path>dmd2.020/lexer.h</path>
<path>dmd2.020/lib.h</path>
<path>dmd2.020/libelf.c</path>
<path>dmd2.020/link.c</path>
<path>dmd2.020/lstring.c</path>
<path>dmd2.020/lstring.h</path>
<path>dmd2.020/macro.c</path>
<path>dmd2.020/macro.h</path>
<path>dmd2.020/man.c</path>
<path>dmd2.020/mangle.c</path>
<path>dmd2.020/mars.c</path>
<path>dmd2.020/mars.h</path>
<path>dmd2.020/md5.c</path>
<path>dmd2.020/md5.h</path>
<path>dmd2.020/mem.c</path>
<path>dmd2.020/mem.h</path>
<path>dmd2.020/module.c</path>
<path>dmd2.020/module.h</path>
<path>dmd2.020/mtype.c</path>
<path>dmd2.020/mtype.h</path>
<path>dmd2.020/opover.c</path>
<path>dmd2.020/optimize.c</path>
<path>dmd2.020/parse.c</path>
<path>dmd2.020/parse.h</path>
<path>dmd2.020/port.h</path>
<path>dmd2.020/root.c</path>
<path>dmd2.020/root.h</path>
<path>dmd2.020/scope.c</path>
<path>dmd2.020/scope.h</path>
<path>dmd2.020/statement.c</path>
<path>dmd2.020/statement.h</path>
<path>dmd2.020/staticassert.c</path>
<path>dmd2.020/staticassert.h</path>
<path>dmd2.020/stringtable.c</path>
<path>dmd2.020/stringtable.h</path>
<path>dmd2.020/struct.c</path>
<path>dmd2.020/template.c</path>
<path>dmd2.020/template.h</path>
<path>dmd2.020/tocsym.c</path>
<path>dmd2.020/todt.c</path>
<path>dmd2.020/toir.c</path>
<path>dmd2.020/toir.h</path>
<path>dmd2.020/toobj.c</path>
<path>dmd2.020/total.h</path>
<path>dmd2.020/traits.c</path>
<path>dmd2.020/typinf.c</path>
<path>dmd2.020/unialpha.c</path>
<path>dmd2.020/utf.c</path>
<path>dmd2.020/utf.h</path>
<path>dmd2.020/version.c</path>
<path>dmd2.020/version.h</path>
<path>dmd36</path>
<path>dmd36/access.c</path>
<path>dmd36/aggregate.h</path>
<path>dmd36/array.c</path>
<path>dmd36/arrayop.c</path>
<path>dmd36/arraytypes.h</path>
<path>dmd36/attrib.c</path>
<path>dmd36/attrib.h</path>
<path>dmd36/bit.c</path>
<path>dmd36/cast.c</path>
<path>dmd36/class.c</path>
<path>dmd36/clone.c</path>
<path>dmd36/complex_t.h</path>
<path>dmd36/cond.c</path>
<path>dmd36/cond.h</path>
<path>dmd36/constfold.c</path>
<path>dmd36/dchar.c</path>
<path>dmd36/dchar.h</path>
<path>dmd36/declaration.c</path>
<path>dmd36/declaration.h</path>
<path>dmd36/delegatize.c</path>
<path>dmd36/doc.c</path>
<path>dmd36/doc.h</path>
<path>dmd36/dsymbol.c</path>
<path>dmd36/dsymbol.h</path>
<path>dmd36/dump.c</path>
<path>dmd36/e2ir.c</path>
<path>dmd36/entity.c</path>
<path>dmd36/enum.c</path>
<path>dmd36/enum.h</path>
<path>dmd36/expression.c</path>
<path>dmd36/expression.h</path>
<path>dmd36/func.c</path>
<path>dmd36/gnuc.c</path>
<path>dmd36/gnuc.h</path>
<path>dmd36/hdrgen.c</path>
<path>dmd36/hdrgen.h</path>
<path>dmd36/html.c</path>
<path>dmd36/html.h</path>
<path>dmd36/identifier.c</path>
<path>dmd36/identifier.h</path>
<path>dmd36/idgen.c</path>
<path>dmd36/impcnvgen.c</path>
<path>dmd36/import.c</path>
<path>dmd36/import.h</path>
<path>dmd36/inifile.c</path>
<path>dmd36/init.c</path>
<path>dmd36/init.h</path>
<path>dmd36/inline.c</path>
<path>dmd36/interpret.c</path>
<path>dmd36/lexer.c</path>
<path>dmd36/lexer.h</path>
<path>dmd36/lib.h</path>
<path>dmd36/libelf.c</path>
<path>dmd36/link.c</path>
<path>dmd36/lstring.c</path>
<path>dmd36/lstring.h</path>
<path>dmd36/macro.c</path>
<path>dmd36/macro.h</path>
<path>dmd36/man.c</path>
<path>dmd36/mangle.c</path>
<path>dmd36/mars.c</path>
<path>dmd36/mars.h</path>
<path>dmd36/md5.c</path>
<path>dmd36/md5.h</path>
<path>dmd36/mem.c</path>
<path>dmd36/mem.h</path>
<path>dmd36/module.c</path>
<path>dmd36/module.h</path>
<path>dmd36/mtype.c</path>
<path>dmd36/mtype.h</path>
<path>dmd36/opover.c</path>
<path>dmd36/optimize.c</path>
<path>dmd36/parse.c</path>
<path>dmd36/parse.h</path>
<path>dmd36/port.h</path>
<path>dmd36/root.c</path>
<path>dmd36/root.h</path>
<path>dmd36/scope.c</path>
<path>dmd36/scope.h</path>
<path>dmd36/statement.c</path>
<path>dmd36/statement.h</path>
<path>dmd36/staticassert.c</path>
<path>dmd36/staticassert.h</path>
<path>dmd36/stringtable.c</path>
<path>dmd36/stringtable.h</path>
<path>dmd36/struct.c</path>
<path>dmd36/template.c</path>
<path>dmd36/template.h</path>
<path>dmd36/tocsym.c</path>
<path>dmd36/todt.c</path>
<path>dmd36/toir.c</path>
<path>dmd36/toir.h</path>
<path>dmd36/toobj.c</path>
<path>dmd36/total.h</path>
<path>dmd36/typinf.c</path>
<path>dmd36/unialpha.c</path>
<path>dmd36/utf.c</path>
<path>dmd36/utf.h</path>
<path>dmd36/version.c</path>
<path>dmd36/version.h</path>
</blacklist>
<build>
<buildtool>make</buildtool>
<builddir/>
</build>
<other>
<prio>0</prio>
<otherbin/>
<defaulttarget/>
<otheroptions/>
<selectedenvironment>default</selectedenvironment>
<environments>
<default/>
</environments>
</other>
<make>
<abortonerror>false</abortonerror>
<numberofjobs>0</numberofjobs>
<prio>0</prio>
<dontact>false</dontact>
<makebin/>
<defaulttarget/>
<makeoptions/>
<selectedenvironment>default</selectedenvironment>
<environments>
<default/>
</environments>
</make>
<general>
<activedir>tangotests</activedir>
</general>
</kdevcustomproject>
<cppsupportpart>
<filetemplates>
<interfacesuffix>.h</interfacesuffix>
<implementationsuffix>.cpp</implementationsuffix>
</filetemplates>
</cppsupportpart>
<kdevdebugger>
<general>
<gdbpath/>
<dbgshell/>
<configGdbScript/>
<runShellScript/>
<runGdbScript/>
<breakonloadinglibs>true</breakonloadinglibs>
<separatetty>false</separatetty>
<floatingtoolbar>false</floatingtoolbar>
<raiseGDBOnStart>false</raiseGDBOnStart>
</general>
<display>
<staticmembers>false</staticmembers>
<demanglenames>true</demanglenames>
<outputradix>10</outputradix>
</display>
</kdevdebugger>
</kdevelop>

View file

@ -1,239 +0,0 @@
# KDevelop Custom Project File List
dmd
dmd/access.c
dmd/aggregate.h
dmd/array.c
dmd/arrayop.c
dmd/arraytypes.h
dmd/attrib.c
dmd/attrib.h
dmd/cast.c
dmd/class.c
dmd/clone.c
dmd/complex_t.h
dmd/cond.c
dmd/cond.h
dmd/constfold.c
dmd/dchar.c
dmd/dchar.h
dmd/declaration.c
dmd/declaration.h
dmd/delegatize.c
dmd/doc.c
dmd/doc.h
dmd/dsymbol.c
dmd/dsymbol.h
dmd/dump.c
dmd/entity.c
dmd/enum.c
dmd/enum.h
dmd/expression.c
dmd/expression.h
dmd/func.c
dmd/gnuc.c
dmd/gnuc.h
dmd/hdrgen.c
dmd/hdrgen.h
dmd/html.c
dmd/html.h
dmd/identifier.c
dmd/identifier.h
dmd/idgen.c
dmd/impcnvgen.c
dmd/import.c
dmd/import.h
dmd/inifile.c
dmd/init.c
dmd/init.h
dmd/inline.c
dmd/interpret.c
dmd/lexer.c
dmd/lexer.h
dmd/lstring.c
dmd/lstring.h
dmd/macro.c
dmd/macro.h
dmd/mangle.c
dmd/mars.c
dmd/mars.h
dmd/mem.c
dmd/mem.h
dmd/module.c
dmd/module.h
dmd/mtype.c
dmd/mtype.h
dmd/opover.c
dmd/optimize.c
dmd/parse.c
dmd/parse.h
dmd/port.h
dmd/root.c
dmd/root.h
dmd/scope.c
dmd/scope.h
dmd/statement.c
dmd/statement.h
dmd/staticassert.c
dmd/staticassert.h
dmd/stringtable.c
dmd/stringtable.h
dmd/struct.c
dmd/template.c
dmd/template.h
dmd/total.h
dmd/unialpha.c
dmd/utf.c
dmd/utf.h
dmd/version.c
dmd/version.h
dmd2
dmd2/access.c
dmd2/aggregate.h
dmd2/array.c
dmd2/arrayop.c
dmd2/arraytypes.h
dmd2/attrib.c
dmd2/attrib.h
dmd2/builtin.c
dmd2/cast.c
dmd2/class.c
dmd2/clone.c
dmd2/complex_t.h
dmd2/cond.c
dmd2/cond.h
dmd2/constfold.c
dmd2/dchar.c
dmd2/dchar.h
dmd2/declaration.c
dmd2/declaration.h
dmd2/delegatize.c
dmd2/doc.c
dmd2/doc.h
dmd2/dsymbol.c
dmd2/dsymbol.h
dmd2/dump.c
dmd2/entity.c
dmd2/enum.c
dmd2/enum.h
dmd2/expression.c
dmd2/expression.h
dmd2/func.c
dmd2/gnuc.c
dmd2/gnuc.h
dmd2/hdrgen.c
dmd2/hdrgen.h
dmd2/html.c
dmd2/html.h
dmd2/id.c
dmd2/id.h
dmd2/identifier.c
dmd2/identifier.h
dmd2/idgen.c
dmd2/impcnvgen.c
dmd2/impcnvtab.c
dmd2/import.c
dmd2/import.h
dmd2/inifile.c
dmd2/init.c
dmd2/init.h
dmd2/inline.c
dmd2/interpret.c
dmd2/lexer.c
dmd2/lexer.h
dmd2/lstring.c
dmd2/lstring.h
dmd2/macro.c
dmd2/macro.h
dmd2/man.c
dmd2/mangle.c
dmd2/mars.c
dmd2/mars.h
dmd2/mem.c
dmd2/mem.h
dmd2/module.c
dmd2/module.h
dmd2/mtype.c
dmd2/mtype.h
dmd2/opover.c
dmd2/optimize.c
dmd2/parse.c
dmd2/parse.h
dmd2/port.h
dmd2/root.c
dmd2/root.h
dmd2/scope.c
dmd2/scope.h
dmd2/statement.c
dmd2/statement.h
dmd2/staticassert.c
dmd2/staticassert.h
dmd2/stringtable.c
dmd2/stringtable.h
dmd2/struct.c
dmd2/template.c
dmd2/template.h
dmd2/total.h
dmd2/traits.c
dmd2/unialpha.c
dmd2/utf.c
dmd2/utf.h
dmd2/version.c
dmd2/version.h
gen
gen/aa.cpp
gen/aa.h
gen/arrays.cpp
gen/arrays.h
gen/asmstmt.cpp
gen/binops.cpp
gen/classes.cpp
gen/classes.h
gen/complex.cpp
gen/complex.h
gen/dvalue.cpp
gen/dvalue.h
gen/dwarftypes.cpp
gen/enums.h
gen/functions.cpp
gen/functions.h
gen/irstate.cpp
gen/irstate.h
gen/linker.cpp
gen/linker.h
gen/llvm.h
gen/llvmhelpers.cpp
gen/llvmhelpers.h
gen/logger.cpp
gen/logger.h
gen/optimizer.cpp
gen/runtime.cpp
gen/runtime.h
gen/statements.cpp
gen/structs.cpp
gen/structs.h
gen/tocall.cpp
gen/tocsym.cpp
gen/todebug.cpp
gen/todebug.h
gen/todt.cpp
gen/toir.cpp
gen/tollvm.cpp
gen/tollvm.h
gen/toobj.cpp
gen/typeinf.h
gen/typinf.cpp
ir
ir/ir.h
ir/irforw.h
ir/irfunction.cpp
ir/irfunction.h
ir/irmodule.cpp
ir/irmodule.h
ir/irstruct.cpp
ir/irstruct.h
ir/irsymbol.cpp
ir/irsymbol.h
ir/irtype.cpp
ir/irtype.h
ir/irvar.cpp
ir/irvar.h

View file

@ -12,14 +12,14 @@ class C : I
int i = 42;
override void func()
{
printf("hello %d\n", i);
printf("hello %d from %p\n", i, this);
i++;
}
}
void main()
{
scope c = new C;
auto c = new C;
{c.func();}
{
I i = c;