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:
Tomas Lindquist Olsen
2009-04-15 20:06:25 +02:00
parent 909c6dae18
commit 37cf5a5789
33 changed files with 3158 additions and 2201 deletions

1473
Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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

View File

@@ -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
} }

View File

@@ -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 */

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@@ -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

View File

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

View File

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

View File

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

View File

@@ -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

View File

@@ -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?

View File

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

View File

@@ -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

View File

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

View File

@@ -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

View File

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

View File

@@ -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
View 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
View 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
View 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
View 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

View File

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

View File

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