Mercurial > projects > ldc
diff gen/tollvm.cpp @ 131:5825d48b27d1 trunk
[svn r135] * Merged DMD 1.025 *
* Fixed a minor linking order mishap *
* Added an command line option -annotate *
* Fixed some problems with running optimizations *
* Added std.stdio and dependencies to lphobos (still not 100% working, but compiles and links) *
* Fixed problems with passing aggregate types to variadic functions *
* Added initial code towards full GC support, currently based on malloc and friends, not all the runtime calls the GC yet for memory *
* Fixed problems with resolving nested function context pointers for some heavily nested cases *
* Redid function argument passing + other minor code cleanups, still lots to do on this end... *
author | lindquist |
---|---|
date | Fri, 04 Jan 2008 01:38:42 +0100 |
parents | 8096ba7082db |
children | 1700239cab2e |
line wrap: on
line diff
--- a/gen/tollvm.cpp Fri Dec 28 23:52:40 2007 +0100 +++ b/gen/tollvm.cpp Fri Jan 04 01:38:42 2008 +0100 @@ -673,156 +673,12 @@ ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Value* DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expression* argexp) -{ - llvm::Value* retval = 0; - - bool haslvals = !gIR->exps.empty(); - if (haslvals) - gIR->exps.push_back(IRExp(NULL,NULL,NULL)); - - DValue* arg = argexp->toElem(gIR); - - if (haslvals) - gIR->exps.pop_back(); - - if (arg->inPlace()) { - retval = arg->getRVal(); - return retval; - } - - Type* realtype = DtoDType(argexp->type); - TY argty = realtype->ty; - if (DtoIsPassedByRef(realtype)) { - if (!fnarg || !fnarg->llvmCopy) { - if (DSliceValue* sv = arg->isSlice()) { - retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint()); - DtoSetArray(retval, DtoArrayLen(sv), DtoArrayPtr(sv)); - } - else if (DComplexValue* cv = arg->isComplex()) { - retval = new llvm::AllocaInst(DtoType(realtype), "tmpparam", gIR->topallocapoint()); - DtoComplexSet(retval, cv->re, cv->im); - } - else { - retval = arg->getRVal(); - } - } - else { - llvm::Value* allocaInst = 0; - llvm::BasicBlock* entryblock = &gIR->topfunc()->front(); - - const llvm::Type* realtypell = DtoType(realtype); - const llvm::PointerType* pty = llvm::PointerType::get(realtypell); - if (argty == Tstruct) { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - DValue* dst = new DVarValue(realtype, allocaInst, true); - DtoAssign(dst,arg); - delete dst; - } - else if (argty == Tdelegate) { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - DValue* dst = new DVarValue(realtype, allocaInst, true); - DtoAssign(dst,arg); - delete dst; - } - else if (argty == Tarray) { - if (arg->isSlice()) { - allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint()); - } - else { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - } - } - else if (realtype->iscomplex()) { - if (arg->isComplex()) { - allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint()); - } - else { - allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - } - } - else - assert(0); - - DValue* dst = new DVarValue(realtype, allocaInst, true); - DtoAssign(dst,arg); - delete dst; - - retval = allocaInst; - } - } - else if (!fnarg || fnarg->llvmCopy) { - Logger::println("regular arg"); - if (DSliceValue* sl = arg->isSlice()) { - if (sl->ptr) Logger::cout() << "ptr = " << *sl->ptr << '\n'; - if (sl->len) Logger::cout() << "len = " << *sl->len << '\n'; - assert(0); - } - else if (DComplexValue* cl = arg->isComplex()) { - assert(0 && "complex in the wrong place"); - } - else { - retval = arg->getRVal(); - } - } - else { - Logger::println("as ptr arg"); - retval = arg->getLVal(); - if (paramtype && retval->getType() != paramtype) - { - assert(0); - /*assert(retval->getType() == paramtype->getContainedType(0)); - new llvm::StoreInst(retval, arg->getLVal(), gIR->scopebb()); - retval = arg->getLVal();*/ - } - } - - if (fnarg && paramtype && retval->getType() != paramtype) { - // this is unfortunately needed with the way SymOffExp is overused - // and static arrays can end up being a pointer to their element type - if (arg->isField()) { - retval = gIR->ir->CreateBitCast(retval, paramtype, "tmp"); - } - else { - Logger::cout() << "got '" << *retval->getType() << "' expected '" << *paramtype << "'\n"; - assert(0 && "parameter type that was actually passed is invalid"); - } - } - - delete arg; - - return retval; -} - -////////////////////////////////////////////////////////////////////////////////////////// - -static void print_frame_worker(VarDeclaration* var, Dsymbol* par) -{ - if (var->toParent2() == par) - { - Logger::println("parent found: '%s' kind: '%s'", par->toChars(), par->kind()); - return; - } - - Logger::println("diving into parent: '%s' kind: '%s'", par->toChars(), par->kind()); - LOG_SCOPE; - print_frame_worker(var, par->toParent2()); -} - -static void print_nested_frame_list(VarDeclaration* var, Dsymbol* par) -{ - Logger::println("PRINTING FRAME LIST FOR NESTED VAR: '%s'", var->toChars()); - { - LOG_SCOPE; - print_frame_worker(var, par); - } - Logger::println("DONE"); -} - static const llvm::Type* get_next_frame_ptr_type(Dsymbol* sc) { assert(sc->isFuncDeclaration() || sc->isClassDeclaration()); Dsymbol* p = sc->toParent2(); + if (!p->isFuncDeclaration() && !p->isClassDeclaration()) + Logger::println("unexpected parent symbol found while resolving frame pointer - '%s' kind: '%s'", p->toChars(), p->kind()); assert(p->isFuncDeclaration() || p->isClassDeclaration()); if (FuncDeclaration* fd = p->isFuncDeclaration()) { @@ -841,21 +697,29 @@ } } -static llvm::Value* get_frame_ptr_impl(VarDeclaration* vd, Dsymbol* sc, llvm::Value* v) +////////////////////////////////////////////////////////////////////////////////////////// + +static llvm::Value* get_frame_ptr_impl(FuncDeclaration* func, Dsymbol* sc, llvm::Value* v) { - if (vd->toParent2() == sc) + LOG_SCOPE; + if (sc == func) { return v; } else if (FuncDeclaration* fd = sc->isFuncDeclaration()) { - Logger::println("scope is function"); + Logger::println("scope is function: %s", fd->toChars()); + + if (fd->toParent2() == func) + { + if (!func->llvmNested) + return NULL; + return DtoBitCast(v, func->llvmNested->getType()); + } + v = DtoBitCast(v, get_next_frame_ptr_type(fd)); Logger::cout() << "v = " << *v << '\n'; - if (fd->toParent2() == vd->toParent2()) - return v; - if (fd->toParent2()->isFuncDeclaration()) { v = DtoGEPi(v, 0,0, "tmp"); @@ -872,33 +736,35 @@ { assert(0); } - return get_frame_ptr_impl(vd, fd->toParent2(), v); + return get_frame_ptr_impl(func, fd->toParent2(), v); } else if (ClassDeclaration* cd = sc->isClassDeclaration()) { - Logger::println("scope is class"); + Logger::println("scope is class: %s", cd->toChars()); /*size_t idx = 2; idx += cd->llvmIRStruct->interfaces.size(); v = DtoGEPi(v,0,idx,"tmp"); Logger::cout() << "gep = " << *v << '\n'; v = DtoLoad(v);*/ - return get_frame_ptr_impl(vd, cd->toParent2(), v); + return get_frame_ptr_impl(func, cd->toParent2(), v); } else { - Logger::println("symbol: '%s'", sc->toChars()); + Logger::println("symbol: '%s'", sc->toPrettyChars()); assert(0); } } -static llvm::Value* get_frame_ptr(VarDeclaration* vd) +////////////////////////////////////////////////////////////////////////////////////////// + +static llvm::Value* get_frame_ptr(FuncDeclaration* func) { - Logger::println("RESOLVING FRAME PTR FOR NESTED VAR: '%s'", vd->toChars()); + Logger::println("Resolving context pointer for nested function: '%s'", func->toPrettyChars()); LOG_SCOPE; IRFunction* irfunc = gIR->func(); - // in the parent scope already - if (vd->toParent2() == irfunc->decl) + // in the right scope already + if (func == irfunc->decl) return irfunc->decl->llvmNested; // use the 'this' pointer @@ -906,24 +772,71 @@ assert(ptr); // return the fully resolved frame pointer - ptr = get_frame_ptr_impl(vd, irfunc->decl, ptr); - Logger::cout() << "FOUND: '" << *ptr << "'\n"; + ptr = get_frame_ptr_impl(func, irfunc->decl, ptr); + if (ptr) Logger::cout() << "Found context!" << *ptr; + else Logger::cout() << "NULL context!\n"; return ptr; } +////////////////////////////////////////////////////////////////////////////////////////// + +llvm::Value* DtoNestedContext(FuncDeclaration* func) +{ + // resolve frame ptr + llvm::Value* ptr = get_frame_ptr(func); + Logger::cout() << "Nested context ptr = "; + if (ptr) Logger::cout() << *ptr; + else Logger::cout() << "NULL"; + Logger::cout() << '\n'; + return ptr; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +static void print_frame_worker(VarDeclaration* vd, Dsymbol* par) +{ + if (vd->toParent2() == par) + { + Logger::println("found: '%s' kind: '%s'", par->toChars(), par->kind()); + return; + } + + Logger::println("diving into: '%s' kind: '%s'", par->toChars(), par->kind()); + LOG_SCOPE; + print_frame_worker(vd, par->toParent2()); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +static void print_nested_frame_list(VarDeclaration* vd, Dsymbol* par) +{ + Logger::println("Frame pointer list for nested var: '%s'", vd->toPrettyChars()); + LOG_SCOPE; + if (vd->toParent2() != par) + print_frame_worker(vd, par); + else + Logger::println("Found at level 0"); + Logger::println("Done"); +} + +////////////////////////////////////////////////////////////////////////////////////////// + llvm::Value* DtoNestedVariable(VarDeclaration* vd) { // log the frame list IRFunction* irfunc = gIR->func(); - print_nested_frame_list(vd, irfunc->decl); + if (Logger::enabled) + print_nested_frame_list(vd, irfunc->decl); // resolve frame ptr - llvm::Value* ptr = get_frame_ptr(vd); - Logger::cout() << "nested ptr = " << *ptr << '\n'; + FuncDeclaration* func = vd->toParent2()->isFuncDeclaration(); + assert(func); + llvm::Value* ptr = DtoNestedContext(func); + assert(ptr && "nested var, but no context"); // we must cast here to be sure. nested classes just have a void* - ptr = DtoBitCast(ptr, vd->toParent2()->isFuncDeclaration()->llvmNested->getType()); + ptr = DtoBitCast(ptr, func->llvmNested->getType()); // index nested var and load (if necessary) llvm::Value* v = DtoGEPi(ptr, 0, vd->llvmNestedIndex, "tmp"); @@ -931,7 +844,8 @@ if (vd->isParameter() && (vd->isRef() || vd->isOut() || DtoIsPassedByRef(vd->type))) v = DtoLoad(v); - Logger::cout() << "FINAL RESULT: " << *v << '\n'; + // log and return + Logger::cout() << "Nested var ptr = " << *v << '\n'; return v; } @@ -940,6 +854,8 @@ void DtoAssign(DValue* lhs, DValue* rhs) { Logger::cout() << "DtoAssign(...);\n"; + LOG_SCOPE; + Type* t = DtoDType(lhs->getType()); Type* t2 = DtoDType(rhs->getType()); @@ -1024,19 +940,15 @@ DtoComplexAssign(dst, rhs->getRVal()); } else { - llvm::Value* l; - if (DLRValue* lr = lhs->isLRValue()) { - l = lr->getLVal(); - rhs = DtoCast(rhs, lr->getLType()); - } - else { - l = lhs->getLVal(); - } + llvm::Value* l = lhs->getLVal(); llvm::Value* r = rhs->getRVal(); Logger::cout() << "assign\nlhs: " << *l << "rhs: " << *r << '\n'; const llvm::Type* lit = l->getType()->getContainedType(0); - if (r->getType() != lit) { // :( - r = DtoBitCast(r, lit); + if (r->getType() != lit) { + if (DLRValue* lr = lhs->isLRValue()) // handle lvalue cast assignments + r = DtoCast(rhs, lr->getLType())->getRVal(); + else + r = DtoCast(rhs, lhs->getType())->getRVal(); Logger::cout() << "really assign\nlhs: " << *l << "rhs: " << *r << '\n'; } gIR->ir->CreateStore(r, l); @@ -1055,34 +967,38 @@ size_t fromsz = from->size(); size_t tosz = to->size(); - llvm::Value* rval; + llvm::Value* rval = val->getRVal(); + if (rval->getType() == tolltype) { + return new DImValue(_to, rval); + } if (to->isintegral()) { if (fromsz < tosz) { Logger::cout() << "cast to: " << *tolltype << '\n'; if (from->isunsigned() || from->ty == Tbool) { - rval = new llvm::ZExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); + rval = new llvm::ZExtInst(rval, tolltype, "tmp", gIR->scopebb()); } else { - rval = new llvm::SExtInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); + rval = new llvm::SExtInst(rval, tolltype, "tmp", gIR->scopebb()); } } else if (fromsz > tosz) { - rval = new llvm::TruncInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); + rval = new llvm::TruncInst(rval, tolltype, "tmp", gIR->scopebb()); } else { - rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); + rval = new llvm::BitCastInst(rval, tolltype, "tmp", gIR->scopebb()); } } else if (to->isfloating()) { if (from->isunsigned()) { - rval = new llvm::UIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); + rval = new llvm::UIToFPInst(rval, tolltype, "tmp", gIR->scopebb()); } else { - rval = new llvm::SIToFPInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); + rval = new llvm::SIToFPInst(rval, tolltype, "tmp", gIR->scopebb()); } } else if (to->ty == Tpointer) { - rval = gIR->ir->CreateIntToPtr(val->getRVal(), tolltype, "tmp"); + Logger::cout() << "cast pointer: " << *tolltype << '\n'; + rval = gIR->ir->CreateIntToPtr(rval, tolltype, "tmp"); } else { assert(0 && "bad int cast"); @@ -1771,3 +1687,20 @@ DtoDefineDsymbol(dsym); } + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoAnnotation(const char* str) +{ + std::string s("CODE: "); + s.append(str); + char* p = &s[0]; + while (*p) + { + if (*p == '"') + *p = '\''; + ++p; + } + // create a noop with the code as the result name! + gIR->ir->CreateAnd(DtoConstSize_t(0),DtoConstSize_t(0),s.c_str()); +}