mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-01-11 10:16:36 +01:00
Added Doxygen file.
Completely seperated type and symbol generation. Should fix a lot of bugs, but is not yet 100% complete.
This commit is contained in:
@@ -115,10 +115,6 @@ 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();
|
||||||
|
|
||||||
#if IN_LLVM
|
|
||||||
void codegen(Ir*);
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PragmaDeclaration : AttribDeclaration
|
struct PragmaDeclaration : AttribDeclaration
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ int isnan(double);
|
|||||||
#include "hdrgen.h"
|
#include "hdrgen.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
|
||||||
Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
|
|
||||||
Expression *expandVar(int result, VarDeclaration *v);
|
Expression *expandVar(int result, VarDeclaration *v);
|
||||||
|
|
||||||
#define LOGSEMANTIC 0
|
#define LOGSEMANTIC 0
|
||||||
|
|||||||
19
dmd/func.c
19
dmd/func.c
@@ -84,6 +84,25 @@ FuncDeclaration::FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC s
|
|||||||
// LDC
|
// LDC
|
||||||
isArrayOp = false;
|
isArrayOp = false;
|
||||||
allowInlining = false;
|
allowInlining = false;
|
||||||
|
|
||||||
|
// function types in ldc don't merge if the context parameter differs
|
||||||
|
// so we actually don't care about the function declaration, but only
|
||||||
|
// what kind of context parameter it has.
|
||||||
|
// however, this constructor is usually called from the parser, which
|
||||||
|
// unfortunately doesn't provide the information needed to get to the
|
||||||
|
// aggregate type. So we have to stick with the FuncDeclaration and
|
||||||
|
// just be sure we don't actually rely on the symbol it points to,
|
||||||
|
// but rather just the type of its context parameter.
|
||||||
|
// this means some function might have a function type pointing to
|
||||||
|
// another function declaration
|
||||||
|
|
||||||
|
if (type)
|
||||||
|
{
|
||||||
|
assert(type->ty == Tfunction && "invalid function type");
|
||||||
|
TypeFunction* tf = (TypeFunction*)type;
|
||||||
|
if (tf->funcdecl == NULL)
|
||||||
|
tf->funcdecl = this;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
// in artistic.txt, or the GNU General Public License in gnu.txt.
|
||||||
// See the included readme.txt for details.
|
// See the included readme.txt for details.
|
||||||
|
|
||||||
|
#if IN_LLVM
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Lexical Analyzer */
|
/* Lexical Analyzer */
|
||||||
|
|
||||||
|
|||||||
72
dmd/mtype.c
72
dmd/mtype.c
@@ -350,14 +350,14 @@ Type *Type::toBasetype()
|
|||||||
* Name mangling.
|
* Name mangling.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void Type::toDecoBuffer(OutBuffer *buf)
|
void Type::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{
|
{
|
||||||
buf->writeByte(mangleChar[ty]);
|
buf->writeByte(mangleChar[ty]);
|
||||||
if (next)
|
if (next)
|
||||||
{
|
{
|
||||||
assert(next != this);
|
assert(next != this);
|
||||||
//printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
|
//printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this->ty, next, next->ty);
|
||||||
next->toDecoBuffer(buf);
|
next->toDecoBuffer(buf, mangle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -434,7 +434,7 @@ Type *Type::merge()
|
|||||||
|
|
||||||
if (next)
|
if (next)
|
||||||
next = next->merge();
|
next = next->merge();
|
||||||
toDecoBuffer(&buf);
|
toDecoBuffer(&buf, false);
|
||||||
sv = stringtable.update((char *)buf.data, buf.offset);
|
sv = stringtable.update((char *)buf.data, buf.offset);
|
||||||
if (sv->ptrvalue)
|
if (sv->ptrvalue)
|
||||||
{ t = (Type *) sv->ptrvalue;
|
{ t = (Type *) sv->ptrvalue;
|
||||||
@@ -444,7 +444,11 @@ Type *Type::merge()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
sv->ptrvalue = this;
|
sv->ptrvalue = this;
|
||||||
deco = sv->lstring.string;
|
|
||||||
|
OutBuffer mangle;
|
||||||
|
toDecoBuffer(&mangle, true);
|
||||||
|
mangle.writeByte(0);
|
||||||
|
deco = mem.strdup((char *)mangle.data);
|
||||||
//printf("new value, deco = '%s' %p\n", t->deco, t->deco);
|
//printf("new value, deco = '%s' %p\n", t->deco, t->deco);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -743,7 +747,7 @@ Identifier *Type::getTypeInfoIdent(int internal)
|
|||||||
buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]);
|
buf.writeByte(mangleChar[((TypeArray *)this)->next->ty]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
toDecoBuffer(&buf);
|
toDecoBuffer(&buf, true);
|
||||||
len = buf.offset;
|
len = buf.offset;
|
||||||
name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
|
name = (char *)alloca(19 + sizeof(len) * 3 + len + 1);
|
||||||
buf.writeByte(0);
|
buf.writeByte(0);
|
||||||
@@ -1933,13 +1937,13 @@ Type *TypeSArray::semantic(Loc loc, Scope *sc)
|
|||||||
return merge();
|
return merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeSArray::toDecoBuffer(OutBuffer *buf)
|
void TypeSArray::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{
|
{
|
||||||
buf->writeByte(mangleChar[ty]);
|
buf->writeByte(mangleChar[ty]);
|
||||||
if (dim)
|
if (dim)
|
||||||
buf->printf("%ju", dim->toInteger());
|
buf->printf("%ju", dim->toInteger());
|
||||||
if (next)
|
if (next)
|
||||||
next->toDecoBuffer(buf);
|
next->toDecoBuffer(buf, mangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
||||||
@@ -2099,11 +2103,11 @@ Type *TypeDArray::semantic(Loc loc, Scope *sc)
|
|||||||
return merge();
|
return merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeDArray::toDecoBuffer(OutBuffer *buf)
|
void TypeDArray::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{
|
{
|
||||||
buf->writeByte(mangleChar[ty]);
|
buf->writeByte(mangleChar[ty]);
|
||||||
if (next)
|
if (next)
|
||||||
next->toDecoBuffer(buf);
|
next->toDecoBuffer(buf, mangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
||||||
@@ -2425,11 +2429,11 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
|
|||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeAArray::toDecoBuffer(OutBuffer *buf)
|
void TypeAArray::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{
|
{
|
||||||
buf->writeByte(mangleChar[ty]);
|
buf->writeByte(mangleChar[ty]);
|
||||||
index->toDecoBuffer(buf);
|
index->toDecoBuffer(buf, mangle);
|
||||||
next->toDecoBuffer(buf);
|
next->toDecoBuffer(buf, mangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
||||||
@@ -2651,6 +2655,10 @@ TypeFunction::TypeFunction(Arguments *parameters, Type *treturn, int varargs, en
|
|||||||
this->varargs = varargs;
|
this->varargs = varargs;
|
||||||
this->linkage = linkage;
|
this->linkage = linkage;
|
||||||
this->inuse = 0;
|
this->inuse = 0;
|
||||||
|
|
||||||
|
#if IN_LLVM
|
||||||
|
this->funcdecl = NULL;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *TypeFunction::syntaxCopy()
|
Type *TypeFunction::syntaxCopy()
|
||||||
@@ -2750,7 +2758,7 @@ Lnotcovariant:
|
|||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeFunction::toDecoBuffer(OutBuffer *buf)
|
void TypeFunction::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{ unsigned char mc;
|
{ unsigned char mc;
|
||||||
|
|
||||||
//printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
|
//printf("TypeFunction::toDecoBuffer() this = %p %s\n", this, toChars());
|
||||||
@@ -2775,11 +2783,23 @@ void TypeFunction::toDecoBuffer(OutBuffer *buf)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
buf->writeByte(mc);
|
buf->writeByte(mc);
|
||||||
|
|
||||||
|
// LDC: if we're not producing a mangle string, add the this
|
||||||
|
// type to prevent merging different member function
|
||||||
|
if (!mangle && funcdecl)
|
||||||
|
{
|
||||||
|
if (AggregateDeclaration* ad = funcdecl->isMember())
|
||||||
|
{
|
||||||
|
buf->writeByte('M');
|
||||||
|
ad->type->toDecoBuffer(buf, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Write argument types
|
// Write argument types
|
||||||
Argument::argsToDecoBuffer(buf, parameters);
|
Argument::argsToDecoBuffer(buf, parameters, mangle);
|
||||||
//if (buf->data[buf->offset - 1] == '@') halt();
|
//if (buf->data[buf->offset - 1] == '@') halt();
|
||||||
buf->writeByte('Z' - varargs); // mark end of arg list
|
buf->writeByte('Z' - varargs); // mark end of arg list
|
||||||
next->toDecoBuffer(buf);
|
next->toDecoBuffer(buf, mangle);
|
||||||
inuse--;
|
inuse--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3461,7 +3481,7 @@ Type *TypeIdentifier::syntaxCopy()
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeIdentifier::toDecoBuffer(OutBuffer *buf)
|
void TypeIdentifier::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{ unsigned len;
|
{ unsigned len;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
@@ -3915,7 +3935,7 @@ Type *TypeEnum::toBasetype()
|
|||||||
return sym->memtype->toBasetype();
|
return sym->memtype->toBasetype();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeEnum::toDecoBuffer(OutBuffer *buf)
|
void TypeEnum::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{ char *name;
|
{ char *name;
|
||||||
|
|
||||||
name = sym->mangle();
|
name = sym->mangle();
|
||||||
@@ -4103,7 +4123,7 @@ Dsymbol *TypeTypedef::toDsymbol(Scope *sc)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeTypedef::toDecoBuffer(OutBuffer *buf)
|
void TypeTypedef::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{ unsigned len;
|
{ unsigned len;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
@@ -4328,7 +4348,7 @@ Dsymbol *TypeStruct::toDsymbol(Scope *sc)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeStruct::toDecoBuffer(OutBuffer *buf)
|
void TypeStruct::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{ unsigned len;
|
{ unsigned len;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
@@ -4621,7 +4641,7 @@ Dsymbol *TypeClass::toDsymbol(Scope *sc)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeClass::toDecoBuffer(OutBuffer *buf)
|
void TypeClass::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{ unsigned len;
|
{ unsigned len;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
@@ -5143,11 +5163,11 @@ void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
|
|||||||
Argument::argsToCBuffer(buf, hgs, arguments, 0);
|
Argument::argsToCBuffer(buf, hgs, arguments, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TypeTuple::toDecoBuffer(OutBuffer *buf)
|
void TypeTuple::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{
|
{
|
||||||
//printf("TypeTuple::toDecoBuffer() this = %p\n", this);
|
//printf("TypeTuple::toDecoBuffer() this = %p\n", this);
|
||||||
OutBuffer buf2;
|
OutBuffer buf2;
|
||||||
Argument::argsToDecoBuffer(&buf2, arguments);
|
Argument::argsToDecoBuffer(&buf2, arguments, mangle);
|
||||||
unsigned len = buf2.offset;
|
unsigned len = buf2.offset;
|
||||||
buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
|
buf->printf("%c%d%.*s", mangleChar[ty], len, len, (char *)buf2.extractData());
|
||||||
}
|
}
|
||||||
@@ -5409,7 +5429,7 @@ void Argument::argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *argume
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
|
void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle)
|
||||||
{
|
{
|
||||||
//printf("Argument::argsToDecoBuffer()\n");
|
//printf("Argument::argsToDecoBuffer()\n");
|
||||||
|
|
||||||
@@ -5420,7 +5440,7 @@ void Argument::argsToDecoBuffer(OutBuffer *buf, Arguments *arguments)
|
|||||||
for (size_t i = 0; i < dim; i++)
|
for (size_t i = 0; i < dim; i++)
|
||||||
{
|
{
|
||||||
Argument *arg = Argument::getNth(arguments, i);
|
Argument *arg = Argument::getNth(arguments, i);
|
||||||
arg->toDecoBuffer(buf);
|
arg->toDecoBuffer(buf, mangle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5454,7 +5474,7 @@ Type *Argument::isLazyArray()
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Argument::toDecoBuffer(OutBuffer *buf)
|
void Argument::toDecoBuffer(OutBuffer *buf, bool mangle)
|
||||||
{
|
{
|
||||||
switch (storageClass & (STCin | STCout | STCref | STClazy))
|
switch (storageClass & (STCin | STCout | STCref | STClazy))
|
||||||
{ case 0:
|
{ case 0:
|
||||||
@@ -5475,7 +5495,7 @@ void Argument::toDecoBuffer(OutBuffer *buf)
|
|||||||
#endif
|
#endif
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
type->toDecoBuffer(buf);
|
type->toDecoBuffer(buf, mangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
|||||||
31
dmd/mtype.h
31
dmd/mtype.h
@@ -219,7 +219,8 @@ struct Type : Object
|
|||||||
virtual d_uns64 size(Loc loc);
|
virtual d_uns64 size(Loc loc);
|
||||||
virtual unsigned alignsize();
|
virtual unsigned alignsize();
|
||||||
virtual Type *semantic(Loc loc, Scope *sc);
|
virtual Type *semantic(Loc loc, Scope *sc);
|
||||||
virtual void toDecoBuffer(OutBuffer *buf);
|
// append the mangleof or a string uniquely identifying this type to buf
|
||||||
|
virtual void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
Type *merge();
|
Type *merge();
|
||||||
virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
||||||
virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
@@ -336,7 +337,7 @@ struct TypeSArray : TypeArray
|
|||||||
unsigned alignsize();
|
unsigned alignsize();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
int isString();
|
int isString();
|
||||||
@@ -367,7 +368,7 @@ struct TypeDArray : TypeArray
|
|||||||
d_uns64 size(Loc loc);
|
d_uns64 size(Loc loc);
|
||||||
unsigned alignsize();
|
unsigned alignsize();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
int isString();
|
int isString();
|
||||||
@@ -394,7 +395,7 @@ struct TypeAArray : TypeArray
|
|||||||
d_uns64 size(Loc loc);
|
d_uns64 size(Loc loc);
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
Expression *defaultInit(Loc loc);
|
Expression *defaultInit(Loc loc);
|
||||||
@@ -462,7 +463,7 @@ struct TypeFunction : Type
|
|||||||
TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
|
TypeFunction(Arguments *parameters, Type *treturn, int varargs, enum LINK linkage);
|
||||||
Type *syntaxCopy();
|
Type *syntaxCopy();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
|
||||||
@@ -481,6 +482,8 @@ struct TypeFunction : Type
|
|||||||
#elif IN_LLVM
|
#elif IN_LLVM
|
||||||
// LDC
|
// LDC
|
||||||
IrFuncTy fty;
|
IrFuncTy fty;
|
||||||
|
|
||||||
|
FuncDeclaration* funcdecl;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -525,7 +528,7 @@ struct TypeIdentifier : TypeQualified
|
|||||||
TypeIdentifier(Loc loc, Identifier *ident);
|
TypeIdentifier(Loc loc, Identifier *ident);
|
||||||
Type *syntaxCopy();
|
Type *syntaxCopy();
|
||||||
//char *toChars();
|
//char *toChars();
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||||
Dsymbol *toDsymbol(Scope *sc);
|
Dsymbol *toDsymbol(Scope *sc);
|
||||||
@@ -544,7 +547,7 @@ struct TypeInstance : TypeQualified
|
|||||||
TypeInstance(Loc loc, TemplateInstance *tempinst);
|
TypeInstance(Loc loc, TemplateInstance *tempinst);
|
||||||
Type *syntaxCopy();
|
Type *syntaxCopy();
|
||||||
//char *toChars();
|
//char *toChars();
|
||||||
//void toDecoBuffer(OutBuffer *buf);
|
//void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
@@ -575,7 +578,7 @@ struct TypeStruct : Type
|
|||||||
Type *syntaxCopy();
|
Type *syntaxCopy();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
Dsymbol *toDsymbol(Scope *sc);
|
Dsymbol *toDsymbol(Scope *sc);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
unsigned memalign(unsigned salign);
|
unsigned memalign(unsigned salign);
|
||||||
@@ -610,7 +613,7 @@ struct TypeEnum : Type
|
|||||||
Type *syntaxCopy();
|
Type *syntaxCopy();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
Dsymbol *toDsymbol(Scope *sc);
|
Dsymbol *toDsymbol(Scope *sc);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
Expression *getProperty(Loc loc, Identifier *ident);
|
Expression *getProperty(Loc loc, Identifier *ident);
|
||||||
@@ -642,7 +645,7 @@ struct TypeTypedef : Type
|
|||||||
char *toChars();
|
char *toChars();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
Dsymbol *toDsymbol(Scope *sc);
|
Dsymbol *toDsymbol(Scope *sc);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
Expression *getProperty(Loc loc, Identifier *ident);
|
Expression *getProperty(Loc loc, Identifier *ident);
|
||||||
@@ -682,7 +685,7 @@ struct TypeClass : Type
|
|||||||
Type *syntaxCopy();
|
Type *syntaxCopy();
|
||||||
Type *semantic(Loc loc, Scope *sc);
|
Type *semantic(Loc loc, Scope *sc);
|
||||||
Dsymbol *toDsymbol(Scope *sc);
|
Dsymbol *toDsymbol(Scope *sc);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
|
||||||
ClassDeclaration *isClassHandle();
|
ClassDeclaration *isClassHandle();
|
||||||
@@ -714,7 +717,7 @@ struct TypeTuple : Type
|
|||||||
int equals(Object *o);
|
int equals(Object *o);
|
||||||
Type *reliesOnTident();
|
Type *reliesOnTident();
|
||||||
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
Expression *getProperty(Loc loc, Identifier *ident);
|
Expression *getProperty(Loc loc, Identifier *ident);
|
||||||
TypeInfoDeclaration *getTypeInfoDeclaration();
|
TypeInfoDeclaration *getTypeInfoDeclaration();
|
||||||
};
|
};
|
||||||
@@ -746,11 +749,11 @@ struct Argument : Object
|
|||||||
Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
|
Argument(unsigned storageClass, Type *type, Identifier *ident, Expression *defaultArg);
|
||||||
Argument *syntaxCopy();
|
Argument *syntaxCopy();
|
||||||
Type *isLazyArray();
|
Type *isLazyArray();
|
||||||
void toDecoBuffer(OutBuffer *buf);
|
void toDecoBuffer(OutBuffer *buf, bool mangle);
|
||||||
static Arguments *arraySyntaxCopy(Arguments *args);
|
static Arguments *arraySyntaxCopy(Arguments *args);
|
||||||
static char *argsTypesToChars(Arguments *args, int varargs);
|
static char *argsTypesToChars(Arguments *args, int varargs);
|
||||||
static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
|
static void argsToCBuffer(OutBuffer *buf, HdrGenState *hgs, Arguments *arguments, int varargs);
|
||||||
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments);
|
static void argsToDecoBuffer(OutBuffer *buf, Arguments *arguments, bool mangle);
|
||||||
static size_t dim(Arguments *arguments);
|
static size_t dim(Arguments *arguments);
|
||||||
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
static Argument *getNth(Arguments *arguments, size_t nth, size_t *pn = NULL);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#ifndef LLVMC_GEN_ARRAYS_H
|
#ifndef LLVMC_GEN_ARRAYS_H
|
||||||
#define LLVMC_GEN_ARRAYS_H
|
#define LLVMC_GEN_ARRAYS_H
|
||||||
|
|
||||||
|
struct ArrayInitializer;
|
||||||
|
|
||||||
struct DSliceValue;
|
struct DSliceValue;
|
||||||
|
|
||||||
const llvm::StructType* DtoArrayType(Type* arrayTy);
|
const llvm::StructType* DtoArrayType(Type* arrayTy);
|
||||||
|
|||||||
1018
gen/classes.cpp
1018
gen/classes.cpp
File diff suppressed because it is too large
Load Diff
@@ -3,28 +3,21 @@
|
|||||||
|
|
||||||
#include "gen/structs.h"
|
#include "gen/structs.h"
|
||||||
|
|
||||||
/**
|
/// Resolves the llvm type for a class declaration
|
||||||
* Resolves the llvm type for a class declaration
|
|
||||||
*/
|
|
||||||
void DtoResolveClass(ClassDeclaration* cd);
|
void DtoResolveClass(ClassDeclaration* cd);
|
||||||
|
|
||||||
/**
|
/// Provides the llvm declaration for a class declaration
|
||||||
* Provides the llvm declaration for a class declaration
|
|
||||||
*/
|
|
||||||
void DtoDeclareClass(ClassDeclaration* cd);
|
void DtoDeclareClass(ClassDeclaration* cd);
|
||||||
|
|
||||||
/**
|
/// Constructs the constant initializer for a class declaration
|
||||||
* Constructs the constant initializer for a class declaration
|
|
||||||
*/
|
|
||||||
void DtoConstInitClass(ClassDeclaration* cd);
|
void DtoConstInitClass(ClassDeclaration* cd);
|
||||||
|
|
||||||
/**
|
/// Provides the llvm definition for a class declaration
|
||||||
* Provides the llvm definition for a class declaration
|
|
||||||
*/
|
|
||||||
void DtoDefineClass(ClassDeclaration* cd);
|
void DtoDefineClass(ClassDeclaration* cd);
|
||||||
|
|
||||||
void DtoDeclareClassInfo(ClassDeclaration* cd);
|
/// Builds the initializer of cd's ClassInfo.
|
||||||
void DtoDefineClassInfo(ClassDeclaration* cd);
|
/// FIXME: this should be put into IrStruct and eventually IrClass.
|
||||||
|
LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
|
||||||
|
|
||||||
DValue* DtoNewClass(Loc loc, TypeClass* type, NewExp* newexp);
|
DValue* DtoNewClass(Loc loc, TypeClass* type, NewExp* newexp);
|
||||||
void DtoInitClass(TypeClass* tc, LLValue* dst);
|
void DtoInitClass(TypeClass* tc, LLValue* dst);
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "ir/ir.h"
|
#include "ir/ir.h"
|
||||||
#include "ir/irvar.h"
|
#include "ir/irvar.h"
|
||||||
|
#include "ir/irtype.h"
|
||||||
|
#include "ir/irtypestruct.h"
|
||||||
|
|
||||||
/* ================================================================== */
|
/* ================================================================== */
|
||||||
|
|
||||||
@@ -72,11 +74,14 @@ void TupleDeclaration::codegen(Ir* p)
|
|||||||
|
|
||||||
/* ================================================================== */
|
/* ================================================================== */
|
||||||
|
|
||||||
|
// FIXME: this is horrible!!!
|
||||||
|
|
||||||
void VarDeclaration::codegen(Ir* p)
|
void VarDeclaration::codegen(Ir* p)
|
||||||
{
|
{
|
||||||
Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
|
Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// just forward aliases
|
||||||
if (aliassym)
|
if (aliassym)
|
||||||
{
|
{
|
||||||
Logger::println("alias sym");
|
Logger::println("alias sym");
|
||||||
@@ -84,10 +89,11 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// output the parent aggregate first
|
||||||
if (AggregateDeclaration* ad = isMember())
|
if (AggregateDeclaration* ad = isMember())
|
||||||
ad->codegen(p);
|
ad->codegen(p);
|
||||||
|
|
||||||
// global variable or magic
|
// global variable
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
// taken from dmd2/structs
|
// taken from dmd2/structs
|
||||||
if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init))
|
if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init))
|
||||||
@@ -138,25 +144,8 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
if (nakedUse)
|
if (nakedUse)
|
||||||
gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
|
gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
|
||||||
|
|
||||||
// don't initialize static struct members yet, they might be of the struct type
|
// initialize
|
||||||
// which doesn't have a static initializer yet.
|
DtoConstInitGlobal(this);
|
||||||
if (AggregateDeclaration* ad = isMember())
|
|
||||||
ad->ir.irStruct->staticVars.push_back(this);
|
|
||||||
else
|
|
||||||
DtoConstInitGlobal(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// might already have its irField, as classes derive each other without getting copies of the VarDeclaration
|
|
||||||
if (!ir.irField)
|
|
||||||
{
|
|
||||||
assert(!ir.isSet());
|
|
||||||
ir.irField = new IrField(this);
|
|
||||||
}
|
|
||||||
IrStruct* irstruct = gIR->topstruct();
|
|
||||||
irstruct->addVar(this);
|
|
||||||
|
|
||||||
Logger::println("added offset %u", offset);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +153,7 @@ void VarDeclaration::codegen(Ir* p)
|
|||||||
|
|
||||||
void TypedefDeclaration::codegen(Ir*)
|
void TypedefDeclaration::codegen(Ir*)
|
||||||
{
|
{
|
||||||
static int tdi = 0;
|
Logger::print("TypedefDeclaration::toObjFile: %s\n", toChars());
|
||||||
Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
|
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
// generate typeinfo
|
// generate typeinfo
|
||||||
@@ -181,33 +169,12 @@ void EnumDeclaration::codegen(Ir*)
|
|||||||
|
|
||||||
/* ================================================================== */
|
/* ================================================================== */
|
||||||
|
|
||||||
void FuncDeclaration::codegen(Ir*)
|
void FuncDeclaration::codegen(Ir* p)
|
||||||
{
|
{
|
||||||
DtoResolveDsymbol(this);
|
// don't touch function aliases, they don't contribute any new symbols
|
||||||
}
|
if (!isFuncAliasDeclaration())
|
||||||
|
|
||||||
/* ================================================================== */
|
|
||||||
|
|
||||||
void AnonDeclaration::codegen(Ir* p)
|
|
||||||
{
|
|
||||||
Array *d = include(NULL, NULL);
|
|
||||||
|
|
||||||
if (d)
|
|
||||||
{
|
{
|
||||||
// get real aggregate parent
|
DtoResolveDsymbol(this);
|
||||||
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->codegen(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
// finish
|
|
||||||
irstruct->popAnon();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,9 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
|
|||||||
llvm::FunctionType* functype = llvm::FunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);
|
llvm::FunctionType* functype = llvm::FunctionType::get(f->fty.ret->ltype, argtypes, f->fty.c_vararg);
|
||||||
f->ir.type = new llvm::PATypeHolder(functype);
|
f->ir.type = new llvm::PATypeHolder(functype);
|
||||||
|
|
||||||
|
#if 0
|
||||||
Logger::cout() << "Final function type: " << *functype << "\n";
|
Logger::cout() << "Final function type: " << *functype << "\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
return functype;
|
return functype;
|
||||||
}
|
}
|
||||||
@@ -304,16 +306,6 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
|
|||||||
return; // ignore declaration completely
|
return; // ignore declaration completely
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AggregateDeclaration* ad = fdecl->isMember())
|
|
||||||
{
|
|
||||||
ad->codegen(Type::sir);
|
|
||||||
if (ad->isStructDeclaration() && llvm::isa<llvm::OpaqueType>(DtoType(ad->type)))
|
|
||||||
{
|
|
||||||
ad->ir.irStruct->structFuncs.push_back(fdecl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//printf("resolve function: %s\n", fdecl->toPrettyChars());
|
//printf("resolve function: %s\n", fdecl->toPrettyChars());
|
||||||
|
|
||||||
if (fdecl->parent)
|
if (fdecl->parent)
|
||||||
@@ -372,7 +364,6 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
|
|||||||
// queue declaration unless the function is abstract without body
|
// queue declaration unless the function is abstract without body
|
||||||
if (!fdecl->isAbstract() || fdecl->fbody)
|
if (!fdecl->isAbstract() || fdecl->fbody)
|
||||||
{
|
{
|
||||||
Logger::println("Ignoring declaration of abstract bodyless function %s", fdecl->toPrettyChars());
|
|
||||||
DtoDeclareFunction(fdecl);
|
DtoDeclareFunction(fdecl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -465,6 +456,9 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||||||
Type* t = fdecl->type->toBasetype();
|
Type* t = fdecl->type->toBasetype();
|
||||||
TypeFunction* f = (TypeFunction*)t;
|
TypeFunction* f = (TypeFunction*)t;
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
assert(fdecl == f->funcdecl && "the function type does not point to this function");
|
||||||
|
|
||||||
bool declareOnly = !mustDefineSymbol(fdecl);
|
bool declareOnly = !mustDefineSymbol(fdecl);
|
||||||
|
|
||||||
if (fdecl->llvmInternal == LLVMva_start)
|
if (fdecl->llvmInternal == LLVMva_start)
|
||||||
|
|||||||
@@ -1069,7 +1069,8 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
|
|||||||
else if (StructInitializer* si = init->isStructInitializer())
|
else if (StructInitializer* si = init->isStructInitializer())
|
||||||
{
|
{
|
||||||
Logger::println("const struct initializer");
|
Logger::println("const struct initializer");
|
||||||
_init = DtoConstStructInitializer(si);
|
si->ad->codegen(Type::sir);
|
||||||
|
return si->ad->ir.irStruct->createStructInitializer(si);
|
||||||
}
|
}
|
||||||
else if (ArrayInitializer* ai = init->isArrayInitializer())
|
else if (ArrayInitializer* ai = init->isArrayInitializer())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -33,5 +33,7 @@ namespace Logger
|
|||||||
|
|
||||||
#define LOG_SCOPE Logger::LoggerScope _logscope;
|
#define LOG_SCOPE Logger::LoggerScope _logscope;
|
||||||
|
|
||||||
|
#define IF_LOG if (Logger::enabled())
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
619
gen/structs.cpp
619
gen/structs.cpp
@@ -15,438 +15,10 @@
|
|||||||
#include "gen/structs.h"
|
#include "gen/structs.h"
|
||||||
#include "gen/dvalue.h"
|
#include "gen/dvalue.h"
|
||||||
#include "gen/functions.h"
|
#include "gen/functions.h"
|
||||||
|
#include "gen/utils.h"
|
||||||
|
|
||||||
#include "ir/irstruct.h"
|
#include "ir/irstruct.h"
|
||||||
|
#include "ir/irtypestruct.h"
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// pair of var and its init
|
|
||||||
typedef std::pair<VarDeclaration*,Initializer*> VarInitPair;
|
|
||||||
|
|
||||||
// comparison func for qsort
|
|
||||||
static int varinit_offset_cmp_func(const void* p1, const void* p2)
|
|
||||||
{
|
|
||||||
VarDeclaration* v1 = ((VarInitPair*)p1)->first;
|
|
||||||
VarDeclaration* v2 = ((VarInitPair*)p2)->first;
|
|
||||||
if (v1->offset < v2->offset)
|
|
||||||
return -1;
|
|
||||||
else if (v1->offset > v2->offset)
|
|
||||||
return 1;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
this uses a simple algorithm to build the correct constant
|
|
||||||
|
|
||||||
(1) first sort the explicit initializers by offset... well, DMD doesn't :)
|
|
||||||
|
|
||||||
(2) if there is NO space before the next explicit initializeer, goto (9)
|
|
||||||
(3) find the next default initializer that fits before it, if NOT found goto (7)
|
|
||||||
(4) insert zero padding up to the next default initializer
|
|
||||||
(5) insert the next default initializer
|
|
||||||
(6) goto (2)
|
|
||||||
|
|
||||||
(7) insert zero padding up to the next explicit initializer
|
|
||||||
|
|
||||||
(9) insert the next explicit initializer
|
|
||||||
(10) goto (2)
|
|
||||||
|
|
||||||
(11) done
|
|
||||||
|
|
||||||
(next can be the end too)
|
|
||||||
|
|
||||||
*/
|
|
||||||
|
|
||||||
// return the next default initializer to use or null
|
|
||||||
static VarDeclaration* nextDefault(IrStruct* irstruct, size_t& idx, size_t pos, size_t offset)
|
|
||||||
{
|
|
||||||
IrStruct::VarDeclVector& defaults = irstruct->defVars;
|
|
||||||
size_t ndefaults = defaults.size();
|
|
||||||
|
|
||||||
// for each valid index
|
|
||||||
while(idx < ndefaults)
|
|
||||||
{
|
|
||||||
VarDeclaration* v = defaults[idx];
|
|
||||||
|
|
||||||
// skip defaults before pos
|
|
||||||
if (v->offset < pos)
|
|
||||||
{
|
|
||||||
idx++;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// this var default fits
|
|
||||||
if (v->offset >= pos && v->offset + v->type->size() <= offset)
|
|
||||||
return v;
|
|
||||||
|
|
||||||
// not usable
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not usable
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
LLConstant* DtoConstStructInitializer(StructInitializer* si)
|
|
||||||
{
|
|
||||||
Logger::println("DtoConstStructInitializer: %s", si->toChars());
|
|
||||||
LOG_SCOPE;
|
|
||||||
|
|
||||||
// get TypeStruct
|
|
||||||
assert(si->ad);
|
|
||||||
TypeStruct* ts = (TypeStruct*)si->ad->type;
|
|
||||||
|
|
||||||
// force constant initialization of the symbol
|
|
||||||
si->ad->codegen(Type::sir);
|
|
||||||
|
|
||||||
// sanity check
|
|
||||||
assert(si->value.dim > 0);
|
|
||||||
assert(si->value.dim == si->vars.dim);
|
|
||||||
|
|
||||||
// vector of final initializer constants
|
|
||||||
std::vector<LLConstant*> inits;
|
|
||||||
|
|
||||||
// get the ir struct
|
|
||||||
IrStruct* irstruct = si->ad->ir.irStruct;
|
|
||||||
|
|
||||||
// get default fields
|
|
||||||
IrStruct::VarDeclVector& defaults = irstruct->defVars;
|
|
||||||
size_t ndefaults = defaults.size();
|
|
||||||
|
|
||||||
// make sure si->vars is sorted by offset
|
|
||||||
std::vector<VarInitPair> vars;
|
|
||||||
size_t nvars = si->vars.dim;
|
|
||||||
vars.resize(nvars);
|
|
||||||
|
|
||||||
// fill pair vector
|
|
||||||
for (size_t i = 0; i < nvars; i++)
|
|
||||||
{
|
|
||||||
VarDeclaration* var = (VarDeclaration*)si->vars.data[i];
|
|
||||||
Initializer* ini = (Initializer*)si->value.data[i];
|
|
||||||
assert(var);
|
|
||||||
assert(ini);
|
|
||||||
vars[i] = std::make_pair(var, ini);
|
|
||||||
}
|
|
||||||
// sort it
|
|
||||||
qsort(&vars[0], nvars, sizeof(VarInitPair), &varinit_offset_cmp_func);
|
|
||||||
|
|
||||||
// check integrity
|
|
||||||
// and do error checking, since the frontend does not 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// error handling, report all overlaps before aborting
|
|
||||||
if (overlap)
|
|
||||||
{
|
|
||||||
error("%s: overlapping union initializers", si->loc.toChars());
|
|
||||||
}
|
|
||||||
|
|
||||||
// go through each explicit initalizer, falling back to defaults or zeros when necessary
|
|
||||||
lastoffset = 0;
|
|
||||||
lastsize = 0;
|
|
||||||
|
|
||||||
size_t j=0; // defaults
|
|
||||||
|
|
||||||
for (size_t i=0; i < nvars; i++)
|
|
||||||
{
|
|
||||||
// get var and init
|
|
||||||
VarDeclaration* var = vars[i].first;
|
|
||||||
Initializer* ini = vars[i].second;
|
|
||||||
|
|
||||||
size_t offset = var->offset;
|
|
||||||
size_t size = var->type->size();
|
|
||||||
|
|
||||||
// if there is space before the next explicit initializer
|
|
||||||
Lpadding:
|
|
||||||
size_t pos = lastoffset+lastsize;
|
|
||||||
if (offset > pos)
|
|
||||||
{
|
|
||||||
// find the the next default initializer that fits in this space
|
|
||||||
VarDeclaration* nextdef = nextDefault(irstruct, j, lastoffset+lastsize, offset);
|
|
||||||
|
|
||||||
// found
|
|
||||||
if (nextdef)
|
|
||||||
{
|
|
||||||
// need zeros before the default
|
|
||||||
if (nextdef->offset > pos)
|
|
||||||
{
|
|
||||||
Logger::println("inserting %lu byte padding at %lu", nextdef->offset - pos, pos);
|
|
||||||
addZeros(inits, pos, nextdef->offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
// do the default
|
|
||||||
Logger::println("adding default field: %s : +%u", nextdef->toChars(), nextdef->offset);
|
|
||||||
if (!nextdef->ir.irField->constInit)
|
|
||||||
nextdef->ir.irField->constInit = DtoConstInitializer(nextdef->loc, nextdef->type, nextdef->init);
|
|
||||||
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 = si->ad->structsize;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
if (!nextdef->ir.irField->constInit)
|
|
||||||
nextdef->ir.irField->constInit = DtoConstInitializer(nextdef->loc, nextdef->type, nextdef->init);
|
|
||||||
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(getTypePaddedSize(c->getType()) == structsize);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
std::vector<llvm::Value*> DtoStructLiteralValues(const StructDeclaration* sd, const std::vector<llvm::Value*>& inits)
|
|
||||||
{
|
|
||||||
// get arrays
|
|
||||||
size_t nvars = sd->fields.dim;
|
|
||||||
VarDeclaration** vars = (VarDeclaration**)sd->fields.data;
|
|
||||||
|
|
||||||
assert(inits.size() == nvars);
|
|
||||||
|
|
||||||
// first locate all explicit initializers
|
|
||||||
std::vector<VarDeclaration*> explicitInits;
|
|
||||||
for (size_t i=0; i < nvars; i++)
|
|
||||||
{
|
|
||||||
if (inits[i])
|
|
||||||
{
|
|
||||||
explicitInits.push_back(vars[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// vector of values to build aggregate from
|
|
||||||
std::vector<llvm::Value*> values;
|
|
||||||
|
|
||||||
// offset trackers
|
|
||||||
size_t lastoffset = 0;
|
|
||||||
size_t lastsize = 0;
|
|
||||||
|
|
||||||
// index of next explicit init
|
|
||||||
size_t exidx = 0;
|
|
||||||
// number of explicit inits
|
|
||||||
size_t nex = explicitInits.size();
|
|
||||||
|
|
||||||
// for through each field and build up the struct, padding with zeros
|
|
||||||
size_t i;
|
|
||||||
for (i=0; i<nvars; i++)
|
|
||||||
{
|
|
||||||
VarDeclaration* var = vars[i];
|
|
||||||
|
|
||||||
// get var info
|
|
||||||
size_t os = var->offset;
|
|
||||||
size_t sz = var->type->size();
|
|
||||||
|
|
||||||
// get next explicit
|
|
||||||
VarDeclaration* nextVar = NULL;
|
|
||||||
size_t nextOs = 0;
|
|
||||||
if (exidx < nex)
|
|
||||||
{
|
|
||||||
nextVar = explicitInits[exidx];
|
|
||||||
nextOs = nextVar->offset;
|
|
||||||
}
|
|
||||||
// none, rest is defaults
|
|
||||||
else
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// not explicit initializer, default initialize if there is room, otherwise skip
|
|
||||||
if (!inits[i])
|
|
||||||
{
|
|
||||||
// default init if there is room
|
|
||||||
// (past current offset) and (small enough to fit before next explicit)
|
|
||||||
if ((os >= lastoffset + lastsize) && (os+sz <= nextOs))
|
|
||||||
{
|
|
||||||
// add any 0 padding needed before this field
|
|
||||||
if (os > lastoffset + lastsize)
|
|
||||||
{
|
|
||||||
//printf("1added %lu zeros\n", os - lastoffset - lastsize);
|
|
||||||
addZeros(values, lastoffset + lastsize, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get field default init
|
|
||||||
IrField* f = var->ir.irField;
|
|
||||||
assert(f);
|
|
||||||
if (!f->constInit)
|
|
||||||
f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
|
|
||||||
|
|
||||||
values.push_back(f->constInit);
|
|
||||||
|
|
||||||
lastoffset = os;
|
|
||||||
lastsize = sz;
|
|
||||||
//printf("added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
|
|
||||||
}
|
|
||||||
// skip
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(nextVar == var);
|
|
||||||
|
|
||||||
// add any 0 padding needed before this field
|
|
||||||
if (os > lastoffset + lastsize)
|
|
||||||
{
|
|
||||||
//printf("added %lu zeros\n", os - lastoffset - lastsize);
|
|
||||||
addZeros(values, lastoffset + lastsize, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the expression value
|
|
||||||
values.push_back(inits[i]);
|
|
||||||
|
|
||||||
// update offsets
|
|
||||||
lastoffset = os;
|
|
||||||
lastsize = sz;
|
|
||||||
|
|
||||||
// go to next explicit init
|
|
||||||
exidx++;
|
|
||||||
|
|
||||||
//printf("added field: %s : %lu (%lu)\n", var->toChars(), os, sz);
|
|
||||||
}
|
|
||||||
|
|
||||||
// fill out rest with default initializers
|
|
||||||
const LLType* structtype = DtoType(sd->type);
|
|
||||||
size_t structsize = getTypePaddedSize(structtype);
|
|
||||||
|
|
||||||
// FIXME: this could probably share some code with the above
|
|
||||||
if (structsize > lastoffset+lastsize)
|
|
||||||
{
|
|
||||||
for (/*continue from first loop*/; i < nvars; i++)
|
|
||||||
{
|
|
||||||
VarDeclaration* var = vars[i];
|
|
||||||
|
|
||||||
// get var info
|
|
||||||
size_t os = var->offset;
|
|
||||||
size_t sz = var->type->size();
|
|
||||||
|
|
||||||
// skip?
|
|
||||||
if (os < lastoffset + lastsize)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// add any 0 padding needed before this field
|
|
||||||
if (os > lastoffset + lastsize)
|
|
||||||
{
|
|
||||||
//printf("2added %lu zeros\n", os - lastoffset - lastsize);
|
|
||||||
addZeros(values, lastoffset + lastsize, os);
|
|
||||||
}
|
|
||||||
|
|
||||||
// get field default init
|
|
||||||
IrField* f = var->ir.irField;
|
|
||||||
assert(f);
|
|
||||||
if (!f->constInit)
|
|
||||||
f->constInit = DtoConstInitializer(var->loc, var->type, var->init);
|
|
||||||
|
|
||||||
values.push_back(f->constInit);
|
|
||||||
|
|
||||||
lastoffset = os;
|
|
||||||
lastsize = sz;
|
|
||||||
//printf("2added default: %s : %lu (%lu)\n", var->toChars(), os, sz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// add any 0 padding needed at the end of the literal
|
|
||||||
if (structsize > lastoffset+lastsize)
|
|
||||||
{
|
|
||||||
//printf("3added %lu zeros\n", structsize - lastoffset - lastsize);
|
|
||||||
addZeros(values, lastoffset + lastsize, structsize);
|
|
||||||
}
|
|
||||||
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -490,10 +62,6 @@ LLValue* DtoIndexStruct(LLValue* src, StructDeclaration* sd, VarDeclaration* vd)
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
static void DtoDeclareStruct(StructDeclaration* sd);
|
|
||||||
static void DtoConstInitStruct(StructDeclaration* sd);
|
|
||||||
static void DtoDefineStruct(StructDeclaration* sd);
|
|
||||||
|
|
||||||
void DtoResolveStruct(StructDeclaration* sd)
|
void DtoResolveStruct(StructDeclaration* sd)
|
||||||
{
|
{
|
||||||
// don't do anything if already been here
|
// don't do anything if already been here
|
||||||
@@ -505,185 +73,38 @@ void DtoResolveStruct(StructDeclaration* sd)
|
|||||||
Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
|
Logger::println("Resolving struct type: %s (%s)", sd->toChars(), sd->locToChars());
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
|
||||||
// get the DMD TypeStruct
|
// make sure type exists
|
||||||
TypeStruct* ts = (TypeStruct*)sd->type;
|
DtoType(sd->type);
|
||||||
|
|
||||||
// create the IrStruct
|
// create the IrStruct
|
||||||
IrStruct* irstruct = new IrStruct(sd);
|
IrStruct* irstruct = new IrStruct(sd);
|
||||||
sd->ir.irStruct = irstruct;
|
sd->ir.irStruct = irstruct;
|
||||||
|
|
||||||
// create the type
|
// emit the initZ symbol
|
||||||
ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
|
LLGlobalVariable* initZ = irstruct->getInitSymbol();
|
||||||
|
|
||||||
// create symbols we're going to need
|
// perform definition
|
||||||
// avoids chicken egg problems
|
|
||||||
std::string initname("_D");
|
|
||||||
initname.append(sd->mangle());
|
|
||||||
initname.append("6__initZ");
|
|
||||||
|
|
||||||
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(sd);
|
|
||||||
sd->ir.irStruct->init = new llvm::GlobalVariable(sd->ir.irStruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
|
|
||||||
|
|
||||||
// handle forward declaration structs (opaques)
|
|
||||||
// didn't even know D had those ...
|
|
||||||
if (sd->sizeok != 1)
|
|
||||||
{
|
|
||||||
// nothing more to do
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make this struct current
|
|
||||||
gIR->structs.push_back(irstruct);
|
|
||||||
|
|
||||||
// get some info
|
|
||||||
bool ispacked = (ts->alignsize() == 1);
|
|
||||||
|
|
||||||
// set irstruct info
|
|
||||||
irstruct->packed = ispacked;
|
|
||||||
|
|
||||||
// methods, fields
|
|
||||||
Array* arr = sd->members;
|
|
||||||
for (int k=0; k < arr->dim; k++) {
|
|
||||||
Dsymbol* s = (Dsymbol*)arr->data[k];
|
|
||||||
s->codegen(Type::sir);
|
|
||||||
}
|
|
||||||
|
|
||||||
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)getTypePaddedSize(ST);
|
|
||||||
unsigned dmdSize = (unsigned)sd->type->size();
|
|
||||||
printf(" llvm size: %u dmd size: %u\n", llvmSize, dmdSize);
|
|
||||||
assert(llvmSize == dmdSize);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*for (int k=0; k < sd->members->dim; k++) {
|
|
||||||
Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]);
|
|
||||||
dsym->toObjFile();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
Logger::println("doing struct fields");
|
|
||||||
|
|
||||||
// refine abstract types for stuff like: struct S{S* next;}
|
|
||||||
llvm::cast<llvm::OpaqueType>(ts->ir.type->get())->refineAbstractTypeTo(ST);
|
|
||||||
ST = ts->ir.type->get();
|
|
||||||
|
|
||||||
// name type
|
|
||||||
if (sd->parent->isModule()) {
|
|
||||||
gIR->module->addTypeName(sd->mangle(),ST);
|
|
||||||
}
|
|
||||||
|
|
||||||
// emit functions
|
|
||||||
size_t n = irstruct->structFuncs.size();
|
|
||||||
for (size_t i = 0; i < n; ++i)
|
|
||||||
{
|
|
||||||
DtoResolveFunction(irstruct->structFuncs[i]);
|
|
||||||
}
|
|
||||||
irstruct->structFuncs.clear();
|
|
||||||
|
|
||||||
gIR->structs.pop_back();
|
|
||||||
|
|
||||||
DtoDeclareStruct(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void DtoDeclareStruct(StructDeclaration* sd)
|
|
||||||
{
|
|
||||||
DtoResolveStruct(sd);
|
|
||||||
|
|
||||||
if (sd->ir.declared) return;
|
|
||||||
sd->ir.declared = true;
|
|
||||||
|
|
||||||
Logger::println("DtoDeclareStruct(%s): %s", sd->toChars(), sd->loc.toChars());
|
|
||||||
LOG_SCOPE;
|
|
||||||
|
|
||||||
TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
|
|
||||||
|
|
||||||
DtoConstInitStruct(sd);
|
|
||||||
if (mustDefineSymbol(sd))
|
if (mustDefineSymbol(sd))
|
||||||
DtoDefineStruct(sd);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void DtoConstInitStruct(StructDeclaration* sd)
|
|
||||||
{
|
|
||||||
DtoDeclareStruct(sd);
|
|
||||||
|
|
||||||
if (sd->ir.initialized) return;
|
|
||||||
sd->ir.initialized = true;
|
|
||||||
|
|
||||||
Logger::println("DtoConstInitStruct(%s): %s", sd->toChars(), sd->loc.toChars());
|
|
||||||
LOG_SCOPE;
|
|
||||||
|
|
||||||
IrStruct* irstruct = sd->ir.irStruct;
|
|
||||||
gIR->structs.push_back(irstruct);
|
|
||||||
|
|
||||||
const llvm::StructType* structtype = isaStruct(sd->type->ir.type->get());
|
|
||||||
|
|
||||||
// always generate the constant initalizer
|
|
||||||
assert(!irstruct->constInit);
|
|
||||||
if (sd->zeroInit)
|
|
||||||
{
|
{
|
||||||
Logger::println("Zero initialized");
|
// set initZ initializer
|
||||||
irstruct->constInit = llvm::ConstantAggregateZero::get(structtype);
|
initZ->setInitializer(irstruct->getDefaultInit());
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::println("Not zero initialized");
|
|
||||||
|
|
||||||
LLConstant* c = irstruct->buildDefaultConstInit();
|
|
||||||
irstruct->constInit = c;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// refine __initZ global type to the one of the initializer
|
// emit members
|
||||||
llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
|
if (sd->members)
|
||||||
|
|
||||||
// build initializers for static member variables
|
|
||||||
size_t n = irstruct->staticVars.size();
|
|
||||||
for (size_t i = 0; i < n; ++i)
|
|
||||||
{
|
{
|
||||||
DtoConstInitGlobal(irstruct->staticVars[i]);
|
ArrayIter<Dsymbol> it(*sd->members);
|
||||||
|
while (!it.done())
|
||||||
|
{
|
||||||
|
Dsymbol* member = it.get();
|
||||||
|
if (member)
|
||||||
|
member->codegen(Type::sir);
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// This is all we use it for. Clear the memory!
|
|
||||||
irstruct->staticVars.clear();
|
|
||||||
|
|
||||||
gIR->structs.pop_back();
|
|
||||||
|
|
||||||
// emit typeinfo
|
// emit typeinfo
|
||||||
if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMno_typeinfo)
|
DtoTypeInfoOf(sd->type);
|
||||||
DtoTypeInfoOf(sd->type, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void DtoDefineStruct(StructDeclaration* sd)
|
|
||||||
{
|
|
||||||
DtoConstInitStruct(sd);
|
|
||||||
|
|
||||||
if (sd->ir.defined) return;
|
|
||||||
sd->ir.defined = true;
|
|
||||||
|
|
||||||
Logger::println("DtoDefineStruct(%s): %s", sd->toChars(), sd->loc.toChars());
|
|
||||||
LOG_SCOPE;
|
|
||||||
|
|
||||||
assert(sd->type->ty == Tstruct);
|
|
||||||
TypeStruct* ts = (TypeStruct*)sd->type;
|
|
||||||
sd->ir.irStruct->init->setInitializer(sd->ir.irStruct->constInit);
|
|
||||||
|
|
||||||
sd->ir.DModule = gIR->dmodule;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "gen/logger.h"
|
#include "gen/logger.h"
|
||||||
#include "gen/llvmhelpers.h"
|
#include "gen/llvmhelpers.h"
|
||||||
#include "gen/linkage.h"
|
#include "gen/linkage.h"
|
||||||
|
#include "gen/utils.h"
|
||||||
|
|
||||||
#include "ir/irmodule.h"
|
#include "ir/irmodule.h"
|
||||||
|
|
||||||
@@ -288,14 +289,12 @@ static llvm::DICompositeType dwarfCompositeType(Type* type, llvm::DICompileUnit
|
|||||||
std::vector<LLConstant*> elems;
|
std::vector<LLConstant*> elems;
|
||||||
if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
|
if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
|
||||||
{
|
{
|
||||||
std::vector<VarDeclaration*>& arr = ir->varDecls;
|
ArrayIter<VarDeclaration> it(sd->fields);
|
||||||
size_t narr = arr.size();
|
size_t narr = sd->fields.dim;
|
||||||
elems.reserve(narr);
|
elems.reserve(narr);
|
||||||
for (int k=0; k<narr; k++)
|
for (; !it.done(); it.next())
|
||||||
{
|
{
|
||||||
VarDeclaration* vd = arr[k];
|
VarDeclaration* vd = it.get();
|
||||||
assert(vd);
|
|
||||||
|
|
||||||
LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV();
|
LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV();
|
||||||
elems.push_back(DBG_CAST(ptr));
|
elems.push_back(DBG_CAST(ptr));
|
||||||
}
|
}
|
||||||
|
|||||||
26
gen/toir.cpp
26
gen/toir.cpp
@@ -131,8 +131,7 @@ DValue* VarExp::toElem(IRState* p)
|
|||||||
{
|
{
|
||||||
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
|
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
|
||||||
cid->cd->codegen(Type::sir);;
|
cid->cd->codegen(Type::sir);;
|
||||||
assert(cid->cd->ir.irStruct->classInfo);
|
return new DVarValue(type, vd, cid->cd->ir.irStruct->getClassInfoSymbol());
|
||||||
return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo);
|
|
||||||
}
|
}
|
||||||
// nested variable
|
// nested variable
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
@@ -216,8 +215,8 @@ DValue* VarExp::toElem(IRState* p)
|
|||||||
TypeStruct* ts = (TypeStruct*)sdecltype;
|
TypeStruct* ts = (TypeStruct*)sdecltype;
|
||||||
assert(ts->sym);
|
assert(ts->sym);
|
||||||
ts->sym->codegen(Type::sir);
|
ts->sym->codegen(Type::sir);
|
||||||
assert(ts->sym->ir.irStruct->init);
|
|
||||||
return new DVarValue(type, ts->sym->ir.irStruct->init);
|
return new DVarValue(type, ts->sym->ir.irStruct->getInitSymbol());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -242,8 +241,8 @@ LLConstant* VarExp::toConstElem(IRState* p)
|
|||||||
assert(sdecltype->ty == Tstruct);
|
assert(sdecltype->ty == Tstruct);
|
||||||
TypeStruct* ts = (TypeStruct*)sdecltype;
|
TypeStruct* ts = (TypeStruct*)sdecltype;
|
||||||
ts->sym->codegen(Type::sir);
|
ts->sym->codegen(Type::sir);
|
||||||
assert(ts->sym->ir.irStruct->constInit);
|
|
||||||
return ts->sym->ir.irStruct->constInit;
|
return ts->sym->ir.irStruct->getDefaultInit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TypeInfoDeclaration* ti = var->isTypeInfoDeclaration())
|
if (TypeInfoDeclaration* ti = var->isTypeInfoDeclaration())
|
||||||
@@ -1134,9 +1133,7 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||||||
size_t vtblidx = fdecl->vtblIndex;
|
size_t vtblidx = fdecl->vtblIndex;
|
||||||
if (Logger::enabled())
|
if (Logger::enabled())
|
||||||
Logger::cout() << "vthis: " << *vthis << '\n';
|
Logger::cout() << "vthis: " << *vthis << '\n';
|
||||||
funcval = vthis;
|
funcval = DtoGEP(vthis, zero, zero);
|
||||||
if (!fdecl->isMember2()->isInterfaceDeclaration())
|
|
||||||
funcval = DtoGEP(funcval, zero, zero);
|
|
||||||
funcval = DtoLoad(funcval);
|
funcval = DtoLoad(funcval);
|
||||||
Logger::println("vtblidx = %lu", vtblidx);
|
Logger::println("vtblidx = %lu", vtblidx);
|
||||||
funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
|
funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
|
||||||
@@ -1646,7 +1643,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||||||
else {
|
else {
|
||||||
assert(ts->sym);
|
assert(ts->sym);
|
||||||
ts->sym->codegen(Type::sir);
|
ts->sym->codegen(Type::sir);
|
||||||
DtoAggrCopy(mem,ts->sym->ir.irStruct->init);
|
DtoAggrCopy(mem,ts->sym->ir.irStruct->getInitSymbol());
|
||||||
}
|
}
|
||||||
return new DImValue(type, mem);
|
return new DImValue(type, mem);
|
||||||
}
|
}
|
||||||
@@ -1658,8 +1655,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||||||
DVarValue tmpvar(newtype, mem);
|
DVarValue tmpvar(newtype, mem);
|
||||||
|
|
||||||
// default initialize
|
// default initialize
|
||||||
// FIXME: should this use DtoConstExpInit instead ?
|
// static arrays never appear here, so using the defaultInit is ok!
|
||||||
// or is static arrays the only troublemaker?
|
|
||||||
Expression* exp = newtype->defaultInit(loc);
|
Expression* exp = newtype->defaultInit(loc);
|
||||||
DValue* iv = exp->toElem(gIR);
|
DValue* iv = exp->toElem(gIR);
|
||||||
DtoAssign(loc, &tmpvar, iv);
|
DtoAssign(loc, &tmpvar, iv);
|
||||||
@@ -2413,7 +2409,8 @@ DValue* StructLiteralExp::toElem(IRState* p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// vector of values to build aggregate from
|
// vector of values to build aggregate from
|
||||||
std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits);
|
std::vector<LLValue*> values;// = DtoStructLiteralValues(sd, inits);
|
||||||
|
assert(0 && "struct literal exp todo");
|
||||||
|
|
||||||
// get the struct type from the values
|
// get the struct type from the values
|
||||||
size_t n = values.size();
|
size_t n = values.size();
|
||||||
@@ -2462,7 +2459,8 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
|
|||||||
inits[i] = exprs[i]->toConstElem(p);
|
inits[i] = exprs[i]->toConstElem(p);
|
||||||
|
|
||||||
// vector of values to build aggregate from
|
// vector of values to build aggregate from
|
||||||
std::vector<LLValue*> values = DtoStructLiteralValues(sd, inits);
|
std::vector<LLValue*> values;// = DtoStructLiteralValues(sd, inits);
|
||||||
|
assert(0 && "struct literal const exp todo");
|
||||||
|
|
||||||
// we know those values are constants.. cast them
|
// we know those values are constants.. cast them
|
||||||
std::vector<LLConstant*> constvals(values.size(), NULL);
|
std::vector<LLConstant*> constvals(values.size(), NULL);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "gen/llvm-version.h"
|
#include "gen/llvm-version.h"
|
||||||
|
|
||||||
#include "ir/irtype.h"
|
#include "ir/irtype.h"
|
||||||
|
#include "ir/irtypeclass.h"
|
||||||
|
|
||||||
bool DtoIsPassedByRef(Type* type)
|
bool DtoIsPassedByRef(Type* type)
|
||||||
{
|
{
|
||||||
@@ -52,11 +53,17 @@ unsigned DtoShouldExtend(Type* type)
|
|||||||
|
|
||||||
const LLType* DtoType(Type* t)
|
const LLType* DtoType(Type* t)
|
||||||
{
|
{
|
||||||
|
#if DMDV2
|
||||||
|
t = t->mutableOf();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (t->irtype)
|
if (t->irtype)
|
||||||
{
|
{
|
||||||
return t->irtype->get();
|
return t->irtype->get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Building type: %s", t->toChars());
|
||||||
|
|
||||||
assert(t);
|
assert(t);
|
||||||
switch (t->ty)
|
switch (t->ty)
|
||||||
{
|
{
|
||||||
@@ -86,57 +93,50 @@ const LLType* DtoType(Type* t)
|
|||||||
case Tdchar:
|
case Tdchar:
|
||||||
{
|
{
|
||||||
t->irtype = new IrTypeBasic(t);
|
t->irtype = new IrTypeBasic(t);
|
||||||
return t->irtype->get();
|
return t->irtype->buildType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// pointers
|
// pointers
|
||||||
case Tpointer:
|
case Tpointer:
|
||||||
{
|
{
|
||||||
t->irtype = new IrTypePointer(t);
|
t->irtype = new IrTypePointer(t);
|
||||||
return t->irtype->get();
|
return t->irtype->buildType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// arrays
|
// arrays
|
||||||
case Tarray:
|
case Tarray:
|
||||||
{
|
{
|
||||||
t->irtype = new IrTypeArray(t);
|
t->irtype = new IrTypeArray(t);
|
||||||
return t->irtype->get();
|
return t->irtype->buildType();
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tsarray:
|
case Tsarray:
|
||||||
{
|
{
|
||||||
t->irtype = new IrTypeSArray(t);
|
t->irtype = new IrTypeSArray(t);
|
||||||
return t->irtype->get();
|
return t->irtype->buildType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// aggregates
|
// aggregates
|
||||||
case Tstruct: {
|
case Tstruct: {
|
||||||
#if DMDV2
|
|
||||||
TypeStruct* ts = (TypeStruct*)t->mutableOf();
|
|
||||||
#else
|
|
||||||
TypeStruct* ts = (TypeStruct*)t;
|
TypeStruct* ts = (TypeStruct*)t;
|
||||||
#endif
|
t->irtype = new IrTypeStruct(ts->sym);
|
||||||
assert(ts->sym);
|
return t->irtype->buildType();
|
||||||
DtoResolveDsymbol(ts->sym);
|
|
||||||
return ts->ir.type->get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case Tclass: {
|
case Tclass: {
|
||||||
#if DMDV2
|
|
||||||
TypeClass* tc = (TypeClass*)t->mutableOf();
|
|
||||||
#else
|
|
||||||
TypeClass* tc = (TypeClass*)t;
|
TypeClass* tc = (TypeClass*)t;
|
||||||
#endif
|
t->irtype = new IrTypeClass(tc->sym);
|
||||||
assert(tc->sym);
|
return t->irtype->buildType();
|
||||||
DtoResolveDsymbol(tc->sym);
|
|
||||||
return getPtrToType(tc->ir.type->get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// functions
|
// functions
|
||||||
case Tfunction:
|
case Tfunction:
|
||||||
{
|
{
|
||||||
if (!t->ir.type || *t->ir.type == NULL) {
|
if (!t->ir.type || *t->ir.type == NULL) {
|
||||||
return DtoFunctionType(t,NULL,NULL);
|
TypeFunction* tf = (TypeFunction*)t;
|
||||||
|
if (tf->funcdecl)
|
||||||
|
return DtoFunctionType(tf->funcdecl);
|
||||||
|
else
|
||||||
|
return DtoFunctionType(tf,NULL,NULL);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return t->ir.type->get();
|
return t->ir.type->get();
|
||||||
@@ -156,6 +156,8 @@ const LLType* DtoType(Type* t)
|
|||||||
|
|
||||||
// typedefs
|
// typedefs
|
||||||
// enum
|
// enum
|
||||||
|
|
||||||
|
// FIXME: maybe just call toBasetype first ?
|
||||||
case Ttypedef:
|
case Ttypedef:
|
||||||
case Tenum:
|
case Tenum:
|
||||||
{
|
{
|
||||||
@@ -166,15 +168,7 @@ const LLType* DtoType(Type* t)
|
|||||||
|
|
||||||
// associative arrays
|
// associative arrays
|
||||||
case Taarray:
|
case Taarray:
|
||||||
#if 1
|
|
||||||
return getVoidPtrType();
|
return getVoidPtrType();
|
||||||
#else
|
|
||||||
{
|
|
||||||
TypeAArray* taa = (TypeAArray*)t;
|
|
||||||
// aa key/val can't be void
|
|
||||||
return getPtrToType(LLStructType::get(DtoType(taa->key), DtoType(taa->next), 0));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Not needed atm as VarDecls for tuples are rewritten as a string of
|
Not needed atm as VarDecls for tuples are rewritten as a string of
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ llvm::Module* Module::genLLVMModule(Ir* sir)
|
|||||||
sir->emitFunctionBodies();
|
sir->emitFunctionBodies();
|
||||||
|
|
||||||
// generate ModuleInfo
|
// generate ModuleInfo
|
||||||
genmoduleinfo();
|
//genmoduleinfo();
|
||||||
|
|
||||||
// emit usedArray
|
// emit usedArray
|
||||||
if (!ir.usedArray.empty())
|
if (!ir.usedArray.empty())
|
||||||
@@ -621,7 +621,7 @@ void Module::genmoduleinfo()
|
|||||||
LLConstant* c = 0;
|
LLConstant* c = 0;
|
||||||
|
|
||||||
// vtable
|
// vtable
|
||||||
c = moduleinfo->ir.irStruct->vtbl;
|
c = moduleinfo->ir.irStruct->getVtblSymbol();
|
||||||
initVec.push_back(c);
|
initVec.push_back(c);
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
@@ -696,8 +696,7 @@ void Module::genmoduleinfo()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Logger::println("class: %s", cd->toPrettyChars());
|
Logger::println("class: %s", cd->toPrettyChars());
|
||||||
assert(cd->ir.irStruct->classInfo);
|
c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy));
|
||||||
c = DtoBitCast(cd->ir.irStruct->classInfo, getPtrToType(classinfoTy));
|
|
||||||
classInits.push_back(c);
|
classInits.push_back(c);
|
||||||
}
|
}
|
||||||
// has class array?
|
// has class array?
|
||||||
|
|||||||
@@ -253,20 +253,6 @@ int TypeDArray::builtinTypeInfo()
|
|||||||
|
|
||||||
/* ========================================================================= */
|
/* ========================================================================= */
|
||||||
|
|
||||||
/***************************************
|
|
||||||
* Create a static array of TypeInfo references
|
|
||||||
* corresponding to an array of Expression's.
|
|
||||||
* Used to supply hidden _arguments[] value for variadic D functions.
|
|
||||||
*/
|
|
||||||
|
|
||||||
Expression *createTypeInfoArray(Scope *sc, Expression *exps[], int dim)
|
|
||||||
{
|
|
||||||
assert(0); // done elsewhere in LDC
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ========================================================================= */
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// MAGIC PLACE
|
// MAGIC PLACE
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -376,7 +362,7 @@ void TypeInfoTypedefDeclaration::llvmDefine()
|
|||||||
|
|
||||||
// vtbl
|
// vtbl
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(getNullPtr(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(getNullPtr(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -433,7 +419,7 @@ void TypeInfoEnumDeclaration::llvmDefine()
|
|||||||
|
|
||||||
// vtbl
|
// vtbl
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -491,7 +477,7 @@ static void LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid,
|
|||||||
|
|
||||||
// vtbl
|
// vtbl
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -553,7 +539,7 @@ void TypeInfoStaticArrayDeclaration::llvmDefine()
|
|||||||
// initializer vector
|
// initializer vector
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
// first is always the vtable
|
// first is always the vtable
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -592,7 +578,7 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
|
|||||||
// initializer vector
|
// initializer vector
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
// first is always the vtable
|
// first is always the vtable
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -664,7 +650,7 @@ void TypeInfoStructDeclaration::llvmDefine()
|
|||||||
|
|
||||||
// vtbl
|
// vtbl
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -687,7 +673,7 @@ void TypeInfoStructDeclaration::llvmDefine()
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
size_t cisize = getTypeStoreSize(tc->ir.type->get());
|
size_t cisize = getTypeStoreSize(tc->ir.type->get());
|
||||||
LLConstant* cicast = llvm::ConstantExpr::getBitCast(sd->ir.irStruct->init, initpt);
|
LLConstant* cicast = llvm::ConstantExpr::getBitCast(sd->ir.irStruct->getInitSymbol(), initpt);
|
||||||
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
|
sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -857,7 +843,7 @@ void TypeInfoClassDeclaration::llvmDefine()
|
|||||||
// initializer vector
|
// initializer vector
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
// first is always the vtable
|
// first is always the vtable
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -865,9 +851,10 @@ void TypeInfoClassDeclaration::llvmDefine()
|
|||||||
// get classinfo
|
// get classinfo
|
||||||
assert(tinfo->ty == Tclass);
|
assert(tinfo->ty == Tclass);
|
||||||
TypeClass *tc = (TypeClass *)tinfo;
|
TypeClass *tc = (TypeClass *)tinfo;
|
||||||
tc->sym->codegen(Type::sir);;
|
|
||||||
assert(tc->sym->ir.irStruct->classInfo);
|
tc->sym->codegen(Type::sir);
|
||||||
sinits.push_back(tc->sym->ir.irStruct->classInfo);
|
|
||||||
|
sinits.push_back(tc->sym->ir.irStruct->getClassInfoSymbol());
|
||||||
|
|
||||||
// create the inititalizer
|
// create the inititalizer
|
||||||
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
|
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
|
||||||
@@ -897,7 +884,7 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
|
|||||||
// initializer vector
|
// initializer vector
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
// first is always the vtable
|
// first is always the vtable
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
@@ -905,8 +892,8 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
|
|||||||
// get classinfo
|
// get classinfo
|
||||||
assert(tinfo->ty == Tclass);
|
assert(tinfo->ty == Tclass);
|
||||||
TypeClass *tc = (TypeClass *)tinfo;
|
TypeClass *tc = (TypeClass *)tinfo;
|
||||||
assert(tc->sym->ir.irStruct->classInfo);
|
|
||||||
sinits.push_back(tc->sym->ir.irStruct->classInfo);
|
sinits.push_back(tc->sym->ir.irStruct->getClassInfoSymbol());
|
||||||
|
|
||||||
// create the inititalizer
|
// create the inititalizer
|
||||||
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
|
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
|
||||||
@@ -936,7 +923,7 @@ void TypeInfoTupleDeclaration::llvmDefine()
|
|||||||
// initializer vector
|
// initializer vector
|
||||||
std::vector<LLConstant*> sinits;
|
std::vector<LLConstant*> sinits;
|
||||||
// first is always the vtable
|
// first is always the vtable
|
||||||
sinits.push_back(base->ir.irStruct->vtbl);
|
sinits.push_back(base->ir.irStruct->getVtblSymbol());
|
||||||
|
|
||||||
// monitor
|
// monitor
|
||||||
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
|
||||||
|
|||||||
46
gen/utils.h
Normal file
46
gen/utils.h
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#ifndef __LDC_GEN_UTILS_H__
|
||||||
|
#define __LDC_GEN_UTILS_H__
|
||||||
|
|
||||||
|
#include "root.h"
|
||||||
|
|
||||||
|
/// Very simple templated iterator for DMD ArrayS.
|
||||||
|
template<class C>
|
||||||
|
struct ArrayIter
|
||||||
|
{
|
||||||
|
Array& array;
|
||||||
|
size_t index;
|
||||||
|
|
||||||
|
ArrayIter(Array& arr, size_t idx = 0)
|
||||||
|
: array(arr), index(idx)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
bool done()
|
||||||
|
{
|
||||||
|
return index >= array.dim;
|
||||||
|
}
|
||||||
|
bool more()
|
||||||
|
{
|
||||||
|
return index < array.dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
C* get()
|
||||||
|
{
|
||||||
|
return static_cast<C*>(array.data[index]);
|
||||||
|
}
|
||||||
|
C* operator->()
|
||||||
|
{
|
||||||
|
return static_cast<C*>(array.data[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void next()
|
||||||
|
{
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// some aliases
|
||||||
|
typedef ArrayIter<Dsymbol> DsymbolIter;
|
||||||
|
typedef ArrayIter<FuncDeclaration> FuncDeclarationIter;
|
||||||
|
typedef ArrayIter<VarDeclaration> VarDeclarationIter;
|
||||||
|
|
||||||
|
#endif
|
||||||
441
ir/irclass.cpp
Normal file
441
ir/irclass.cpp
Normal file
@@ -0,0 +1,441 @@
|
|||||||
|
#include "llvm/Constants.h"
|
||||||
|
#include "llvm/DerivedTypes.h"
|
||||||
|
|
||||||
|
#include "aggregate.h"
|
||||||
|
#include "declaration.h"
|
||||||
|
#include "mtype.h"
|
||||||
|
|
||||||
|
#include "gen/irstate.h"
|
||||||
|
#include "gen/logger.h"
|
||||||
|
#include "gen/tollvm.h"
|
||||||
|
#include "gen/llvmhelpers.h"
|
||||||
|
#include "gen/utils.h"
|
||||||
|
#include "gen/arrays.h"
|
||||||
|
|
||||||
|
#include "ir/irstruct.h"
|
||||||
|
#include "ir/irtypeclass.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init);
|
||||||
|
extern size_t add_zeros(std::vector<llvm::Constant*>& constants, size_t diff);
|
||||||
|
|
||||||
|
extern LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLGlobalVariable * IrStruct::getVtblSymbol()
|
||||||
|
{
|
||||||
|
if (vtbl)
|
||||||
|
return vtbl;
|
||||||
|
|
||||||
|
// create the initZ symbol
|
||||||
|
std::string initname("_D");
|
||||||
|
initname.append(aggrdecl->mangle());
|
||||||
|
initname.append("6__vtblZ");
|
||||||
|
|
||||||
|
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
||||||
|
|
||||||
|
const LLType* vtblTy = type->irtype->isClass()->getVtbl();
|
||||||
|
|
||||||
|
vtbl = new llvm::GlobalVariable(
|
||||||
|
vtblTy, true, _linkage, NULL, initname, gIR->module);
|
||||||
|
|
||||||
|
return vtbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLGlobalVariable * IrStruct::getClassInfoSymbol()
|
||||||
|
{
|
||||||
|
if (classInfo)
|
||||||
|
return classInfo;
|
||||||
|
|
||||||
|
// create the initZ symbol
|
||||||
|
std::string initname("_D");
|
||||||
|
initname.append(aggrdecl->mangle());
|
||||||
|
if (aggrdecl->isInterfaceDeclaration())
|
||||||
|
initname.append("11__InterfaceZ");
|
||||||
|
else
|
||||||
|
initname.append("7__ClassZ");
|
||||||
|
|
||||||
|
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
||||||
|
|
||||||
|
ClassDeclaration* cinfo = ClassDeclaration::classinfo;
|
||||||
|
DtoType(cinfo->type);
|
||||||
|
IrTypeClass* tc = cinfo->type->irtype->isClass();
|
||||||
|
assert(tc && "invalid ClassInfo type");
|
||||||
|
|
||||||
|
classInfo = new llvm::GlobalVariable(
|
||||||
|
tc->getPA().get(), true, _linkage, NULL, initname, gIR->module);
|
||||||
|
|
||||||
|
return classInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLGlobalVariable * IrStruct::getInterfaceArraySymbol()
|
||||||
|
{
|
||||||
|
if (classInterfacesArray)
|
||||||
|
return classInterfacesArray;
|
||||||
|
|
||||||
|
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
|
||||||
|
|
||||||
|
assert(cd->vtblInterfaces && cd->vtblInterfaces->dim > 0 &&
|
||||||
|
"should not create interface info array for class with no explicit "
|
||||||
|
"interface implementations")
|
||||||
|
|
||||||
|
VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
|
||||||
|
const llvm::Type* InterfaceTy = DtoType(idx->type);
|
||||||
|
|
||||||
|
// create Interface[N]
|
||||||
|
const llvm::ArrayType* array_type = llvm::ArrayType::get(
|
||||||
|
InterfaceTy,
|
||||||
|
cd->vtblInterfaces->dim);
|
||||||
|
|
||||||
|
// put it in a global
|
||||||
|
std::string name("_D");
|
||||||
|
name.append(cd->mangle());
|
||||||
|
name.append("16__interfaceInfosZ");
|
||||||
|
classInterfacesArray = new llvm::GlobalVariable(array_type, true, DtoLinkage(cd), NULL, name, classInfo);
|
||||||
|
|
||||||
|
return classInterfacesArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLConstant * IrStruct::getVtblInit()
|
||||||
|
{
|
||||||
|
if (constVtbl)
|
||||||
|
return constVtbl;
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Building vtbl initializer");
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
|
||||||
|
assert(cd && "not class");
|
||||||
|
|
||||||
|
std::vector<llvm::Constant*> constants;
|
||||||
|
constants.reserve(cd->vtbl.dim);
|
||||||
|
|
||||||
|
// start with the classinfo
|
||||||
|
llvm::Constant* c = getClassInfoSymbol();
|
||||||
|
c = DtoBitCast(c, DtoType(ClassDeclaration::classinfo->type));
|
||||||
|
constants.push_back(c);
|
||||||
|
|
||||||
|
// add virtual function pointers
|
||||||
|
size_t n = cd->vtbl.dim;
|
||||||
|
for (size_t i = 1; i < n; i++)
|
||||||
|
{
|
||||||
|
Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[i];
|
||||||
|
assert(dsym && "null vtbl member");
|
||||||
|
|
||||||
|
FuncDeclaration* fd = dsym->isFuncDeclaration();
|
||||||
|
assert(fd && "vtbl entry not a function");
|
||||||
|
|
||||||
|
if (fd->isAbstract() && !fd->fbody)
|
||||||
|
{
|
||||||
|
c = getNullValue(DtoType(fd->type->pointerTo()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fd->codegen(Type::sir);
|
||||||
|
assert(fd->ir.irFunc && "invalid vtbl function");
|
||||||
|
c = fd->ir.irFunc->func;
|
||||||
|
}
|
||||||
|
constants.push_back(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the constant struct
|
||||||
|
constVtbl = llvm::ConstantStruct::get(constants, false);
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
#if 0
|
||||||
|
IF_LOG Logger::cout() << "constVtbl type: " << *constVtbl->getType() << std::endl;
|
||||||
|
IF_LOG Logger::cout() << "vtbl type: " << *type->irtype->isClass()->getVtbl() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
assert(constVtbl->getType() == type->irtype->isClass()->getVtbl() &&
|
||||||
|
"vtbl initializer type mismatch");
|
||||||
|
|
||||||
|
return constVtbl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLConstant * IrStruct::getClassInfoInit()
|
||||||
|
{
|
||||||
|
if (constClassInfo)
|
||||||
|
return constClassInfo;
|
||||||
|
constClassInfo = DtoDefineClassInfo(aggrdecl->isClassDeclaration());
|
||||||
|
return constClassInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void IrStruct::addBaseClassInits(
|
||||||
|
std::vector<llvm::Constant*>& constants,
|
||||||
|
ClassDeclaration* base,
|
||||||
|
size_t& offset,
|
||||||
|
size_t& field_index)
|
||||||
|
{
|
||||||
|
if (base->baseClass)
|
||||||
|
{
|
||||||
|
addBaseClassInits(constants, base->baseClass, offset, field_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayIter<VarDeclaration> it(base->fields);
|
||||||
|
for (; !it.done(); it.next())
|
||||||
|
{
|
||||||
|
VarDeclaration* vd = it.get();
|
||||||
|
|
||||||
|
// skip if offset moved backwards
|
||||||
|
if (vd->offset < offset)
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// get next aligned offset for this type
|
||||||
|
size_t alignsize = vd->type->alignsize();
|
||||||
|
size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
|
||||||
|
|
||||||
|
// insert explicit padding?
|
||||||
|
if (alignedoffset < vd->offset)
|
||||||
|
{
|
||||||
|
add_zeros(constants, vd->offset - alignedoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add default type
|
||||||
|
constants.push_back(get_default_initializer(vd, vd->init));
|
||||||
|
|
||||||
|
// advance offset to right past this field
|
||||||
|
offset = vd->offset + vd->type->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// has interface vtbls?
|
||||||
|
if (base->vtblInterfaces)
|
||||||
|
{
|
||||||
|
// false when it's not okay to use functions from super classes
|
||||||
|
bool newinsts = (base == aggrdecl->isClassDeclaration());
|
||||||
|
|
||||||
|
ArrayIter<BaseClass> it2(*base->vtblInterfaces);
|
||||||
|
for (; !it2.done(); it2.next())
|
||||||
|
{
|
||||||
|
BaseClass* b = it2.get();
|
||||||
|
constants.push_back(getInterfaceVtbl(b, newinsts));
|
||||||
|
offset += PTRSIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tail padding?
|
||||||
|
if (offset < base->structsize)
|
||||||
|
{
|
||||||
|
add_zeros(constants, base->structsize - offset);
|
||||||
|
offset = base->structsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLConstant * IrStruct::createClassDefaultInitializer()
|
||||||
|
{
|
||||||
|
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
|
||||||
|
assert(cd && "invalid class aggregate");
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Building class default initializer %s @ %s", cd->toPrettyChars(), cd->locToChars());
|
||||||
|
LOG_SCOPE;
|
||||||
|
IF_LOG Logger::println("Instance size: %u", cd->structsize);
|
||||||
|
|
||||||
|
// find the fields that contribute to the default initializer.
|
||||||
|
// these will define the default type.
|
||||||
|
|
||||||
|
std::vector<llvm::Constant*> constants;
|
||||||
|
constants.reserve(32);
|
||||||
|
|
||||||
|
// add vtbl
|
||||||
|
constants.push_back(getVtblSymbol());
|
||||||
|
// add monitor
|
||||||
|
constants.push_back(getNullValue(DtoType(Type::tvoid->pointerTo())));
|
||||||
|
|
||||||
|
// we start right after the vtbl and monitor
|
||||||
|
size_t offset = PTRSIZE * 2;
|
||||||
|
size_t field_index = 2;
|
||||||
|
|
||||||
|
// add data members recursively
|
||||||
|
addBaseClassInits(constants, cd, offset, field_index);
|
||||||
|
|
||||||
|
// build the constant
|
||||||
|
llvm::Constant* definit = llvm::ConstantStruct::get(constants, false);
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
assert(definit->getType() == type->irtype->getPA().get() && "class initializer type mismatch");
|
||||||
|
|
||||||
|
return definit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
llvm::GlobalVariable * IrStruct::getInterfaceVtbl(BaseClass * b, bool new_instance)
|
||||||
|
{
|
||||||
|
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
|
||||||
|
assert(cd && "not a class aggregate");
|
||||||
|
|
||||||
|
ClassGlobalMap::iterator it = interfaceVtblMap.find(cd);
|
||||||
|
if (it != interfaceVtblMap.end())
|
||||||
|
return it->second;
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Building vtbl for implementation of interface %s in class %s",
|
||||||
|
b->base->toPrettyChars(), aggrdecl->toPrettyChars());
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
Array vtbl_array;
|
||||||
|
b->fillVtbl(cd, &vtbl_array, new_instance);
|
||||||
|
|
||||||
|
std::vector<llvm::Constant*> constants;
|
||||||
|
constants.reserve(vtbl_array.dim);
|
||||||
|
|
||||||
|
// start with the interface info
|
||||||
|
llvm::Constant* c = getNullValue(DtoType(Type::tvoid->pointerTo()));
|
||||||
|
constants.push_back(c);
|
||||||
|
|
||||||
|
// add virtual function pointers
|
||||||
|
size_t n = vtbl_array.dim;
|
||||||
|
for (size_t i = 1; i < n; i++)
|
||||||
|
{
|
||||||
|
Dsymbol* dsym = (Dsymbol*)vtbl_array.data[i];
|
||||||
|
assert(dsym && "null vtbl member");
|
||||||
|
|
||||||
|
FuncDeclaration* fd = dsym->isFuncDeclaration();
|
||||||
|
assert(fd && "vtbl entry not a function");
|
||||||
|
|
||||||
|
assert(!(fd->isAbstract() && !fd->fbody) &&
|
||||||
|
"null symbol in interface implementation vtable");
|
||||||
|
|
||||||
|
fd->codegen(Type::sir);
|
||||||
|
assert(fd->ir.irFunc && "invalid vtbl function");
|
||||||
|
|
||||||
|
constants.push_back(fd->ir.irFunc->func);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the vtbl constant
|
||||||
|
llvm::Constant* vtbl_constant = llvm::ConstantStruct::get(constants, false);
|
||||||
|
|
||||||
|
// create the global variable to hold it
|
||||||
|
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
||||||
|
|
||||||
|
std::string mangle("_D");
|
||||||
|
mangle.append(cd->mangle());
|
||||||
|
mangle.append("11__interface");
|
||||||
|
mangle.append(b->base->mangle());
|
||||||
|
mangle.append("6__vtblZ");
|
||||||
|
|
||||||
|
llvm::GlobalVariable* GV = new llvm::GlobalVariable(
|
||||||
|
vtbl_constant->getType(),
|
||||||
|
true,
|
||||||
|
_linkage,
|
||||||
|
vtbl_constant,
|
||||||
|
mangle,
|
||||||
|
gIR->module
|
||||||
|
);
|
||||||
|
|
||||||
|
interfaceVtblMap.insert(std::make_pair(b->base, GV));
|
||||||
|
|
||||||
|
return GV;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLConstant * IrStruct::getClassInfoInterfaces()
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Building ClassInfo.interfaces");
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
ClassDeclaration* cd = aggrdecl->isClassDeclaration();
|
||||||
|
assert(cd);
|
||||||
|
|
||||||
|
if (!cd->vtblInterfaces || cd->vtblInterfaces->dim == 0)
|
||||||
|
{
|
||||||
|
VarDeclarationIter idx(ClassDeclaration::classinfo->fields, 3);
|
||||||
|
return getNullValue(DtoType(idx->type));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build array of:
|
||||||
|
//
|
||||||
|
// struct Interface
|
||||||
|
// {
|
||||||
|
// ClassInfo classinfo;
|
||||||
|
// void*[] vtbl;
|
||||||
|
// ptrdiff_t offset;
|
||||||
|
// }
|
||||||
|
|
||||||
|
LLSmallVector<LLConstant*, 6> constants;
|
||||||
|
constants.reserve(cd->vtblInterfaces->dim);
|
||||||
|
|
||||||
|
const LLType* classinfo_type = DtoType(ClassDeclaration::classinfo->type);
|
||||||
|
const LLType* voidptrptr_type = DtoType(
|
||||||
|
Type::tvoid->pointerTo()->pointerTo());
|
||||||
|
|
||||||
|
const LLType* our_type = type->irtype->isClass()->getPA().get();
|
||||||
|
|
||||||
|
ArrayIter<BaseClass> it(*cd->vtblInterfaces);
|
||||||
|
while (it.more())
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Adding interface %s", it->base->toPrettyChars());
|
||||||
|
|
||||||
|
IrStruct* irinter = it->base->ir.irStruct;
|
||||||
|
assert(irinter && "interface has null IrStruct");
|
||||||
|
IrTypeClass* itc = irinter->type->irtype->isClass();
|
||||||
|
assert(itc && "null interface IrTypeClass");
|
||||||
|
|
||||||
|
// classinfo
|
||||||
|
LLConstant* ci = irinter->getClassInfoSymbol();
|
||||||
|
ci = DtoBitCast(ci, classinfo_type);
|
||||||
|
|
||||||
|
// vtbl
|
||||||
|
ClassGlobalMap::iterator itv = interfaceVtblMap.find(it->base);
|
||||||
|
assert(itv != interfaceVtblMap.end() && "interface vtbl not found");
|
||||||
|
LLConstant* vtb = itv->second;
|
||||||
|
vtb = DtoBitCast(vtb, voidptrptr_type);
|
||||||
|
vtb = DtoConstSlice(DtoConstSize_t(itc->getVtblSize()), vtb);
|
||||||
|
|
||||||
|
// offset
|
||||||
|
LLConstant* off = DtoConstSize_t(it->offset);
|
||||||
|
|
||||||
|
// create Interface struct
|
||||||
|
LLConstant* inits[3] = { ci, vtb, off };
|
||||||
|
LLConstant* entry = llvm::ConstantStruct::get(inits, 3);
|
||||||
|
constants.push_back(entry);
|
||||||
|
|
||||||
|
// next
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
// create Interface[N]
|
||||||
|
const llvm::ArrayType* array_type = llvm::ArrayType::get(
|
||||||
|
constants[0]->getType(),
|
||||||
|
cd->vtblInterfaces->dim);
|
||||||
|
|
||||||
|
LLConstant* arr = llvm::ConstantArray::get(
|
||||||
|
array_type,
|
||||||
|
&constants[0],
|
||||||
|
constants.size());
|
||||||
|
|
||||||
|
// apply the initializer
|
||||||
|
classInterfacesArray->setInitializer(arr);
|
||||||
|
|
||||||
|
LLConstant* idxs[2] = {
|
||||||
|
DtoConstSize_t(0),
|
||||||
|
DtoConstSize_t(0)
|
||||||
|
};
|
||||||
|
|
||||||
|
// return as a slice
|
||||||
|
return DtoConstSlice(
|
||||||
|
DtoConstSize_t(cd->vtblInterfaces->dim),
|
||||||
|
llvm::ConstantExpr::getGetElementPtr(classInterfacesArray, idxs, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -128,7 +128,7 @@ void IRLandingPad::constructLandingPad(llvm::BasicBlock* inBB)
|
|||||||
}
|
}
|
||||||
assert(it->catchType);
|
assert(it->catchType);
|
||||||
assert(it->catchType->ir.irStruct);
|
assert(it->catchType->ir.irStruct);
|
||||||
selectorargs.insert(selectorargs.begin(), it->catchType->ir.irStruct->classInfo);
|
selectorargs.insert(selectorargs.begin(), it->catchType->ir.irStruct->getClassInfoSymbol());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if there's a finally, the eh table has to have a 0 action
|
// if there's a finally, the eh table has to have a 0 action
|
||||||
|
|||||||
523
ir/irstruct.cpp
523
ir/irstruct.cpp
@@ -5,353 +5,330 @@
|
|||||||
#include "declaration.h"
|
#include "declaration.h"
|
||||||
#include "init.h"
|
#include "init.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"
|
#include "gen/logger.h"
|
||||||
#include "gen/llvmhelpers.h"
|
#include "gen/llvmhelpers.h"
|
||||||
|
#include "gen/utils.h"
|
||||||
|
|
||||||
IrInterface::IrInterface(BaseClass* b)
|
#include "ir/irstruct.h"
|
||||||
: vtblInitTy(llvm::OpaqueType::get())
|
#include "ir/irtypeclass.h"
|
||||||
{
|
|
||||||
base = b;
|
|
||||||
decl = b->base;
|
|
||||||
vtblInit = NULL;
|
|
||||||
vtbl = NULL;
|
|
||||||
infoTy = NULL;
|
|
||||||
infoInit = NULL;
|
|
||||||
info = NULL;
|
|
||||||
|
|
||||||
index = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IrStruct::IrStruct(AggregateDeclaration* aggr)
|
IrStruct::IrStruct(AggregateDeclaration* aggr)
|
||||||
: initOpaque(llvm::OpaqueType::get()),
|
: diCompositeType(NULL)
|
||||||
classInfoOpaque(llvm::OpaqueType::get()),
|
|
||||||
vtblTy(llvm::OpaqueType::get()),
|
|
||||||
vtblInitTy(llvm::OpaqueType::get()),
|
|
||||||
diCompositeType(NULL)
|
|
||||||
{
|
{
|
||||||
aggrdecl = aggr;
|
aggrdecl = aggr;
|
||||||
defaultFound = false;
|
|
||||||
anon = NULL;
|
|
||||||
index = 0;
|
|
||||||
|
|
||||||
type = aggr->type;
|
type = aggr->type;
|
||||||
defined = false;
|
|
||||||
constinited = false;
|
|
||||||
|
|
||||||
interfaceInfos = NULL;
|
packed = false;
|
||||||
vtbl = NULL;
|
|
||||||
constVtbl = NULL;
|
// above still need to be looked at
|
||||||
|
|
||||||
init = NULL;
|
init = NULL;
|
||||||
constInit = NULL;
|
constInit = NULL;
|
||||||
|
|
||||||
|
vtbl = NULL;
|
||||||
|
constVtbl = NULL;
|
||||||
classInfo = NULL;
|
classInfo = NULL;
|
||||||
constClassInfo = NULL;
|
constClassInfo = NULL;
|
||||||
classInfoDeclared = false;
|
|
||||||
classInfoDefined = false;
|
|
||||||
|
|
||||||
packed = false;
|
classInterfacesArray = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
IrStruct::~IrStruct()
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
LLGlobalVariable * IrStruct::getInitSymbol()
|
||||||
{
|
{
|
||||||
|
if (init)
|
||||||
|
return init;
|
||||||
|
|
||||||
|
// create the initZ symbol
|
||||||
|
std::string initname("_D");
|
||||||
|
initname.append(aggrdecl->mangle());
|
||||||
|
initname.append("6__initZ");
|
||||||
|
|
||||||
|
llvm::GlobalValue::LinkageTypes _linkage = DtoExternalLinkage(aggrdecl);
|
||||||
|
|
||||||
|
init = new llvm::GlobalVariable(
|
||||||
|
type->irtype->getPA().get(), true, _linkage, NULL, initname, gIR->module);
|
||||||
|
|
||||||
|
return init;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void IrStruct::pushAnon(bool isunion)
|
llvm::Constant * IrStruct::getDefaultInit()
|
||||||
{
|
{
|
||||||
anon = new Anon(isunion, anon);
|
if (constInit)
|
||||||
}
|
return constInit;
|
||||||
|
|
||||||
//////////////////////////////////////////
|
if (type->ty == Tstruct)
|
||||||
|
|
||||||
void IrStruct::popAnon()
|
|
||||||
{
|
|
||||||
assert(anon);
|
|
||||||
|
|
||||||
const LLType* BT;
|
|
||||||
|
|
||||||
// get the anon type
|
|
||||||
if (anon->isunion)
|
|
||||||
{
|
{
|
||||||
// get biggest type in block
|
constInit = createStructDefaultInitializer();
|
||||||
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
|
else
|
||||||
{
|
{
|
||||||
// build a struct from the types
|
constInit = createClassDefaultInitializer();
|
||||||
BT = LLStructType::get(anon->types, aggrdecl->ir.irStruct->packed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// pop anon
|
return constInit;
|
||||||
Anon* tmp = anon;
|
}
|
||||||
anon = anon->parent;
|
|
||||||
delete tmp;
|
|
||||||
|
|
||||||
// is there a parent anon?
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
if (anon)
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// helper function that returns the static default initializer of a variable
|
||||||
|
LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init)
|
||||||
|
{
|
||||||
|
if (init)
|
||||||
{
|
{
|
||||||
// make sure type gets pushed in the anon, not the main
|
return DtoConstInitializer(init->loc, vd->type, init);
|
||||||
anon->types.push_back(BT);
|
}
|
||||||
// index is only manipulated at the top level, anons use raw offsets
|
else if (vd->init)
|
||||||
|
{
|
||||||
|
return DtoConstInitializer(vd->init->loc, vd->type, vd->init);
|
||||||
}
|
}
|
||||||
// no parent anon, finally add to aggrdecl
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
types.push_back(BT);
|
return DtoConstExpInit(vd->loc, vd->type, vd->type->defaultInit(vd->loc));
|
||||||
// only advance to next position if main is not a union
|
}
|
||||||
if (!aggrdecl->isUnionDeclaration())
|
}
|
||||||
|
|
||||||
|
// helper function that adds zero bytes to a vector of constants
|
||||||
|
size_t add_zeros(std::vector<llvm::Constant*>& constants, size_t diff)
|
||||||
|
{
|
||||||
|
size_t n = constants.size();
|
||||||
|
while (diff)
|
||||||
|
{
|
||||||
|
if (global.params.is64bit && diff % 8 == 0)
|
||||||
{
|
{
|
||||||
index++;
|
constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int64Ty));
|
||||||
|
diff -= 8;
|
||||||
|
}
|
||||||
|
else if (diff % 4 == 0)
|
||||||
|
{
|
||||||
|
constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int32Ty));
|
||||||
|
diff -= 4;
|
||||||
|
}
|
||||||
|
else if (diff % 2 == 0)
|
||||||
|
{
|
||||||
|
constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int16Ty));
|
||||||
|
diff -= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
constants.push_back(llvm::Constant::getNullValue(llvm::Type::Int8Ty));
|
||||||
|
diff -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return constants.size() - n;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////
|
// Matches the way the type is built in IrTypeStruct
|
||||||
|
// maybe look at unifying the interface.
|
||||||
|
|
||||||
void IrStruct::addVar(VarDeclaration * var)
|
LLConstant * IrStruct::createStructDefaultInitializer()
|
||||||
{
|
{
|
||||||
TypeVector* tvec = &types;
|
IF_LOG Logger::println("Building default initializer for %s", aggrdecl->toPrettyChars());
|
||||||
if (anon)
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
assert(type->ty == Tstruct && "cannot build struct default initializer for non struct type");
|
||||||
|
|
||||||
|
// start at offset zero
|
||||||
|
size_t offset = 0;
|
||||||
|
|
||||||
|
// vector of constants
|
||||||
|
std::vector<llvm::Constant*> constants;
|
||||||
|
|
||||||
|
// go through fields
|
||||||
|
ArrayIter<VarDeclaration> it(aggrdecl->fields);
|
||||||
|
for (; !it.done(); it.next())
|
||||||
{
|
{
|
||||||
// make sure type gets pushed in the anon, not the main
|
VarDeclaration* vd = it.get();
|
||||||
tvec = &anon->types;
|
|
||||||
|
|
||||||
// set but don't advance index
|
if (vd->offset < offset)
|
||||||
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];
|
IF_LOG Logger::println("skipping field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
IF_LOG Logger::println("using field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
|
||||||
// only add vars that don't overlap
|
// get next aligned offset for this field
|
||||||
size_t offset = var->offset;
|
size_t alignedoffset = offset;
|
||||||
size_t size = var->type->size();
|
if (!packed)
|
||||||
if (offset >= lastoffset+lastsize)
|
{
|
||||||
|
size_t alignsize = vd->type->alignsize();
|
||||||
|
alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert explicit padding?
|
||||||
|
if (alignedoffset < vd->offset)
|
||||||
|
{
|
||||||
|
add_zeros(constants, vd->offset - alignedoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add initializer
|
||||||
|
constants.push_back(get_default_initializer(vd, NULL));
|
||||||
|
|
||||||
|
// advance offset to right past this field
|
||||||
|
offset = vd->offset + vd->type->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// tail padding?
|
||||||
|
if (offset < aggrdecl->structsize)
|
||||||
|
{
|
||||||
|
add_zeros(constants, aggrdecl->structsize - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build constant struct
|
||||||
|
llvm::Constant* definit = llvm::ConstantStruct::get(constants, packed);
|
||||||
|
IF_LOG Logger::cout() << "final default initializer: " << *definit << std::endl;
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
assert(definit->getType() == type->irtype->get() &&
|
||||||
|
"default initializer type does not match the default struct type");
|
||||||
|
|
||||||
|
return definit;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// yet another rewrite of the notorious StructInitializer.
|
||||||
|
|
||||||
|
// this time a bit more inspired by the DMD code.
|
||||||
|
|
||||||
|
LLConstant * IrStruct::createStructInitializer(StructInitializer * si)
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Building StructInitializer of type %s", si->ad->toPrettyChars());
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// sanity check
|
||||||
|
assert(si->ad == aggrdecl && "struct type mismatch");
|
||||||
|
assert(si->vars.dim == si->value.dim && "inconsistent StructInitializer");
|
||||||
|
|
||||||
|
// array of things to build
|
||||||
|
typedef std::pair<VarDeclaration*, llvm::Constant*> VCPair;
|
||||||
|
llvm::SmallVector<VCPair, 16> data(aggrdecl->fields.dim);
|
||||||
|
|
||||||
|
// start by creating a map from initializer indices to field indices.
|
||||||
|
// I have no fucking clue why dmd represents it like this :/
|
||||||
|
size_t n = si->vars.dim;
|
||||||
|
LLSmallVector<int, 16> datamap(n, 0);
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; 1; j++)
|
||||||
|
{
|
||||||
|
assert(j < aggrdecl->fields.dim);
|
||||||
|
if (aggrdecl->fields.data[j] == si->vars.data[i])
|
||||||
{
|
{
|
||||||
Logger::println(" added");
|
datamap[i] = j;
|
||||||
lastoffset = offset;
|
break;
|
||||||
lastsize = size;
|
|
||||||
defVars.push_back(var);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fill in explicit initializers
|
||||||
|
n = si->vars.dim;
|
||||||
|
for (size_t i = 0; i < n; i++)
|
||||||
{
|
{
|
||||||
Logger::println("Build the default initializer");
|
VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
|
||||||
LOG_SCOPE;
|
Initializer* ini = (Initializer*)si->value.data[i];
|
||||||
|
|
||||||
lastoffset = 0;
|
size_t idx = datamap[i];
|
||||||
lastsize = 0;
|
|
||||||
|
|
||||||
// go through the default vars and build the default constant initializer
|
if (data[idx].first != NULL)
|
||||||
// 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];
|
Loc l = ini ? ini->loc : si->loc;
|
||||||
|
error(l, "duplicate initialization of %s", vd->toChars());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
data[idx].first = vd;
|
||||||
|
data[idx].second = get_default_initializer(vd, ini);
|
||||||
|
}
|
||||||
|
|
||||||
// get offset and size
|
// build array of constants and try to fill in default initializers
|
||||||
size_t offset = var->offset;
|
// where there is room.
|
||||||
size_t size = var->type->size();
|
size_t offset = 0;
|
||||||
|
std::vector<llvm::Constant*> constants;
|
||||||
|
constants.reserve(16);
|
||||||
|
|
||||||
// is there space in between last last offset and this one?
|
n = data.size();
|
||||||
// if so, fill it with zeros
|
for (size_t i = 0; i < n; i++)
|
||||||
if (offset > lastoffset+lastsize)
|
{
|
||||||
|
VarDeclaration* vd = data[i].first;
|
||||||
|
|
||||||
|
// explicitly initialized?
|
||||||
|
if (vd != NULL)
|
||||||
|
{
|
||||||
|
// get next aligned offset for this field
|
||||||
|
size_t alignedoffset = offset;
|
||||||
|
if (!packed)
|
||||||
{
|
{
|
||||||
size_t pos = lastoffset + lastsize;
|
size_t alignsize = vd->type->alignsize();
|
||||||
addZeros(inits, pos, offset);
|
alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the field
|
// insert explicit padding?
|
||||||
// lazily default initialize
|
if (alignedoffset < vd->offset)
|
||||||
if (!var->ir.irField->constInit)
|
{
|
||||||
var->ir.irField->constInit = DtoConstInitializer(var->loc, var->type, var->init);
|
add_zeros(constants, vd->offset - alignedoffset);
|
||||||
inits.push_back(var->ir.irField->constInit);
|
}
|
||||||
|
|
||||||
lastoffset = offset;
|
IF_LOG Logger::println("using field: %s", vd->toChars());
|
||||||
lastsize = var->type->size();
|
constants.push_back(data[i].second);
|
||||||
|
offset = vd->offset + vd->type->size();
|
||||||
}
|
}
|
||||||
|
// not explicit! try and fit in the default initialization instead
|
||||||
// there might still be padding after the last one, make sure that is zeroed as well
|
// make sure we don't overlap with any following explicity initialized fields
|
||||||
// is there space in between last last offset and this one?
|
else
|
||||||
size_t structsize = getTypePaddedSize(structtype);
|
|
||||||
|
|
||||||
if (structsize > lastoffset+lastsize)
|
|
||||||
{
|
{
|
||||||
size_t pos = lastoffset + lastsize;
|
vd = (VarDeclaration*)aggrdecl->fields.data[i];
|
||||||
addZeros(inits, pos, structsize);
|
|
||||||
|
// check all the way that we don't overlap, slow but it works!
|
||||||
|
for (size_t j = i+1; j <= n; j++)
|
||||||
|
{
|
||||||
|
if (j == n) // no overlap
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("using field default: %s", vd->toChars());
|
||||||
|
constants.push_back(get_default_initializer(vd, NULL));
|
||||||
|
offset = vd->offset + vd->type->size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
VarDeclaration* vd2 = (VarDeclaration*)aggrdecl->fields.data[j];
|
||||||
|
|
||||||
|
size_t o2 = vd->offset + vd->type->size();
|
||||||
|
|
||||||
|
if (vd2->offset < o2 && data[i].first)
|
||||||
|
break; // overlaps
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
LLConstant* IrStruct::buildDefaultConstInit()
|
// tail padding?
|
||||||
{
|
if (offset < aggrdecl->structsize)
|
||||||
// doesn't work for classes, they add stuff before and maybe after data fields
|
{
|
||||||
assert(!aggrdecl->isClassDeclaration());
|
add_zeros(constants, aggrdecl->structsize - offset);
|
||||||
|
}
|
||||||
|
|
||||||
// initializer llvm constant list
|
// stop if there were errors
|
||||||
std::vector<LLConstant*> inits;
|
if (global.errors)
|
||||||
|
{
|
||||||
|
fatal();
|
||||||
|
}
|
||||||
|
|
||||||
// just start with an empty list
|
// build constant
|
||||||
buildDefaultConstInit(inits);
|
assert(!constants.empty());
|
||||||
|
llvm::Constant* c = llvm::ConstantStruct::get(&constants[0], constants.size(), packed);
|
||||||
// build the constant
|
IF_LOG Logger::cout() << "final struct initializer: " << *c << std::endl;
|
||||||
// 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;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
236
ir/irstruct.h
236
ir/irstruct.h
@@ -6,178 +6,110 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
struct IrInterface;
|
// DMD forward declarations
|
||||||
|
struct StructInitializer;
|
||||||
|
|
||||||
void addZeros(std::vector<const llvm::Type*>& inits, size_t pos, size_t offset);
|
|
||||||
void addZeros(std::vector<llvm::Constant*>& inits, size_t pos, size_t offset);
|
|
||||||
void addZeros(std::vector<llvm::Value*>& inits, size_t pos, size_t offset);
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// represents a struct or class
|
// represents a struct or class
|
||||||
// it is used during codegen to hold all the vital info we need
|
// it is used during codegen to hold all the vital info we need
|
||||||
struct IrStruct : IrBase
|
struct IrStruct : IrBase
|
||||||
{
|
{
|
||||||
/////////////////////////////////////////////////////////////////////
|
/// Constructor.
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
typedef std::vector<VarDeclaration*> VarDeclVector;
|
|
||||||
|
|
||||||
typedef std::map<ClassDeclaration*, IrInterface*> InterfaceMap;
|
|
||||||
typedef InterfaceMap::iterator InterfaceMapIter;
|
|
||||||
|
|
||||||
typedef std::vector<IrInterface*> InterfaceVector;
|
|
||||||
typedef InterfaceVector::iterator InterfaceVectorIter;
|
|
||||||
|
|
||||||
// vector of LLVM types
|
|
||||||
typedef std::vector<const llvm::Type*> TypeVector;
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// Anon represents an anonymous struct union block inside an aggregate
|
|
||||||
// during LLVM type construction.
|
|
||||||
struct Anon
|
|
||||||
{
|
|
||||||
bool isunion;
|
|
||||||
Anon* parent;
|
|
||||||
|
|
||||||
TypeVector types;
|
|
||||||
|
|
||||||
Anon(bool IsUnion, Anon* par) : isunion(IsUnion), parent(par) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/// ctor
|
|
||||||
IrStruct(AggregateDeclaration* agg);
|
IrStruct(AggregateDeclaration* agg);
|
||||||
|
|
||||||
/// dtor
|
//////////////////////////////////////////////////////////////////////////
|
||||||
virtual ~IrStruct();
|
// public fields,
|
||||||
|
// FIXME this is basically stuff I just haven't gotten around to yet.
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/// The D aggregate.
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
/// 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;
|
AggregateDeclaration* aggrdecl;
|
||||||
|
|
||||||
// vector of VarDeclarations in this aggregate
|
/// Aggregate D type.
|
||||||
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;
|
||||||
|
|
||||||
// class vtable type
|
/// true only for: align(1) struct S { ... }
|
||||||
llvm::PATypeHolder vtblTy;
|
|
||||||
llvm::PATypeHolder vtblInitTy;
|
|
||||||
|
|
||||||
// initializer type opaque (type of global matches initializer, not formal type)
|
|
||||||
llvm::PATypeHolder initOpaque;
|
|
||||||
llvm::PATypeHolder classInfoOpaque;
|
|
||||||
|
|
||||||
// map/vector of interfaces implemented
|
|
||||||
InterfaceMap interfaceMap;
|
|
||||||
InterfaceVector interfaceVec;
|
|
||||||
|
|
||||||
// interface info array global
|
|
||||||
LLGlobalVariable* interfaceInfos;
|
|
||||||
|
|
||||||
// ...
|
|
||||||
bool defined;
|
|
||||||
bool constinited;
|
|
||||||
|
|
||||||
// vtbl global and initializer
|
|
||||||
LLGlobalVariable* vtbl;
|
|
||||||
LLConstant* constVtbl;
|
|
||||||
|
|
||||||
// static initializers global and constant
|
|
||||||
LLGlobalVariable* init;
|
|
||||||
LLConstant* constInit;
|
|
||||||
|
|
||||||
// classinfo global and initializer constant
|
|
||||||
LLGlobalVariable* classInfo;
|
|
||||||
LLConstant* constClassInfo;
|
|
||||||
bool classInfoDeclared;
|
|
||||||
bool classInfoDefined;
|
|
||||||
// vector of interfaces that should be put in ClassInfo.interfaces
|
|
||||||
InterfaceVector classInfoInterfaces;
|
|
||||||
|
|
||||||
// align(1) struct S { ... }
|
|
||||||
bool packed;
|
bool packed;
|
||||||
|
|
||||||
// composite type debug description
|
/// Composite type debug description.
|
||||||
llvm::DICompositeType diCompositeType;
|
llvm::DICompositeType diCompositeType;
|
||||||
|
|
||||||
std::vector<VarDeclaration*> staticVars;
|
//////////////////////////////////////////////////////////////////////////
|
||||||
std::vector<FuncDeclaration*> structFuncs;
|
|
||||||
|
/// Create the __initZ symbol lazily.
|
||||||
|
LLGlobalVariable* getInitSymbol();
|
||||||
|
/// Builds the __initZ initializer constant lazily.
|
||||||
|
LLConstant* getDefaultInit();
|
||||||
|
|
||||||
|
/// Create the __vtblZ symbol lazily.
|
||||||
|
LLGlobalVariable* getVtblSymbol();
|
||||||
|
/// Builds the __vtblZ initializer constant lazily.
|
||||||
|
LLConstant* getVtblInit();
|
||||||
|
|
||||||
|
/// Create the __ClassZ symbol lazily.
|
||||||
|
LLGlobalVariable* getClassInfoSymbol();
|
||||||
|
/// Builds the __ClassZ initializer constant lazily.
|
||||||
|
LLConstant* getClassInfoInit();
|
||||||
|
|
||||||
|
/// Create the __interfaceInfos symbol lazily.
|
||||||
|
LLGlobalVariable* getInterfaceArraySymbol();
|
||||||
|
|
||||||
|
/// Creates a StructInitializer constant.
|
||||||
|
LLConstant* createStructInitializer(StructInitializer* si);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
protected:
|
||||||
|
/// Static default initializer global.
|
||||||
|
llvm::GlobalVariable* init;
|
||||||
|
/// Static default initializer constant.
|
||||||
|
LLConstant* constInit;
|
||||||
|
|
||||||
|
/// Vtbl global.
|
||||||
|
llvm::GlobalVariable* vtbl;
|
||||||
|
/// Vtbl initializer constant.
|
||||||
|
LLConstant* constVtbl;
|
||||||
|
|
||||||
|
/// ClassInfo global.
|
||||||
|
llvm::GlobalVariable* classInfo;
|
||||||
|
/// ClassInfo initializer constant.
|
||||||
|
LLConstant* constClassInfo;
|
||||||
|
|
||||||
|
/// Map for mapping ClassDeclaration* to LLVM GlobalVariable.
|
||||||
|
typedef std::map<ClassDeclaration*, llvm::GlobalVariable*> ClassGlobalMap;
|
||||||
|
|
||||||
|
/// Map from of interface vtbls implemented by this class.
|
||||||
|
ClassGlobalMap interfaceVtblMap;
|
||||||
|
|
||||||
|
/// Interface info array global.
|
||||||
|
/// Basically: static object.Interface[num_interfaces]
|
||||||
|
llvm::GlobalVariable* classInterfacesArray;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/// Create static default initializer for struct.
|
||||||
|
LLConstant* createStructDefaultInitializer();
|
||||||
|
|
||||||
|
/// Create static default initializer for class.
|
||||||
|
LLConstant* createClassDefaultInitializer();
|
||||||
|
|
||||||
|
/// Returns vtbl for interface implementation, creates it if not already built.
|
||||||
|
llvm::GlobalVariable* getInterfaceVtbl(BaseClass* b, bool new_inst);
|
||||||
|
|
||||||
|
/// Add base class data to initializer list.
|
||||||
|
/// Also creates the IrField instance for each data field.
|
||||||
|
void addBaseClassInits(
|
||||||
|
std::vector<llvm::Constant*>& constants,
|
||||||
|
ClassDeclaration* base,
|
||||||
|
size_t& offset,
|
||||||
|
size_t& field_index);
|
||||||
|
|
||||||
|
// FIXME make this a member instead
|
||||||
|
friend LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
|
||||||
|
|
||||||
|
/// Create the Interface[] interfaces ClassInfo field initializer.
|
||||||
|
LLConstant* getClassInfoInterfaces();
|
||||||
};
|
};
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// represents interface implemented by a class
|
|
||||||
struct IrInterface : IrBase
|
|
||||||
{
|
|
||||||
BaseClass* base;
|
|
||||||
ClassDeclaration* decl;
|
|
||||||
|
|
||||||
llvm::PATypeHolder vtblInitTy;
|
|
||||||
|
|
||||||
LLConstant* vtblInit;
|
|
||||||
LLGlobalVariable* vtbl;
|
|
||||||
Array vtblDecls; // array of FuncDecls that make up the vtbl
|
|
||||||
|
|
||||||
const LLStructType* infoTy;
|
|
||||||
LLConstant* infoInit;
|
|
||||||
LLConstant* info;
|
|
||||||
|
|
||||||
size_t index;
|
|
||||||
|
|
||||||
IrInterface(BaseClass* b);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
#include "llvm/DerivedTypes.h"
|
#include "llvm/DerivedTypes.h"
|
||||||
#include "ir/irtype.h"
|
|
||||||
|
|
||||||
#include "mars.h"
|
#include "mars.h"
|
||||||
#include "mtype.h"
|
#include "mtype.h"
|
||||||
|
#include "gen/irstate.h"
|
||||||
|
#include "gen/logger.h"
|
||||||
|
#include "ir/irtype.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern const llvm::Type* DtoType(Type* dt);
|
||||||
|
extern const llvm::Type* DtoSize_t();
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IrType::IrType(Type* dt, const llvm::Type* lt)
|
IrType::IrType(Type* dt, const llvm::Type* lt)
|
||||||
: dtype(dt),
|
: dtype(dt),
|
||||||
@@ -10,6 +18,8 @@ IrType::IrType(Type* dt, const llvm::Type* lt)
|
|||||||
{
|
{
|
||||||
assert(dt && "null D Type");
|
assert(dt && "null D Type");
|
||||||
assert(lt && "null LLVM Type");
|
assert(lt && "null LLVM Type");
|
||||||
|
assert(dt->ir.type == NULL && "llvm type (old one) already set");
|
||||||
|
dt->ir.type = &pa;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -23,6 +33,13 @@ IrTypeBasic::IrTypeBasic(Type * dt)
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const llvm::Type * IrTypeBasic::buildType()
|
||||||
|
{
|
||||||
|
return pa.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const llvm::Type * IrTypeBasic::basic2llvm(Type* t)
|
const llvm::Type * IrTypeBasic::basic2llvm(Type* t)
|
||||||
{
|
{
|
||||||
const llvm::Type* t2;
|
const llvm::Type* t2;
|
||||||
@@ -101,19 +118,26 @@ const llvm::Type * IrTypeBasic::basic2llvm(Type* t)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IrTypePointer::IrTypePointer(Type * dt)
|
IrTypePointer::IrTypePointer(Type * dt)
|
||||||
: IrType(dt, pointer2llvm(dt))
|
: IrType(dt, llvm::OpaqueType::get())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
extern const llvm::Type* DtoType(Type* dt);
|
const llvm::Type * IrTypePointer::buildType()
|
||||||
|
|
||||||
const llvm::Type * IrTypePointer::pointer2llvm(Type * t)
|
|
||||||
{
|
{
|
||||||
assert(t->ty == Tpointer && "not pointer type");
|
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(
|
||||||
|
pointer2llvm(dtype));
|
||||||
|
return pa.get();
|
||||||
|
}
|
||||||
|
|
||||||
const llvm::Type* elemType = DtoType(t->nextOf());
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const llvm::Type * IrTypePointer::pointer2llvm(Type * dt)
|
||||||
|
{
|
||||||
|
assert(dt->ty == Tpointer && "not pointer type");
|
||||||
|
|
||||||
|
const llvm::Type* elemType = DtoType(dt->nextOf());
|
||||||
if (elemType == llvm::Type::VoidTy)
|
if (elemType == llvm::Type::VoidTy)
|
||||||
elemType = llvm::Type::Int8Ty;
|
elemType = llvm::Type::Int8Ty;
|
||||||
return llvm::PointerType::get(elemType, 0);
|
return llvm::PointerType::get(elemType, 0);
|
||||||
@@ -124,21 +148,26 @@ const llvm::Type * IrTypePointer::pointer2llvm(Type * t)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IrTypeSArray::IrTypeSArray(Type * dt)
|
IrTypeSArray::IrTypeSArray(Type * dt)
|
||||||
: IrType(dt, sarray2llvm(dt))
|
: IrType(dt, llvm::OpaqueType::get())
|
||||||
{
|
{
|
||||||
|
assert(dt->ty == Tsarray && "not static array type");
|
||||||
TypeSArray* tsa = (TypeSArray*)dt;
|
TypeSArray* tsa = (TypeSArray*)dt;
|
||||||
uint64_t d = (uint64_t)tsa->dim->toUInteger();
|
dim = (uint64_t)tsa->dim->toUInteger();
|
||||||
assert(d == dim);
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const llvm::Type * IrTypeSArray::buildType()
|
||||||
|
{
|
||||||
|
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(
|
||||||
|
sarray2llvm(dtype));
|
||||||
|
return pa.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
|
const llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
|
||||||
{
|
{
|
||||||
assert(t->ty == Tsarray && "not static array type");
|
|
||||||
|
|
||||||
TypeSArray* tsa = (TypeSArray*)t;
|
|
||||||
dim = (uint64_t)tsa->dim->toUInteger();
|
|
||||||
const llvm::Type* elemType = DtoType(t->nextOf());
|
const llvm::Type* elemType = DtoType(t->nextOf());
|
||||||
if (elemType == llvm::Type::VoidTy)
|
if (elemType == llvm::Type::VoidTy)
|
||||||
elemType = llvm::Type::Int8Ty;
|
elemType = llvm::Type::Int8Ty;
|
||||||
@@ -150,23 +179,38 @@ const llvm::Type * IrTypeSArray::sarray2llvm(Type * t)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IrTypeArray::IrTypeArray(Type * dt)
|
IrTypeArray::IrTypeArray(Type * dt)
|
||||||
: IrType(dt, array2llvm(dt))
|
: IrType(dt, llvm::OpaqueType::get())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
extern const llvm::Type* DtoSize_t();
|
const llvm::Type * IrTypeArray::buildType()
|
||||||
|
{
|
||||||
|
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(
|
||||||
|
array2llvm(dtype));
|
||||||
|
return pa.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
const llvm::Type * IrTypeArray::array2llvm(Type * t)
|
const llvm::Type * IrTypeArray::array2llvm(Type * t)
|
||||||
{
|
{
|
||||||
assert(t->ty == Tarray && "not dynamic array type");
|
assert(t->ty == Tarray && "not dynamic array type");
|
||||||
|
|
||||||
|
// get .ptr type
|
||||||
const llvm::Type* elemType = DtoType(t->nextOf());
|
const llvm::Type* elemType = DtoType(t->nextOf());
|
||||||
if (elemType == llvm::Type::VoidTy)
|
if (elemType == llvm::Type::VoidTy)
|
||||||
elemType = llvm::Type::Int8Ty;
|
elemType = llvm::Type::Int8Ty;
|
||||||
elemType = llvm::PointerType::get(elemType, 0);
|
elemType = llvm::PointerType::get(elemType, 0);
|
||||||
return llvm::StructType::get(DtoSize_t(), elemType, NULL);
|
|
||||||
|
// create struct type
|
||||||
|
const llvm::Type* at = llvm::StructType::get(DtoSize_t(), elemType, NULL);
|
||||||
|
|
||||||
|
// name dynamic array types
|
||||||
|
Type::sir->getState()->module->addTypeName(t->toChars(), at);
|
||||||
|
|
||||||
|
return at;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
35
ir/irtype.h
35
ir/irtype.h
@@ -9,10 +9,13 @@
|
|||||||
|
|
||||||
struct Type;
|
struct Type;
|
||||||
|
|
||||||
|
class IrTypeAggr;
|
||||||
class IrTypeArray;
|
class IrTypeArray;
|
||||||
class IrTypeBasic;
|
class IrTypeBasic;
|
||||||
|
class IrTypeClass;
|
||||||
class IrTypePointer;
|
class IrTypePointer;
|
||||||
class IrTypeSArray;
|
class IrTypeSArray;
|
||||||
|
class IrTypeStruct;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@@ -24,19 +27,29 @@ public:
|
|||||||
IrType(Type* dt, const llvm::Type* lt);
|
IrType(Type* dt, const llvm::Type* lt);
|
||||||
|
|
||||||
///
|
///
|
||||||
Type* getD() { return dtype; }
|
virtual IrTypeAggr* isAggr() { return NULL; }
|
||||||
|
|
||||||
///
|
|
||||||
const llvm::Type* get() { return pa.get(); }
|
|
||||||
|
|
||||||
///
|
///
|
||||||
virtual IrTypeArray* isArray() { return NULL; }
|
virtual IrTypeArray* isArray() { return NULL; }
|
||||||
///
|
///
|
||||||
virtual IrTypeBasic* isBasic() { return NULL; }
|
virtual IrTypeBasic* isBasic() { return NULL; }
|
||||||
///
|
///
|
||||||
|
virtual IrTypeClass* isClass() { return NULL; }
|
||||||
|
///
|
||||||
virtual IrTypePointer* isPointer() { return NULL; }
|
virtual IrTypePointer* isPointer() { return NULL; }
|
||||||
///
|
///
|
||||||
virtual IrTypeSArray* isSArray() { return NULL; }
|
virtual IrTypeSArray* isSArray() { return NULL; }
|
||||||
|
///
|
||||||
|
virtual IrTypeStruct* isStruct() { return NULL; }
|
||||||
|
|
||||||
|
///
|
||||||
|
Type* getD() { return dtype; }
|
||||||
|
///
|
||||||
|
virtual const llvm::Type* get() { return pa.get(); }
|
||||||
|
///
|
||||||
|
llvm::PATypeHolder& getPA() { return pa; }
|
||||||
|
|
||||||
|
///
|
||||||
|
virtual const llvm::Type* buildType() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///
|
///
|
||||||
@@ -58,6 +71,9 @@ public:
|
|||||||
///
|
///
|
||||||
IrTypeBasic* isBasic() { return this; }
|
IrTypeBasic* isBasic() { return this; }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///
|
///
|
||||||
const llvm::Type* basic2llvm(Type* t);
|
const llvm::Type* basic2llvm(Type* t);
|
||||||
@@ -75,6 +91,9 @@ public:
|
|||||||
///
|
///
|
||||||
IrTypePointer* isPointer() { return this; }
|
IrTypePointer* isPointer() { return this; }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///
|
///
|
||||||
const llvm::Type* pointer2llvm(Type* t);
|
const llvm::Type* pointer2llvm(Type* t);
|
||||||
@@ -92,6 +111,9 @@ public:
|
|||||||
///
|
///
|
||||||
IrTypeSArray* isSArray() { return this; }
|
IrTypeSArray* isSArray() { return this; }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///
|
///
|
||||||
const llvm::Type* sarray2llvm(Type* t);
|
const llvm::Type* sarray2llvm(Type* t);
|
||||||
@@ -112,6 +134,9 @@ public:
|
|||||||
///
|
///
|
||||||
IrTypeArray* isArray() { return this; }
|
IrTypeArray* isArray() { return this; }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildType();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
///
|
///
|
||||||
const llvm::Type* array2llvm(Type* t);
|
const llvm::Type* array2llvm(Type* t);
|
||||||
|
|||||||
236
ir/irtypeclass.cpp
Normal file
236
ir/irtypeclass.cpp
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
#include "llvm/DerivedTypes.h"
|
||||||
|
|
||||||
|
#include "aggregate.h"
|
||||||
|
#include "declaration.h"
|
||||||
|
#include "dsymbol.h"
|
||||||
|
#include "mtype.h"
|
||||||
|
|
||||||
|
#include "gen/irstate.h"
|
||||||
|
#include "gen/logger.h"
|
||||||
|
#include "gen/tollvm.h"
|
||||||
|
#include "gen/utils.h"
|
||||||
|
#include "ir/irtypeclass.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
extern size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IrTypeClass::IrTypeClass(ClassDeclaration* cd)
|
||||||
|
: IrTypeAggr(cd),
|
||||||
|
cd(cd),
|
||||||
|
tc((TypeClass*)cd->type),
|
||||||
|
vtbl_pa(llvm::OpaqueType::get())
|
||||||
|
{
|
||||||
|
vtbl_size = cd->vtbl.dim;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void IrTypeClass::addBaseClassData(
|
||||||
|
std::vector< const llvm::Type * > & defaultTypes,
|
||||||
|
ClassDeclaration * base,
|
||||||
|
size_t & offset,
|
||||||
|
size_t & field_index)
|
||||||
|
{
|
||||||
|
if (base->baseClass)
|
||||||
|
{
|
||||||
|
addBaseClassData(defaultTypes, base->baseClass, offset, field_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayIter<VarDeclaration> it(base->fields);
|
||||||
|
for (; !it.done(); it.next())
|
||||||
|
{
|
||||||
|
VarDeclaration* vd = it.get();
|
||||||
|
|
||||||
|
// skip if offset moved backwards
|
||||||
|
if (vd->offset < offset)
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
if (vd->ir.irField == NULL)
|
||||||
|
{
|
||||||
|
new IrField(vd, 2, vd->offset - PTRSIZE * 2);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
|
||||||
|
// get next aligned offset for this type
|
||||||
|
size_t alignsize = vd->type->alignsize();
|
||||||
|
size_t alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
|
||||||
|
|
||||||
|
// do we need to insert explicit padding before the field?
|
||||||
|
if (alignedoffset < vd->offset)
|
||||||
|
{
|
||||||
|
field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add default type
|
||||||
|
defaultTypes.push_back(DtoType(vd->type));
|
||||||
|
|
||||||
|
// advance offset to right past this field
|
||||||
|
offset = vd->offset + vd->type->size();
|
||||||
|
|
||||||
|
// give field index
|
||||||
|
// the IrField creation doesn't really belong here, but it's a trivial operation
|
||||||
|
// and it save yet another of these loops.
|
||||||
|
IF_LOG Logger::println("Field index: %zu", field_index);
|
||||||
|
if (vd->ir.irField == NULL)
|
||||||
|
{
|
||||||
|
new IrField(vd, field_index);
|
||||||
|
}
|
||||||
|
field_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// any interface implementations?
|
||||||
|
if (base->vtblInterfaces)
|
||||||
|
{
|
||||||
|
bool new_instances = (base == cd);
|
||||||
|
|
||||||
|
ArrayIter<BaseClass> it2(*base->vtblInterfaces);
|
||||||
|
|
||||||
|
for (; !it2.done(); it2.next())
|
||||||
|
{
|
||||||
|
BaseClass* b = it2.get();
|
||||||
|
IF_LOG Logger::println("Adding interface vtbl for %s", b->base->toPrettyChars());
|
||||||
|
|
||||||
|
Array arr;
|
||||||
|
b->fillVtbl(cd, &arr, new_instances);
|
||||||
|
|
||||||
|
const llvm::Type* ivtbl_type = buildVtblType(Type::tvoid->pointerTo(), &arr);
|
||||||
|
defaultTypes.push_back(llvm::PointerType::get(ivtbl_type, 0));
|
||||||
|
|
||||||
|
offset += PTRSIZE;
|
||||||
|
|
||||||
|
// add to the interface map
|
||||||
|
if (interfaceMap.find(b->base) == interfaceMap.end())
|
||||||
|
interfaceMap.insert(std::make_pair(b->base, field_index));
|
||||||
|
field_index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// tail padding?
|
||||||
|
if (offset < base->structsize)
|
||||||
|
{
|
||||||
|
field_index += add_zeros(defaultTypes, base->structsize - offset);
|
||||||
|
offset = base->structsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const llvm::Type* IrTypeClass::buildType()
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Building class type %s @ %s", cd->toPrettyChars(), cd->locToChars());
|
||||||
|
LOG_SCOPE;
|
||||||
|
IF_LOG Logger::println("Instance size: %u", cd->structsize);
|
||||||
|
|
||||||
|
// find the fields that contribute to the default initializer.
|
||||||
|
// these will define the default type.
|
||||||
|
|
||||||
|
std::vector<const llvm::Type*> defaultTypes;
|
||||||
|
defaultTypes.reserve(32);
|
||||||
|
|
||||||
|
// add vtbl
|
||||||
|
defaultTypes.push_back(llvm::PointerType::get(vtbl_pa.get(), 0));
|
||||||
|
|
||||||
|
// interface are just a vtable
|
||||||
|
if (!cd->isInterfaceDeclaration())
|
||||||
|
{
|
||||||
|
// add monitor
|
||||||
|
defaultTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty, 0));
|
||||||
|
|
||||||
|
// we start right after the vtbl and monitor
|
||||||
|
size_t offset = PTRSIZE * 2;
|
||||||
|
size_t field_index = 2;
|
||||||
|
|
||||||
|
// add data members recursively
|
||||||
|
addBaseClassData(defaultTypes, cd, offset, field_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// errors are fatal during codegen
|
||||||
|
if (global.errors)
|
||||||
|
fatal();
|
||||||
|
|
||||||
|
// build the llvm type
|
||||||
|
const llvm::Type* st = llvm::StructType::get(defaultTypes, false);
|
||||||
|
|
||||||
|
// refine type
|
||||||
|
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st);
|
||||||
|
|
||||||
|
// name type
|
||||||
|
Type::sir->getState()->module->addTypeName(cd->toPrettyChars(), pa.get());
|
||||||
|
|
||||||
|
// VTBL
|
||||||
|
|
||||||
|
// build vtbl type
|
||||||
|
const llvm::Type* vtblty = buildVtblType(
|
||||||
|
ClassDeclaration::classinfo->type,
|
||||||
|
&cd->vtbl);
|
||||||
|
|
||||||
|
// refine vtbl pa
|
||||||
|
llvm::cast<llvm::OpaqueType>(vtbl_pa.get())->refineAbstractTypeTo(vtblty);
|
||||||
|
|
||||||
|
// name vtbl type
|
||||||
|
std::string name(cd->toPrettyChars());
|
||||||
|
name.append(".__vtbl");
|
||||||
|
Type::sir->getState()->module->addTypeName(name, vtbl_pa.get());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
IF_LOG Logger::cout() << "class type: " << *pa.get() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const llvm::Type* IrTypeClass::buildVtblType(Type* first, Array* vtbl_array)
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Building vtbl type for class %s", cd->toPrettyChars());
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
std::vector<const llvm::Type*> types;
|
||||||
|
types.reserve(vtbl_array->dim);
|
||||||
|
|
||||||
|
// first comes the classinfo
|
||||||
|
types.push_back(DtoType(first));
|
||||||
|
|
||||||
|
// then come the functions
|
||||||
|
ArrayIter<Dsymbol> it(*vtbl_array);
|
||||||
|
it.index = 1;
|
||||||
|
|
||||||
|
for (; !it.done(); it.next())
|
||||||
|
{
|
||||||
|
FuncDeclaration* fd = it.get()->isFuncDeclaration();
|
||||||
|
assert(fd && "invalid vtbl entry");
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Adding type of %s", fd->toPrettyChars());
|
||||||
|
|
||||||
|
types.push_back(DtoType(fd->type->pointerTo()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the vtbl llvm type
|
||||||
|
return llvm::StructType::get(types, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
const llvm::Type * IrTypeClass::get()
|
||||||
|
{
|
||||||
|
return llvm::PointerType::get(pa.get(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
size_t IrTypeClass::getInterfaceIndex(ClassDeclaration * inter)
|
||||||
|
{
|
||||||
|
ClassIndexMap::iterator it = interfaceMap.find(inter);
|
||||||
|
if (it == interfaceMap.end())
|
||||||
|
return ~0;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
65
ir/irtypeclass.h
Normal file
65
ir/irtypeclass.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#ifndef __LDC_IR_IRTYPECLASS_H__
|
||||||
|
#define __LDC_IR_IRTYPECLASS_H__
|
||||||
|
|
||||||
|
#include "ir/irtypestruct.h"
|
||||||
|
|
||||||
|
///
|
||||||
|
class IrTypeClass : public IrTypeAggr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
IrTypeClass(ClassDeclaration* cd);
|
||||||
|
|
||||||
|
///
|
||||||
|
virtual IrTypeClass* isClass() { return this; }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildType();
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* getVtbl() { return vtbl_pa.get(); }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* get();
|
||||||
|
|
||||||
|
/// Get index to interface implementation.
|
||||||
|
/// Returns the index of a specific interface implementation in this
|
||||||
|
/// class or ~0 if not found.
|
||||||
|
size_t getInterfaceIndex(ClassDeclaration* inter);
|
||||||
|
|
||||||
|
/// Returns the total number of pointers in the vtable.
|
||||||
|
unsigned getVtblSize() { return vtbl_size; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
///
|
||||||
|
ClassDeclaration* cd;
|
||||||
|
///
|
||||||
|
TypeClass* tc;
|
||||||
|
|
||||||
|
///
|
||||||
|
llvm::PATypeHolder vtbl_pa;
|
||||||
|
|
||||||
|
/// Number of pointers in vtable.
|
||||||
|
unsigned vtbl_size;
|
||||||
|
|
||||||
|
/// std::map type mapping ClassDeclaration* to size_t.
|
||||||
|
typedef std::map<ClassDeclaration*, size_t> ClassIndexMap;
|
||||||
|
|
||||||
|
/// Map for mapping the index of a specific interface implementation
|
||||||
|
/// in this class to it's ClassDeclaration*.
|
||||||
|
ClassIndexMap interfaceMap;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildVtblType(Type* first, Array* vtbl_array);
|
||||||
|
|
||||||
|
///
|
||||||
|
void addBaseClassData(
|
||||||
|
std::vector<const llvm::Type*>& defaultTypes,
|
||||||
|
ClassDeclaration* base,
|
||||||
|
size_t& offset,
|
||||||
|
size_t& field_index);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
148
ir/irtypestruct.cpp
Normal file
148
ir/irtypestruct.cpp
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
#include "llvm/DerivedTypes.h"
|
||||||
|
|
||||||
|
#include "aggregate.h"
|
||||||
|
#include "declaration.h"
|
||||||
|
#include "mtype.h"
|
||||||
|
|
||||||
|
#include "gen/irstate.h"
|
||||||
|
#include "gen/tollvm.h"
|
||||||
|
#include "gen/logger.h"
|
||||||
|
#include "gen/utils.h"
|
||||||
|
#include "ir/irtypestruct.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IrTypeAggr::IrTypeAggr(AggregateDeclaration * ad)
|
||||||
|
: IrType(ad->type, llvm::OpaqueType::get()),
|
||||||
|
aggr(ad)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
IrTypeStruct::IrTypeStruct(StructDeclaration * sd)
|
||||||
|
: IrTypeAggr(sd),
|
||||||
|
sd(sd),
|
||||||
|
ts((TypeStruct*)sd->type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
size_t add_zeros(std::vector<const llvm::Type*>& defaultTypes, size_t diff)
|
||||||
|
{
|
||||||
|
size_t n = defaultTypes.size();
|
||||||
|
while (diff)
|
||||||
|
{
|
||||||
|
if (global.params.is64bit && diff % 8 == 0)
|
||||||
|
{
|
||||||
|
defaultTypes.push_back(llvm::Type::Int64Ty);
|
||||||
|
diff -= 8;
|
||||||
|
}
|
||||||
|
else if (diff % 4 == 0)
|
||||||
|
{
|
||||||
|
defaultTypes.push_back(llvm::Type::Int32Ty);
|
||||||
|
diff -= 4;
|
||||||
|
}
|
||||||
|
else if (diff % 2 == 0)
|
||||||
|
{
|
||||||
|
defaultTypes.push_back(llvm::Type::Int16Ty);
|
||||||
|
diff -= 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
defaultTypes.push_back(llvm::Type::Int8Ty);
|
||||||
|
diff -= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return defaultTypes.size() - n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm::Type* IrTypeStruct::buildType()
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Building struct type %s @ %s", sd->toPrettyChars(), sd->locToChars());
|
||||||
|
LOG_SCOPE;
|
||||||
|
|
||||||
|
// find the fields that contribute to the default initializer.
|
||||||
|
// these will define the default type.
|
||||||
|
|
||||||
|
std::vector<const llvm::Type*> defaultTypes;
|
||||||
|
defaultTypes.reserve(16);
|
||||||
|
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t field_index = 0;
|
||||||
|
|
||||||
|
bool packed = (sd->type->alignsize() == 1);
|
||||||
|
|
||||||
|
ArrayIter<VarDeclaration> it(sd->fields);
|
||||||
|
for (; !it.done(); it.next())
|
||||||
|
{
|
||||||
|
VarDeclaration* vd = it.get();
|
||||||
|
|
||||||
|
assert(vd->ir.irField == NULL && "struct inheritance is not allowed, how can this happen?");
|
||||||
|
|
||||||
|
// skip if offset moved backwards
|
||||||
|
if (vd->offset < offset)
|
||||||
|
{
|
||||||
|
IF_LOG Logger::println("Skipping field %s %s (+%u) for default", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
new IrField(vd, 0, vd->offset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
IF_LOG Logger::println("Adding default field %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset);
|
||||||
|
|
||||||
|
// get next aligned offset for this type
|
||||||
|
size_t alignedoffset = offset;
|
||||||
|
if (!packed)
|
||||||
|
{
|
||||||
|
size_t alignsize = vd->type->alignsize();
|
||||||
|
alignedoffset = (offset + alignsize - 1) & ~(alignsize - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// insert explicit padding?
|
||||||
|
if (alignedoffset < vd->offset)
|
||||||
|
{
|
||||||
|
field_index += add_zeros(defaultTypes, vd->offset - alignedoffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add default type
|
||||||
|
defaultTypes.push_back(DtoType(vd->type));
|
||||||
|
|
||||||
|
// advance offset to right past this field
|
||||||
|
offset = vd->offset + vd->type->size();
|
||||||
|
|
||||||
|
// give field index
|
||||||
|
// the IrField creation doesn't really belong here, but it's a trivial operation
|
||||||
|
// and it save yet another of these loops.
|
||||||
|
IF_LOG Logger::println("Field index: %zu", field_index);
|
||||||
|
new IrField(vd, field_index);
|
||||||
|
field_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// tail padding?
|
||||||
|
if (offset < sd->structsize)
|
||||||
|
{
|
||||||
|
add_zeros(defaultTypes, sd->structsize - offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// build the llvm type
|
||||||
|
const llvm::Type* st = llvm::StructType::get(defaultTypes, packed);
|
||||||
|
|
||||||
|
// refine type
|
||||||
|
llvm::cast<llvm::OpaqueType>(pa.get())->refineAbstractTypeTo(st);
|
||||||
|
|
||||||
|
// name types
|
||||||
|
Type::sir->getState()->module->addTypeName(sd->toPrettyChars(), pa.get());
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
IF_LOG Logger::cout() << "struct type: " << *pa.get() << std::endl;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return pa.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
52
ir/irtypestruct.h
Normal file
52
ir/irtypestruct.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef __LDC_IR_IRTYPESTRUCT_H__
|
||||||
|
#define __LDC_IR_IRTYPESTRUCT_H__
|
||||||
|
|
||||||
|
#include "ir/irtype.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
struct AggregateDeclaration;
|
||||||
|
struct StructDeclaration;
|
||||||
|
struct TypeStruct;
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class IrTypeAggr : public IrType
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
IrTypeAggr(AggregateDeclaration* ad);
|
||||||
|
|
||||||
|
///
|
||||||
|
IrTypeAggr* isAggr() { return this; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// AggregateDeclaration this type represents.
|
||||||
|
AggregateDeclaration* aggr;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class IrTypeStruct : public IrTypeAggr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
IrTypeStruct(StructDeclaration* sd);
|
||||||
|
|
||||||
|
///
|
||||||
|
IrTypeStruct* isStruct() { return this; }
|
||||||
|
|
||||||
|
///
|
||||||
|
const llvm::Type* buildType();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/// StructDeclaration this type represents.
|
||||||
|
StructDeclaration* sd;
|
||||||
|
|
||||||
|
/// DMD TypeStruct of this type.
|
||||||
|
TypeStruct* ts;
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -36,11 +36,14 @@ IrLocal::IrLocal(VarDeclaration* v) : IrVar(v)
|
|||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
IrField::IrField(VarDeclaration* v) : IrVar(v)
|
IrField::IrField(VarDeclaration* v, size_t idx, size_t offset) : IrVar(v)
|
||||||
{
|
{
|
||||||
index = 0;
|
index = idx;
|
||||||
unionOffset = 0;
|
unionOffset = offset;
|
||||||
constInit = NULL;
|
constInit = NULL;
|
||||||
|
|
||||||
|
assert(V->ir.irField == NULL && "field for this variable already exists");
|
||||||
|
V->ir.irField = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -34,11 +34,12 @@ struct IrLocal : IrVar
|
|||||||
// represents an aggregate field variable
|
// represents an aggregate field variable
|
||||||
struct IrField : IrVar
|
struct IrField : IrVar
|
||||||
{
|
{
|
||||||
IrField(VarDeclaration* v);
|
IrField(VarDeclaration* v, size_t idx, size_t offset = 0);
|
||||||
|
|
||||||
unsigned index;
|
unsigned index;
|
||||||
unsigned unionOffset;
|
unsigned unionOffset;
|
||||||
|
|
||||||
|
protected:
|
||||||
llvm::Constant* constInit;
|
llvm::Constant* constInit;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user