mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 02:45:25 +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
|
||||
#if IN_LLVM
|
||||
|
||||
// pragma(intrinsic, string) { funcdecl(s) }
|
||||
// pragma(intrinsic, "string") { funcdecl(s) }
|
||||
else if (ident == Id::intrinsic)
|
||||
{
|
||||
Expression* expr = (Expression *)args->data[0];
|
||||
|
@ -920,6 +920,27 @@ void PragmaDeclaration::semantic(Scope *sc)
|
|||
}
|
||||
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
|
||||
|
||||
|
|
|
@ -260,6 +260,10 @@ Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
|
|||
{
|
||||
//printf("rewriting e1 to %s's this\n", f->toChars());
|
||||
n++;
|
||||
|
||||
// LLVMDC seems dmd misses it sometimes here :/
|
||||
f->vthis->nestedref = 1;
|
||||
|
||||
e1 = new VarExp(loc, f->vthis);
|
||||
}
|
||||
}
|
||||
|
@ -5983,6 +5987,13 @@ Expression *AddrExp::semantic(Scope *sc)
|
|||
FuncDeclaration *f = dve->var->isFuncDeclaration();
|
||||
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())
|
||||
{ Expression *e;
|
||||
|
||||
|
|
2
dmd/id.c
2
dmd/id.c
|
@ -176,6 +176,7 @@ Identifier *Id::vastart;
|
|||
Identifier *Id::vacopy;
|
||||
Identifier *Id::vaend;
|
||||
Identifier *Id::vaarg;
|
||||
Identifier *Id::llvmdc;
|
||||
Identifier *Id::tohash;
|
||||
Identifier *Id::tostring;
|
||||
Identifier *Id::main;
|
||||
|
@ -357,6 +358,7 @@ void Id::initialize()
|
|||
vacopy = Lexer::idPool("va_copy");
|
||||
vaend = Lexer::idPool("va_end");
|
||||
vaarg = Lexer::idPool("va_arg");
|
||||
llvmdc = Lexer::idPool("llvmdc");
|
||||
tohash = Lexer::idPool("toHash");
|
||||
tostring = Lexer::idPool("toString");
|
||||
main = Lexer::idPool("main");
|
||||
|
|
1
dmd/id.h
1
dmd/id.h
|
@ -178,6 +178,7 @@ struct Id
|
|||
static Identifier *vacopy;
|
||||
static Identifier *vaend;
|
||||
static Identifier *vaarg;
|
||||
static Identifier *llvmdc;
|
||||
static Identifier *tohash;
|
||||
static Identifier *tostring;
|
||||
static Identifier *main;
|
||||
|
|
|
@ -223,6 +223,7 @@ Msgtable msgtable[] =
|
|||
{ "vacopy", "va_copy" },
|
||||
{ "vaend", "va_end" },
|
||||
{ "vaarg", "va_arg" },
|
||||
{ "llvmdc" },
|
||||
|
||||
// For toHash/toString
|
||||
{ "tohash", "toHash" },
|
||||
|
|
|
@ -311,6 +311,7 @@ int main(int argc, char *argv[])
|
|||
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
||||
VersionCondition::addPredefinedGlobalIdent("LLVMDC");
|
||||
#endif
|
||||
|
||||
#if _WIN32
|
||||
VersionCondition::addPredefinedGlobalIdent("Windows");
|
||||
VersionCondition::addPredefinedGlobalIdent("Win32");
|
||||
|
|
|
@ -162,6 +162,9 @@ Module::Module(char *filename, Identifier *ident, int doDocComment, int doHdrGen
|
|||
bcfile = new File(bcfilename);
|
||||
llfile = new File(llfilename);
|
||||
symfile = new File(symfilename);
|
||||
|
||||
// LLVMDC
|
||||
llvmForceLogging = false;
|
||||
}
|
||||
|
||||
void Module::setDocfile()
|
||||
|
|
|
@ -66,8 +66,11 @@ struct Module : Package
|
|||
ModuleDeclaration *md; // if !NULL, the contents of the ModuleDeclaration declaration
|
||||
File *srcfile; // input source file
|
||||
File *objfile; // output .obj file
|
||||
|
||||
// LLVMDC
|
||||
File *bcfile; // output .bc file
|
||||
File *llfile; // output .ll file
|
||||
|
||||
File *hdrfile; // 'header' file
|
||||
File *symfile; // output symbol file
|
||||
File *docfile; // output documentation file
|
||||
|
@ -171,6 +174,8 @@ struct Module : Package
|
|||
|
||||
// LLVMDC
|
||||
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->linkage = linkage;
|
||||
this->inuse = 0;
|
||||
this->llvmRetInPtr = false;
|
||||
this->llvmUsesThis = false;
|
||||
this->llvmRetAttrs = 0;
|
||||
this->retInPtr = false;
|
||||
this->usesThis = false;
|
||||
this->usesNest = false;
|
||||
this->retAttrs = 0;
|
||||
}
|
||||
|
||||
Type *TypeFunction::syntaxCopy()
|
||||
|
@ -2661,9 +2662,10 @@ Type *TypeFunction::syntaxCopy()
|
|||
Type *treturn = next ? next->syntaxCopy() : NULL;
|
||||
Arguments *params = Argument::arraySyntaxCopy(parameters);
|
||||
TypeFunction *t = new TypeFunction(params, treturn, varargs, linkage);
|
||||
t->llvmRetInPtr = llvmRetInPtr;
|
||||
t->llvmUsesThis = llvmUsesThis;
|
||||
t->llvmRetAttrs = llvmRetAttrs;
|
||||
t->retInPtr = retInPtr;
|
||||
t->usesThis = usesThis;
|
||||
t->usesNest = usesNest;
|
||||
t->retAttrs = retAttrs;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -3813,6 +3815,11 @@ char *TypeEnum::toChars()
|
|||
return sym->toChars();
|
||||
}
|
||||
|
||||
Type *TypeEnum::syntaxCopy()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
Type *TypeEnum::semantic(Loc loc, Scope *sc)
|
||||
{
|
||||
sym->semantic(sc);
|
||||
|
|
|
@ -441,9 +441,11 @@ struct TypeFunction : Type
|
|||
|
||||
unsigned totym();
|
||||
|
||||
bool llvmRetInPtr;
|
||||
bool llvmUsesThis;
|
||||
unsigned llvmRetAttrs;
|
||||
// LLVMDC
|
||||
bool retInPtr;
|
||||
bool usesThis;
|
||||
bool usesNest;
|
||||
unsigned retAttrs;
|
||||
};
|
||||
|
||||
struct TypeDelegate : Type
|
||||
|
@ -556,6 +558,7 @@ struct TypeEnum : Type
|
|||
d_uns64 size(Loc loc);
|
||||
unsigned alignsize();
|
||||
char *toChars();
|
||||
Type *syntaxCopy();
|
||||
Type *semantic(Loc loc, Scope *sc);
|
||||
Dsymbol *toDsymbol(Scope *sc);
|
||||
void toDecoBuffer(OutBuffer *buf);
|
||||
|
|
|
@ -89,7 +89,7 @@ void DtoArrayAssign(LLValue* dst, LLValue* src)
|
|||
const LLArrayType* arrty = isaArray(src->getType()->getContainedType(0));
|
||||
if (!arrty)
|
||||
{
|
||||
Logger::cout() << "invalid: " << *src << '\n';
|
||||
std::cout << "invalid: " << *src << '\n';
|
||||
assert(0);
|
||||
}
|
||||
const LLType* dstty = getPtrToType(arrty->getElementType());
|
||||
|
@ -244,7 +244,7 @@ LLConstant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
|
|||
Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* arrinittype = DtoDType(arrinit->type);
|
||||
Type* arrinittype = arrinit->type->toBasetype();
|
||||
|
||||
Type* t;
|
||||
integer_t tdim;
|
||||
|
@ -530,8 +530,7 @@ DSliceValue* DtoCatAssignElement(DValue* array, Expression* exp)
|
|||
|
||||
DValue* e = exp->toElem(gIR);
|
||||
|
||||
if (!e->inPlace())
|
||||
DtoAssign(exp->loc, dptr, e);
|
||||
DtoAssign(exp->loc, dptr, e);
|
||||
|
||||
return slice;
|
||||
}
|
||||
|
@ -573,8 +572,8 @@ DSliceValue* DtoCatArrays(Type* type, Expression* exp1, Expression* exp2)
|
|||
Logger::println("DtoCatArrays");
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t1 = DtoDType(exp1->type);
|
||||
Type* t2 = DtoDType(exp2->type);
|
||||
Type* t1 = exp1->type->toBasetype();
|
||||
Type* t2 = exp2->type->toBasetype();
|
||||
|
||||
assert(t1->ty == Tarray || t1->ty == Tsarray);
|
||||
assert(t2->ty == Tarray || t2->ty == Tsarray);
|
||||
|
@ -614,8 +613,8 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
|
|||
Logger::println("DtoCatArrayElement");
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t1 = DtoDType(exp1->type);
|
||||
Type* t2 = DtoDType(exp2->type);
|
||||
Type* t1 = exp1->type->toBasetype();
|
||||
Type* t2 = exp2->type->toBasetype();
|
||||
|
||||
DValue* e1 = exp1->toElem(gIR);
|
||||
DValue* e2 = exp2->toElem(gIR);
|
||||
|
@ -623,7 +622,7 @@ DSliceValue* DtoCatArrayElement(Type* type, Expression* exp1, Expression* exp2)
|
|||
llvm::Value *len1, *src1, *res;
|
||||
|
||||
// handle prefix case, eg. int~int[]
|
||||
if (t2->next && t1 == DtoDType(t2->next))
|
||||
if (t2->next && t1 == t2->next->toBasetype())
|
||||
{
|
||||
len1 = DtoArrayLen(e2);
|
||||
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
|
||||
Logger::println("casting to dynamic arrays");
|
||||
Type* l_ty = DtoDType(l->getType());
|
||||
Type* r_ty = DtoDType(r->getType());
|
||||
Type* l_ty = l->getType()->toBasetype();
|
||||
Type* r_ty = r->getType()->toBasetype();
|
||||
assert(l_ty->next == r_ty->next);
|
||||
if ((l_ty->ty == Tsarray) || (r_ty->ty == Tsarray)) {
|
||||
Type* a_ty = l_ty->next->arrayOf();
|
||||
|
@ -815,7 +814,7 @@ LLValue* DtoArrayCompare(Loc& loc, TOK op, DValue* l, DValue* r)
|
|||
|
||||
if (!skip)
|
||||
{
|
||||
Type* t = DtoDType(DtoDType(l->getType())->next);
|
||||
Type* t = l->getType()->toBasetype()->next->toBasetype();
|
||||
if (t->ty == Tchar)
|
||||
res = DtoArrayEqCmp_impl(loc, "_adCmpChar", l, r, false);
|
||||
else
|
||||
|
@ -900,7 +899,7 @@ LLValue* DtoArrayLen(DValue* v)
|
|||
Logger::println("DtoArrayLen");
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t = DtoDType(v->getType());
|
||||
Type* t = v->getType()->toBasetype();
|
||||
if (t->ty == Tarray) {
|
||||
if (DSliceValue* s = v->isSlice())
|
||||
return s->len;
|
||||
|
@ -926,7 +925,7 @@ LLValue* DtoArrayPtr(DValue* v)
|
|||
Logger::println("DtoArrayPtr");
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t = DtoDType(v->getType());
|
||||
Type* t = v->getType()->toBasetype();
|
||||
if (t->ty == Tarray) {
|
||||
if (DSliceValue* s = v->isSlice())
|
||||
return s->ptr;
|
||||
|
@ -951,8 +950,8 @@ DValue* DtoCastArray(Loc& loc, DValue* u, Type* to)
|
|||
|
||||
const LLType* tolltype = DtoType(to);
|
||||
|
||||
Type* totype = DtoDType(to);
|
||||
Type* fromtype = DtoDType(u->getType());
|
||||
Type* totype = to->toBasetype();
|
||||
Type* fromtype = u->getType()->toBasetype();
|
||||
assert(fromtype->ty == Tarray || fromtype->ty == Tsarray);
|
||||
|
||||
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
|
||||
DtoForceDeclareDsymbol(tc->sym);
|
||||
|
@ -829,25 +829,18 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
|
|||
DtoStore(src, dst);
|
||||
}
|
||||
// set the context for nested classes
|
||||
else if (tc->sym->isNested())
|
||||
else if (tc->sym->isNested() && tc->sym->vthis)
|
||||
{
|
||||
Logger::println("Resolving nested context");
|
||||
LOG_SCOPE;
|
||||
|
||||
// get context
|
||||
LLValue* nest = DtoNestedContext(loc, tc->sym);
|
||||
|
||||
// store into right location
|
||||
size_t idx = 2 + tc->sym->vthis->ir.irField->index;
|
||||
LLValue* gep = DtoGEPi(mem,0,idx,"tmp");
|
||||
|
||||
// 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);
|
||||
DtoStore(DtoBitCast(nest, gep->getType()->getContainedType(0)), gep);
|
||||
}
|
||||
|
||||
// call constructor
|
||||
|
@ -860,7 +853,7 @@ DValue* DtoNewClass(TypeClass* tc, NewExp* newexp)
|
|||
}
|
||||
|
||||
// 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());
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* to = DtoDType(_to);
|
||||
Type* to = _to->toBasetype();
|
||||
if (to->ty == Tpointer) {
|
||||
const LLType* tolltype = DtoType(_to);
|
||||
LLValue* rval = DtoBitCast(val->getRVal(), tolltype);
|
||||
|
@ -922,7 +915,7 @@ DValue* DtoCastClass(DValue* val, Type* _to)
|
|||
assert(to->ty == Tclass);
|
||||
TypeClass* tc = (TypeClass*)to;
|
||||
|
||||
Type* from = DtoDType(val->getType());
|
||||
Type* from = val->getType()->toBasetype();
|
||||
TypeClass* fc = (TypeClass*)from;
|
||||
|
||||
if (tc->sym->isInterfaceDeclaration()) {
|
||||
|
@ -977,7 +970,7 @@ DValue* DtoDynamicCastObject(DValue* val, Type* _to)
|
|||
assert(funcTy->getParamType(0) == obj->getType());
|
||||
|
||||
// ClassInfo c
|
||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||
TypeClass* to = (TypeClass*)_to->toBasetype();
|
||||
DtoForceDeclareDsymbol(to->sym);
|
||||
assert(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));
|
||||
|
||||
// ClassInfo c
|
||||
TypeClass* to = (TypeClass*)DtoDType(_to);
|
||||
TypeClass* to = (TypeClass*)_to->toBasetype();
|
||||
DtoForceDeclareDsymbol(to->sym);
|
||||
assert(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) {
|
||||
VarDeclaration* vd = i->second.var;
|
||||
assert(vd);
|
||||
Type* vdtype = DtoDType(vd->type);
|
||||
Type* vdtype = vd->type->toBasetype();
|
||||
//Logger::println("found %u type %s", vd->offset, vdtype->toChars());
|
||||
assert(vd->ir.irField->index >= 0);
|
||||
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->vtblIndex > 0);
|
||||
assert(DtoDType(inst->getType())->ty == Tclass);
|
||||
assert(inst->getType()->toBasetype()->ty == Tclass);
|
||||
|
||||
LLValue* vthis = inst->getRVal();
|
||||
Logger::cout() << "vthis: " << *vthis << '\n';
|
||||
|
|
|
@ -26,7 +26,7 @@ void DtoDefineClass(ClassDeclaration* cd);
|
|||
void DtoDeclareClassInfo(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);
|
||||
DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, LLValue* mem);
|
||||
void DtoFinalizeClass(LLValue* inst);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
const llvm::StructType* DtoComplexType(Type* type)
|
||||
{
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
const LLType* base = DtoComplexBaseType(t);
|
||||
|
||||
|
@ -26,7 +26,7 @@ const llvm::StructType* DtoComplexType(Type* type)
|
|||
|
||||
const LLType* DtoComplexBaseType(Type* t)
|
||||
{
|
||||
TY ty = DtoDType(t)->ty;
|
||||
TY ty = t->toBasetype()->ty;
|
||||
const LLType* base;
|
||||
if (ty == Tcomplex32) {
|
||||
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)
|
||||
{
|
||||
TY ty = DtoDType(_ty)->ty;
|
||||
TY ty = _ty->toBasetype()->ty;
|
||||
|
||||
llvm::ConstantFP* fre;
|
||||
llvm::ConstantFP* fim;
|
||||
|
@ -106,7 +106,7 @@ LLValue* DtoImagPart(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()) {
|
||||
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)
|
||||
{
|
||||
Type* to = DtoDType(_to);
|
||||
Type* to = _to->toBasetype();
|
||||
Type* vty = val->getType();
|
||||
if (to->iscomplex()) {
|
||||
if (vty->size() == to->size())
|
||||
|
|
|
@ -54,8 +54,6 @@ struct DValue : Object
|
|||
virtual DComplexValue* isComplex() { return NULL; }
|
||||
virtual DLRValue* isLRValue() { return NULL; }
|
||||
|
||||
virtual bool inPlace() { return false; }
|
||||
|
||||
protected:
|
||||
DValue() {}
|
||||
DValue(const DValue&) { }
|
||||
|
@ -67,16 +65,13 @@ struct DImValue : DValue
|
|||
{
|
||||
Type* type;
|
||||
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 Type*& getType() { assert(type); return type; }
|
||||
virtual DImValue* isIm() { return this; }
|
||||
|
||||
virtual bool inPlace() { return inplace; }
|
||||
};
|
||||
|
||||
// constant d-value
|
||||
|
|
|
@ -8,5 +8,6 @@ enum
|
|||
LLVMva_start,
|
||||
LLVMva_copy,
|
||||
LLVMva_end,
|
||||
LLVMva_arg
|
||||
LLVMva_arg,
|
||||
LLVMllvmdc
|
||||
};
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "gen/classes.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);
|
||||
TypeFunction* f = (TypeFunction*)type;
|
||||
|
@ -46,6 +46,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
|||
Type* rt = f->next;
|
||||
bool retinptr = false;
|
||||
bool usesthis = false;
|
||||
bool usesnest = false;
|
||||
|
||||
// parameter types
|
||||
std::vector<const LLType*> paramvec;
|
||||
|
@ -66,7 +67,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
|||
if (DtoIsReturnedInArg(rt)) {
|
||||
rettype = getPtrToType(DtoType(rt));
|
||||
actualRettype = LLType::VoidTy;
|
||||
f->llvmRetInPtr = retinptr = true;
|
||||
f->retInPtr = retinptr = true;
|
||||
}
|
||||
else {
|
||||
rettype = DtoType(rt);
|
||||
|
@ -75,7 +76,7 @@ const llvm::FunctionType* DtoFunctionType(Type* type, const LLType* thistype, bo
|
|||
|
||||
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);
|
||||
usesthis = true;
|
||||
}
|
||||
else if (nesttype) {
|
||||
paramvec.push_back(nesttype);
|
||||
usesnest = true;
|
||||
}
|
||||
|
||||
if (typesafeVararg) {
|
||||
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) {
|
||||
Argument* arg = Argument::getNth(f->parameters, i);
|
||||
// ensure scalar
|
||||
Type* argT = DtoDType(arg->type);
|
||||
Type* argT = arg->type->toBasetype();
|
||||
assert(argT);
|
||||
|
||||
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;
|
||||
llvm::FunctionType* functype = llvm::FunctionType::get(actualRettype, paramvec, isvararg);
|
||||
|
||||
f->llvmRetInPtr = retinptr;
|
||||
f->llvmUsesThis = usesthis;
|
||||
f->retInPtr = retinptr;
|
||||
f->usesThis = usesthis;
|
||||
f->usesNest = usesnest;
|
||||
|
||||
f->ir.type = new llvm::PATypeHolder(functype);
|
||||
|
||||
|
@ -210,7 +216,9 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
|
|||
if (fdecl->type->ir.type != 0)
|
||||
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 (AggregateDeclaration* ad = fdecl->isMember2()) {
|
||||
Logger::println("isMember = this is: %s", ad->type->toChars());
|
||||
|
@ -225,10 +233,10 @@ const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl)
|
|||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -237,7 +245,7 @@ const llvm::FunctionType* DtoFunctionType(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);
|
||||
llvm::Function* func = 0;
|
||||
|
||||
|
@ -306,8 +314,9 @@ void DtoResolveFunction(FuncDeclaration* fdecl)
|
|||
static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclaration* fdecl)
|
||||
{
|
||||
int llidx = 1;
|
||||
if (f->llvmRetInPtr) ++llidx;
|
||||
if (f->llvmUsesThis) ++llidx;
|
||||
if (f->retInPtr) ++llidx;
|
||||
if (f->usesThis) ++llidx;
|
||||
else if (f->usesNest) ++llidx;
|
||||
if (f->linkage == LINKd && f->varargs == 1)
|
||||
llidx += 2;
|
||||
|
||||
|
@ -318,15 +327,15 @@ static void set_param_attrs(TypeFunction* f, llvm::Function* func, FuncDeclarati
|
|||
llvm::ParamAttrsWithIndex PAWI;
|
||||
|
||||
// set return value attrs if any
|
||||
if (f->llvmRetAttrs)
|
||||
if (f->retAttrs)
|
||||
{
|
||||
PAWI.Index = 0;
|
||||
PAWI.Attrs = f->llvmRetAttrs;
|
||||
PAWI.Attrs = f->retAttrs;
|
||||
attrs.push_back(PAWI);
|
||||
}
|
||||
|
||||
// set sret param
|
||||
if (f->llvmRetInPtr)
|
||||
if (f->retInPtr)
|
||||
{
|
||||
PAWI.Index = 1;
|
||||
PAWI.Attrs = llvm::ParamAttr::StructRet;
|
||||
|
@ -378,7 +387,7 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||
}
|
||||
|
||||
// get TypeFunction*
|
||||
Type* t = DtoDType(fdecl->type);
|
||||
Type* t = fdecl->type->toBasetype();
|
||||
TypeFunction* f = (TypeFunction*)t;
|
||||
|
||||
bool declareOnly = false;
|
||||
|
@ -417,8 +426,6 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||
llvm::Function* func = vafunc ? vafunc : gIR->module->getFunction(mangled_name);
|
||||
if (!func)
|
||||
func = llvm::Function::Create(functype, DtoLinkage(fdecl), mangled_name, gIR->module);
|
||||
else
|
||||
assert(func->getFunctionType() == functype);
|
||||
|
||||
// add func to IRFunc
|
||||
fdecl->ir.irFunc->func = func;
|
||||
|
@ -457,15 +464,22 @@ void DtoDeclareFunction(FuncDeclaration* fdecl)
|
|||
// name parameters
|
||||
llvm::Function::arg_iterator iarg = func->arg_begin();
|
||||
int k = 0;
|
||||
if (f->llvmRetInPtr) {
|
||||
iarg->setName("retval");
|
||||
if (f->retInPtr) {
|
||||
iarg->setName(".sretarg");
|
||||
fdecl->ir.irFunc->retArg = iarg;
|
||||
++iarg;
|
||||
}
|
||||
if (f->llvmUsesThis) {
|
||||
iarg->setName(fdecl->isNested()?".context":"this");
|
||||
fdecl->ir.irFunc->thisVar = iarg;
|
||||
assert(fdecl->ir.irFunc->thisVar);
|
||||
|
||||
if (f->usesThis) {
|
||||
iarg->setName("this");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -520,13 +534,19 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
|||
Logger::println("DtoDefineFunc(%s): %s", fd->toPrettyChars(), fd->loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
// warn about naked
|
||||
if (fd->naked)
|
||||
{
|
||||
warning("%s: naked is currently ignored", fd->locToChars());
|
||||
}
|
||||
|
||||
// debug info
|
||||
if (global.params.symdebug) {
|
||||
Module* mo = fd->getModule();
|
||||
fd->ir.irFunc->dwarfSubProg = DtoDwarfSubProgram(fd);
|
||||
}
|
||||
|
||||
Type* t = DtoDType(fd->type);
|
||||
Type* t = fd->type->toBasetype();
|
||||
TypeFunction* f = (TypeFunction*)t;
|
||||
assert(f->ir.type);
|
||||
|
||||
|
@ -568,26 +588,32 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
|||
// debug info - after all allocas, but before any llvm.dbg.declare etc
|
||||
if (global.params.symdebug) DtoDwarfFuncStart(fd);
|
||||
|
||||
// need result variable? (not nested)
|
||||
if (fd->vresult && !fd->vresult->nestedref) {
|
||||
Logger::println("non-nested vresult value");
|
||||
// need result variable?
|
||||
if (fd->vresult) {
|
||||
Logger::println("vresult value");
|
||||
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
|
||||
// only if not referenced by nested functions
|
||||
if (fd->needThis() && !fd->vthis->nestedref)
|
||||
if (f->usesThis)
|
||||
{
|
||||
LLValue* thisvar = irfunction->thisVar;
|
||||
LLValue* thisvar = irfunction->thisArg;
|
||||
assert(thisvar);
|
||||
|
||||
LLValue* thismem = DtoAlloca(thisvar->getType(), ".newthis");
|
||||
LLValue* thismem = DtoAlloca(thisvar->getType(), ".this");
|
||||
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)
|
||||
DtoDwarfLocalVariable(thismem, fd->vthis);
|
||||
|
||||
if (fd->vthis->nestedref)
|
||||
fd->nestedVars.insert(fd->vthis);
|
||||
}
|
||||
|
||||
// give arguments storage
|
||||
|
@ -600,13 +626,16 @@ void DtoDefineFunc(FuncDeclaration* fd)
|
|||
Dsymbol* argsym = (Dsymbol*)fd->parameters->data[i];
|
||||
VarDeclaration* vd = argsym->isVarDeclaration();
|
||||
assert(vd);
|
||||
|
||||
if (vd->nestedref)
|
||||
fd->nestedVars.insert(vd);
|
||||
|
||||
IrLocal* irloc = vd->ir.irLocal;
|
||||
assert(irloc);
|
||||
|
||||
bool refoutlazy = vd->storage_class & (STCref | STCout | STClazy);
|
||||
|
||||
if (vd->nestedref || refoutlazy)
|
||||
if (refoutlazy)
|
||||
{
|
||||
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)
|
||||
if (fd->vresult && fd->vresult->nestedref) {
|
||||
Logger::println("nested vresult value: %s", fd->vresult->toChars());
|
||||
fd->nestedVars.insert(fd->vresult);
|
||||
}
|
||||
|
||||
// construct nested variables struct
|
||||
if (!fd->nestedVars.empty() || parentNested) {
|
||||
std::vector<const LLType*> nestTypes;
|
||||
int j = 0;
|
||||
if (parentNested) {
|
||||
nestTypes.push_back(parentNested->getType());
|
||||
j++;
|
||||
// construct nested variables array
|
||||
if (!fd->nestedVars.empty())
|
||||
{
|
||||
Logger::println("has nested frame");
|
||||
// start with add all enclosing parent frames
|
||||
int nparelems = 0;
|
||||
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;
|
||||
Logger::println("referenced nested variable %s", vd->toChars());
|
||||
if (!vd->ir.irLocal)
|
||||
vd->ir.irLocal = new IrLocal(vd);
|
||||
vd->ir.irLocal->nestedIndex = j++;
|
||||
if (vd->isParameter()) {
|
||||
if (!vd->ir.irLocal->value) {
|
||||
assert(vd == fd->vthis);
|
||||
vd->ir.irLocal->value = fd->ir.irFunc->thisVar;
|
||||
}
|
||||
assert(vd->ir.irLocal->value);
|
||||
nestTypes.push_back(vd->ir.irLocal->value->getType());
|
||||
|
||||
if (vd->isParameter())
|
||||
{
|
||||
Logger::println("nested param: %s", vd->toChars());
|
||||
LLValue* gep = DtoGEPi(nestedVars, 0, idx);
|
||||
LLValue* val = DtoBitCast(vd->ir.irLocal->value, getVoidPtrType());
|
||||
DtoStore(val, gep);
|
||||
}
|
||||
else {
|
||||
nestTypes.push_back(DtoType(vd->type));
|
||||
else
|
||||
{
|
||||
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';
|
||||
fd->ir.irFunc->nestedVar = DtoAlloca(nestSType,"nestedvars");
|
||||
if (parentNested) {
|
||||
assert(fd->ir.irFunc->thisVar);
|
||||
LLValue* ptr = gIR->ir->CreateBitCast(fd->ir.irFunc->thisVar, parentNested->getType(), "tmp");
|
||||
gIR->ir->CreateStore(ptr, DtoGEPi(fd->ir.irFunc->nestedVar, 0,0, "tmp"));
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
// fixup nested result variable
|
||||
if (fd->vresult && fd->vresult->nestedref) {
|
||||
Logger::println("nested vresult value: %s", fd->vresult->toChars());
|
||||
LLValue* gep = DtoGEPi(nestedVars, 0, fd->vresult->ir.irLocal->nestedIndex);
|
||||
LLValue* val = DtoBitCast(fd->vresult->ir.irLocal->value, getVoidPtrType());
|
||||
DtoStore(val, gep);
|
||||
}
|
||||
}
|
||||
|
||||
// copy _argptr to a memory location
|
||||
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());
|
||||
fd->ir.irFunc->_argptr = argptrmem;
|
||||
}
|
||||
|
@ -784,14 +846,14 @@ DValue* DtoArgument(Argument* fnarg, Expression* argexp)
|
|||
if (fnarg && ((fnarg->storageClass & STCref) || (fnarg->storageClass & STCout)))
|
||||
{
|
||||
if (arg->isVar() || arg->isLRValue())
|
||||
arg = new DImValue(argexp->type, arg->getLVal(), false);
|
||||
arg = new DImValue(argexp->type, arg->getLVal());
|
||||
else
|
||||
arg = new DImValue(argexp->type, arg->getRVal(), false);
|
||||
arg = new DImValue(argexp->type, arg->getRVal());
|
||||
}
|
||||
// byval arg, but expr has no storage yet
|
||||
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);
|
||||
DtoAssign(argexp->loc, vv, arg);
|
||||
arg = vv;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef 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* DtoBaseFunctionType(FuncDeclaration* fdecl);
|
||||
|
|
|
@ -349,154 +349,70 @@ void DtoLeaveMonitor(LLValue* v)
|
|||
// NESTED VARIABLE HELPERS
|
||||
////////////////////////////////////////////////////////////////////////////////////////*/
|
||||
|
||||
/*
|
||||
|
||||
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)
|
||||
DValue* DtoNestedVariable(Loc loc, Type* astype, VarDeclaration* vd)
|
||||
{
|
||||
from = from->toParent2();
|
||||
|
||||
// parent is a function
|
||||
if (FuncDeclaration* f = from->isFuncDeclaration())
|
||||
Dsymbol* vdparent = vd->toParent2();
|
||||
assert(vdparent);
|
||||
|
||||
IrFunction* irfunc = gIR->func();
|
||||
|
||||
// is the nested variable in this scope?
|
||||
if (vdparent == irfunc->decl)
|
||||
{
|
||||
IrFunction* irfunc = f->ir.irFunc;
|
||||
// parent has nested var struct
|
||||
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());
|
||||
}
|
||||
LLValue* val = vd->ir.getIrValue();
|
||||
return new DVarValue(astype, vd, val, true);
|
||||
}
|
||||
// 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
|
||||
{
|
||||
assert(0 && "!(class|function)");
|
||||
}
|
||||
ctx = irfunc->nestArg;
|
||||
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;
|
||||
|
||||
int level = 0;
|
||||
|
||||
IrFunction* irfunc = gIR->func();
|
||||
Dsymbol* current = irfunc->decl;
|
||||
|
||||
// this context ?
|
||||
if (current == func)
|
||||
{
|
||||
|
||||
if (irfunc->nestedVar)
|
||||
return irfunc->nestedVar;
|
||||
}
|
||||
|
||||
// otherwise use the context argument
|
||||
LLValue* val = dive_into_nested(current, irfunc->thisVar);
|
||||
current = current->toParent2();
|
||||
assert(val);
|
||||
|
||||
for (;;)
|
||||
else if (irfunc->nestArg)
|
||||
return irfunc->nestArg;
|
||||
else if (irfunc->thisArg)
|
||||
{
|
||||
Logger::cout() << "context: " << *val << '\n';
|
||||
Logger::println("(%d) looking in: %s (%s)", level, current->toPrettyChars(), current->kind());
|
||||
if (FuncDeclaration* f = current->isFuncDeclaration())
|
||||
{
|
||||
if (f == func)
|
||||
{
|
||||
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;
|
||||
ClassDeclaration* cd = irfunc->decl->isMember2()->isClassDeclaration();
|
||||
assert(cd);
|
||||
if (!cd->vthis)
|
||||
return getNullPtr(getVoidPtrType());
|
||||
LLValue* val = DtoLoad(irfunc->thisArg);
|
||||
return DtoLoad(DtoGEPi(val, 0,2+cd->vthis->ir.irField->index, ".vthis"));
|
||||
}
|
||||
|
||||
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)
|
||||
else
|
||||
{
|
||||
LLValue* nest = irfunc->nestedVar;
|
||||
LLValue* v = DtoGEPi(nest, 0, vd->ir.irLocal->nestedIndex, "tmp");
|
||||
// references must be loaded to get the variable address
|
||||
if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type)))
|
||||
v = DtoLoad(v);
|
||||
return new DVarValue(astype, vd, v, true);
|
||||
if (irfunc->decl->isStatic())
|
||||
{
|
||||
irfunc->decl->error("is static and cannot access nested %s %s", sym->kind(), sym->toChars());
|
||||
fatal();
|
||||
}
|
||||
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";
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t = DtoDType(lhs->getType());
|
||||
Type* t2 = DtoDType(rhs->getType());
|
||||
Type* t = lhs->getType()->toBasetype();
|
||||
Type* t2 = rhs->getType()->toBasetype();
|
||||
|
||||
if (t->ty == Tstruct) {
|
||||
if (!t->equals(t2)) {
|
||||
// TODO: fix this, use 'rhs' for something
|
||||
DtoAggrZeroInit(lhs->getLVal());
|
||||
}
|
||||
else if (!rhs->inPlace()) {
|
||||
else {
|
||||
DtoAggrCopy(lhs->getLVal(), rhs->getRVal());
|
||||
}
|
||||
}
|
||||
|
@ -559,7 +475,7 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
|
|||
else if (t->ty == Tdelegate) {
|
||||
if (rhs->isNull())
|
||||
DtoAggrZeroInit(lhs->getLVal());
|
||||
else if (!rhs->inPlace()) {
|
||||
else {
|
||||
LLValue* l = lhs->getLVal();
|
||||
LLValue* r = rhs->getRVal();
|
||||
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);
|
||||
|
||||
Type* to = DtoDType(_to);
|
||||
Type* from = DtoDType(val->getType());
|
||||
Type* to = _to->toBasetype();
|
||||
Type* from = val->getType()->toBasetype();
|
||||
assert(from->isintegral());
|
||||
|
||||
size_t fromsz = from->size();
|
||||
|
@ -720,8 +636,8 @@ DValue* DtoCastPtr(Loc& loc, DValue* val, Type* to)
|
|||
{
|
||||
const LLType* tolltype = DtoType(to);
|
||||
|
||||
Type* totype = DtoDType(to);
|
||||
Type* fromtype = DtoDType(val->getType());
|
||||
Type* totype = to->toBasetype();
|
||||
Type* fromtype = val->getType()->toBasetype();
|
||||
assert(fromtype->ty == Tpointer || fromtype->ty == Tfunction);
|
||||
|
||||
LLValue* rval;
|
||||
|
@ -749,8 +665,8 @@ DValue* DtoCastFloat(Loc& loc, DValue* val, Type* to)
|
|||
|
||||
const LLType* tolltype = DtoType(to);
|
||||
|
||||
Type* totype = DtoDType(to);
|
||||
Type* fromtype = DtoDType(val->getType());
|
||||
Type* totype = to->toBasetype();
|
||||
Type* fromtype = val->getType()->toBasetype();
|
||||
assert(fromtype->isfloating());
|
||||
|
||||
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)
|
||||
{
|
||||
Type* fromtype = DtoDType(val->getType());
|
||||
Type* fromtype = val->getType()->toBasetype();
|
||||
Logger::println("Casting from '%s' to '%s'", fromtype->toChars(), to->toChars());
|
||||
if (fromtype->isintegral()) {
|
||||
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->scope() = IRScope(initbb,endinitbb);
|
||||
DValue* ie = DtoInitializer(gvar, init);
|
||||
if (!ie->inPlace()) {
|
||||
DValue* dst = new DVarValue(t, gvar, true);
|
||||
DtoAssign(init->loc, dst, ie);
|
||||
}
|
||||
|
||||
DVarValue dst(t, gvar, true);
|
||||
DtoAssign(init->loc, &dst, ie);
|
||||
|
||||
gIR->ir->CreateStore(DtoConstBool(true), gflag);
|
||||
gIR->ir->CreateBr(endinitbb);
|
||||
gIR->scope() = IRScope(endinitbb,oldend);
|
||||
|
@ -1001,7 +917,7 @@ void DtoConstInitGlobal(VarDeclaration* vd)
|
|||
}
|
||||
|
||||
const LLType* _type = DtoType(vd->type);
|
||||
Type* t = DtoDType(vd->type);
|
||||
Type* t = vd->type->toBasetype();
|
||||
|
||||
//Logger::cout() << "initializer: " << *_init << '\n';
|
||||
if (_type != _init->getType()) {
|
||||
|
@ -1218,9 +1134,23 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
|
|||
if (vd->nestedref) {
|
||||
Logger::println("has nestedref set");
|
||||
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);
|
||||
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
|
||||
else if(!vd->ir.irLocal) {
|
||||
|
@ -1241,6 +1171,10 @@ DValue* DtoDeclarationExp(Dsymbol* declaration)
|
|||
DtoDwarfLocalVariable(allocainst, vd);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(vd->ir.irLocal->value);
|
||||
}
|
||||
|
||||
Logger::cout() << "llvm value for decl: " << *vd->ir.irLocal->value << '\n';
|
||||
DValue* ie = DtoInitializer(vd->ir.irLocal->value, vd->init);
|
||||
|
|
|
@ -38,9 +38,18 @@ void DtoEnterMonitor(LLValue* v);
|
|||
// leaves a monitor lock
|
||||
void DtoLeaveMonitor(LLValue* v);
|
||||
|
||||
// nested variable/class helpers
|
||||
LLValue* DtoNestedContext(FuncDeclaration* func);
|
||||
DValue* DtoNestedVariable(Type* astype, VarDeclaration* vd);
|
||||
// nested variable and context helpers
|
||||
|
||||
// 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
|
||||
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs);
|
||||
|
|
|
@ -57,7 +57,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
{
|
||||
if (p->topfunc()->getReturnType() == LLType::VoidTy) {
|
||||
IrFunction* f = p->func();
|
||||
assert(f->type->llvmRetInPtr);
|
||||
assert(f->type->retInPtr);
|
||||
assert(f->decl->ir.irFunc->retArg);
|
||||
|
||||
if (global.params.symdebug) DtoDwarfStopPoint(loc.linnum);
|
||||
|
@ -66,8 +66,7 @@ void ReturnStatement::toIR(IRState* p)
|
|||
|
||||
DValue* e = exp->toElem(p);
|
||||
|
||||
if (!e->inPlace())
|
||||
DtoAssign(loc, rvar, e);
|
||||
DtoAssign(loc, rvar, e);
|
||||
|
||||
DtoEnclosingHandlers(enclosinghandler, NULL);
|
||||
|
||||
|
@ -647,8 +646,8 @@ struct Case : Object
|
|||
|
||||
static LLValue* call_string_switch_runtime(llvm::GlobalVariable* table, Expression* e)
|
||||
{
|
||||
Type* dt = DtoDType(e->type);
|
||||
Type* dtnext = DtoDType(dt->next);
|
||||
Type* dt = e->type->toBasetype();
|
||||
Type* dtnext = dt->next->toBasetype();
|
||||
TY ty = dtnext->ty;
|
||||
const char* fname;
|
||||
if (ty == Tchar) {
|
||||
|
@ -934,7 +933,7 @@ void ForeachStatement::toIR(IRState* p)
|
|||
|
||||
// what to iterate
|
||||
DValue* aggrval = aggr->toElem(p);
|
||||
Type* aggrtype = DtoDType(aggr->type);
|
||||
Type* aggrtype = aggr->type->toBasetype();
|
||||
|
||||
// get length and pointer
|
||||
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) {
|
||||
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());
|
||||
assert(vd->ir.irField->index >= 0);
|
||||
if (os == vd->offset && vdtype == t) {
|
||||
|
@ -125,7 +125,7 @@ void DtoResolveStruct(StructDeclaration* sd)
|
|||
if (sd->prot() == PROTprivate && sd->getModule() != gIR->dmodule)
|
||||
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);
|
||||
|
||||
|
@ -279,7 +279,7 @@ void DtoDeclareStruct(StructDeclaration* sd)
|
|||
Logger::println("DtoDeclareStruct(%s): %s", sd->toChars(), sd->loc.toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
TypeStruct* ts = (TypeStruct*)DtoDType(sd->type);
|
||||
TypeStruct* ts = (TypeStruct*)sd->type->toBasetype();
|
||||
|
||||
std::string initname("_D");
|
||||
initname.append(sd->mangle());
|
||||
|
|
|
@ -71,6 +71,7 @@ LLValue* DtoCallableValue(DValue* fn)
|
|||
else if (type->ty == Tdelegate)
|
||||
{
|
||||
LLValue* dg = fn->getRVal();
|
||||
Logger::cout() << "delegate: " << *dg << '\n';
|
||||
LLValue* funcptr = DtoGEPi(dg, 0, 1);
|
||||
return DtoLoad(funcptr);
|
||||
}
|
||||
|
@ -200,10 +201,10 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
TypeFunction* tf = DtoTypeFunction(fnval);
|
||||
|
||||
// misc
|
||||
bool retinptr = tf->llvmRetInPtr;
|
||||
bool usesthis = tf->llvmUsesThis;
|
||||
bool retinptr = tf->retInPtr;
|
||||
bool thiscall = tf->usesThis;
|
||||
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);
|
||||
|
||||
unsigned callconv = DtoCallingConv(tf->linkage);
|
||||
|
@ -221,8 +222,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
llvm::PAListPtr palist;
|
||||
|
||||
// return attrs
|
||||
if (tf->llvmRetAttrs)
|
||||
palist = palist.addAttr(0, tf->llvmRetAttrs);
|
||||
if (tf->retAttrs)
|
||||
palist = palist.addAttr(0, tf->retAttrs);
|
||||
|
||||
// handle implicit arguments
|
||||
std::vector<LLValue*> args;
|
||||
|
@ -237,11 +238,12 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
}
|
||||
|
||||
// then comes a context argument...
|
||||
if(usesthis || delegatecall || nestedcall)
|
||||
if(thiscall || delegatecall || nestedcall)
|
||||
{
|
||||
// ... which can be a 'this' argument
|
||||
if (dfnval && dfnval->vthis)
|
||||
if (thiscall)
|
||||
{
|
||||
assert(dfnval && dfnval->vthis);
|
||||
LLValue* thisarg = DtoBitCast(dfnval->vthis, argiter->get());
|
||||
++argiter;
|
||||
args.push_back(thisarg);
|
||||
|
@ -257,11 +259,8 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
// ... or a nested function context arg
|
||||
else if (nestedcall)
|
||||
{
|
||||
LLValue* contextptr = DtoNestedContext(dfnval->func->toParent2()->isFuncDeclaration());
|
||||
if (!contextptr)
|
||||
contextptr = getNullPtr(getVoidPtrType());
|
||||
else
|
||||
contextptr = DtoBitCast(contextptr, getVoidPtrType());
|
||||
LLValue* contextptr = DtoNestedContext(loc, dfnval->func);
|
||||
contextptr = DtoBitCast(contextptr, getVoidPtrType());
|
||||
++argiter;
|
||||
args.push_back(contextptr);
|
||||
}
|
||||
|
@ -354,7 +353,7 @@ DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions*
|
|||
call->setCallingConv(callconv);
|
||||
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)
|
||||
{
|
||||
const LLType* T = DtoType(type);
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
// defaults
|
||||
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)
|
||||
{
|
||||
const LLType* T = DtoType(type);
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
// defaults
|
||||
LLConstant* name;
|
||||
|
@ -356,7 +356,7 @@ static LLGlobalVariable* dwarfMemberType(unsigned linnum, Type* type, LLGlobalVa
|
|||
static LLGlobalVariable* dwarfCompositeType(Type* type, llvm::GlobalVariable* compileUnit)
|
||||
{
|
||||
const LLType* T = DtoType(type);
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
// defaults
|
||||
LLConstant* name = getNullPtr(getVoidPtrType());
|
||||
|
|
177
gen/toir.cpp
177
gen/toir.cpp
|
@ -106,7 +106,7 @@ DValue* VarExp::toElem(IRState* p)
|
|||
// nested variable
|
||||
else if (vd->nestedref) {
|
||||
Logger::println("nested variable");
|
||||
return DtoNestedVariable(type, vd);
|
||||
return DtoNestedVariable(loc, type, vd);
|
||||
}
|
||||
// function parameter
|
||||
else if (vd->isParameter()) {
|
||||
|
@ -114,7 +114,7 @@ DValue* VarExp::toElem(IRState* p)
|
|||
FuncDeclaration* fd = vd->toParent2()->isFuncDeclaration();
|
||||
if (fd && fd != p->func()->decl) {
|
||||
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())) {
|
||||
return new DVarValue(type, vd, vd->ir.getIrValue(), true);
|
||||
|
@ -151,7 +151,7 @@ DValue* VarExp::toElem(IRState* p)
|
|||
else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
|
||||
{
|
||||
// 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());
|
||||
assert(sdecltype->ty == Tstruct);
|
||||
TypeStruct* ts = (TypeStruct*)sdecltype;
|
||||
|
@ -177,7 +177,7 @@ LLConstant* VarExp::toConstElem(IRState* p)
|
|||
if (SymbolDeclaration* sdecl = var->isSymbolDeclaration())
|
||||
{
|
||||
// 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());
|
||||
assert(sdecltype->ty == Tstruct);
|
||||
TypeStruct* ts = (TypeStruct*)sdecltype;
|
||||
|
@ -242,7 +242,7 @@ LLConstant* RealExp::toConstElem(IRState* p)
|
|||
{
|
||||
Logger::print("RealExp::toConstElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
return DtoConstFP(t, value);
|
||||
}
|
||||
|
||||
|
@ -283,7 +283,7 @@ DValue* ComplexExp::toElem(IRState* p)
|
|||
LLConstant* c = toConstElem(p);
|
||||
|
||||
if (c->isNullValue()) {
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
if (t->ty == Tcomplex32)
|
||||
c = DtoConstFP(Type::tfloat32, 0);
|
||||
else if (t->ty == Tcomplex64)
|
||||
|
@ -314,8 +314,8 @@ DValue* StringExp::toElem(IRState* p)
|
|||
Logger::print("StringExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* dtype = DtoDType(type);
|
||||
Type* cty = DtoDType(dtype->next);
|
||||
Type* dtype = type->toBasetype();
|
||||
Type* cty = dtype->next->toBasetype();
|
||||
|
||||
const LLType* ct = DtoTypeNotVoid(cty);
|
||||
//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());
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* t = DtoDType(type);
|
||||
Type* cty = DtoDType(t->next);
|
||||
Type* t = type->toBasetype();
|
||||
Type* cty = t->next->toBasetype();
|
||||
|
||||
bool nullterm = (t->ty != Tsarray);
|
||||
size_t endlen = nullterm ? len+1 : len;
|
||||
|
@ -472,7 +472,19 @@ DValue* AssignExp::toElem(IRState* p)
|
|||
if (l->isSlice() || l->isComplex())
|
||||
return l;
|
||||
|
||||
#if 0
|
||||
if (type->toBasetype()->ty == Tstruct && e2->type->isintegral())
|
||||
{
|
||||
// handle struct = 0;
|
||||
return l;
|
||||
}
|
||||
else
|
||||
{
|
||||
return r;
|
||||
}
|
||||
#else
|
||||
return r;
|
||||
#endif
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -485,10 +497,10 @@ DValue* AddExp::toElem(IRState* p)
|
|||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = DtoDType(type);
|
||||
Type* e1type = DtoDType(e1->type);
|
||||
Type* e1next = e1type->next ? DtoDType(e1type->next) : NULL;
|
||||
Type* e2type = DtoDType(e2->type);
|
||||
Type* t = type->toBasetype();
|
||||
Type* e1type = e1->type->toBasetype();
|
||||
Type* e1next = e1type->next ? e1type->next->toBasetype() : NULL;
|
||||
Type* e2type = e2->type->toBasetype();
|
||||
|
||||
if (e1type != e2type) {
|
||||
if (llvmFieldIndex) {
|
||||
|
@ -537,10 +549,10 @@ DValue* AddAssignExp::toElem(IRState* p)
|
|||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
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());
|
||||
res = new DImValue(type, gep);
|
||||
}
|
||||
|
@ -565,9 +577,9 @@ DValue* MinExp::toElem(IRState* p)
|
|||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = DtoDType(type);
|
||||
Type* t1 = DtoDType(e1->type);
|
||||
Type* t2 = DtoDType(e2->type);
|
||||
Type* t = type->toBasetype();
|
||||
Type* t1 = e1->type->toBasetype();
|
||||
Type* t2 = e2->type->toBasetype();
|
||||
|
||||
if (t1->ty == Tpointer && t2->ty == Tpointer) {
|
||||
LLValue* lv = l->getRVal();
|
||||
|
@ -603,10 +615,10 @@ DValue* MinAssignExp::toElem(IRState* p)
|
|||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
DValue* res;
|
||||
if (DtoDType(e1->type)->ty == Tpointer) {
|
||||
if (e1->type->toBasetype()->ty == Tpointer) {
|
||||
Logger::println("ptr");
|
||||
LLValue* tmp = r->getRVal();
|
||||
LLValue* zero = llvm::ConstantInt::get(tmp->getType(),0,false);
|
||||
|
@ -770,7 +782,7 @@ DValue* CallExp::toElem(IRState* p)
|
|||
DValue* expv = exp->toElem(p);
|
||||
if (expv->getType()->toBasetype()->ty != 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);
|
||||
VarExp* vexp = (VarExp*)e1;
|
||||
|
||||
if (vexp->var->needThis())
|
||||
{
|
||||
error("need 'this' to access %s", vexp->var->toChars());
|
||||
fatal();
|
||||
}
|
||||
|
||||
// global variable
|
||||
if (VarDeclaration* vd = vexp->var->isVarDeclaration())
|
||||
{
|
||||
|
@ -892,8 +910,8 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
|
||||
DValue* l = e1->toElem(p);
|
||||
|
||||
Type* t = DtoDType(type);
|
||||
Type* e1type = DtoDType(e1->type);
|
||||
Type* t = type->toBasetype();
|
||||
Type* e1type = e1->type->toBasetype();
|
||||
|
||||
//Logger::println("e1type=%s", e1type->toChars());
|
||||
//Logger::cout() << *DtoType(e1type) << '\n';
|
||||
|
@ -910,6 +928,16 @@ DValue* DotVarExp::toElem(IRState* p)
|
|||
DStructIndexVector 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) {
|
||||
TypeClass* tc = (TypeClass*)e1type;
|
||||
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* 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 = DtoLoad(funcval);
|
||||
funcval = DtoGEP(funcval, zero, vtblidx, toChars());
|
||||
|
@ -991,7 +1019,7 @@ DValue* ThisExp::toElem(IRState* p)
|
|||
// FIXME: check for TOKthis in AssertExp instead
|
||||
if (!var)
|
||||
{
|
||||
LLValue* v = p->func()->thisVar;
|
||||
LLValue* v = p->func()->thisArg;
|
||||
assert(v);
|
||||
return new DVarValue(type, v, true);
|
||||
}
|
||||
|
@ -1000,11 +1028,11 @@ DValue* ThisExp::toElem(IRState* p)
|
|||
LLValue* v;
|
||||
if (vd->toParent2() != p->func()->decl) {
|
||||
Logger::println("nested this exp");
|
||||
return DtoNestedVariable(type, vd);
|
||||
return DtoNestedVariable(loc, type, vd);
|
||||
}
|
||||
else {
|
||||
Logger::println("normal this exp");
|
||||
v = p->func()->decl->ir.irFunc->thisVar;
|
||||
v = p->func()->thisArg;
|
||||
}
|
||||
return new DVarValue(type, vd, v, true);
|
||||
}
|
||||
|
@ -1023,7 +1051,7 @@ DValue* IndexExp::toElem(IRState* 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.
|
||||
DValue* r = e2->toElem(p);
|
||||
|
@ -1141,8 +1169,8 @@ DValue* CmpExp::toElem(IRState* p)
|
|||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = DtoDType(e1->type);
|
||||
Type* e2t = DtoDType(e2->type);
|
||||
Type* t = e1->type->toBasetype();
|
||||
Type* e2t = e2->type->toBasetype();
|
||||
assert(DtoType(t) == DtoType(e2t));
|
||||
|
||||
LLValue* eval = 0;
|
||||
|
@ -1254,8 +1282,8 @@ DValue* EqualExp::toElem(IRState* p)
|
|||
DValue* l = e1->toElem(p);
|
||||
DValue* r = e2->toElem(p);
|
||||
|
||||
Type* t = DtoDType(e1->type);
|
||||
Type* e2t = DtoDType(e2->type);
|
||||
Type* t = e1->type->toBasetype();
|
||||
Type* e2t = e2->type->toBasetype();
|
||||
//assert(t == e2t);
|
||||
|
||||
LLValue* eval = 0;
|
||||
|
@ -1341,8 +1369,8 @@ DValue* PostExp::toElem(IRState* p)
|
|||
LLValue* val = l->getRVal();
|
||||
LLValue* post = 0;
|
||||
|
||||
Type* e1type = DtoDType(e1->type);
|
||||
Type* e2type = DtoDType(e2->type);
|
||||
Type* e1type = e1->type->toBasetype();
|
||||
Type* e2type = e2->type->toBasetype();
|
||||
|
||||
if (e1type->isintegral())
|
||||
{
|
||||
|
@ -1379,7 +1407,7 @@ DValue* PostExp::toElem(IRState* p)
|
|||
|
||||
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;
|
||||
|
||||
assert(newtype);
|
||||
Type* ntype = DtoDType(newtype);
|
||||
Type* ntype = newtype->toBasetype();
|
||||
|
||||
// new class
|
||||
if (ntype->ty == Tclass) {
|
||||
Logger::println("new class");
|
||||
return DtoNewClass((TypeClass*)ntype, this);
|
||||
return DtoNewClass(loc, (TypeClass*)ntype, this);
|
||||
}
|
||||
// new dynamic array
|
||||
else if (ntype->ty == Tarray)
|
||||
|
@ -1439,7 +1467,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||
assert(ts->sym);
|
||||
DtoAggrCopy(mem,ts->sym->ir.irStruct->init);
|
||||
}
|
||||
return new DImValue(type, mem, false);
|
||||
return new DImValue(type, mem);
|
||||
}
|
||||
// new basic type
|
||||
else
|
||||
|
@ -1454,7 +1482,7 @@ DValue* NewExp::toElem(IRState* p)
|
|||
DtoAssign(loc, &tmpvar, iv);
|
||||
|
||||
// return as pointer-to
|
||||
return new DImValue(type, mem, false);
|
||||
return new DImValue(type, mem);
|
||||
}
|
||||
|
||||
assert(0);
|
||||
|
@ -1468,7 +1496,7 @@ DValue* DeleteExp::toElem(IRState* p)
|
|||
LOG_SCOPE;
|
||||
|
||||
DValue* dval = e1->toElem(p);
|
||||
Type* et = DtoDType(e1->type);
|
||||
Type* et = e1->type->toBasetype();
|
||||
|
||||
// simple pointer
|
||||
if (et->ty == Tpointer)
|
||||
|
@ -1763,12 +1791,13 @@ DValue* DelegateExp::toElem(IRState* p)
|
|||
DValue* u = e1->toElem(p);
|
||||
LLValue* uval;
|
||||
if (DFuncValue* f = u->isFunc()) {
|
||||
assert(f->func);
|
||||
LLValue* contextptr = DtoNestedContext(f->func->toParent2()->isFuncDeclaration());
|
||||
if (!contextptr)
|
||||
uval = LLConstant::getNullValue(getVoidPtrType());
|
||||
assert(f->func);
|
||||
LLValue* contextptr;
|
||||
if (p->func()->decl == f->func)
|
||||
contextptr = p->func()->thisArg;
|
||||
else
|
||||
uval = DtoBitCast(contextptr, getVoidPtrType());
|
||||
contextptr = DtoNestedContext(loc, f->func);
|
||||
uval = DtoBitCast(contextptr, getVoidPtrType());
|
||||
}
|
||||
else {
|
||||
DValue* src = u;
|
||||
|
@ -1892,7 +1921,7 @@ DValue* CondExp::toElem(IRState* p)
|
|||
Logger::print("CondExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
LOG_SCOPE;
|
||||
|
||||
Type* dtype = DtoDType(type);
|
||||
Type* dtype = type->toBasetype();
|
||||
const LLType* resty = DtoType(dtype);
|
||||
|
||||
// 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();
|
||||
Type* t = DtoDType(type);
|
||||
Type* t = type->toBasetype();
|
||||
|
||||
LLValue* zero = 0;
|
||||
if (t->isintegral())
|
||||
|
@ -1975,9 +2004,9 @@ DValue* CatExp::toElem(IRState* p)
|
|||
Logger::print("CatExp::toElem: %s | %s\n", toChars(), type->toChars());
|
||||
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
|
||||
if (arrNarr)
|
||||
|
@ -2001,9 +2030,9 @@ DValue* CatAssignExp::toElem(IRState* p)
|
|||
|
||||
DValue* l = e1->toElem(p);
|
||||
|
||||
Type* e1type = DtoDType(e1->type);
|
||||
Type* elemtype = DtoDType(e1type->next);
|
||||
Type* e2type = DtoDType(e2->type);
|
||||
Type* e1type = e1->type->toBasetype();
|
||||
Type* elemtype = e1type->next->toBasetype();
|
||||
Type* e2type = e2->type->toBasetype();
|
||||
|
||||
if (e2type == elemtype) {
|
||||
DSliceValue* slice = DtoCatAssignElement(l,e2);
|
||||
|
@ -2037,17 +2066,17 @@ DValue* FuncExp::toElem(IRState* p)
|
|||
LLValue* lval = DtoAlloca(dgty,"dgstorage");
|
||||
|
||||
LLValue* context = DtoGEPi(lval,0,0);
|
||||
const LLPointerType* pty = isaPointer(context->getType()->getContainedType(0));
|
||||
LLValue* llvmNested = p->func()->decl->ir.irFunc->nestedVar;
|
||||
if (llvmNested == NULL) {
|
||||
LLValue* nullcontext = llvm::ConstantPointerNull::get(pty);
|
||||
DtoStore(nullcontext, context);
|
||||
}
|
||||
else {
|
||||
LLValue* nestedcontext = DtoBitCast(llvmNested, pty);
|
||||
DtoStore(nestedcontext, context);
|
||||
}
|
||||
|
||||
LLValue* cval;
|
||||
IrFunction* irfn = p->func();
|
||||
if (irfn->nestedVar)
|
||||
cval = irfn->nestedVar;
|
||||
else if (irfn->nestArg)
|
||||
cval = irfn->nestArg;
|
||||
else
|
||||
cval = getNullPtr(getVoidPtrType());
|
||||
cval = DtoBitCast(cval, context->getType()->getContainedType(0));
|
||||
DtoStore(cval, context);
|
||||
|
||||
LLValue* fptr = DtoGEPi(lval,0,1,"tmp",p->scopebb());
|
||||
|
||||
assert(fd->ir.irFunc->func);
|
||||
|
@ -2072,8 +2101,6 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
|
|||
bool dyn = (arrayType->ty == Tarray);
|
||||
// length
|
||||
size_t len = elements->dim;
|
||||
// store into slice?
|
||||
bool sliceInPlace = false;
|
||||
|
||||
// llvm target type
|
||||
const LLType* llType = DtoType(arrayType);
|
||||
|
@ -2096,15 +2123,13 @@ DValue* ArrayLiteralExp::toElem(IRState* p)
|
|||
// emulate assignment
|
||||
DVarValue* vv = new DVarValue(expr->type, elemAddr, true);
|
||||
DValue* e = expr->toElem(p);
|
||||
DImValue* im = e->isIm();
|
||||
if (!im || !im->inPlace()) {
|
||||
DtoAssign(loc, vv, e);
|
||||
}
|
||||
DtoAssign(loc, vv, e);
|
||||
}
|
||||
|
||||
// return storage directly ?
|
||||
if (!dyn || (dyn && sliceInPlace))
|
||||
return new DImValue(type, dstMem, false);
|
||||
if (!dyn)
|
||||
return new DImValue(type, dstMem);
|
||||
|
||||
// wrap in a slice
|
||||
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* ve = vx->toElem(p);
|
||||
|
||||
if (!ve->inPlace())
|
||||
DtoAssign(loc, darrptr, ve);
|
||||
DtoAssign(loc, darrptr, ve);
|
||||
|
||||
j++;
|
||||
}
|
||||
|
@ -2214,7 +2237,7 @@ LLConstant* StructLiteralExp::toConstElem(IRState* p)
|
|||
vals[i] = vx->toConstElem(p);
|
||||
}
|
||||
|
||||
assert(DtoDType(type)->ty == Tstruct);
|
||||
assert(type->toBasetype()->ty == Tstruct);
|
||||
const LLType* t = DtoType(type);
|
||||
const LLStructType* st = isaStruct(t);
|
||||
return llvm::ConstantStruct::get(st,vals);
|
||||
|
@ -2257,7 +2280,7 @@ DValue* AssocArrayLiteralExp::toElem(IRState* p)
|
|||
assert(values);
|
||||
assert(keys->dim == values->dim);
|
||||
|
||||
Type* aatype = DtoDType(type);
|
||||
Type* aatype = type->toBasetype();
|
||||
Type* vtype = aatype->next;
|
||||
const LLType* aalltype = DtoType(type);
|
||||
|
||||
|
|
|
@ -23,14 +23,14 @@
|
|||
|
||||
bool DtoIsPassedByRef(Type* type)
|
||||
{
|
||||
Type* typ = DtoDType(type);
|
||||
Type* typ = type->toBasetype();
|
||||
TY t = typ->ty;
|
||||
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
|
||||
}
|
||||
|
||||
bool DtoIsReturnedInArg(Type* type)
|
||||
{
|
||||
Type* typ = DtoDType(type);
|
||||
Type* typ = type->toBasetype();
|
||||
TY t = typ->ty;
|
||||
return (t == Tstruct || t == Tarray || t == Tdelegate || t == Tsarray || typ->iscomplex());
|
||||
}
|
||||
|
@ -54,16 +54,6 @@ unsigned DtoShouldExtend(Type* type)
|
|||
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)
|
||||
{
|
||||
assert(t);
|
||||
|
@ -143,7 +133,7 @@ const LLType* DtoType(Type* t)
|
|||
case Tfunction:
|
||||
{
|
||||
if (!t->ir.type || *t->ir.type == NULL) {
|
||||
return DtoFunctionType(t,NULL);
|
||||
return DtoFunctionType(t,NULL,NULL);
|
||||
}
|
||||
else {
|
||||
return t->ir.type->get();
|
||||
|
@ -205,7 +195,7 @@ const LLType* DtoTypeNotVoid(Type* t)
|
|||
const LLStructType* DtoDelegateType(Type* t)
|
||||
{
|
||||
const LLType* i8ptr = getVoidPtrType();
|
||||
const LLType* func = DtoFunctionType(t->next, i8ptr);
|
||||
const LLType* func = DtoFunctionType(t->next, NULL, i8ptr);
|
||||
const LLType* funcptr = getPtrToType(func);
|
||||
return LLStructType::get(i8ptr, funcptr, 0);
|
||||
}
|
||||
|
@ -666,8 +656,9 @@ size_t getTypeStoreSize(const LLType* t)
|
|||
|
||||
size_t getABITypeSize(const LLType* t)
|
||||
{
|
||||
Logger::cout() << "getting abi type of: " << *t << '\n';
|
||||
return gTargetData->getABITypeSize(t);
|
||||
size_t sz = gTargetData->getABITypeSize(t);
|
||||
Logger::cout() << "abi type size of: " << *t << " == " << sz << '\n';
|
||||
return sz;
|
||||
}
|
||||
|
||||
unsigned char getABITypeAlign(const LLType* t)
|
||||
|
|
|
@ -23,10 +23,6 @@ bool DtoIsReturnedInArg(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
|
||||
const LLStructType* DtoDelegateType(Type* t);
|
||||
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 getTypeStoreSize(const LLType* t);
|
||||
size_t getABITypeSize(const LLType* t);
|
||||
|
||||
// type alignments
|
||||
unsigned char getABITypeAlign(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)
|
||||
{
|
||||
bool logenabled = Logger::enabled();
|
||||
if (llvmForceLogging && !logenabled)
|
||||
{
|
||||
Logger::enable();
|
||||
}
|
||||
|
||||
Logger::cout() << "Generating module: " << (md ? md->toChars() : toChars()) << '\n';
|
||||
LOG_SCOPE;
|
||||
|
||||
//printf("codegen: %s\n", srcfile->toChars());
|
||||
|
||||
// start by deleting the old object file
|
||||
deleteObjFile();
|
||||
|
||||
|
@ -161,10 +169,10 @@ void Module::genobjfile(int multiobj)
|
|||
|
||||
if (global.params.fqnPaths)
|
||||
{
|
||||
bcpath = LLPath(md->toChars());
|
||||
bcpath = LLPath(mname);
|
||||
bcpath.appendSuffix("bc");
|
||||
|
||||
llpath = LLPath(md->toChars());
|
||||
llpath = LLPath(mname);
|
||||
llpath.appendSuffix("ll");
|
||||
}
|
||||
else
|
||||
|
@ -190,6 +198,11 @@ void Module::genobjfile(int multiobj)
|
|||
delete ir.module;
|
||||
gTargetData = 0;
|
||||
gIR = NULL;
|
||||
|
||||
if (llvmForceLogging && !logenabled)
|
||||
{
|
||||
Logger::disable();
|
||||
}
|
||||
}
|
||||
|
||||
/* ================================================================== */
|
||||
|
|
|
@ -13,7 +13,7 @@ IrFunction::IrFunction(FuncDeclaration* fd)
|
|||
{
|
||||
decl = fd;
|
||||
|
||||
Type* t = DtoDType(fd->type);
|
||||
Type* t = fd->type->toBasetype();
|
||||
assert(t->ty == Tfunction);
|
||||
type = (TypeFunction*)t;
|
||||
func = NULL;
|
||||
|
@ -23,10 +23,14 @@ IrFunction::IrFunction(FuncDeclaration* fd)
|
|||
defined = false;
|
||||
|
||||
retArg = NULL;
|
||||
thisVar = NULL;
|
||||
thisArg = NULL;
|
||||
nestArg = NULL;
|
||||
|
||||
nestedVar = NULL;
|
||||
|
||||
_arguments = NULL;
|
||||
_argptr = NULL;
|
||||
|
||||
dwarfSubProg = NULL;
|
||||
|
||||
srcfileArg = NULL;
|
||||
|
|
|
@ -18,11 +18,16 @@ struct IrFunction : IrBase
|
|||
|
||||
bool queued;
|
||||
bool defined;
|
||||
llvm::Value* retArg;
|
||||
llvm::Value* thisVar;
|
||||
llvm::Value* nestedVar;
|
||||
|
||||
llvm::Value* retArg; // return in ptr arg
|
||||
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* _argptr;
|
||||
|
||||
llvm::Constant* dwarfSubProg;
|
||||
|
||||
llvm::AllocaInst* srcfileArg;
|
||||
|
|
|
@ -79,7 +79,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRcd1.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
|
@ -143,7 +143,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRwd1.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(dchar d; s)
|
||||
|
@ -229,7 +229,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRcw1.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
|
@ -310,7 +310,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRwc1.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
|
@ -389,7 +389,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRdc1.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(char d; s)
|
||||
|
@ -461,7 +461,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRdw1.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(wchar d; s)
|
||||
|
@ -543,7 +543,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRcd2.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
|
@ -608,7 +608,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRwd2.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, dchar d; s)
|
||||
|
@ -696,7 +696,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRcw2.unittest\n");
|
||||
|
||||
auto s = "hello"c;
|
||||
char[] s = "hello"c;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
|
@ -779,7 +779,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRwc2.unittest\n");
|
||||
|
||||
auto s = "hello"w;
|
||||
wchar[] s = "hello"w;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
|
@ -859,7 +859,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRdc2.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, char d; s)
|
||||
|
@ -933,7 +933,7 @@ unittest
|
|||
{
|
||||
debug(apply) printf("_aApplyRdw2.unittest\n");
|
||||
|
||||
auto s = "hello"d;
|
||||
dchar[] s = "hello"d;
|
||||
int i;
|
||||
|
||||
foreach_reverse(k, wchar d; s)
|
||||
|
|
|
@ -101,7 +101,6 @@ alias BB* AA;
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -67,7 +67,7 @@ struct Array
|
|||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) Array _adReverseChar(char[] a)
|
||||
extern (C) char[] _adReverseChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
|
@ -127,14 +127,14 @@ extern (C) Array _adReverseChar(char[] a)
|
|||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return Array(a.length, a.ptr);
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
auto a = "abcd"c;
|
||||
char[] a = "abcd"c;
|
||||
|
||||
auto r = a.dup.reverse;
|
||||
char[] r = a.dup.reverse;
|
||||
//writefln(r);
|
||||
assert(r == "dcba");
|
||||
|
||||
|
@ -162,7 +162,7 @@ unittest
|
|||
* reversed.
|
||||
*/
|
||||
|
||||
extern (C) Array _adReverseWchar(wchar[] a)
|
||||
extern (C) wchar[] _adReverseWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
|
@ -220,13 +220,13 @@ extern (C) Array _adReverseWchar(wchar[] a)
|
|||
hi = hi - 1 + (stridehi - stridelo);
|
||||
}
|
||||
}
|
||||
return Array(a.length, a.ptr);
|
||||
return a;
|
||||
}
|
||||
|
||||
unittest
|
||||
{
|
||||
wstring a = "abcd";
|
||||
wstring r;
|
||||
wchar[] a = "abcd";
|
||||
wchar[] r;
|
||||
|
||||
r = a.dup.reverse;
|
||||
assert(r == "dcba");
|
||||
|
@ -331,7 +331,7 @@ unittest
|
|||
* Sort array of chars.
|
||||
*/
|
||||
|
||||
extern (C) Array _adSortChar(char[] a)
|
||||
extern (C) char[] _adSortChar(char[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
|
@ -346,14 +346,14 @@ extern (C) Array _adSortChar(char[] a)
|
|||
}
|
||||
delete da;
|
||||
}
|
||||
return Array(a.length, a.ptr);
|
||||
return a;
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* Sort array of wchars.
|
||||
*/
|
||||
|
||||
extern (C) Array _adSortWchar(wchar[] a)
|
||||
extern (C) wchar[] _adSortWchar(wchar[] a)
|
||||
{
|
||||
if (a.length > 1)
|
||||
{
|
||||
|
@ -368,7 +368,7 @@ extern (C) Array _adSortWchar(wchar[] a)
|
|||
}
|
||||
delete da;
|
||||
}
|
||||
return Array(a.length, a.ptr);
|
||||
return a;
|
||||
}
|
||||
|
||||
/***************************************
|
||||
|
@ -392,7 +392,7 @@ unittest
|
|||
{
|
||||
debug(adi) printf("array.Eq unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
char[] a = "hello"c;
|
||||
|
||||
assert(a != "hel");
|
||||
assert(a != "helloo");
|
||||
|
@ -425,7 +425,7 @@ unittest
|
|||
{
|
||||
debug(adi) printf("array.Cmp unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
char[] a = "hello"c;
|
||||
|
||||
assert(a > "hel");
|
||||
assert(a >= "hel");
|
||||
|
@ -575,7 +575,7 @@ unittest
|
|||
{
|
||||
debug(adi) printf("array.CmpChar unittest\n");
|
||||
|
||||
auto a = "hello"c;
|
||||
char[] a = "hello"c;
|
||||
|
||||
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*, ...);
|
||||
|
||||
|
|
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()
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
scope c2 = new C2;
|
||||
c2.func2();
|
||||
}
|
||||
auto c2 = new C2;
|
||||
c2.func2();
|
||||
}
|
||||
}
|
||||
|
||||
scope c = new C;
|
||||
auto c = new C;
|
||||
c.func();
|
||||
|
||||
assert(i == 45);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue