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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3186,6 +3186,14 @@ d_uns64 TypeDelegate::size(Loc loc)
return PTRSIZE * 2; 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) void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
if (mod != this->mod) if (mod != this->mod)

View file

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

View file

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

View file

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

View file

@ -50,7 +50,7 @@ struct AttribDeclaration : Dsymbol
void toCBuffer(OutBuffer *buf, HdrGenState *hgs); void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
AttribDeclaration *isAttribDeclaration() { return this; } 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); int cvMember(unsigned char *p);
}; };

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3694,6 +3694,14 @@ d_uns64 TypeDelegate::size(Loc loc)
return PTRSIZE * 2; 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) void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{ {
if (mod != this->mod) if (mod != this->mod)

View file

@ -516,6 +516,7 @@ struct TypeDelegate : TypeNext
Type *syntaxCopy(); Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc); Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
unsigned alignsize(); // added in LDC
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod); void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *defaultInit(Loc loc); Expression *defaultInit(Loc loc);
int isZeroInit(); 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) LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
{ {
Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars()); Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
@ -241,6 +244,9 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
Type* arrnext = arrinittype->nextOf(); Type* arrnext = arrinittype->nextOf();
const LLType* elemty = DtoType(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); assert(arrinit->index.dim == arrinit->value.dim);
for (unsigned i=0,j=0; i < tdim; ++i) for (unsigned i=0,j=0; i < tdim; ++i)
{ {
@ -292,23 +298,51 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
v = DtoConstInitializer(arrinit->loc, t->nextOf(), init); v = DtoConstInitializer(arrinit->loc, t->nextOf(), init);
assert(v); 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; inits[i] = v;
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "llval: " << *v << '\n'; Logger::cout() << "llval: " << *v << '\n';
} }
Logger::println("building constant array"); Logger::println("building constant array");
LLConstant* constarr;
const LLArrayType* arrty = LLArrayType::get(elemty,tdim); 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) if (arrinittype->ty == Tsarray)
return constarr; return constarr;
else else
assert(arrinittype->ty == Tarray); 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* idxs[2] = { DtoConstUint(0), DtoConstUint(0) };
LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2); LLConstant* gep = llvm::ConstantExpr::getGetElementPtr(gvar,idxs,2);
gep = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(elemty));
return DtoConstSlice(DtoConstSize_t(tdim),gep); 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; 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) LLValue* DtoArrayLen(DValue* v)
{ {

View file

@ -9,7 +9,6 @@ const llvm::ArrayType* DtoStaticArrayType(Type* sarrayTy);
LLConstant* DtoConstArrayInitializer(ArrayInitializer* si); LLConstant* DtoConstArrayInitializer(ArrayInitializer* si);
LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr); LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr);
LLConstant* DtoConstStaticArray(const LLType* t, LLConstant* c);
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src); void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* 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) { if (dVararg) {
ClassDeclaration* ti = Type::typeinfo; paramvec.push_back(DtoType(Type::typeinfo->type->arrayOf())); // _arguments
ti->toObjFile(0); // TODO: multiobj paramvec.push_back(getVoidPtrType()); // _argptr
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));
} }
// number of formal params // number of formal params
@ -286,7 +278,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
Logger::println("isMember = this is: %s", ad->type->toChars()); Logger::println("isMember = this is: %s", ad->type->toChars());
thisty = DtoType(ad->type); thisty = DtoType(ad->type);
//Logger::cout() << "this llvm type: " << *thisty << '\n'; //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); thisty = getPtrToType(thisty);
} }
else { else {
@ -547,35 +539,36 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
} }
// we never reference parameters of function prototypes // we never reference parameters of function prototypes
std::string str;
if (!declareOnly) if (!declareOnly)
{ {
// name parameters // name parameters
llvm::Function::arg_iterator iarg = func->arg_begin(); llvm::Function::arg_iterator iarg = func->arg_begin();
if (f->retInPtr) { if (f->retInPtr) {
iarg->setName(".sretarg"); iarg->setName(".sret_arg");
fdecl->ir.irFunc->retArg = iarg; fdecl->ir.irFunc->retArg = iarg;
++iarg; ++iarg;
} }
if (f->usesThis) { if (f->usesThis) {
iarg->setName("this"); iarg->setName(".this_arg");
fdecl->ir.irFunc->thisArg = iarg; fdecl->ir.irFunc->thisArg = iarg;
assert(fdecl->ir.irFunc->thisArg); assert(fdecl->ir.irFunc->thisArg);
++iarg; ++iarg;
} }
else if (f->usesNest) { else if (f->usesNest) {
iarg->setName(".nest"); iarg->setName(".nest_arg");
fdecl->ir.irFunc->nestArg = iarg; fdecl->ir.irFunc->nestArg = iarg;
assert(fdecl->ir.irFunc->nestArg); assert(fdecl->ir.irFunc->nestArg);
++iarg; ++iarg;
} }
if (f->linkage == LINKd && f->varargs == 1) { if (f->linkage == LINKd && f->varargs == 1) {
iarg->setName("_arguments"); iarg->setName("._arguments");
fdecl->ir.irFunc->_arguments = iarg; fdecl->ir.irFunc->_arguments = iarg;
++iarg; ++iarg;
iarg->setName("_argptr"); iarg->setName("._argptr");
fdecl->ir.irFunc->_argptr = iarg; fdecl->ir.irFunc->_argptr = iarg;
++iarg; ++iarg;
} }
@ -597,7 +590,10 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
assert(!argvd->ir.irLocal); assert(!argvd->ir.irLocal);
argvd->ir.irLocal = new IrLocal(argvd); argvd->ir.irLocal = new IrLocal(argvd);
argvd->ir.irLocal->value = iarg; argvd->ir.irLocal->value = iarg;
iarg->setName(argvd->ident->toChars());
str = argvd->ident->toChars();
str.append("_arg");
iarg->setName(str);
k++; k++;
} }
@ -671,8 +667,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
if (fd->isMain()) if (fd->isMain())
gIR->emitMain = true; gIR->emitMain = true;
std::string entryname("entry_"); std::string entryname("entry");
entryname.append(fd->toPrettyChars());
llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(entryname,func); llvm::BasicBlock* beginbb = llvm::BasicBlock::Create(entryname,func);
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endentry",func); llvm::BasicBlock* endbb = llvm::BasicBlock::Create("endentry",func);
@ -710,7 +705,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
LLValue* thisvar = irfunction->thisArg; LLValue* thisvar = irfunction->thisArg;
assert(thisvar); assert(thisvar);
LLValue* thismem = DtoAlloca(thisvar->getType(), ".this"); LLValue* thismem = DtoAlloca(thisvar->getType(), "this");
DtoStore(thisvar, thismem); DtoStore(thisvar, thismem);
irfunction->thisArg = thismem; irfunction->thisArg = thismem;
@ -760,7 +755,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
if (!refout && (!DtoIsPassedByRef(vd->type) || lazy)) if (!refout && (!DtoIsPassedByRef(vd->type) || lazy))
{ {
LLValue* a = irloc->value; LLValue* a = irloc->value;
LLValue* v = DtoAlloca(a->getType(), "."+a->getName()); LLValue* v = DtoAlloca(a->getType(), vd->ident->toChars());
DtoStore(a,v); DtoStore(a,v);
irloc->value = v; irloc->value = v;
} }
@ -822,7 +817,7 @@ void DtoDefineFunc(FuncDeclaration* fd)
ClassDeclaration* cd = fd->isMember2()->isClassDeclaration(); ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
assert(cd); assert(cd);
assert(cd->vthis); 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)); DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
} }

View file

@ -23,6 +23,7 @@ struct FuncDeclaration;
struct Module; struct Module;
struct TypeStruct; struct TypeStruct;
struct BaseClass; struct BaseClass;
struct AnonDeclaration;
struct EnclosingHandler; struct EnclosingHandler;
struct IrModule; struct IrModule;
@ -147,10 +148,6 @@ struct IRState
StructVector structs; StructVector structs;
IrStruct* topstruct(); IrStruct* topstruct();
// classes TODO move into IRClass
typedef std::vector<ClassDeclaration*> ClassDeclVec;
ClassDeclVec classes;
// D main function // D main function
bool emitMain; bool emitMain;
llvm::Function* mainFunc; llvm::Function* mainFunc;

View file

@ -338,7 +338,7 @@ DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
{ {
ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration(); ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
LLValue* val = DtoLoad(irfunc->thisArg); 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 else
ctx = irfunc->nestArg; ctx = irfunc->nestArg;
@ -374,7 +374,7 @@ LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
if (!cd || !cd->vthis) if (!cd || !cd->vthis)
return getNullPtr(getVoidPtrType()); return getNullPtr(getVoidPtrType());
LLValue* val = DtoLoad(irfunc->thisArg); 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 else
{ {
@ -964,73 +964,68 @@ void DtoConstInitGlobal(VarDeclaration* vd)
if (vd->ir.initialized) return; if (vd->ir.initialized) return;
vd->ir.initialized = gIR->dmodule; vd->ir.initialized = gIR->dmodule;
Logger::println("* DtoConstInitGlobal(%s)", vd->toChars()); Logger::println("DtoConstInitGlobal(%s) @ %s", vd->toChars(), vd->locToChars());
LOG_SCOPE; 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; bool doLazyInit = false;
if (vd->parent && vd->parent->isFuncDeclaration() && vd->init && vd->init->isExpInitializer()) { Dsymbol* par = vd->toParent2();
_init = DtoConstInitializer(vd->loc, vd->type, NULL);
emitRTstaticInit = true;
}
else {
_init = DtoConstInitializer(vd->loc, vd->type, vd->init);
}
const LLType* _type = DtoType(vd->type); if (par && par->isFuncDeclaration() && vd->init)
Type* t = vd->type->toBasetype(); {
if (ExpInitializer* einit = vd->init->isExpInitializer())
//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))
{ {
assert(_init->getType()->getContainedType(0) == _type); if (!einit->exp->isConst())
llvm::GlobalVariable* gv = llvm::cast<llvm::GlobalVariable>(_init); {
assert(t->ty == Tstruct); // mark as needing lazy now
TypeStruct* ts = (TypeStruct*)t; doLazyInit = true;
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 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; bool istempl = false;
if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) { if ((vd->storage_class & STCcomdat) || (vd->parent && DtoIsTemplateInstance(vd->parent))) {
istempl = true; istempl = true;
} }
if (_init && _init->getType() != _type) // assign the initializer
_type = _init->getType(); llvm::GlobalVariable* globalvar = llvm::cast<llvm::GlobalVariable>(glob->value);
llvm::cast<LLOpaqueType>(vd->ir.irGlobal->type.get())->refineAbstractTypeTo(_type);
_type = vd->ir.irGlobal->type.get();
llvm::GlobalVariable* gvar = llvm::cast<llvm::GlobalVariable>(vd->ir.irGlobal->value);
if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl)) if (!(vd->storage_class & STCextern) && (vd->getModule() == gIR->dmodule || istempl))
{ {
if (Logger::enabled()) if (Logger::enabled())
{ {
Logger::println("setting initializer"); Logger::println("setting initializer");
Logger::cout() << "global: " << *gvar << '\n'; Logger::cout() << "global: " << *gvar << '\n';
Logger::cout() << "init: " << *_init << '\n'; Logger::cout() << "init: " << *initVal << '\n';
} }
gvar->setInitializer(_init);
gvar->setInitializer(initVal);
// do debug info // do debug info
if (global.params.symdebug) if (global.params.symdebug)
{ {
@ -1040,8 +1035,8 @@ void DtoConstInitGlobal(VarDeclaration* vd)
} }
} }
if (emitRTstaticInit) if (doLazyInit)
DtoLazyStaticInit(istempl, gvar, vd->init, t); DtoLazyStaticInit(istempl, gvar, vd->init, vd->type);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -1396,18 +1391,18 @@ LLValue* DtoRawVarDeclaration(VarDeclaration* var)
// INITIALIZER HELPERS // INITIALIZER HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/ ////////////////////////////////////////////////////////////////////////////////////////*/
LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init) LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
{ {
LLConstant* _init = 0; // may return zero LLConstant* _init = 0; // may return zero
if (!init) if (!init)
{ {
Logger::println("const default initializer for %s", type->toChars()); 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()) else if (ExpInitializer* ex = init->isExpInitializer())
{ {
Logger::println("const expression initializer"); Logger::println("const expression initializer");
_init = ex->exp->toConstElem(gIR); _init = DtoConstExpInit(loc, type, ex->exp);;
} }
else if (StructInitializer* si = init->isStructInitializer()) 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"); Logger::println("DtoConstFieldInitializer");
LOG_SCOPE; LOG_SCOPE;
@ -1530,7 +1525,7 @@ DValue* DtoInitializer(LLValue* target, Initializer* init)
static LLConstant* expand_to_sarray(Type *base, Expression* exp) 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); const LLType* dstTy = DtoType(base);
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "final llvm type requested: " << *dstTy << '\n'; 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); LLConstant* val = exp->toConstElem(gIR);
Type* expbase = exp->type->toBasetype(); Type* expbase = exp->type->toBasetype();
Type* t = base; Logger::println("expbase: %s", expbase->toChars());
Type* t = base->toBasetype();
LLSmallVector<size_t, 4> dims; 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) while(1)
{ {
Logger::println("t: %s", t->toChars());
if (t->equals(expbase)) if (t->equals(expbase))
break; break;
assert(t->ty == Tsarray); assert(t->ty == Tsarray);
@ -1568,10 +1576,8 @@ static LLConstant* expand_to_sarray(Type *base, Expression* exp)
return val; 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* expbase = exp->type->toBasetype();
Type* base = 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"); error(loc, "static arrays of voids have no default initializer");
fatal(); fatal();
} }
Logger::println("type is a static array, building constant array initializer to single value"); Logger::println("type is a static array, building constant array initializer to single value");
return expand_to_sarray(base, exp); return expand_to_sarray(base, exp);
} }
@ -1594,7 +1599,6 @@ LLConstant* DtoDefaultInit(Loc& loc, Type* type)
fatal(); fatal();
} }
assert(0); assert(0);
} }
return exp->toConstElem(gIR); return exp->toConstElem(gIR);
@ -1615,6 +1619,7 @@ void DtoAnnotation(const char* str)
++p; ++p;
} }
// create a noop with the code as the result name! // 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()); 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); LLValue* DtoRawVarDeclaration(VarDeclaration* var);
// initializer helpers // initializer helpers
LLConstant* DtoConstInitializer(Loc& loc, Type* type, Initializer* init); LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init);
LLConstant* DtoConstFieldInitializer(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); DValue* DtoInitializer(LLValue* target, Initializer* init);
// annotation generator // annotation generator
@ -108,9 +109,6 @@ DValue* DtoBinRem(Type* resulttype, DValue* lhs, DValue* rhs);
// target stuff // target stuff
void findDefaultTarget(); void findDefaultTarget();
/// get the default initializer of the type
LLConstant* DtoDefaultInit(Loc& loc, Type* t);
// fixup an overloaded intrinsic name string // fixup an overloaded intrinsic name string
void DtoOverloadedIntrinsicName(TemplateInstance* ti, TemplateDeclaration* td, std::string& name); 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() static void LLVM_D_BuildRuntimeModule()
{ {
Logger::println("building module");
M = new llvm::Module("ldc internal runtime"); M = new llvm::Module("ldc internal runtime");
Logger::println("building basic types");
const LLType* voidTy = LLType::VoidTy; const LLType* voidTy = LLType::VoidTy;
const LLType* boolTy = LLType::Int1Ty; const LLType* boolTy = LLType::Int1Ty;
const LLType* byteTy = LLType::Int8Ty; const LLType* byteTy = LLType::Int8Ty;
@ -144,6 +146,7 @@ static void LLVM_D_BuildRuntimeModule()
const LLType* longTy = LLType::Int64Ty; const LLType* longTy = LLType::Int64Ty;
const LLType* sizeTy = DtoSize_t(); const LLType* sizeTy = DtoSize_t();
Logger::println("building float types");
const LLType* floatTy = LLType::FloatTy; const LLType* floatTy = LLType::FloatTy;
const LLType* doubleTy = LLType::DoubleTy; const LLType* doubleTy = LLType::DoubleTy;
const LLType* realTy; const LLType* realTy;
@ -156,15 +159,22 @@ static void LLVM_D_BuildRuntimeModule()
const LLType* cdoubleTy = llvm::StructType::get(doubleTy, doubleTy, NULL); const LLType* cdoubleTy = llvm::StructType::get(doubleTy, doubleTy, NULL);
const LLType* crealTy = llvm::StructType::get(realTy, realTy, NULL); const LLType* crealTy = llvm::StructType::get(realTy, realTy, NULL);
Logger::println("building aggr types");
const LLType* voidPtrTy = rt_ptr(byteTy); const LLType* voidPtrTy = rt_ptr(byteTy);
const LLType* stringTy = rt_array(byteTy); const LLType* stringTy = rt_array(byteTy);
const LLType* wstringTy = rt_array(shortTy); const LLType* wstringTy = rt_array(shortTy);
const LLType* dstringTy = rt_array(intTy); 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()); Logger::println("building class types");
const LLType* typeInfoTy = rt_ptr(Type::typeinfo->type->ir.type->get()); 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()); 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); DtoDwarfStopPoint(loc.linnum);
// DMD doesn't fold stuff like continue/break, and since this isn't really a loop // 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(); llvm::BasicBlock* oldend = gIR->scopeend();

View file

@ -18,36 +18,279 @@
#include "ir/irstruct.h" #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) LLConstant* DtoConstStructInitializer(StructInitializer* si)
{ {
Logger::println("DtoConstStructInitializer: %s", si->toChars()); Logger::println("DtoConstStructInitializer: %s", si->toChars());
LOG_SCOPE; LOG_SCOPE;
// get TypeStruct
assert(si->ad); assert(si->ad);
TypeStruct* ts = (TypeStruct*)si->ad->type; 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()); const llvm::StructType* structtype = isaStruct(ts->ir.type->get());
// log it
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "llvm struct type: " << *structtype << '\n'; Logger::cout() << "llvm struct type: " << *structtype << '\n';
// sanity check
assert(si->value.dim > 0);
assert(si->value.dim == si->vars.dim); assert(si->value.dim == si->vars.dim);
std::vector<DUnionIdx> inits; // vector of final initializer constants
for (int i = 0; i < si->value.dim; ++i) 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]; Initializer* ini = (Initializer*)si->value.data[i];
assert(var);
assert(ini); assert(ini);
VarDeclaration* vd = (VarDeclaration*)si->vars.data[i]; vars[i] = std::make_pair(var, ini);
assert(vd); }
LLConstant* v = DtoConstInitializer(vd->loc, vd->type, ini); // sort it
inits.push_back(DUnionIdx(vd->ir.irField->index, vd->ir.irField->indexOffset, v)); 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); // error handling, report all overlaps before aborting
return si->ad->ir.irStruct->dunion->getConst(inits); 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; IrField* field = vd->ir.irField;
assert(field); assert(field);
unsigned idx = field->index; // get the start pointer
unsigned off = field->indexOffset;
const LLType* st = getPtrToType(DtoType(sd->type)); const LLType* st = getPtrToType(DtoType(sd->type));
// cast to the formal struct type
src = DtoBitCast(src, st); src = DtoBitCast(src, st);
LLValue* val = DtoGEPi(src, 0,idx); // gep to the index
val = DtoBitCast(val, getPtrToType(DtoType(vd->type))); LLValue* val = DtoGEPi(src, 0, field->index);
if (off) // do we need to offset further? (union area)
val = DtoGEPi1(val, off); 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()) if (Logger::enabled())
Logger::cout() << "value: " << *val << '\n'; Logger::cout() << "value: " << *val << '\n';
@ -79,46 +331,46 @@ LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
return val; return val;
} }
//////////////////////////////////////////////////////////////////////////////////////////
void DtoResolveStruct(StructDeclaration* sd) void DtoResolveStruct(StructDeclaration* sd)
{ {
// don't do anything if already been here
if (sd->ir.resolved) return; if (sd->ir.resolved) return;
// make sure above works :P
sd->ir.resolved = true; 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; 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 ... // didn't even know D had those ...
if (sd->sizeok != 1) if (sd->sizeok != 1)
{ {
sd->ir.irStruct = new IrStruct(ts); // nothing more to do
ts->ir.type = new llvm::PATypeHolder(llvm::OpaqueType::get());
return; return;
} }
bool ispacked = (ts->alignsize() == 1); // make this struct current
// create the IrStruct
IrStruct* irstruct = new IrStruct(ts);
sd->ir.irStruct = irstruct;
gIR->structs.push_back(irstruct); gIR->structs.push_back(irstruct);
// add fields // get some info
Array* fields = &sd->fields; bool ispacked = (ts->alignsize() == 1);
for (int k=0; k < fields->dim; k++) bool isunion = sd->isUnionDeclaration();
{
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);
}
// set irstruct info
irstruct->packed = ispacked; irstruct->packed = ispacked;
// defined in this module?
bool thisModule = false; bool thisModule = false;
if (sd->getModule() == gIR->dmodule) if (sd->getModule() == gIR->dmodule)
thisModule = true; thisModule = true;
@ -127,21 +379,29 @@ void DtoResolveStruct(StructDeclaration* sd)
Array* arr = sd->members; Array* arr = sd->members;
for (int k=0; k < arr->dim; k++) { for (int k=0; k < arr->dim; k++) {
Dsymbol* s = (Dsymbol*)arr->data[k]; Dsymbol* s = (Dsymbol*)arr->data[k];
if (FuncDeclaration* fd = s->isFuncDeclaration()) { s->toObjFile(0);
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());
}
} }
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++) { /*for (int k=0; k < sd->members->dim; k++) {
Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]); Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
dsym->toObjFile(); dsym->toObjFile();
@ -149,98 +409,13 @@ void DtoResolveStruct(StructDeclaration* sd)
Logger::println("doing struct fields"); 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;} // refine abstract types for stuff like: struct S{S* next;}
if (irstruct->recty != 0) llvm::cast<llvm::OpaqueType>(ts->ir.type->get())->refineAbstractTypeTo(ST);
{ ST = ts->ir.type->get();
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);
// name type
if (sd->parent->isModule()) { if (sd->parent->isModule()) {
gIR->module->addTypeName(sd->mangle(),structtype); gIR->module->addTypeName(sd->mangle(),ST);
} }
gIR->structs.pop_back(); gIR->structs.pop_back();
@ -265,7 +440,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
initname.append("6__initZ"); initname.append("6__initZ");
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd); 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; sd->ir.irStruct->init = initvar;
gIR->constInitList.push_back(sd); gIR->constInitList.push_back(sd);
@ -286,59 +461,33 @@ void DtoConstInitStruct(StructDeclaration* sd)
IrStruct* irstruct = sd->ir.irStruct; IrStruct* irstruct = sd->ir.irStruct;
gIR->structs.push_back(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()); const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
// go through the field inits and build the default initializer // make sure each offset knows its default initializer
std::vector<LLConstant*> fieldinits_ll; Array* fields = &sd->fields;
size_t nfi = irstruct->defaultFields.size(); for (int k=0; k < fields->dim; k++)
for (size_t i=0; i<nfi; ++i) { {
LLConstant* c; VarDeclaration* v = (VarDeclaration*)fields->data[k];
if (irstruct->defaultFields[i] != NULL) { LLConstant* finit = DtoConstFieldInitializer(v->loc, v->type, v->init);
c = irstruct->defaultFields[i]->ir.irField->constInit; v->ir.irField->constInit = finit;
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);
} }
// generate the union mapper
sd->ir.irStruct->dunion = new DUnion(); // uses gIR->topstruct()
// always generate the constant initalizer // always generate the constant initalizer
if (!sd->zeroInit) { 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 {
Logger::println("Zero initialized"); 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(); 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)); LLValue* val = DtoMemCmp(lhs->getRVal(), rhs->getRVal(), DtoConstSize_t(sz));
return gIR->ir->CreateICmp(cmpop, val, LLConstantInt::get(val->getType(), 0, false), "tmp"); 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 // index a struct one level
LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd); 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 #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 //TODO: StdCall is not a good base on Windows due to extra name mangling
// applied there // applied there
if (global.params.cpu == ARCHx86 && global.params.os != OSWindows) if (global.params.cpu == ARCHx86)
return llvm::CallingConv::X86_StdCall; return (global.params.os != OSWindows) ? llvm::CallingConv::X86_StdCall : llvm::CallingConv::C;
else else
return llvm::CallingConv::Fast; return llvm::CallingConv::Fast;
} }
// on the other hand, here, it's exactly what we want!!! TODO: right?
else if (l == LINKwindows) else if (l == LINKwindows)
return llvm::CallingConv::X86_StdCall; return llvm::CallingConv::X86_StdCall;
else else
@ -155,7 +156,6 @@ void DtoBuildDVarArgList(std::vector<LLValue*>& args, std::vector<llvm::Attribut
} }
// build type info array // build type info array
assert(Type::typeinfo->ir.irStruct->constInit);
const LLType* typeinfotype = DtoType(Type::typeinfo->type); const LLType* typeinfotype = DtoType(Type::typeinfo->type);
const LLArrayType* typeinfoarraytype = LLArrayType::get(typeinfotype,vtype->getNumElements()); 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()); definedCU = DtoDwarfCompileUnit(sd->getModule());
std::vector<LLConstant*> elems; std::vector<LLConstant*> elems;
elems.reserve(ir->offsets.size()); if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
for (IrStruct::OffsetMap::iterator i=ir->offsets.begin(); i!=ir->offsets.end(); ++i)
{ {
unsigned offset = i->first; std::vector<VarDeclaration*>& arr = ir->varDecls;
IrStruct::Offset& o = i->second; 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); LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset);
elems.push_back(DBG_CAST(ptr)); elems.push_back(DBG_CAST(ptr));
}
} }
const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size()); const LLArrayType* at = LLArrayType::get(DBG_TYPE, elems.size());

View file

@ -135,20 +135,27 @@ DValue* VarExp::toElem(IRState* p)
} }
else { else {
Logger::println("a normal variable"); Logger::println("a normal variable");
// take care of forward references of global variables // take care of forward references of global variables
if (vd->isDataseg() || (vd->storage_class & STCextern)) { if (vd->isDataseg() || (vd->storage_class & STCextern)) {
vd->toObjFile(0); // TODO: multiobj 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()); error("variable %s not resolved", vd->toChars());
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n'; Logger::cout() << "unresolved variable had type: " << *DtoType(vd->type) << '\n';
fatal(); fatal();
} }
if (vd->isDataseg() || (vd->storage_class & STCextern)) { if (vd->isDataseg() || (vd->storage_class & STCextern)) {
DtoConstInitGlobal(vd); 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()) else if (FuncDeclaration* fdecl = var->isFuncDeclaration())
@ -369,7 +376,7 @@ DValue* StringExp::toElem(IRState* p)
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage;
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; 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); llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
LLConstant* idxs[2] = { zero, zero }; LLConstant* idxs[2] = { zero, zero };
@ -443,7 +450,7 @@ LLConstant* StringExp::toConstElem(IRState* p)
} }
llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; 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); llvm::ConstantInt* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
LLConstant* idxs[2] = { zero, zero }; LLConstant* idxs[2] = { zero, zero };
@ -1008,19 +1015,21 @@ DValue* DotVarExp::toElem(IRState* p)
assert(fdecl->vtblIndex > 0); assert(fdecl->vtblIndex > 0);
assert(e1type->ty == Tclass); assert(e1type->ty == Tclass);
LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); LLValue* zero = DtoConstUint(0);
LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false); size_t vtblidx = fdecl->vtblIndex;
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "vthis: " << *vthis << '\n'; 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 = DtoLoad(funcval);
funcval = DtoGEP(funcval, zero, vtblidx, toChars()); Logger::println("vtblidx = %lu", vtblidx);
funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
funcval = DtoLoad(funcval); funcval = DtoLoad(funcval);
#if OPAQUE_VTBLS
funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type))); funcval = DtoBitCast(funcval, getPtrToType(DtoType(fdecl->type)));
if (Logger::enabled()) if (Logger::enabled())
Logger::cout() << "funcval casted: " << *funcval << '\n'; Logger::cout() << "funcval casted: " << *funcval << '\n';
#endif
} }
// static call // static call
else { 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) DValue* ArrayLiteralExp::toElem(IRState* p)
{ {
Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); 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) DValue* StructLiteralExp::toElem(IRState* p)
{ {
Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); Logger::print("StructLiteralExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; 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 // trackers
// and unspecified members size_t lastoffset = 0;
TypeStruct* ts = (TypeStruct*)type->toBasetype(); size_t lastsize = 0;
assert(ts->sym);
DtoForceConstInitDsymbol(ts->sym);
assert(ts->sym->ir.irStruct->init);
DtoAggrCopy(sptr, ts->sym->ir.irStruct->init);
// num elements in literal // for through each field and build up the struct, padding with zeros
unsigned n = elements->dim; for (size_t i=0; i<n; i++)
// 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)
{ {
Expression* vx = (Expression*)elements->data[i]; Expression* e = exprs[i];
if (!vx) continue; VarDeclaration* var = vars[i];
if (Logger::enabled()) // field is skipped
Logger::cout() << "getting index " << j << " of " << *sptr << '\n'; if (!e)
LLValue* arrptr = DtoGEPi(sptr,0,j); continue;
DValue* darrptr = new DVarValue(vx->type, arrptr);
DValue* ve = vx->toElem(p); // add any 0 padding needed before this field
DtoAssign(loc, darrptr, ve); 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) LLConstant* StructLiteralExp::toConstElem(IRState* p)
{ {
Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars()); Logger::print("StructLiteralExp::toConstElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; LOG_SCOPE;
unsigned n = elements->dim; // get arrays
std::vector<LLConstant*> vals(n, NULL); 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]; Expression* e = exprs[i];
vals[i] = vx->toConstElem(p); 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); // add any 0 padding needed at the end of the literal
const LLType* t = DtoType(type); const LLType* structtype = DtoType(sd->type);
const LLStructType* st = isaStruct(t); size_t structsize = getABITypeSize(structtype);
return llvm::ConstantStruct::get(st,vals);
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; TypeStruct* ts = (TypeStruct*)t;
assert(ts->sym); assert(ts->sym);
DtoResolveDsymbol(ts->sym); DtoResolveDsymbol(ts->sym);
return ts->sym->ir.irStruct->recty.get(); // t->ir.type->get(); return ts->ir.type->get();
} }
case Tclass: { case Tclass: {
TypeClass* tc = (TypeClass*)t; TypeClass* tc = (TypeClass*)t;
assert(tc->sym); assert(tc->sym);
DtoResolveDsymbol(tc->sym); DtoResolveDsymbol(tc->sym);
return getPtrToType(tc->sym->ir.irStruct->recty.get()); // t->ir.type->get()); return getPtrToType(tc->ir.type->get());
} }
// functions // functions
@ -584,6 +584,13 @@ LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name)
return gIR->ir->CreateBitCast(v, t, name ? name : "tmp"); 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) const LLPointerType* isaPointer(LLValue* v)
@ -695,6 +702,33 @@ unsigned char getPrefTypeAlign(const LLType* t)
return gTargetData->getPrefTypeAlignment(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() const LLStructType* DtoInterfaceInfoType()

View file

@ -67,6 +67,7 @@ LLConstant* DtoConstBool(bool);
LLValue* DtoLoad(LLValue* src, const char* name=0); LLValue* DtoLoad(LLValue* src, const char* name=0);
void DtoStore(LLValue* src, LLValue* dst); void DtoStore(LLValue* src, LLValue* dst);
LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0); LLValue* DtoBitCast(LLValue* v, const LLType* t, const char* name=0);
LLConstant* DtoBitCast(LLConstant* v, const LLType* t);
// llvm::dyn_cast wrappers // llvm::dyn_cast wrappers
const LLPointerType* isaPointer(LLValue* v); const LLPointerType* isaPointer(LLValue* v);
@ -96,6 +97,9 @@ size_t getABITypeSize(const LLType* t);
unsigned char getABITypeAlign(const LLType* t); unsigned char getABITypeAlign(const LLType* t);
unsigned char getPrefTypeAlign(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 // pair type helpers
LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name = 0); LLValue* DtoAggrPair(const LLType* type, LLValue* V1, LLValue* V2, const char* name = 0);
LLValue* DtoAggrPair(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()); //printf("codegen: %s\n", srcfile->toChars());
assert(!global.errors);
// start by deleting the old object file // start by deleting the old object file
deleteObjFile(); deleteObjFile();
@ -156,16 +158,6 @@ void Module::genobjfile(int multiobj, char** envp)
fatal(); 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 // process module members
for (int k=0; k < members->dim; k++) { for (int k=0; k < members->dim; k++) {
Dsymbol* dsym = (Dsymbol*)(members->data[k]); Dsymbol* dsym = (Dsymbol*)(members->data[k]);
@ -638,7 +630,7 @@ static LLFunction* build_module_reference_and_ctor(LLConstant* moduleinfo)
const LLStructType* modulerefTy = DtoModuleReferenceType(); const LLStructType* modulerefTy = DtoModuleReferenceType();
std::vector<LLConstant*> mrefvalues; std::vector<LLConstant*> mrefvalues;
mrefvalues.push_back(LLConstant::getNullValue(modulerefTy->getContainedType(0))); 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); LLConstant* thismrefinit = LLConstantStruct::get(modulerefTy, mrefvalues);
// create the ModuleReference node for this module // create the ModuleReference node for this module
@ -704,6 +696,13 @@ void Module::genmoduleinfo()
assert(moduleinfo); assert(moduleinfo);
DtoForceConstInitDsymbol(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 // moduleinfo llvm struct type
const llvm::StructType* moduleinfoTy = isaStruct(moduleinfo->type->ir.type->get()); 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()); Logger::println("skipping interface '%s' in moduleinfo", cd->toPrettyChars());
continue; continue;
} }
else if (cd->sizeok != 1)
{
Logger::println("skipping opaque class declaration '%s' in moduleinfo", cd->toPrettyChars());
continue;
}
Logger::println("class: %s", cd->toPrettyChars()); Logger::println("class: %s", cd->toPrettyChars());
assert(cd->ir.irStruct->classInfo); 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? // has class array?
if (!classInits.empty()) if (!classInits.empty())
@ -842,7 +847,7 @@ void Module::genmoduleinfo()
}*/ }*/
// create initializer // create initializer
LLConstant* constMI = llvm::ConstantStruct::get(moduleinfoTy, initVec); LLConstant* constMI = llvm::ConstantStruct::get(initVec);
// create name // create name
std::string MIname("_D"); std::string MIname("_D");
@ -853,7 +858,8 @@ void Module::genmoduleinfo()
// flags will be modified at runtime so can't make it constant // flags will be modified at runtime so can't make it constant
llvm::GlobalVariable* gvar = gIR->module->getGlobalVariable(MIname); 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); gvar->setInitializer(constMI);
// build the modulereference and ctor for registering it // build the modulereference and ctor for registering it
@ -988,7 +994,8 @@ void VarDeclaration::toObjFile(int multiobj)
#else #else
bool _isconst = isConst(); bool _isconst = isConst();
#endif #endif
if (parent && parent->isFuncDeclaration()) Dsymbol* par = toParent2();
if (par && par->isFuncDeclaration())
{ {
static_local = true; static_local = true;
if (init && init->isExpInitializer()) { if (init && init->isExpInitializer()) {
@ -1015,20 +1022,17 @@ void VarDeclaration::toObjFile(int multiobj)
} }
else else
{ {
#if DMDV2 // might already have its irField, as classes derive each other without getting copies of the VarDeclaration
#if 0
if (!ir.irField) if (!ir.irField)
{ {
printf("dataseg: %d\n", isDataseg()); assert(!ir.isSet());
printf("parent: %s %s\n", parent->kind(), parent->toPrettyChars()); ir.irField = new IrField(this);
printf("this: %s %s\n", this->kind(), this->toPrettyChars());
} }
#endif IrStruct* irstruct = gIR->topstruct();
#else irstruct->addVar(this);
assert(ir.irField != 0);
#endif 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); 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()); const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoTypedefDeclaration::llvmDefine()
@ -390,10 +390,6 @@ void TypeInfoTypedefDeclaration::llvmDefine()
ClassDeclaration* base = Type::typeinfotypedef; ClassDeclaration* base = Type::typeinfotypedef;
DtoForceConstInitDsymbol(base); DtoForceConstInitDsymbol(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
if (Logger::enabled())
Logger::cout() << "got stype: " << *stype << '\n';
// vtbl // vtbl
std::vector<LLConstant*> sinits; std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl); sinits.push_back(base->ir.irStruct->vtbl);
@ -408,13 +404,11 @@ void TypeInfoTypedefDeclaration::llvmDefine()
// TypeInfo base // TypeInfo base
sd->basetype = sd->basetype->merge(); // DMD does this! sd->basetype = sd->basetype->merge(); // DMD does this!
LLConstant* castbase = DtoTypeInfoOf(sd->basetype, true); LLConstant* castbase = DtoTypeInfoOf(sd->basetype, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase); sinits.push_back(castbase);
// char[] name // char[] name
char *name = sd->toPrettyChars(); char *name = sd->toPrettyChars();
sinits.push_back(DtoConstString(name)); sinits.push_back(DtoConstString(name));
assert(sinits.back()->getType() == stype->getElementType(3));
// void[] init // void[] init
const LLPointerType* initpt = getPtrToType(LLType::Int8Ty); const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
@ -433,9 +427,14 @@ void TypeInfoTypedefDeclaration::llvmDefine()
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
} }
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
@ -453,10 +452,8 @@ void TypeInfoEnumDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfoenum; ClassDeclaration* base = Type::typeinfoenum;
DtoResolveClass(base); DtoResolveClass(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoEnumDeclaration::llvmDefine()
@ -467,8 +464,6 @@ void TypeInfoEnumDeclaration::llvmDefine()
ClassDeclaration* base = Type::typeinfoenum; ClassDeclaration* base = Type::typeinfoenum;
DtoForceConstInitDsymbol(base); DtoForceConstInitDsymbol(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// vtbl // vtbl
std::vector<LLConstant*> sinits; std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl); sinits.push_back(base->ir.irStruct->vtbl);
@ -482,13 +477,11 @@ void TypeInfoEnumDeclaration::llvmDefine()
// TypeInfo base // TypeInfo base
LLConstant* castbase = DtoTypeInfoOf(sd->memtype, true); LLConstant* castbase = DtoTypeInfoOf(sd->memtype, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase); sinits.push_back(castbase);
// char[] name // char[] name
char *name = sd->toPrettyChars(); char *name = sd->toPrettyChars();
sinits.push_back(DtoConstString(name)); sinits.push_back(DtoConstString(name));
assert(sinits.back()->getType() == stype->getElementType(3));
// void[] init // void[] init
const LLPointerType* initpt = getPtrToType(LLType::Int8Ty); const LLPointerType* initpt = getPtrToType(LLType::Int8Ty);
@ -512,9 +505,14 @@ void TypeInfoEnumDeclaration::llvmDefine()
#endif #endif
} }
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
@ -529,10 +527,8 @@ static LLConstant* LLVM_D_Declare_TypeInfoBase(TypeInfoDeclaration* tid, ClassDe
ClassDeclaration* base = cd; ClassDeclaration* base = cd;
DtoResolveClass(base); DtoResolveClass(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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) 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; ClassDeclaration* base = cd;
DtoForceConstInitDsymbol(base); DtoForceConstInitDsymbol(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// vtbl // vtbl
std::vector<LLConstant*> sinits; std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl); sinits.push_back(base->ir.irStruct->vtbl);
@ -551,11 +545,15 @@ static LLConstant* LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaratio
// TypeInfo base // TypeInfo base
LLConstant* castbase = DtoTypeInfoOf(basetype, true); LLConstant* castbase = DtoTypeInfoOf(basetype, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase); sinits.push_back(castbase);
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); 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); isaGlobalVar(tid->ir.irGlobal->value)->setInitializer(tiInit);
} }
@ -628,11 +626,8 @@ void TypeInfoStaticArrayDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfostaticarray; ClassDeclaration* base = Type::typeinfostaticarray;
DtoResolveClass(base); DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoStaticArrayDeclaration::llvmDefine()
@ -665,9 +660,14 @@ void TypeInfoStaticArrayDeclaration::llvmDefine()
// length // length
sinits.push_back(DtoConstSize_t(tc->dim->toInteger())); sinits.push_back(DtoConstSize_t(tc->dim->toInteger()));
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
@ -686,11 +686,8 @@ void TypeInfoAssociativeArrayDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfoassociativearray; ClassDeclaration* base = Type::typeinfoassociativearray;
DtoResolveClass(base); DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoAssociativeArrayDeclaration::llvmDefine()
@ -702,9 +699,6 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
ClassDeclaration* base = Type::typeinfoassociativearray; ClassDeclaration* base = Type::typeinfoassociativearray;
DtoForceConstInitDsymbol(base); DtoForceConstInitDsymbol(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// initializer vector // initializer vector
std::vector<LLConstant*> sinits; std::vector<LLConstant*> sinits;
// first is always the vtable // first is always the vtable
@ -719,17 +713,20 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
// value typeinfo // value typeinfo
LLConstant* castbase = DtoTypeInfoOf(tc->next, true); LLConstant* castbase = DtoTypeInfoOf(tc->next, true);
assert(castbase->getType() == stype->getElementType(2));
sinits.push_back(castbase); sinits.push_back(castbase);
// key typeinfo // key typeinfo
castbase = DtoTypeInfoOf(tc->index, true); castbase = DtoTypeInfoOf(tc->index, true);
assert(castbase->getType() == stype->getElementType(3));
sinits.push_back(castbase); sinits.push_back(castbase);
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
@ -810,10 +807,8 @@ void TypeInfoStructDeclaration::llvmDeclare()
ClassDeclaration* base = Type::typeinfostruct; ClassDeclaration* base = Type::typeinfostruct;
DtoResolveClass(base); DtoResolveClass(base);
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoStructDeclaration::llvmDefine()
@ -1001,9 +996,14 @@ void TypeInfoStructDeclaration::llvmDefine()
#endif #endif
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoStructDeclaration::toDt(dt_t **pdt)
@ -1023,11 +1023,8 @@ void TypeInfoClassDeclaration::llvmDeclare()
assert(base); assert(base);
DtoResolveClass(base); DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoClassDeclaration::llvmDefine()
@ -1040,9 +1037,6 @@ void TypeInfoClassDeclaration::llvmDefine()
assert(base); assert(base);
DtoForceConstInitDsymbol(base); DtoForceConstInitDsymbol(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// initializer vector // initializer vector
std::vector<LLConstant*> sinits; std::vector<LLConstant*> sinits;
// first is always the vtable // first is always the vtable
@ -1058,9 +1052,14 @@ void TypeInfoClassDeclaration::llvmDefine()
assert(tc->sym->ir.irStruct->classInfo); assert(tc->sym->ir.irStruct->classInfo);
sinits.push_back(tc->sym->ir.irStruct->classInfo); sinits.push_back(tc->sym->ir.irStruct->classInfo);
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoClassDeclaration::toDt(dt_t **pdt)
@ -1080,11 +1079,8 @@ void TypeInfoInterfaceDeclaration::llvmDeclare()
assert(base); assert(base);
DtoResolveClass(base); DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoInterfaceDeclaration::llvmDefine()
@ -1114,9 +1110,14 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
assert(tc->sym->ir.irStruct->classInfo); assert(tc->sym->ir.irStruct->classInfo);
sinits.push_back(tc->sym->ir.irStruct->classInfo); sinits.push_back(tc->sym->ir.irStruct->classInfo);
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
@ -1136,11 +1137,8 @@ void TypeInfoTupleDeclaration::llvmDeclare()
assert(base); assert(base);
DtoResolveClass(base); DtoResolveClass(base);
// get type of typeinfo class
const LLStructType* stype = isaStruct(base->type->ir.type->get());
// create the symbol // 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() void TypeInfoTupleDeclaration::llvmDefine()
@ -1199,9 +1197,14 @@ void TypeInfoTupleDeclaration::llvmDefine()
LLConstant* slice = DtoConstSlice(DtoConstSize_t(dim), arrptr); LLConstant* slice = DtoConstSlice(DtoConstSize_t(dim), arrptr);
sinits.push_back(slice); sinits.push_back(slice);
// create the symbol // create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(stype, sinits); LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
isaGlobalVar(this->ir.irGlobal->value)->setInitializer(tiInit);
// 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) void TypeInfoTupleDeclaration::toDt(dt_t **pdt)

View file

@ -3,54 +3,57 @@
#include "mtype.h" #include "mtype.h"
#include "aggregate.h" #include "aggregate.h"
#include "declaration.h" #include "declaration.h"
#include "init.h"
#include "ir/irstruct.h" #include "ir/irstruct.h"
#include "gen/irstate.h" #include "gen/irstate.h"
#include "gen/tollvm.h" #include "gen/tollvm.h"
#include "gen/logger.h"
IrInterface::IrInterface(BaseClass* b) IrInterface::IrInterface(BaseClass* b)
: vtblInitTy(llvm::OpaqueType::get())
{ {
base = b; base = b;
decl = b->base; decl = b->base;
vtblTy = NULL;
vtblInit = NULL; vtblInit = NULL;
vtbl = NULL; vtbl = NULL;
infoTy = NULL; infoTy = NULL;
infoInit = NULL; infoInit = NULL;
info = NULL; info = NULL;
index = -1; index = 0;
}
IrInterface::~IrInterface()
{
delete vtblTy;
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
IrStruct::IrStruct(Type* t) IrStruct::IrStruct(AggregateDeclaration* aggr)
: recty((t->ir.type) ? *t->ir.type : llvm::OpaqueType::get()) : 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; defined = false;
constinited = false; constinited = false;
interfaceInfosTy = NULL;
interfaceInfos = NULL;
interfaceInfos = NULL;
vtbl = NULL; vtbl = NULL;
constVtbl = NULL; constVtbl = NULL;
init = NULL; init = NULL;
constInit = NULL; constInit = NULL;
classInfo = NULL; classInfo = NULL;
constClassInfo = NULL; constClassInfo = NULL;
hasUnions = false; classInfoDeclared = false;
dunion = NULL; classInfoDefined = false;
classDeclared = false;
classDefined = false;
packed = 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 anon = new Anon(isunion, anon);
if (!v->ir.irField) }
{
assert(!v->ir.isSet()); //////////////////////////////////////////
v->ir.irField = new IrField(v);
} void IrStruct::popAnon()
const LLType* _type = DtoType(v->type); {
offsets.insert(std::make_pair(v->offset, IrStruct::Offset(v, _type))); 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 <vector>
#include <map> #include <map>
struct IrInterface : IrBase struct IrInterface;
{
BaseClass* base;
ClassDeclaration* decl;
llvm::PATypeHolder* vtblTy;
LLConstant* vtblInit;
LLGlobalVariable* vtbl;
const LLStructType* infoTy;
LLConstantStruct* infoInit;
LLConstant* info;
int index;
IrInterface(BaseClass* b);
~IrInterface();
};
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// represents a struct or class // represents a struct or class
// it is used during codegen to hold all the vital info we need
struct IrStruct : IrBase 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::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 std::vector<IrInterface*> InterfaceVector;
typedef InterfaceVector::iterator InterfaceVectorIter; typedef InterfaceVector::iterator InterfaceVectorIter;
public: // vector of LLVM types
IrStruct(Type*); 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(); 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; 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; InterfaceMap interfaceMap;
InterfaceVector interfaceVec; InterfaceVector interfaceVec;
const llvm::ArrayType* interfaceInfosTy;
// interface info array global
LLGlobalVariable* interfaceInfos; LLGlobalVariable* interfaceInfos;
// ...
bool defined; bool defined;
bool constinited; bool constinited;
// vtbl global and initializer
LLGlobalVariable* vtbl; LLGlobalVariable* vtbl;
#if OPAQUE_VTBLS
LLConstant* constVtbl; LLConstant* constVtbl;
#else
LLConstantStruct* constVtbl; // static initializers global and constant
#endif
LLGlobalVariable* init; LLGlobalVariable* init;
LLConstant* constInit; LLConstant* constInit;
// classinfo global and initializer constant
LLGlobalVariable* classInfo; LLGlobalVariable* classInfo;
LLConstant* constClassInfo; LLConstant* constClassInfo;
bool hasUnions; bool classInfoDeclared;
DUnion* dunion; bool classInfoDefined;
bool classDeclared;
bool classDefined;
bool packed; // true for: align(1) struct S { ... } // align(1) struct S { ... }
bool packed;
// dwarf composite global
LLGlobalVariable* dwarfComposite; 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 #endif

View file

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

View file

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

View file

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

View file

@ -34,8 +34,9 @@ struct IrField : IrVar
{ {
IrField(VarDeclaration* v); IrField(VarDeclaration* v);
int index; unsigned index;
size_t indexOffset; unsigned unionOffset;
llvm::Constant* constInit; 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; int i = 42;
override void func() override void func()
{ {
printf("hello %d\n", i); printf("hello %d from %p\n", i, this);
i++; i++;
} }
} }
void main() void main()
{ {
scope c = new C; auto c = new C;
{c.func();} {c.func();}
{ {
I i = c; I i = c;