# HG changeset patch # User lindquist # Date 1195365177 -3600 # Node ID 027b8d8b71ec4ce7be338734b15fdda1a909ce2c # Parent 169fda3a77d441ccf73717cfd4e57a24414826a0 [svn r106] Turns out the last commit wasn't enough, now the D->LLVM process is even more split up. Basically it tries to do the following in order: Resolve types, Declare symbols, Create constant initializers, Apply initializers, Generate functions bodies. ClassInfo is now has the most useful(biased?) members working. Probably other stuf... diff -r 169fda3a77d4 -r 027b8d8b71ec dmd/aggregate.h --- a/dmd/aggregate.h Fri Nov 16 10:01:24 2007 +0100 +++ b/dmd/aggregate.h Sun Nov 18 06:52:57 2007 +0100 @@ -110,6 +110,8 @@ bool llvmHasUnions; DUnion* llvmUnion; IRStruct* llvmIRStruct; + bool llvmClassDeclared; + bool llvmClassDefined; AggregateDeclaration *isAggregateDeclaration() { return this; } }; diff -r 169fda3a77d4 -r 027b8d8b71ec dmd/dsymbol.c --- a/dmd/dsymbol.c Fri Nov 16 10:01:24 2007 +0100 +++ b/dmd/dsymbol.c Sun Nov 18 06:52:57 2007 +0100 @@ -48,7 +48,11 @@ this->llvmInternal2 = NULL; this->llvmValue = NULL; this->llvmDModule = NULL; - this->llvmTouched = false; + + this->llvmResolved = false; + this->llvmDeclared = false; + this->llvmInitialized = false; + this->llvmDefined = false; } Dsymbol::Dsymbol(Identifier *ident) @@ -66,7 +70,11 @@ this->llvmInternal2 = NULL; this->llvmValue = NULL; this->llvmDModule = NULL; - this->llvmTouched = false; + + this->llvmResolved = false; + this->llvmDeclared = false; + this->llvmInitialized = false; + this->llvmDefined = false; } int Dsymbol::equals(Object *o) diff -r 169fda3a77d4 -r 027b8d8b71ec dmd/dsymbol.h --- a/dmd/dsymbol.h Fri Nov 16 10:01:24 2007 +0100 +++ b/dmd/dsymbol.h Sun Nov 18 06:52:57 2007 +0100 @@ -223,7 +223,10 @@ llvm::Value* llvmValue; Module* llvmDModule; - bool llvmTouched; + bool llvmResolved; + bool llvmDeclared; + bool llvmInitialized; + bool llvmDefined; }; // Dsymbol that generates a scope diff -r 169fda3a77d4 -r 027b8d8b71ec dmd/mtype.c --- a/dmd/mtype.c Fri Nov 16 10:01:24 2007 +0100 +++ b/dmd/mtype.c Sun Nov 18 06:52:57 2007 +0100 @@ -4374,6 +4374,7 @@ { this->sym = sym; llvmInit = 0; + llvmVtblType = 0; } char *TypeClass::toChars() diff -r 169fda3a77d4 -r 027b8d8b71ec dmd/mtype.h --- a/dmd/mtype.h Fri Nov 16 10:01:24 2007 +0100 +++ b/dmd/mtype.h Sun Nov 18 06:52:57 2007 +0100 @@ -642,6 +642,7 @@ Symbol *toSymbol(); llvm::GlobalVariable* llvmInit; + llvm::PATypeHolder* llvmVtblType; }; struct TypeTuple : Type diff -r 169fda3a77d4 -r 027b8d8b71ec dmd/struct.c --- a/dmd/struct.c Fri Nov 16 10:01:24 2007 +0100 +++ b/dmd/struct.c Sun Nov 18 06:52:57 2007 +0100 @@ -54,6 +54,8 @@ llvmHasUnions = false; llvmUnion = NULL; llvmIRStruct = NULL; + llvmClassDeclared = false; + llvmClassDefined = false; } enum PROT AggregateDeclaration::prot() diff -r 169fda3a77d4 -r 027b8d8b71ec gen/arrays.cpp --- a/gen/arrays.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/arrays.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -60,10 +60,8 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoNullArray(llvm::Value* v) +void DtoSetArrayToNull(llvm::Value* v) { - assert(gIR); - llvm::Value* len = DtoGEPi(v,0,0,"tmp",gIR->scopebb()); llvm::Value* zerolen = llvm::ConstantInt::get(len->getType()->getContainedType(0), 0, false); new llvm::StoreInst(zerolen, len, gIR->scopebb()); @@ -593,7 +591,7 @@ if (useti) { TypeInfoDeclaration* ti = DtoDType(l->getType())->next->getTypeInfoDeclaration(); if (!ti->llvmValue) { - ti->toObjFile(); + DtoForceConstInitDsymbol(ti); } Logger::cout() << "typeinfo decl: " << *ti->llvmValue << '\n'; @@ -786,3 +784,85 @@ return 0; } +////////////////////////////////////////////////////////////////////////////////////////// +DValue* DtoCastArray(DValue* u, Type* to) +{ + const llvm::Type* tolltype = DtoType(to); + + Type* totype = DtoDType(to); + Type* fromtype = DtoDType(u->getType()); + assert(fromtype->ty == Tarray || fromtype->ty == Tsarray); + + llvm::Value* rval; + llvm::Value* rval2; + bool isslice = false; + + Logger::cout() << "from array or sarray" << '\n'; + if (totype->ty == Tpointer) { + Logger::cout() << "to pointer" << '\n'; + assert(fromtype->next == totype->next || totype->next->ty == Tvoid); + 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"); + } + 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); + + const llvm::Type* ety = DtoType(fromtype->next); + if (ety == llvm::Type::VoidTy) + ety = llvm::Type::Int8Ty; + + if (DSliceValue* usl = u->isSlice()) { + Logger::println("from slice"); + Logger::cout() << "from: " << *usl->ptr << " to: " << *ptrty << '\n'; + rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb()); + if (fromtype->next->size() == totype->next->size()) + rval2 = usl->len; + else + rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0)); + } + else { + llvm::Value* uval = u->getRVal(); + if (fromtype->ty == Tsarray) { + Logger::cout() << "uvalTy = " << *uval->getType() << '\n'; + assert(isaPointer(uval->getType())); + const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0)); + rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false); + rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); + rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb()); + } + else { + llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); + llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); + rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb()); + rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb()); + rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); + + rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb()); + rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb()); + //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n'; + rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb()); + } + } + isslice = true; + } + else if (totype->ty == Tsarray) { + Logger::cout() << "to sarray" << '\n'; + assert(0); + } + else { + assert(0); + } + + if (isslice) { + Logger::println("isslice"); + return new DSliceValue(to, rval2, rval); + } + + return new DImValue(to, rval); +} diff -r 169fda3a77d4 -r 027b8d8b71ec gen/arrays.h --- a/gen/arrays.h Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/arrays.h Sun Nov 18 06:52:57 2007 +0100 @@ -16,7 +16,7 @@ void DtoArrayInit(llvm::Value* ptr, llvm::Value* dim, llvm::Value* val); void DtoArrayAssign(llvm::Value* l, llvm::Value* r); void DtoSetArray(llvm::Value* arr, llvm::Value* dim, llvm::Value* ptr); -void DtoNullArray(llvm::Value* v); +void DtoSetArrayToNull(llvm::Value* v); llvm::Value* DtoNewDynArray(llvm::Value* dst, llvm::Value* dim, Type* dty, bool doinit=true); llvm::Value* DtoResizeDynArray(llvm::Value* arr, llvm::Value* sz); @@ -37,4 +37,6 @@ llvm::Value* DtoArrayLen(DValue* v); llvm::Value* DtoArrayPtr(DValue* v); +DValue* DtoCastArray(DValue* val, Type* to); + #endif // LLVMC_GEN_ARRAYS_H diff -r 169fda3a77d4 -r 027b8d8b71ec gen/classes.cpp --- a/gen/classes.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/classes.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -10,6 +10,7 @@ #include "gen/arrays.h" #include "gen/logger.h" #include "gen/classes.h" +#include "gen/functions.h" ////////////////////////////////////////////////////////////////////////////////////////// @@ -23,8 +24,6 @@ Logger::println("Adding base class members of %s", bc->base->toChars()); LOG_SCOPE; - bc->base->toObjFile(); - LLVM_AddBaseClassData(&bc->base->baseclasses); for (int k=0; k < bc->base->members->dim; k++) { Dsymbol* dsym = (Dsymbol*)(bc->base->members->data[k]); @@ -38,12 +37,17 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoDeclareClass(ClassDeclaration* cd) +void DtoResolveClass(ClassDeclaration* cd) { - if (cd->llvmTouched) return; - cd->llvmTouched = true; + if (cd->llvmResolved) return; + cd->llvmResolved = true; - Logger::println("DtoDeclareClass(%s)\n", cd->toPrettyChars()); + // first resolve the base class + if (cd->baseClass) { + DtoResolveClass(cd->baseClass); + } + + Logger::println("DtoResolveClass(%s)", cd->toPrettyChars()); LOG_SCOPE; assert(cd->type->ty == Tclass); @@ -57,8 +61,8 @@ gIR->classes.push_back(cd); // add vtable - llvm::PATypeHolder pa = llvm::OpaqueType::get(); - const llvm::Type* vtabty = llvm::PointerType::get(pa); + ts->llvmVtblType = new llvm::PATypeHolder(llvm::OpaqueType::get()); + const llvm::Type* vtabty = llvm::PointerType::get(ts->llvmVtblType->get()); std::vector fieldtypes; fieldtypes.push_back(vtabty); @@ -80,13 +84,11 @@ const llvm::StructType* structtype = llvm::StructType::get(fieldtypes); // refine abstract types for stuff like: class C {C next;} assert(irstruct->recty != 0); - { + llvm::PATypeHolder& spa = irstruct->recty; llvm::cast(spa.get())->refineAbstractTypeTo(structtype); structtype = isaStruct(spa.get()); - } - // create the type ts->llvmType = new llvm::PATypeHolder(structtype); bool needs_definition = false; @@ -100,10 +102,7 @@ // generate vtable llvm::GlobalVariable* svtblVar = 0; - std::vector sinits; std::vector sinits_ty; - sinits.reserve(cd->vtbl.dim); - sinits_ty.reserve(cd->vtbl.dim); for (int k=0; k < cd->vtbl.dim; k++) { @@ -112,73 +111,100 @@ //Logger::cout() << "vtblsym: " << dsym->toChars() << '\n'; if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { - fd->toObjFile(); - assert(fd->llvmValue); - llvm::Constant* c = llvm::cast(fd->llvmValue); - sinits.push_back(c); - sinits_ty.push_back(c->getType()); + DtoResolveFunction(fd); + assert(fd->type->ty == Tfunction); + TypeFunction* tf = (TypeFunction*)fd->type; + const llvm::Type* fpty = llvm::PointerType::get(tf->llvmType->get()); + sinits_ty.push_back(fpty); } else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); - llvm::Constant* c = llvm::Constant::getNullValue(cty); - sinits.push_back(c); sinits_ty.push_back(cty); } else assert(0); } - const llvm::StructType* svtbl_ty = 0; - if (!sinits.empty()) - { - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; + assert(!sinits_ty.empty()); + const llvm::StructType* svtbl_ty = llvm::StructType::get(sinits_ty); + + std::string styname(cd->mangle()); + styname.append("__vtblType"); + gIR->module->addTypeName(styname, svtbl_ty); - std::string varname("_D"); - varname.append(cd->mangle()); - varname.append("6__vtblZ"); + // refine for final vtable type + llvm::cast(ts->llvmVtblType->get())->refineAbstractTypeTo(svtbl_ty); + + gIR->classes.pop_back(); + gIR->structs.pop_back(); + + gIR->declareList.push_back(cd); +} + +////////////////////////////////////////////////////////////////////////////////////////// - std::string styname(cd->mangle()); - styname.append("__vtblTy"); +void DtoDeclareClass(ClassDeclaration* cd) +{ + if (cd->llvmDeclared) return; + cd->llvmDeclared = true; + + Logger::println("DtoDeclareClass(%s)", cd->toPrettyChars()); + LOG_SCOPE; - svtbl_ty = llvm::StructType::get(sinits_ty); - gIR->module->addTypeName(styname, svtbl_ty); - svtblVar = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); + assert(cd->type->ty == Tclass); + TypeClass* ts = (TypeClass*)cd->type; + + assert(cd->llvmIRStruct); + IRStruct* irstruct = cd->llvmIRStruct; - cd->llvmConstVtbl = llvm::cast(llvm::ConstantStruct::get(svtbl_ty, sinits)); - if (needs_definition) - svtblVar->setInitializer(cd->llvmConstVtbl); - cd->llvmVtbl = svtblVar; + gIR->structs.push_back(irstruct); + gIR->classes.push_back(cd); + + bool needs_definition = false; + if (cd->parent->isModule()) { + needs_definition = (cd->getModule() == gIR->dmodule); } - // refine for final vtable type - llvm::cast(pa.get())->refineAbstractTypeTo(svtbl_ty); + // vtable + std::string varname("_D"); + varname.append(cd->mangle()); + varname.append("6__vtblZ"); + std::string styname(cd->mangle()); + styname.append("__vtblTy"); + + llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; + + const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); + cd->llvmVtbl = new llvm::GlobalVariable(svtbl_ty, true, _linkage, 0, varname, gIR->module); + + // init std::string initname("_D"); initname.append(cd->mangle()); initname.append("6__initZ"); - llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage; + llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); ts->llvmInit = initvar; gIR->classes.pop_back(); gIR->structs.pop_back(); - gIR->constInitQueue.push_back(cd); + gIR->constInitList.push_back(cd); if (needs_definition) - gIR->defineQueue.push_back(cd); + gIR->defineList.push_back(cd); } ////////////////////////////////////////////////////////////////////////////////////////// void DtoConstInitClass(ClassDeclaration* cd) { - IRStruct* irstruct = cd->llvmIRStruct; - if (irstruct->constinited) return; - irstruct->constinited = true; + if (cd->llvmInitialized) return; + cd->llvmInitialized = true; - Logger::println("DtoConstInitClass(%s)\n", cd->toPrettyChars()); + Logger::println("DtoConstInitClass(%s)", cd->toPrettyChars()); LOG_SCOPE; + IRStruct* irstruct = cd->llvmIRStruct; gIR->structs.push_back(irstruct); gIR->classes.push_back(cd); @@ -200,6 +226,7 @@ // rest for (IRStruct::OffsetMap::iterator i=irstruct->offsets.begin(); i!=irstruct->offsets.end(); ++i) { + Logger::println("adding fieldinit for: %s", i->second.var->toChars()); fieldinits.push_back(i->second.init); } @@ -210,24 +237,69 @@ // generate initializer Logger::cout() << cd->toPrettyChars() << " | " << *structtype << '\n'; - Logger::println("%u %u fields", structtype->getNumElements(), fieldinits.size()); + + for(size_t i=0; igetNumElements(); ++i) { + Logger::cout() << "s#" << i << " = " << *structtype->getElementType(i) << '\n'; + } + + for(size_t i=0; itoChars() << '\n'; + + if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { + DtoForceDeclareDsymbol(fd); + assert(fd->llvmValue); + llvm::Constant* c = llvm::cast(fd->llvmValue); + sinits.push_back(c); + } + else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { + const llvm::Type* cty = llvm::PointerType::get(llvm::Type::Int8Ty); + llvm::Constant* c = llvm::Constant::getNullValue(cty); + sinits.push_back(c); + } + else + assert(0); + } + + const llvm::StructType* svtbl_ty = isaStruct(ts->llvmVtblType->get()); + + /*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()); + }*/ + + llvm::Constant* cvtblInit = llvm::ConstantStruct::get(svtbl_ty, sinits); + cd->llvmConstVtbl = llvm::cast(cvtblInit); + gIR->classes.pop_back(); gIR->structs.pop_back(); + + DtoDeclareClassInfo(cd); } ////////////////////////////////////////////////////////////////////////////////////////// void DtoDefineClass(ClassDeclaration* cd) { - IRStruct* irstruct = cd->llvmIRStruct; - if (irstruct->defined) return; - irstruct->defined = true; + if (cd->llvmDefined) return; + cd->llvmDefined = true; - Logger::println("DtoDefineClass(%s)\n", cd->toPrettyChars()); + Logger::println("DtoDefineClass(%s)", cd->toPrettyChars()); LOG_SCOPE; // get the struct (class) type @@ -237,11 +309,11 @@ bool def = false; if (cd->parent->isModule() && cd->getModule() == gIR->dmodule) { ts->llvmInit->setInitializer(cd->llvmInitZ); + cd->llvmVtbl->setInitializer(cd->llvmConstVtbl); def = true; } // generate classinfo - DtoDeclareClassInfo(cd); if (def) DtoDefineClassInfo(cd); } @@ -302,21 +374,21 @@ void DtoDeclareClassInfo(ClassDeclaration* cd) { - if (cd->llvmClass) - return; + if (cd->llvmClassDeclared) return; + cd->llvmClassDeclared = true; - Logger::println("CLASS INFO DECLARATION: %s", cd->toChars()); + Logger::println("DtoDeclareClassInfo(%s)", cd->toChars()); LOG_SCOPE; ClassDeclaration* cinfo = ClassDeclaration::classinfo; - cinfo->toObjFile(); - - const llvm::Type* st = cinfo->type->llvmType->get(); + DtoResolveClass(cinfo); std::string gname("_D"); gname.append(cd->mangle()); gname.append("7__ClassZ"); + const llvm::Type* st = cinfo->type->llvmType->get(); + cd->llvmClass = new llvm::GlobalVariable(st, true, llvm::GlobalValue::ExternalLinkage, NULL, gname, gIR->module); } @@ -339,18 +411,26 @@ // void *defaultConstructor; // } - if (cd->llvmClassZ) - return; + if (cd->llvmClassDefined) return; + cd->llvmClassDefined = true; + + Logger::println("DtoDefineClassInfo(%s)", cd->toChars()); + LOG_SCOPE; - Logger::println("CLASS INFO DEFINITION: %s", cd->toChars()); - LOG_SCOPE; + assert(cd->type->ty == Tclass); assert(cd->llvmClass); + assert(cd->llvmInitZ); + assert(cd->llvmVtbl); + assert(cd->llvmConstVtbl); + + TypeClass* cdty = (TypeClass*)cd->type; + assert(cdty->llvmInit); // holds the list of initializers for llvm std::vector inits; ClassDeclaration* cinfo = ClassDeclaration::classinfo; - DtoConstInitClass(cinfo); + DtoForceConstInitDsymbol(cinfo); assert(cinfo->llvmInitZ); llvm::Constant* c; @@ -363,8 +443,12 @@ // monitor // TODO no monitors yet - // initializer - c = cinfo->llvmInitZ->getOperand(1); + // byte[] init + const llvm::Type* byteptrty = llvm::PointerType::get(llvm::Type::Int8Ty); + c = llvm::ConstantExpr::getBitCast(cdty->llvmInit, byteptrty); + assert(!cd->llvmInitZ->getType()->isAbstract()); + size_t initsz = gTargetData->getTypeSize(cd->llvmInitZ->getType()); + c = DtoConstSlice(DtoConstSize_t(initsz), c); inits.push_back(c); // class name @@ -380,38 +464,77 @@ inits.push_back(c); // vtbl array - c = cinfo->llvmInitZ->getOperand(3); + const llvm::Type* byteptrptrty = llvm::PointerType::get(byteptrty); + assert(!cd->llvmVtbl->getType()->isAbstract()); + c = llvm::ConstantExpr::getBitCast(cd->llvmVtbl, byteptrptrty); + assert(!cd->llvmConstVtbl->getType()->isAbstract()); + size_t vtblsz = gTargetData->getTypeSize(cd->llvmConstVtbl->getType()); + c = DtoConstSlice(DtoConstSize_t(vtblsz), c); inits.push_back(c); // interfaces array + // TODO c = cinfo->llvmInitZ->getOperand(4); inits.push_back(c); // base classinfo - c = cinfo->llvmInitZ->getOperand(5); - inits.push_back(c); + if (cd->baseClass) { + DtoDeclareClassInfo(cd->baseClass); + c = cd->baseClass->llvmClass; + assert(c); + inits.push_back(c); + } + else { + // null + c = cinfo->llvmInitZ->getOperand(5); + inits.push_back(c); + } // destructor + // TODO c = cinfo->llvmInitZ->getOperand(6); inits.push_back(c); // invariant + // TODO c = cinfo->llvmInitZ->getOperand(7); inits.push_back(c); - // flags - c = cinfo->llvmInitZ->getOperand(8); + // uint flags, adapted from original dmd code + uint flags = 0; + //flags |= 4; // has offTi + //flags |= isCOMclass(); // IUnknown + if (cd->ctor) flags |= 8; + for (ClassDeclaration *cd2 = cd; cd2; cd2 = cd2->baseClass) + { + if (cd2->members) + { + for (size_t i = 0; i < cd2->members->dim; i++) + { + Dsymbol *sm = (Dsymbol *)cd2->members->data[i]; + //printf("sm = %s %s\n", sm->kind(), sm->toChars()); + if (sm->hasPointers()) + goto L2; + } + } + } + flags |= 2; // no pointers +L2: + c = DtoConstUint(flags); inits.push_back(c); // allocator + // TODO c = cinfo->llvmInitZ->getOperand(9); inits.push_back(c); // offset typeinfo + // TODO c = cinfo->llvmInitZ->getOperand(10); inits.push_back(c); // default constructor + // TODO c = cinfo->llvmInitZ->getOperand(11); inits.push_back(c); diff -r 169fda3a77d4 -r 027b8d8b71ec gen/classes.h --- a/gen/classes.h Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/classes.h Sun Nov 18 06:52:57 2007 +0100 @@ -2,6 +2,11 @@ #define LLVMDC_GEN_CLASSES_H /** + * Resolves the llvm type for a class declaration + */ +void DtoResolveClass(ClassDeclaration* cd); + +/** * Provides the llvm declaration for a class declaration */ void DtoDeclareClass(ClassDeclaration* cd); diff -r 169fda3a77d4 -r 027b8d8b71ec gen/functions.cpp --- a/gen/functions.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/functions.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -71,7 +71,7 @@ if (typesafeVararg) { ClassDeclaration* ti = Type::typeinfo; ti->toObjFile(); - DtoConstInitClass(ti); + DtoForceConstInitDsymbol(ti); assert(ti->llvmInitZ); std::vector types; types.push_back(DtoSize_t()); @@ -131,10 +131,10 @@ f->llvmRetInPtr = retinptr; f->llvmUsesThis = usesthis; - if (!f->llvmType) + //if (!f->llvmType) f->llvmType = new llvm::PATypeHolder(functype); - else - assert(functype == f->llvmType->get()); + //else + //assert(functype == f->llvmType->get()); return functype; } @@ -143,6 +143,11 @@ static const llvm::FunctionType* DtoVaFunctionType(FuncDeclaration* fdecl) { + // type has already been resolved + if (fdecl->type->llvmType != 0) { + return llvm::cast(fdecl->type->llvmType->get()); + } + TypeFunction* f = (TypeFunction*)fdecl->type; assert(f != 0); @@ -163,10 +168,7 @@ const llvm::FunctionType* fty = llvm::FunctionType::get(llvm::Type::VoidTy, args, false); - if (!f->llvmType) - f->llvmType = new llvm::PATypeHolder(fty); - else - assert(fty == f->llvmType->get()); + f->llvmType = new llvm::PATypeHolder(fty); return fty; } @@ -190,7 +192,7 @@ Logger::print("isMember = this is: %s\n", ad->type->toChars()); thisty = DtoType(ad->type); Logger::cout() << "this llvm type: " << *thisty << '\n'; - if (isaStruct(thisty) || thisty == gIR->topstruct()->recty.get()) + if (isaStruct(thisty) || (!gIR->structs.empty() && thisty == gIR->topstruct()->recty.get())) thisty = llvm::PointerType::get(thisty); } else @@ -233,8 +235,57 @@ ////////////////////////////////////////////////////////////////////////////////////////// +void DtoResolveFunction(FuncDeclaration* fdecl) +{ + if (fdecl->llvmResolved) return; + fdecl->llvmResolved = true; + + Logger::println("DtoResolveFunction(%s)", fdecl->toPrettyChars()); + LOG_SCOPE; + + if (fdecl->llvmRunTimeHack) { + gIR->declareList.push_back(fdecl); + return; + } + + if (fdecl->isUnitTestDeclaration()) { + Logger::attention("ignoring unittest declaration: %s", fdecl->toChars()); + return; + } + + if (fdecl->parent) + if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance()) + { + TemplateDeclaration* tempdecl = tinst->tempdecl; + if (tempdecl->llvmInternal == LLVMva_arg) + { + Logger::println("magic va_arg found"); + fdecl->llvmInternal = LLVMva_arg; + fdecl->llvmDeclared = true; + fdecl->llvmInitialized = true; + fdecl->llvmDefined = true; + return; // this gets mapped to an instruction so a declaration makes no sence + } + else if (tempdecl->llvmInternal == LLVMva_start) + { + Logger::println("magic va_start found"); + fdecl->llvmInternal = LLVMva_start; + } + } + + DtoFunctionType(fdecl); + + // queue declaration + gIR->declareList.push_back(fdecl); +} + +////////////////////////////////////////////////////////////////////////////////////////// + void DtoDeclareFunction(FuncDeclaration* fdecl) { + if (fdecl->llvmDeclared) return; + fdecl->llvmDeclared = true; + Logger::println("DtoDeclareFunction(%s)", fdecl->toPrettyChars()); LOG_SCOPE; @@ -245,34 +296,12 @@ return; } - if (fdecl->isUnitTestDeclaration()) { - Logger::attention("ignoring unittest declaration: %s", fdecl->toChars()); - return; - } - bool declareOnly = false; - if (fdecl->parent) - { - if (TemplateInstance* tinst = fdecl->parent->isTemplateInstance()) - { - TemplateDeclaration* tempdecl = tinst->tempdecl; - if (tempdecl->llvmInternal == LLVMva_start) - { - Logger::println("magic va_start found"); - fdecl->llvmInternal = LLVMva_start; - declareOnly = true; - } - else if (tempdecl->llvmInternal == LLVMva_arg) - { - Logger::println("magic va_arg found"); - fdecl->llvmInternal = LLVMva_arg; - return; - } - } - } - - if (fdecl->llvmTouched) return; - fdecl->llvmTouched = true; + bool templInst = fdecl->parent && DtoIsTemplateInstance(fdecl->parent); + if (!templInst && fdecl->getModule() != gIR->dmodule) + declareOnly = true; + else if (fdecl->llvmInternal == LLVMva_start) + declareOnly = true; if (!fdecl->llvmIRFunc) { fdecl->llvmIRFunc = new IRFunction(fdecl); @@ -384,7 +413,7 @@ } if (!declareOnly) - gIR->defineQueue.push_back(fdecl); + gIR->defineList.push_back(fdecl); Logger::cout() << "func decl: " << *func << '\n'; } @@ -394,6 +423,12 @@ // TODO split this monster up void DtoDefineFunc(FuncDeclaration* fd) { + if (fd->llvmDefined) return; + fd->llvmDefined = true; + + Logger::println("DtoDefineFunc(%s)", fd->toPrettyChars()); + LOG_SCOPE; + // debug info if (global.params.symdebug) { Module* mo = fd->getModule(); diff -r 169fda3a77d4 -r 027b8d8b71ec gen/functions.h --- a/gen/functions.h Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/functions.h Sun Nov 18 06:52:57 2007 +0100 @@ -4,6 +4,7 @@ const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false); const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl); +void DtoResolveFunction(FuncDeclaration* fdecl); void DtoDeclareFunction(FuncDeclaration* fdecl); void DtoDefineFunc(FuncDeclaration* fd); diff -r 169fda3a77d4 -r 027b8d8b71ec gen/irstate.h --- a/gen/irstate.h Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/irstate.h Sun Nov 18 06:52:57 2007 +0100 @@ -5,6 +5,7 @@ #include #include #include +#include #include "root.h" @@ -176,11 +177,15 @@ // builder helper IRBuilderHelper ir; - typedef std::vector DsymbolVector; + typedef std::list DsymbolList; + // dsymbols that need to be resolved + DsymbolList resolveList; + // dsymbols that need to be declared + DsymbolList declareList; // dsymbols that need constant initializers constructed - DsymbolVector constInitQueue; - // dsymbols that need definitions (symbols in current module) - DsymbolVector defineQueue; + DsymbolList constInitList; + // dsymbols that need definitions + DsymbolList defineList; }; #endif // LLVMDC_GEN_IRSTATE_H diff -r 169fda3a77d4 -r 027b8d8b71ec gen/logger.cpp --- a/gen/logger.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/logger.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -16,8 +16,9 @@ static bool enabled = false; void indent() { - if (enabled) - indent_str += " "; + if (enabled) { + indent_str += "* "; + } } void undent() { diff -r 169fda3a77d4 -r 027b8d8b71ec gen/structs.cpp --- a/gen/structs.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/structs.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -96,6 +96,7 @@ inits.push_back(DUnionIdx(vd->llvmFieldIndex, vd->llvmFieldIndexOffset, v)); } + DtoConstInitStruct((StructDeclaration*)si->ad); return si->ad->llvmUnion->getConst(inits); } @@ -165,12 +166,12 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoDeclareStruct(StructDeclaration* sd) +void DtoResolveStruct(StructDeclaration* sd) { - if (sd->llvmTouched) return; - sd->llvmTouched = true; + if (sd->llvmResolved) return; + sd->llvmResolved = true; - Logger::println("DtoDeclareStruct(%s)", sd->toChars()); + Logger::println("DtoResolveStruct(%s)", sd->toChars()); LOG_SCOPE; TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); @@ -280,6 +281,23 @@ gIR->module->addTypeName(sd->mangle(),structtype); } + gIR->structs.pop_back(); + + gIR->declareList.push_back(sd); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDeclareStruct(StructDeclaration* sd) +{ + if (sd->llvmDeclared) return; + sd->llvmDeclared = true; + + Logger::println("DtoDeclareStruct(%s)", sd->toChars()); + LOG_SCOPE; + + TypeStruct* ts = (TypeStruct*)DtoDType(sd->type); + std::string initname("_D"); initname.append(sd->mangle()); initname.append("6__initZ"); @@ -288,28 +306,22 @@ llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType->get(), true, _linkage, NULL, initname, gIR->module); ts->llvmInit = initvar; - gIR->structs.pop_back(); - - gIR->constInitQueue.push_back(sd); + gIR->constInitList.push_back(sd); if (sd->getModule() == gIR->dmodule) - gIR->defineQueue.push_back(sd); - - // declare typeinfo - if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo) - sd->type->getTypeInfo(NULL); + gIR->defineList.push_back(sd); } ////////////////////////////////////////////////////////////////////////////////////////// void DtoConstInitStruct(StructDeclaration* sd) { - IRStruct* irstruct = sd->llvmIRStruct; - if (irstruct->constinited) return; - irstruct->constinited = true; + if (sd->llvmInitialized) return; + sd->llvmInitialized = true; Logger::println("DtoConstInitStruct(%s)", sd->toChars()); LOG_SCOPE; + IRStruct* irstruct = sd->llvmIRStruct; gIR->structs.push_back(irstruct); // make sure each offset knows its default initializer @@ -365,17 +377,18 @@ } gIR->structs.pop_back(); + + // emit typeinfo + if (sd->getModule() == gIR->dmodule && sd->llvmInternal != LLVMnotypeinfo) + sd->type->getTypeInfo(NULL); } ////////////////////////////////////////////////////////////////////////////////////////// void DtoDefineStruct(StructDeclaration* sd) { - IRStruct* irstruct = sd->llvmIRStruct; - if (irstruct->defined) return; - irstruct->defined = true; - - DtoConstInitStruct(sd); + if (sd->llvmDefined) return; + sd->llvmDefined = true; Logger::println("DtoDefineStruct(%s)", sd->toChars()); LOG_SCOPE; diff -r 169fda3a77d4 -r 027b8d8b71ec gen/structs.h --- a/gen/structs.h Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/structs.h Sun Nov 18 06:52:57 2007 +0100 @@ -11,6 +11,11 @@ llvm::Constant* DtoConstStructInitializer(StructInitializer* si); /** + * Resolves the llvm type for a struct + */ +void DtoResolveStruct(StructDeclaration* sd); + +/** * Provides the llvm declaration for a struct */ void DtoDeclareStruct(StructDeclaration* sd); diff -r 169fda3a77d4 -r 027b8d8b71ec gen/toir.cpp --- a/gen/toir.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/toir.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -27,6 +27,7 @@ #include "gen/arrays.h" #include "gen/structs.h" #include "gen/classes.h" +#include "gen/typeinf.h" #include "gen/dvalue.h" @@ -45,7 +46,7 @@ // static if (vd->isDataseg()) { - vd->toObjFile(); + vd->toObjFile(); // TODO } else { @@ -75,13 +76,13 @@ else if (StructDeclaration* s = declaration->isStructDeclaration()) { Logger::println("StructDeclaration"); - s->toObjFile(); + DtoForceConstInitDsymbol(s); } // function declaration else if (FuncDeclaration* f = declaration->isFuncDeclaration()) { Logger::println("FuncDeclaration"); - f->toObjFile(); + DtoForceDeclareDsymbol(f); } // alias declaration else if (AliasDeclaration* a = declaration->isAliasDeclaration()) @@ -145,7 +146,7 @@ else if (TypeInfoDeclaration* tid = vd->isTypeInfoDeclaration()) { Logger::println("TypeInfoDeclaration"); - tid->toObjFile(); + DtoForceDeclareDsymbol(tid); assert(tid->llvmValue); const llvm::Type* vartype = DtoType(type); llvm::Value* m; @@ -159,6 +160,7 @@ else if (ClassInfoDeclaration* cid = vd->isClassInfoDeclaration()) { Logger::println("ClassInfoDeclaration: %s", cid->cd->toChars()); + DtoDeclareClassInfo(cid->cd); assert(cid->cd->llvmClass); return new DVarValue(vd, cid->cd->llvmClass, true); } @@ -199,8 +201,9 @@ else if (FuncDeclaration* fdecl = var->isFuncDeclaration()) { Logger::println("FuncDeclaration"); - if (fdecl->llvmInternal != LLVMva_arg)// && fdecl->llvmValue == 0) - fdecl->toObjFile(); + if (fdecl->llvmInternal != LLVMva_arg) {// && fdecl->llvmValue == 0) + DtoForceDeclareDsymbol(fdecl); + } return new DFuncValue(fdecl, fdecl->llvmValue); } else if (SymbolDeclaration* sdecl = var->isSymbolDeclaration()) @@ -234,8 +237,7 @@ Logger::print("Sym: type=%s\n", sdecltype->toChars()); assert(sdecltype->ty == Tstruct); TypeStruct* ts = (TypeStruct*)sdecltype; - ts->sym->toObjFile(); - DtoConstInitStruct(ts->sym); + DtoForceConstInitDsymbol(ts->sym); assert(ts->sym->llvmInitZ); return ts->sym->llvmInitZ; } @@ -1063,7 +1065,7 @@ bool delegateCall = false; llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty,0,false); llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty,1,false); - LINK dlink = LINKdefault; + LINK dlink = LINKd; // hidden struct return parameter handling bool retinptr = false; @@ -1117,7 +1119,7 @@ llt = llvm::PointerType::get(llt); // TODO if (strcmp(global.params.llvmArch, "x86") != 0) { - warning("va_arg for C variadic functions is broken for anything but x86"); + warning("%s: va_arg for C variadic functions is broken for anything but x86", loc.toChars()); } return new DImValue(type, p->ir->CreateVAArg(expelem->getLVal(),llt,"tmp")); } @@ -1267,7 +1269,7 @@ vtypes.push_back(vvalues.back()->getType()); TypeInfoDeclaration* tidecl = argexp->type->getTypeInfoDeclaration(); - tidecl->toObjFile(); + DtoForceDeclareDsymbol(tidecl); assert(tidecl->llvmValue); vtypeinfos.push_back(tidecl->llvmValue); } @@ -1306,8 +1308,10 @@ llargs[j] = DtoArgument(llfnty->getParamType(j), fnarg, (Expression*)arguments->data[i]); // this hack is necessary :/ if (dfn && dfn->func && dfn->func->llvmRunTimeHack) { - if (llargs[j]->getType() != llfnty->getParamType(j)) + Logger::println("llvmRunTimeHack==true"); + if (llargs[j]->getType() != llfnty->getParamType(j)) { llargs[j] = DtoBitCast(llargs[j], llfnty->getParamType(j)); + } } } Logger::println("%d params passed", n); @@ -1336,13 +1340,13 @@ call->setCallingConv(DtoCallingConv(dlink)); } } - else if (delegateCall) { + /*else if (delegateCall) { call->setCallingConv(DtoCallingConv(dlink)); - } + }*/ else if (dfn && dfn->cc != (unsigned)-1) { call->setCallingConv(dfn->cc); } - else if (llvm::isa(funcval)) { + else { call->setCallingConv(DtoCallingConv(dlink)); } @@ -1385,8 +1389,11 @@ if (VarDeclaration* vd = var->isVarDeclaration()) { Logger::println("VarDeclaration"); - if (!vd->llvmTouched && vd->isDataseg()) - vd->toObjFile(); + + // handle forward reference + if (!vd->llvmDeclared && vd->isDataseg()) { + vd->toObjFile(); // TODO + } assert(vd->llvmValue); Type* t = DtoDType(type); @@ -1465,7 +1472,7 @@ FuncDeclaration* fd = fv->func; assert(fd); if (fd->llvmValue == 0) - fd->toObjFile(); + DtoForceDeclareDsymbol(fd); return new DFuncValue(fd, fd->llvmValue); } else if (DImValue* im = v->isIm()) { @@ -1539,7 +1546,7 @@ { if (fdecl->llvmValue == 0) { - fdecl->toObjFile(); + DtoForceDeclareDsymbol(fdecl); } llvm::Value* funcval = fdecl->llvmValue; @@ -2099,7 +2106,7 @@ llvm::Value* ptr = DtoGEP(val,zero,one,"tmp",p->scopebb()); ptr = new llvm::LoadInst(ptr,"tmp",p->scopebb()); new llvm::FreeInst(ptr, p->scopebb()); - DtoNullArray(val); + DtoSetArrayToNull(val); } else { assert(0); @@ -2507,7 +2514,7 @@ if (fd->isNested()) Logger::println("nested"); Logger::println("kind = %s\n", fd->kind()); - fd->toObjFile(); + DtoForceDeclareDsymbol(fd); bool temp = false; llvm::Value* lval = NULL; diff -r 169fda3a77d4 -r 027b8d8b71ec gen/tollvm.cpp --- a/gen/tollvm.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/tollvm.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -17,6 +17,7 @@ #include "gen/functions.h" #include "gen/structs.h" #include "gen/classes.h" +#include "gen/typeinf.h" bool DtoIsPassedByRef(Type* type) { @@ -114,7 +115,7 @@ // forward declaration TypeStruct* ts = (TypeStruct*)t; assert(ts->sym); - ts->sym->toObjFile(); + DtoResolveDsymbol(ts->sym); } return t->llvmType->get(); } @@ -137,7 +138,7 @@ // forward declaration TypeClass* tc = (TypeClass*)t; assert(tc->sym); - tc->sym->toObjFile(); + DtoResolveDsymbol(tc->sym); } return llvm::PointerType::get(t->llvmType->get()); } @@ -654,7 +655,17 @@ llargs.resize(3); llargs[0] = cond ? DtoBoolean(cond) : llvm::ConstantInt::getFalse(); llargs[1] = DtoConstUint(loc->linnum); - llargs[2] = msg ? msg->getRVal() : llvm::Constant::getNullValue(fnt->getParamType(2)); + 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; + } assert(fn); llvm::CallInst* call = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb()); @@ -861,7 +872,7 @@ } // null else if (rhs->isNull()) { - DtoNullArray(lhs->getLVal()); + DtoSetArrayToNull(lhs->getLVal()); } // reference assignment else { @@ -1030,87 +1041,6 @@ return new DImValue(_to, rval); } -DValue* DtoCastArray(DValue* u, Type* to) -{ - const llvm::Type* tolltype = DtoType(to); - - Type* totype = DtoDType(to); - Type* fromtype = DtoDType(u->getType()); - assert(fromtype->ty == Tarray || fromtype->ty == Tsarray); - - llvm::Value* rval; - llvm::Value* rval2; - bool isslice = false; - - Logger::cout() << "from array or sarray" << '\n'; - if (totype->ty == Tpointer) { - Logger::cout() << "to pointer" << '\n'; - assert(fromtype->next == totype->next || totype->next->ty == Tvoid); - 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"); - } - 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); - - const llvm::Type* ety = DtoType(fromtype->next); - if (ety == llvm::Type::VoidTy) - ety = llvm::Type::Int8Ty; - - if (DSliceValue* usl = u->isSlice()) { - Logger::println("from slice"); - rval = new llvm::BitCastInst(usl->ptr, ptrty, "tmp", gIR->scopebb()); - if (fromtype->next->size() == totype->next->size()) - rval2 = usl->len; - else - rval2 = DtoArrayCastLength(usl->len, ety, ptrty->getContainedType(0)); - } - else { - llvm::Value* uval = u->getRVal(); - if (fromtype->ty == Tsarray) { - Logger::cout() << "uvalTy = " << *uval->getType() << '\n'; - assert(isaPointer(uval->getType())); - const llvm::ArrayType* arrty = isaArray(uval->getType()->getContainedType(0)); - rval2 = llvm::ConstantInt::get(DtoSize_t(), arrty->getNumElements(), false); - rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); - rval = new llvm::BitCastInst(uval, ptrty, "tmp", gIR->scopebb()); - } - else { - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - llvm::Value* one = llvm::ConstantInt::get(llvm::Type::Int32Ty, 1, false); - rval2 = DtoGEP(uval,zero,zero,"tmp",gIR->scopebb()); - rval2 = new llvm::LoadInst(rval2, "tmp", gIR->scopebb()); - rval2 = DtoArrayCastLength(rval2, ety, ptrty->getContainedType(0)); - - rval = DtoGEP(uval,zero,one,"tmp",gIR->scopebb()); - rval = new llvm::LoadInst(rval, "tmp", gIR->scopebb()); - //Logger::cout() << *e->mem->getType() << '|' << *ptrty << '\n'; - rval = new llvm::BitCastInst(rval, ptrty, "tmp", gIR->scopebb()); - } - } - isslice = true; - } - else if (totype->ty == Tsarray) { - Logger::cout() << "to sarray" << '\n'; - assert(0); - } - else { - assert(0); - } - - if (isslice) { - Logger::println("isslice"); - return new DSliceValue(to, rval2, rval); - } - - return new DImValue(to, rval); -} - DValue* DtoCast(DValue* val, Type* to) { Type* fromtype = DtoDType(val->getType()); @@ -1180,6 +1110,15 @@ ////////////////////////////////////////////////////////////////////////////////////////// +llvm::Constant* DtoConstNullPtr(const llvm::Type* t) +{ + return llvm::ConstantPointerNull::get( + llvm::PointerType::get(t) + ); +} + +////////////////////////////////////////////////////////////////////////////////////////// + void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes) { assert(dst->getType() == src->getType()); @@ -1321,20 +1260,45 @@ ////////////////////////////////////////////////////////////////////////////////////////// -void DtoDefineDsymbol(Dsymbol* dsym) +void DtoResolveDsymbol(Dsymbol* dsym) { if (StructDeclaration* sd = dsym->isStructDeclaration()) { - DtoDefineStruct(sd); + DtoResolveStruct(sd); } else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { - DtoDefineClass(cd); + DtoResolveClass(cd); } else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { - DtoDefineFunc(fd); + DtoResolveFunction(fd); + } + else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) { + DtoResolveTypeInfo(fd); } else { error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars()); - assert(0 && "unsupported dsymbol for DtoDefineDsymbol"); + assert(0 && "unsupported dsymbol for DtoResolveDsymbol"); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDeclareDsymbol(Dsymbol* dsym) +{ + if (StructDeclaration* sd = dsym->isStructDeclaration()) { + DtoDeclareStruct(sd); + } + else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { + DtoDeclareClass(cd); + } + else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { + DtoDeclareFunction(fd); + } + else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) { + DtoDeclareTypeInfo(fd); + } + else { + error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars()); + assert(0 && "unsupported dsymbol for DtoDeclareDsymbol"); } } @@ -1348,12 +1312,37 @@ else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { DtoConstInitClass(cd); } + else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) { + DtoConstInitTypeInfo(fd); + } else if (VarDeclaration* vd = dsym->isVarDeclaration()) { DtoConstInitGlobal(vd); } else { error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars()); - assert(0 && "unsupported dsymbol for DtoInitDsymbol"); + assert(0 && "unsupported dsymbol for DtoConstInitDsymbol"); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDefineDsymbol(Dsymbol* dsym) +{ + if (StructDeclaration* sd = dsym->isStructDeclaration()) { + DtoDefineStruct(sd); + } + else if (ClassDeclaration* cd = dsym->isClassDeclaration()) { + DtoDefineClass(cd); + } + else if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { + DtoDefineFunc(fd); + } + else if (TypeInfoDeclaration* fd = dsym->isTypeInfoDeclaration()) { + DtoDefineTypeInfo(fd); + } + else { + error(dsym->loc, "unsupported dsymbol: %s", dsym->toChars()); + assert(0 && "unsupported dsymbol for DtoDefineDsymbol"); } } @@ -1361,11 +1350,11 @@ void DtoConstInitGlobal(VarDeclaration* vd) { - Logger::println("DtoConstInitGlobal(%s)", vd->toChars()); - LOG_SCOPE; + if (vd->llvmInitialized) return; + vd->llvmInitialized = gIR->dmodule; - if (vd->llvmDModule) return; - vd->llvmDModule = gIR->dmodule; + Logger::println("* DtoConstInitGlobal(%s)", vd->toChars()); + LOG_SCOPE; bool emitRTstaticInit = false; @@ -1428,3 +1417,100 @@ if (emitRTstaticInit) DtoLazyStaticInit(istempl, gvar, vd->init, t); } + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoEmptyResolveList() +{ + //Logger::println("DtoEmptyResolveList()"); + Dsymbol* dsym; + while (!gIR->resolveList.empty()) { + dsym = gIR->resolveList.front(); + gIR->resolveList.pop_front(); + DtoResolveDsymbol(dsym); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoEmptyDeclareList() +{ + //Logger::println("DtoEmptyDeclareList()"); + Dsymbol* dsym; + while (!gIR->declareList.empty()) { + dsym = gIR->declareList.front(); + gIR->declareList.pop_front(); + DtoDeclareDsymbol(dsym); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoEmptyConstInitList() +{ + //Logger::println("DtoEmptyConstInitList()"); + Dsymbol* dsym; + while (!gIR->constInitList.empty()) { + dsym = gIR->constInitList.front(); + gIR->constInitList.pop_front(); + DtoConstInitDsymbol(dsym); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoEmptyDefineList() +{ + //Logger::println("DtoEmptyDefineList()"); + Dsymbol* dsym; + while (!gIR->defineList.empty()) { + dsym = gIR->defineList.front(); + gIR->defineList.pop_front(); + DtoDefineDsymbol(dsym); + } +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoForceDeclareDsymbol(Dsymbol* dsym) +{ + if (dsym->llvmDeclared) return; + Logger::println("DtoForceDeclareDsymbol(%s)", dsym->toChars()); + LOG_SCOPE; + DtoResolveDsymbol(dsym); + + DtoEmptyResolveList(); + + DtoDeclareDsymbol(dsym); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoForceConstInitDsymbol(Dsymbol* dsym) +{ + if (dsym->llvmInitialized) return; + Logger::println("DtoForceConstInitDsymbol(%s)", dsym->toChars()); + LOG_SCOPE; + DtoResolveDsymbol(dsym); + + DtoEmptyResolveList(); + DtoEmptyDeclareList(); + + DtoConstInitDsymbol(dsym); +} + +////////////////////////////////////////////////////////////////////////////////////////// + +void DtoForceDefineDsymbol(Dsymbol* dsym) +{ + if (dsym->llvmDefined) return; + Logger::println("DtoForceDefineDsymbol(%s)", dsym->toChars()); + LOG_SCOPE; + DtoResolveDsymbol(dsym); + + DtoEmptyResolveList(); + DtoEmptyDeclareList(); + DtoEmptyConstInitList(); + + DtoDefineDsymbol(dsym); +} diff -r 169fda3a77d4 -r 027b8d8b71ec gen/tollvm.h --- a/gen/tollvm.h Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/tollvm.h Sun Nov 18 06:52:57 2007 +0100 @@ -53,15 +53,26 @@ llvm::Constant* DtoConstString(const char*); llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0); llvm::Constant* DtoConstBool(bool); +llvm::Constant* DtoConstNullPtr(const llvm::Type* t); bool DtoIsTemplateInstance(Dsymbol* s); void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t); +void DtoResolveDsymbol(Dsymbol* dsym); +void DtoDeclareDsymbol(Dsymbol* dsym); void DtoDefineDsymbol(Dsymbol* dsym); void DtoConstInitDsymbol(Dsymbol* dsym); + void DtoConstInitGlobal(VarDeclaration* vd); +void DtoEmptyResolveList(); +void DtoEmptyDeclareList(); +void DtoEmptyConstInitList(); +void DtoForceDeclareDsymbol(Dsymbol* dsym); +void DtoForceConstInitDsymbol(Dsymbol* dsym); +void DtoForceDefineDsymbol(Dsymbol* dsym); + // llvm wrappers void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes); bool DtoCanLoad(llvm::Value* ptr); @@ -87,7 +98,6 @@ DValue* DtoCastInt(DValue* val, Type* to); DValue* DtoCastPtr(DValue* val, Type* to); DValue* DtoCastFloat(DValue* val, Type* to); -DValue* DtoCastArray(DValue* val, Type* to); DValue* DtoCastClass(DValue* val, Type* to); DValue* DtoCast(DValue* val, Type* to); diff -r 169fda3a77d4 -r 027b8d8b71ec gen/toobj.cpp --- a/gen/toobj.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/toobj.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -92,14 +92,33 @@ dsym->toObjFile(); } - // process deferred const initializers - for (size_t i=0; iresolveList.push_back(this); } /* ================================================================== */ @@ -364,7 +383,7 @@ void ClassDeclaration::toObjFile() { - DtoDeclareClass(this); + gIR->resolveList.push_back(this); } /****************************************** @@ -394,8 +413,9 @@ // global variable or magic if (isDataseg()) { - if (llvmTouched) return; - else llvmTouched = true; + if (llvmResolved) return; + llvmResolved = true; + llvmDeclared = true; llvmIRGlobal = new IRGlobal(this); @@ -430,7 +450,7 @@ if (static_local) DtoConstInitGlobal(this); else - gIR->constInitQueue.push_back(this); + gIR->constInitList.push_back(this); //if (storage_class & STCprivate) // gvar->setVisibility(llvm::GlobalValue::ProtectedVisibility); @@ -473,5 +493,5 @@ void FuncDeclaration::toObjFile() { - DtoDeclareFunction(this); + gIR->resolveList.push_back(this); } diff -r 169fda3a77d4 -r 027b8d8b71ec gen/typeinf.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gen/typeinf.h Sun Nov 18 06:52:57 2007 +0100 @@ -0,0 +1,9 @@ +#ifndef LLVMDC_GEN_TYPEINF_H +#define LLVMDC_GEN_TYPEINF_H + +void DtoResolveTypeInfo(TypeInfoDeclaration* tid); +void DtoDeclareTypeInfo(TypeInfoDeclaration* tid); +void DtoConstInitTypeInfo(TypeInfoDeclaration* tid); +void DtoDefineTypeInfo(TypeInfoDeclaration* tid); + +#endif diff -r 169fda3a77d4 -r 027b8d8b71ec gen/typinf.cpp --- a/gen/typinf.cpp Fri Nov 16 10:01:24 2007 +0100 +++ b/gen/typinf.cpp Sun Nov 18 06:52:57 2007 +0100 @@ -8,6 +8,10 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +// Modifications for LLVMDC: +// Copyright (c) 2007 by Tomas Lindquist Olsen +// tomas at famolsen dk + #include #include @@ -238,32 +242,76 @@ void TypeInfoDeclaration::toObjFile() { - if (llvmTouched) return; - else llvmTouched = true; + gIR->resolveList.push_back(this); +} - Logger::println("TypeInfoDeclaration::toObjFile()"); +void DtoResolveTypeInfo(TypeInfoDeclaration* tid) +{ + if (tid->llvmResolved) return; + tid->llvmResolved = true; + + Logger::println("* DtoResolveTypeInfo(%s)", tid->toChars()); LOG_SCOPE; - std::string mangled(mangle()); + tid->llvmIRGlobal = new IRGlobal(tid); + + gIR->declareList.push_back(tid); +} - Logger::println("type = '%s'", tinfo->toChars()); +void DtoDeclareTypeInfo(TypeInfoDeclaration* tid) +{ + if (tid->llvmDeclared) return; + tid->llvmDeclared = true; + + Logger::println("* DtoDeclareTypeInfo(%s)", tid->toChars()); + LOG_SCOPE; + + std::string mangled(tid->mangle()); + + Logger::println("type = '%s'", tid->tinfo->toChars()); Logger::println("typeinfo mangle: %s", mangled.c_str()); // this is a declaration of a builtin __initZ var - if (tinfo->builtinTypeInfo()) { - llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str()); - assert(llvmValue); + if (tid->tinfo->builtinTypeInfo()) { + tid->llvmValue = LLVM_D_GetRuntimeGlobal(gIR->module, mangled.c_str()); + assert(tid->llvmValue); mangled.append("__TYPE"); - gIR->module->addTypeName(mangled, llvmValue->getType()->getContainedType(0)); - Logger::println("Got typeinfo var: %s", llvmValue->getName().c_str()); + gIR->module->addTypeName(mangled, tid->llvmValue->getType()->getContainedType(0)); + Logger::println("Got typeinfo var: %s", tid->llvmValue->getName().c_str()); + tid->llvmInitialized = true; + tid->llvmDefined = true; } // custom typedef else { - // emit globals - toDt(NULL); + gIR->constInitList.push_back(tid); } } +void DtoConstInitTypeInfo(TypeInfoDeclaration* tid) +{ + if (tid->llvmInitialized) return; + tid->llvmInitialized = true; + + Logger::println("* DtoConstInitTypeInfo(%s)", tid->toChars()); + LOG_SCOPE; + + tid->toDt(NULL); + + tid->llvmDefined = true; + //gIR->defineList.push_back(tid); +} + +void DtoDefineTypeInfo(TypeInfoDeclaration* tid) +{ + if (tid->llvmDefined) return; + tid->llvmDefined = true; + + Logger::println("* DtoDefineTypeInfo(%s)", tid->toChars()); + LOG_SCOPE; + + assert(0); +} + /* ========================================================================= */ void TypeInfoDeclaration::toDt(dt_t **pdt) @@ -279,9 +327,10 @@ LOG_SCOPE; ClassDeclaration* base = Type::typeinfotypedef; - base->toObjFile(); + DtoForceConstInitDsymbol(base); const llvm::StructType* stype = isaStruct(base->type->llvmType->get()); + Logger::cout() << "got stype: " << *stype << '\n'; std::vector sinits; sinits.push_back(base->llvmVtbl); @@ -295,10 +344,13 @@ //sinits.push_back(llvm::ConstantPointerNull::get(basept)); Logger::println("generating base typeinfo"); //sd->basetype = sd->basetype->merge(); + sd->basetype->getTypeInfo(NULL); // generate vtinfo assert(sd->basetype->vtinfo); if (!sd->basetype->vtinfo->llvmValue) - sd->basetype->vtinfo->toObjFile(); + DtoForceConstInitDsymbol(sd->basetype->vtinfo); + + assert(sd->basetype->vtinfo->llvmValue); assert(llvm::isa(sd->basetype->vtinfo->llvmValue)); llvm::Constant* castbase = llvm::cast(sd->basetype->vtinfo->llvmValue); castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1)); @@ -341,7 +393,7 @@ LOG_SCOPE; ClassDeclaration* base = Type::typeinfoenum; - base->toObjFile(); + DtoForceConstInitDsymbol(base); const llvm::StructType* stype = isaStruct(base->type->llvmType->get()); @@ -357,10 +409,12 @@ //sinits.push_back(llvm::ConstantPointerNull::get(basept)); Logger::println("generating base typeinfo"); //sd->basetype = sd->basetype->merge(); + sd->memtype->getTypeInfo(NULL); // generate vtinfo assert(sd->memtype->vtinfo); if (!sd->memtype->vtinfo->llvmValue) - sd->memtype->vtinfo->toObjFile(); + DtoForceConstInitDsymbol(sd->memtype->vtinfo); + assert(llvm::isa(sd->memtype->vtinfo->llvmValue)); llvm::Constant* castbase = llvm::cast(sd->memtype->vtinfo->llvmValue); castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1)); @@ -401,7 +455,7 @@ static llvm::Constant* LLVM_D_Create_TypeInfoBase(Type* basetype, TypeInfoDeclaration* tid, ClassDeclaration* cd) { ClassDeclaration* base = cd; - base->toObjFile(); + DtoForceConstInitDsymbol(base); const llvm::StructType* stype = isaStruct(base->type->llvmType->get()); @@ -413,7 +467,7 @@ basetype->getTypeInfo(NULL); assert(basetype->vtinfo); if (!basetype->vtinfo->llvmValue) - basetype->vtinfo->toObjFile(); + DtoForceConstInitDsymbol(basetype->vtinfo); assert(llvm::isa(basetype->vtinfo->llvmValue)); llvm::Constant* castbase = llvm::cast(basetype->vtinfo->llvmValue); castbase = llvm::ConstantExpr::getBitCast(castbase, stype->getElementType(1)); @@ -533,11 +587,10 @@ assert(tinfo->ty == Tstruct); TypeStruct *tc = (TypeStruct *)tinfo; StructDeclaration *sd = tc->sym; - sd->toObjFile(); - DtoConstInitStruct(sd); + DtoForceConstInitDsymbol(sd); ClassDeclaration* base = Type::typeinfostruct; - base->toObjFile(); + DtoForceConstInitDsymbol(base); const llvm::StructType* stype = isaStruct(((TypeClass*)base->type)->llvmType->get()); diff -r 169fda3a77d4 -r 027b8d8b71ec llvmdc.kdevelop --- a/llvmdc.kdevelop Fri Nov 16 10:01:24 2007 +0100 +++ b/llvmdc.kdevelop Sun Nov 18 06:52:57 2007 +0100 @@ -98,7 +98,7 @@ false - *.o,*.lo,CVS + *.bc false @@ -394,6 +394,7 @@ obj/Debug/unialpha.d obj/Debug/utf.d obj/Debug/version.d + obj make diff -r 169fda3a77d4 -r 027b8d8b71ec llvmdc.kdevelop.filelist --- a/llvmdc.kdevelop.filelist Fri Nov 16 10:01:24 2007 +0100 +++ b/llvmdc.kdevelop.filelist Sun Nov 18 06:52:57 2007 +0100 @@ -129,6 +129,7 @@ gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp +gen/typeinf.h gen/typinf.cpp lphobos lphobos/crc32.d @@ -299,7 +300,7 @@ test/bug63.d test/bug64.d test/bug66.d -test/bug67.d +test/bug69.d test/bug7.d test/bug8.d test/bug9.d diff -r 169fda3a77d4 -r 027b8d8b71ec lphobos/build.sh --- a/lphobos/build.sh Fri Nov 16 10:01:24 2007 +0100 +++ b/lphobos/build.sh Sun Nov 18 06:52:57 2007 +0100 @@ -20,7 +20,7 @@ echo "compiling typeinfo 1" -rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix || exit 1 +rebuild typeinfos1.d -c -oqobj -dc=llvmdc-posix -v || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/typeinfo1.*.bc` ../lib/llvmdcore.bc || exit 1 echo "compiling typeinfo 2" @@ -52,7 +52,7 @@ llvm-link -f -o=../lib/llvmdcore.bc obj/gclinux.bc obj/gcstub.bc ../lib/llvmdcore.bc || exit 1 echo "compiling phobos" -rebuild phobos.d -c -oqobj -dc=llvmdc-posix || exit 1 +rebuild phobos.d -c -oqobj -dc=llvmdc-posix -v || exit 1 llvm-link -f -o=../lib/llvmdcore.bc `ls obj/std.*.bc` ../lib/llvmdcore.bc || exit 1 echo "optimizing" diff -r 169fda3a77d4 -r 027b8d8b71ec test/bug51.d --- a/test/bug51.d Fri Nov 16 10:01:24 2007 +0100 +++ b/test/bug51.d Sun Nov 18 06:52:57 2007 +0100 @@ -1,5 +1,7 @@ module bug51; const ubyte[3] arr1 = 0; const ubyte[3] arr2 = [0]; -const ubyte[3] arr3 = [0:1]; -void main() {} +const ubyte[3] arr3 = [1:1]; +void main() +{ +} diff -r 169fda3a77d4 -r 027b8d8b71ec test/classinfo1.d --- a/test/classinfo1.d Fri Nov 16 10:01:24 2007 +0100 +++ b/test/classinfo1.d Sun Nov 18 06:52:57 2007 +0100 @@ -1,10 +1,28 @@ module classinfo1; -class C +class NoPtrs { } +class HasPtrs +{ + void* p; +} + void main() { - ClassInfo ci = C.classinfo; + { + ClassInfo ci = NoPtrs.classinfo; + char[] name = ci.name; + printf("%.*s\n", name.length, name.ptr); + assert(ci.name == "classinfo1.NoPtrs"); + assert(ci.flags == 2); + } + { + ClassInfo ci = HasPtrs.classinfo; + char[] name = ci.name; + printf("%.*s\n", name.length, name.ptr); + assert(ci.name == "classinfo1.HasPtrs"); + assert(ci.flags == 0); + } } diff -r 169fda3a77d4 -r 027b8d8b71ec test/funcptr.d --- a/test/funcptr.d Fri Nov 16 10:01:24 2007 +0100 +++ b/test/funcptr.d Sun Nov 18 06:52:57 2007 +0100 @@ -42,14 +42,14 @@ binfn_t binfn = &add_int; assert(binfn(4,1045) == 1049); - + assert(binop_int(binfn, 10,656) == 666); - + binfn = get_binop_int('+'); assert(binop_int(binfn, 10,100) == 110); binfn = get_binop_int('-'); assert(binop_int(binfn, 10,100) == -90); - + { auto ffn = &mul_float; float ftmp = mul_float(2.5,5);