Added pragma(llvmdc, "string") for misc per-module compiler configuration, currently "string" can only be "verbose" which forces -vv for module it appears in.

Reimplemented support for nested functions/class using a new approach.
Added error on taking address of intrinsic.
Fixed problems with the ->syntaxCopy of TypeFunction delegate exp.
Removed DtoDType and replaced all uses with ->toBasetype() instead.
Removed unused inplace stuff.
Fixed a bunch of issues in the runtime unittests, not complete yet.
Added mini tests.
This commit is contained in:
Tomas Lindquist Olsen 2008-08-10 08:37:38 +02:00
parent b2d860374b
commit 9d7f16b967
39 changed files with 693 additions and 455 deletions

View file

@ -831,7 +831,7 @@ void PragmaDeclaration::semantic(Scope *sc)
// LLVMDC // LLVMDC
#if IN_LLVM #if IN_LLVM
// pragma(intrinsic, string) { funcdecl(s) } // pragma(intrinsic, "string") { funcdecl(s) }
else if (ident == Id::intrinsic) else if (ident == Id::intrinsic)
{ {
Expression* expr = (Expression *)args->data[0]; Expression* expr = (Expression *)args->data[0];
@ -920,6 +920,27 @@ void PragmaDeclaration::semantic(Scope *sc)
} }
llvm_internal = LLVMva_arg; llvm_internal = LLVMva_arg;
} }
// pragma(llvmdc, "string") { templdecl(s) }
else if (ident == Id::llvmdc)
{
Expression* expr = (Expression *)args->data[0];
expr = expr->semantic(sc);
if (!args || args->dim != 1 || !parseStringExp(expr, arg1str))
{
error("pragma llvmdc requires exactly 1 string literal parameter");
fatal();
}
else if (arg1str == "verbose")
{
sc->module->llvmForceLogging = true;
}
else
{
error("pragma llvmdc command '%s' invalid");
fatal();
}
}
#endif // LLVMDC #endif // LLVMDC

View file

@ -260,6 +260,10 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
{ {
//printf("rewriting e1 to %s's this\n", f->toChars()); //printf("rewriting e1 to %s's this\n", f->toChars());
n++; n++;
// LLVMDC seems dmd misses it sometimes here :/
f->vthis->nestedref = 1;
e1 = new VarExp(loc, f->vthis); e1 = new VarExp(loc, f->vthis);
} }
} }
@ -5983,6 +5987,13 @@ Expression *AddrExp::semantic(Scope *sc)
FuncDeclaration *f = dve->var->isFuncDeclaration(); FuncDeclaration *f = dve->var->isFuncDeclaration();
VarDeclaration *v = dve->var->isVarDeclaration(); VarDeclaration *v = dve->var->isVarDeclaration();
// LLVMDC
if (f && f->isIntrinsic())
{
error("cannot take the address of intrinsic function %s", e1->toChars());
return this;
}
if (f && f->isNested()) if (f && f->isNested())
{ Expression *e; { Expression *e;

View file

@ -176,6 +176,7 @@ Identifier *Id::vastart;
Identifier *Id::vacopy; Identifier *Id::vacopy;
Identifier *Id::vaend; Identifier *Id::vaend;
Identifier *Id::vaarg; Identifier *Id::vaarg;
Identifier *Id::llvmdc;
Identifier *Id::tohash; Identifier *Id::tohash;
Identifier *Id::tostring; Identifier *Id::tostring;
Identifier *Id::main; Identifier *Id::main;
@ -357,6 +358,7 @@ void Id::initialize()
vacopy = Lexer::idPool("va_copy"); vacopy = Lexer::idPool("va_copy");
vaend = Lexer::idPool("va_end"); vaend = Lexer::idPool("va_end");
vaarg = Lexer::idPool("va_arg"); vaarg = Lexer::idPool("va_arg");
llvmdc = Lexer::idPool("llvmdc");
tohash = Lexer::idPool("toHash"); tohash = Lexer::idPool("toHash");
tostring = Lexer::idPool("toString"); tostring = Lexer::idPool("toString");
main = Lexer::idPool("main"); main = Lexer::idPool("main");

View file

@ -178,6 +178,7 @@ struct Id
static Identifier *vacopy; static Identifier *vacopy;
static Identifier *vaend; static Identifier *vaend;
static Identifier *vaarg; static Identifier *vaarg;
static Identifier *llvmdc;
static Identifier *tohash; static Identifier *tohash;
static Identifier *tostring; static Identifier *tostring;
static Identifier *main; static Identifier *main;

View file

@ -223,6 +223,7 @@ Msgtable msgtable[] =
{ "vacopy", "va_copy" }, { "vacopy", "va_copy" },
{ "vaend", "va_end" }, { "vaend", "va_end" },
{ "vaarg", "va_arg" }, { "vaarg", "va_arg" },
{ "llvmdc" },
// For toHash/toString // For toHash/toString
{ "tohash", "toHash" }, { "tohash", "toHash" },

View file

@ -311,6 +311,7 @@ int main(int argc, char *argv[])
VersionCondition::addPredefinedGlobalIdent("LLVM"); VersionCondition::addPredefinedGlobalIdent("LLVM");
VersionCondition::addPredefinedGlobalIdent("LLVMDC"); VersionCondition::addPredefinedGlobalIdent("LLVMDC");
#endif #endif
#if _WIN32 #if _WIN32
VersionCondition::addPredefinedGlobalIdent("Windows"); VersionCondition::addPredefinedGlobalIdent("Windows");
VersionCondition::addPredefinedGlobalIdent("Win32"); VersionCondition::addPredefinedGlobalIdent("Win32");

View file

@ -162,6 +162,9 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
bcfile = new File(bcfilename); bcfile = new File(bcfilename);
llfile = new File(llfilename); llfile = new File(llfilename);
symfile = new File(symfilename); symfile = new File(symfilename);
// LLVMDC
llvmForceLogging = false;
} }
void Module::setDocfile() void Module::setDocfile()

View file

@ -66,8 +66,11 @@ struct Module : Package
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
File *srcfile; // input source file File *srcfile; // input source file
File *objfile; // output .obj file File *objfile; // output .obj file
// LLVMDC
File *bcfile; // output .bc file File *bcfile; // output .bc file
File *llfile; // output .ll file File *llfile; // output .ll file
File *hdrfile; // 'header' file File *hdrfile; // 'header' file
File *symfile; // output symbol file File *symfile; // output symbol file
File *docfile; // output documentation file File *docfile; // output documentation file
@ -171,6 +174,8 @@ struct Module : Package
// LLVMDC // LLVMDC
Module *isModule() { return this; } Module *isModule() { return this; }
bool llvmForceLogging;
}; };

View file

@ -2651,9 +2651,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;
this->llvmRetInPtr = false; this->retInPtr = false;
this->llvmUsesThis = false; this->usesThis = false;
this->llvmRetAttrs = 0; this->usesNest = false;
this->retAttrs = 0;
} }
Type *TypeFunction::syntaxCopy() Type *TypeFunction::syntaxCopy()
@ -2661,9 +2662,10 @@ Type *TypeFunction::syntaxCopy()
Type *treturn = next ? next->syntaxCopy() : NULL; Type *treturn = next ? next->syntaxCopy() : NULL;
Arguments *params = Argument::arraySyntaxCopy(parameters); Arguments *params = Argument::arraySyntaxCopy(parameters);
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage); TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
t->llvmRetInPtr = llvmRetInPtr; t->retInPtr = retInPtr;
t->llvmUsesThis = llvmUsesThis; t->usesThis = usesThis;
t->llvmRetAttrs = llvmRetAttrs; t->usesNest = usesNest;
t->retAttrs = retAttrs;
return t; return t;
} }
@ -3813,6 +3815,11 @@ char *TypeEnum::toChars()
return sym->toChars(); return sym->toChars();
} }
Type *TypeEnum::syntaxCopy()
{
return this;
}
Type *TypeEnum::semantic(Loc loc, Scope *sc) Type *TypeEnum::semantic(Loc loc, Scope *sc)
{ {
sym->semantic(sc); sym->semantic(sc);

View file

@ -441,9 +441,11 @@ struct TypeFunction : Type
unsigned totym(); unsigned totym();
bool llvmRetInPtr; // LLVMDC
bool llvmUsesThis; bool retInPtr;
unsigned llvmRetAttrs; bool usesThis;
bool usesNest;
unsigned retAttrs;
}; };
struct TypeDelegate : Type struct TypeDelegate : Type
@ -556,6 +558,7 @@ struct TypeEnum : Type
d_uns64 size(Loc loc); d_uns64 size(Loc loc);
unsigned alignsize(); unsigned alignsize();
char *toChars(); char *toChars();
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);

View file

@ -89,7 +89,7 @@ void DtoArrayAssign(LLValue* dst, LLValue* src)
const LLArrayType* arrty = isaArray(src->getType()->getContainedType(0)); const LLArrayType* arrty = isaArray(src->getType()->getContainedType(0));
if (!arrty) if (!arrty)
{ {
Logger::cout() << "invalid: " << *src << '\n'; std::cout << "invalid: " << *src << '\n';
assert(0); assert(0);
} }
const LLType* dstty = getPtrToType(arrty->getElementType()); const LLType* dstty = getPtrToType(arrty->getElementType());
@ -244,7 +244,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars()); Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* arrinittype = DtoDType(arrinit->type); Type* arrinittype = arrinit->type->toBasetype();
Type* t; Type* t;
integer_t tdim; integer_t tdim;
@ -530,8 +530,7 @@ DSliceValue* DtoCatAssignElement(DValue* array, Expression* exp)
DValue* e = exp->toElem(gIR); DValue* e = exp->toElem(gIR);
if (!e->inPlace()) DtoAssign(exp->loc, dptr, e);
DtoAssign(exp->loc, dptr, e);
return slice; return slice;
} }
@ -573,8 +572,8 @@ DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2)
Logger::println("DtoCatArrays"); Logger::println("DtoCatArrays");
LOG_SCOPE; LOG_SCOPE;
Type* t1 = DtoDType(exp1->type); Type* t1 = exp1->type->toBasetype();
Type* t2 = DtoDType(exp2->type); Type* t2 = exp2->type->toBasetype();
assert(t1->ty == Tarray || t1->ty == Tsarray); assert(t1->ty == Tarray || t1->ty == Tsarray);
assert(t2->ty == Tarray || t2->ty == Tsarray); assert(t2->ty == Tarray || t2->ty == Tsarray);
@ -614,8 +613,8 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
Logger::println("DtoCatArrayElement"); Logger::println("DtoCatArrayElement");
LOG_SCOPE; LOG_SCOPE;
Type* t1 = DtoDType(exp1->type); Type* t1 = exp1->type->toBasetype();
Type* t2 = DtoDType(exp2->type); Type* t2 = exp2->type->toBasetype();
DValue* e1 = exp1->toElem(gIR); DValue* e1 = exp1->toElem(gIR);
DValue* e2 = exp2->toElem(gIR); DValue* e2 = exp2->toElem(gIR);
@ -623,7 +622,7 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
llvm::Value *len1, *src1, *res; llvm::Value *len1, *src1, *res;
// handle prefix case, eg. int~int[] // handle prefix case, eg. int~int[]
if (t2->next && t1 == DtoDType(t2->next)) if (t2->next && t1 == t2->next->toBasetype())
{ {
len1 = DtoArrayLen(e2); len1 = DtoArrayLen(e2);
res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp"); res = gIR->ir->CreateAdd(len1,DtoConstSize_t(1),"tmp");
@ -683,8 +682,8 @@ static LLValue* DtoArrayEqCmp_impl(Loc& loc, const char* func, DValue* l, DValue
// cast static arrays to dynamic ones, this turns them into DSliceValues // cast static arrays to dynamic ones, this turns them into DSliceValues
Logger::println("casting to dynamic arrays"); Logger::println("casting to dynamic arrays");
Type* l_ty = DtoDType(l->getType()); Type* l_ty = l->getType()->toBasetype();
Type* r_ty = DtoDType(r->getType()); Type* r_ty = r->getType()->toBasetype();
assert(l_ty->next == r_ty->next); assert(l_ty->next == r_ty->next);
if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) { if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
Type* a_ty = l_ty->next->arrayOf(); Type* a_ty = l_ty->next->arrayOf();
@ -815,7 +814,7 @@ LLValue* DtoArrayCompare(Loc& loc, TOK op, DValue* l, DValue* r)
if (!skip) if (!skip)
{ {
Type* t = DtoDType(DtoDType(l->getType())->next); Type* t = l->getType()->toBasetype()->next->toBasetype();
if (t->ty == Tchar) if (t->ty == Tchar)
res = DtoArrayEqCmp_impl(loc, "_adCmpChar", l, r, false); res = DtoArrayEqCmp_impl(loc, "_adCmpChar", l, r, false);
else else
@ -900,7 +899,7 @@ LLValue* DtoArrayLen(DValue* v)
Logger::println("DtoArrayLen"); Logger::println("DtoArrayLen");
LOG_SCOPE; LOG_SCOPE;
Type* t = DtoDType(v->getType()); Type* t = v->getType()->toBasetype();
if (t->ty == Tarray) { if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) if (DSliceValue* s = v->isSlice())
return s->len; return s->len;
@ -926,7 +925,7 @@ LLValue* DtoArrayPtr(DValue* v)
Logger::println("DtoArrayPtr"); Logger::println("DtoArrayPtr");
LOG_SCOPE; LOG_SCOPE;
Type* t = DtoDType(v->getType()); Type* t = v->getType()->toBasetype();
if (t->ty == Tarray) { if (t->ty == Tarray) {
if (DSliceValue* s = v->isSlice()) if (DSliceValue* s = v->isSlice())
return s->ptr; return s->ptr;
@ -951,8 +950,8 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
const LLType* tolltype = DtoType(to); const LLType* tolltype = DtoType(to);
Type* totype = DtoDType(to); Type* totype = to->toBasetype();
Type* fromtype = DtoDType(u->getType()); Type* fromtype = u->getType()->toBasetype();
assert(fromtype->ty == Tarray || fromtype->ty == Tsarray); assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
LLValue* rval; LLValue* rval;

View file

@ -786,7 +786,7 @@ void DtoDefineClass(ClassDeclaration* cd)
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
DValue* DtoNewClass(TypeClass* tc, NewExp* newexp) DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
{ {
// resolve type // resolve type
DtoForceDeclareDsymbol(tc->sym); DtoForceDeclareDsymbol(tc->sym);
@ -829,25 +829,18 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
DtoStore(src, dst); DtoStore(src, dst);
} }
// set the context for nested classes // set the context for nested classes
else if (tc->sym->isNested()) else if (tc->sym->isNested() && tc->sym->vthis)
{ {
Logger::println("Resolving nested context"); Logger::println("Resolving nested context");
LOG_SCOPE; LOG_SCOPE;
// get context
LLValue* nest = DtoNestedContext(loc, tc->sym);
// store into right location
size_t idx = 2 + tc->sym->vthis->ir.irField->index; size_t idx = 2 + tc->sym->vthis->ir.irField->index;
LLValue* gep = DtoGEPi(mem,0,idx,"tmp"); LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
// this value might be zero if it was not necessary to generate it ...
LLValue* nest = gIR->func()->nestedVar;
// ... then revert to the this ptr if there is one
if (!nest)
nest = gIR->func()->thisVar;
// ... or just use zero, since it must be unused.
if (!nest)
nest = llvm::Constant::getNullValue(gep->getType()->getContainedType(0));
else
nest = DtoBitCast(nest, gep->getType()->getContainedType(0));
DtoStore(nest, gep);
} }
// call constructor // call constructor
@ -860,7 +853,7 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
} }
// return default constructed class // return default constructed class
return new DImValue(tc, mem, false); return new DImValue(tc, mem);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -912,7 +905,7 @@ DValue* DtoCastClass(DValue* val, Type* _to)
Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars()); Logger::println("DtoCastClass(%s, %s)", val->getType()->toChars(), _to->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* to = DtoDType(_to); Type* to = _to->toBasetype();
if (to->ty == Tpointer) { if (to->ty == Tpointer) {
const LLType* tolltype = DtoType(_to); const LLType* tolltype = DtoType(_to);
LLValue* rval = DtoBitCast(val->getRVal(), tolltype); LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
@ -922,7 +915,7 @@ DValue* DtoCastClass(DValue* val, Type* _to)
assert(to->ty == Tclass); assert(to->ty == Tclass);
TypeClass* tc = (TypeClass*)to; TypeClass* tc = (TypeClass*)to;
Type* from = DtoDType(val->getType()); Type* from = val->getType()->toBasetype();
TypeClass* fc = (TypeClass*)from; TypeClass* fc = (TypeClass*)from;
if (tc->sym->isInterfaceDeclaration()) { if (tc->sym->isInterfaceDeclaration()) {
@ -977,7 +970,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
assert(funcTy->getParamType(0) == obj->getType()); assert(funcTy->getParamType(0) == obj->getType());
// ClassInfo c // ClassInfo c
TypeClass* to = (TypeClass*)DtoDType(_to); TypeClass* to = (TypeClass*)_to->toBasetype();
DtoForceDeclareDsymbol(to->sym); DtoForceDeclareDsymbol(to->sym);
assert(to->sym->ir.irStruct->classInfo); assert(to->sym->ir.irStruct->classInfo);
LLValue* cinfo = to->sym->ir.irStruct->classInfo; LLValue* cinfo = to->sym->ir.irStruct->classInfo;
@ -1041,7 +1034,7 @@ DValue* DtoDynamicCastInterface(DValue* val, Type* _to)
ptr = DtoBitCast(ptr, funcTy->getParamType(0)); ptr = DtoBitCast(ptr, funcTy->getParamType(0));
// ClassInfo c // ClassInfo c
TypeClass* to = (TypeClass*)DtoDType(_to); TypeClass* to = (TypeClass*)_to->toBasetype();
DtoForceDeclareDsymbol(to->sym); DtoForceDeclareDsymbol(to->sym);
assert(to->sym->ir.irStruct->classInfo); assert(to->sym->ir.irStruct->classInfo);
LLValue* cinfo = to->sym->ir.irStruct->classInfo; LLValue* cinfo = to->sym->ir.irStruct->classInfo;
@ -1116,7 +1109,7 @@ LLValue* DtoIndexClass(LLValue* ptr, ClassDeclaration* cd, Type* t, unsigned os,
for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { for (IrStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) {
VarDeclaration* vd = i->second.var; VarDeclaration* vd = i->second.var;
assert(vd); assert(vd);
Type* vdtype = DtoDType(vd->type); Type* vdtype = vd->type->toBasetype();
//Logger::println("found %u type %s", vd->offset, vdtype->toChars()); //Logger::println("found %u type %s", vd->offset, vdtype->toChars());
assert(vd->ir.irField->index >= 0); assert(vd->ir.irField->index >= 0);
if (os == vd->offset && vdtype->toBasetype() == t->toBasetype()) { if (os == vd->offset && vdtype->toBasetype() == t->toBasetype()) {
@ -1173,7 +1166,7 @@ LLValue* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl)
{ {
assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())); assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual()));
assert(fdecl->vtblIndex > 0); assert(fdecl->vtblIndex > 0);
assert(DtoDType(inst->getType())->ty == Tclass); assert(inst->getType()->toBasetype()->ty == Tclass);
LLValue* vthis = inst->getRVal(); LLValue* vthis = inst->getRVal();
Logger::cout() << "vthis: " << *vthis << '\n'; Logger::cout() << "vthis: " << *vthis << '\n';

View file

@ -26,7 +26,7 @@ void DtoDefineClass(ClassDeclaration* cd);
void DtoDeclareClassInfo(ClassDeclaration* cd); void DtoDeclareClassInfo(ClassDeclaration* cd);
void DtoDefineClassInfo(ClassDeclaration* cd); void DtoDefineClassInfo(ClassDeclaration* cd);
DValue* DtoNewClass(TypeClass* type, NewExp* newexp); DValue* DtoNewClass(Loc loc, TypeClass* type, NewExp* newexp);
void DtoInitClass(TypeClass* tc, LLValue* dst); void DtoInitClass(TypeClass* tc, LLValue* dst);
DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, LLValue* mem); DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, LLValue* mem);
void DtoFinalizeClass(LLValue* inst); void DtoFinalizeClass(LLValue* inst);

View file

@ -13,7 +13,7 @@
const llvm::StructType* DtoComplexType(Type* type) const llvm::StructType* DtoComplexType(Type* type)
{ {
Type* t = DtoDType(type); Type* t = type->toBasetype();
const LLType* base = DtoComplexBaseType(t); const LLType* base = DtoComplexBaseType(t);
@ -26,7 +26,7 @@ const llvm::StructType* DtoComplexType(Type* type)
const LLType* DtoComplexBaseType(Type* t) const LLType* DtoComplexBaseType(Type* t)
{ {
TY ty = DtoDType(t)->ty; TY ty = t->toBasetype()->ty;
const LLType* base; const LLType* base;
if (ty == Tcomplex32) { if (ty == Tcomplex32) {
return LLType::FloatTy; return LLType::FloatTy;
@ -62,7 +62,7 @@ LLConstant* DtoConstComplex(Type* ty, LLConstant* re, LLConstant* im)
LLConstant* DtoConstComplex(Type* _ty, long double re, long double im) LLConstant* DtoConstComplex(Type* _ty, long double re, long double im)
{ {
TY ty = DtoDType(_ty)->ty; TY ty = _ty->toBasetype()->ty;
llvm::ConstantFP* fre; llvm::ConstantFP* fre;
llvm::ConstantFP* fim; llvm::ConstantFP* fim;
@ -106,7 +106,7 @@ LLValue* DtoImagPart(DValue* val)
DValue* DtoComplex(Loc& loc, Type* to, DValue* val) DValue* DtoComplex(Loc& loc, Type* to, DValue* val)
{ {
Type* t = DtoDType(val->getType()); Type* t = val->getType()->toBasetype();
if (val->isComplex() || t->iscomplex()) { if (val->isComplex() || t->iscomplex()) {
return DtoCastComplex(loc, val, to); return DtoCastComplex(loc, val, to);
@ -448,7 +448,7 @@ LLValue* DtoComplexEquals(Loc& loc, TOK op, DValue* lhs, DValue* rhs)
DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to) DValue* DtoCastComplex(Loc& loc, DValue* val, Type* _to)
{ {
Type* to = DtoDType(_to); Type* to = _to->toBasetype();
Type* vty = val->getType(); Type* vty = val->getType();
if (to->iscomplex()) { if (to->iscomplex()) {
if (vty->size() == to->size()) if (vty->size() == to->size())

View file

@ -54,8 +54,6 @@ struct DValue : Object
virtual DComplexValue* isComplex() { return NULL; } virtual DComplexValue* isComplex() { return NULL; }
virtual DLRValue* isLRValue() { return NULL; } virtual DLRValue* isLRValue() { return NULL; }
virtual bool inPlace() { return false; }
protected: protected:
DValue() {} DValue() {}
DValue(const DValue&) { } DValue(const DValue&) { }
@ -67,16 +65,13 @@ struct DImValue : DValue
{ {
Type* type; Type* type;
LLValue* val; LLValue* val;
bool inplace;
DImValue(Type* t, LLValue* v, bool in_place = false) { type = t; val = v; inplace = in_place; } DImValue(Type* t, LLValue* v) : type(t), val(v) { }
virtual LLValue* getRVal() { assert(val); return val; } virtual LLValue* getRVal() { assert(val); return val; }
virtual Type*& getType() { assert(type); return type; } virtual Type*& getType() { assert(type); return type; }
virtual DImValue* isIm() { return this; } virtual DImValue* isIm() { return this; }
virtual bool inPlace() { return inplace; }
}; };
// constant d-value // constant d-value

View file

@ -8,5 +8,6 @@ enum
LLVMva_start, LLVMva_start,
LLVMva_copy, LLVMva_copy,
LLVMva_end, LLVMva_end,
LLVMva_arg LLVMva_arg,
LLVMllvmdc
}; };

View file

@ -21,7 +21,7 @@
#include "gen/classes.h" #include "gen/classes.h"
#include "gen/dvalue.h" #include "gen/dvalue.h"
const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bool ismain) const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, const LLType* nesttype, bool ismain)
{ {
assert(type->ty == Tfunction); assert(type->ty == Tfunction);
TypeFunction* f = (TypeFunction*)type; TypeFunction* f = (TypeFunction*)type;
@ -46,6 +46,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
Type* rt = f->next; Type* rt = f->next;
bool retinptr = false; bool retinptr = false;
bool usesthis = false; bool usesthis = false;
bool usesnest = false;
// parameter types // parameter types
std::vector<const LLType*> paramvec; std::vector<const LLType*> paramvec;
@ -66,7 +67,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
if (DtoIsReturnedInArg(rt)) { if (DtoIsReturnedInArg(rt)) {
rettype = getPtrToType(DtoType(rt)); rettype = getPtrToType(DtoType(rt));
actualRettype = LLType::VoidTy; actualRettype = LLType::VoidTy;
f->llvmRetInPtr = retinptr = true; f->retInPtr = retinptr = true;
} }
else { else {
rettype = DtoType(rt); rettype = DtoType(rt);
@ -75,7 +76,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
if (unsigned ea = DtoShouldExtend(rt)) if (unsigned ea = DtoShouldExtend(rt))
{ {
f->llvmRetAttrs |= ea; f->retAttrs |= ea;
} }
} }
@ -88,6 +89,10 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
paramvec.push_back(thistype); paramvec.push_back(thistype);
usesthis = true; usesthis = true;
} }
else if (nesttype) {
paramvec.push_back(nesttype);
usesnest = true;
}
if (typesafeVararg) { if (typesafeVararg) {
ClassDeclaration* ti = Type::typeinfo; ClassDeclaration* ti = Type::typeinfo;
@ -111,7 +116,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
for (int i=0; i < n; ++i) { for (int i=0; i < n; ++i) {
Argument* arg = Argument::getNth(f->parameters, i); Argument* arg = Argument::getNth(f->parameters, i);
// ensure scalar // ensure scalar
Type* argT = DtoDType(arg->type); Type* argT = arg->type->toBasetype();
assert(argT); assert(argT);
bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout)); bool refOrOut = ((arg->storageClass & STCref) || (arg->storageClass & STCout));
@ -166,8 +171,9 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs; bool isvararg = !(typesafeVararg || arrayVararg) && f->varargs;
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg); llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
f->llvmRetInPtr = retinptr; f->retInPtr = retinptr;
f->llvmUsesThis = usesthis; f->usesThis = usesthis;
f->usesNest = usesnest;
f->ir.type = new llvm::PATypeHolder(functype); f->ir.type = new llvm::PATypeHolder(functype);
@ -210,7 +216,9 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
if (fdecl->type->ir.type != 0) if (fdecl->type->ir.type != 0)
return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get()); return llvm::cast<llvm::FunctionType>(fdecl->type->ir.type->get());
const LLType* thisty = NULL; const LLType* thisty = 0;
const LLType* nestty = 0;
if (fdecl->needThis()) { if (fdecl->needThis()) {
if (AggregateDeclaration* ad = fdecl->isMember2()) { if (AggregateDeclaration* ad = fdecl->isMember2()) {
Logger::println("isMember = this is: %s", ad->type->toChars()); Logger::println("isMember = this is: %s", ad->type->toChars());
@ -225,10 +233,10 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
} }
} }
else if (fdecl->isNested()) { else if (fdecl->isNested()) {
thisty = getPtrToType(LLType::Int8Ty); nestty = getPtrToType(LLType::Int8Ty);
} }
const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain()); const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, nestty, fdecl->isMain());
return functype; return functype;
} }
@ -237,7 +245,7 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl) static llvm::Function* DtoDeclareVaFunction(FuncDeclaration* fdecl)
{ {
TypeFunction* f = (TypeFunction*)DtoDType(fdecl->type); TypeFunction* f = (TypeFunction*)fdecl->type->toBasetype();
const llvm::FunctionType* fty = DtoVaFunctionType(fdecl); const llvm::FunctionType* fty = DtoVaFunctionType(fdecl);
llvm::Function* func = 0; llvm::Function* func = 0;
@ -306,8 +314,9 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl) static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl)
{ {
int llidx = 1; int llidx = 1;
if (f->llvmRetInPtr) ++llidx; if (f->retInPtr) ++llidx;
if (f->llvmUsesThis) ++llidx; if (f->usesThis) ++llidx;
else if (f->usesNest) ++llidx;
if (f->linkage == LINKd && f->varargs == 1) if (f->linkage == LINKd && f->varargs == 1)
llidx += 2; llidx += 2;
@ -318,15 +327,15 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
llvm::ParamAttrsWithIndex PAWI; llvm::ParamAttrsWithIndex PAWI;
// set return value attrs if any // set return value attrs if any
if (f->llvmRetAttrs) if (f->retAttrs)
{ {
PAWI.Index = 0; PAWI.Index = 0;
PAWI.Attrs = f->llvmRetAttrs; PAWI.Attrs = f->retAttrs;
attrs.push_back(PAWI); attrs.push_back(PAWI);
} }
// set sret param // set sret param
if (f->llvmRetInPtr) if (f->retInPtr)
{ {
PAWI.Index = 1; PAWI.Index = 1;
PAWI.Attrs = llvm::ParamAttr::StructRet; PAWI.Attrs = llvm::ParamAttr::StructRet;
@ -378,7 +387,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
} }
// get TypeFunction* // get TypeFunction*
Type* t = DtoDType(fdecl->type); Type* t = fdecl->type->toBasetype();
TypeFunction* f = (TypeFunction*)t; TypeFunction* f = (TypeFunction*)t;
bool declareOnly = false; bool declareOnly = false;
@ -417,8 +426,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name); llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
if (!func) if (!func)
func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module); func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module);
else
assert(func->getFunctionType() == functype);
// add func to IRFunc // add func to IRFunc
fdecl->ir.irFunc->func = func; fdecl->ir.irFunc->func = func;
@ -457,15 +464,22 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
// name parameters // name parameters
llvm::Function::arg_iterator iarg = func->arg_begin(); llvm::Function::arg_iterator iarg = func->arg_begin();
int k = 0; int k = 0;
if (f->llvmRetInPtr) { if (f->retInPtr) {
iarg->setName("retval"); iarg->setName(".sretarg");
fdecl->ir.irFunc->retArg = iarg; fdecl->ir.irFunc->retArg = iarg;
++iarg; ++iarg;
} }
if (f->llvmUsesThis) {
iarg->setName(fdecl->isNested()?".context":"this"); if (f->usesThis) {
fdecl->ir.irFunc->thisVar = iarg; iarg->setName("this");
assert(fdecl->ir.irFunc->thisVar); fdecl->ir.irFunc->thisArg = iarg;
assert(fdecl->ir.irFunc->thisArg);
++iarg;
}
else if (f->usesNest) {
iarg->setName(".nest");
fdecl->ir.irFunc->nestArg = iarg;
assert(fdecl->ir.irFunc->nestArg);
++iarg; ++iarg;
} }
@ -520,13 +534,19 @@ void DtoDefineFunc(FuncDeclaration* fd)
Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars()); Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars());
LOG_SCOPE; LOG_SCOPE;
// warn about naked
if (fd->naked)
{
warning("%s: naked is currently ignored", fd->locToChars());
}
// debug info // debug info
if (global.params.symdebug) { if (global.params.symdebug) {
Module* mo = fd->getModule(); Module* mo = fd->getModule();
fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd); fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd);
} }
Type* t = DtoDType(fd->type); Type* t = fd->type->toBasetype();
TypeFunction* f = (TypeFunction*)t; TypeFunction* f = (TypeFunction*)t;
assert(f->ir.type); assert(f->ir.type);
@ -568,26 +588,32 @@ void DtoDefineFunc(FuncDeclaration* fd)
// debug info - after all allocas, but before any llvm.dbg.declare etc // debug info - after all allocas, but before any llvm.dbg.declare etc
if (global.params.symdebug) DtoDwarfFuncStart(fd); if (global.params.symdebug) DtoDwarfFuncStart(fd);
// need result variable? (not nested) // need result variable?
if (fd->vresult && !fd->vresult->nestedref) { if (fd->vresult) {
Logger::println("non-nested vresult value"); Logger::println("vresult value");
fd->vresult->ir.irLocal = new IrLocal(fd->vresult); fd->vresult->ir.irLocal = new IrLocal(fd->vresult);
fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type),"function_vresult"); fd->vresult->ir.irLocal->value = DtoAlloca(DtoType(fd->vresult->type), "function_vresult");
} }
// give the 'this' argument storage and debug info // give the 'this' argument storage and debug info
// only if not referenced by nested functions if (f->usesThis)
if (fd->needThis() && !fd->vthis->nestedref)
{ {
LLValue* thisvar = irfunction->thisVar; LLValue* thisvar = irfunction->thisArg;
assert(thisvar); assert(thisvar);
LLValue* thismem = DtoAlloca(thisvar->getType(), ".newthis"); LLValue* thismem = DtoAlloca(thisvar->getType(), ".this");
DtoStore(thisvar, thismem); DtoStore(thisvar, thismem);
irfunction->thisVar = thismem; irfunction->thisArg = thismem;
assert(!fd->vthis->ir.irLocal);
fd->vthis->ir.irLocal = new IrLocal(fd->vthis);
fd->vthis->ir.irLocal->value = thismem;
if (global.params.symdebug) if (global.params.symdebug)
DtoDwarfLocalVariable(thismem, fd->vthis); DtoDwarfLocalVariable(thismem, fd->vthis);
if (fd->vthis->nestedref)
fd->nestedVars.insert(fd->vthis);
} }
// give arguments storage // give arguments storage
@ -600,13 +626,16 @@ void DtoDefineFunc(FuncDeclaration* fd)
Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i]; Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i];
VarDeclaration* vd = argsym->isVarDeclaration(); VarDeclaration* vd = argsym->isVarDeclaration();
assert(vd); assert(vd);
if (vd->nestedref)
fd->nestedVars.insert(vd);
IrLocal* irloc = vd->ir.irLocal; IrLocal* irloc = vd->ir.irLocal;
assert(irloc); assert(irloc);
bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy); bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy);
if (vd->nestedref || refoutlazy) if (refoutlazy)
{ {
continue; continue;
} }
@ -625,66 +654,99 @@ void DtoDefineFunc(FuncDeclaration* fd)
} }
} }
LLValue* parentNested = NULL;
if (FuncDeclaration* fd2 = fd->toParent2()->isFuncDeclaration()) {
if (!fd->isStatic()) // huh?
parentNested = fd2->ir.irFunc->nestedVar;
}
// need result variable? (nested) // need result variable? (nested)
if (fd->vresult && fd->vresult->nestedref) { if (fd->vresult && fd->vresult->nestedref) {
Logger::println("nested vresult value: %s", fd->vresult->toChars()); Logger::println("nested vresult value: %s", fd->vresult->toChars());
fd->nestedVars.insert(fd->vresult); fd->nestedVars.insert(fd->vresult);
} }
// construct nested variables struct // construct nested variables array
if (!fd->nestedVars.empty() || parentNested) { if (!fd->nestedVars.empty())
std::vector<const LLType*> nestTypes; {
int j = 0; Logger::println("has nested frame");
if (parentNested) { // start with add all enclosing parent frames
nestTypes.push_back(parentNested->getType()); int nparelems = 0;
j++; Dsymbol* par = fd->toParent2();
while (par)
{
if (FuncDeclaration* parfd = par->isFuncDeclaration())
{
nparelems += parfd->nestedVars.size();
}
else if (ClassDeclaration* parcd = par->isClassDeclaration())
{
// nothing needed
}
else
{
break;
}
par = par->toParent2();
} }
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) { int nelems = fd->nestedVars.size() + nparelems;
// make array type for nested vars
const LLType* nestedVarsTy = LLArrayType::get(getVoidPtrType(), nelems);
// alloca it
LLValue* nestedVars = DtoAlloca(nestedVarsTy, ".nested_vars");
// copy parent frame into beginning
if (nparelems)
{
LLValue* src = irfunction->nestArg;
if (!src)
{
assert(irfunction->thisArg);
assert(fd->isMember2());
LLValue* thisval = DtoLoad(irfunction->thisArg);
ClassDeclaration* cd = fd->isMember2()->isClassDeclaration();
assert(cd);
assert(cd->vthis);
src = DtoLoad(DtoGEPi(thisval, 0,2+cd->vthis->ir.irField->index, ".vthis"));
}
DtoMemCpy(nestedVars, src, DtoConstSize_t(nparelems*PTRSIZE));
}
// store in IrFunction
irfunction->nestedVar = nestedVars;
// go through all nested vars and assign indices
int idx = nparelems;
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i)
{
VarDeclaration* vd = *i; VarDeclaration* vd = *i;
Logger::println("referenced nested variable %s", vd->toChars());
if (!vd->ir.irLocal) if (!vd->ir.irLocal)
vd->ir.irLocal = new IrLocal(vd); vd->ir.irLocal = new IrLocal(vd);
vd->ir.irLocal->nestedIndex = j++;
if (vd->isParameter()) { if (vd->isParameter())
if (!vd->ir.irLocal->value) { {
assert(vd == fd->vthis); Logger::println("nested param: %s", vd->toChars());
vd->ir.irLocal->value = fd->ir.irFunc->thisVar; LLValue* gep = DtoGEPi(nestedVars, 0, idx);
} LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
assert(vd->ir.irLocal->value); DtoStore(val, gep);
nestTypes.push_back(vd->ir.irLocal->value->getType());
} }
else { else
nestTypes.push_back(DtoType(vd->type)); {
Logger::println("nested var: %s", vd->toChars());
} }
vd->ir.irLocal->nestedIndex = idx++;
} }
const llvm::StructType* nestSType = llvm::StructType::get(nestTypes);
Logger::cout() << "nested var struct has type:" << *nestSType << '\n'; // fixup nested result variable
fd->ir.irFunc->nestedVar = DtoAlloca(nestSType,"nestedvars"); if (fd->vresult && fd->vresult->nestedref) {
if (parentNested) { Logger::println("nested vresult value: %s", fd->vresult->toChars());
assert(fd->ir.irFunc->thisVar); LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
LLValue* ptr = gIR->ir->CreateBitCast(fd->ir.irFunc->thisVar, parentNested->getType(), "tmp"); LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
gIR->ir->CreateStore(ptr, DtoGEPi(fd->ir.irFunc->nestedVar, 0,0, "tmp")); DtoStore(val, gep);
}
for (std::set<VarDeclaration*>::iterator i=fd->nestedVars.begin(); i!=fd->nestedVars.end(); ++i) {
VarDeclaration* vd = *i;
if (vd->isParameter()) {
assert(vd->ir.irLocal);
gIR->ir->CreateStore(vd->ir.irLocal->value, DtoGEPi(fd->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex, "tmp"));
vd->ir.irLocal->value = fd->ir.irFunc->nestedVar;
}
} }
} }
// copy _argptr to a memory location // copy _argptr to a memory location
if (f->linkage == LINKd && f->varargs == 1) if (f->linkage == LINKd && f->varargs == 1)
{ {
LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptrmem"); LLValue* argptrmem = DtoAlloca(fd->ir.irFunc->_argptr->getType(), "_argptr_mem");
new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb()); new llvm::StoreInst(fd->ir.irFunc->_argptr, argptrmem, gIR->scopebb());
fd->ir.irFunc->_argptr = argptrmem; fd->ir.irFunc->_argptr = argptrmem;
} }
@ -784,14 +846,14 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout))) if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout)))
{ {
if (arg->isVar() || arg->isLRValue()) if (arg->isVar() || arg->isLRValue())
arg = new DImValue(argexp->type, arg->getLVal(), false); arg = new DImValue(argexp->type, arg->getLVal());
else else
arg = new DImValue(argexp->type, arg->getRVal(), false); arg = new DImValue(argexp->type, arg->getRVal());
} }
// byval arg, but expr has no storage yet // byval arg, but expr has no storage yet
else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull())) else if (DtoIsPassedByRef(argexp->type) && (arg->isSlice() || arg->isComplex() || arg->isNull()))
{ {
LLValue* alloc = DtoAlloca(DtoType(argexp->type), "tmpparam"); LLValue* alloc = DtoAlloca(DtoType(argexp->type), ".tmp_arg");
DVarValue* vv = new DVarValue(argexp->type, alloc, true); DVarValue* vv = new DVarValue(argexp->type, alloc, true);
DtoAssign(argexp->loc, vv, arg); DtoAssign(argexp->loc, vv, arg);
arg = vv; arg = vv;

View file

@ -1,7 +1,7 @@
#ifndef LLVMDC_GEN_FUNCTIONS_H #ifndef LLVMDC_GEN_FUNCTIONS_H
#define LLVMDC_GEN_FUNCTIONS_H #define LLVMDC_GEN_FUNCTIONS_H
const llvm::FunctionType* DtoFunctionType(Type* t, const LLType* thistype, bool ismain = false); const llvm::FunctionType* DtoFunctionType(Type* t, const LLType* thistype, const LLType* nesttype, bool ismain = false);
const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl); const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl); const llvm::FunctionType* DtoBaseFunctionType(FuncDeclaration* fdecl);

View file

@ -349,154 +349,70 @@ void DtoLeaveMonitor(LLValue* v)
// NESTED VARIABLE HELPERS // NESTED VARIABLE HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/ ////////////////////////////////////////////////////////////////////////////////////////*/
/* DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
got:
context pointer of 'this' function
declaration for target context's function
want:
context pointer of target function in call chain
*/
static LLValue* dive_into_nested(Dsymbol* from, LLValue* val)
{ {
from = from->toParent2(); Dsymbol* vdparent = vd->toParent2();
assert(vdparent);
// parent is a function
if (FuncDeclaration* f = from->isFuncDeclaration()) IrFunction* irfunc = gIR->func();
// is the nested variable in this scope?
if (vdparent == irfunc->decl)
{ {
IrFunction* irfunc = f->ir.irFunc; LLValue* val = vd->ir.getIrValue();
// parent has nested var struct return new DVarValue(astype, vd, val, true);
if (irfunc->nestedVar)
{
return DtoBitCast(val, irfunc->nestedVar->getType());
}
// parent has this argument
else if (irfunc->thisVar)
{
return DtoBitCast(val, irfunc->thisVar->getType()->getContainedType(0));
}
// none of the above, means no context is required, dummy.
else
{
return getNullPtr(getVoidPtrType());
}
} }
// parent is a class
else if (ClassDeclaration* c = from->isClassDeclaration()) // get it from the nested context
LLValue* ctx = 0;
if (irfunc->decl->isMember2())
{ {
return DtoBitCast(DtoLoad(val), DtoType(c->type)); ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
LLValue* val = DtoLoad(irfunc->thisArg);
ctx = DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
} }
// parent is not valid
else else
{ ctx = irfunc->nestArg;
assert(0 && "!(class|function)"); assert(ctx);
}
assert(vd->ir.irLocal);
LLValue* val = DtoBitCast(ctx, getPtrToType(getVoidPtrType()));
val = DtoGEPi1(val, vd->ir.irLocal->nestedIndex);
val = DtoLoad(val);
assert(vd->ir.irLocal->value);
val = DtoBitCast(val, vd->ir.irLocal->value->getType(), vd->toChars());
return new DVarValue(astype, vd, val, true);
} }
LLValue* DtoNestedContext(FuncDeclaration* func) LLValue* DtoNestedContext(Loc loc, Dsymbol* sym)
{ {
Logger::println("listing context frame list for funcdecl '%s'", func->toPrettyChars()); Logger::println("DtoNestedContext for %s", sym->toPrettyChars());
LOG_SCOPE; LOG_SCOPE;
int level = 0;
IrFunction* irfunc = gIR->func(); IrFunction* irfunc = gIR->func();
Dsymbol* current = irfunc->decl;
if (irfunc->nestedVar)
// this context ?
if (current == func)
{
return irfunc->nestedVar; return irfunc->nestedVar;
} else if (irfunc->nestArg)
return irfunc->nestArg;
// otherwise use the context argument else if (irfunc->thisArg)
LLValue* val = dive_into_nested(current, irfunc->thisVar);
current = current->toParent2();
assert(val);
for (;;)
{ {
Logger::cout() << "context: " << *val << '\n'; ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind()); assert(cd);
if (FuncDeclaration* f = current->isFuncDeclaration()) if (!cd->vthis)
{ return getNullPtr(getVoidPtrType());
if (f == func) LLValue* val = DtoLoad(irfunc->thisArg);
{ return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
Logger::println("-> found <-");
Logger::cout() << "-> val: " << *val << '\n';
return val;
}
else
{
val = DtoLoad(DtoGEPi(val,0,0));
}
}
else if (ClassDeclaration* c = current->isClassDeclaration())
{
val = DtoLoad(DtoGEPi(val, 0, 2+c->vthis->ir.irField->index));
val = dive_into_nested(current, val);
}
else
{
Logger::cout() << "val: " << *val << '\n';
assert(0 && "!(class|function)");
}
current = current->toParent2();
++level;
} }
else
assert(0);
return val;
}
DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd)
{
IrFunction* irfunc = gIR->func();
// var parent (the scope we're looking for)
Dsymbol* varParent = vd->toParent2();
// on level 0
if (varParent == irfunc->decl)
{ {
LLValue* nest = irfunc->nestedVar; if (irfunc->decl->isStatic())
LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp"); {
// references must be loaded to get the variable address irfunc->decl->error("is static and cannot access nested %s %s", sym->kind(), sym->toChars());
if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) fatal();
v = DtoLoad(v); }
return new DVarValue(astype, vd, v, true); return getNullPtr(getVoidPtrType());
} }
// on level n != 0
FuncDeclaration* varFunc = varParent->isFuncDeclaration();
assert(varFunc);
// get context of variable
LLValue* ctx = DtoNestedContext(varFunc);
// if no local var, it's the context itself (class this)
if (!vd->ir.irLocal)
return new DImValue(astype, ctx);
// extract variable
IrLocal* local = vd->ir.irLocal;
assert(local);
assert(local->nestedIndex >= 0);
LLValue* val = DtoGEPi(ctx, 0, local->nestedIndex);
// references must be loaded to get the variable address
if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
val = DtoLoad(val);
Logger::cout() << "value: " << *val << '\n';
return new DVarValue(astype, vd, val, true);
} }
/****************************************************************************************/ /****************************************************************************************/
@ -509,15 +425,15 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
Logger::cout() << "DtoAssign(...);\n"; Logger::cout() << "DtoAssign(...);\n";
LOG_SCOPE; LOG_SCOPE;
Type* t = DtoDType(lhs->getType()); Type* t = lhs->getType()->toBasetype();
Type* t2 = DtoDType(rhs->getType()); Type* t2 = rhs->getType()->toBasetype();
if (t->ty == Tstruct) { if (t->ty == Tstruct) {
if (!t->equals(t2)) { if (!t->equals(t2)) {
// TODO: fix this, use 'rhs' for something // TODO: fix this, use 'rhs' for something
DtoAggrZeroInit(lhs->getLVal()); DtoAggrZeroInit(lhs->getLVal());
} }
else if (!rhs->inPlace()) { else {
DtoAggrCopy(lhs->getLVal(), rhs->getRVal()); DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
} }
} }
@ -559,7 +475,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
else if (t->ty == Tdelegate) { else if (t->ty == Tdelegate) {
if (rhs->isNull()) if (rhs->isNull())
DtoAggrZeroInit(lhs->getLVal()); DtoAggrZeroInit(lhs->getLVal());
else if (!rhs->inPlace()) { else {
LLValue* l = lhs->getLVal(); LLValue* l = lhs->getLVal();
LLValue* r = rhs->getRVal(); LLValue* r = rhs->getRVal();
Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n';
@ -665,8 +581,8 @@ DValue* DtoCastInt(Loc& loc, DValue* val, Type* _to)
{ {
const LLType* tolltype = DtoType(_to); const LLType* tolltype = DtoType(_to);
Type* to = DtoDType(_to); Type* to = _to->toBasetype();
Type* from = DtoDType(val->getType()); Type* from = val->getType()->toBasetype();
assert(from->isintegral()); assert(from->isintegral());
size_t fromsz = from->size(); size_t fromsz = from->size();
@ -720,8 +636,8 @@ DValue* DtoCastPtr(Loc& loc, DValue* val, Type* to)
{ {
const LLType* tolltype = DtoType(to); const LLType* tolltype = DtoType(to);
Type* totype = DtoDType(to); Type* totype = to->toBasetype();
Type* fromtype = DtoDType(val->getType()); Type* fromtype = val->getType()->toBasetype();
assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction); assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction);
LLValue* rval; LLValue* rval;
@ -749,8 +665,8 @@ DValue* DtoCastFloat(Loc& loc, DValue* val, Type* to)
const LLType* tolltype = DtoType(to); const LLType* tolltype = DtoType(to);
Type* totype = DtoDType(to); Type* totype = to->toBasetype();
Type* fromtype = DtoDType(val->getType()); Type* fromtype = val->getType()->toBasetype();
assert(fromtype->isfloating()); assert(fromtype->isfloating());
size_t fromsz = fromtype->size(); size_t fromsz = fromtype->size();
@ -814,7 +730,7 @@ DValue* DtoCastDelegate(Loc& loc, DValue* val, Type* to)
DValue* DtoCast(Loc& loc, DValue* val, Type* to) DValue* DtoCast(Loc& loc, DValue* val, Type* to)
{ {
Type* fromtype = DtoDType(val->getType()); Type* fromtype = val->getType()->toBasetype();
Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars()); Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars());
if (fromtype->isintegral()) { if (fromtype->isintegral()) {
return DtoCastInt(loc, val, to); return DtoCastInt(loc, val, to);
@ -879,10 +795,10 @@ void DtoLazyStaticInit(bool istempl, LLValue* gvar, Initializer* init, Type* t)
gIR->ir->CreateCondBr(cond, initbb, endinitbb); gIR->ir->CreateCondBr(cond, initbb, endinitbb);
gIR->scope() = IRScope(initbb,endinitbb); gIR->scope() = IRScope(initbb,endinitbb);
DValue* ie = DtoInitializer(gvar, init); DValue* ie = DtoInitializer(gvar, init);
if (!ie->inPlace()) {
DValue* dst = new DVarValue(t, gvar, true); DVarValue dst(t, gvar, true);
DtoAssign(init->loc, dst, ie); DtoAssign(init->loc, &dst, ie);
}
gIR->ir->CreateStore(DtoConstBool(true), gflag); gIR->ir->CreateStore(DtoConstBool(true), gflag);
gIR->ir->CreateBr(endinitbb); gIR->ir->CreateBr(endinitbb);
gIR->scope() = IRScope(endinitbb,oldend); gIR->scope() = IRScope(endinitbb,oldend);
@ -1001,7 +917,7 @@ void DtoConstInitGlobal(VarDeclaration* vd)
} }
const LLType* _type = DtoType(vd->type); const LLType* _type = DtoType(vd->type);
Type* t = DtoDType(vd->type); Type* t = vd->type->toBasetype();
//Logger::cout() << "initializer: " << *_init << '\n'; //Logger::cout() << "initializer: " << *_init << '\n';
if (_type != _init->getType()) { if (_type != _init->getType()) {
@ -1218,9 +1134,23 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
if (vd->nestedref) { if (vd->nestedref) {
Logger::println("has nestedref set"); Logger::println("has nestedref set");
assert(vd->ir.irLocal); assert(vd->ir.irLocal);
vd->ir.irLocal->value = gIR->func()->decl->ir.irFunc->nestedVar;
assert(vd->ir.irLocal->value); // alloca as usual is no value already
if (!vd->ir.irLocal->value)
{
vd->ir.irLocal->value = DtoAlloca(DtoType(vd->type), vd->toChars());
}
// store the address into the nested vars array
assert(vd->ir.irLocal->nestedIndex >= 0); assert(vd->ir.irLocal->nestedIndex >= 0);
LLValue* gep = DtoGEPi(gIR->func()->decl->ir.irFunc->nestedVar, 0, vd->ir.irLocal->nestedIndex);
assert(isaPointer(vd->ir.irLocal->value));
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
DtoStore(val, gep);
} }
// normal stack variable, allocate storage on the stack if it has not already been done // normal stack variable, allocate storage on the stack if it has not already been done
else if(!vd->ir.irLocal) { else if(!vd->ir.irLocal) {
@ -1241,6 +1171,10 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
DtoDwarfLocalVariable(allocainst, vd); DtoDwarfLocalVariable(allocainst, vd);
} }
} }
else
{
assert(vd->ir.irLocal->value);
}
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n'; Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init); DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init);

View file

@ -38,9 +38,18 @@ void DtoEnterMonitor(LLValue* v);
// leaves a monitor lock // leaves a monitor lock
void DtoLeaveMonitor(LLValue* v); void DtoLeaveMonitor(LLValue* v);
// nested variable/class helpers // nested variable and context helpers
LLValue* DtoNestedContext(FuncDeclaration* func);
DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd); // gets the context value for a call to a nested function or newing a class, with arbitrary nesting
LLValue* DtoNestedContext(Loc loc, Dsymbol* sym);
// gets the dvalue of a nested variable with arbitrary nesting
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);
// old nested stuff
// LLValue* DtoNestedContext(Loc loc, FuncDeclaration* func);
// LLValue* DtoNestedContext(Loc loc, ClassDeclaration* cd);
// DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd);
// basic operations // basic operations
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs); void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs);

View file

@ -57,7 +57,7 @@ void ReturnStatement::toIR(IRState* p)
{ {
if (p->topfunc()->getReturnType() == LLType::VoidTy) { if (p->topfunc()->getReturnType() == LLType::VoidTy) {
IrFunction* f = p->func(); IrFunction* f = p->func();
assert(f->type->llvmRetInPtr); assert(f->type->retInPtr);
assert(f->decl->ir.irFunc->retArg); assert(f->decl->ir.irFunc->retArg);
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum); if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
@ -66,8 +66,7 @@ void ReturnStatement::toIR(IRState* p)
DValue* e = exp->toElem(p); DValue* e = exp->toElem(p);
if (!e->inPlace()) DtoAssign(loc, rvar, e);
DtoAssign(loc, rvar, e);
DtoEnclosingHandlers(enclosinghandler, NULL); DtoEnclosingHandlers(enclosinghandler, NULL);
@ -647,8 +646,8 @@ struct Case : Object
static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expression* e) static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expression* e)
{ {
Type* dt = DtoDType(e->type); Type* dt = e->type->toBasetype();
Type* dtnext = DtoDType(dt->next); Type* dtnext = dt->next->toBasetype();
TY ty = dtnext->ty; TY ty = dtnext->ty;
const char* fname; const char* fname;
if (ty == Tchar) { if (ty == Tchar) {
@ -934,7 +933,7 @@ void ForeachStatement::toIR(IRState* p)
// what to iterate // what to iterate
DValue* aggrval = aggr->toElem(p); DValue* aggrval = aggr->toElem(p);
Type* aggrtype = DtoDType(aggr->type); Type* aggrtype = aggr->type->toBasetype();
// get length and pointer // get length and pointer
LLValue* niters = DtoArrayLen(aggrval); LLValue* niters = DtoArrayLen(aggrval);

View file

@ -67,7 +67,7 @@ LLValue* DtoIndexStruct(LLValue* ptr, StructDeclaration* sd, Type* t, unsigned o
for (unsigned i=0; i<sd->fields.dim; ++i) { for (unsigned i=0; i<sd->fields.dim; ++i) {
VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i]; VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
Type* vdtype = DtoDType(vd->type); Type* vdtype = vd->type->toBasetype();
//Logger::println("found %u type %s", vd->offset, vdtype->toChars()); //Logger::println("found %u type %s", vd->offset, vdtype->toChars());
assert(vd->ir.irField->index >= 0); assert(vd->ir.irField->index >= 0);
if (os == vd->offset && vdtype == t) { if (os == vd->offset && vdtype == t) {
@ -125,7 +125,7 @@ void DtoResolveStruct(StructDeclaration* sd)
if (sd->prot() == PROTprivate && sd->getModule() != gIR->dmodule) if (sd->prot() == PROTprivate && sd->getModule() != gIR->dmodule)
Logger::println("using a private struct from outside its module"); Logger::println("using a private struct from outside its module");
TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
bool ispacked = (ts->alignsize() == 1); bool ispacked = (ts->alignsize() == 1);
@ -279,7 +279,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
Logger::println("DtoDeclareStruct(%s): %s", sd->toChars(), sd->loc.toChars()); Logger::println("DtoDeclareStruct(%s): %s", sd->toChars(), sd->loc.toChars());
LOG_SCOPE; LOG_SCOPE;
TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
std::string initname("_D"); std::string initname("_D");
initname.append(sd->mangle()); initname.append(sd->mangle());

View file

@ -71,6 +71,7 @@ LLValue* DtoCallableValue(DValue* fn)
else if (type->ty == Tdelegate) else if (type->ty == Tdelegate)
{ {
LLValue* dg = fn->getRVal(); LLValue* dg = fn->getRVal();
Logger::cout() << "delegate: " << *dg << '\n';
LLValue* funcptr = DtoGEPi(dg, 0, 1); LLValue* funcptr = DtoGEPi(dg, 0, 1);
return DtoLoad(funcptr); return DtoLoad(funcptr);
} }
@ -200,10 +201,10 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
TypeFunction* tf = DtoTypeFunction(fnval); TypeFunction* tf = DtoTypeFunction(fnval);
// misc // misc
bool retinptr = tf->llvmRetInPtr; bool retinptr = tf->retInPtr;
bool usesthis = tf->llvmUsesThis; bool thiscall = tf->usesThis;
bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate); bool delegatecall = (calleeType->toBasetype()->ty == Tdelegate);
bool nestedcall = (dfnval && dfnval->func && dfnval->func->isNested()); bool nestedcall = tf->usesNest;
bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1); bool dvarargs = (tf->linkage == LINKd && tf->varargs == 1);
unsigned callconv = DtoCallingConv(tf->linkage); unsigned callconv = DtoCallingConv(tf->linkage);
@ -221,8 +222,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
llvm::PAListPtr palist; llvm::PAListPtr palist;
// return attrs // return attrs
if (tf->llvmRetAttrs) if (tf->retAttrs)
palist = palist.addAttr(0, tf->llvmRetAttrs); palist = palist.addAttr(0, tf->retAttrs);
// handle implicit arguments // handle implicit arguments
std::vector<LLValue*> args; std::vector<LLValue*> args;
@ -237,11 +238,12 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
} }
// then comes a context argument... // then comes a context argument...
if(usesthis || delegatecall || nestedcall) if(thiscall || delegatecall || nestedcall)
{ {
// ... which can be a 'this' argument // ... which can be a 'this' argument
if (dfnval && dfnval->vthis) if (thiscall)
{ {
assert(dfnval && dfnval->vthis);
LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get()); LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get());
++argiter; ++argiter;
args.push_back(thisarg); args.push_back(thisarg);
@ -257,11 +259,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
// ... or a nested function context arg // ... or a nested function context arg
else if (nestedcall) else if (nestedcall)
{ {
LLValue* contextptr = DtoNestedContext(dfnval->func->toParent2()->isFuncDeclaration()); LLValue* contextptr = DtoNestedContext(loc, dfnval->func);
if (!contextptr) contextptr = DtoBitCast(contextptr, getVoidPtrType());
contextptr = getNullPtr(getVoidPtrType());
else
contextptr = DtoBitCast(contextptr, getVoidPtrType());
++argiter; ++argiter;
args.push_back(contextptr); args.push_back(contextptr);
} }
@ -354,7 +353,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
call->setCallingConv(callconv); call->setCallingConv(callconv);
call->setParamAttrs(palist); call->setParamAttrs(palist);
return new DImValue(resulttype, retllval, false); return new DImValue(resulttype, retllval);
} }

View file

@ -239,7 +239,7 @@ static LLGlobalVariable* dwarfBasicType(Type* type, llvm::GlobalVariable* compil
static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* compileUnit) static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* compileUnit)
{ {
const LLType* T = DtoType(type); const LLType* T = DtoType(type);
Type* t = DtoDType(type); Type* t = type->toBasetype();
// defaults // defaults
LLConstant* name = getNullPtr(getVoidPtrType()); LLConstant* name = getNullPtr(getVoidPtrType());
@ -300,7 +300,7 @@ static LLGlobalVariable* dwarfDerivedType(Type* type, llvm::GlobalVariable* comp
static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVariable* compileUnit, LLGlobalVariable* definedCU, const char* c_name, unsigned offset) static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVariable* compileUnit, LLGlobalVariable* definedCU, const char* c_name, unsigned offset)
{ {
const LLType* T = DtoType(type); const LLType* T = DtoType(type);
Type* t = DtoDType(type); Type* t = type->toBasetype();
// defaults // defaults
LLConstant* name; LLConstant* name;
@ -356,7 +356,7 @@ static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVa
static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit) static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit)
{ {
const LLType* T = DtoType(type); const LLType* T = DtoType(type);
Type* t = DtoDType(type); Type* t = type->toBasetype();
// defaults // defaults
LLConstant* name = getNullPtr(getVoidPtrType()); LLConstant* name = getNullPtr(getVoidPtrType());

View file

@ -106,7 +106,7 @@ DValue* VarExp::toElem(IRState* p)
// nested variable // nested variable
else if (vd->nestedref) { else if (vd->nestedref) {
Logger::println("nested variable"); Logger::println("nested variable");
return DtoNestedVariable(type, vd); return DtoNestedVariable(loc, type, vd);
} }
// function parameter // function parameter
else if (vd->isParameter()) { else if (vd->isParameter()) {
@ -114,7 +114,7 @@ DValue* VarExp::toElem(IRState* p)
FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration(); FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration();
if (fd && fd != p->func()->decl) { if (fd && fd != p->func()->decl) {
Logger::println("nested parameter"); Logger::println("nested parameter");
return DtoNestedVariable(type, vd); return DtoNestedVariable(loc, type, vd);
} }
else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->ir.getIrValue())) { else if (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type) || llvm::isa<llvm::AllocaInst>(vd->ir.getIrValue())) {
return new DVarValue(type, vd, vd->ir.getIrValue(), true); return new DVarValue(type, vd, vd->ir.getIrValue(), true);
@ -151,7 +151,7 @@ DValue* VarExp::toElem(IRState* p)
else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
{ {
// this seems to be the static initialiser for structs // this seems to be the static initialiser for structs
Type* sdecltype = DtoDType(sdecl->type); Type* sdecltype = sdecl->type->toBasetype();
Logger::print("Sym: type=%s\n", sdecltype->toChars()); Logger::print("Sym: type=%s\n", sdecltype->toChars());
assert(sdecltype->ty == Tstruct); assert(sdecltype->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)sdecltype; TypeStruct* ts = (TypeStruct*)sdecltype;
@ -177,7 +177,7 @@ LLConstant* VarExp::toConstElem(IRState* p)
if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
{ {
// this seems to be the static initialiser for structs // this seems to be the static initialiser for structs
Type* sdecltype = DtoDType(sdecl->type); Type* sdecltype = sdecl->type->toBasetype();
Logger::print("Sym: type=%s\n", sdecltype->toChars()); Logger::print("Sym: type=%s\n", sdecltype->toChars());
assert(sdecltype->ty == Tstruct); assert(sdecltype->ty == Tstruct);
TypeStruct* ts = (TypeStruct*)sdecltype; TypeStruct* ts = (TypeStruct*)sdecltype;
@ -242,7 +242,7 @@ LLConstant* RealExp::toConstElem(IRState* p)
{ {
Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars()); Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* t = DtoDType(type); Type* t = type->toBasetype();
return DtoConstFP(t, value); return DtoConstFP(t, value);
} }
@ -283,7 +283,7 @@ DValue* ComplexExp::toElem(IRState* p)
LLConstant* c = toConstElem(p); LLConstant* c = toConstElem(p);
if (c->isNullValue()) { if (c->isNullValue()) {
Type* t = DtoDType(type); Type* t = type->toBasetype();
if (t->ty == Tcomplex32) if (t->ty == Tcomplex32)
c = DtoConstFP(Type::tfloat32, 0); c = DtoConstFP(Type::tfloat32, 0);
else if (t->ty == Tcomplex64) else if (t->ty == Tcomplex64)
@ -314,8 +314,8 @@ DValue* StringExp::toElem(IRState* p)
Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars()); Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* dtype = DtoDType(type); Type* dtype = type->toBasetype();
Type* cty = DtoDType(dtype->next); Type* cty = dtype->next->toBasetype();
const LLType* ct = DtoTypeNotVoid(cty); const LLType* ct = DtoTypeNotVoid(cty);
//printf("ct = %s\n", type->next->toChars()); //printf("ct = %s\n", type->next->toChars());
@ -382,8 +382,8 @@ LLConstant* StringExp::toConstElem(IRState* p)
Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars()); Logger::print("StringExp::toConstElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* t = DtoDType(type); Type* t = type->toBasetype();
Type* cty = DtoDType(t->next); Type* cty = t->next->toBasetype();
bool nullterm = (t->ty != Tsarray); bool nullterm = (t->ty != Tsarray);
size_t endlen = nullterm ? len+1 : len; size_t endlen = nullterm ? len+1 : len;
@ -472,7 +472,19 @@ DValue* AssignExp::toElem(IRState* p)
if (l->isSlice() || l->isComplex()) if (l->isSlice() || l->isComplex())
return l; return l;
#if 0
if (type->toBasetype()->ty == Tstruct && e2->type->isintegral())
{
// handle struct = 0;
return l;
}
else
{
return r;
}
#else
return r; return r;
#endif
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -485,10 +497,10 @@ DValue* AddExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
Type* t = DtoDType(type); Type* t = type->toBasetype();
Type* e1type = DtoDType(e1->type); Type* e1type = e1->type->toBasetype();
Type* e1next = e1type->next ? DtoDType(e1type->next) : NULL; Type* e1next = e1type->next ? e1type->next->toBasetype() : NULL;
Type* e2type = DtoDType(e2->type); Type* e2type = e2->type->toBasetype();
if (e1type != e2type) { if (e1type != e2type) {
if (llvmFieldIndex) { if (llvmFieldIndex) {
@ -537,10 +549,10 @@ DValue* AddAssignExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
Type* t = DtoDType(type); Type* t = type->toBasetype();
DValue* res; DValue* res;
if (DtoDType(e1->type)->ty == Tpointer) { if (e1->type->toBasetype()->ty == Tpointer) {
LLValue* gep = llvm::GetElementPtrInst::Create(l->getRVal(),r->getRVal(),"tmp",p->scopebb()); LLValue* gep = llvm::GetElementPtrInst::Create(l->getRVal(),r->getRVal(),"tmp",p->scopebb());
res = new DImValue(type, gep); res = new DImValue(type, gep);
} }
@ -565,9 +577,9 @@ DValue* MinExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
Type* t = DtoDType(type); Type* t = type->toBasetype();
Type* t1 = DtoDType(e1->type); Type* t1 = e1->type->toBasetype();
Type* t2 = DtoDType(e2->type); Type* t2 = e2->type->toBasetype();
if (t1->ty == Tpointer && t2->ty == Tpointer) { if (t1->ty == Tpointer && t2->ty == Tpointer) {
LLValue* lv = l->getRVal(); LLValue* lv = l->getRVal();
@ -603,10 +615,10 @@ DValue* MinAssignExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
Type* t = DtoDType(type); Type* t = type->toBasetype();
DValue* res; DValue* res;
if (DtoDType(e1->type)->ty == Tpointer) { if (e1->type->toBasetype()->ty == Tpointer) {
Logger::println("ptr"); Logger::println("ptr");
LLValue* tmp = r->getRVal(); LLValue* tmp = r->getRVal();
LLValue* zero = llvm::ConstantInt::get(tmp->getType(),0,false); LLValue* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
@ -770,7 +782,7 @@ DValue* CallExp::toElem(IRState* p)
DValue* expv = exp->toElem(p); DValue* expv = exp->toElem(p);
if (expv->getType()->toBasetype()->ty != Tint32) if (expv->getType()->toBasetype()->ty != Tint32)
expv = DtoCast(loc, expv, Type::tint32); expv = DtoCast(loc, expv, Type::tint32);
return new DImValue(type, DtoAlloca(LLType::Int8Ty, expv->getRVal(), ".alloca")); return new DImValue(type, p->ir->CreateAlloca(LLType::Int8Ty, expv->getRVal(), ".alloca"));
} }
} }
@ -844,6 +856,12 @@ LLConstant* AddrExp::toConstElem(IRState* p)
assert(e1->op == TOKvar); assert(e1->op == TOKvar);
VarExp* vexp = (VarExp*)e1; VarExp* vexp = (VarExp*)e1;
if (vexp->var->needThis())
{
error("need 'this' to access %s", vexp->var->toChars());
fatal();
}
// global variable // global variable
if (VarDeclaration* vd = vexp->var->isVarDeclaration()) if (VarDeclaration* vd = vexp->var->isVarDeclaration())
{ {
@ -892,8 +910,8 @@ DValue* DotVarExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
Type* t = DtoDType(type); Type* t = type->toBasetype();
Type* e1type = DtoDType(e1->type); Type* e1type = e1->type->toBasetype();
//Logger::println("e1type=%s", e1type->toChars()); //Logger::println("e1type=%s", e1type->toChars());
//Logger::cout() << *DtoType(e1type) << '\n'; //Logger::cout() << *DtoType(e1type) << '\n';
@ -910,6 +928,16 @@ DValue* DotVarExp::toElem(IRState* p)
DStructIndexVector vdoffsets; DStructIndexVector vdoffsets;
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets); arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
} }
// happens for tuples
else if (e1type->ty == Tstruct) {
TypeStruct* ts = (TypeStruct*)e1type;
Logger::println("Struct member offset:%d", vd->offset);
LLValue* src = l->getRVal();
DStructIndexVector vdoffsets;
arrptr = DtoIndexStruct(src, ts->sym, vd->type, vd->offset, vdoffsets);
}
else if (e1type->ty == Tclass) { else if (e1type->ty == Tclass) {
TypeClass* tc = (TypeClass*)e1type; TypeClass* tc = (TypeClass*)e1type;
Logger::println("Class member offset: %d", vd->offset); Logger::println("Class member offset: %d", vd->offset);
@ -953,7 +981,7 @@ DValue* DotVarExp::toElem(IRState* p)
LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false); LLValue* zero = llvm::ConstantInt::get(LLType::Int32Ty, 0, false);
LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false); LLValue* vtblidx = llvm::ConstantInt::get(LLType::Int32Ty, (size_t)fdecl->vtblIndex, false);
//Logger::cout() << "vthis: " << *vthis << '\n'; Logger::cout() << "vthis: " << *vthis << '\n';
funcval = DtoGEP(vthis, zero, zero); funcval = DtoGEP(vthis, zero, zero);
funcval = DtoLoad(funcval); funcval = DtoLoad(funcval);
funcval = DtoGEP(funcval, zero, vtblidx, toChars()); funcval = DtoGEP(funcval, zero, vtblidx, toChars());
@ -991,7 +1019,7 @@ DValue* ThisExp::toElem(IRState* p)
// FIXME: check for TOKthis in AssertExp instead // FIXME: check for TOKthis in AssertExp instead
if (!var) if (!var)
{ {
LLValue* v = p->func()->thisVar; LLValue* v = p->func()->thisArg;
assert(v); assert(v);
return new DVarValue(type, v, true); return new DVarValue(type, v, true);
} }
@ -1000,11 +1028,11 @@ DValue* ThisExp::toElem(IRState* p)
LLValue* v; LLValue* v;
if (vd->toParent2() != p->func()->decl) { if (vd->toParent2() != p->func()->decl) {
Logger::println("nested this exp"); Logger::println("nested this exp");
return DtoNestedVariable(type, vd); return DtoNestedVariable(loc, type, vd);
} }
else { else {
Logger::println("normal this exp"); Logger::println("normal this exp");
v = p->func()->decl->ir.irFunc->thisVar; v = p->func()->thisArg;
} }
return new DVarValue(type, vd, v, true); return new DVarValue(type, vd, v, true);
} }
@ -1023,7 +1051,7 @@ DValue* IndexExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
Type* e1type = DtoDType(e1->type); Type* e1type = e1->type->toBasetype();
p->arrays.push_back(l); // if $ is used it must be an array so this is fine. p->arrays.push_back(l); // if $ is used it must be an array so this is fine.
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
@ -1141,8 +1169,8 @@ DValue* CmpExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
Type* t = DtoDType(e1->type); Type* t = e1->type->toBasetype();
Type* e2t = DtoDType(e2->type); Type* e2t = e2->type->toBasetype();
assert(DtoType(t) == DtoType(e2t)); assert(DtoType(t) == DtoType(e2t));
LLValue* eval = 0; LLValue* eval = 0;
@ -1254,8 +1282,8 @@ DValue* EqualExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p); DValue* r = e2->toElem(p);
Type* t = DtoDType(e1->type); Type* t = e1->type->toBasetype();
Type* e2t = DtoDType(e2->type); Type* e2t = e2->type->toBasetype();
//assert(t == e2t); //assert(t == e2t);
LLValue* eval = 0; LLValue* eval = 0;
@ -1341,8 +1369,8 @@ DValue* PostExp::toElem(IRState* p)
LLValue* val = l->getRVal(); LLValue* val = l->getRVal();
LLValue* post = 0; LLValue* post = 0;
Type* e1type = DtoDType(e1->type); Type* e1type = e1->type->toBasetype();
Type* e2type = DtoDType(e2->type); Type* e2type = e2->type->toBasetype();
if (e1type->isintegral()) if (e1type->isintegral())
{ {
@ -1379,7 +1407,7 @@ DValue* PostExp::toElem(IRState* p)
DtoStore(post,l->getLVal()); DtoStore(post,l->getLVal());
return new DImValue(type,val,true); return new DImValue(type,val);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -1390,12 +1418,12 @@ DValue* NewExp::toElem(IRState* p)
LOG_SCOPE; LOG_SCOPE;
assert(newtype); assert(newtype);
Type* ntype = DtoDType(newtype); Type* ntype = newtype->toBasetype();
// new class // new class
if (ntype->ty == Tclass) { if (ntype->ty == Tclass) {
Logger::println("new class"); Logger::println("new class");
return DtoNewClass((TypeClass*)ntype, this); return DtoNewClass(loc, (TypeClass*)ntype, this);
} }
// new dynamic array // new dynamic array
else if (ntype->ty == Tarray) else if (ntype->ty == Tarray)
@ -1439,7 +1467,7 @@ DValue* NewExp::toElem(IRState* p)
assert(ts->sym); assert(ts->sym);
DtoAggrCopy(mem,ts->sym->ir.irStruct->init); DtoAggrCopy(mem,ts->sym->ir.irStruct->init);
} }
return new DImValue(type, mem, false); return new DImValue(type, mem);
} }
// new basic type // new basic type
else else
@ -1454,7 +1482,7 @@ DValue* NewExp::toElem(IRState* p)
DtoAssign(loc, &tmpvar, iv); DtoAssign(loc, &tmpvar, iv);
// return as pointer-to // return as pointer-to
return new DImValue(type, mem, false); return new DImValue(type, mem);
} }
assert(0); assert(0);
@ -1468,7 +1496,7 @@ DValue* DeleteExp::toElem(IRState* p)
LOG_SCOPE; LOG_SCOPE;
DValue* dval = e1->toElem(p); DValue* dval = e1->toElem(p);
Type* et = DtoDType(e1->type); Type* et = e1->type->toBasetype();
// simple pointer // simple pointer
if (et->ty == Tpointer) if (et->ty == Tpointer)
@ -1763,12 +1791,13 @@ DValue* DelegateExp::toElem(IRState* p)
DValue* u = e1->toElem(p); DValue* u = e1->toElem(p);
LLValue* uval; LLValue* uval;
if (DFuncValue* f = u->isFunc()) { if (DFuncValue* f = u->isFunc()) {
assert(f->func); assert(f->func);
LLValue* contextptr = DtoNestedContext(f->func->toParent2()->isFuncDeclaration()); LLValue* contextptr;
if (!contextptr) if (p->func()->decl == f->func)
uval = LLConstant::getNullValue(getVoidPtrType()); contextptr = p->func()->thisArg;
else else
uval = DtoBitCast(contextptr, getVoidPtrType()); contextptr = DtoNestedContext(loc, f->func);
uval = DtoBitCast(contextptr, getVoidPtrType());
} }
else { else {
DValue* src = u; DValue* src = u;
@ -1892,7 +1921,7 @@ DValue* CondExp::toElem(IRState* p)
Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars()); Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* dtype = DtoDType(type); Type* dtype = type->toBasetype();
const LLType* resty = DtoType(dtype); const LLType* resty = DtoType(dtype);
// allocate a temporary for the final result. failed to come up with a better way :/ // allocate a temporary for the final result. failed to come up with a better way :/
@ -1953,7 +1982,7 @@ DValue* NegExp::toElem(IRState* p)
} }
LLValue* val = l->getRVal(); LLValue* val = l->getRVal();
Type* t = DtoDType(type); Type* t = type->toBasetype();
LLValue* zero = 0; LLValue* zero = 0;
if (t->isintegral()) if (t->isintegral())
@ -1975,9 +2004,9 @@ DValue* CatExp::toElem(IRState* p)
Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars()); Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
LOG_SCOPE; LOG_SCOPE;
Type* t = DtoDType(type); Type* t = type->toBasetype();
bool arrNarr = DtoDType(e1->type) == DtoDType(e2->type); bool arrNarr = e1->type->toBasetype() == e2->type->toBasetype();
// array ~ array // array ~ array
if (arrNarr) if (arrNarr)
@ -2001,9 +2030,9 @@ DValue* CatAssignExp::toElem(IRState* p)
DValue* l = e1->toElem(p); DValue* l = e1->toElem(p);
Type* e1type = DtoDType(e1->type); Type* e1type = e1->type->toBasetype();
Type* elemtype = DtoDType(e1type->next); Type* elemtype = e1type->next->toBasetype();
Type* e2type = DtoDType(e2->type); Type* e2type = e2->type->toBasetype();
if (e2type == elemtype) { if (e2type == elemtype) {
DSliceValue* slice = DtoCatAssignElement(l,e2); DSliceValue* slice = DtoCatAssignElement(l,e2);
@ -2037,17 +2066,17 @@ DValue* FuncExp::toElem(IRState* p)
LLValue* lval = DtoAlloca(dgty,"dgstorage"); LLValue* lval = DtoAlloca(dgty,"dgstorage");
LLValue* context = DtoGEPi(lval,0,0); LLValue* context = DtoGEPi(lval,0,0);
const LLPointerType* pty = isaPointer(context->getType()->getContainedType(0)); LLValue* cval;
LLValue* llvmNested = p->func()->decl->ir.irFunc->nestedVar; IrFunction* irfn = p->func();
if (llvmNested == NULL) { if (irfn->nestedVar)
LLValue* nullcontext = llvm::ConstantPointerNull::get(pty); cval = irfn->nestedVar;
DtoStore(nullcontext, context); else if (irfn->nestArg)
} cval = irfn->nestArg;
else { else
LLValue* nestedcontext = DtoBitCast(llvmNested, pty); cval = getNullPtr(getVoidPtrType());
DtoStore(nestedcontext, context); cval = DtoBitCast(cval, context->getType()->getContainedType(0));
} DtoStore(cval, context);
LLValue* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb()); LLValue* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb());
assert(fd->ir.irFunc->func); assert(fd->ir.irFunc->func);
@ -2072,8 +2101,6 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
bool dyn = (arrayType->ty == Tarray); bool dyn = (arrayType->ty == Tarray);
// length // length
size_t len = elements->dim; size_t len = elements->dim;
// store into slice?
bool sliceInPlace = false;
// llvm target type // llvm target type
const LLType* llType = DtoType(arrayType); const LLType* llType = DtoType(arrayType);
@ -2096,15 +2123,13 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
// emulate assignment // emulate assignment
DVarValue* vv = new DVarValue(expr->type, elemAddr, true); DVarValue* vv = new DVarValue(expr->type, elemAddr, true);
DValue* e = expr->toElem(p); DValue* e = expr->toElem(p);
DImValue* im = e->isIm(); DtoAssign(loc, vv, e);
if (!im || !im->inPlace()) {
DtoAssign(loc, vv, e);
}
} }
// return storage directly ? // return storage directly ?
if (!dyn || (dyn && sliceInPlace)) if (!dyn)
return new DImValue(type, dstMem, false); return new DImValue(type, dstMem);
// wrap in a slice // wrap in a slice
return new DSliceValue(type, DtoConstSize_t(len), DtoGEPi(dstMem,0,0,"tmp")); return new DSliceValue(type, DtoConstSize_t(len), DtoGEPi(dstMem,0,0,"tmp"));
} }
@ -2188,9 +2213,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
DValue* darrptr = new DVarValue(vx->type, arrptr, true); DValue* darrptr = new DVarValue(vx->type, arrptr, true);
DValue* ve = vx->toElem(p); DValue* ve = vx->toElem(p);
DtoAssign(loc, darrptr, ve);
if (!ve->inPlace())
DtoAssign(loc, darrptr, ve);
j++; j++;
} }
@ -2214,7 +2237,7 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
vals[i] = vx->toConstElem(p); vals[i] = vx->toConstElem(p);
} }
assert(DtoDType(type)->ty == Tstruct); assert(type->toBasetype()->ty == Tstruct);
const LLType* t = DtoType(type); const LLType* t = DtoType(type);
const LLStructType* st = isaStruct(t); const LLStructType* st = isaStruct(t);
return llvm::ConstantStruct::get(st,vals); return llvm::ConstantStruct::get(st,vals);
@ -2257,7 +2280,7 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p)
assert(values); assert(values);
assert(keys->dim == values->dim); assert(keys->dim == values->dim);
Type* aatype = DtoDType(type); Type* aatype = type->toBasetype();
Type* vtype = aatype->next; Type* vtype = aatype->next;
const LLType* aalltype = DtoType(type); const LLType* aalltype = DtoType(type);

View file

@ -23,14 +23,14 @@
bool DtoIsPassedByRef(Type* type) bool DtoIsPassedByRef(Type* type)
{ {
Type* typ = DtoDType(type); Type* typ = type->toBasetype();
TY t = typ->ty; TY t = typ->ty;
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex()); return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
} }
bool DtoIsReturnedInArg(Type* type) bool DtoIsReturnedInArg(Type* type)
{ {
Type* typ = DtoDType(type); Type* typ = type->toBasetype();
TY t = typ->ty; TY t = typ->ty;
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex()); return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
} }
@ -54,16 +54,6 @@ unsigned DtoShouldExtend(Type* type)
return llvm::ParamAttr::None; return llvm::ParamAttr::None;
} }
Type* DtoDType(Type* t)
{
if (t->ty == Ttypedef) {
Type* bt = t->toBasetype();
assert(bt);
return DtoDType(bt);
}
return t;
}
const LLType* DtoType(Type* t) const LLType* DtoType(Type* t)
{ {
assert(t); assert(t);
@ -143,7 +133,7 @@ const LLType* DtoType(Type* t)
case Tfunction: case Tfunction:
{ {
if (!t->ir.type || *t->ir.type == NULL) { if (!t->ir.type || *t->ir.type == NULL) {
return DtoFunctionType(t,NULL); return DtoFunctionType(t,NULL,NULL);
} }
else { else {
return t->ir.type->get(); return t->ir.type->get();
@ -205,7 +195,7 @@ const LLType* DtoTypeNotVoid(Type* t)
const LLStructType* DtoDelegateType(Type* t) const LLStructType* DtoDelegateType(Type* t)
{ {
const LLType* i8ptr = getVoidPtrType(); const LLType* i8ptr = getVoidPtrType();
const LLType* func = DtoFunctionType(t->next, i8ptr); const LLType* func = DtoFunctionType(t->next, NULL, i8ptr);
const LLType* funcptr = getPtrToType(func); const LLType* funcptr = getPtrToType(func);
return LLStructType::get(i8ptr, funcptr, 0); return LLStructType::get(i8ptr, funcptr, 0);
} }
@ -666,8 +656,9 @@ size_t getTypeStoreSize(const LLType* t)
size_t getABITypeSize(const LLType* t) size_t getABITypeSize(const LLType* t)
{ {
Logger::cout() << "getting abi type of: " << *t << '\n'; size_t sz = gTargetData->getABITypeSize(t);
return gTargetData->getABITypeSize(t); Logger::cout() << "abi type size of: " << *t << " == " << sz << '\n';
return sz;
} }
unsigned char getABITypeAlign(const LLType* t) unsigned char getABITypeAlign(const LLType* t)

View file

@ -23,10 +23,6 @@ bool DtoIsReturnedInArg(Type* type);
unsigned DtoShouldExtend(Type* type); unsigned DtoShouldExtend(Type* type);
// resolve typedefs to their real type.
// TODO should probably be removed in favor of DMD's Type::toBasetype
Type* DtoDType(Type* t);
// delegate helpers // delegate helpers
const LLStructType* DtoDelegateType(Type* t); const LLStructType* DtoDelegateType(Type* t);
LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs); LLValue* DtoDelegateEquals(TOK op, LLValue* lhs, LLValue* rhs);
@ -92,6 +88,7 @@ llvm::ConstantPointerNull* getNullPtr(const LLType* t);
size_t getTypeBitSize(const LLType* t); size_t getTypeBitSize(const LLType* t);
size_t getTypeStoreSize(const LLType* t); size_t getTypeStoreSize(const LLType* t);
size_t getABITypeSize(const LLType* t); size_t getABITypeSize(const LLType* t);
// type alignments // type alignments
unsigned char getABITypeAlign(const LLType* t); unsigned char getABITypeAlign(const LLType* t);
unsigned char getPrefTypeAlign(const LLType* t); unsigned char getPrefTypeAlign(const LLType* t);

View file

@ -55,9 +55,17 @@ void llvmdc_optimize_module(llvm::Module* m, char lvl, bool doinline);
void Module::genobjfile(int multiobj) void Module::genobjfile(int multiobj)
{ {
bool logenabled = Logger::enabled();
if (llvmForceLogging && !logenabled)
{
Logger::enable();
}
Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n'; Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
LOG_SCOPE; LOG_SCOPE;
//printf("codegen: %s\n", srcfile->toChars());
// start by deleting the old object file // start by deleting the old object file
deleteObjFile(); deleteObjFile();
@ -161,10 +169,10 @@ void Module::genobjfile(int multiobj)
if (global.params.fqnPaths) if (global.params.fqnPaths)
{ {
bcpath = LLPath(md->toChars()); bcpath = LLPath(mname);
bcpath.appendSuffix("bc"); bcpath.appendSuffix("bc");
llpath = LLPath(md->toChars()); llpath = LLPath(mname);
llpath.appendSuffix("ll"); llpath.appendSuffix("ll");
} }
else else
@ -190,6 +198,11 @@ void Module::genobjfile(int multiobj)
delete ir.module; delete ir.module;
gTargetData = 0; gTargetData = 0;
gIR = NULL; gIR = NULL;
if (llvmForceLogging && !logenabled)
{
Logger::disable();
}
} }
/* ================================================================== */ /* ================================================================== */

View file

@ -13,7 +13,7 @@ IrFunction::IrFunction(FuncDeclaration* fd)
{ {
decl = fd; decl = fd;
Type* t = DtoDType(fd->type); Type* t = fd->type->toBasetype();
assert(t->ty == Tfunction); assert(t->ty == Tfunction);
type = (TypeFunction*)t; type = (TypeFunction*)t;
func = NULL; func = NULL;
@ -23,10 +23,14 @@ IrFunction::IrFunction(FuncDeclaration* fd)
defined = false; defined = false;
retArg = NULL; retArg = NULL;
thisVar = NULL; thisArg = NULL;
nestArg = NULL;
nestedVar = NULL; nestedVar = NULL;
_arguments = NULL; _arguments = NULL;
_argptr = NULL; _argptr = NULL;
dwarfSubProg = NULL; dwarfSubProg = NULL;
srcfileArg = NULL; srcfileArg = NULL;

View file

@ -18,11 +18,16 @@ struct IrFunction : IrBase
bool queued; bool queued;
bool defined; bool defined;
llvm::Value* retArg;
llvm::Value* thisVar; llvm::Value* retArg; // return in ptr arg
llvm::Value* nestedVar; llvm::Value* thisArg; // class/struct 'this' arg
llvm::Value* nestArg; // nested function 'this' arg
llvm::Value* nestedVar; // nested var alloca
llvm::Value* _arguments; llvm::Value* _arguments;
llvm::Value* _argptr; llvm::Value* _argptr;
llvm::Constant* dwarfSubProg; llvm::Constant* dwarfSubProg;
llvm::AllocaInst* srcfileArg; llvm::AllocaInst* srcfileArg;

View file

@ -79,7 +79,7 @@ unittest
{ {
debug(apply) printf("_aApplyRcd1.unittest\n"); debug(apply) printf("_aApplyRcd1.unittest\n");
auto s = "hello"c; char[] s = "hello"c;
int i; int i;
foreach_reverse(dchar d; s) foreach_reverse(dchar d; s)
@ -143,7 +143,7 @@ unittest
{ {
debug(apply) printf("_aApplyRwd1.unittest\n"); debug(apply) printf("_aApplyRwd1.unittest\n");
auto s = "hello"w; wchar[] s = "hello"w;
int i; int i;
foreach_reverse(dchar d; s) foreach_reverse(dchar d; s)
@ -229,7 +229,7 @@ unittest
{ {
debug(apply) printf("_aApplyRcw1.unittest\n"); debug(apply) printf("_aApplyRcw1.unittest\n");
auto s = "hello"c; char[] s = "hello"c;
int i; int i;
foreach_reverse(wchar d; s) foreach_reverse(wchar d; s)
@ -310,7 +310,7 @@ unittest
{ {
debug(apply) printf("_aApplyRwc1.unittest\n"); debug(apply) printf("_aApplyRwc1.unittest\n");
auto s = "hello"w; wchar[] s = "hello"w;
int i; int i;
foreach_reverse(char d; s) foreach_reverse(char d; s)
@ -389,7 +389,7 @@ unittest
{ {
debug(apply) printf("_aApplyRdc1.unittest\n"); debug(apply) printf("_aApplyRdc1.unittest\n");
auto s = "hello"d; dchar[] s = "hello"d;
int i; int i;
foreach_reverse(char d; s) foreach_reverse(char d; s)
@ -461,7 +461,7 @@ unittest
{ {
debug(apply) printf("_aApplyRdw1.unittest\n"); debug(apply) printf("_aApplyRdw1.unittest\n");
auto s = "hello"d; dchar[] s = "hello"d;
int i; int i;
foreach_reverse(wchar d; s) foreach_reverse(wchar d; s)
@ -543,7 +543,7 @@ unittest
{ {
debug(apply) printf("_aApplyRcd2.unittest\n"); debug(apply) printf("_aApplyRcd2.unittest\n");
auto s = "hello"c; char[] s = "hello"c;
int i; int i;
foreach_reverse(k, dchar d; s) foreach_reverse(k, dchar d; s)
@ -608,7 +608,7 @@ unittest
{ {
debug(apply) printf("_aApplyRwd2.unittest\n"); debug(apply) printf("_aApplyRwd2.unittest\n");
auto s = "hello"w; wchar[] s = "hello"w;
int i; int i;
foreach_reverse(k, dchar d; s) foreach_reverse(k, dchar d; s)
@ -696,7 +696,7 @@ unittest
{ {
debug(apply) printf("_aApplyRcw2.unittest\n"); debug(apply) printf("_aApplyRcw2.unittest\n");
auto s = "hello"c; char[] s = "hello"c;
int i; int i;
foreach_reverse(k, wchar d; s) foreach_reverse(k, wchar d; s)
@ -779,7 +779,7 @@ unittest
{ {
debug(apply) printf("_aApplyRwc2.unittest\n"); debug(apply) printf("_aApplyRwc2.unittest\n");
auto s = "hello"w; wchar[] s = "hello"w;
int i; int i;
foreach_reverse(k, char d; s) foreach_reverse(k, char d; s)
@ -859,7 +859,7 @@ unittest
{ {
debug(apply) printf("_aApplyRdc2.unittest\n"); debug(apply) printf("_aApplyRdc2.unittest\n");
auto s = "hello"d; dchar[] s = "hello"d;
int i; int i;
foreach_reverse(k, char d; s) foreach_reverse(k, char d; s)
@ -933,7 +933,7 @@ unittest
{ {
debug(apply) printf("_aApplyRdw2.unittest\n"); debug(apply) printf("_aApplyRdw2.unittest\n");
auto s = "hello"d; dchar[] s = "hello"d;
int i; int i;
foreach_reverse(k, wchar d; s) foreach_reverse(k, wchar d; s)

View file

@ -101,7 +101,6 @@ alias BB* AA;
size_t aligntsize(size_t tsize) size_t aligntsize(size_t tsize)
{ {
// Is pointer alignment on the x64 4 bytes or 8?
return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1); return (tsize + size_t.sizeof - 1) & ~(size_t.sizeof - 1);
} }

View file

@ -67,7 +67,7 @@ struct Array
* reversed. * reversed.
*/ */
extern (C) Array _adReverseChar(char[] a) extern (C) char[] _adReverseChar(char[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -127,14 +127,14 @@ extern (C) Array _adReverseChar(char[] a)
hi = hi - 1 + (stridehi - stridelo); hi = hi - 1 + (stridehi - stridelo);
} }
} }
return Array(a.length, a.ptr); return a;
} }
unittest unittest
{ {
auto a = "abcd"c; char[] a = "abcd"c;
auto r = a.dup.reverse; char[] r = a.dup.reverse;
//writefln(r); //writefln(r);
assert(r == "dcba"); assert(r == "dcba");
@ -162,7 +162,7 @@ unittest
* reversed. * reversed.
*/ */
extern (C) Array _adReverseWchar(wchar[] a) extern (C) wchar[] _adReverseWchar(wchar[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -220,13 +220,13 @@ extern (C) Array _adReverseWchar(wchar[] a)
hi = hi - 1 + (stridehi - stridelo); hi = hi - 1 + (stridehi - stridelo);
} }
} }
return Array(a.length, a.ptr); return a;
} }
unittest unittest
{ {
wstring a = "abcd"; wchar[] a = "abcd";
wstring r; wchar[] r;
r = a.dup.reverse; r = a.dup.reverse;
assert(r == "dcba"); assert(r == "dcba");
@ -331,7 +331,7 @@ unittest
* Sort array of chars. * Sort array of chars.
*/ */
extern (C) Array _adSortChar(char[] a) extern (C) char[] _adSortChar(char[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -346,14 +346,14 @@ extern (C) Array _adSortChar(char[] a)
} }
delete da; delete da;
} }
return Array(a.length, a.ptr); return a;
} }
/********************************************** /**********************************************
* Sort array of wchars. * Sort array of wchars.
*/ */
extern (C) Array _adSortWchar(wchar[] a) extern (C) wchar[] _adSortWchar(wchar[] a)
{ {
if (a.length > 1) if (a.length > 1)
{ {
@ -368,7 +368,7 @@ extern (C) Array _adSortWchar(wchar[] a)
} }
delete da; delete da;
} }
return Array(a.length, a.ptr); return a;
} }
/*************************************** /***************************************
@ -392,7 +392,7 @@ unittest
{ {
debug(adi) printf("array.Eq unittest\n"); debug(adi) printf("array.Eq unittest\n");
auto a = "hello"c; char[] a = "hello"c;
assert(a != "hel"); assert(a != "hel");
assert(a != "helloo"); assert(a != "helloo");
@ -425,7 +425,7 @@ unittest
{ {
debug(adi) printf("array.Cmp unittest\n"); debug(adi) printf("array.Cmp unittest\n");
auto a = "hello"c; char[] a = "hello"c;
assert(a > "hel"); assert(a > "hel");
assert(a >= "hel"); assert(a >= "hel");
@ -575,7 +575,7 @@ unittest
{ {
debug(adi) printf("array.CmpChar unittest\n"); debug(adi) printf("array.CmpChar unittest\n");
auto a = "hello"c; char[] a = "hello"c;
assert(a > "hel"); assert(a > "hel");
assert(a >= "hel"); assert(a >= "hel");

57
tests/mini/aa7.d Normal file
View file

@ -0,0 +1,57 @@
// adapted from dstress.run.a.associative_array_19_A to catch regressions early
module mini.aa7;
extern (C) int printf(char*, ...);
extern (C) void gc_collect();
union Key{
char x;
}
class Payload {
this(Key value) {
value.x += 1;
_value = value;
}
Key value() {
return _value;
}
Key _value;
}
int main(){
Payload[Key] aa;
Key[] allKeys;
static Key a = { 'a' };
static Key b = { 'b' };
static Key c = { 'c' };
allKeys ~= a;
allKeys ~= b;
allKeys ~= c;
foreach(Key key; allKeys) {
aa[key] = new Payload(key);
}
int i = 0;
foreach(Key key; allKeys) {
printf("1st #%d\n", i++);
assert(key in aa);
}
gc_collect();
i = 0;
foreach(Key key; allKeys) {
printf("2nd #%d\n", i++);
assert(key in aa);
}
return 0;
}

View file

@ -1,4 +1,4 @@
module tangotests.nested2; module mini.nested13;
extern(C) int printf(char*, ...); extern(C) int printf(char*, ...);

31
tests/mini/nested16.d Normal file
View file

@ -0,0 +1,31 @@
module mini.nested16;
void main()
{
int idx = 123;
int func(int* idp)
{
void foo()
{
void bar(int* idp)
{
auto c = new class
{
void mem()
{
scope(exit) ++*idp;
}
};
auto dg = () {
c.mem();
};
dg();
}
bar(idp);
++*idp;
}
foo();
return ++*idp;
}
assert(func(&idx) == 126);
}

45
tests/mini/nested17.d Normal file
View file

@ -0,0 +1,45 @@
// $HeadURL: svn://svn.berlios.de/dstress/trunk/run/n/nested_class_03_A.d $
// $Date: 2005-06-18 09:15:32 +0200 (Sat, 18 Jun 2005) $
// $Author: thomask $
// @author@ John C <johnch_atms@hotmail.com>
// @date@ 2005-06-09
// @uri@ news:d88vta$vak$1@digitaldaemon.com
//module dstress.run.n.nested_class_03_A;
module mini.nested17;
interface Inner{
int value();
}
class Outer{
int x;
Inner test(){
printf("val = %d\n", x);
return new class Inner {
int y;
this(){
printf("val = %d\n", x);
y=x;
}
int value(){
return y;
}
};
}
}
int main(){
Outer o = new Outer();
o.x=2;
int val = o.test().value();
printf("val = %d\n", val);
assert(val == o.x);
return 0;
}
extern(C) int printf(char*, ...);

27
tests/mini/nested19.d Normal file
View file

@ -0,0 +1,27 @@
module mini.nested19;
void main()
{
int i = 1;
class C
{
int j = 2;
void func()
{
int k = 3;
void foo()
{
i = i+j+k;
}
foo();
}
}
auto c = new C;
c.func();
assert(i == 6);
}

View file

@ -21,13 +21,13 @@ void main()
} }
} }
{ auto c2 = new C2;
scope c2 = new C2; c2.func2();
c2.func2();
}
} }
} }
scope c = new C; auto c = new C;
c.func(); c.func();
assert(i == 45);
} }