# HG changeset patch # User lindquist # Date 1195079950 -3600 # Node ID 6789050b5ad1c88cb016cc04134aaa18c78884e0 # Parent c4e161556a21d000753987b7e1559fdb2b405d90 [svn r102] Further delayed emission of function bodies to avoid problems with circular-forward-references. Now uses the DMD _adEq(void[], void[], TypeInfo) runtime function for array equality comparison. diff -r c4e161556a21 -r 6789050b5ad1 gen/arrays.cpp --- a/gen/arrays.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/arrays.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -546,93 +546,60 @@ } ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Value* DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r) + +llvm::Value* DtoArrayEquals(TOK op, DValue* l, DValue* r) { - const char* fname; - if (op == TOKequal) - fname = "_d_static_array_eq"; - else if (op == TOKnotequal) - fname = "_d_static_array_neq"; - else - assert(0); - llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname); - assert(fn); - - assert(l->getType() == r->getType()); - assert(isaPointer(l->getType())); - const llvm::Type* arrty = l->getType()->getContainedType(0); - assert(isaArray(arrty)); - - llvm::Value* ll = new llvm::BitCastInst(l, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb()); - llvm::Value* rr = new llvm::BitCastInst(r, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb()); - llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(),gTargetData->getTypeSize(arrty),false); - - std::vector args; - args.push_back(ll); - args.push_back(rr); - args.push_back(n); - return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb()); -} - -////////////////////////////////////////////////////////////////////////////////////////// - -llvm::Value* DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r) -{ - const char* fname; - if (op == TOKequal) - fname = "_d_dyn_array_eq"; - else if (op == TOKnotequal) - fname = "_d_dyn_array_neq"; - else - assert(0); - llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname); + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_adEq"); assert(fn); - Logger::cout() << "lhsType:" << *l->getType() << "\nrhsType:" << *r->getType() << '\n'; - assert(l->getType() == r->getType()); - assert(isaPointer(l->getType())); - const llvm::StructType* structType = isaStruct(l->getType()->getContainedType(0)); - assert(structType); - const llvm::Type* elemType = structType->getElementType(1)->getContainedType(0); + llvm::Value* lmem; + llvm::Value* rmem; - std::vector arrTypes; - arrTypes.push_back(DtoSize_t()); - arrTypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); - const llvm::StructType* arrType = llvm::StructType::get(arrTypes); - - llvm::Value* llmem = l; - llvm::Value* rrmem = r; - - if (structType != arrType) { - llmem= new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint()); + // cast static arrays to dynamic ones, this turns them into DSliceValues + Type* l_ty = DtoDType(l->getType()); + Type* r_ty = DtoDType(r->getType()); + assert(l_ty->next == r_ty->next); + Type* a_ty = new Type(Tarray, l_ty->next); + if (l_ty->ty == Tsarray) + l = DtoCastArray(l, a_ty); + if (r_ty->ty == Tsarray) + r = DtoCastArray(r, a_ty); - llvm::Value* ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,0, "tmp"),"tmp"); - ll = DtoArrayCastLength(ll, elemType, llvm::Type::Int8Ty); - llvm::Value* lllen = DtoGEPi(llmem, 0,0, "tmp"); - gIR->ir->CreateStore(ll,lllen); - - ll = gIR->ir->CreateLoad(DtoGEPi(l, 0,1, "tmp"),"tmp"); - ll = new llvm::BitCastInst(ll, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb()); - llvm::Value* llptr = DtoGEPi(llmem, 0,1, "tmp"); - gIR->ir->CreateStore(ll,llptr); + // we need to give slices storage + if (l->isSlice()) { + lmem = new llvm::AllocaInst(DtoType(l->getType()), "tmpparam", gIR->topallocapoint()); + DtoSetArray(lmem, DtoArrayLen(l), DtoArrayPtr(l)); + } + else + lmem = l->getRVal(); - rrmem = new llvm::AllocaInst(arrType,"tmparr",gIR->topallocapoint()); + if (r->isSlice()) { + rmem = new llvm::AllocaInst(DtoType(r->getType()), "tmpparam", gIR->topallocapoint()); + DtoSetArray(rmem, DtoArrayLen(r), DtoArrayPtr(r)); + } + else + rmem = r->getRVal(); - llvm::Value* rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,0, "tmp"),"tmp"); - rr = DtoArrayCastLength(rr, elemType, llvm::Type::Int8Ty); - llvm::Value* rrlen = DtoGEPi(rrmem, 0,0, "tmp"); - gIR->ir->CreateStore(rr,rrlen); - - rr = gIR->ir->CreateLoad(DtoGEPi(r, 0,1, "tmp"),"tmp"); - rr = new llvm::BitCastInst(rr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp", gIR->scopebb()); - llvm::Value* rrptr = DtoGEPi(rrmem, 0,1, "tmp"); - gIR->ir->CreateStore(rr,rrptr); - } + const llvm::Type* pt = fn->getFunctionType()->getParamType(0); std::vector args; - args.push_back(llmem); - args.push_back(rrmem); - return new llvm::CallInst(fn, args.begin(), args.end(), "tmp", gIR->scopebb()); + args.push_back(DtoBitCast(lmem,pt)); + args.push_back(DtoBitCast(rmem,pt)); + + TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration(); + if (!ti->llvmValue) { + ti->toObjFile(); + } + Logger::cout() << "typeinfo decl: " << *ti->llvmValue << '\n'; + + pt = fn->getFunctionType()->getParamType(2); + args.push_back(DtoBitCast(ti->llvmValue, pt)); + + llvm::Value* res = gIR->ir->CreateCall(fn, args.begin(), args.end(), "tmp"); + if (op == TOKnotequal) + res = gIR->ir->CreateNot(res, "tmp"); + + return res; } ////////////////////////////////////////////////////////////////////////////////////////// diff -r c4e161556a21 -r 6789050b5ad1 gen/arrays.h --- a/gen/arrays.h Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/arrays.h Wed Nov 14 23:39:10 2007 +0100 @@ -27,9 +27,8 @@ void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src); -llvm::Value* DtoStaticArrayCompare(TOK op, llvm::Value* l, llvm::Value* r); +llvm::Value* DtoArrayEquals(TOK op, DValue* l, DValue* r); -llvm::Value* DtoDynArrayCompare(TOK op, llvm::Value* l, llvm::Value* r); llvm::Value* DtoDynArrayIs(TOK op, llvm::Value* l, llvm::Value* r); llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty); diff -r c4e161556a21 -r 6789050b5ad1 gen/irstate.h --- a/gen/irstate.h Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/irstate.h Wed Nov 14 23:39:10 2007 +0100 @@ -162,6 +162,10 @@ // builder helper IRBuilderHelper ir; + + // functions queued for lazy definition + typedef std::vector FuncDeclVector; + FuncDeclVector funcQueue; }; #endif // LLVMDC_GEN_IRSTATE_H diff -r c4e161556a21 -r 6789050b5ad1 gen/runtime.cpp --- a/gen/runtime.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/runtime.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -61,9 +61,6 @@ llvm::Function* LLVM_D_GetRuntimeFunction(llvm::Module* target, const char* name) { - // TODO maybe check the target module first, to allow overriding the runtime on a pre module basis? - // could be done and seems like it could be neat too :) - if (global.params.noruntime) { error("No implicit runtime calls allowed with -noruntime option enabled"); fatal(); @@ -74,10 +71,14 @@ LLVM_D_InitRuntime(); } - llvm::Function* fn = M->getFunction(name); + llvm::Function* fn = target->getFunction(name); + if (fn) + return fn; + + fn = M->getFunction(name); if (!fn) { - error("Runtime function '%s' was not found", name); - fatal(); + printf("Runtime function '%s' was not found\n", name); + assert(0); //return NULL; } diff -r c4e161556a21 -r 6789050b5ad1 gen/statements.cpp --- a/gen/statements.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/statements.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -26,8 +26,7 @@ void CompoundStatement::toIR(IRState* p) { - static int csi = 0; - Logger::println("CompoundStatement::toIR(%d):\n<<<\n%s>>>", csi++, toChars()); + Logger::println("CompoundStatement::toIR()"); LOG_SCOPE; for (int i=0; idim; i++) diff -r c4e161556a21 -r 6789050b5ad1 gen/toir.cpp --- a/gen/toir.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/toir.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -64,6 +64,7 @@ //allocainst->setAlignment(vd->type->alignsize()); // TODO vd->llvmValue = allocainst; } + Logger::cout() << "llvm value for decl: " << *vd->llvmValue << '\n'; DValue* ie = DtoInitializer(vd->init); } @@ -1364,19 +1365,14 @@ Logger::print("SymOffExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; + assert(0 && "SymOffExp::toElem should no longer be called :/"); + if (VarDeclaration* vd = var->isVarDeclaration()) { Logger::println("VarDeclaration"); if (!vd->llvmTouched && vd->isDataseg()) vd->toObjFile(); - // TODO - /* - if (vd->isTypedefDeclaration()) { - e->istypeinfo = true; - } - */ - assert(vd->llvmValue); Type* t = DtoDType(type); Type* tnext = DtoDType(t->next); @@ -1540,6 +1536,7 @@ llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); llvm::Value* vtblidx = llvm::ConstantInt::get(llvm::Type::Int32Ty, (size_t)fdecl->vtblIndex, false); + Logger::cout() << "vthis: " << *vthis << '\n'; funcval = DtoGEP(vthis, zero, zero, "tmp", p->scopebb()); funcval = new llvm::LoadInst(funcval,"tmp",p->scopebb()); funcval = DtoGEP(funcval, zero, vtblidx, toChars(), p->scopebb()); @@ -1871,15 +1868,10 @@ } eval = new llvm::FCmpInst(cmpop, l->getRVal(), r->getRVal(), "tmp", p->scopebb()); } - else if (t->ty == Tsarray) + else if (t->ty == Tsarray || t->ty == Tarray) { - Logger::println("static array"); - eval = DtoStaticArrayCompare(op,l->getRVal(),r->getRVal()); - } - else if (t->ty == Tarray) - { - Logger::println("dynamic array"); - eval = DtoDynArrayCompare(op,l->getRVal(),r->getRVal()); + Logger::println("static or dynamic array"); + eval = DtoArrayEquals(op,l,r); } else if (t->ty == Tdelegate) { @@ -2568,12 +2560,21 @@ else assert(0); + Logger::cout() << "array literal mem: " << *mem << '\n'; + for (unsigned i=0; idim; ++i) { Expression* expr = (Expression*)elements->data[i]; llvm::Value* elemAddr = DtoGEPi(mem,0,i,"tmp",p->scopebb()); + DVarValue* vv = new DVarValue(expr->type, elemAddr, true); + p->exps.push_back(IRExp(NULL, expr, vv)); DValue* e = expr->toElem(p); - new llvm::StoreInst(e->getRVal(), elemAddr, p->scopebb()); + p->exps.pop_back(); + + DImValue* im = e->isIm(); + if (!im || !im->inPlace()) { + DtoAssign(vv, e); + } } if (ty->ty == Tsarray) diff -r c4e161556a21 -r 6789050b5ad1 gen/tollvm.cpp --- a/gen/tollvm.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/tollvm.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -818,7 +818,7 @@ std::vector v(2); v[0] = i0; v[1] = i1; - Logger::cout() << "DtoGEP: " << *ptr << '\n'; + //Logger::cout() << "DtoGEP: " << *ptr << '\n'; return new llvm::GetElementPtrInst(ptr, v.begin(), v.end(), var, bb?bb:gIR->scopebb()); } @@ -827,15 +827,15 @@ llvm::Value* DtoGEP(llvm::Value* ptr, const std::vector& src, const std::string& var, llvm::BasicBlock* bb) { size_t n = src.size(); - std::vector dst(n); - std::ostream& ostr = Logger::cout(); - ostr << "indices for '" << *ptr << "':"; + std::vector dst(n, NULL); + //std::ostream& ostr = Logger::cout(); + //ostr << "indices for '" << *ptr << "':"; for (size_t i=0; iscopebb()); } @@ -1423,7 +1423,7 @@ { const llvm::Type* tolltype = DtoType(_to); Type* to = DtoDType(_to); - assert(to->ty == Tclass); + assert(to->ty == Tclass || to->ty == Tpointer); llvm::Value* rval = new llvm::BitCastInst(val->getRVal(), tolltype, "tmp", gIR->scopebb()); return new DImValue(_to, rval); } @@ -1628,6 +1628,8 @@ llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t) { + if (v->getType() == t) + return v; return gIR->ir->CreateBitCast(v, t, "tmp"); } diff -r c4e161556a21 -r 6789050b5ad1 gen/toobj.cpp --- a/gen/toobj.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/toobj.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -90,6 +90,14 @@ dsym->toObjFile(); } + // check if there are queued function definitions, if so process their bodies now + if (!ir.funcQueue.empty()) { + size_t n = ir.funcQueue.size(); + for (size_t i=0; itoObjFile(); + } + } + // generate ModuleInfo genmoduleinfo(); @@ -480,7 +488,8 @@ IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); + //mfs[i]->toObjFile(); + gIR->funcQueue.push_back(mfs[i]); } llvmDModule = gIR->dmodule; @@ -693,7 +702,8 @@ IRStruct::FuncDeclVector& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); + //mfs[i]->toObjFile(); + gIR->funcQueue.push_back(mfs[i]); } } diff -r c4e161556a21 -r 6789050b5ad1 gen/typinf.cpp --- a/gen/typinf.cpp Wed Nov 14 20:18:01 2007 +0100 +++ b/gen/typinf.cpp Wed Nov 14 23:39:10 2007 +0100 @@ -243,14 +243,18 @@ Logger::println("TypeInfoDeclaration::toObjFile()"); LOG_SCOPE; + std::string mangled(mangle()); + Logger::println("type = '%s'", tinfo->toChars()); - Logger::println("typeinfo mangle: %s", mangle()); + Logger::println("typeinfo mangle: %s", mangled.c_str()); // this is a declaration of a builtin __initZ var if (tinfo->builtinTypeInfo()) { - llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangle()); + llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str()); assert(llvmValue); - Logger::cout() << "Got typeinfo var:" << '\n' << *llvmValue << '\n'; + mangled.append("__TYPE"); + gIR->module->addTypeName(mangled, llvmValue->getType()->getContainedType(0)); + Logger::println("Got typeinfo var: %s", llvmValue->getName().c_str()); } // custom typedef else { diff -r c4e161556a21 -r 6789050b5ad1 llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Wed Nov 14 20:18:01 2007 +0100 +++ b/llvmdc.kdevelop.filelist Wed Nov 14 23:39:10 2007 +0100 @@ -221,6 +221,7 @@ test/arrayinit.d test/arrays.d test/arrays10.d +test/arrays11.d test/arrays2.d test/arrays3.d test/arrays4.d @@ -377,6 +378,7 @@ test/structs4.d test/structs5.d test/structs6.d +test/structs7.d test/switch1.d test/sync1.d test/templ1.d diff -r c4e161556a21 -r 6789050b5ad1 lphobos/build.sh --- a/lphobos/build.sh Wed Nov 14 20:18:01 2007 +0100 +++ b/lphobos/build.sh Wed Nov 14 23:39:10 2007 +0100 @@ -18,9 +18,6 @@ llvm-as -f -o=obj/moduleinit_backend.bc internal/moduleinit_backend.ll || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/internal.*.bc` ../lib/llvmdcore.bc obj/moduleinit_backend.bc || exit 1 -echo "compiling object implementation" -llvmdc internal/objectimpl.d -c -odobj || exit 1 -llvm-link -f -o=../lib/llvmdcore.bc obj/objectimpl.bc ../lib/llvmdcore.bc || exit 1 echo "compiling typeinfo 1" rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1 @@ -41,6 +38,10 @@ llvmdc internal/adi.d -c -odobj || exit llvm-link -f -o=../lib/llvmdcore.bc obj/adi.bc ../lib/llvmdcore.bc || exit 1 +echo "compiling object implementation" +llvmdc internal/objectimpl.d -c -odobj || exit 1 +llvm-link -f -o=../lib/llvmdcore.bc obj/objectimpl.bc ../lib/llvmdcore.bc || exit 1 + echo "compiling llvm runtime support" rebuild llvmsupport.d -c -oqobj -dc=llvmdc-posix || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/llvm.*.bc` ../lib/llvmdcore.bc || exit 1 diff -r c4e161556a21 -r 6789050b5ad1 lphobos/internal/adi.d --- a/lphobos/internal/adi.d Wed Nov 14 20:18:01 2007 +0100 +++ b/lphobos/internal/adi.d Wed Nov 14 23:39:10 2007 +0100 @@ -38,6 +38,7 @@ import std.outofmemory; import std.utf; +pragma(LLVM_internal, "notypeinfo") struct Array { size_t length; @@ -478,6 +479,7 @@ { printf("%4x %4x\n", (cast(short*)p1)[i], (cast(short*)p2)[i]); } + printf("sz = %u\n", sz); +/ if (sz == 1) diff -r c4e161556a21 -r 6789050b5ad1 test/arrays11.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/arrays11.d Wed Nov 14 23:39:10 2007 +0100 @@ -0,0 +1,51 @@ +module arrays11; + +void ints() +{ + int[] a = [1,2,3,4,5,6]; + {assert(a == a);} + + int[] b = [4,5,6,7,8,9]; + {assert(a != b);} + {assert(a[3..$] == b[0..3]);} +} + +void floats() +{ + float[] a = [1.0f, 2.0f, 3.0f, 4.0f]; + {assert(a == a);} + + float[] b = [2.0f, 3.0f, 5.0f]; + {assert(a != b);} + {assert(a[1..3] == b[0..2]);} +} + +struct S +{ + int i; + int j; + + int opEquals(S s) + { + return (i == s.i) && (j == s.j); + } +} + +void structs() +{ + S[] a = [S(0,0), S(1,0), S(2,0), S(3,0)]; + {assert(a == a);} + S[] b = [S(0,1), S(1,0), S(2,0), S(3,1)]; + {assert(a != b);} + {assert(a[1..3] == b[1..3]);} + + S[2] c = [S(2,0), S(3,1)]; + {assert(c == b[2..$]);} +} + +void main() +{ + ints(); + floats(); + structs(); +}