# HG changeset patch # User lindquist # Date 1200283914 -3600 # Node ID 44a95ac7368a708a801eedb26e968ea0edc0ceb9 # Parent 1700239cab2e8d32e11e8562237a978a176edc40 [svn r137] Many fixes towards tango.io.Console working, but not quite there yet... In particular, assertions has been fixed to include file/line info, and much more! diff -r 1700239cab2e -r 44a95ac7368a bin/llvmdc.conf --- a/bin/llvmdc.conf Fri Jan 11 17:57:40 2008 +0100 +++ b/bin/llvmdc.conf Mon Jan 14 05:11:54 2008 +0100 @@ -1,4 +1,4 @@ [Environment] -DFLAGS=-I%@P%/../tango -E%@P%/../lib -L-L=%@P%/../lib +DFLAGS=-I%@P%/../tango -L-L%@P%/../lib -R%@P%/../lib diff -r 1700239cab2e -r 44a95ac7368a bin/llvmdc.phobos --- a/bin/llvmdc.phobos Fri Jan 11 17:57:40 2008 +0100 +++ b/bin/llvmdc.phobos Mon Jan 14 05:11:54 2008 +0100 @@ -1,4 +1,4 @@ [Environment] -DFLAGS=-I%@P%/../lphobos -E%@P%/../lib -L-L=%@P%/../lib +DFLAGS=-I%@P%/../lphobos -L-L%@P%/../lib -R%@P%/../lib diff -r 1700239cab2e -r 44a95ac7368a dmd/link.c --- a/dmd/link.c Fri Jan 11 17:57:40 2008 +0100 +++ b/dmd/link.c Mon Jan 14 05:11:54 2008 +0100 @@ -283,14 +283,18 @@ * passed with -l. */ - //argv.push((void *)"-lphobos"); // turns into /usr/lib/libphobos.a - argv.push((void *)"-lpthread"); - argv.push((void *)"-lm"); + argv.push((void*)"-ltango-base-c-llvmdc"); + argv.push((void*)"-lpthread"); + argv.push((void*)"-ldl"); + argv.push((void*)"-lm"); - std::string corelibpath = global.params.runtimeImppath; - corelibpath.append("/libtango-base-llvmdc.a"); argv.append(global.params.objfiles); - argv.push((void *)corelibpath.c_str()); + + std::string runtime_path(global.params.runtimePath); + if (*runtime_path.rbegin() != '/') + runtime_path.append("/"); + runtime_path.append("libtango-base-llvmdc.a"); + argv.push((void*)runtime_path.c_str()); if (!global.params.quiet) { diff -r 1700239cab2e -r 44a95ac7368a dmd/mars.c --- a/dmd/mars.c Fri Jan 11 17:57:40 2008 +0100 +++ b/dmd/mars.c Mon Jan 14 05:11:54 2008 +0100 @@ -158,7 +158,7 @@ void usage() { - printf("LLVM D Compiler %s (based on DMD %s)\n%s\n%s\n", + printf("LLVM D Compiler %s (based on DMD %s and LLVM 2.2)\n%s\n%s\n", global.llvmdc_version, global.version, global.copyright, global.written); printf("\ D Language Documentation: http://www.digitalmars.com/d/1.0/index.html\n\ @@ -187,7 +187,6 @@ -Hf write 'header' file to \n\ --help print help\n\ -I where to look for imports\n\ - -E where to look for the core runtime\n\ -J where to look for string imports\n\ -inline do function inlining\n\ -Llinkerflag pass linkerflag to link\n\ @@ -206,6 +205,7 @@ -quiet suppress unnecessary messages\n\ -release compile release version\n\ -run srcfile args... run resulting program, passing args\n\ + -R provide path to the directory containing the runtime library\n\ -unittest compile in unit tests\n\ -v verbose\n\ -vv very verbose (does not include -v)\n\ @@ -386,15 +386,15 @@ } } else if (strcmp(p + 1, "forcebe") == 0) - global.params.forceBE = 1; + global.params.forceBE = 1; else if (strcmp(p + 1, "noruntime") == 0) - global.params.noruntime = 1; + global.params.noruntime = 1; else if (strcmp(p + 1, "noverify") == 0) - global.params.novalidate = 1; + global.params.novalidate = 1; else if (strcmp(p + 1, "dis") == 0) - global.params.disassemble = 1; + global.params.disassemble = 1; else if (strcmp(p + 1, "annotate") == 0) - global.params.llvmAnnotate = 1; + global.params.llvmAnnotate = 1; else if (p[1] == 'o') { switch (p[2]) @@ -503,9 +503,9 @@ global.params.fileImppath = new Array(); global.params.fileImppath->push(p + 2); } - else if (p[1] == 'E') + else if (p[1] == 'R') { - global.params.runtimeImppath = p+2; + global.params.runtimePath = p+2; } else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l') { @@ -671,7 +671,7 @@ if (global.params.llvmArch == 0) { std::string err_str; - const llvm::TargetMachineRegistry::Entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str); + const llvm::TargetMachineRegistry::entry* e = llvm::TargetMachineRegistry::getClosestTargetForJIT(err_str); if (e == 0) { error("Failed to find a default target machine: %s", err_str.c_str()); fatal(); diff -r 1700239cab2e -r 44a95ac7368a dmd/mars.h --- a/dmd/mars.h Fri Jan 11 17:57:40 2008 +0100 +++ b/dmd/mars.h Mon Jan 14 05:11:54 2008 +0100 @@ -131,6 +131,7 @@ char disassemble; char llvmInline; char llvmAnnotate; + char *runtimePath; }; struct Global diff -r 1700239cab2e -r 44a95ac7368a gen/aa.cpp --- a/gen/aa.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/aa.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -86,7 +86,7 @@ pkey = DtoBitCast(pkey, funcTy->getParamType(2)); // valuesize param - llvm::Value* valsize = DtoConstSize_t(gTargetData->getTypeSize(DtoType(type))); + llvm::Value* valsize = DtoConstSize_t(getABITypeSize(DtoType(type))); // build arg vector std::vector args; @@ -99,7 +99,7 @@ llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "aa.index"); // cast return value - const llvm::Type* targettype = llvm::PointerType::get(DtoType(type)); + const llvm::Type* targettype = getPtrToType(DtoType(type)); if (ret->getType() != targettype) ret = DtoBitCast(ret, targettype); diff -r 1700239cab2e -r 44a95ac7368a gen/arrays.cpp --- a/gen/arrays.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/arrays.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -24,7 +24,7 @@ if (at == llvm::Type::VoidTy) { at = llvm::Type::Int8Ty; } - arrty = llvm::PointerType::get(at); + arrty = getPtrToType(at); std::vector members; if (global.params.is64bit) @@ -98,7 +98,7 @@ Logger::cout() << "invalid: " << *src << '\n'; assert(0); } - llvm::Type* dstty = llvm::PointerType::get(arrty->getElementType()); + const llvm::Type* dstty = getPtrToType(arrty->getElementType()); llvm::Value* dstlen = DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); llvm::Value* srclen = DtoConstSize_t(arrty->getNumElements()); @@ -161,10 +161,10 @@ llvm::Constant* c = isaConstant(dim); assert(c); dim = llvm::ConstantExpr::getMul(c, DtoConstSize_t(arrsz)); - ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(finalTy), "tmp"); + ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(finalTy), "tmp"); } else if (isaStruct(t)) { - aggrsz = gTargetData->getTypeSize(t); + aggrsz = getABITypeSize(t); llvm::Constant* c = isaConstant(val); if (c && c->isNullValue()) { llvm::Value* nbytes; @@ -176,7 +176,7 @@ return; } else { - ptr = gIR->ir->CreateBitCast(ptr, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); + ptr = gIR->ir->CreateBitCast(ptr, getPtrToType(llvm::Type::Int8Ty), "tmp"); } } else { @@ -199,11 +199,11 @@ else if (isaPointer(t)) { funcname = "_d_array_init_pointer"; - const llvm::Type* dstty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + const llvm::Type* dstty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); if (args[0]->getType() != dstty) args[0] = new llvm::BitCastInst(args[0],dstty,"tmp",gIR->scopebb()); - const llvm::Type* valty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* valty = getPtrToType(llvm::Type::Int8Ty); if (args[2]->getType() != valty) args[2] = new llvm::BitCastInst(args[2],valty,"tmp",gIR->scopebb()); } @@ -365,7 +365,7 @@ // this means it's a real slice ret = e->ptr; - size_t elembsz = gTargetData->getTypeSize(ret->getType()); + size_t elembsz = getABITypeSize(ret->getType()); llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false); if (isaConstantInt(e->len)) { @@ -378,7 +378,7 @@ else if (isaArray(t)) { ret = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb()); - size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0)); + size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0)); llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false); size_t numelements = isaArray(t)->getNumElements(); @@ -390,7 +390,7 @@ ret = DtoGEPi(e->ptr, 0, 1, "tmp", gIR->scopebb()); ret = new llvm::LoadInst(ret, "tmp", gIR->scopebb()); - size_t elembsz = gTargetData->getTypeSize(ret->getType()->getContainedType(0)); + size_t elembsz = getABITypeSize(ret->getType()->getContainedType(0)); llvm::ConstantInt* elemsz = llvm::ConstantInt::get(DtoSize_t(), elembsz, false); llvm::Value* len = DtoGEPi(e->ptr, 0, 0, "tmp", gIR->scopebb()); @@ -405,7 +405,7 @@ void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src) { - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* sz1; llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb()); @@ -426,7 +426,7 @@ void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src) { - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* sz1; llvm::Value* dstarr = new llvm::BitCastInst(get_slice_ptr(dst,sz1),arrty,"tmp",gIR->scopebb()); @@ -447,10 +447,10 @@ void DtoStaticArrayCopy(llvm::Value* dst, llvm::Value* src) { assert(dst->getType() == src->getType()); - size_t arrsz = gTargetData->getTypeSize(dst->getType()->getContainedType(0)); + size_t arrsz = getABITypeSize(dst->getType()->getContainedType(0)); llvm::Value* n = llvm::ConstantInt::get(DtoSize_t(), arrsz, false); - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); @@ -483,11 +483,11 @@ { const llvm::Type* ty = DtoType(dty); assert(ty != llvm::Type::VoidTy); - size_t sz = gTargetData->getTypeSize(ty); + size_t sz = getABITypeSize(ty); llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false); llvm::Value* bytesize = (sz == 1) ? dim : llvm::BinaryOperator::createMul(n,dim,"tmp",gIR->scopebb()); - llvm::Value* nullptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(ty)); + llvm::Value* nullptr = llvm::ConstantPointerNull::get(getPtrToType(ty)); llvm::Value* newptr = DtoRealloc(nullptr, bytesize); @@ -510,7 +510,7 @@ llvm::Value* ptr = DtoGEPi(arr, 0, 1, "tmp", gIR->scopebb()); llvm::Value* ptrld = new llvm::LoadInst(ptr,"tmp",gIR->scopebb()); - size_t isz = gTargetData->getTypeSize(ptrld->getType()->getContainedType(0)); + size_t isz = getABITypeSize(ptrld->getType()->getContainedType(0)); llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), isz, false); llvm::Value* bytesz = (isz == 1) ? sz : llvm::BinaryOperator::createMul(n,sz,"tmp",gIR->scopebb()); @@ -758,8 +758,8 @@ ////////////////////////////////////////////////////////////////////////////////////////// llvm::Value* DtoArrayCastLength(llvm::Value* len, const llvm::Type* elemty, const llvm::Type* newelemty) { - size_t esz = gTargetData->getTypeSize(elemty); - size_t nsz = gTargetData->getTypeSize(newelemty); + size_t esz = getABITypeSize(elemty); + size_t nsz = getABITypeSize(newelemty); if (esz == nsz) return len; @@ -898,14 +898,14 @@ llvm::Value* ptr = DtoGEPi(u->getRVal(),0,1,"tmp",gIR->scopebb()); rval = new llvm::LoadInst(ptr, "tmp", gIR->scopebb()); if (fromtype->next != totype->next) - rval = gIR->ir->CreateBitCast(rval, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); + rval = gIR->ir->CreateBitCast(rval, getPtrToType(llvm::Type::Int8Ty), "tmp"); } else if (totype->ty == Tarray) { Logger::cout() << "to array" << '\n'; const llvm::Type* ptrty = DtoType(totype->next); if (ptrty == llvm::Type::VoidTy) ptrty = llvm::Type::Int8Ty; - ptrty = llvm::PointerType::get(ptrty); + ptrty = getPtrToType(ptrty); const llvm::Type* ety = DtoType(fromtype->next); if (ety == llvm::Type::VoidTy) diff -r 1700239cab2e -r 44a95ac7368a gen/classes.cpp --- a/gen/classes.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/classes.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -56,7 +56,21 @@ if (cd->llvmResolved) return; cd->llvmResolved = true; - // first resolve the base class + Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); + LOG_SCOPE; + + // get the TypeClass + assert(cd->type->ty == Tclass); + TypeClass* ts = (TypeClass*)cd->type; + + // make sure the IRStruct is created + IRStruct* irstruct = cd->llvmIRStruct; + if (!irstruct) { + irstruct = new IRStruct(ts); + cd->llvmIRStruct = irstruct; + } + + // resolve the base class if (cd->baseClass) { DtoResolveClass(cd->baseClass); } @@ -72,28 +86,18 @@ } } - Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars()); - LOG_SCOPE; - - assert(cd->type->ty == Tclass); - TypeClass* ts = (TypeClass*)cd->type; - - assert(!cd->llvmIRStruct); - IRStruct* irstruct = new IRStruct(ts); - cd->llvmIRStruct = irstruct; - gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); // add vtable ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); - const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get()); + const llvm::Type* vtabty = getPtrToType(ts->llvmVtblType->get()); std::vector fieldtypes; fieldtypes.push_back(vtabty); // add monitor - fieldtypes.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); + fieldtypes.push_back(getPtrToType(llvm::Type::Int8Ty)); // add interface vtables if (cd->vtblInterfaces) @@ -103,7 +107,7 @@ ClassDeclaration *id = b->base; assert(id->type->ty == Tclass); TypeClass* itc = (TypeClass*)id->type; - const llvm::Type* ivtblTy = llvm::PointerType::get(itc->llvmVtblType->get()); + const llvm::Type* ivtblTy = getPtrToType(itc->llvmVtblType->get()); fieldtypes.push_back(ivtblTy); // add this interface to the map @@ -142,12 +146,12 @@ lastoffset = i->first; fieldtype = i->second.type; fieldinit = i->second.var; - prevsize = gTargetData->getTypeSize(fieldtype); + prevsize = getABITypeSize(fieldtype); i->second.var->llvmFieldIndex = idx; } // colliding offset? else if (lastoffset == i->first) { - size_t s = gTargetData->getTypeSize(i->second.type); + size_t s = getABITypeSize(i->second.type); if (s > prevsize) { fieldpad += s - prevsize; prevsize = s; @@ -157,7 +161,7 @@ } // intersecting offset? else if (i->first < (lastoffset + prevsize)) { - size_t s = gTargetData->getTypeSize(i->second.type); + size_t s = getABITypeSize(i->second.type); assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size cd->llvmHasUnions = true; i->second.var->llvmFieldIndex = idx; @@ -180,7 +184,7 @@ lastoffset = i->first; fieldtype = i->second.type; fieldinit = i->second.var; - prevsize = gTargetData->getTypeSize(fieldtype); + prevsize = getABITypeSize(fieldtype); i->second.var->llvmFieldIndex = idx; fieldpad = 0; } @@ -212,6 +216,7 @@ ts->llvmType = new llvm::PATypeHolder(structtype); else *ts->llvmType = structtype; + spa = *ts->llvmType; // name the type gIR->module->addTypeName(cd->mangle(), ts->llvmType->get()); @@ -221,11 +226,11 @@ // ClassInfo classinfo ClassDeclaration* cinfod = ClassDeclaration::classinfo; DtoResolveClass(cinfod); - infoTypes.push_back(llvm::PointerType::get(cinfod->type->llvmType->get())); + infoTypes.push_back(getPtrToType(cinfod->type->llvmType->get())); // void*[] vtbl std::vector infoVtbltypes; infoVtbltypes.push_back(DtoSize_t()); - const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); infoVtbltypes.push_back(byteptrptrty); infoTypes.push_back(llvm::StructType::get(infoVtbltypes)); // int offset @@ -247,9 +252,9 @@ DtoResolveFunction(fd); //assert(fd->type->ty == Tfunction); //TypeFunction* tf = (TypeFunction*)fd->type; - //const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); + //const llvm::Type* fpty = getPtrToType(tf->llvmType->get()); const llvm::FunctionType* vfty = DtoBaseFunctionType(fd); - const llvm::Type* vfpty = llvm::PointerType::get(vfty); + const llvm::Type* vfpty = getPtrToType(vfty); sinits_ty.push_back(vfpty); } else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { @@ -266,7 +271,7 @@ // this is the ClassInfo class, the type is this type cinfoty = ts->llvmType->get(); } - const llvm::Type* cty = llvm::PointerType::get(cinfoty); + const llvm::Type* cty = getPtrToType(cinfoty); sinits_ty.push_back(cty); } else @@ -314,8 +319,9 @@ } // interface vtables are emitted by the class implementing them - // also interfaces have no static initializer - if (!cd->isInterfaceDeclaration()) { + // also, interfaces have no static initializer + // also, abstract classes have no vtable + if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { // vtable std::string varname("_D"); varname.append(cd->mangle()); @@ -331,11 +337,11 @@ // ClassInfo classinfo ClassDeclaration* cd2 = ClassDeclaration::classinfo; DtoResolveClass(cd2); - types.push_back(llvm::PointerType::get(cd2->type->llvmType->get())); + types.push_back(getPtrToType(cd2->type->llvmType->get())); // void*[] vtbl std::vector vtbltypes; vtbltypes.push_back(DtoSize_t()); - const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); vtbltypes.push_back(byteptrptrty); types.push_back(llvm::StructType::get(vtbltypes)); // int offset @@ -418,6 +424,12 @@ gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); + // get the struct (class) type + assert(cd->type->ty == Tclass); + TypeClass* ts = (TypeClass*)cd->type; + const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); + const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); + // make sure each offset knows its default initializer for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { @@ -431,11 +443,24 @@ std::vector fieldinits; // first field is always the vtable - assert(cd->llvmVtbl != 0); - fieldinits.push_back(cd->llvmVtbl); + if (cd->isAbstract()) + { + fieldinits.push_back( + llvm::ConstantPointerNull::get( + getPtrToType( + ts->llvmVtblType->get() + ) + ) + ); + } + else + { + assert(cd->llvmVtbl != 0); + fieldinits.push_back(cd->llvmVtbl); + } // then comes monitor - fieldinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + fieldinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); size_t dataoffset = 2; @@ -443,9 +468,16 @@ for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) { IRInterface* iri = i->second; - assert(iri->vtbl); - fieldinits.push_back(iri->vtbl); - ++dataoffset; + if (cd->isAbstract()) + { + fieldinits.push_back(llvm::Constant::getNullValue(iri->vtblTy)); + } + else + { + assert(iri->vtbl); + fieldinits.push_back(iri->vtbl); + ++dataoffset; + } } /* @@ -456,12 +488,6 @@ } */ - // get the struct (class) type - assert(cd->type->ty == Tclass); - TypeClass* ts = (TypeClass*)cd->type; - const llvm::StructType* structtype = isaStruct(ts->llvmType->get()); - const llvm::StructType* vtbltype = isaStruct(ts->llvmVtblType->get()); - // go through the field inits and build the default initializer size_t nfi = irstruct->defaultFields.size(); for (size_t i=0; illvmConstInit = _init; - // generate vtable initializer - std::vector sinits; + // abstract classes have no static vtable + if (!cd->isAbstract()) + { + // generate vtable initializer + std::vector sinits; - for (int k=0; k < cd->vtbl.dim; k++) - { - Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; - assert(dsym); - //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; + for (int k=0; k < cd->vtbl.dim; k++) + { + Dsymbol* dsym = (Dsymbol*)cd->vtbl.data[k]; + assert(dsym); + //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; - if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { - DtoForceDeclareDsymbol(fd); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast(fd->llvmValue); - // cast if necessary (overridden method) - if (c->getType() != vtbltype->getElementType(k)) - c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); - sinits.push_back(c); + if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { + DtoForceDeclareDsymbol(fd); + assert(fd->llvmValue); + llvm::Constant* c = llvm::cast(fd->llvmValue); + // cast if necessary (overridden method) + if (c->getType() != vtbltype->getElementType(k)) + c = llvm::ConstantExpr::getBitCast(c, vtbltype->getElementType(k)); + sinits.push_back(c); + } + else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { + assert(cd->llvmClass); + llvm::Constant* c = cd->llvmClass; + sinits.push_back(c); + } + else + assert(0); } - else if (ClassDeclaration* cd2 = dsym->isClassDeclaration()) { - assert(cd->llvmClass); - llvm::Constant* c = cd->llvmClass; - sinits.push_back(c); - } - else - assert(0); - } - const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); + const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); #if 0 - for (size_t i=0; i< sinits.size(); ++i) - { - Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; - Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; - assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); - } -#endif - - llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); - cd->llvmConstVtbl = llvm::cast(cvtblInit); - - // create interface vtable const initalizers - int idx = 2; - int idxScale = PTRSIZE; - for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) - { - ClassDeclaration* id = i->first; - assert(id->type->ty == Tclass); - TypeClass* its = (TypeClass*)id->type; - - IRInterface* iri = i->second; - BaseClass* b = iri->base; - - const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); - - // generate interface info initializer - std::vector infoInits; - // classinfo - assert(id->llvmClass); - llvm::Constant* c = id->llvmClass; - infoInits.push_back(c); - // vtbl - const llvm::Type* byteptrptrty = llvm::PointerType::get(llvm::PointerType::get(llvm::Type::Int8Ty)); - c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); - c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); - infoInits.push_back(c); - // offset - infoInits.push_back(DtoConstInt(idx*idxScale)); - // create interface info initializer constant - iri->infoInit = llvm::cast(llvm::ConstantStruct::get(iri->infoTy, infoInits)); - - // generate vtable initializer - std::vector iinits; - - // add interface info - iinits.push_back(iri->info); - - for (int k=1; k < b->vtbl.dim; k++) + for (size_t i=0; i< sinits.size(); ++i) { - Logger::println("interface vtbl const init nr. %d", k); - Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; - FuncDeclaration* fd = dsym->isFuncDeclaration(); - assert(fd); - DtoForceDeclareDsymbol(fd); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast(fd->llvmValue); - // we have to bitcast, as the type created in ResolveClass expects a different this type - c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); - iinits.push_back(c); - } - -#if 1 - for (size_t x=0; x< iinits.size(); ++x) - { - Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; - Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; - assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); + Logger::cout() << "field[" << i << "] = " << *svtbl_ty->getElementType(i) << '\n'; + Logger::cout() << "init [" << i << "] = " << *sinits[i]->getType() << '\n'; + assert(svtbl_ty->getElementType(i) == sinits[i]->getType()); } #endif - llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); - iri->vtblInit = llvm::cast(civtblInit); + llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); + cd->llvmConstVtbl = llvm::cast(cvtblInit); + + // create interface vtable const initalizers + int idx = 2; + int idxScale = PTRSIZE; + for (IRStruct::InterfaceIter i=irstruct->interfaces.begin(); i!=irstruct->interfaces.end(); ++i) + { + ClassDeclaration* id = i->first; + assert(id->type->ty == Tclass); + TypeClass* its = (TypeClass*)id->type; + + IRInterface* iri = i->second; + BaseClass* b = iri->base; + + const llvm::StructType* ivtbl_ty = isaStruct(its->llvmVtblType->get()); + + // generate interface info initializer + std::vector infoInits; + // classinfo + assert(id->llvmClass); + llvm::Constant* c = id->llvmClass; + infoInits.push_back(c); + // vtbl + const llvm::Type* byteptrptrty = getPtrToType(getPtrToType(llvm::Type::Int8Ty)); + c = llvm::ConstantExpr::getBitCast(iri->vtbl, byteptrptrty); + c = DtoConstSlice(DtoConstSize_t(b->vtbl.dim), c); + infoInits.push_back(c); + // offset + infoInits.push_back(DtoConstInt(idx*idxScale)); + // create interface info initializer constant + iri->infoInit = llvm::cast(llvm::ConstantStruct::get(iri->infoTy, infoInits)); - idx++; - } + // generate vtable initializer + std::vector iinits; + + // add interface info + iinits.push_back(iri->info); + + for (int k=1; k < b->vtbl.dim; k++) + { + Logger::println("interface vtbl const init nr. %d", k); + Dsymbol* dsym = (Dsymbol*)b->vtbl.data[k]; + FuncDeclaration* fd = dsym->isFuncDeclaration(); + assert(fd); + DtoForceDeclareDsymbol(fd); + assert(fd->llvmValue); + llvm::Constant* c = llvm::cast(fd->llvmValue); + // we have to bitcast, as the type created in ResolveClass expects a different this type + c = llvm::ConstantExpr::getBitCast(c, iri->vtblTy->getContainedType(k)); + iinits.push_back(c); + } + + #if 1 + for (size_t x=0; x< iinits.size(); ++x) + { + Logger::cout() << "field[" << x << "] = " << *ivtbl_ty->getElementType(x) << "\n\n"; + Logger::cout() << "init [" << x << "] = " << *iinits[x] << "\n\n"; + assert(ivtbl_ty->getElementType(x) == iinits[x]->getType()); + } + #endif + + llvm::Constant* civtblInit = llvm::ConstantStruct::get(ivtbl_ty, iinits); + iri->vtblInit = llvm::cast(civtblInit); + + idx++; + } + } // !abstract gIR->classes.pop_back(); gIR->structs.pop_back(); @@ -621,7 +651,9 @@ if (cd->getModule() == gIR->dmodule) { // interfaces don't have initializers - if (!cd->isInterfaceDeclaration()) { + // neither do abstract classes + if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) + { cd->llvmInit->setInitializer(cd->llvmConstInit); cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); @@ -635,7 +667,8 @@ infoInits.push_back(iri->infoInit); } // initialize interface info array - if (!infoInits.empty()) { + if (!infoInits.empty()) + { llvm::Constant* arrInit = llvm::ConstantArray::get(irstruct->interfaceInfosTy, infoInits); irstruct->interfaceInfos->setInitializer(arrInit); } @@ -648,6 +681,141 @@ ////////////////////////////////////////////////////////////////////////////////////////// +DValue* DtoNewClass(TypeClass* tc, NewExp* newexp) +{ + // resolve type + DtoForceDeclareDsymbol(tc->sym); + + // allocate + llvm::Value* mem; + if (newexp->onstack) + { + mem = new llvm::AllocaInst(DtoType(tc)->getContainedType(0), "newclass_alloca", gIR->topallocapoint()); + } + else + { + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_newclass"); + std::vector args; + args.push_back(tc->sym->llvmClass); + mem = gIR->ir->CreateCall(fn, args.begin(), args.end(), "newclass_gc_alloc"); + mem = DtoBitCast(mem, DtoType(tc), "newclass_gc"); + } + + // init + DtoInitClass(tc, mem); + + // init inner-class outer reference + if (newexp->thisexp) + { + Logger::println("Resolving outer class"); + LOG_SCOPE; + DValue* thisval = newexp->thisexp->toElem(gIR); + size_t idx = 2; + idx += tc->sym->llvmIRStruct->interfaces.size(); + llvm::Value* dst = thisval->getRVal(); + llvm::Value* src = DtoGEPi(mem,0,idx,"tmp"); + Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; + DtoStore(dst, src); + } + // set the context for nested classes + else if (tc->sym->isNested()) + { + Logger::println("Resolving nested context"); + LOG_SCOPE; + size_t idx = 2; + idx += tc->sym->llvmIRStruct->interfaces.size(); + llvm::Value* nest = gIR->func()->decl->llvmNested; + if (!nest) + nest = gIR->func()->decl->llvmThisVar; + assert(nest); + llvm::Value* gep = DtoGEPi(mem,0,idx,"tmp"); + nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); + DtoStore(nest, gep); + } + + // call constructor + if (newexp->arguments) + return DtoCallClassCtor(tc, newexp->member, newexp->arguments, mem); + + // return default constructed class + return new DImValue(tc, mem, false); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoInitClass(TypeClass* tc, llvm::Value* dst) +{ + size_t presz = 2*getABITypeSize(DtoSize_t()); + uint64_t n = getABITypeSize(tc->llvmType->get()) - presz; + + // set vtable field seperately, this might give better optimization + assert(tc->sym->llvmVtbl); + DtoStore(tc->sym->llvmVtbl, DtoGEPi(dst,0,0,"vtbl")); + + // monitor always defaults to zero + llvm::Value* tmp = DtoGEPi(dst,0,1,"monitor"); + DtoStore(llvm::Constant::getNullValue(tmp->getType()->getContainedType(0)), tmp); + + // done? + if (n == 0) + return; + + // copy the rest from the static initializer + assert(tc->sym->llvmInit); + assert(dst->getType() == tc->sym->llvmInit->getType()); + + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); + + llvm::Value* dstarr = DtoGEPi(dst,0,2,"tmp"); + dstarr = DtoBitCast(dstarr, arrty); + + llvm::Value* srcarr = DtoGEPi(tc->sym->llvmInit,0,2,"tmp"); + srcarr = DtoBitCast(srcarr, arrty); + + llvm::Function* fn = LLVM_DeclareMemCpy32(); + std::vector llargs; + llargs.resize(4); + llargs[0] = dstarr; + llargs[1] = srcarr; + llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); + llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); + + new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem) +{ + Logger::println("Calling constructor"); + LOG_SCOPE; + + assert(ctor); + DtoForceDeclareDsymbol(ctor); + llvm::Function* fn = llvm::cast(ctor->llvmValue); + TypeFunction* tf = (TypeFunction*)DtoDType(ctor->type); + + std::vector ctorargs; + ctorargs.push_back(mem); + for (size_t i=0; idim; ++i) + { + Expression* ex = (Expression*)arguments->data[i]; + Argument* fnarg = Argument::getNth(tf->parameters, i); + DValue* argval = DtoArgument(fnarg, ex); + llvm::Value* a = argval->getRVal(); + const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1); + if (a->getType() != aty) + a = DtoBitCast(a, aty); + ctorargs.push_back(a); + } + llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", gIR->scopebb()); + call->setCallingConv(DtoCallingConv(LINKd)); + + return new DImValue(type, call, false); +} + +////////////////////////////////////////////////////////////////////////////////////////// + void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance) { Array* arr = &tc->sym->dtors; @@ -661,46 +829,6 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoInitClass(TypeClass* tc, llvm::Value* dst) -{ - assert(gIR); - - assert(tc->llvmType); - uint64_t size_t_size = gTargetData->getTypeSize(DtoSize_t()); - uint64_t n = gTargetData->getTypeSize(tc->llvmType->get()) - size_t_size; - - // set vtable field - llvm::Value* vtblvar = DtoGEPi(dst,0,0,"tmp",gIR->scopebb()); - assert(tc->sym->llvmVtbl); - new llvm::StoreInst(tc->sym->llvmVtbl, vtblvar, gIR->scopebb()); - - // copy the static initializer - if (n > 0) { - assert(tc->sym->llvmInit); - assert(dst->getType() == tc->sym->llvmInit->getType()); - - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); - - llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); - dstarr = DtoGEPi(dstarr,size_t_size,"tmp",gIR->scopebb()); - - llvm::Value* srcarr = new llvm::BitCastInst(tc->sym->llvmInit,arrty,"tmp",gIR->scopebb()); - srcarr = DtoGEPi(srcarr,size_t_size,"tmp",gIR->scopebb()); - - llvm::Function* fn = LLVM_DeclareMemCpy32(); - std::vector llargs; - llargs.resize(4); - llargs[0] = dstarr; - llargs[1] = srcarr; - llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false); - llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - - new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); - } -} - -////////////////////////////////////////////////////////////////////////////////////////// - DValue* DtoCastClass(DValue* val, Type* _to) { Type* to = DtoDType(_to); @@ -717,8 +845,12 @@ TypeClass* fc = (TypeClass*)from; if (tc->sym->isInterfaceDeclaration()) { - assert(!fc->sym->isInterfaceDeclaration()); - return DtoDynamicCastObject(val, _to); + if (fc->sym->isInterfaceDeclaration()) { + return DtoDynamicCastInterface(val, _to); + } + else { + return DtoDynamicCastObject(val, _to); + } } else { int poffset; @@ -805,6 +937,45 @@ ////////////////////////////////////////////////////////////////////////////////////////// +DValue* DtoDynamicCastInterface(DValue* val, Type* _to) +{ + // call: + // Object _d_interface_cast(void* p, ClassInfo c) + + DtoForceDeclareDsymbol(ClassDeclaration::object); + DtoForceDeclareDsymbol(ClassDeclaration::classinfo); + + llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast"); + const llvm::FunctionType* funcTy = func->getFunctionType(); + + std::vector args; + + // void* p + llvm::Value* tmp = val->getRVal(); + tmp = DtoBitCast(tmp, funcTy->getParamType(0)); + args.push_back(tmp); + + // ClassInfo c + TypeClass* to = (TypeClass*)DtoDType(_to); + DtoForceDeclareDsymbol(to->sym); + assert(to->sym->llvmClass); + tmp = to->sym->llvmClass; + // unfortunately this is needed as the implementation of object differs somehow from the declaration + // this could happen in user code as well :/ + tmp = DtoBitCast(tmp, funcTy->getParamType(1)); + args.push_back(tmp); + + // call it + llvm::Value* ret = gIR->ir->CreateCall(func, args.begin(), args.end(), "tmp"); + + // cast return value + ret = DtoBitCast(ret, DtoType(_to)); + + return new DImValue(_to, ret); +} + +////////////////////////////////////////////////////////////////////////////////////////// + static unsigned LLVM_ClassOffsetToIndex(ClassDeclaration* cd, unsigned os, unsigned& idx) { // start at the bottom of the inheritance chain @@ -851,7 +1022,7 @@ if (idxs.empty()) idxs.push_back(0); - const llvm::Type* llt = llvm::PointerType::get(DtoType(t)); + const llvm::Type* llt = getPtrToType(DtoType(t)); const llvm::Type* st = DtoType(cd->type); if (ptr->getType() != st) { assert(cd->llvmHasUnions); @@ -895,7 +1066,7 @@ return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); } else { - const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type)); + const llvm::Type* sty = getPtrToType(DtoType(vd->type)); if (ptr->getType() != sty) { ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp"); std::vector tmp; @@ -910,7 +1081,7 @@ assert(0); - size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); + size_t llt_sz = getABITypeSize(llt->getContainedType(0)); assert(os % llt_sz == 0); ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); @@ -918,6 +1089,29 @@ ////////////////////////////////////////////////////////////////////////////////////////// +llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl) +{ + assert(fdecl->isVirtual());//fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())); + assert(fdecl->vtblIndex > 0); + assert(DtoDType(inst->getType())->ty == Tclass); + + llvm::Value* vthis = inst->getRVal(); + //Logger::cout() << "vthis: " << *vthis << '\n'; + + llvm::Value* funcval; + funcval = DtoGEPi(vthis, 0, 0, "tmp"); + funcval = DtoLoad(funcval); + funcval = DtoGEPi(funcval, 0, fdecl->vtblIndex, fdecl->toPrettyChars()); + funcval = DtoLoad(funcval); + + //assert(funcval->getType() == DtoType(fdecl->type)); + //cc = DtoCallingConv(fdecl->linkage); + + return funcval; +} + +////////////////////////////////////////////////////////////////////////////////////////// + void DtoDeclareClassInfo(ClassDeclaration* cd) { if (cd->llvmClassDeclared) return; @@ -961,7 +1155,7 @@ DtoForceDeclareDsymbol(vd->type->vtinfo); llvm::Constant* c = isaConstant(vd->type->vtinfo->llvmValue); - const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get()); + const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); //Logger::cout() << "tiTy = " << *tiTy << '\n'; types.push_back(tiTy); @@ -1002,7 +1196,7 @@ // OffsetTypeInfo type std::vector elemtypes; elemtypes.push_back(DtoSize_t()); - const llvm::Type* tiTy = llvm::PointerType::get(Type::typeinfo->type->llvmType->get()); + const llvm::Type* tiTy = getPtrToType(Type::typeinfo->type->llvmType->get()); elemtypes.push_back(tiTy); const llvm::StructType* sTy = llvm::StructType::get(elemtypes); @@ -1013,7 +1207,7 @@ std::string name(cd->type->vtinfo->toChars()); name.append("__OffsetTypeInfos"); llvm::GlobalVariable* gvar = new llvm::GlobalVariable(arrTy,true,llvm::GlobalValue::InternalLinkage,arrInit,name,gIR->module); - ptr = llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(sTy)); + ptr = llvm::ConstantExpr::getBitCast(gvar, getPtrToType(sTy)); } else { ptr = llvm::ConstantPointerNull::get(isaPointer(initTy->getElementType(1))); @@ -1026,18 +1220,18 @@ { // construct the function std::vector paramTypes; - paramTypes.push_back(llvm::PointerType::get(cd->type->llvmType->get())); + paramTypes.push_back(getPtrToType(cd->type->llvmType->get())); const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy, paramTypes, false); if (cd->dtors.dim == 0) { - return llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + return llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)); } else if (cd->dtors.dim == 1) { DtorDeclaration *d = (DtorDeclaration *)cd->dtors.data[0]; DtoForceDeclareDsymbol(d); assert(d->llvmValue); - return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), llvm::PointerType::get(llvm::Type::Int8Ty)); + return llvm::ConstantExpr::getBitCast(isaConstant(d->llvmValue), getPtrToType(llvm::Type::Int8Ty)); } std::string gname("_D"); @@ -1060,7 +1254,7 @@ } builder.CreateRetVoid(); - return llvm::ConstantExpr::getBitCast(func, llvm::PointerType::get(llvm::Type::Int8Ty)); + return llvm::ConstantExpr::getBitCast(func, getPtrToType(llvm::Type::Int8Ty)); } static uint build_classinfo_flags(ClassDeclaration* cd) @@ -1121,7 +1315,7 @@ assert(cd->llvmClass); TypeClass* cdty = (TypeClass*)cd->type; - if (!cd->isInterfaceDeclaration()) { + if (!cd->isInterfaceDeclaration() && !cd->isAbstract()) { assert(cd->llvmInit); assert(cd->llvmConstInit); assert(cd->llvmVtbl); @@ -1147,14 +1341,14 @@ inits.push_back(c); // byte[] init - const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty); - if (cd->isInterfaceDeclaration()) { + const llvm::Type* byteptrty = getPtrToType(llvm::Type::Int8Ty); + if (cd->isInterfaceDeclaration() || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(2); } else { c = llvm::ConstantExpr::getBitCast(cd->llvmInit, byteptrty); assert(!cd->llvmConstInit->getType()->isAbstract()); - size_t initsz = gTargetData->getTypeSize(cd->llvmConstInit->getType()); + size_t initsz = getABITypeSize(cd->llvmConstInit->getType()); c = DtoConstSlice(DtoConstSize_t(initsz), c); } inits.push_back(c); @@ -1172,11 +1366,11 @@ inits.push_back(c); // vtbl array - if (cd->isInterfaceDeclaration()) { + if (cd->isInterfaceDeclaration() || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(4); } else { - const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty); + const llvm::Type* byteptrptrty = getPtrToType(byteptrty); assert(!cd->llvmVtbl->getType()->isAbstract()); c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); assert(!cd->llvmConstVtbl->getType()->isAbstract()); @@ -1187,7 +1381,7 @@ // interfaces array IRStruct* irstruct = cd->llvmIRStruct; - if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos) { + if (cd->isInterfaceDeclaration() || !irstruct->interfaceInfos || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(5); } else { @@ -1199,7 +1393,7 @@ inits.push_back(c); // base classinfo - if (cd->baseClass && !cd->isInterfaceDeclaration()) { + if (cd->baseClass && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { DtoDeclareClassInfo(cd->baseClass); c = cd->baseClass->llvmClass; assert(c); @@ -1212,7 +1406,7 @@ } // destructor - if (cd->isInterfaceDeclaration()) { + if (cd->isInterfaceDeclaration() || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(7); } else { @@ -1226,7 +1420,7 @@ inits.push_back(c); // uint flags - if (cd->isInterfaceDeclaration()) { + if (cd->isInterfaceDeclaration() || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(9); } else { @@ -1241,7 +1435,7 @@ inits.push_back(c); // offset typeinfo - if (cd->isInterfaceDeclaration()) { + if (cd->isInterfaceDeclaration() || cd->isAbstract()) { c = cinfo->llvmConstInit->getOperand(11); } else { @@ -1250,7 +1444,7 @@ inits.push_back(c); // default constructor - if (cd->defaultCtor && !cd->isInterfaceDeclaration()) { + if (cd->defaultCtor && !cd->isInterfaceDeclaration() && !cd->isAbstract()) { DtoForceDeclareDsymbol(cd->defaultCtor); c = isaConstant(cd->defaultCtor->llvmValue); const llvm::Type* toTy = cinfo->llvmConstInit->getOperand(12)->getType(); diff -r 1700239cab2e -r 44a95ac7368a gen/classes.h --- a/gen/classes.h Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/classes.h Mon Jan 14 05:11:54 2008 +0100 @@ -24,13 +24,19 @@ void DtoDeclareClassInfo(ClassDeclaration* cd); void DtoDefineClassInfo(ClassDeclaration* cd); +DValue* DtoNewClass(TypeClass* type, NewExp* newexp); +void DtoInitClass(TypeClass* tc, llvm::Value* dst); +DValue* DtoCallClassCtor(TypeClass* type, CtorDeclaration* ctor, Array* arguments, llvm::Value* mem); void DtoCallClassDtors(TypeClass* tc, llvm::Value* instance); -void DtoInitClass(TypeClass* tc, llvm::Value* dst); DValue* DtoCastClass(DValue* val, Type* to); DValue* DtoDynamicCastObject(DValue* val, Type* to); + DValue* DtoCastInterfaceToObject(DValue* val, Type* to); +DValue* DtoDynamicCastInterface(DValue* val, Type* to); llvm::Value* DtoIndexClass(llvm::Value* ptr, ClassDeclaration* cd, Type* t, unsigned os, std::vector& idxs); +llvm::Value* DtoVirtualFunctionPointer(DValue* inst, FuncDeclaration* fdecl); + #endif diff -r 1700239cab2e -r 44a95ac7368a gen/complex.cpp --- a/gen/complex.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/complex.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -135,9 +135,9 @@ llvm::Constant* undef = llvm::UndefValue::get(base); llvm::Constant* zero; if (ty == Tfloat32 || ty == Timaginary32 || ty == Tcomplex32) - zero = llvm::ConstantFP::get(llvm::Type::FloatTy, float(0)); + zero = llvm::ConstantFP::get(llvm::Type::FloatTy, llvm::APFloat(0.0f)); else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tcomplex64 || ty == Tfloat80 || ty == Timaginary80 || ty == Tcomplex80) - zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, double(0)); + zero = llvm::ConstantFP::get(llvm::Type::DoubleTy, llvm::APFloat(0.0)); if (t->isimaginary()) { return new DComplexValue(to, zero, val->getRVal()); diff -r 1700239cab2e -r 44a95ac7368a gen/dwarftypes.cpp --- a/gen/dwarftypes.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/dwarftypes.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -32,10 +32,10 @@ std::vectorStructTy_1_fields; StructType* StructTy_1 = StructType::get(StructTy_1_fields, /*isPacked=*/false); - PointerType* PointerTy_0 = PointerType::get(StructTy_1); + PointerType* PointerTy_0 = PointerType::get(StructTy_1,0); StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0); - PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8)); + PointerType* PointerTy_2 = PointerType::get(IntegerType::get(8),0); StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_2); StructTy_llvm_dbg_basictype_type_fields.push_back(PointerTy_0); @@ -130,33 +130,27 @@ std::vectorFuncTy_3_args; FuncTy_3_args.push_back(PointerTy_0); - ParamAttrsList *FuncTy_3_PAL = 0; FunctionType* FuncTy_3 = FunctionType::get( /*Result=*/Type::VoidTy, /*Params=*/FuncTy_3_args, - /*isVarArg=*/false, - /*ParamAttrs=*/FuncTy_3_PAL); + /*isVarArg=*/false); std::vectorFuncTy_4_args; FuncTy_4_args.push_back(IntegerType::get(32)); FuncTy_4_args.push_back(IntegerType::get(32)); FuncTy_4_args.push_back(PointerTy_0); - ParamAttrsList *FuncTy_4_PAL = 0; FunctionType* FuncTy_4 = FunctionType::get( /*Result=*/Type::VoidTy, /*Params=*/FuncTy_4_args, - /*isVarArg=*/false, - /*ParamAttrs=*/FuncTy_4_PAL); + /*isVarArg=*/false); std::vectorFuncTy_5_args; FuncTy_5_args.push_back(PointerTy_0); FuncTy_5_args.push_back(PointerTy_0); - ParamAttrsList *FuncTy_5_PAL = 0; FunctionType* FuncTy_5 = FunctionType::get( /*Result=*/Type::VoidTy, /*Params=*/FuncTy_5_args, - /*isVarArg=*/false, - /*ParamAttrs=*/FuncTy_5_PAL); + /*isVarArg=*/false); // Function Declarations diff -r 1700239cab2e -r 44a95ac7368a gen/functions.cpp --- a/gen/functions.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/functions.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -47,7 +47,7 @@ assert(rt); Type* rtfin = DtoDType(rt); if (DtoIsPassedByRef(rt)) { - rettype = llvm::PointerType::get(DtoType(rt)); + rettype = getPtrToType(DtoType(rt)); actualRettype = llvm::Type::VoidTy; f->llvmRetInPtr = retinptr = true; } @@ -77,10 +77,10 @@ assert(ti->llvmConstInit); std::vector types; types.push_back(DtoSize_t()); - types.push_back(llvm::PointerType::get(llvm::PointerType::get(ti->llvmConstInit->getType()))); + types.push_back(getPtrToType(getPtrToType(ti->llvmConstInit->getType()))); const llvm::Type* t1 = llvm::StructType::get(types); - paramvec.push_back(llvm::PointerType::get(t1)); - paramvec.push_back(llvm::PointerType::get(llvm::Type::Int8Ty)); + paramvec.push_back(getPtrToType(t1)); + paramvec.push_back(getPtrToType(llvm::Type::Int8Ty)); } size_t n = Argument::dim(f->parameters); @@ -94,23 +94,23 @@ const llvm::Type* at = DtoType(argT); if (isaStruct(at)) { Logger::println("struct param"); - paramvec.push_back(llvm::PointerType::get(at)); + paramvec.push_back(getPtrToType(at)); } else if (isaArray(at)) { Logger::println("sarray param"); assert(argT->ty == Tsarray); - //paramvec.push_back(llvm::PointerType::get(at->getContainedType(0))); - paramvec.push_back(llvm::PointerType::get(at)); + //paramvec.push_back(getPtrToType(at->getContainedType(0))); + paramvec.push_back(getPtrToType(at)); } else if (llvm::isa(at)) { Logger::println("opaque param"); assert(argT->ty == Tstruct || argT->ty == Tclass); - paramvec.push_back(llvm::PointerType::get(at)); + paramvec.push_back(getPtrToType(at)); } else { if ((arg->storageClass & STCref) || (arg->storageClass & STCout)) { Logger::println("by ref param"); - at = llvm::PointerType::get(at); + at = getPtrToType(at); } else { Logger::println("in param"); @@ -146,7 +146,7 @@ TypeFunction* f = (TypeFunction*)fdecl->type; assert(f != 0); - const llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty); std::vector args; if (fdecl->llvmInternal == LLVMva_start) { @@ -194,7 +194,7 @@ thisty = DtoType(ad->type); //Logger::cout() << "this llvm type: " << *thisty << '\n'; if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get())) - thisty = llvm::PointerType::get(thisty); + thisty = getPtrToType(thisty); } else { Logger::println("chars: %s type: %s kind: %s", fdecl->toChars(), fdecl->type->toChars(), fdecl->kind()); @@ -202,7 +202,7 @@ } } else if (fdecl->isNested()) { - thisty = llvm::PointerType::get(llvm::Type::Int8Ty); + thisty = getPtrToType(llvm::Type::Int8Ty); } const llvm::FunctionType* functype = DtoFunctionType(fdecl->type, thisty, fdecl->isMain()); @@ -244,6 +244,13 @@ return; // ignore declaration completely } + // is imported and we don't have access? + if (fdecl->getModule() != gIR->dmodule) + { + if (fdecl->prot() == PROTprivate) + return; + } + if (fdecl->llvmResolved) return; fdecl->llvmResolved = true; @@ -427,6 +434,8 @@ if (!declareOnly) gIR->defineList.push_back(fdecl); + else + assert(func->getLinkage() != llvm::GlobalValue::InternalLinkage); Logger::cout() << "func decl: " << *func << '\n'; } @@ -637,9 +646,9 @@ // parameter types std::vector pvec; pvec.push_back((const llvm::Type*)llvm::Type::Int32Ty); - const llvm::Type* chPtrType = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); - pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); - pvec.push_back((const llvm::Type*)llvm::PointerType::get(chPtrType)); + const llvm::Type* chPtrType = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty); + pvec.push_back((const llvm::Type*)getPtrToType(chPtrType)); + pvec.push_back((const llvm::Type*)getPtrToType(chPtrType)); const llvm::Type* rettype = (const llvm::Type*)llvm::Type::Int32Ty; llvm::FunctionType* functype = llvm::FunctionType::get(rettype, pvec, false); diff -r 1700239cab2e -r 44a95ac7368a gen/runtime.cpp --- a/gen/runtime.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/runtime.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -133,7 +133,7 @@ static const llvm::Type* rt_ptr(const llvm::Type* t) { - return llvm::PointerType::get(t); + return getPtrToType(t); } static const llvm::Type* rt_array(const llvm::Type* elemty) @@ -197,15 +197,30 @@ ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// - // assert - // void _d_assert(bool cond, uint line, char[] msg) + // void _d_assert( char[] file, uint line ) + // void _d_array_bounds( char[] file, uint line ) + // void _d_switch_error( char[] file, uint line ) { std::string fname("_d_assert"); + std::string fname2("_d_array_bounds"); + std::string fname3("_d_switch_error"); std::vector types; - types.push_back(boolTy); + types.push_back(stringTy); types.push_back(intTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname3, M); + } + + // void _d_assert_msg( char[] msg, char[] file, uint line ) + { + std::string fname("_d_assert_msg"); + std::vector types; types.push_back(stringTy); - const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false); + types.push_back(stringTy); + types.push_back(intTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false); new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } @@ -234,6 +249,15 @@ new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } + // Object _d_newclass(ClassInfo ci) + { + std::string fname("_d_newclass"); + std::vector types; + types.push_back(classInfoTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////// @@ -626,6 +650,51 @@ new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname2, M); } + ///////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////// + + // Object _d_toObject(void* p) + { + std::string fname("_d_toObject"); + std::vector types; + types.push_back(voidPtrTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + + // Object _d_dynamic_cast(Object o, ClassInfo c) + { + std::string fname("_d_dynamic_cast"); + std::vector types; + types.push_back(objectTy); + types.push_back(classInfoTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + + // Object _d_interface_cast(void* p, ClassInfo c) + { + std::string fname("_d_interface_cast"); + std::vector types; + types.push_back(voidPtrTy); + types.push_back(classInfoTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } + + ///////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////// + + // void _d_throw_exception(Object e) + { + std::string fname("_d_throw_exception"); + std::vector types; + types.push_back(objectTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false); + new llvm::Function(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } } diff -r 1700239cab2e -r 44a95ac7368a gen/statements.cpp --- a/gen/statements.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/statements.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -8,6 +8,7 @@ #include "gen/llvm.h" #include "llvm/InlineAsm.h" +#include "llvm/Support/CFG.h" #include "mars.h" #include "total.h" @@ -488,17 +489,39 @@ Logger::println("TryCatchStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - Logger::attention(loc, "try-catch is not yet fully implemented, only the try block will be emitted."); + Logger::attention(loc, "try-catch is not yet fully implemented"); + + // create basic blocks + llvm::BasicBlock* oldend = p->scopeend(); + llvm::BasicBlock* trybb = new llvm::BasicBlock("try", p->topfunc(), oldend); + llvm::BasicBlock* catchbb = new llvm::BasicBlock("catch", p->topfunc(), oldend); + llvm::BasicBlock* endbb = new llvm::BasicBlock("endtrycatch", p->topfunc(), oldend); + + // pass the previous BB into this + assert(!gIR->scopereturned()); + new llvm::BranchInst(trybb, p->scopebb()); + + // do the try block + p->scope() = IRScope(trybb,catchbb); assert(body); body->toIR(p); + if (!gIR->scopereturned()) + new llvm::BranchInst(endbb, p->scopebb()); + + // do catch + p->scope() = IRScope(catchbb,oldend); + new llvm::BranchInst(endbb, p->scopebb()); /*assert(catches); for(size_t i=0; idim; ++i) { Catch* c = (Catch*)catches->data[i]; c->handler->toIR(p); }*/ + + // rewrite the scope + p->scope() = IRScope(endbb,oldend); } ////////////////////////////////////////////////////////////////////////////// @@ -508,15 +531,16 @@ Logger::println("ThrowStatement::toIR(): %s", loc.toChars()); LOG_SCOPE; - Logger::attention(loc, "throw is not yet implemented, replacing expression with assert(0);"); + Logger::attention(loc, "throw is not yet fully implemented"); - DtoAssert(NULL, &loc, NULL); - - /* assert(exp); DValue* e = exp->toElem(p); - delete e; - */ + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_throw_exception"); + //Logger::cout() << "calling: " << *fn << '\n'; + llvm::Value* arg = DtoBitCast(e->getRVal(), fn->getFunctionType()->getParamType(0)); + //Logger::cout() << "arg: " << *arg << '\n'; + gIR->ir->CreateCall(fn, arg, ""); + gIR->ir->CreateUnreachable(); } ////////////////////////////////////////////////////////////////////////////// @@ -629,7 +653,7 @@ llvm::Constant* arrInit = llvm::ConstantArray::get(arrTy, inits); llvm::GlobalVariable* arr = new llvm::GlobalVariable(arrTy, true, llvm::GlobalValue::InternalLinkage, arrInit, "string_switch_table_data", gIR->module); - const llvm::Type* elemPtrTy = llvm::PointerType::get(elemTy); + const llvm::Type* elemPtrTy = getPtrToType(elemTy); llvm::Constant* arrPtr = llvm::ConstantExpr::getBitCast(arr, elemPtrTy); // build the static table @@ -824,8 +848,8 @@ if (niters->getType() != keytype) { - size_t sz1 = gTargetData->getTypeSize(niters->getType()); - size_t sz2 = gTargetData->getTypeSize(keytype); + size_t sz1 = getTypeBitSize(niters->getType()); + size_t sz2 = getTypeBitSize(keytype); if (sz1 < sz2) niters = gIR->ir->CreateZExt(niters, keytype, "foreachtrunckey"); else if (sz1 > sz2) diff -r 1700239cab2e -r 44a95ac7368a gen/structs.cpp --- a/gen/structs.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/structs.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -27,11 +27,11 @@ llvm::Value* DtoStructZeroInit(llvm::Value* v) { assert(gIR); - uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0)); - //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); - llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty); + uint64_t n = getTypeStoreSize(v->getType()->getContainedType(0)); + //llvm::Type* sarrty = getPtrToType(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); + const llvm::Type* sarrty = getPtrToType(llvm::Type::Int8Ty); - llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb()); + llvm::Value* sarr = DtoBitCast(v, sarrty); llvm::Function* fn = LLVM_DeclareMemSet32(); std::vector llargs; @@ -54,9 +54,9 @@ assert(dst->getType() == src->getType()); assert(gIR); - uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0)); - //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + uint64_t n = getTypeStoreSize(dst->getType()->getContainedType(0)); + //llvm::Type* sarrty = getPtrToType(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); @@ -110,8 +110,8 @@ if (idxs.empty()) idxs.push_back(0); - const llvm::Type* llt = llvm::PointerType::get(DtoType(t)); - const llvm::Type* st = llvm::PointerType::get(DtoType(sd->type)); + const llvm::Type* llt = getPtrToType(DtoType(t)); + const llvm::Type* st = getPtrToType(DtoType(sd->type)); if (ptr->getType() != st) { assert(sd->llvmHasUnions); ptr = gIR->ir->CreateBitCast(ptr, st, "tmp"); @@ -139,15 +139,15 @@ Logger::println("has union field offset"); ptr = DtoGEP(ptr, idxs, "tmp"); if (ptr->getType() != llt) - ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); + ptr = DtoBitCast(ptr, llt); ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb()); std::vector tmp; return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); } else { - const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type)); + const llvm::Type* sty = getPtrToType(DtoType(vd->type)); if (ptr->getType() != sty) { - ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp"); + ptr = DtoBitCast(ptr, sty); std::vector tmp; return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp); } @@ -158,9 +158,9 @@ } } - size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0)); + size_t llt_sz = getTypeStoreSize(llt->getContainedType(0)); assert(os % llt_sz == 0); - ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp"); + ptr = DtoBitCast(ptr, llt); return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb()); } @@ -180,12 +180,34 @@ sd->llvmIRStruct = irstruct; gIR->structs.push_back(irstruct); + // fields Array* arr = &sd->fields; for (int k=0; k < arr->dim; k++) { - VarDeclaration* v = (VarDeclaration*)(arr->data[k]); + VarDeclaration* v = (VarDeclaration*)arr->data[k]; v->toObjFile(); } + bool thisModule = false; + if (sd->getModule() == gIR->dmodule) + thisModule = true; + + // methods + arr = sd->members; + for (int k=0; k < arr->dim; k++) { + Dsymbol* s = (Dsymbol*)arr->data[k]; + if (FuncDeclaration* fd = s->isFuncDeclaration()) { + if (thisModule || (fd->prot() != PROTprivate)) { + fd->toObjFile(); + } + } + else if (s->isAttribDeclaration()) { + s->toObjFile(); + } + else { + Logger::println("Ignoring dsymbol '%s' in this->members of kind '%s'", s->toPrettyChars(), s->kind()); + } + } + /*for (int k=0; k < sd->members->dim; k++) { Dsymbol* dsym = (Dsymbol*)(sd->members->data[k]); dsym->toObjFile(); @@ -218,12 +240,12 @@ assert(lastoffset == 0); fieldtype = i->second.type; fieldinit = i->second.var; - prevsize = gTargetData->getTypeSize(fieldtype); + prevsize = getABITypeSize(fieldtype); i->second.var->llvmFieldIndex = idx; } // colliding offset? else if (lastoffset == i->first) { - size_t s = gTargetData->getTypeSize(i->second.type); + size_t s = getABITypeSize(i->second.type); if (s > prevsize) { fieldpad += s - prevsize; prevsize = s; @@ -233,7 +255,7 @@ } // intersecting offset? else if (i->first < (lastoffset + prevsize)) { - size_t s = gTargetData->getTypeSize(i->second.type); + size_t s = getABITypeSize(i->second.type); assert((i->first + s) <= (lastoffset + prevsize)); // this holds because all types are aligned to their size sd->llvmHasUnions = true; i->second.var->llvmFieldIndex = idx; @@ -256,7 +278,7 @@ lastoffset = i->first; fieldtype = i->second.type; fieldinit = i->second.var; - prevsize = gTargetData->getTypeSize(fieldtype); + prevsize = getABITypeSize(fieldtype); i->second.var->llvmFieldIndex = idx; fieldpad = 0; } @@ -420,7 +442,7 @@ unsigned o = i->first; IRStruct::Offset* so = &i->second; const llvm::Type* ft = so->init->getType(); - size_t sz = gTargetData->getTypeSize(ft); + size_t sz = getABITypeSize(ft); if (f == NULL) { // new field fields.push_back(DUnionField()); f = &fields.back(); @@ -495,7 +517,7 @@ if (ii < nin && fi == in[ii].idx) { - size_t s = gTargetData->getTypeSize(in[ii].c->getType()); + size_t s = getABITypeSize(in[ii].c->getType()); if (in[ii].idx == last) { size_t nos = in[ii].idxos * s; diff -r 1700239cab2e -r 44a95ac7368a gen/todebug.cpp --- a/gen/todebug.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/todebug.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -15,7 +15,7 @@ static const llvm::PointerType* ptrTy(const llvm::Type* t) { - return llvm::PointerType::get(t); + return llvm::PointerType::get(t, 0); } static const llvm::PointerType* dbgArrTy() diff -r 1700239cab2e -r 44a95ac7368a gen/toir.cpp --- a/gen/toir.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/toir.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -179,7 +179,7 @@ assert(tid->llvmValue); const llvm::Type* vartype = DtoType(type); llvm::Value* m; - if (tid->llvmValue->getType() != llvm::PointerType::get(vartype)) + if (tid->llvmValue->getType() != getPtrToType(vartype)) m = p->ir->CreateBitCast(tid->llvmValue, vartype, "tmp"); else m = tid->llvmValue; @@ -278,7 +278,7 @@ const llvm::Type* vartype = DtoType(type); llvm::Constant* m = isaConstant(ti->llvmValue); assert(m); - if (ti->llvmValue->getType() != llvm::PointerType::get(vartype)) + if (ti->llvmValue->getType() != getPtrToType(vartype)) m = llvm::ConstantExpr::getBitCast(m, vartype); return m; } @@ -403,11 +403,13 @@ Type* cty = DtoDType(dtype->next); const llvm::Type* ct = DtoType(cty); + if (ct == llvm::Type::VoidTy) + ct = llvm::Type::Int8Ty; //printf("ct = %s\n", type->next->toChars()); const llvm::ArrayType* at = llvm::ArrayType::get(ct,len+1); llvm::Constant* _init; - if (cty->ty == Tchar) { + if (cty->ty == Tchar || cty->ty == Tvoid) { uint8_t* str = (uint8_t*)string; std::string cont((char*)str, len); _init = llvm::ConstantArray::get(cont,true); @@ -434,6 +436,7 @@ assert(0); llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::InternalLinkage;//WeakLinkage; + Logger::cout() << "type: " << *at << "\ninit: " << *_init << '\n'; llvm::GlobalVariable* gvar = new llvm::GlobalVariable(at,true,_linkage,_init,"stringliteral",gIR->module); llvm::ConstantInt* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); @@ -461,7 +464,7 @@ assert(0); } else if (dtype->ty == Tsarray) { - const llvm::Type* dstType = llvm::PointerType::get(llvm::ArrayType::get(ct, len)); + const llvm::Type* dstType = getPtrToType(llvm::ArrayType::get(ct, len)); llvm::Value* emem = (gvar->getType() == dstType) ? gvar : DtoBitCast(gvar, dstType); return new DVarValue(type, emem, true); } @@ -877,7 +880,7 @@ Type* t = DtoDType(type); const llvm::Type* llt = DtoType(type); if (DtoIsPassedByRef(t)) - llt = llvm::PointerType::get(llt); + llt = getPtrToType(llt); // TODO if (strcmp(global.params.llvmArch, "x86") != 0) { warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars()); @@ -972,7 +975,7 @@ } if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { - const llvm::Type* rettype = llvm::PointerType::get(DtoType(type)); + const llvm::Type* rettype = getPtrToType(DtoType(type)); if (llargs[j]->getType() != llfnty->getParamType(j)) { Logger::println("llvmRunTimeHack==true - force casting return value param"); Logger::cout() << "casting: " << *llargs[j] << " to type: " << *llfnty->getParamType(j) << '\n'; @@ -986,9 +989,9 @@ // this arguments if (dfn && dfn->vthis) { - Logger::println("This Call"); + Logger::cout() << "This Call func val:" << *funcval << '\n'; if (dfn->vthis->getType() != argiter->get()) { - //Logger::cout() << *fn->thisparam << '|' << *argiter->get() << '\n'; + //Logger::cout() << "value: " << *dfn->vthis << " totype: " << *argiter->get() << '\n'; llargs[j] = DtoBitCast(dfn->vthis, argiter->get()); } else { @@ -1010,8 +1013,8 @@ Logger::println("Nested Call"); llvm::Value* contextptr = DtoNestedContext(dfn->func->toParent2()->isFuncDeclaration()); if (!contextptr) - contextptr = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); - llargs[j] = DtoBitCast(contextptr, llvm::PointerType::get(llvm::Type::Int8Ty)); + contextptr = llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty)); + llargs[j] = DtoBitCast(contextptr, getPtrToType(llvm::Type::Int8Ty)); ++j; ++argiter; } @@ -1025,7 +1028,7 @@ Argument* fnarg = Argument::getNth(tf->parameters, i); Expression* exp = (Expression*)arguments->data[i]; DValue* expelem = exp->toElem(p); - llargs[j] = DtoBitCast(expelem->getLVal(), llvm::PointerType::get(llvm::Type::Int8Ty)); + llargs[j] = DtoBitCast(expelem->getLVal(), getPtrToType(llvm::Type::Int8Ty)); } } // regular arguments @@ -1062,7 +1065,7 @@ // build type info array assert(Type::typeinfo->llvmConstInit); - const llvm::Type* typeinfotype = llvm::PointerType::get(Type::typeinfo->llvmConstInit->getType()); + const llvm::Type* typeinfotype = getPtrToType(Type::typeinfo->llvmConstInit->getType()); Logger::cout() << "typeinfo ptr type: " << *typeinfotype << '\n'; const llvm::ArrayType* typeinfoarraytype = llvm::ArrayType::get(typeinfotype,vtype->getNumElements()); @@ -1081,13 +1084,13 @@ // put data in d-array llvm::Value* typeinfoarrayparam = new llvm::AllocaInst(llfnty->getParamType(j)->getContainedType(0),"_arguments_array",p->topallocapoint()); p->ir->CreateStore(DtoConstSize_t(vtype->getNumElements()), DtoGEPi(typeinfoarrayparam,0,0,"tmp")); - llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, llvm::PointerType::get(typeinfotype), "tmp"); + llvm::Value* casttypeinfomem = p->ir->CreateBitCast(typeinfomem, getPtrToType(typeinfotype), "tmp"); p->ir->CreateStore(casttypeinfomem, DtoGEPi(typeinfoarrayparam,0,1,"tmp")); // specify arguments llargs[j] = typeinfoarrayparam;; j++; - llargs[j] = p->ir->CreateBitCast(mem, llvm::PointerType::get(llvm::Type::Int8Ty), "tmp"); + llargs[j] = p->ir->CreateBitCast(mem, getPtrToType(llvm::Type::Int8Ty), "tmp"); j++; llargs.resize(nimplicit+2); } @@ -1128,14 +1131,14 @@ if (llfnty->getReturnType() != llvm::Type::VoidTy) varname = "tmp"; - Logger::cout() << "Calling: " << *funcval << '\n'; + //Logger::cout() << "Calling: " << *funcval << '\n'; // call the function llvm::CallInst* call = new llvm::CallInst(funcval, llargs.begin(), llargs.end(), varname, p->scopebb()); llvm::Value* retllval = (retinptr) ? llargs[0] : call; if (retinptr && dfn && dfn->func && dfn->func->llvmRunTimeHack) { - const llvm::Type* rettype = llvm::PointerType::get(DtoType(type)); + const llvm::Type* rettype = getPtrToType(DtoType(type)); if (retllval->getType() != rettype) { Logger::println("llvmRunTimeHack==true - force casting return value"); Logger::cout() << "from: " << *retllval->getType() << " to: " << *rettype << '\n'; @@ -1243,7 +1246,7 @@ } else { const llvm::Type* elemtype = llvalue->getType()->getContainedType(0)->getContainedType(0); - size_t elemsz = gTargetData->getTypeSize(elemtype); + size_t elemsz = getABITypeSize(elemtype); varmem = DtoGEPi(llvalue, 0, offset / elemsz, "tmp"); } } @@ -1388,8 +1391,14 @@ if (!vthis2) vthis2 = vthis; //unsigned cc = (unsigned)-1; - // virtual call - if (!fdecl->isFinal() && fdecl->isVirtual()) { + // super call + if (e1->op == TOKsuper) { + DtoForceDeclareDsymbol(fdecl); + funcval = fdecl->llvmValue; + assert(funcval); + } + // normal virtual call + else if (fdecl->isAbstract() || (!fdecl->isFinal() && fdecl->isVirtual())) { assert(fdecl->vtblIndex > 0); assert(e1type->ty == Tclass); @@ -1428,7 +1437,8 @@ LOG_SCOPE; if (VarDeclaration* vd = var->isVarDeclaration()) { - llvm::Value* v = p->func()->decl->llvmThisVar; + llvm::Value* v; + v = p->func()->decl->llvmThisVar; if (llvm::isa(v)) v = new llvm::LoadInst(v, "tmp", p->scopebb()); return new DThisValue(vd, v); @@ -1818,7 +1828,7 @@ else if (e1type->isfloating()) { assert(e2type->isfloating()); - llvm::Value* one = llvm::ConstantFP::get(val->getType(), 1.0f); + llvm::Value* one = llvm::ConstantFP::get(val->getType(), llvm::APFloat(1.0f)); if (op == TOKplusplus) { post = llvm::BinaryOperator::createAdd(val,one,"tmp",p->scopebb()); } @@ -1847,113 +1857,47 @@ Type* ntype = DtoDType(newtype); + if (ntype->ty == Tclass) { + return DtoNewClass((TypeClass*)ntype, this); + } + const llvm::Type* t = DtoType(ntype); llvm::Value* emem = 0; bool inplace = false; - { - Logger::println("Allocating memory"); - LOG_SCOPE; - if (onstack) { - assert(ntype->ty == Tclass); - emem = new llvm::AllocaInst(t->getContainedType(0),"tmp",p->topallocapoint()); - } - else if (ntype->ty == Tclass) { - emem = new llvm::MallocInst(t->getContainedType(0),"tmp",p->scopebb()); - } - else if (ntype->ty == Tarray) { - assert(arguments); - if (arguments->dim == 1) { - DValue* sz = ((Expression*)arguments->data[0])->toElem(p); - llvm::Value* dimval = sz->getRVal(); - Type* nnt = DtoDType(ntype->next); - if (nnt->ty == Tvoid) - nnt = Type::tint8; - - if (p->topexp() && p->topexp()->e2 == this) { - assert(p->topexp()->v); - emem = p->topexp()->v->getLVal(); - DtoNewDynArray(emem, dimval, nnt); - inplace = true; - } - else { - const llvm::Type* restype = DtoType(type); - Logger::cout() << "restype = " << *restype << '\n'; - emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint()); - DtoNewDynArray(emem, dimval, nnt); - return new DVarValue(newtype, emem, true); - } + if (ntype->ty == Tarray) { + assert(arguments); + if (arguments->dim == 1) { + DValue* sz = ((Expression*)arguments->data[0])->toElem(p); + llvm::Value* dimval = sz->getRVal(); + Type* nnt = DtoDType(ntype->next); + if (nnt->ty == Tvoid) + nnt = Type::tint8; + + if (p->topexp() && p->topexp()->e2 == this) { + assert(p->topexp()->v); + emem = p->topexp()->v->getLVal(); + DtoNewDynArray(emem, dimval, nnt); + inplace = true; } else { - assert(0 && "num args to 'new' != 1"); + const llvm::Type* restype = DtoType(type); + Logger::cout() << "restype = " << *restype << '\n'; + emem = new llvm::AllocaInst(restype,"newstorage",p->topallocapoint()); + DtoNewDynArray(emem, dimval, nnt); + return new DVarValue(newtype, emem, true); } } else { - emem = new llvm::MallocInst(t,"tmp",p->scopebb()); + assert(0 && "num args to 'new' != 1"); } } - - if (ntype->ty == Tclass) { - // first apply the static initializer - TypeClass* tc = (TypeClass*)ntype; - DtoInitClass(tc, emem); - - // set the this var for nested classes - if (thisexp) { - Logger::println("Resolving 'this' expression"); - LOG_SCOPE; - DValue* thisval = thisexp->toElem(p); - size_t idx = 2; - idx += tc->sym->llvmIRStruct->interfaces.size(); - llvm::Value* dst = thisval->getRVal(); - llvm::Value* src = DtoGEPi(emem,0,idx,"tmp"); - Logger::cout() << "dst: " << *dst << "\nsrc: " << *src << '\n'; - DtoStore(dst, src); - } - else if (tc->sym->isNested()) - { - Logger::println("Resolving nested context"); - LOG_SCOPE; - size_t idx = 2; - idx += tc->sym->llvmIRStruct->interfaces.size(); - llvm::Value* nest = p->func()->decl->llvmNested; - if (!nest) - nest = p->func()->decl->llvmThisVar; - assert(nest); - llvm::Value* gep = DtoGEPi(emem,0,idx,"tmp"); - nest = DtoBitCast(nest, gep->getType()->getContainedType(0)); - DtoStore(nest, gep); - } - - // then call constructor - if (arguments) { - Logger::println("Calling constructor"); - LOG_SCOPE; - assert(member); - assert(member->llvmValue); - llvm::Function* fn = llvm::cast(member->llvmValue); - TypeFunction* tf = (TypeFunction*)DtoDType(member->type); - - std::vector ctorargs; - ctorargs.push_back(emem); - for (size_t i=0; idim; ++i) - { - Expression* ex = (Expression*)arguments->data[i]; - Argument* fnarg = Argument::getNth(tf->parameters, i); - DValue* argval = DtoArgument(fnarg, ex); - llvm::Value* a = argval->getRVal(); - const llvm::Type* aty = fn->getFunctionType()->getParamType(i+1); - if (a->getType() != aty) // this param might have type mismatch - a = DtoBitCast(a, aty); - ctorargs.push_back(a); - } - llvm::CallInst* call = new llvm::CallInst(fn, ctorargs.begin(), ctorargs.end(), "tmp", p->scopebb()); - call->setCallingConv(DtoCallingConv(LINKd)); - emem = call; - } + else { + emem = new llvm::MallocInst(t,"tmp",p->scopebb()); } - else if (ntype->ty == Tstruct) { + + if (ntype->ty == Tstruct) { TypeStruct* ts = (TypeStruct*)ntype; if (ts->isZeroInit()) { DtoStructZeroInit(emem); @@ -2053,12 +1997,33 @@ Logger::print("AssertExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - DValue* u = e1->toElem(p); - DValue* m = msg ? msg->toElem(p) : NULL; - - DtoAssert(u->getRVal(), &loc, m); - - return 0; + // condition + DValue* cond = e1->toElem(p); + + // create basic blocks + llvm::BasicBlock* oldend = p->scopeend(); + llvm::BasicBlock* assertbb = new llvm::BasicBlock("assert", p->topfunc(), oldend); + llvm::BasicBlock* endbb = new llvm::BasicBlock("endassert", p->topfunc(), oldend); + + // test condition + llvm::Value* condval = cond->getRVal(); + condval = DtoBoolean(condval); + + // branch + new llvm::BranchInst(endbb, assertbb, condval, p->scopebb()); + + // call assert runtime functions + p->scope() = IRScope(assertbb,endbb); + DtoAssert(&loc, msg ? msg->toElem(p) : NULL); + + if (!gIR->scopereturned()) + new llvm::BranchInst(endbb, p->scopebb()); + + // rewrite the scope + p->scope() = IRScope(endbb,oldend); + + // no meaningful return value + return NULL; } ////////////////////////////////////////////////////////////////////////////////////////// @@ -2192,7 +2157,7 @@ Logger::print("HaltExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - DtoAssert(DtoConstBool(false), &loc, NULL); + DtoAssert(&loc, NULL); new llvm::UnreachableInst(p->scopebb()); return 0; @@ -2207,10 +2172,7 @@ DValue* u = e1->toElem(p); - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); - - const llvm::Type* int8ptrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::PointerType* int8ptrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* lval; if (p->topexp() && p->topexp()->e2 == this) { @@ -2229,21 +2191,32 @@ if (nestvar) uval = nestvar; else - uval = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + uval = llvm::ConstantPointerNull::get(int8ptrty); } else { uval = u->getRVal(); } - llvm::Value* context = DtoGEP(lval,zero,zero,"tmp",p->scopebb()); - llvm::Value* castcontext = DtoBitCast(uval,int8ptrty); - new llvm::StoreInst(castcontext, context, p->scopebb()); - - llvm::Value* fptr = DtoGEP(lval,zero,one,"tmp",p->scopebb()); - - assert(func->llvmValue); - llvm::Value* castfptr = DtoBitCast(func->llvmValue,fptr->getType()->getContainedType(0)); - new llvm::StoreInst(castfptr, fptr, p->scopebb()); + llvm::Value* context = DtoGEPi(lval,0,0,"tmp"); + llvm::Value* castcontext = DtoBitCast(uval, int8ptrty); + DtoStore(castcontext, context); + + llvm::Value* fptr = DtoGEPi(lval,0,1,"tmp"); + + Logger::println("func: '%s'", func->toPrettyChars()); + + llvm::Value* castfptr; + if (func->isVirtual()) + castfptr = DtoVirtualFunctionPointer(u, func); + else if (func->isAbstract()) + assert(0 && "TODO delegate to abstract method"); + else if (func->toParent()->isInterfaceDeclaration()) + assert(0 && "TODO delegate to interface method"); + else + castfptr = func->llvmValue; + + castfptr = DtoBitCast(castfptr, fptr->getType()->getContainedType(0)); + DtoStore(castfptr, fptr); return new DVarValue(type, lval, true); } @@ -2279,7 +2252,7 @@ if (t1->ty == Tpointer && v->isNull() && l->getType() != r->getType()) { r = llvm::ConstantPointerNull::get(isaPointer(l->getType())); } - Logger::cout() << "l = " << *l << " r = " << *r << '\n'; + //Logger::cout() << "l = " << *l << " r = " << *r << '\n'; eval = new llvm::ICmpInst(pred, l, r, "tmp", p->scopebb()); } return new DImValue(type, eval); @@ -2368,9 +2341,9 @@ zero = llvm::ConstantInt::get(val->getType(), 0, true); else if (t->isfloating()) { if (t->ty == Tfloat32 || t->ty == Timaginary32) - zero = llvm::ConstantFP::get(val->getType(), float(0)); + zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0f)); else if (t->ty == Tfloat64 || t->ty == Tfloat80 || t->ty == Timaginary64 || t->ty == Timaginary80) - zero = llvm::ConstantFP::get(val->getType(), double(0)); + zero = llvm::ConstantFP::get(val->getType(), llvm::APFloat(0.0)); else assert(0); } @@ -2619,11 +2592,11 @@ } const llvm::StructType* t = llvm::StructType::get(tys); if (t != llt) { - if (gTargetData->getTypeSize(t) != gTargetData->getTypeSize(llt)) { - Logger::cout() << "got size " << gTargetData->getTypeSize(t) << ", expected " << gTargetData->getTypeSize(llt) << '\n'; + if (getABITypeSize(t) != getABITypeSize(llt)) { + Logger::cout() << "got size " << getABITypeSize(t) << ", expected " << getABITypeSize(llt) << '\n'; assert(0 && "type size mismatch"); } - sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp"); + sptr = DtoBitCast(sptr, getPtrToType(t)); Logger::cout() << "sptr type is now: " << *t << '\n'; } } diff -r 1700239cab2e -r 44a95ac7368a gen/tollvm.cpp --- a/gen/tollvm.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/tollvm.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -82,9 +82,9 @@ case Tpointer: { assert(t->next); if (t->next->ty == Tvoid) - return (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); + return (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty); else - return (const llvm::Type*)llvm::PointerType::get(DtoType(t->next)); + return (const llvm::Type*)getPtrToType(DtoType(t->next)); } // arrays @@ -117,11 +117,11 @@ TypeStruct* ts = (TypeStruct*)t; assert(ts->sym); DtoResolveDsymbol(ts->sym); - return t->llvmType->get(); + return ts->sym->llvmIRStruct->recty.get();//t->llvmType->get(); } case Tclass: { - if (!t->llvmType || *t->llvmType == NULL) { + /*if (!t->llvmType || *t->llvmType == NULL) { // recursive or cyclic declaration if (!gIR->structs.empty()) { @@ -130,17 +130,17 @@ { if (t == (*i)->type) { - return llvm::PointerType::get((*i)->recty.get()); + return getPtrToType((*i)->recty.get()); } } } Logger::println("no type found"); - } + }*/ TypeClass* tc = (TypeClass*)t; assert(tc->sym); DtoResolveDsymbol(tc->sym); - return llvm::PointerType::get(t->llvmType->get()); + return getPtrToType(tc->sym->llvmIRStruct->recty.get());//t->llvmType->get()); } // functions @@ -182,7 +182,7 @@ std::vector types; types.push_back(DtoType(taa->key)); types.push_back(DtoType(taa->next)); - return llvm::PointerType::get(llvm::StructType::get(types)); + return getPtrToType(llvm::StructType::get(types)); } default: @@ -196,9 +196,9 @@ const llvm::StructType* DtoDelegateType(Type* t) { - const llvm::Type* i8ptr = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* i8ptr = getPtrToType(llvm::Type::Int8Ty); const llvm::Type* func = DtoFunctionType(t->next, i8ptr); - const llvm::Type* funcptr = llvm::PointerType::get(func); + const llvm::Type* funcptr = getPtrToType(func); std::vector types; types.push_back(i8ptr); @@ -214,7 +214,7 @@ const llvm::Type* int8ty = (const llvm::Type*)llvm::Type::Int8Ty; const llvm::Type* int32ty = (const llvm::Type*)llvm::Type::Int32Ty; const llvm::Type* int64ty = (const llvm::Type*)llvm::Type::Int64Ty; - const llvm::Type* int8ptrty = (const llvm::Type*)llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* int8ptrty = (const llvm::Type*)getPtrToType(llvm::Type::Int8Ty); const llvm::Type* voidty = (const llvm::Type*)llvm::Type::VoidTy; assert(gIR); @@ -284,7 +284,7 @@ assert(gIR); d_uns64 n = (global.params.is64bit) ? 16 : 8; - llvm::Type* i8p_ty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* i8p_ty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* arr = new llvm::BitCastInst(v,i8p_ty,"tmp",gIR->scopebb()); @@ -310,7 +310,7 @@ d_uns64 n = (global.params.is64bit) ? 16 : 8; - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb()); llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb()); @@ -434,10 +434,8 @@ } } else if (isaPointer(t)) { - const llvm::Type* st = DtoSize_t(); - llvm::Value* ptrasint = new llvm::PtrToIntInst(val,st,"tmp",gIR->scopebb()); - llvm::Value* zero = llvm::ConstantInt::get(st, 0, false); - return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, ptrasint, zero, "tmp", gIR->scopebb()); + llvm::Value* zero = llvm::Constant::getNullValue(t); + return new llvm::ICmpInst(llvm::ICmpInst::ICMP_NE, val, zero, "tmp", gIR->scopebb()); } else { @@ -615,7 +613,7 @@ /*size_t sz = gTargetData->getTypeSize(ty); llvm::ConstantInt* n = llvm::ConstantInt::get(DtoSize_t(), sz, false); if (ptr == 0) { - llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); + llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty); ptr = llvm::ConstantPointerNull::get(i8pty); } return DtoRealloc(ptr, n);*/ @@ -634,7 +632,7 @@ llvm::Value* newptr = ptr; - llvm::PointerType* i8pty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::PointerType* i8pty = getPtrToType(llvm::Type::Int8Ty); if (ptr->getType() != i8pty) { newptr = new llvm::BitCastInst(ptr,i8pty,"tmp",gIR->scopebb()); } @@ -649,30 +647,33 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg) +void DtoAssert(Loc* loc, DValue* msg) { - llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_assert"); - const llvm::FunctionType* fnt = fn->getFunctionType(); + std::vector args; + llvm::Constant* c; + + // func + const char* fname = msg ? "_d_assert_msg" : "_d_assert"; + + // msg param + if (msg) args.push_back(msg->getRVal()); - std::vector llargs; - llargs.resize(3); - llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse(); - llargs[1] = DtoConstUint(loc->linnum); - if (msg) - llargs[2] = msg->getRVal(); - else { - llvm::Constant* c = DtoConstSlice(DtoConstSize_t(0), DtoConstNullPtr(llvm::Type::Int8Ty)); - static llvm::AllocaInst* alloc = 0; - if (!alloc || alloc->getParent()->getParent() != gIR->func()->func) { - alloc = new llvm::AllocaInst(c->getType(), "assertnullparam", gIR->topallocapoint()); - DtoSetArrayToNull(alloc); - } - llargs[2] = alloc; - } + // file param + c = DtoConstString(loc->filename); + llvm::AllocaInst* alloc = new llvm::AllocaInst(c->getType(), "srcfile", gIR->topallocapoint()); + llvm::Value* ptr = DtoGEPi(alloc, 0,0, "tmp"); + DtoStore(c->getOperand(0), ptr); + ptr = DtoGEPi(alloc, 0,1, "tmp"); + DtoStore(c->getOperand(1), ptr); + args.push_back(alloc); - assert(fn); - llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); - call->setCallingConv(llvm::CallingConv::C); + // line param + c = DtoConstUint(loc->linnum); + args.push_back(c); + + // call + llvm::Function* fn = LLVM_D_GetRuntimeFunction(gIR->module, fname); + llvm::CallInst* call = new llvm::CallInst(fn, args.begin(), args.end(), "", gIR->scopebb()); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1191,9 +1192,9 @@ { TY ty = DtoDType(t)->ty; if (ty == Tfloat32 || ty == Timaginary32) - return llvm::ConstantFP::get(llvm::Type::FloatTy, float(value)); + return llvm::ConstantFP::get(llvm::Type::FloatTy, llvm::APFloat(float(value))); else if (ty == Tfloat64 || ty == Timaginary64 || ty == Tfloat80 || ty == Timaginary80) - return llvm::ConstantFP::get(llvm::Type::DoubleTy, double(value)); + return llvm::ConstantFP::get(llvm::Type::DoubleTy, llvm::APFloat(double(value))); } @@ -1227,7 +1228,7 @@ llvm::Constant* DtoConstNullPtr(const llvm::Type* t) { return llvm::ConstantPointerNull::get( - llvm::PointerType::get(t) + getPtrToType(t) ); } @@ -1235,7 +1236,7 @@ void DtoMemSetZero(llvm::Value* dst, llvm::Value* nbytes) { - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value *dstarr; if (dst->getType() == arrty) { @@ -1263,7 +1264,7 @@ { assert(dst->getType() == src->getType()); - llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::Type* arrty = getPtrToType(llvm::Type::Int8Ty); llvm::Value *dstarr, *srcarr; if (dst->getType() == arrty) { @@ -1309,11 +1310,11 @@ ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t) +llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t, const char* name) { if (v->getType() == t) return v; - return gIR->ir->CreateBitCast(v, t, "tmp"); + return gIR->ir->CreateBitCast(v, t, name ? name : "tmp"); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -1370,6 +1371,36 @@ ////////////////////////////////////////////////////////////////////////////////////////// +const llvm::PointerType* getPtrToType(const llvm::Type* t) +{ + return llvm::PointerType::get(t, 0); +} + +llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t) +{ + const llvm::PointerType* pt = llvm::cast(t); + return llvm::ConstantPointerNull::get(pt); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +size_t getTypeBitSize(const llvm::Type* t) +{ + return gTargetData->getTypeSizeInBits(t); +} + +size_t getTypeStoreSize(const llvm::Type* t) +{ + return gTargetData->getTypeStoreSize(t); +} + +size_t getABITypeSize(const llvm::Type* t) +{ + return gTargetData->getABITypeSize(t); +} + +////////////////////////////////////////////////////////////////////////////////////////// + bool DtoIsTemplateInstance(Dsymbol* s) { if (!s) return false; @@ -1656,7 +1687,7 @@ void DtoForceDeclareDsymbol(Dsymbol* dsym) { if (dsym->llvmDeclared) return; - Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toChars()); + Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toPrettyChars()); LOG_SCOPE; DtoResolveDsymbol(dsym); @@ -1670,7 +1701,7 @@ void DtoForceConstInitDsymbol(Dsymbol* dsym) { if (dsym->llvmInitialized) return; - Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toChars()); + Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toPrettyChars()); LOG_SCOPE; DtoResolveDsymbol(dsym); @@ -1685,7 +1716,7 @@ void DtoForceDefineDsymbol(Dsymbol* dsym) { if (dsym->llvmDefined) return; - Logger::println("DtoForceDefineDsymbol(%s)", dsym->toChars()); + Logger::println("DtoForceDefineDsymbol(%s)", dsym->toPrettyChars()); LOG_SCOPE; DtoResolveDsymbol(dsym); diff -r 1700239cab2e -r 44a95ac7368a gen/tollvm.h --- a/gen/tollvm.h Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/tollvm.h Mon Jan 14 05:11:54 2008 +0100 @@ -39,7 +39,7 @@ llvm::Value* DtoRealloc(llvm::Value* ptr, const llvm::Type* ty); llvm::Value* DtoRealloc(llvm::Value* ptr, llvm::Value* len); -void DtoAssert(llvm::Value* cond, Loc* loc, DValue* msg); +void DtoAssert(Loc* loc, DValue* msg); llvm::Value* DtoNestedContext(FuncDeclaration* func); llvm::Value* DtoNestedVariable(VarDeclaration* vd); @@ -81,7 +81,7 @@ bool DtoCanLoad(llvm::Value* ptr); llvm::Value* DtoLoad(llvm::Value* src); void DtoStore(llvm::Value* src, llvm::Value* dst); -llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t); +llvm::Value* DtoBitCast(llvm::Value* v, const llvm::Type* t, const char* name=0); // llvm::dyn_cast wrappers const llvm::PointerType* isaPointer(llvm::Value* v); @@ -95,6 +95,15 @@ llvm::Argument* isaArgument(llvm::Value* v); llvm::GlobalVariable* isaGlobalVar(llvm::Value* v); +// llvm::T::get(...) wrappers +const llvm::PointerType* getPtrToType(const llvm::Type* t); +llvm::ConstantPointerNull* getNullPtr(const llvm::Type* t); + +// type sizes +size_t getTypeBitSize(const llvm::Type* t); +size_t getTypeStoreSize(const llvm::Type* t); +size_t getABITypeSize(const llvm::Type* t); + // basic operations void DtoAssign(DValue* lhs, DValue* rhs); diff -r 1700239cab2e -r 44a95ac7368a gen/toobj.cpp --- a/gen/toobj.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/toobj.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -74,7 +74,7 @@ ir.module->setDataLayout(global.params.data_layout); // heavily inspired by tools/llc/llc.cpp:200-230 - const llvm::TargetMachineRegistry::Entry* targetEntry; + const llvm::TargetMachineRegistry::entry* targetEntry; std::string targetError; targetEntry = llvm::TargetMachineRegistry::getClosestStaticTargetForModule(*ir.module, targetError); assert(targetEntry && "Failed to find a static target for module"); @@ -118,7 +118,7 @@ // emit the llvm main function if necessary if (ir.emitMain) { - DtoMain(); + //DtoMain(); } // verify the llvm @@ -295,7 +295,7 @@ initVec.push_back(c); // monitor - c = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + c = getNullPtr(getPtrToType(llvm::Type::Int8Ty)); initVec.push_back(c); // name @@ -321,14 +321,15 @@ } } // has import array? - if (!importInits.empty()) { - const llvm::ArrayType* importArrTy = llvm::ArrayType::get(llvm::PointerType::get(moduleinfoTy), importInits.size()); + if (!importInits.empty()) + { + const llvm::ArrayType* importArrTy = llvm::ArrayType::get(getPtrToType(moduleinfoTy), importInits.size()); c = llvm::ConstantArray::get(importArrTy, importInits); std::string m_name("_D"); m_name.append(mangle()); m_name.append("9__importsZ"); llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(importArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module); - c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(importArrTy->getElementType())); + c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(importArrTy->getElementType())); c = DtoConstSlice(DtoConstSize_t(importInits.size()), c); } else @@ -351,19 +352,25 @@ for (size_t i = 0; i < aclasses.dim; i++) { ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; + if (cd->isInterfaceDeclaration()) + { + Logger::println("skipping interface '%s'", cd->toPrettyChars()); + continue; + } Logger::println("class: %s", cd->toPrettyChars()); assert(cd->llvmClass); classInits.push_back(cd->llvmClass); } // has class array? - if (!classInits.empty()) { - const llvm::ArrayType* classArrTy = llvm::ArrayType::get(llvm::PointerType::get(classinfoTy), classInits.size()); + if (!classInits.empty()) + { + const llvm::ArrayType* classArrTy = llvm::ArrayType::get(getPtrToType(classinfoTy), classInits.size()); c = llvm::ConstantArray::get(classArrTy, classInits); std::string m_name("_D"); m_name.append(mangle()); m_name.append("9__classesZ"); llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(classArrTy, true, llvm::GlobalValue::InternalLinkage, c, m_name, gIR->module); - c = llvm::ConstantExpr::getBitCast(m_gvar, llvm::PointerType::get(classArrTy->getElementType())); + c = llvm::ConstantExpr::getBitCast(m_gvar, getPtrToType(classArrTy->getElementType())); c = DtoConstSlice(DtoConstSize_t(classInits.size()), c); } else @@ -420,9 +427,9 @@ llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module); // declare the appending array - const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(llvm::PointerType::get(llvm::Type::Int8Ty), 1); + const llvm::ArrayType* appendArrTy = llvm::ArrayType::get(getPtrToType(llvm::Type::Int8Ty), 1); std::vector appendInits; - appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, llvm::PointerType::get(llvm::Type::Int8Ty))); + appendInits.push_back(llvm::ConstantExpr::getBitCast(gvar, getPtrToType(llvm::Type::Int8Ty))); llvm::Constant* appendInit = llvm::ConstantArray::get(appendArrTy, appendInits); std::string appendName("_d_moduleinfo_array"); llvm::GlobalVariable* appendVar = new llvm::GlobalVariable(appendArrTy, true, llvm::GlobalValue::AppendingLinkage, appendInit, appendName, gIR->module); @@ -446,7 +453,8 @@ void InterfaceDeclaration::toObjFile() { - Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars()); + //Logger::println("Ignoring InterfaceDeclaration::toObjFile for %s", toChars()); + gIR->resolveList.push_back(this); } /* ================================================================== */ @@ -491,7 +499,7 @@ if (isDataseg()) { // we don't want to touch private static members at all !!! - if ((prot() & PROTprivate) && getModule() != gIR->dmodule) + if ((prot() == PROTprivate) && getModule() != gIR->dmodule) return; // don't duplicate work diff -r 1700239cab2e -r 44a95ac7368a gen/typinf.cpp --- a/gen/typinf.cpp Fri Jan 11 17:57:40 2008 +0100 +++ b/gen/typinf.cpp Mon Jan 14 05:11:54 2008 +0100 @@ -371,7 +371,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(getNullPtr(getPtrToType(llvm::Type::Int8Ty))); assert(tinfo->ty == Ttypedef); TypeTypedef *tc = (TypeTypedef *)tinfo; @@ -400,10 +400,10 @@ assert(sinits.back()->getType() == stype->getElementType(3)); // void[] init - const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::PointerType* initpt = getPtrToType(llvm::Type::Int8Ty); if (tinfo->isZeroInit() || !sd->init) // 0 initializer, or the same as the base type { - sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); + sinits.push_back(DtoConstSlice(DtoConstSize_t(0), getNullPtr(initpt))); } else { @@ -412,7 +412,7 @@ ciname.append("__init"); llvm::GlobalVariable* civar = new llvm::GlobalVariable(DtoType(sd->basetype),true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module); llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt); - size_t cisize = gTargetData->getTypeSize(DtoType(sd->basetype)); + size_t cisize = getTypeStoreSize(DtoType(sd->basetype)); sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); } @@ -457,7 +457,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); assert(tinfo->ty == Tenum); TypeEnum *tc = (TypeEnum *)tinfo; @@ -485,7 +485,7 @@ assert(sinits.back()->getType() == stype->getElementType(3)); // void[] init - const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::PointerType* initpt = getPtrToType(llvm::Type::Int8Ty); if (tinfo->isZeroInit() || !sd->defaultval) // 0 initializer, or the same as the base type { sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); @@ -498,7 +498,7 @@ ciname.append("__init"); llvm::GlobalVariable* civar = new llvm::GlobalVariable(memty,true,llvm::GlobalValue::InternalLinkage,ci,ciname,gIR->module); llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(civar, initpt); - size_t cisize = gTargetData->getTypeSize(memty); + size_t cisize = getTypeStoreSize(memty); sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); } @@ -537,7 +537,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // TypeInfo base Logger::println("generating base typeinfo"); @@ -649,7 +649,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // value typeinfo assert(tinfo->ty == Tsarray); @@ -712,7 +712,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // get type assert(tinfo->ty == Taarray); @@ -847,7 +847,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // char[] name char *name = sd->toPrettyChars(); @@ -856,14 +856,14 @@ assert(sinits.back()->getType() == stype->getElementType(2)); // void[] init - const llvm::PointerType* initpt = llvm::PointerType::get(llvm::Type::Int8Ty); + const llvm::PointerType* initpt = getPtrToType(llvm::Type::Int8Ty); if (sd->zeroInit) // 0 initializer, or the same as the base type { sinits.push_back(DtoConstSlice(DtoConstSize_t(0), llvm::ConstantPointerNull::get(initpt))); } else { - size_t cisize = gTargetData->getTypeSize(tc->llvmType->get()); + size_t cisize = getTypeStoreSize(tc->llvmType->get()); llvm::Constant* cicast = llvm::ConstantExpr::getBitCast(sd->llvmInit, initpt); sinits.push_back(DtoConstSlice(DtoConstSize_t(cisize), cicast)); } @@ -1046,7 +1046,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // get classinfo assert(tinfo->ty == Tclass); @@ -1102,7 +1102,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // get classinfo assert(tinfo->ty == Tclass); @@ -1158,7 +1158,7 @@ sinits.push_back(base->llvmVtbl); // monitor - sinits.push_back(llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty))); + sinits.push_back(llvm::ConstantPointerNull::get(getPtrToType(llvm::Type::Int8Ty))); // create elements array assert(tinfo->ty == Ttuple); @@ -1168,7 +1168,7 @@ std::vector arrInits; const llvm::Type* tiTy = Type::typeinfo->type->llvmType->get(); - tiTy = llvm::PointerType::get(tiTy); + tiTy = getPtrToType(tiTy); for (size_t i = 0; i < dim; i++) { diff -r 1700239cab2e -r 44a95ac7368a llvmdc-posix-internal --- a/llvmdc-posix-internal Fri Jan 11 17:57:40 2008 +0100 +++ b/llvmdc-posix-internal Mon Jan 14 05:11:54 2008 +0100 @@ -8,7 +8,7 @@ objext=bc -version=LLVM +version=LLVMDC noversion=DigitalMars noversion=GNU testversion=linux diff -r 1700239cab2e -r 44a95ac7368a llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Fri Jan 11 17:57:40 2008 +0100 +++ b/llvmdc.kdevelop.filelist Mon Jan 14 05:11:54 2008 +0100 @@ -120,6 +120,7 @@ gen/irstate.cpp gen/irstate.h gen/llvm.h +gen/llvmd.h gen/logger.cpp gen/logger.h gen/optimizer.cpp @@ -255,187 +256,24 @@ tango/lib/common/tango/stdc/posix/pthread_darwin.d tango/lib/common/tango/stdc/wrap.c tango/lib/compiler -tango/lib/compiler/dmd -tango/lib/compiler/dmd/aApply.d -tango/lib/compiler/dmd/aApplyR.d -tango/lib/compiler/dmd/aaA.d -tango/lib/compiler/dmd/adi.d -tango/lib/compiler/dmd/alloca.d -tango/lib/compiler/dmd/arraycast.d -tango/lib/compiler/dmd/arraycat.d -tango/lib/compiler/dmd/cast.d -tango/lib/compiler/dmd/cmath2.d -tango/lib/compiler/dmd/compiler.d -tango/lib/compiler/dmd/complex.c -tango/lib/compiler/dmd/cover.d -tango/lib/compiler/dmd/critical.c -tango/lib/compiler/dmd/deh.c -tango/lib/compiler/dmd/deh2.d -tango/lib/compiler/dmd/dmain2.d -tango/lib/compiler/dmd/genobj.d -tango/lib/compiler/dmd/invariant.d -tango/lib/compiler/dmd/lifetime.d -tango/lib/compiler/dmd/llmath.d -tango/lib/compiler/dmd/mars.h -tango/lib/compiler/dmd/memory.d -tango/lib/compiler/dmd/memset.d -tango/lib/compiler/dmd/monitor.c -tango/lib/compiler/dmd/obj.d -tango/lib/compiler/dmd/qsort.d -tango/lib/compiler/dmd/qsort2.d -tango/lib/compiler/dmd/switch.d -tango/lib/compiler/dmd/trace.d -tango/lib/compiler/dmd/typeinfo -tango/lib/compiler/dmd/typeinfo/ti_AC.d -tango/lib/compiler/dmd/typeinfo/ti_Acdouble.d -tango/lib/compiler/dmd/typeinfo/ti_Acfloat.d -tango/lib/compiler/dmd/typeinfo/ti_Acreal.d -tango/lib/compiler/dmd/typeinfo/ti_Adouble.d -tango/lib/compiler/dmd/typeinfo/ti_Afloat.d -tango/lib/compiler/dmd/typeinfo/ti_Ag.d -tango/lib/compiler/dmd/typeinfo/ti_Aint.d -tango/lib/compiler/dmd/typeinfo/ti_Along.d -tango/lib/compiler/dmd/typeinfo/ti_Areal.d -tango/lib/compiler/dmd/typeinfo/ti_Ashort.d -tango/lib/compiler/dmd/typeinfo/ti_C.d -tango/lib/compiler/dmd/typeinfo/ti_byte.d -tango/lib/compiler/dmd/typeinfo/ti_cdouble.d -tango/lib/compiler/dmd/typeinfo/ti_cfloat.d -tango/lib/compiler/dmd/typeinfo/ti_char.d -tango/lib/compiler/dmd/typeinfo/ti_creal.d -tango/lib/compiler/dmd/typeinfo/ti_dchar.d -tango/lib/compiler/dmd/typeinfo/ti_delegate.d -tango/lib/compiler/dmd/typeinfo/ti_double.d -tango/lib/compiler/dmd/typeinfo/ti_float.d -tango/lib/compiler/dmd/typeinfo/ti_idouble.d -tango/lib/compiler/dmd/typeinfo/ti_ifloat.d -tango/lib/compiler/dmd/typeinfo/ti_int.d -tango/lib/compiler/dmd/typeinfo/ti_ireal.d -tango/lib/compiler/dmd/typeinfo/ti_long.d -tango/lib/compiler/dmd/typeinfo/ti_ptr.d -tango/lib/compiler/dmd/typeinfo/ti_real.d -tango/lib/compiler/dmd/typeinfo/ti_short.d -tango/lib/compiler/dmd/typeinfo/ti_ubyte.d -tango/lib/compiler/dmd/typeinfo/ti_uint.d -tango/lib/compiler/dmd/typeinfo/ti_ulong.d -tango/lib/compiler/dmd/typeinfo/ti_ushort.d -tango/lib/compiler/dmd/typeinfo/ti_void.d -tango/lib/compiler/dmd/typeinfo/ti_wchar.d -tango/lib/compiler/dmd/util -tango/lib/compiler/dmd/util/console.d -tango/lib/compiler/dmd/util/ctype.d -tango/lib/compiler/dmd/util/string.d -tango/lib/compiler/dmd/util/utf.d -tango/lib/compiler/gdc -tango/lib/compiler/gdc/aApply.d -tango/lib/compiler/gdc/aApplyR.d -tango/lib/compiler/gdc/aaA.d -tango/lib/compiler/gdc/actest.d -tango/lib/compiler/gdc/adi.d -tango/lib/compiler/gdc/arraycast.d -tango/lib/compiler/gdc/arraycat.d -tango/lib/compiler/gdc/cast.d -tango/lib/compiler/gdc/cmain.d -tango/lib/compiler/gdc/cmath2.d -tango/lib/compiler/gdc/compiler.d -tango/lib/compiler/gdc/config -tango/lib/compiler/gdc/config.h -tango/lib/compiler/gdc/config/darwin8 -tango/lib/compiler/gdc/config/gen_config1.c -tango/lib/compiler/gdc/config/gen_math.c -tango/lib/compiler/gdc/config/gen_unix.c -tango/lib/compiler/gdc/config/makestruct.h -tango/lib/compiler/gdc/config/mingw -tango/lib/compiler/gdc/config/skyos -tango/lib/compiler/gdc/critical.c -tango/lib/compiler/gdc/deh.c -tango/lib/compiler/gdc/dgccmain2.d -tango/lib/compiler/gdc/fpmath.d -tango/lib/compiler/gdc/gcc -tango/lib/compiler/gdc/gcc/aix_float.h -tango/lib/compiler/gdc/gcc/builtins.d -tango/lib/compiler/gdc/gcc/cbridge_fdset.c -tango/lib/compiler/gdc/gcc/cbridge_math.c -tango/lib/compiler/gdc/gcc/cbridge_stdio.c -tango/lib/compiler/gdc/gcc/cbridge_time.c -tango/lib/compiler/gdc/gcc/configext.d -tango/lib/compiler/gdc/gcc/configunix.d -tango/lib/compiler/gdc/gcc/deh.d -tango/lib/compiler/gdc/gcc/fpmath.d -tango/lib/compiler/gdc/gcc/support.d -tango/lib/compiler/gdc/gcc/threadsem.d -tango/lib/compiler/gdc/gcc/unwind.d -tango/lib/compiler/gdc/genobj.d -tango/lib/compiler/gdc/invariant.d -tango/lib/compiler/gdc/lifetime.d -tango/lib/compiler/gdc/mars.h -tango/lib/compiler/gdc/memory.d -tango/lib/compiler/gdc/memory_dyld.c -tango/lib/compiler/gdc/memory_freebsd.c -tango/lib/compiler/gdc/memset.d -tango/lib/compiler/gdc/minimal.c -tango/lib/compiler/gdc/monitor.c -tango/lib/compiler/gdc/obj.d -tango/lib/compiler/gdc/qsort2.d -tango/lib/compiler/gdc/qsortg.d -tango/lib/compiler/gdc/rundmain.d -tango/lib/compiler/gdc/std -tango/lib/compiler/gdc/std/intrinsic.d -tango/lib/compiler/gdc/switch.d -tango/lib/compiler/gdc/typeinfo -tango/lib/compiler/gdc/typeinfo/ti_AC.d -tango/lib/compiler/gdc/typeinfo/ti_Acdouble.d -tango/lib/compiler/gdc/typeinfo/ti_Acfloat.d -tango/lib/compiler/gdc/typeinfo/ti_Acreal.d -tango/lib/compiler/gdc/typeinfo/ti_Adouble.d -tango/lib/compiler/gdc/typeinfo/ti_Afloat.d -tango/lib/compiler/gdc/typeinfo/ti_Ag.d -tango/lib/compiler/gdc/typeinfo/ti_Aint.d -tango/lib/compiler/gdc/typeinfo/ti_Along.d -tango/lib/compiler/gdc/typeinfo/ti_Areal.d -tango/lib/compiler/gdc/typeinfo/ti_Ashort.d -tango/lib/compiler/gdc/typeinfo/ti_C.d -tango/lib/compiler/gdc/typeinfo/ti_byte.d -tango/lib/compiler/gdc/typeinfo/ti_cdouble.d -tango/lib/compiler/gdc/typeinfo/ti_cfloat.d -tango/lib/compiler/gdc/typeinfo/ti_char.d -tango/lib/compiler/gdc/typeinfo/ti_creal.d -tango/lib/compiler/gdc/typeinfo/ti_dchar.d -tango/lib/compiler/gdc/typeinfo/ti_delegate.d -tango/lib/compiler/gdc/typeinfo/ti_double.d -tango/lib/compiler/gdc/typeinfo/ti_float.d -tango/lib/compiler/gdc/typeinfo/ti_idouble.d -tango/lib/compiler/gdc/typeinfo/ti_ifloat.d -tango/lib/compiler/gdc/typeinfo/ti_int.d -tango/lib/compiler/gdc/typeinfo/ti_ireal.d -tango/lib/compiler/gdc/typeinfo/ti_long.d -tango/lib/compiler/gdc/typeinfo/ti_ptr.d -tango/lib/compiler/gdc/typeinfo/ti_real.d -tango/lib/compiler/gdc/typeinfo/ti_short.d -tango/lib/compiler/gdc/typeinfo/ti_ubyte.d -tango/lib/compiler/gdc/typeinfo/ti_uint.d -tango/lib/compiler/gdc/typeinfo/ti_ulong.d -tango/lib/compiler/gdc/typeinfo/ti_ushort.d -tango/lib/compiler/gdc/typeinfo/ti_void.d -tango/lib/compiler/gdc/typeinfo/ti_wchar.d -tango/lib/compiler/gdc/util -tango/lib/compiler/gdc/util/console.d -tango/lib/compiler/gdc/util/ctype.d -tango/lib/compiler/gdc/util/string.d -tango/lib/compiler/gdc/util/utf.d tango/lib/compiler/llvmdc tango/lib/compiler/llvmdc/aApply.d tango/lib/compiler/llvmdc/aApplyR.d tango/lib/compiler/llvmdc/aaA.d tango/lib/compiler/llvmdc/adi.d tango/lib/compiler/llvmdc/arrays.d -tango/lib/compiler/llvmdc/build.sh tango/lib/compiler/llvmdc/cast.d tango/lib/compiler/llvmdc/contract.d +tango/lib/compiler/llvmdc/critical.c +tango/lib/compiler/llvmdc/dmain2.d +tango/lib/compiler/llvmdc/eh.d tango/lib/compiler/llvmdc/genobj.d +tango/lib/compiler/llvmdc/lifetime.d tango/lib/compiler/llvmdc/llvm -tango/lib/compiler/llvmdc/llvm/intrinsic.di -tango/lib/compiler/llvmdc/obj +tango/lib/compiler/llvmdc/mars.h +tango/lib/compiler/llvmdc/mem.d +tango/lib/compiler/llvmdc/memory.d +tango/lib/compiler/llvmdc/monitor.c tango/lib/compiler/llvmdc/qsort2.d tango/lib/compiler/llvmdc/std tango/lib/compiler/llvmdc/std/intrinsic.d @@ -900,6 +738,17 @@ tangotests/e.d tangotests/f.d tangotests/g.d +tangotests/h.d +tangotests/i.d +tangotests/j.d +tangotests/k.d +tangotests/l.d +tangotests/m.d +tangotests/n.d +tangotests/o.d +tangotests/p.d +tangotests/q.d +tangotests/r.d test test/a.d test/aa1.d diff -r 1700239cab2e -r 44a95ac7368a tango/lib/common/tango/core/Exception.d --- a/tango/lib/common/tango/core/Exception.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/common/tango/core/Exception.d Mon Jan 14 05:11:54 2008 +0100 @@ -481,6 +481,7 @@ // Overridable Callbacks //////////////////////////////////////////////////////////////////////////////// +private extern(C) int printf(char*,...); /** * A callback for assert errors in D. The user-supplied assert handler will @@ -493,8 +494,11 @@ */ extern (C) void onAssertError( char[] file, size_t line ) { - if( assertHandler is null ) + printf("Assertion failed:\n"); + printf("%.*s(%lu)\n", file.length, file.ptr, line); + if( assertHandler is null ) { throw new AssertException( file, line ); + } assertHandler( file, line ); } @@ -511,6 +515,9 @@ */ extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg ) { + printf("Assertion failed:\n"); + printf("%.*s(%lu):\n", file.length, file.ptr, line); + printf("%.*s\n", msg.length, msg.ptr); if( assertHandler is null ) throw new AssertException( msg, file, line ); assertHandler( file, line, msg ); diff -r 1700239cab2e -r 44a95ac7368a tango/lib/common/tango/llvmdc.mak --- a/tango/lib/common/tango/llvmdc.mak Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/common/tango/llvmdc.mak Mon Jan 14 05:11:54 2008 +0100 @@ -12,6 +12,8 @@ LIB_TARGET=libtango-cc-tango.a LIB_MASK=libtango-cc-tango*.a +LIB_TARGET_C=libtango-cc-c-tango.a +LIB_MASK_C=libtango-cc-c-tango*.a CP=cp -f RM=rm -f @@ -33,6 +35,7 @@ CC=gcc LC=llvm-ar rsv +CLC=ar rsv DC=llvmdc LLC=llvm-as @@ -68,7 +71,7 @@ targets : lib doc all : lib doc tango : lib -lib : tango.lib +lib : tango.lib tango.clib doc : tango.doc ###################################################### @@ -82,14 +85,15 @@ # core/ThreadASM.o OBJ_STDC= \ - stdc/wrap.bc + stdc/wrap.o +# stdc/wrap.bc OBJ_STDC_POSIX= \ stdc/posix/pthread_darwin.o ALL_OBJS= \ - $(OBJ_CORE) \ - $(OBJ_STDC) + $(OBJ_CORE) +# $(OBJ_STDC) # $(OBJ_STDC_POSIX) ###################################################### @@ -112,6 +116,14 @@ $(RM) $@ $(LC) $@ $(ALL_OBJS) + +tango.clib : $(LIB_TARGET_C) + +$(LIB_TARGET_C) : $(OBJ_STDC) + $(RM) $@ + $(CLC) $@ $(OBJ_STDC) + + tango.doc : $(ALL_DOCS) echo Documentation generated. @@ -127,8 +139,10 @@ clean : find . -name "*.di" | xargs $(RM) $(RM) $(ALL_OBJS) + $(RM) $(OBJ_STDC) $(RM) $(ALL_DOCS) find . -name "$(LIB_MASK)" | xargs $(RM) + find . -name "$(LIB_MASK_C)" | xargs $(RM) install : $(MD) $(INC_DEST) @@ -137,3 +151,4 @@ find . -name "*.html" -exec cp -f {} $(DOC_DEST)/{} \; $(MD) $(LIB_DEST) find . -name "$(LIB_MASK)" -exec cp -f {} $(LIB_DEST)/{} \; + find . -name "$(LIB_MASK_C)" -exec cp -f {} $(LIB_DEST)/{} \; diff -r 1700239cab2e -r 44a95ac7368a tango/lib/common/tango/stdc/wrap.ll --- a/tango/lib/common/tango/stdc/wrap.ll Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/common/tango/stdc/wrap.ll Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,5 @@ ; ModuleID = 'wrap.bc' -@errno = external global i32 ; [#uses=2] +@errno = external thread_local global i32 ; [#uses=2] define i32 @getErrno() { entry: diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/cast.d --- a/tango/lib/compiler/llvmdc/cast.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/compiler/llvmdc/cast.d Mon Jan 14 05:11:54 2008 +0100 @@ -99,7 +99,7 @@ return o; } -int _d_isbaseof2(ClassInfo oc, ClassInfo c, inout size_t offset) +int _d_isbaseof2(ClassInfo oc, ClassInfo c, ref size_t offset) { int i; if (oc is c) diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/contract.d --- a/tango/lib/compiler/llvmdc/contract.d Fri Jan 11 17:57:40 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -extern(C): - -void exit(int); -int printf(char*,...); - -void _d_assert(bool cond, uint line, char[] msg) -{ - if (!cond) { - printf("Aborted(%u): %.*s\n", line, msg.length, msg.ptr); - exit(1); - } -} diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/critical.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/lib/compiler/llvmdc/critical.c Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,160 @@ +/* + * Placed into the Public Domain + * written by Walter Bright, Digital Mars + * www.digitalmars.com + */ + +/* ================================= Win32 ============================ */ + +#if _WIN32 + +#include + +/****************************************** + * Enter/exit critical section. + */ + +/* We don't initialize critical sections unless we actually need them. + * So keep a linked list of the ones we do use, and in the static destructor + * code, walk the list and release them. + */ + +typedef struct D_CRITICAL_SECTION +{ + struct D_CRITICAL_SECTION *next; + CRITICAL_SECTION cs; +} D_CRITICAL_SECTION; + +static D_CRITICAL_SECTION *dcs_list; +static D_CRITICAL_SECTION critical_section; +static volatile int inited; + +void _d_criticalenter(D_CRITICAL_SECTION *dcs) +{ + if (!dcs->next) + { + EnterCriticalSection(&critical_section.cs); + if (!dcs->next) // if, in the meantime, another thread didn't set it + { + dcs->next = dcs_list; + dcs_list = dcs; + InitializeCriticalSection(&dcs->cs); + } + LeaveCriticalSection(&critical_section.cs); + } + EnterCriticalSection(&dcs->cs); +} + +void _d_criticalexit(D_CRITICAL_SECTION *dcs) +{ + LeaveCriticalSection(&dcs->cs); +} + +void _STI_critical_init() +{ + if (!inited) + { InitializeCriticalSection(&critical_section.cs); + dcs_list = &critical_section; + inited = 1; + } +} + +void _STD_critical_term() +{ + if (inited) + { inited = 0; + while (dcs_list) + { + DeleteCriticalSection(&dcs_list->cs); + dcs_list = dcs_list->next; + } + } +} + +#endif + +/* ================================= linux ============================ */ + +#if linux + +#include +#include +#include + +/****************************************** + * Enter/exit critical section. + */ + +/* We don't initialize critical sections unless we actually need them. + * So keep a linked list of the ones we do use, and in the static destructor + * code, walk the list and release them. + */ + +typedef struct D_CRITICAL_SECTION +{ + struct D_CRITICAL_SECTION *next; + pthread_mutex_t cs; +} D_CRITICAL_SECTION; + +static D_CRITICAL_SECTION *dcs_list; +static D_CRITICAL_SECTION critical_section; +static pthread_mutexattr_t _criticals_attr; + +void _STI_critical_init(void); +void _STD_critical_term(void); + +void _d_criticalenter(D_CRITICAL_SECTION *dcs) +{ + if (!dcs_list) + { _STI_critical_init(); + atexit(_STD_critical_term); + } + //printf("_d_criticalenter(dcs = x%x)\n", dcs); + if (!dcs->next) + { + pthread_mutex_lock(&critical_section.cs); + if (!dcs->next) // if, in the meantime, another thread didn't set it + { + dcs->next = dcs_list; + dcs_list = dcs; + pthread_mutex_init(&dcs->cs, &_criticals_attr); + } + pthread_mutex_unlock(&critical_section.cs); + } + pthread_mutex_lock(&dcs->cs); +} + +void _d_criticalexit(D_CRITICAL_SECTION *dcs) +{ + //printf("_d_criticalexit(dcs = x%x)\n", dcs); + pthread_mutex_unlock(&dcs->cs); +} + +void _STI_critical_init() +{ + if (!dcs_list) + { //printf("_STI_critical_init()\n"); + pthread_mutexattr_init(&_criticals_attr); + pthread_mutexattr_settype(&_criticals_attr, PTHREAD_MUTEX_RECURSIVE_NP); + + // The global critical section doesn't need to be recursive + pthread_mutex_init(&critical_section.cs, 0); + dcs_list = &critical_section; + } +} + +void _STD_critical_term() +{ + if (dcs_list) + { //printf("_STI_critical_term()\n"); + while (dcs_list) + { + //printf("\tlooping... %x\n", dcs_list); + pthread_mutex_destroy(&dcs_list->cs); + dcs_list = dcs_list->next; + } + } +} + +#endif + diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/dmain2.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/lib/compiler/llvmdc/dmain2.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,303 @@ +/* + * Placed into the Public Domain. + * written by Walter Bright + * www.digitalmars.com + */ + +/* + * Modified by Sean Kelly for use with Tango. + */ + +private +{ + import util.console; + + import tango.stdc.stddef; + import tango.stdc.stdlib; + import tango.stdc.string; +} + +version( Win32 ) +{ + extern (Windows) void* LocalFree(void*); + extern (Windows) wchar_t* GetCommandLineW(); + extern (Windows) wchar_t** CommandLineToArgvW(wchar_t*, int*); + extern (Windows) export int WideCharToMultiByte(uint, uint, wchar_t*, int, char*, int, char*, int); + pragma(lib, "shell32.lib"); // needed for CommandLineToArgvW + pragma(lib, "tango-win32-dmd.lib"); // links Tango's Win32 library to reduce EXE size +} + +extern (C) void _STI_monitor_staticctor(); +extern (C) void _STD_monitor_staticdtor(); +extern (C) void _STI_critical_init(); +extern (C) void _STD_critical_term(); +extern (C) void gc_init(); +extern (C) void gc_term(); +extern (C) void _minit(); +extern (C) void _moduleCtor(); +extern (C) void _moduleDtor(); +extern (C) void thread_joinAll(); + +//debug=PRINTF; +debug(PRINTF) extern (C) int printf(char*, ...); + +/*********************************** + * These functions must be defined for any D program linked + * against this library. + */ +extern (C) void onAssertError( char[] file, size_t line ); +extern (C) void onAssertErrorMsg( char[] file, size_t line, char[] msg ); +extern (C) void onArrayBoundsError( char[] file, size_t line ); +extern (C) void onSwitchError( char[] file, size_t line ); +extern (C) bool runModuleUnitTests(); + +// this function is called from the utf module +//extern (C) void onUnicodeError( char[] msg, size_t idx ); + +/*********************************** + * These are internal callbacks for various language errors. + */ +extern (C) void _d_assert( char[] file, uint line ) +{ + onAssertError( file, line ); +} + +extern (C) void _d_assert_msg( char[] msg, char[] file, uint line ) +{ + onAssertErrorMsg( file, line, msg ); +} + +extern (C) void _d_array_bounds( char[] file, uint line ) +{ + onArrayBoundsError( file, line ); +} + +extern (C) void _d_switch_error( char[] file, uint line ) +{ + onSwitchError( file, line ); +} + +bool _d_isHalting = false; + +extern (C) bool rt_isHalting() +{ + return _d_isHalting; +} + +extern (C) bool rt_trapExceptions = true; + +void _d_criticalInit() +{ + version (linux) + { + _STI_monitor_staticctor(); + _STI_critical_init(); + } +} + +extern (C) bool rt_init( void delegate( Exception ) dg = null ) +{ + _d_criticalInit(); + + try + { + gc_init(); + version (Win32) + _minit(); + _moduleCtor(); + return true; + } + catch( Exception e ) + { + if( dg ) + dg( e ); + } + catch + { + + } + _d_criticalTerm(); + return false; +} + +void _d_criticalTerm() +{ + version (linux) + { + _STD_critical_term(); + _STD_monitor_staticdtor(); + } +} + +extern (C) bool rt_term( void delegate( Exception ) dg = null ) +{ + try + { + thread_joinAll(); + _d_isHalting = true; + _moduleDtor(); + gc_term(); + return true; + } + catch( Exception e ) + { + if( dg ) + dg( e ); + } + catch + { + + } + finally + { + _d_criticalTerm(); + } + return false; +} + +/*********************************** + * The D main() function supplied by the user's program + */ +int main(char[][] args); + +/*********************************** + * Substitutes for the C main() function. + * It's purpose is to wrap the call to the D main() + * function and catch any unhandled exceptions. + */ + +extern (C) int main(int argc, char **argv, char** env) +{ + char[][] args; + int result; + + version (linux) + { + debug(PRINTF) printf("main ctors\n"); + _STI_monitor_staticctor(); + _STI_critical_init(); + } + + debug(PRINTF) printf("main args\n"); + version (Win32) + { + wchar_t* wcbuf = GetCommandLineW(); + size_t wclen = wcslen(wcbuf); + int wargc = 0; + wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc); + assert(wargc == argc); + + char* cargp = null; + size_t cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, 0); + + cargp = cast(char*) alloca(cargl); + args = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc]; + + for (size_t i = 0, p = 0; i < wargc; i++) + { + int wlen = wcslen( wargs[i] ); + int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, 0); + args[i] = cargp[p .. p+clen]; + p += clen; assert(p <= cargl); + WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, 0); + } + LocalFree(wargs); + wargs = null; + wargc = 0; + } + else version (linux) + { + char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof); + scope(exit) free(am); + + for (size_t i = 0; i < argc; i++) + { + auto len = strlen(argv[i]); + am[i] = argv[i][0 .. len]; + } + args = am[0 .. argc]; + } + + debug(PRINTF) printf("main trap exceptions\n"); + bool trapExceptions = rt_trapExceptions; + + void tryExec(void delegate() dg) + { + debug(PRINTF) printf("main try exec\n"); + if (trapExceptions) + { + try + { + dg(); + } + catch (Exception e) + { + while (e) + { + if (e.file) + { + debug(PRINTF) printf("%.*s(%u): %.*s\n", e.file.length, e.file.ptr, e.line, e.msg.length, e.msg.ptr); + console (e.classinfo.name)("@")(e.file)("(")(e.line)("): ")(e.msg)("\n"); + } + else + { + // debug(PRINTF) printf("%.*s\n", e.toString()); + console (e.classinfo.name)(": ")(e.toString)("\n"); + } + e = e.next; + } + result = EXIT_FAILURE; + } + catch (Object o) + { + // fprintf(stderr, "%.*s\n", o.toString()); + console (o.toString)("\n"); + result = EXIT_FAILURE; + } + } + else + { + dg(); + } + } + + // NOTE: The lifetime of a process is much like the lifetime of an object: + // it is initialized, then used, then destroyed. If initialization + // fails, the successive two steps are never reached. However, if + // initialization succeeds, then cleanup will occur even if the use + // step fails in some way. Here, the use phase consists of running + // the user's main function. If main terminates with an exception, + // the exception is handled and then cleanup begins. An exception + // thrown during cleanup, however, will abort the cleanup process. + + void runMain() + { + debug(PRINTF) printf("main runMain\n"); + result = main(args); + } + + void runAll() + { + debug(PRINTF) printf("main runAll\n"); + gc_init(); + version (Win32) + _minit(); + _moduleCtor(); + if (runModuleUnitTests()) + tryExec(&runMain); + thread_joinAll(); + _d_isHalting = true; + _moduleDtor(); + gc_term(); + } + + tryExec(&runAll); + + version (linux) + { + debug(PRINTF) printf("main dtor\n"); + _STD_critical_term(); + _STD_monitor_staticdtor(); + } + return result; +} diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/eh.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/lib/compiler/llvmdc/eh.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,17 @@ +/* + * Temporary exception handling stubs + */ + +import util.console; + +private extern(C) void abort(); + +extern(C) void _d_throw_exception(Object e) +{ + console("Exception: "); + if (e !is null) + { + console(e.toString())("\n"); + } + abort(); +} diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/genobj.d --- a/tango/lib/compiler/llvmdc/genobj.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/compiler/llvmdc/genobj.d Mon Jan 14 05:11:54 2008 +0100 @@ -37,6 +37,8 @@ module object; +//debug=PRINTF; + private { import tango.stdc.string; // : memcmp, memcpy; @@ -962,19 +964,8 @@ // linux: this gets initialized in _moduleCtor() extern (C) ModuleInfo[] _moduleinfo_array; - -version (linux) -{ - // This linked list is created by a compiler generated function inserted - // into the .ctor list by the compiler. - struct ModuleReference - { - ModuleReference* next; - ModuleInfo mod; - } - - extern (C) ModuleReference* _Dmodule_ref; // start of linked list -} +// llvmdc method +extern (C) void** _d_get_moduleinfo_array(); ModuleInfo[] _moduleinfo_dtors; uint _moduleinfo_dtors_i; @@ -989,19 +980,20 @@ extern (C) void _moduleCtor() { debug(PRINTF) printf("_moduleCtor()\n"); - version (linux) - { - int len = 0; - ModuleReference *mr; + + ModuleInfo* mrbegin = cast(ModuleInfo*)_d_get_moduleinfo_array(); + assert(mrbegin !is null); - for (mr = _Dmodule_ref; mr; mr = mr.next) - len++; - _moduleinfo_array = new ModuleInfo[len]; - len = 0; - for (mr = _Dmodule_ref; mr; mr = mr.next) - { _moduleinfo_array[len] = mr.mod; - len++; - } + int len = 0; + ModuleInfo* mr; + for (mr = mrbegin; *mr !is null; ++mr) + len++; + _moduleinfo_array = new ModuleInfo[len]; + + len = 0; + for (mr = mrbegin; *mr !is null; ++mr) + { _moduleinfo_array[len] = *mr; + len++; } version (Win32) @@ -1014,6 +1006,7 @@ debug(PRINTF) printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors); _moduleIndependentCtors(); _moduleCtor2(_moduleinfo_array, 0); + debug(PRINTF) printf("_moduleCtor() DONE\n"); } extern (C) void _moduleIndependentCtors() @@ -1026,6 +1019,7 @@ (*m.ictor)(); } } + debug(PRINTF) printf("_moduleIndependentCtors() DONE\n"); } void _moduleCtor2(ModuleInfo[] mi, int skip) @@ -1038,10 +1032,10 @@ debug(PRINTF) printf("\tmodule[%d] = '%p'\n", i, m); if (!m) continue; - debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name); + debug(PRINTF) printf("\tmodule[%d] = '%.*s'\n", i, m.name.length, m.name.ptr); if (m.flags & MIctordone) continue; - debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name, m); + debug(PRINTF) printf("\tmodule[%d] = '%.*s', m = x%x\n", i, m.name.length, m.name.ptr, m); if (m.ctor || m.dtor) { @@ -1069,6 +1063,7 @@ _moduleCtor2(m.importedModules, 1); } } + debug(PRINTF) printf("_moduleCtor2() DONE\n"); } /** diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/lifetime.d --- a/tango/lib/compiler/llvmdc/lifetime.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/compiler/llvmdc/lifetime.d Mon Jan 14 05:11:54 2008 +0100 @@ -26,6 +26,8 @@ */ module lifetime; +//debug=PRINTF; +debug=PRINTF2; private { @@ -33,6 +35,7 @@ import tango.stdc.string; import tango.stdc.stdarg; debug(PRINTF) import tango.stdc.stdio; + else debug(PRINTF2) import tango.stdc.stdio; } @@ -86,7 +89,8 @@ { void* p; - debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name); + debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name.ptr); + /+ if (ci.flags & 1) // if COM object { /* COM objects are not garbage collected, they are reference counted * using AddRef() and Release(). They get free'd by C's free() @@ -98,10 +102,11 @@ onOutOfMemoryError(); } else + +/ { p = gc_malloc(ci.init.length, BlkAttr.FINALIZE | (ci.flags & 2 ? BlkAttr.NO_SCAN : 0)); - debug(PRINTF) printf(" p = %p\n", p); + debug(PRINTF2) printf(" p = %p\n", p); } debug(PRINTF) @@ -119,7 +124,8 @@ } // initialize it - (cast(byte*) p)[0 .. ci.init.length] = ci.init[]; + // llvmdc does this inline + //(cast(byte*) p)[0 .. ci.init.length] = ci.init[]; debug(PRINTF) printf("initialization done\n"); return cast(Object) p; diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/llvmdc.mak --- a/tango/lib/compiler/llvmdc/llvmdc.mak Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/compiler/llvmdc/llvmdc.mak Mon Jan 14 05:11:54 2008 +0100 @@ -13,6 +13,9 @@ LIB_TARGET=libtango-rt-llvmdc.a LIB_MASK=libtango-rt-llvmdc*.a +LIB_TARGET_C=libtango-rt-c-llvmdc.a +LIB_MASK_C=libtango-rt-c-llvmdc*.a + CP=cp -f RM=rm -f MD=mkdir -p @@ -30,6 +33,7 @@ CC=gcc LC=llvm-ar rsv +CLC=ar rsv DC=llvmdc LLC=llvm-as @@ -60,10 +64,13 @@ targets : lib doc all : lib doc -lib : llvmdc.lib +lib : llvmdc.lib llvmdc.clib doc : llvmdc.doc ###################################################### +OBJ_C= \ + monitor.o \ + critical.o OBJ_BASE= \ aaA.bc \ @@ -72,7 +79,8 @@ adi.bc \ arrays.bc \ cast.bc \ - contract.bc \ + dmain2.bc \ + eh.bc \ genobj.bc \ lifetime.bc \ mem.bc \ @@ -147,6 +155,12 @@ $(RM) $@ $(LC) $@ $(ALL_OBJS) +llvmdc.clib : $(LIB_TARGET_C) + +$(LIB_TARGET_C) : $(OBJ_C) + $(RM) $@ + $(CLC) $@ $(OBJ_C) + llvmdc.doc : $(ALL_DOCS) echo No documentation available. @@ -155,9 +169,12 @@ clean : find . -name "*.di" | xargs $(RM) $(RM) $(ALL_OBJS) + $(RM) $(OBJ_C) $(RM) $(ALL_DOCS) $(RM) $(LIB_MASK) + $(RM) $(LIB_MASK_C) install : $(MD) $(LIB_DEST) $(CP) $(LIB_MASK) $(LIB_DEST)/. + $(CP) $(LIB_MASK_C) $(LIB_DEST)/. diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/mars.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/lib/compiler/llvmdc/mars.h Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,104 @@ + +/* + * Placed into the Public Domain + * written by Walter Bright, Digital Mars + * www.digitalmars.com + */ + +/* + * Modified by Sean Kelly for use with Tango. + */ + +#include + +#if __cplusplus +extern "C" { +#endif + +struct ClassInfo; +struct Vtbl; + +typedef struct Vtbl +{ + size_t len; + void **vptr; +} Vtbl; + +typedef struct Interface +{ + struct ClassInfo *classinfo; + struct Vtbl vtbl; + int offset; +} Interface; + +typedef struct Object +{ + void **vptr; + void *monitor; +} Object; + +typedef struct ClassInfo +{ + Object object; + + size_t initlen; + void *init; + + size_t namelen; + char *name; + + Vtbl vtbl; + + size_t interfacelen; + Interface *interfaces; + + struct ClassInfo *baseClass; + + void *destructor; + void *invariant; + + int flags; +} ClassInfo; + +typedef struct Exception +{ + Object object; + + size_t msglen; + char* msg; + + size_t filelen; + char* file; + + size_t line; + + struct Exception *next; +} Exception; + +typedef struct Array +{ + size_t length; + void *ptr; +} Array; + +typedef struct Delegate +{ + void *thisptr; + void (*funcptr)(); +} Delegate; + +void _d_monitorenter(Object *h); +void _d_monitorexit(Object *h); + +int _d_isbaseof(ClassInfo *b, ClassInfo *c); +Object *_d_dynamic_cast(Object *o, ClassInfo *ci); + +Object * _d_newclass(ClassInfo *ci); +void _d_delclass(Object **p); + +void _d_OutOfMemory(); + +#if __cplusplus +} +#endif + diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/monitor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tango/lib/compiler/llvmdc/monitor.c Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,207 @@ +// D programming language runtime library +// Public Domain +// written by Walter Bright, Digital Mars +// www.digitalmars.com + +// This is written in C because nobody has written a pthreads interface +// to D yet. + + +#include +#include +#include + +#if _WIN32 +#elif linux +#define USE_PTHREADS 1 +#else +#endif + +#if _WIN32 +#include +#endif + +#if USE_PTHREADS +#include +#endif + +#include "mars.h" + +// This is what the monitor reference in Object points to +typedef struct Monitor +{ + void* impl; // for user-level monitors + +#if _WIN32 + CRITICAL_SECTION mon; +#endif + +#if USE_PTHREADS + pthread_mutex_t mon; +#endif +} Monitor; + +#define MONPTR(h) (&((Monitor *)(h)->monitor)->mon) + +static volatile int inited; + +/* =============================== Win32 ============================ */ + +#if _WIN32 + +static CRITICAL_SECTION _monitor_critsec; + +void _STI_monitor_staticctor() +{ + if (!inited) + { InitializeCriticalSection(&_monitor_critsec); + inited = 1; + } +} + +void _STD_monitor_staticdtor() +{ + if (inited) + { inited = 0; + DeleteCriticalSection(&_monitor_critsec); + } +} + +void _d_monitor_create(Object *h) +{ + /* + * NOTE: Assume this is only called when h->monitor is null prior to the + * call. However, please note that another thread may call this function + * at the same time, so we can not assert this here. Instead, try and + * create a lock, and if one already exists then forget about it. + */ + + //printf("+_d_monitor_create(%p)\n", h); + assert(h); + Monitor *cs = NULL; + EnterCriticalSection(&_monitor_critsec); + if (!h->monitor) + { + cs = (Monitor *)calloc(sizeof(Monitor), 1); + assert(cs); + InitializeCriticalSection(&cs->mon); + h->monitor = (void *)cs; + cs = NULL; + } + LeaveCriticalSection(&_monitor_critsec); + if (cs) + free(cs); + //printf("-_d_monitor_create(%p)\n", h); +} + +void _d_monitor_destroy(Object *h) +{ + //printf("+_d_monitor_destroy(%p)\n", h); + assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); + DeleteCriticalSection(MONPTR(h)); + free((void *)h->monitor); + h->monitor = NULL; + //printf("-_d_monitor_destroy(%p)\n", h); +} + +int _d_monitor_lock(Object *h) +{ + //printf("+_d_monitor_acquire(%p)\n", h); + assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); + EnterCriticalSection(MONPTR(h)); + //printf("-_d_monitor_acquire(%p)\n", h); +} + +void _d_monitor_unlock(Object *h) +{ + //printf("+_d_monitor_release(%p)\n", h); + assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); + LeaveCriticalSection(MONPTR(h)); + //printf("-_d_monitor_release(%p)\n", h); +} + +#endif + +/* =============================== linux ============================ */ + +#if USE_PTHREADS + +// Includes attribute fixes from David Friedman's GDC port + +static pthread_mutex_t _monitor_critsec; +static pthread_mutexattr_t _monitors_attr; + +void _STI_monitor_staticctor() +{ + if (!inited) + { + pthread_mutexattr_init(&_monitors_attr); + pthread_mutexattr_settype(&_monitors_attr, PTHREAD_MUTEX_RECURSIVE_NP); + pthread_mutex_init(&_monitor_critsec, 0); + inited = 1; + } +} + +void _STD_monitor_staticdtor() +{ + if (inited) + { inited = 0; + pthread_mutex_destroy(&_monitor_critsec); + pthread_mutexattr_destroy(&_monitors_attr); + } +} + +void _d_monitor_create(Object *h) +{ + /* + * NOTE: Assume this is only called when h->monitor is null prior to the + * call. However, please note that another thread may call this function + * at the same time, so we can not assert this here. Instead, try and + * create a lock, and if one already exists then forget about it. + */ + + //printf("+_d_monitor_create(%p)\n", h); + assert(h); + Monitor *cs = NULL; + pthread_mutex_lock(&_monitor_critsec); + if (!h->monitor) + { + cs = (Monitor *)calloc(sizeof(Monitor), 1); + assert(cs); + pthread_mutex_init(&cs->mon, & _monitors_attr); + h->monitor = (void *)cs; + cs = NULL; + } + pthread_mutex_unlock(&_monitor_critsec); + if (cs) + free(cs); + //printf("-_d_monitor_create(%p)\n", h); +} + +void _d_monitor_destroy(Object *h) +{ + //printf("+_d_monitor_destroy(%p)\n", h); + assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); + pthread_mutex_destroy(MONPTR(h)); + free((void *)h->monitor); + h->monitor = NULL; + //printf("-_d_monitor_destroy(%p)\n", h); +} + +int _d_monitor_lock(Object *h) +{ + //printf("+_d_monitor_acquire(%p)\n", h); + assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); + pthread_mutex_lock(MONPTR(h)); + //printf("-_d_monitor_acquire(%p)\n", h); +} + +void _d_monitor_unlock(Object *h) +{ + //printf("+_d_monitor_release(%p)\n", h); + assert(h && h->monitor && !(((Monitor*)h->monitor)->impl)); + pthread_mutex_unlock(MONPTR(h)); + //printf("-_d_monitor_release(%p)\n", h); +} + +#endif diff -r 1700239cab2e -r 44a95ac7368a tango/lib/compiler/llvmdc/util/console.d --- a/tango/lib/compiler/llvmdc/util/console.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/compiler/llvmdc/util/console.d Mon Jan 14 05:11:54 2008 +0100 @@ -75,9 +75,9 @@ } // emit an integer to the console - Console opCall (uint i) + Console opCall (size_t i) { - char[10] tmp = void; + char[20] tmp = void; return console (intToUtf8 (tmp, i)); } diff -r 1700239cab2e -r 44a95ac7368a tango/lib/llvmdc-posix.mak --- a/tango/lib/llvmdc-posix.mak Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/lib/llvmdc-posix.mak Mon Jan 14 05:11:54 2008 +0100 @@ -12,6 +12,8 @@ LIB_TARGET=libtango-base-llvmdc.a LIB_MASK=libtango-base-llvmdc*.a +LIB_TARGET_C=libtango-base-c-llvmdc.a +LIB_MASK_C=libtango-base-c-llvmdc*.a DIR_CC=./common/tango DIR_RT=./compiler/llvmdc @@ -23,13 +25,14 @@ CC=gcc LC=llvm-ar rsv +CLC=ar rsv DC=llvmdc ADD_CFLAGS= ADD_DFLAGS= -targets : lib doc -all : lib doc +targets : lib clib doc +all : lib clib doc ###################################################### @@ -49,6 +52,8 @@ $(LC) $(LIB_TARGET) `find $(DIR_CC) -name "*.bc" | xargs echo` $(LC) $(LIB_TARGET) `find $(DIR_RT) -name "*.bc" | xargs echo` $(LC) $(LIB_TARGET) `find $(DIR_GC) -name "*.bc" | xargs echo` + $(CLC) $(LIB_TARGET_C) `find $(DIR_CC) -name "*.o" | xargs echo` + $(CLC) $(LIB_TARGET_C) `find $(DIR_RT) -name "*.o" | xargs echo` doc : $(ALL_DOCS) make -C $(DIR_CC) -fllvmdc.mak doc @@ -65,9 +70,11 @@ make -C $(DIR_RT) -fllvmdc.mak clean make -C $(DIR_GC) -fllvmdc.mak clean $(RM) $(LIB_MASK) + $(RM) $(LIB_MASK_C) install : make -C $(DIR_CC) -fllvmdc.mak install make -C $(DIR_RT) -fllvmdc.mak install make -C $(DIR_GC) -fllvmdc.mak install -# $(CP) $(LIB_MASK) $(LIB_DEST)/. + $(CP) $(LIB_MASK) $(LIB_DEST)/. + $(CP) $(LIB_MASK_C) $(LIB_DEST)/. diff -r 1700239cab2e -r 44a95ac7368a tango/tango/io/Console.d --- a/tango/tango/io/Console.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tango/tango/io/Console.d Mon Jan 14 05:11:54 2008 +0100 @@ -621,14 +621,21 @@ ******************************************************************************/ +extern(C) int printf(char*, ...); + static this () { + printf("STATIC INIT FOR CONSOLE\n"); + printf("Cin\n"); auto conduit = new Console.Conduit (0); + assert(conduit); Cin = new Console.Input (conduit, conduit.redirected); + printf("Cout\n"); conduit = new Console.Conduit (1); Cout = new Console.Output (conduit, conduit.redirected); + printf("Cerr\n"); conduit = new Console.Conduit (2); Cerr = new Console.Output (conduit, conduit.redirected); } diff -r 1700239cab2e -r 44a95ac7368a tangotests/f.d --- a/tangotests/f.d Fri Jan 11 17:57:40 2008 +0100 +++ b/tangotests/f.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ extern(C) int printf(char*,...); + + void main() { printf("Hello World!\n"); diff -r 1700239cab2e -r 44a95ac7368a tangotests/h.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/h.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,27 @@ +interface Iin +{ + void[] read(size_t n); +} + +interface Iout +{ + size_t write(void[] d); +} + +class C : Iin +{ + void[] read(size_t n) + { + return null; + } + + size_t write(void[] d) + { + return 0; + } +} + +void func() +{ + scope c = new C; +} diff -r 1700239cab2e -r 44a95ac7368a tangotests/i.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/i.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,20 @@ +interface IN +{ + void func(); +} +abstract class AC +{ + abstract void func(); + long ll; +} +class C : AC +{ + void func() + { + } +} + +void func() +{ + scope c = new C; +} diff -r 1700239cab2e -r 44a95ac7368a tangotests/j.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/j.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,44 @@ +module j; + +interface Inter1 +{ + int func1(); +} + +interface Inter2 +{ + int func2(); +} + +class C12 : Inter1, Inter2 +{ + int func1() + { + return 1; + } + int func2() + { + return 2; + } +} + +void func(Object c) +{ + auto i1 = cast(Inter1)c; + assert(i1.func1() == 1); + auto i2 = cast(Inter2)c; + assert(i2.func2() == 2); + auto j1 = cast(Inter1)i2; + assert(j1.func1() == 1); + auto j2 = cast(Inter2)i1; + assert(j2.func2() == 2); +} + +void main() +{ + scope c = new C12; + func(c); + printf("OK\n"); +} + +extern(C) int printf(char*,...); diff -r 1700239cab2e -r 44a95ac7368a tangotests/k.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/k.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,31 @@ +interface Inter +{ + int func(); +} + +extern(C) int printf(char*, ...); + +class InterClass : Inter +{ + int func() + { + return printf("InterClass.func()\n"); + } +} + +alias int delegate() dg_t; + +void main() +{ + scope c = new InterClass; + + { + Inter i = cast(Inter)c; + { + dg_t dg = &i.func; + { + int j = dg(); + } + } + } +} diff -r 1700239cab2e -r 44a95ac7368a tangotests/l.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/l.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,11 @@ +import tango.io.Console; + +void main() +{ + printf("enter\n"); + assert(Cout !is null); + Cout("Hi, says LLVMDC + Tango").newline; + printf("exit\n"); +} + +extern(C) int printf(char*,...); diff -r 1700239cab2e -r 44a95ac7368a tangotests/m.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/m.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,10 @@ +void main() +{ + int* e = __errno_location(); + printf("&errno = %p\n", e); + printf("errno = %d\n", *e); +} + +extern(C): +int* __errno_location(); +int printf(char*,...); diff -r 1700239cab2e -r 44a95ac7368a tangotests/n.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/n.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,18 @@ +struct Structure +{ + static void static_method() + { + } + + void method() + { + } +} + +void main() +{ + //Structure.static_method(); + + Structure s; + s.method(); +} diff -r 1700239cab2e -r 44a95ac7368a tangotests/o.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tangotests/o.d Mon Jan 14 05:11:54 2008 +0100 @@ -0,0 +1,24 @@ +extern(C) int printf(char*, ...); + +void func() +{ + try + { + printf("try\n"); + return 0; + } + catch + { + printf("catch\n"); + } + finally + { + printf("finally\n"); + } + return 0; +} + +void main() +{ + func(); +} diff -r 1700239cab2e -r 44a95ac7368a test/interface1.d --- a/test/interface1.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface1.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface1; +extern(C) int printf(char*,...); + interface Inter { void func(); diff -r 1700239cab2e -r 44a95ac7368a test/interface2.d --- a/test/interface2.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface2.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface2; +extern(C) int printf(char*,...); + interface A { void a(); diff -r 1700239cab2e -r 44a95ac7368a test/interface3.d --- a/test/interface3.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface3.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface3; +extern(C) int printf(char*,...); + interface I { void func(); diff -r 1700239cab2e -r 44a95ac7368a test/interface4.d --- a/test/interface4.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface4.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface4; +extern(C) int printf(char*,...); + interface I { void func(); diff -r 1700239cab2e -r 44a95ac7368a test/interface5.d --- a/test/interface5.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface5.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface5; +extern(C) int printf(char*,...); + interface I { void func(); diff -r 1700239cab2e -r 44a95ac7368a test/interface6.d --- a/test/interface6.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface6.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface6; +extern(C) int printf(char*,...); + interface I { void Ifunc(); diff -r 1700239cab2e -r 44a95ac7368a test/interface7.d --- a/test/interface7.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/interface7.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module interface7; +extern(C) int printf(char*,...); + interface I { } diff -r 1700239cab2e -r 44a95ac7368a test/intrinsics.d --- a/test/intrinsics.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/intrinsics.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,6 @@ import llvm.intrinsic; +extern(C) int printf(char*,...); extern(C) int scanf(char*,...); void main() diff -r 1700239cab2e -r 44a95ac7368a test/mainargs1.d --- a/test/mainargs1.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/mainargs1.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module mainargs1; +extern(C) int printf(char*,...); + void main(string[] args) { foreach(v; args) diff -r 1700239cab2e -r 44a95ac7368a test/memory1.d --- a/test/memory1.d Fri Jan 11 17:57:40 2008 +0100 +++ b/test/memory1.d Mon Jan 14 05:11:54 2008 +0100 @@ -1,5 +1,7 @@ module memory1; +extern(C) int printf(char*,...); + void main() { auto a = new int[16];