mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-01 23:50:43 +03:00
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:
parent
b2d860374b
commit
9d7f16b967
39 changed files with 693 additions and 455 deletions
23
dmd/attrib.c
23
dmd/attrib.c
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
2
dmd/id.c
2
dmd/id.c
|
@ -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");
|
||||||
|
|
1
dmd/id.h
1
dmd/id.h
|
@ -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;
|
||||||
|
|
|
@ -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" },
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
19
dmd/mtype.c
19
dmd/mtype.c
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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';
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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())
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -8,5 +8,6 @@ enum
|
||||||
LLVMva_start,
|
LLVMva_start,
|
||||||
LLVMva_copy,
|
LLVMva_copy,
|
||||||
LLVMva_end,
|
LLVMva_end,
|
||||||
LLVMva_arg
|
LLVMva_arg,
|
||||||
|
LLVMllvmdc
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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());
|
||||||
|
|
177
gen/toir.cpp
177
gen/toir.cpp
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ================================================================== */
|
/* ================================================================== */
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
57
tests/mini/aa7.d
Normal 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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
31
tests/mini/nested16.d
Normal 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
45
tests/mini/nested17.d
Normal 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
27
tests/mini/nested19.d
Normal 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);
|
||||||
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue