235 changes: 127 additions & 108 deletions dmd2/mtype.c
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@ Type *Type::merge()

//if (next)
//next = next->merge();
toDecoBuffer(&buf, false);
toDecoBuffer(&buf, false);
sv = stringtable.update((char *)buf.data, buf.offset);
if (sv->ptrvalue)
{ t = (Type *) sv->ptrvalue;
Expand All @@ -1556,19 +1556,19 @@ Type *Type::merge()
// we still need deco strings to be unique
// or Type::equals fails, which breaks a bunch of stuff,
// like covariant member function overloads.
OutBuffer mangle;
toDecoBuffer(&mangle, true);
StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset);
if (sv2->ptrvalue)
{ Type* t2 = (Type *) sv2->ptrvalue;
assert(t2->deco);
deco = t2->deco;
}
else
{
sv2->ptrvalue = this;
deco = (char *)sv2->lstring.string;
}
OutBuffer mangle;
toDecoBuffer(&mangle, true);
StringValue* sv2 = deco_stringtable.update((char *)mangle.data, mangle.offset);
if (sv2->ptrvalue)
{ Type* t2 = (Type *) sv2->ptrvalue;
assert(t2->deco);
deco = t2->deco;
}
else
{
sv2->ptrvalue = this;
deco = (char *)sv2->lstring.string;
}
//printf("new value, deco = '%s' %p\n", t->deco, t->deco);
}
}
Expand Down Expand Up @@ -1753,7 +1753,11 @@ Expression *Type::getProperty(Loc loc, Identifier *ident)
{
if (ty == Tvoid)
error(loc, "void does not have an initializer");
#if IN_LLVM
e = defaultInit(loc);
#else
e = defaultInitLiteral(loc);
#endif
}
else if (ident == Id::mangleof)
{ const char *s;
Expand Down Expand Up @@ -3123,26 +3127,26 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
Expression *ec;
Expressions *arguments;

//LDC: Build arguments.
static FuncDeclaration *adReverseChar_fd = NULL;
if(!adReverseChar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::tchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adReverseChar_fd = FuncDeclaration::genCfunc(args, arrty, "_adReverseChar");
}
static FuncDeclaration *adReverseWchar_fd = NULL;
if(!adReverseWchar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::twchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adReverseWchar_fd = FuncDeclaration::genCfunc(args, arrty, "_adReverseWchar");
}
//LDC: Build arguments.
static FuncDeclaration *adReverseChar_fd = NULL;
if(!adReverseChar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::tchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adReverseChar_fd = FuncDeclaration::genCfunc(args, arrty, "_adReverseChar");
}
static FuncDeclaration *adReverseWchar_fd = NULL;
if(!adReverseWchar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::twchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adReverseWchar_fd = FuncDeclaration::genCfunc(args, arrty, "_adReverseWchar");
}

if(n->ty == Twchar)
ec = new VarExp(0, adReverseWchar_fd);
else
ec = new VarExp(0, adReverseChar_fd);
if(n->ty == Twchar)
ec = new VarExp(0, adReverseWchar_fd);
else
ec = new VarExp(0, adReverseChar_fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions();
arguments->push(e);
Expand All @@ -3154,26 +3158,26 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
Expression *ec;
Expressions *arguments;

//LDC: Build arguments.
static FuncDeclaration *adSortChar_fd = NULL;
if(!adSortChar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::tchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adSortChar_fd = FuncDeclaration::genCfunc(args, arrty, "_adSortChar");
}
static FuncDeclaration *adSortWchar_fd = NULL;
if(!adSortWchar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::twchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adSortWchar_fd = FuncDeclaration::genCfunc(args, arrty, "_adSortWchar");
}
//LDC: Build arguments.
static FuncDeclaration *adSortChar_fd = NULL;
if(!adSortChar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::tchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adSortChar_fd = FuncDeclaration::genCfunc(args, arrty, "_adSortChar");
}
static FuncDeclaration *adSortWchar_fd = NULL;
if(!adSortWchar_fd) {
Parameters* args = new Parameters;
Type* arrty = Type::twchar->arrayOf();
args->push(new Parameter(STCin, arrty, NULL, NULL));
adSortWchar_fd = FuncDeclaration::genCfunc(args, arrty, "_adSortWchar");
}

if(n->ty == Twchar)
ec = new VarExp(0, adSortWchar_fd);
else
ec = new VarExp(0, adSortChar_fd);
if(n->ty == Twchar)
ec = new VarExp(0, adSortWchar_fd);
else
ec = new VarExp(0, adSortChar_fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions();
arguments->push(e);
Expand All @@ -3189,37 +3193,39 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)

assert(size);
dup = (ident == Id::dup || ident == Id::idup);
//LDC: Build arguments.
static FuncDeclaration *adDup_fd = NULL;
if(!adDup_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
adDup_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::adDup);
}
static FuncDeclaration *adReverse_fd = NULL;
if(!adReverse_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL));
adReverse_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::adReverse);
}

if(dup)
ec = new VarExp(0, adDup_fd);
else
ec = new VarExp(0, adReverse_fd);
//LDC: Build arguments.
static FuncDeclaration *adDup_fd = NULL;
if(!adDup_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
adDup_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::adDup);
}
static FuncDeclaration *adReverse_fd = NULL;
if(!adReverse_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::tsize_t, NULL, NULL));
adReverse_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), Id::adReverse);
}

if(dup)
ec = new VarExp(0, adDup_fd);
else
ec = new VarExp(0, adReverse_fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions();
if (dup)
arguments->push(getTypeInfo(sc));

// LDC repaint array type to void[]
if (n->ty != Tvoid) {
e = new CastExp(e->loc, e, e->type);
e->type = Type::tvoid->arrayOf();
}
arguments->push(e);
// LDC repaint array type to void[]
if (n->ty != Tvoid) {
CastExp *exp = new CastExp(e->loc, e, e->type);
exp->type = Type::tvoid->arrayOf();
exp->disableOptimization = true;
e = exp;
}
arguments->push(e);

if (!dup)
arguments->push(new IntegerExp(0, size, Type::tsize_t));
Expand All @@ -3237,41 +3243,46 @@ Expression *TypeArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
{
Expression *ec;
Expressions *arguments;
bool isBit = (n->ty == Tbit);

//LDC: Build arguments.
static FuncDeclaration *adSort_fd = NULL;
if(!adSort_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSort_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSort");
}
static FuncDeclaration *adSortBit_fd = NULL;
if(!adSortBit_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSortBit_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSortBit");
}

if(isBit)
ec = new VarExp(0, adSortBit_fd);
else
ec = new VarExp(0, adSort_fd);
bool isBit = (n->ty == Tbit);

//LDC: Build arguments.
static FuncDeclaration *adSort_fd = NULL;
if(!adSort_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSort_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSort");
}
static FuncDeclaration *adSortBit_fd = NULL;
if(!adSortBit_fd) {
Parameters* args = new Parameters;
args->push(new Parameter(STCin, Type::tvoid->arrayOf(), NULL, NULL));
args->push(new Parameter(STCin, Type::typeinfo->type, NULL, NULL));
adSortBit_fd = FuncDeclaration::genCfunc(args, Type::tvoid->arrayOf(), "_adSortBit");
}

if(isBit)
ec = new VarExp(0, adSortBit_fd);
else
ec = new VarExp(0, adSort_fd);
e = e->castTo(sc, n->arrayOf()); // convert to dynamic array
arguments = new Expressions();

// LDC repaint array type to void[]
if (n->ty != Tvoid) {
e = new CastExp(e->loc, e, e->type);
e->type = Type::tvoid->arrayOf();
}
// LDC repaint array type to void[]
if (n->ty != Tvoid) {
CastExp *exp = new CastExp(e->loc, e, e->type);
exp->type = Type::tvoid->arrayOf();
exp->disableOptimization = true;
e = exp;
}
arguments->push(e);

if (next->ty != Tbit)
arguments->push(n->getTypeInfo(sc)); // LDC, we don't support the getInternalTypeInfo
// optimization arbitrarily, not yet at least...
if (next->ty != Tbit) {
// LDC, we don't support the getInternalTypeInfo
// optimization arbitrarily, not yet at least...
arguments->push(n->getTypeInfo(sc));
}

e = new CallExp(e->loc, ec, arguments);
e->type = next->arrayOf();
}
Expand Down Expand Up @@ -7499,9 +7510,17 @@ Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
{ /* The handle to the monitor (call it a void*)
* *(cast(void**)e + 1)
*/
#if IN_LLVM
e = e->castTo(sc, tint8->pointerTo()->pointerTo());
e = new AddExp(e->loc, e, new IntegerExp(1));
e->type = tint8->pointerTo();
e = e->castTo(sc, tvoidptr->pointerTo());
e = new PtrExp(e->loc, e);
#else
e = e->castTo(sc, tvoidptr->pointerTo());
e = new AddExp(e->loc, e, new IntegerExp(1));
e = new PtrExp(e->loc, e);
#endif
e = e->semantic(sc);
return e;
}
Expand Down
13 changes: 11 additions & 2 deletions dmd2/optimize.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ Expression *AddrExp::optimize(int result)
{ Expression *e;

//printf("AddrExp::optimize(result = %d) %s\n", result, toChars());
// LDC never try to interpret: it could change the semantics by turning
// const p = &s; into an something like const p = &(Struct());

/* Rewrite &(a,b) as (a,&b)
*/
Expand All @@ -295,13 +297,13 @@ Expression *AddrExp::optimize(int result)
ae->type = type;
e = new CommaExp(ce->loc, ce->e1, ae);
e->type = type;
return e->optimize(result);
return e->optimize(result & ~WANTinterpret);
}

if (e1->op == TOKvar)
{ VarExp *ve = (VarExp *)e1;
if (ve->var->storage_class & STCmanifest)
e1 = e1->optimize(result);
e1 = e1->optimize(result & ~WANTinterpret);
}
else
e1 = e1->optimize(result);
Expand Down Expand Up @@ -523,6 +525,10 @@ Expression *CallExp::optimize(int result)

Expression *CastExp::optimize(int result)
{
#if IN_LLVM
if (disableOptimization)
return this;
#endif
//printf("CastExp::optimize(result = %d) %s\n", result, toChars());
//printf("from %s to %s\n", type->toChars(), to->toChars());
//printf("from %s\n", type->toChars());
Expand Down Expand Up @@ -551,6 +557,9 @@ Expression *CastExp::optimize(int result)
e1->type->nextOf()->size() == type->nextOf()->size()
)
{
// LDC make a copy before adjusting type to avoid
// messing up the type of an existing initializer
e1 = e1->syntaxCopy();
Expression *e = e1->castTo(NULL, type);
if (X) printf(" returning1 %s\n", e->toChars());
return e;
Expand Down
10 changes: 10 additions & 0 deletions dmd2/struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ AggregateDeclaration::AggregateDeclaration(Loc loc, Identifier *id)
protection = PROTpublic;
type = NULL;
handle = NULL;
scope = 0;
structsize = 0; // size of struct
alignsize = 0; // size of struct for alignment purposes
structalign = 0; // struct member alignment in effect
Expand Down Expand Up @@ -263,6 +264,15 @@ StructDeclaration::StructDeclaration(Loc loc, Identifier *id)

// For forward references
type = new TypeStruct(this);

#if MODULEINFO_IS_STRUCT
if (id == Id::ModuleInfo)
{
if (Module::moduleinfo)
Module::moduleinfo->error("only object.d can define this reserved class name");
Module::moduleinfo = this;
}
#endif
}

Dsymbol *StructDeclaration::syntaxCopy(Dsymbol *s)
Expand Down
4 changes: 4 additions & 0 deletions gen/aa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,12 @@ DValue* DtoAAIn(Loc& loc, Type* type, DValue* aa, DValue* key)
keyti = DtoBitCast(keyti, funcTy->getParamType(1));

// pkey param
#if DMDV1
LLValue* pkey = makeLValue(loc, key);
pkey = DtoBitCast(pkey, funcTy->getParamType(2));
#else
LLValue* pkey = getNullValue(getVoidPtrType());
#endif

// call runtime
LLValue* ret = gIR->CreateCallOrInvoke3(func, aaval, keyti, pkey, "aa.in").getInstruction();
Expand Down
28 changes: 21 additions & 7 deletions gen/arrays.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,20 @@ void DtoArrayInit(Loc& loc, DValue* array, DValue* value)

//////////////////////////////////////////////////////////////////////////////////////////

void DtoSetArray(LLValue* arr, LLValue* dim, LLValue* ptr)
void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr)
{
Logger::println("SetArray");
LLValue *arr = array->getLVal();
assert(isaStruct(arr->getType()->getContainedType(0)));
#if 1
DtoStore(dim, DtoGEPi(arr,0,0));
DtoStore(ptr, DtoGEPi(arr,0,1));
#else
DSliceValue *slice = DtoResizeDynArray(array->type, array, dim);
DtoMemCpy(DtoArrayPtr(array), ptr, dim);
DtoStore(dim, DtoGEPi(arr,0,0));
DtoStore(slice->ptr, DtoGEPi(arr,0,1));
#endif
}

//////////////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -498,7 +506,7 @@ DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size
}

//////////////////////////////////////////////////////////////////////////////////////////
DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, LLValue* newdim)
{
Logger::println("DtoResizeDynArray : %s", arrayType->toChars());
LOG_SCOPE;
Expand All @@ -516,7 +524,7 @@ DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)

LLSmallVector<LLValue*,4> args;
args.push_back(DtoTypeInfoOf(arrayType));
args.push_back(newdim->getRVal());
args.push_back(newdim);
args.push_back(DtoArrayLen(array));

LLValue* arrPtr = DtoArrayPtr(array);
Expand All @@ -528,7 +536,7 @@ DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim)
if (newptr->getType() != arrPtr->getType())
newptr = DtoBitCast(newptr, arrPtr->getType(), ".gc_mem");

return new DSliceValue(arrayType, newdim->getRVal(), newptr);
return new DSliceValue(arrayType, newdim, newptr);
}

//////////////////////////////////////////////////////////////////////////////////////////
Expand All @@ -544,7 +552,7 @@ void DtoCatAssignElement(Loc& loc, Type* arrayType, DValue* array, Expression* e
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arrayappendcT");
LLSmallVector<LLValue*,3> args;
args.push_back(DtoTypeInfoOf(arrayType));
args.push_back(DtoBitCast(array->getLVal(), getVoidPtrType()));
args.push_back(DtoBitCast(array->getLVal(), fn->getFunctionType()->getParamType(1)));
args.push_back(DtoBitCast(valueToAppend, getVoidPtrType()));

gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray");
Expand All @@ -565,7 +573,7 @@ DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp)
res = gIR->ir->CreateAdd(len1,len2,"tmp");

DValue* newdim = new DImValue(Type::tsize_t, res);
DSliceValue* slice = DtoResizeDynArray(arr->getType(), arr, newdim);
DSliceValue* slice = DtoResizeDynArray(arr->getType(), arr, newdim->getRVal());

src1 = slice->ptr;
src2 = DtoArrayPtr(e);
Expand Down Expand Up @@ -734,7 +742,7 @@ static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue
//////////////////////////////////////////////////////////////////////////////////////////
LLValue* DtoArrayEquals(Loc& loc, TOK op, DValue* l, DValue* r)
{
LLValue* res = DtoArrayEqCmp_impl(loc, "_adEq", l, r, true);
LLValue* res = DtoArrayEqCmp_impl(loc, _adEq, l, r, true);
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0), "tmp");
if (op == TOKnotequal)
res = gIR->ir->CreateNot(res, "tmp");
Expand Down Expand Up @@ -1007,6 +1015,12 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
LLConstant* nul = getNullPtr(ptr->getType());
rval = gIR->ir->CreateICmpNE(ptr, nul, "tmp");
}
else if (fromtype->nextOf()->ty == Tvoid) {
// TODO:
rval = DtoArrayPtr(u);
rval = DtoBitCast(rval, getPtrToType(tolltype));
rval = DtoLoad(rval);
}
else {
assert(0);
}
Expand Down
4 changes: 2 additions & 2 deletions gen/arrays.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);

void DtoArrayInit(Loc& loc, DValue* array, DValue* value);
void DtoArrayAssign(LLValue* l, LLValue* r);
void DtoSetArray(LLValue* arr, LLValue* dim, LLValue* ptr);
void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr);
void DtoSetArrayToNull(LLValue* v);

DSliceValue* DtoNewDynArray(Loc& loc, Type* arrayType, DValue* dim, bool defaultInit=true);
DSliceValue* DtoNewMulDimDynArray(Loc& loc, Type* arrayType, DValue** dims, size_t ndims, bool defaultInit=true);
DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, DValue* newdim);
DSliceValue* DtoResizeDynArray(Type* arrayType, DValue* array, llvm::Value* newdim);

void DtoCatAssignElement(Loc& loc, Type* type, DValue* arr, Expression* exp);
DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp);
Expand Down
16 changes: 8 additions & 8 deletions gen/classes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
// default allocator
else
{
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_allocclass");
llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, _d_allocclass);
LLConstant* ci = DtoBitCast(tc->sym->ir.irStruct->getClassInfoSymbol(), DtoType(ClassDeclaration::classinfo->type));
mem = gIR->CreateCallOrInvoke(fn, ci, ".newclass_gc_alloc").getInstruction();
mem = DtoBitCast(mem, DtoType(tc), ".newclass_gc");
Expand Down Expand Up @@ -686,7 +686,8 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
// void *defaultConstructor;
// version(D_Version2)
// const(MemberInfo[]) function(string) xgetMembers;
// TypeInfo typeinfo; // since dmd 1.045
// else
// TypeInfo typeinfo; // since dmd 1.045
// }

Logger::println("DtoDefineClassInfo(%s)", cd->toChars());
Expand All @@ -700,11 +701,7 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)

ClassDeclaration* cinfo = ClassDeclaration::classinfo;

#if DMDV2
if (cinfo->fields.dim != 13)
#else
if (cinfo->fields.dim != 12)
#endif
{
error("object.d ClassInfo class is incorrect");
fatal();
Expand Down Expand Up @@ -798,7 +795,8 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
#endif // GENERATE_OFFTI

// default constructor
b.push_funcptr(cd->defaultCtor, Type::tvoid->pointerTo());
VarDeclaration* defConstructorVar = (VarDeclaration*)cinfo->fields.data[10];
b.push_funcptr(cd->defaultCtor, defConstructorVar->type);

#if DMDV2

Expand All @@ -808,11 +806,13 @@ LLConstant* DtoDefineClassInfo(ClassDeclaration* cd)
// FIXME: fill it out!
b.push_null(xgetVar->type);

#endif
#else

// typeinfo - since 1.045
b.push_typeinfo(cd->type);

#endif

/*size_t n = inits.size();
for (size_t i=0; i<n; ++i)
{
Expand Down
2 changes: 1 addition & 1 deletion gen/declarations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ void VarDeclaration::codegen(Ir* p)
llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(this);
std::string _name(mangle());

llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module,_type,_isconst,_linkage,NULL,_name);
llvm::GlobalVariable* gvar = new llvm::GlobalVariable(*gIR->module,_type,_isconst,_linkage,NULL,_name,0,isThreadlocal());
this->ir.irGlobal->value = gvar;

// set the alignment
Expand Down
12 changes: 8 additions & 4 deletions gen/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ const llvm::FunctionType* DtoFunctionType(Type* type, Type* thistype, Type* nest
if (thistype)
{
bool toref = (thistype->toBasetype()->ty == Tstruct);
#if STRUCTTHISREF
fty.is_arg_this_ref = toref;
#endif
fty.arg_this = new IrFuncTyArg(thistype, toref);
lidx++;
}
Expand Down Expand Up @@ -475,8 +478,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
else // fall back to C, it should be the right thing to do
func->setCallingConv(llvm::CallingConv::C);

fdecl->ir.irFunc->func = func;

// parameter attributes
if (!fdecl->isIntrinsic()) {
set_param_attrs(f, func, fdecl);
Expand Down Expand Up @@ -607,7 +608,7 @@ void DtoDefineFunction(FuncDeclaration* fd)

Type* t = fd->type->toBasetype();
TypeFunction* f = (TypeFunction*)t;
assert(f->irtype);
// assert(f->irtype);

llvm::Function* func = fd->ir.irFunc->func;
const llvm::FunctionType* functype = func->getFunctionType();
Expand Down Expand Up @@ -665,7 +666,10 @@ void DtoDefineFunction(FuncDeclaration* fd)

LLValue* thismem = DtoRawAlloca(thisvar->getType(), 0, "this"); // FIXME: align?
DtoStore(thisvar, thismem);
irfunction->thisArg = thismem;
if (f->fty.is_arg_this_ref)
irfunction->thisArg = DtoLoad(thismem, "thisRef");
else
irfunction->thisArg = thismem;

assert(!fd->vthis->ir.irLocal);
fd->vthis->ir.irLocal = new IrLocal(fd->vthis);
Expand Down
15 changes: 5 additions & 10 deletions gen/llvmhelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,8 +378,8 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
}
// rhs is slice
else if (DSliceValue* s = rhs->isSlice()) {
assert(s->getType()->toBasetype() == lhs->getType()->toBasetype());
DtoSetArray(lhs->getLVal(),DtoArrayLen(s),DtoArrayPtr(s));
//assert(s->getType()->toBasetype() == lhs->getType()->toBasetype());
DtoSetArray(lhs,DtoArrayLen(s),DtoArrayPtr(s));
}
// null
else if (rhs->isNull()) {
Expand All @@ -391,7 +391,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
}
// some implicitly converting ref assignment
else {
DtoSetArray(lhs->getLVal(), DtoArrayLen(rhs), DtoArrayPtr(rhs));
DtoSetArray(lhs, DtoArrayLen(rhs), DtoArrayPtr(rhs));
}
}
else if (t->ty == Tsarray) {
Expand Down Expand Up @@ -1271,12 +1271,7 @@ void DtoAnnotation(const char* str)

LLConstant* DtoTypeInfoOf(Type* type, bool base)
{
#if DMDV2
// FIXME: this is probably wrong, but it makes druntime's genobj.d compile!
type = type->mutableOf()->merge(); // needed.. getTypeInfo does the same
#else
type = type->merge(); // needed.. getTypeInfo does the same
#endif
type = type->merge2(); // needed.. getTypeInfo does the same
type->getTypeInfo(NULL);
TypeInfoDeclaration* tidecl = type->vtinfo;
assert(tidecl);
Expand Down Expand Up @@ -1351,7 +1346,7 @@ bool mustDefineSymbol(Dsymbol* s)
if (fd->semanticRun < 4)
return false;

if (fd->isArrayOp)
if (fd->isArrayOp)
return true;

if (global.params.useAvailableExternally && fd->availableExternally) {
Expand Down
3 changes: 2 additions & 1 deletion gen/passes/GarbageCollect2Stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

using namespace llvm;

STATISTIC(NumGcToStack, "Number of calls promoted to constant-size allocas");
Expand Down Expand Up @@ -296,7 +297,7 @@ GarbageCollect2Stack::GarbageCollect2Stack()
KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT;
KnownFunctions["_d_newarrayvT"] = &NewArrayVT;
KnownFunctions["_d_newarrayT"] = &NewArrayT;
KnownFunctions["_d_allocclass"] = &AllocClass;
KnownFunctions[_d_allocclass] = &AllocClass;
}

static void RemoveCall(CallSite CS, const Analysis& A) {
Expand Down
4 changes: 3 additions & 1 deletion gen/passes/SimplifyDRuntimeCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "gen/runtime.h"

using namespace llvm;

STATISTIC(NumSimplified, "Number of runtime calls simplified");
Expand Down Expand Up @@ -332,7 +334,7 @@ void SimplifyDRuntimeCalls::InitOptimizations() {
Optimizations["_d_newarraymT"] = &Allocation;
Optimizations["_d_newarraymiT"] = &Allocation;
Optimizations["_d_newarraymvT"] = &Allocation;
Optimizations["_d_allocclass"] = &Allocation;
Optimizations[_d_allocclass] = &Allocation;
}


Expand Down
12 changes: 7 additions & 5 deletions gen/rttibuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

#include "ir/irstruct.h"

RTTIBuilder::RTTIBuilder(ClassDeclaration* base_class)
RTTIBuilder::RTTIBuilder(AggregateDeclaration* base_class)
{
// make sure the base typeinfo class has been processed
base_class->codegen(Type::sir);
Expand All @@ -23,10 +23,12 @@ RTTIBuilder::RTTIBuilder(ClassDeclaration* base_class)
baseir = base->ir.irStruct;
assert(baseir && "no IrStruct for TypeInfo base class");

// just start with adding the vtbl
inits.push_back(baseir->getVtblSymbol());
// and monitor
push_null_vp();
if (base->isClassDeclaration()) {
// just start with adding the vtbl
inits.push_back(baseir->getVtblSymbol());
// and monitor
push_null_vp();
}
}

void RTTIBuilder::push(llvm::Constant* C)
Expand Down
5 changes: 3 additions & 2 deletions gen/rttibuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,23 @@
#include "llvm/ADT/SmallVector.h"

struct ClassDeclaration;
struct AggregateDeclaration;
struct TypeClass;
struct Type;

struct IrStruct;

struct RTTIBuilder
{
ClassDeclaration* base;
AggregateDeclaration* base;
TypeClass* basetype;
IrStruct* baseir;

// 10 is enough for any D1 TypeInfo
// 14 is enough for any D1 ClassInfo
llvm::SmallVector<llvm::Constant*, 14> inits;

RTTIBuilder(ClassDeclaration* base_class);
RTTIBuilder(AggregateDeclaration* base_class);

void push(llvm::Constant* C);
void push_null(Type* T);
Expand Down
4 changes: 2 additions & 2 deletions gen/runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ static void LLVM_D_BuildRuntimeModule()

// Object _d_allocclass(ClassInfo ci)
{
llvm::StringRef fname("_d_allocclass");
llvm::StringRef fname(_d_allocclass);
std::vector<const LLType*> types;
types.push_back(classInfoTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
Expand Down Expand Up @@ -608,7 +608,7 @@ static void LLVM_D_BuildRuntimeModule()
// int _adEq(void[] a1, void[] a2, TypeInfo ti)
// int _adCmp(void[] a1, void[] a2, TypeInfo ti)
{
llvm::StringRef fname("_adEq");
llvm::StringRef fname(_adEq);
llvm::StringRef fname2("_adCmp");
std::vector<const LLType*> types;
types.push_back(rt_array(byteTy));
Expand Down
13 changes: 13 additions & 0 deletions gen/runtime.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#ifndef LDC_GEN_RUNTIME_H_
#define LDC_GEN_RUNTIME_H_

// D runtime support helpers

bool LLVM_D_InitRuntime();
Expand All @@ -6,3 +9,13 @@ void LLVM_D_FreeRuntime();
llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name);

llvm::GlobalVariable* LLVM_D_GetRuntimeGlobal(llvm::Module* target, const char* name);

#if DMDV1
#define _d_allocclass "_d_allocclass"
#define _adEq "_adEq"
#else
#define _d_allocclass "_d_newclass"
#define _adEq "_adEq2"
#endif

#endif // LDC_GEN_RUNTIME_H_
39 changes: 17 additions & 22 deletions gen/toir.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,13 @@ DValue* VarExp::toElem(IRState* p)
LLValue* tmp = DtoArrayLen(p->arrays.back());
return new DImValue(type, tmp);
}
// classinfo
else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
{
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
cid->cd->codegen(Type::sir);;
return new DVarValue(type, vd, cid->cd->ir.irStruct->getClassInfoSymbol());
}
// typeinfo
else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration())
{
Expand All @@ -133,13 +140,6 @@ DValue* VarExp::toElem(IRState* p)
m = p->ir->CreateBitCast(m, vartype, "tmp");
return new DImValue(type, m);
}
// classinfo
else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration())
{
Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars());
cid->cd->codegen(Type::sir);;
return new DVarValue(type, vd, cid->cd->ir.irStruct->getClassInfoSymbol());
}
// nested variable
#if DMDV2
else if (vd->nestedrefs.dim) {
Expand Down Expand Up @@ -552,7 +552,7 @@ DValue* AssignExp::toElem(IRState* p)
DValue* arr = ale->e1->toElem(p);
DVarValue arrval(ale->e1->type, arr->getLVal());
DValue* newlen = e2->toElem(p);
DSliceValue* slice = DtoResizeDynArray(arrval.getType(), &arrval, newlen);
DSliceValue* slice = DtoResizeDynArray(arrval.getType(), &arrval, newlen->getRVal());
DtoAssign(loc, &arrval, slice);
return newlen;
}
Expand Down Expand Up @@ -648,22 +648,16 @@ DValue* AddExp::toElem(IRState* p)

errorOnIllegalArrayOp(this, e1, e2);

if (e1type != e2type) {
if (e1type->ty == Tpointer) {
Logger::println("add to pointer");
if (DConstValue* cv = r->isConst()) {
if (cv->c->isNullValue()) {
Logger::println("is zero");
return new DImValue(type, l->getRVal());
}
if (e1type != e2type && e1type->ty == Tpointer) {
Logger::println("add to pointer");
if (DConstValue* cv = r->isConst()) {
if (cv->c->isNullValue()) {
Logger::println("is zero");
return new DImValue(type, l->getRVal());
}
LLValue* v = llvm::GetElementPtrInst::Create(l->getRVal(), r->getRVal(), "tmp", p->scopebb());
return new DImValue(type, v);
}
else if (t->iscomplex()) {
return DtoComplexAdd(loc, type, l, r);
}
assert(0);
LLValue* v = llvm::GetElementPtrInst::Create(l->getRVal(), r->getRVal(), "tmp", p->scopebb());
return new DImValue(type, v);
}
else if (t->iscomplex()) {
return DtoComplexAdd(loc, type, l, r);
Expand Down Expand Up @@ -1785,6 +1779,7 @@ DValue* AssertExp::toElem(IRState* p)
(invdecl = ((TypeStruct*)condty->nextOf())->sym->inv) != NULL)
{
Logger::print("calling struct invariant");
((TypeStruct*)condty->nextOf())->sym->codegen(Type::sir);
DFuncValue invfunc(invdecl, invdecl->ir.irFunc->func, cond->getRVal());
DtoCallFunction(loc, NULL, &invfunc, NULL);
}
Expand Down
4 changes: 4 additions & 0 deletions gen/tollvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,7 +896,11 @@ const LLStructType* DtoModuleReferenceType()
// add members
std::vector<const LLType*> types;
types.push_back(getPtrToType(opaque));
#if DMDV1
types.push_back(DtoType(Module::moduleinfo->type));
#else
types.push_back(DtoType(Module::moduleinfo->type->pointerTo()));
#endif

// resolve type
const LLStructType* st = LLStructType::get(gIR->context(), types);
Expand Down
21 changes: 14 additions & 7 deletions gen/toobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -635,8 +635,11 @@ void Module::genmoduleinfo()
// void* xgetMembers;
// void function() ictor;
//
// version(D_Version2)
// void*[4] reserved; // useless to us
// version(D_Version2) {
// void *sharedctor;
// void *shareddtor;
// uint index;
// void*[1] reserved;
// }

// resolve ModuleInfo
Expand All @@ -646,14 +649,18 @@ void Module::genmoduleinfo()
fatal();
}
// check for patch
else
{
#if DMDV2
else if (moduleinfo->fields.dim != 10)
unsigned sizeof_ModuleInfo = 16 * PTRSIZE;
#else
else if (moduleinfo->fields.dim != 9)
unsigned sizeof_ModuleInfo = 14 * PTRSIZE;
#endif
{
error("object.d ModuleInfo class is incorrect");
fatal();
if (sizeof_ModuleInfo != moduleinfo->structsize)
{
error("object.d ModuleInfo class is incorrect");
fatal();
}
}

// use the RTTIBuilder
Expand Down
111 changes: 82 additions & 29 deletions gen/typinf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,43 +112,52 @@ Expression *Type::getInternalTypeInfo(Scope *sc)

Expression *Type::getTypeInfo(Scope *sc)
{
Expression *e;
Type *t;

//printf("Type::getTypeInfo() %p, %s\n", this, toChars());
t = merge(); // do this since not all Type's are merge'd
if (!Type::typeinfo)
{
error(0, "TypeInfo not found. object.d may be incorrectly installed or corrupt, compile with -v switch");
fatal();
}

Expression *e = 0;
Type *t = merge2(); // do this since not all Type's are merge'd

if (!t->vtinfo)
{
#if DMDV2
if (t->isConst())
t->vtinfo = new TypeInfoConstDeclaration(t);
else if (t->isImmutable())
t->vtinfo = new TypeInfoInvariantDeclaration(t);
else
if (t->isShared())
t->vtinfo = new TypeInfoSharedDeclaration(t);
else if (t->isConst())
t->vtinfo = new TypeInfoConstDeclaration(t);
else if (t->isImmutable())
t->vtinfo = new TypeInfoInvariantDeclaration(t);
else if (t->isWild())
t->vtinfo = new TypeInfoWildDeclaration(t);
else
#endif
t->vtinfo = t->getTypeInfoDeclaration();
assert(t->vtinfo);

/* If this has a custom implementation in std/typeinfo, then
* do not generate a COMDAT for it.
*/
if (!t->builtinTypeInfo())
{ // Generate COMDAT
if (sc) // if in semantic() pass
{ // Find module that will go all the way to an object file
Module *m = sc->module->importedFrom;
m->members->push(t->vtinfo);
}
else // if in obj generation pass
{
t->vtinfo = t->getTypeInfoDeclaration();
assert(t->vtinfo);

/* If this has a custom implementation in std/typeinfo, then
* do not generate a COMDAT for it.
*/
if (!t->builtinTypeInfo())
{ // Generate COMDAT
if (sc) // if in semantic() pass
{ // Find module that will go all the way to an object file
Module *m = sc->module->importedFrom;
m->members->push(t->vtinfo);
}
else // if in obj generation pass
{
#if IN_DMD
t->vtinfo->toObjFile(0); // TODO: multiobj
t->vtinfo->toObjFile(0); // TODO: multiobj
#else
t->vtinfo->codegen(sir);
t->vtinfo->codegen(sir);
#endif
}
}
}
}
e = new VarExp(0, t->vtinfo);
e = e->addressOf(sc);
e->type = t->vtinfo->type; // do this so we don't get redundant dereference
Expand Down Expand Up @@ -239,7 +248,7 @@ int Type::builtinTypeInfo()
int TypeBasic::builtinTypeInfo()
{
#if DMDV2
return !mod;
return mod ? 0 : 1;
#else
return 1;
#endif
Expand All @@ -260,7 +269,7 @@ int TypeClass::builtinTypeInfo()
* claim it is built in so it isn't regenerated by each module.
*/
#if IN_DMD
return 1;
return mod ? 0 : 1;
#elif IN_LLVM
// FIXME if I enable this, the way LDC does typeinfo will cause a bunch
// of linker errors to missing class typeinfo definitions.
Expand Down Expand Up @@ -673,8 +682,24 @@ void TypeInfoStructDeclaration::llvmDefine()

/* ========================================================================= */

#if DMDV2
void TypeInfoClassDeclaration::codegen(Ir*i)
{

IrGlobal* irg = new IrGlobal(this);
ir.irGlobal = irg;
assert(tinfo->ty == Tclass);
TypeClass *tc = (TypeClass *)tinfo;
tc->sym->codegen(Type::sir); // make sure class is resolved
irg->value = tc->sym->ir.irStruct->getClassInfoSymbol();
}
#endif

void TypeInfoClassDeclaration::llvmDefine()
{
#if DMDV2
assert(0);
#endif
Logger::println("TypeInfoClassDeclaration::llvmDefine() %s", toChars());
LOG_SCOPE;

Expand Down Expand Up @@ -779,4 +804,32 @@ void TypeInfoInvariantDeclaration::llvmDefine()
b.finalize(ir.irGlobal);
}

/* ========================================================================= */

void TypeInfoSharedDeclaration::llvmDefine()
{
Logger::println("TypeInfoSharedDeclaration::llvmDefine() %s", toChars());
LOG_SCOPE;

RTTIBuilder b(Type::typeinfoshared);
// TypeInfo base
b.push_typeinfo(tinfo->unSharedOf()->merge());
// finish
b.finalize(ir.irGlobal);
}

/* ========================================================================= */

void TypeInfoWildDeclaration::llvmDefine()
{
Logger::println("TypeInfoWildDeclaration::llvmDefine() %s", toChars());
LOG_SCOPE;

RTTIBuilder b(Type::typeinfowild);
// TypeInfo base
b.push_typeinfo(tinfo->mutableOf()->merge());
// finish
b.finalize(ir.irGlobal);
}

#endif
3 changes: 2 additions & 1 deletion ir/irclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ LLGlobalVariable * IrStruct::getClassInfoSymbol()
// create the initZ symbol
std::string initname("_D");
initname.append(aggrdecl->mangle());

if (aggrdecl->isInterfaceDeclaration())
initname.append("11__InterfaceZ");
else
Expand All @@ -69,7 +70,7 @@ LLGlobalVariable * IrStruct::getClassInfoSymbol()

// classinfos cannot be constants since they're used a locks for synchronized
classInfo = new llvm::GlobalVariable(
*gIR->module, tc->getPA().get(), false, _linkage, NULL, initname);
*gIR->module, tc->getPA().get(), false, _linkage, NULL, initname);

#if USE_METADATA
// Generate some metadata on this ClassInfo if it's for a class.
Expand Down
6 changes: 5 additions & 1 deletion ir/irfuncty.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ struct IrFuncTy : IrBase
// range of normal parameters to reverse
bool reverseParams;

// arg_this is reference
bool is_arg_this_ref;

IrFuncTy()
: ret(NULL),
arg_sret(NULL),
Expand All @@ -86,7 +89,8 @@ struct IrFuncTy : IrBase
arg_arguments(NULL),
arg_argptr(NULL),
c_vararg(false),
reverseParams(false)
reverseParams(false),
is_arg_this_ref(false)
{}

void reset() {
Expand Down
46 changes: 33 additions & 13 deletions runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,30 @@ if(D_VERSION EQUAL 1)
# set paths to source files, or fill lists directly
set(RUNTIME_DC_DIR ${PROJECT_SOURCE_DIR}/internal)
set(RUNTIME_GC_DIR ${RUNTIME_DIR}/lib/gc/basic)
set(RUNTIME_INCLUDE ${RUNTIME_DC_DIR})
file(GLOB CORE_D ${RUNTIME_DIR}/lib/common/tango/core/*.d)
file(GLOB CORE_C ${RUNTIME_DIR}/lib/common/tango/stdc/*.c)
elseif(D_VERSION EQUAL 2)
set(RUNTIME_CC druntime-core)
set(RUNTIME_GC druntime-gc-basic)
set(RUNTIME_DC druntime-rt-ldc)
set(RUNTIME_AIO druntime-ldc)
set(RUNTIME_DC_DIR ${RUNTIME_DIR}/src/compiler/ldc)
set(RUNTIME_DC_DIR ${RUNTIME_DIR}/src/rt)
set(RUNTIME_GC_DIR ${RUNTIME_DIR}/src/gc)
set(RUNTIME_INCLUDE ${RUNTIME_DIR}/src)
file(GLOB CORE_D ${RUNTIME_DIR}/src/core/*.d )
file(GLOB CORE_D_SYNC ${RUNTIME_DIR}/src/core/sync/*.d )
if(UNIX)
file(GLOB CORE_D_SYS ${RUNTIME_DIR}/src/core/sys/posix/*.d)
elseif(WIN32)
file(GLOB CORE_D_SYS ${RUNTIME_DIR}/src/core/sys/windows/*.d)
elseif(APPLE)
file(GLOB CORE_D_SYS ${RUNTIME_DIR}/src/core/sys/osx/*.d)
endif(UNIX)
list(APPEND CORE_D ${CORE_D_SYNC} ${CORE_D_SYS} ${RUNTIME_DIR}/src/object_.d
${RUNTIME_DIR}/src/std/intrinsic.d
${RUNTIME_DIR}/src/core/stdc/stdarg.d
)
file(GLOB CORE_C ${RUNTIME_DIR}/src/core/stdc/*.c)
endif(D_VERSION EQUAL 1)

Expand Down Expand Up @@ -107,38 +121,44 @@ file(GLOB_RECURSE GC_D ${RUNTIME_GC_DIR}/*.d)
file(GLOB_RECURSE DCRT_D ${RUNTIME_DC_DIR}/*.d)
file(GLOB DCRT_C ${RUNTIME_DC_DIR}/*.c)

# compile d file into outdir, include incdir, and append names of generated .o and .bc to outlist_o and _bc
macro(dc INPUT_D OUTLIST_O OUTLIST_BC OUTDIR INCDIR MOREFLAGS)
get_filename_component(BASENAME ${INPUT_D} NAME_WE)
set(OUTPUT_O ${PROJECT_BINARY_DIR}/${OUTDIR}/${BASENAME}.o)
set(OUTPUT_BC ${PROJECT_BINARY_DIR}/${OUTDIR}/${BASENAME}.bc)
macro(dc INPUT_D OUTLIST_O OUTLIST_BC INCDIR MOREFLAGS PATH)
if ("${PATH}" STREQUAL "")
file(RELATIVE_PATH output ${RUNTIME_DIR} ${INPUT_D})
else ("${PATH}" STREQUAL "")
file(RELATIVE_PATH output ${PATH} ${INPUT_D})
endif ("${PATH}" STREQUAL "")
set(OUTPUT_O ${PROJECT_BINARY_DIR}/${output}.o)
set(OUTPUT_BC ${PROJECT_BINARY_DIR}/${output}.bc)
list(APPEND ${OUTLIST_O} ${OUTPUT_O})
list(APPEND ${OUTLIST_BC} ${OUTPUT_BC})

# Compile
add_custom_command(
OUTPUT
${OUTPUT_O}
${OUTPUT_BC}
COMMAND ${LDC_LOC} -c -I${INCDIR} -I${RUNTIME_GC_DIR} -output-bc ${INPUT_D} -of${OUTPUT_O} ${D_FLAGS} ${MOREFLAGS}
#${OUTPUT_BC}
COMMAND ${LDC_LOC} -c -I${INCDIR} -I${RUNTIME_GC_DIR} ${INPUT_D} -of${OUTPUT_O} ${D_FLAGS} ${MOREFLAGS}
DEPENDS ${LDC_LOC}
${INPUT_D}
${LDC_IMPORTS}
${PROJECT_BINARY_DIR}/../bin/${LDC_EXE}.conf
)
endmacro(dc)

# dc_dir include for core and gc only necessary with druntime
foreach(f ${CORE_D})
dc(${f} CORE_O CORE_BC core ${RUNTIME_DC_DIR} "")
dc(${f} CORE_O CORE_BC ${RUNTIME_INCLUDE} "" "")
endforeach(f)

foreach(f ${GC_D})
dc(${f} GC_O GC_BC gc "${RUNTIME_GC_DIR} ${RUNTIME_DC_DIR}" "-disable-invariants")
dc(${f} GC_O GC_BC ${RUNTIME_INCLUDE} "-disable-invariants" "")
endforeach(f)

foreach(f ${DCRT_D})
dc(${f} DCRT_O DCRT_BC dcrt ${RUNTIME_DC_DIR} "")
if(D_VERSION EQUAL 1)
dc(${f} DCRT_O DCRT_BC ${RUNTIME_INCLUDE} "" ${RUNTIME_DC_DIR})
else(D_VERSION EQUAL 1)
dc(${f} DCRT_O DCRT_BC ${RUNTIME_INCLUDE} "" "")
endif(D_VERSION EQUAL 1)
endforeach(f)

if(BUILD_SINGLE_LIB)
Expand Down