# HG changeset patch # User lindquist # Date 1191380192 -7200 # Node ID 37a4fdab33fcbe1c34def07bd920bfa706326529 # Parent 0e86428ee567879b54ed9b07470a5d42c4e29ac3 [svn r19] * Added support for reassigning 'this' inside class constructors. * Added preliminary support for UnrolledLoopStatement. That is foreach on a tuple. diff -r 0e86428ee567 -r 37a4fdab33fc dmd/declaration.h --- a/dmd/declaration.h Wed Oct 03 02:15:12 2007 +0200 +++ b/dmd/declaration.h Wed Oct 03 04:56:32 2007 +0200 @@ -511,6 +511,7 @@ FuncDeclaration *isFuncDeclaration() { return this; } bool llvmQueued; + llvm::Value* llvmThisVar; }; struct FuncAliasDeclaration : FuncDeclaration diff -r 0e86428ee567 -r 37a4fdab33fc dmd/func.c --- a/dmd/func.c Wed Oct 03 02:15:12 2007 +0200 +++ b/dmd/func.c Wed Oct 03 04:56:32 2007 +0200 @@ -74,6 +74,7 @@ nrvo_var = NULL; shidden = NULL; llvmQueued = false; + llvmThisVar = NULL; } Dsymbol *FuncDeclaration::syntaxCopy(Dsymbol *s) diff -r 0e86428ee567 -r 37a4fdab33fc gen/elem.c --- a/gen/elem.c Wed Oct 03 02:15:12 2007 +0200 +++ b/gen/elem.c Wed Oct 03 04:56:32 2007 +0200 @@ -18,6 +18,7 @@ inplace = false; field = false; callconv = (unsigned)-1; + isthis = false; vardecl = 0; funcdecl = 0; diff -r 0e86428ee567 -r 37a4fdab33fc gen/elem.h --- a/gen/elem.h Wed Oct 03 02:15:12 2007 +0200 +++ b/gen/elem.h Wed Oct 03 04:56:32 2007 +0200 @@ -32,6 +32,7 @@ bool inplace; bool field; unsigned callconv; + bool isthis; VarDeclaration* vardecl; FuncDeclaration* funcdecl; diff -r 0e86428ee567 -r 37a4fdab33fc gen/irstate.h --- a/gen/irstate.h Wed Oct 03 02:15:12 2007 +0200 +++ b/gen/irstate.h Wed Oct 03 04:56:32 2007 +0200 @@ -78,9 +78,11 @@ // classes TODO move into IRClass typedef std::vector ClassDeclVec; ClassDeclVec classes; + typedef std::vector FuncDeclVec; typedef std::vector ClassMethodVec; ClassMethodVec classmethods; + typedef std::vector BoolVec; BoolVec queueClassMethods; @@ -111,6 +113,9 @@ // VarDeclaration for __dollar, but I can't see how to get the // array pointer from this :( LvalVec arrays; + + // keeping track of the declaration for the current function body + FuncDeclVec funcdecls; }; #endif // LLVMDC_GEN_IRSTATE_H diff -r 0e86428ee567 -r 37a4fdab33fc gen/statements.c --- a/gen/statements.c Wed Oct 03 02:15:12 2007 +0200 +++ b/gen/statements.c Wed Oct 03 04:56:32 2007 +0200 @@ -27,7 +27,7 @@ #include "gen/runtime.h" #include "gen/arrays.h" -/* --------------------------------------------------------------------------------------- */ +////////////////////////////////////////////////////////////////////////////// void CompoundStatement::toIR(IRState* p) { @@ -71,6 +71,8 @@ //p->bbs.pop(); } +////////////////////////////////////////////////////////////////////////////// + void ReturnStatement::toIR(IRState* p) { static int rsi = 0; @@ -134,6 +136,8 @@ p->scope().returned = true; } +////////////////////////////////////////////////////////////////////////////// + void ExpStatement::toIR(IRState* p) { static int esi = 0; @@ -150,6 +154,8 @@ p->buf.writenl();*/ } +////////////////////////////////////////////////////////////////////////////// + void IfStatement::toIR(IRState* p) { static int wsi = 0; @@ -204,6 +210,8 @@ gIR->scope() = IRScope(endbb,oldend); } +////////////////////////////////////////////////////////////////////////////// + void ScopeStatement::toIR(IRState* p) { Logger::println("ScopeStatement::toIR(): %s", toChars()); @@ -240,6 +248,8 @@ */ } +////////////////////////////////////////////////////////////////////////////// + void WhileStatement::toIR(IRState* p) { static int wsi = 0; @@ -281,6 +291,8 @@ gIR->scope() = IRScope(endbb,oldend); } +////////////////////////////////////////////////////////////////////////////// + void DoStatement::toIR(IRState* p) { static int wsi = 0; @@ -313,6 +325,8 @@ gIR->scope() = IRScope(endbb,oldend); } +////////////////////////////////////////////////////////////////////////////// + void ForStatement::toIR(IRState* p) { static int wsi = 0; @@ -374,6 +388,8 @@ gIR->scope() = IRScope(endbb,oldend); } +////////////////////////////////////////////////////////////////////////////// + void BreakStatement::toIR(IRState* p) { static int wsi = 0; @@ -389,6 +405,8 @@ } } +////////////////////////////////////////////////////////////////////////////// + void ContinueStatement::toIR(IRState* p) { static int wsi = 0; @@ -404,6 +422,8 @@ } } +////////////////////////////////////////////////////////////////////////////// + void OnScopeStatement::toIR(IRState* p) { static int wsi = 0; @@ -414,6 +434,8 @@ //statement->toIR(p); // this seems to be redundant } +////////////////////////////////////////////////////////////////////////////// + void TryFinallyStatement::toIR(IRState* p) { static int wsi = 0; @@ -446,6 +468,8 @@ gIR->scope() = IRScope(endbb,oldend); } +////////////////////////////////////////////////////////////////////////////// + void TryCatchStatement::toIR(IRState* p) { static int wsi = 0; @@ -465,6 +489,8 @@ } } +////////////////////////////////////////////////////////////////////////////// + void ThrowStatement::toIR(IRState* p) { static int wsi = 0; @@ -478,6 +504,8 @@ delete e; } +////////////////////////////////////////////////////////////////////////////// + void SwitchStatement::toIR(IRState* p) { Logger::println("SwitchStatement::toIR(): %s", toChars()); @@ -561,6 +589,35 @@ gIR->scope() = IRScope(endbb,oldend); } +////////////////////////////////////////////////////////////////////////////// + +void UnrolledLoopStatement::toIR(IRState* p) +{ + Logger::println("UnrolledLoopStatement::toIR(): %s", toChars()); + LOG_SCOPE; + + llvm::BasicBlock* oldend = gIR->scopeend(); + llvm::BasicBlock* endbb = new llvm::BasicBlock("unrolledend", p->topfunc(), oldend); + + p->scope() = IRScope(p->scopebb(),endbb); + p->loopbbs.push_back(IRScope(p->scopebb(),endbb)); + + for (int i=0; idim; ++i) + { + Statement* s = (Statement*)statements->data[i]; + s->toIR(p); + } + + p->loopbbs.pop_back(); + + new llvm::BranchInst(endbb, p->scopebb()); + p->scope() = IRScope(endbb,oldend); +} + +////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// + #define STUBST(x) void x::toIR(IRState * p) {error("Statement type "#x" not implemented: %s", toChars());fatal();} //STUBST(BreakStatement); //STUBST(ForStatement); @@ -589,5 +646,5 @@ STUBST(GotoCaseStatement); STUBST(GotoDefaultStatement); STUBST(GotoStatement); -STUBST(UnrolledLoopStatement); +//STUBST(UnrolledLoopStatement); //STUBST(OnScopeStatement); diff -r 0e86428ee567 -r 37a4fdab33fc gen/toir.c --- a/gen/toir.c Wed Oct 03 02:15:12 2007 +0200 +++ b/gen/toir.c Wed Oct 03 04:56:32 2007 +0200 @@ -384,8 +384,19 @@ else if (e1ty == Tclass) { if (e2ty == Tclass) { llvm::Value* tmp = r->getValue(); - Logger::cout() << "tmp: " << *tmp << ", " << *l->mem << '\n'; - new llvm::StoreInst(tmp, l->mem, p->scopebb()); + Logger::cout() << "tmp: " << *tmp << " ||| " << *l->mem << '\n'; + // assignment to this in constructor special case + if (l->isthis) { + FuncDeclaration* fdecl = p->funcdecls.back(); + // respecify the this param + if (!llvm::isa(fdecl->llvmThisVar)) + fdecl->llvmThisVar = new llvm::AllocaInst(tmp->getType(), "newthis", p->topallocapoint()); + new llvm::StoreInst(tmp, fdecl->llvmThisVar, p->scopebb()); + } + // regular class ref -> class ref assignment + else { + new llvm::StoreInst(tmp, l->mem, p->scopebb()); + } } else assert(0); @@ -1218,7 +1229,7 @@ TypeStruct* ts = (TypeStruct*)e1->type->next; ts->sym->offsetToIndex(vd->offset, vdoffsets); Logger::println("Struct member offset:%d", vd->offset); - src = l->val; + src = l->val ? l->val : l->mem; } else if (e1->type->ty == Tclass) { TypeClass* tc = (TypeClass*)e1->type; @@ -1279,7 +1290,7 @@ elem* e = new elem; if (VarDeclaration* vd = var->isVarDeclaration()) { - assert(vd->llvmValue == 0); + /*assert(vd->llvmValue == 0); llvm::Function* fn = p->topfunc(); assert(fn); @@ -1292,10 +1303,14 @@ v = ++fn->arg_begin(); else v = fn->arg_begin(); - assert(v); + assert(v);*/ - e->val = v; + llvm::Value* v = p->funcdecls.back()->llvmThisVar; + if (llvm::isa(v)) + v = new llvm::LoadInst(v, "tmp", p->scopebb()); + e->mem = v; e->type = elem::VAL; + e->isthis = true; } else { assert(0); @@ -1794,7 +1809,7 @@ e->inplace = true; e->type = elem::VAR; - + return e; } diff -r 0e86428ee567 -r 37a4fdab33fc gen/toobj.c --- a/gen/toobj.c Wed Oct 03 02:15:12 2007 +0200 +++ b/gen/toobj.c Wed Oct 03 04:56:32 2007 +0200 @@ -665,9 +665,20 @@ // function definition if (allow_fbody && fbody != 0) { + gIR->funcdecls.push_back(this); + // first make absolutely sure the type is up to date f->llvmType = llvmValue->getType()->getContainedType(0); + // this handling + if (f->llvmUsesThis) { + if (f->llvmRetInPtr) + llvmThisVar = ++func->arg_begin(); + else + llvmThisVar = func->arg_begin(); + assert(llvmThisVar != 0); + } + if (isMain()) gIR->emitMain = true; @@ -716,6 +727,8 @@ // possibly assert(lastbb->getNumPredecessors() == 0); ??? try it out sometime ... new llvm::UnreachableInst(lastbb); } + + gIR->funcdecls.pop_back(); } } } diff -r 0e86428ee567 -r 37a4fdab33fc test/classes8.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/classes8.d Wed Oct 03 04:56:32 2007 +0200 @@ -0,0 +1,22 @@ +class A { + int i; + int l; + this(bool b,bool b2=false) { + if (b) this = new B; + i = 4; + if (b2) this = new C; + l = 64; + } +} +class B : A{ + this() { + super(false); + } +} +class C : A{ + this() { + super(false); + } +} +void main() { +} diff -r 0e86428ee567 -r 37a4fdab33fc test/unrolled.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/unrolled.d Wed Oct 03 04:56:32 2007 +0200 @@ -0,0 +1,13 @@ +module unrolled; + +void test(T...)(T t) { + foreach (value; t) { + printf("%d\n", value); + if (value == 2) + break; + } +} + +void main() { + test(1,4,3); +}