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
+2
View File
@@ -1,6 +1,8 @@
#ifndef LLVMC_GEN_ARRAYS_H
#define LLVMC_GEN_ARRAYS_H
struct ArrayInitializer;
struct DSliceValue;
const llvm::StructType* DtoArrayType(Type* arrayTy);
+68 -950
View File
File diff suppressed because it is too large Load Diff
+7 -14
View File
@@ -3,28 +3,21 @@
#include "gen/structs.h"
/**
* Resolves the llvm type for a class declaration
*/
/// Resolves the llvm type for a class declaration
void DtoResolveClass(ClassDeclaration* cd);
/**
* Provides the llvm declaration for a class declaration
*/
/// Provides the llvm declaration for a class declaration
void DtoDeclareClass(ClassDeclaration* cd);
/**
* Constructs the constant initializer for a class declaration
*/
/// Constructs the constant initializer for a class declaration
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 DtoDeclareClassInfo(ClassDeclaration* cd);
void DtoDefineClassInfo(ClassDeclaration* cd);
/// Builds the initializer of cd's ClassInfo.
/// FIXME: this should be put into IrStruct and eventually IrClass.
LLConstant* DtoDefineClassInfo(ClassDeclaration* cd);
DValue* DtoNewClass(Loc loc, TypeClass* type, NewExp* newexp);
void DtoInitClass(TypeClass* tc, LLValue* dst);
+14 -47
View File
@@ -14,6 +14,8 @@
#include "ir/ir.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)
{
Logger::print("VarDeclaration::toObjFile(): %s | %s\n", toChars(), type->toChars());
LOG_SCOPE;
// just forward aliases
if (aliassym)
{
Logger::println("alias sym");
@@ -84,10 +89,11 @@ void VarDeclaration::codegen(Ir* p)
return;
}
// output the parent aggregate first
if (AggregateDeclaration* ad = isMember())
ad->codegen(p);
// global variable or magic
// global variable
#if DMDV2
// taken from dmd2/structs
if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init))
@@ -138,25 +144,8 @@ void VarDeclaration::codegen(Ir* p)
if (nakedUse)
gIR->usedArray.push_back(DtoBitCast(gvar, getVoidPtrType()));
// don't initialize static struct members yet, they might be of the struct type
// which doesn't have a static initializer yet.
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);
// initialize
DtoConstInitGlobal(this);
}
}
@@ -164,8 +153,7 @@ void VarDeclaration::codegen(Ir* p)
void TypedefDeclaration::codegen(Ir*)
{
static int tdi = 0;
Logger::print("TypedefDeclaration::toObjFile(%d): %s\n", tdi++, toChars());
Logger::print("TypedefDeclaration::toObjFile: %s\n", toChars());
LOG_SCOPE;
// generate typeinfo
@@ -181,33 +169,12 @@ void EnumDeclaration::codegen(Ir*)
/* ================================================================== */
void FuncDeclaration::codegen(Ir*)
void FuncDeclaration::codegen(Ir* p)
{
DtoResolveDsymbol(this);
}
/* ================================================================== */
void AnonDeclaration::codegen(Ir* p)
{
Array *d = include(NULL, NULL);
if (d)
// don't touch function aliases, they don't contribute any new symbols
if (!isFuncAliasDeclaration())
{
// get real aggregate parent
IrStruct* irstruct = gIR->topstruct();
// push a block on the stack
irstruct->pushAnon(isunion);
// go over children
for (unsigned i = 0; i < d->dim; i++)
{ Dsymbol *s = (Dsymbol *)d->data[i];
s->codegen(p);
}
// finish
irstruct->popAnon();
DtoResolveDsymbol(this);
}
}
+5 -11
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);
f->ir.type = new llvm::PATypeHolder(functype);
#if 0
Logger::cout() << "Final function type: " << *functype << "\n";
#endif
return functype;
}
@@ -304,16 +306,6 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
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());
if (fdecl->parent)
@@ -372,7 +364,6 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
// queue declaration unless the function is abstract without body
if (!fdecl->isAbstract() || fdecl->fbody)
{
Logger::println("Ignoring declaration of abstract bodyless function %s", fdecl->toPrettyChars());
DtoDeclareFunction(fdecl);
}
}
@@ -465,6 +456,9 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
Type* t = fdecl->type->toBasetype();
TypeFunction* f = (TypeFunction*)t;
// sanity check
assert(fdecl == f->funcdecl && "the function type does not point to this function");
bool declareOnly = !mustDefineSymbol(fdecl);
if (fdecl->llvmInternal == LLVMva_start)
+2 -1
View File
@@ -1069,7 +1069,8 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init)
else if (StructInitializer* si = init->isStructInitializer())
{
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())
{
+2
View File
@@ -33,5 +33,7 @@ namespace Logger
#define LOG_SCOPE Logger::LoggerScope _logscope;
#define IF_LOG if (Logger::enabled())
#endif
+20 -599
View File
@@ -15,438 +15,10 @@
#include "gen/structs.h"
#include "gen/dvalue.h"
#include "gen/functions.h"
#include "gen/utils.h"
#include "ir/irstruct.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;
}
#include "ir/irtypestruct.h"
//////////////////////////////////////////////////////////////////////////////////////////
@@ -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)
{
// 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());
LOG_SCOPE;
// get the DMD TypeStruct
TypeStruct* ts = (TypeStruct*)sd->type;
// make sure type exists
DtoType(sd->type);
// create the IrStruct
IrStruct* irstruct = new IrStruct(sd);
sd->ir.irStruct = irstruct;
// create the type
ts->ir.type = new LLPATypeHolder(llvm::OpaqueType::get());
// emit the initZ symbol
LLGlobalVariable* initZ = irstruct->getInitSymbol();
// create symbols we're going to need
// 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);
// perform definition
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");
irstruct->constInit = llvm::ConstantAggregateZero::get(structtype);
}
else
{
Logger::println("Not zero initialized");
LLConstant* c = irstruct->buildDefaultConstInit();
irstruct->constInit = c;
// set initZ initializer
initZ->setInitializer(irstruct->getDefaultInit());
}
// refine __initZ global type to the one of the initializer
llvm::cast<llvm::OpaqueType>(irstruct->initOpaque.get())->refineAbstractTypeTo(irstruct->constInit->getType());
// build initializers for static member variables
size_t n = irstruct->staticVars.size();
for (size_t i = 0; i < n; ++i)
// emit members
if (sd->members)
{
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
if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMno_typeinfo)
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;
DtoTypeInfoOf(sd->type);
}
//////////////////////////////////////////////////////////////////////////////////////////
+5 -6
View File
@@ -13,6 +13,7 @@
#include "gen/logger.h"
#include "gen/llvmhelpers.h"
#include "gen/linkage.h"
#include "gen/utils.h"
#include "ir/irmodule.h"
@@ -288,14 +289,12 @@ static llvm::DICompositeType dwarfCompositeType(Type* type, llvm::DICompileUnit
std::vector<LLConstant*> elems;
if (!ir->aggrdecl->isInterfaceDeclaration()) // plain interfaces don't have one
{
std::vector<VarDeclaration*>& arr = ir->varDecls;
size_t narr = arr.size();
ArrayIter<VarDeclaration> it(sd->fields);
size_t narr = sd->fields.dim;
elems.reserve(narr);
for (int k=0; k<narr; k++)
for (; !it.done(); it.next())
{
VarDeclaration* vd = arr[k];
assert(vd);
VarDeclaration* vd = it.get();
LLGlobalVariable* ptr = dwarfMemberType(vd->loc.linnum, vd->type, compileUnit, definedCU, vd->toChars(), vd->offset).getGV();
elems.push_back(DBG_CAST(ptr));
}
+12 -14
View File
@@ -131,8 +131,7 @@ DValue* VarExp::toElem(IRState* p)
{
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
cid->cd->codegen(Type::sir);;
assert(cid->cd->ir.irStruct->classInfo);
return new DVarValue(type, vd, cid->cd->ir.irStruct->classInfo);
return new DVarValue(type, vd, cid->cd->ir.irStruct->getClassInfoSymbol());
}
// nested variable
#if DMDV2
@@ -216,8 +215,8 @@ DValue* VarExp::toElem(IRState* p)
TypeStruct* ts = (TypeStruct*)sdecltype;
assert(ts->sym);
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
{
@@ -242,8 +241,8 @@ LLConstant* VarExp::toConstElem(IRState* p)
assert(sdecltype->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)sdecltype;
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())
@@ -1134,9 +1133,7 @@ DValue* DotVarExp::toElem(IRState* p)
size_t vtblidx = fdecl->vtblIndex;
if (Logger::enabled())
Logger::cout() << "vthis: " << *vthis << '\n';
funcval = vthis;
if (!fdecl->isMember2()->isInterfaceDeclaration())
funcval = DtoGEP(funcval, zero, zero);
funcval = DtoGEP(vthis, zero, zero);
funcval = DtoLoad(funcval);
Logger::println("vtblidx = %lu", vtblidx);
funcval = DtoGEP(funcval, zero, DtoConstUint(vtblidx), toChars());
@@ -1646,7 +1643,7 @@ DValue* NewExp::toElem(IRState* p)
else {
assert(ts->sym);
ts->sym->codegen(Type::sir);
DtoAggrCopy(mem,ts->sym->ir.irStruct->init);
DtoAggrCopy(mem,ts->sym->ir.irStruct->getInitSymbol());
}
return new DImValue(type, mem);
}
@@ -1658,8 +1655,7 @@ DValue* NewExp::toElem(IRState* p)
DVarValue tmpvar(newtype, mem);
// default initialize
// FIXME: should this use DtoConstExpInit instead ?
// or is static arrays the only troublemaker?
// static arrays never appear here, so using the defaultInit is ok!
Expression* exp = newtype->defaultInit(loc);
DValue* iv = exp->toElem(gIR);
DtoAssign(loc, &tmpvar, iv);
@@ -2413,7 +2409,8 @@ DValue* StructLiteralExp::toElem(IRState* p)
}
// 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
size_t n = values.size();
@@ -2462,7 +2459,8 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
inits[i] = exprs[i]->toConstElem(p);
// 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
std::vector<LLConstant*> constvals(values.size(), NULL);
+22 -28
View File
@@ -23,6 +23,7 @@
#include "gen/llvm-version.h"
#include "ir/irtype.h"
#include "ir/irtypeclass.h"
bool DtoIsPassedByRef(Type* type)
{
@@ -52,11 +53,17 @@ unsigned DtoShouldExtend(Type* type)
const LLType* DtoType(Type* t)
{
#if DMDV2
t = t->mutableOf();
#endif
if (t->irtype)
{
return t->irtype->get();
}
IF_LOG Logger::println("Building type: %s", t->toChars());
assert(t);
switch (t->ty)
{
@@ -86,57 +93,50 @@ const LLType* DtoType(Type* t)
case Tdchar:
{
t->irtype = new IrTypeBasic(t);
return t->irtype->get();
return t->irtype->buildType();
}
// pointers
case Tpointer:
{
t->irtype = new IrTypePointer(t);
return t->irtype->get();
return t->irtype->buildType();
}
// arrays
case Tarray:
{
t->irtype = new IrTypeArray(t);
return t->irtype->get();
return t->irtype->buildType();
}
case Tsarray:
{
t->irtype = new IrTypeSArray(t);
return t->irtype->get();
return t->irtype->buildType();
}
// aggregates
case Tstruct: {
#if DMDV2
TypeStruct* ts = (TypeStruct*)t->mutableOf();
#else
TypeStruct* ts = (TypeStruct*)t;
#endif
assert(ts->sym);
DtoResolveDsymbol(ts->sym);
return ts->ir.type->get();
t->irtype = new IrTypeStruct(ts->sym);
return t->irtype->buildType();
}
case Tclass: {
#if DMDV2
TypeClass* tc = (TypeClass*)t->mutableOf();
#else
TypeClass* tc = (TypeClass*)t;
#endif
assert(tc->sym);
DtoResolveDsymbol(tc->sym);
return getPtrToType(tc->ir.type->get());
t->irtype = new IrTypeClass(tc->sym);
return t->irtype->buildType();
}
// functions
case Tfunction:
{
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 {
return t->ir.type->get();
@@ -156,6 +156,8 @@ const LLType* DtoType(Type* t)
// typedefs
// enum
// FIXME: maybe just call toBasetype first ?
case Ttypedef:
case Tenum:
{
@@ -166,15 +168,7 @@ const LLType* DtoType(Type* t)
// associative arrays
case Taarray:
#if 1
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
+3 -4
View File
@@ -146,7 +146,7 @@ llvm::Module* Module::genLLVMModule(Ir* sir)
sir->emitFunctionBodies();
// generate ModuleInfo
genmoduleinfo();
//genmoduleinfo();
// emit usedArray
if (!ir.usedArray.empty())
@@ -621,7 +621,7 @@ void Module::genmoduleinfo()
LLConstant* c = 0;
// vtable
c = moduleinfo->ir.irStruct->vtbl;
c = moduleinfo->ir.irStruct->getVtblSymbol();
initVec.push_back(c);
// monitor
@@ -696,8 +696,7 @@ void Module::genmoduleinfo()
continue;
}
Logger::println("class: %s", cd->toPrettyChars());
assert(cd->ir.irStruct->classInfo);
c = DtoBitCast(cd->ir.irStruct->classInfo, getPtrToType(classinfoTy));
c = DtoBitCast(cd->ir.irStruct->getClassInfoSymbol(), getPtrToType(classinfoTy));
classInits.push_back(c);
}
// has class array?
+16 -29
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
//////////////////////////////////////////////////////////////////////////////
@@ -376,7 +362,7 @@ void TypeInfoTypedefDeclaration::llvmDefine()
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(getNullPtr(getPtrToType(LLType::Int8Ty)));
@@ -433,7 +419,7 @@ void TypeInfoEnumDeclaration::llvmDefine()
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -491,7 +477,7 @@ static void LLVM_D_Define_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid,
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -553,7 +539,7 @@ void TypeInfoStaticArrayDeclaration::llvmDefine()
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -592,7 +578,7 @@ void TypeInfoAssociativeArrayDeclaration::llvmDefine()
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -664,7 +650,7 @@ void TypeInfoStructDeclaration::llvmDefine()
// vtbl
std::vector<LLConstant*> sinits;
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -687,7 +673,7 @@ void TypeInfoStructDeclaration::llvmDefine()
#endif
{
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));
}
@@ -857,7 +843,7 @@ void TypeInfoClassDeclaration::llvmDefine()
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -865,9 +851,10 @@ void TypeInfoClassDeclaration::llvmDefine()
// get classinfo
assert(tinfo->ty == Tclass);
TypeClass *tc = (TypeClass *)tinfo;
tc->sym->codegen(Type::sir);;
assert(tc->sym->ir.irStruct->classInfo);
sinits.push_back(tc->sym->ir.irStruct->classInfo);
tc->sym->codegen(Type::sir);
sinits.push_back(tc->sym->ir.irStruct->getClassInfoSymbol());
// create the inititalizer
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
@@ -897,7 +884,7 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
@@ -905,8 +892,8 @@ void TypeInfoInterfaceDeclaration::llvmDefine()
// get classinfo
assert(tinfo->ty == Tclass);
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
LLConstant* tiInit = llvm::ConstantStruct::get(sinits);
@@ -936,7 +923,7 @@ void TypeInfoTupleDeclaration::llvmDefine()
// initializer vector
std::vector<LLConstant*> sinits;
// first is always the vtable
sinits.push_back(base->ir.irStruct->vtbl);
sinits.push_back(base->ir.irStruct->getVtblSymbol());
// monitor
sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(LLType::Int8Ty)));
+46
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