# HG changeset patch # User lindquist # Date 1196013352 -3600 # Node ID fd7ad91fd7136a95536b70c79c263013f37b1373 # Parent 5ba6d286c9410b143ae71ced1567f61ea6bcbb38 [svn r120] ModuleInfo implementation is now almost complete. Fixed some nasty static array-initializer bugs. Fixed bug in DtoArrayLen and DtoArrayPtr for full slices of static arrays. diff -r 5ba6d286c941 -r fd7ad91fd713 gen/arrays.cpp --- a/gen/arrays.cpp Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/arrays.cpp Sun Nov 25 18:55:52 2007 +0100 @@ -285,22 +285,32 @@ std::vector inits(tdim, NULL); + Type* arrnext = arrinittype->next; const llvm::Type* elemty = DtoType(arrinittype->next); assert(arrinit->index.dim == arrinit->value.dim); for (unsigned i=0,j=0; i < tdim; ++i) { Initializer* init = 0; - Expression* idx = (Expression*)arrinit->index.data[j]; + Expression* idx; + + if (j < arrinit->index.dim) + idx = (Expression*)arrinit->index.data[j]; + else + idx = NULL; + + llvm::Constant* v = NULL; if (idx) { + Logger::println("%d has idx", i); // this is pretty weird :/ idx->type turned out NULL for the initializer: // const in6_addr IN6ADDR_ANY = { s6_addr8: [0] }; // in std.c.linux.socket if (idx->type) { + Logger::println("has idx->type", i); //integer_t k = idx->toInteger(); - Logger::println("getting value for exp: %s | %s", idx->toChars(), idx->type->toChars()); + //Logger::println("getting value for exp: %s | %s", idx->toChars(), arrnext->toChars()); llvm::Constant* cc = idx->toConstElem(gIR); Logger::println("value gotten"); assert(cc != NULL); @@ -317,11 +327,16 @@ } else { - init = (Initializer*)arrinit->value.data[j]; - ++j; + if (j < arrinit->value.dim) { + init = (Initializer*)arrinit->value.data[j]; + ++j; + } + else + v = arrnext->defaultInit()->toConstElem(gIR); } - llvm::Constant* v = DtoConstInitializer(t->next, init); + if (!v) + v = DtoConstInitializer(t->next, init); assert(v); inits[i] = v; @@ -784,16 +799,22 @@ ////////////////////////////////////////////////////////////////////////////////////////// llvm::Value* DtoArrayLen(DValue* v) { + Logger::println("DtoArrayLen"); + LOG_SCOPE; Type* t = DtoDType(v->getType()); if (t->ty == Tarray) { if (DSliceValue* s = v->isSlice()) { - if (s->len) return s->len; - DValue* next = new DVarValue(t,s->ptr,true); - return DtoArrayLen(next); + if (s->len) { + return s->len; + } + const llvm::ArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0)); + assert(arrTy); + return DtoConstSize_t(arrTy->getNumElements()); } return DtoLoad(DtoGEPi(v->getRVal(), 0,0, "tmp")); } else if (t->ty == Tsarray) { + assert(!v->isSlice()); llvm::Value* rv = v->getRVal(); Logger::cout() << "casting: " << *rv << '\n'; const llvm::ArrayType* t = isaArray(rv->getType()->getContainedType(0)); @@ -810,8 +831,9 @@ if (t->ty == Tarray) { if (DSliceValue* s = v->isSlice()) { if (s->len) return s->ptr; - DValue* next = new DVarValue(t,s->ptr,true); - return DtoArrayPtr(next); + const llvm::ArrayType* arrTy = isaArray(s->ptr->getType()->getContainedType(0)); + assert(arrTy); + return DtoGEPi(s->ptr, 0,0, "tmp"); } return DtoLoad(DtoGEPi(v->getRVal(), 0,1, "tmp")); } diff -r 5ba6d286c941 -r fd7ad91fd713 gen/functions.cpp --- a/gen/functions.cpp Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/functions.cpp Sun Nov 25 18:55:52 2007 +0100 @@ -368,10 +368,20 @@ fdecl->llvmValue = func; assert(llvm::isa(f->llvmType->get())); + // main if (fdecl->isMain()) { gIR->mainFunc = func; } + // static ctor + if (fdecl->isStaticCtorDeclaration()) { + gIR->ctors.push_back(fdecl); + } + // static dtor + else if (fdecl->isStaticDtorDeclaration()) { + gIR->dtors.push_back(fdecl); + } + // name parameters llvm::Function::arg_iterator iarg = func->arg_begin(); int k = 0; diff -r 5ba6d286c941 -r fd7ad91fd713 gen/irstate.h --- a/gen/irstate.h Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/irstate.h Sun Nov 25 18:55:52 2007 +0100 @@ -218,6 +218,12 @@ DsymbolList constInitList; // dsymbols that need definitions DsymbolList defineList; + + // static ctors/dtors/unittests + typedef std::vector FuncDeclVector; + FuncDeclVector ctors; + FuncDeclVector dtors; + FuncDeclVector unitTests; }; #endif // LLVMDC_GEN_IRSTATE_H diff -r 5ba6d286c941 -r fd7ad91fd713 gen/toir.cpp --- a/gen/toir.cpp Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/toir.cpp Sun Nov 25 18:55:52 2007 +0100 @@ -1491,6 +1491,9 @@ emem = vmem; } + if (earg) Logger::cout() << "slice exp result, length = " << *earg << '\n'; + Logger::cout() << "slice exp result, ptr = " << *emem << '\n'; + return new DSliceValue(type,earg,emem); } diff -r 5ba6d286c941 -r fd7ad91fd713 gen/tollvm.cpp --- a/gen/tollvm.cpp Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/tollvm.cpp Sun Nov 25 18:55:52 2007 +0100 @@ -1617,6 +1617,38 @@ } ////////////////////////////////////////////////////////////////////////////////////////// +void DtoEmptyAllLists() +{ + for(;;) + { + Dsymbol* dsym; + if (!gIR->resolveList.empty()) { + dsym = gIR->resolveList.front(); + gIR->resolveList.pop_front(); + DtoResolveDsymbol(dsym); + } + else if (!gIR->declareList.empty()) { + dsym = gIR->declareList.front(); + gIR->declareList.pop_front(); + DtoDeclareDsymbol(dsym); + } + else if (!gIR->constInitList.empty()) { + dsym = gIR->constInitList.front(); + gIR->constInitList.pop_front(); + DtoConstInitDsymbol(dsym); + } + else if (!gIR->defineList.empty()) { + dsym = gIR->defineList.front(); + gIR->defineList.pop_front(); + DtoDefineDsymbol(dsym); + } + else { + break; + } + } +} + +////////////////////////////////////////////////////////////////////////////////////////// void DtoForceDeclareDsymbol(Dsymbol* dsym) { diff -r 5ba6d286c941 -r fd7ad91fd713 gen/tollvm.h --- a/gen/tollvm.h Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/tollvm.h Sun Nov 25 18:55:52 2007 +0100 @@ -69,6 +69,7 @@ void DtoEmptyResolveList(); void DtoEmptyDeclareList(); void DtoEmptyConstInitList(); +void DtoEmptyAllLists(); void DtoForceDeclareDsymbol(Dsymbol* dsym); void DtoForceConstInitDsymbol(Dsymbol* dsym); void DtoForceDefineDsymbol(Dsymbol* dsym); diff -r 5ba6d286c941 -r fd7ad91fd713 gen/toobj.cpp --- a/gen/toobj.cpp Sun Nov 25 03:58:55 2007 +0100 +++ b/gen/toobj.cpp Sun Nov 25 18:55:52 2007 +0100 @@ -106,36 +106,11 @@ } // main driver loop - for(;;) - { - Dsymbol* dsym; - if (!ir.resolveList.empty()) { - dsym = ir.resolveList.front(); - ir.resolveList.pop_front(); - DtoResolveDsymbol(dsym); - } - else if (!ir.declareList.empty()) { - dsym = ir.declareList.front(); - ir.declareList.pop_front(); - DtoDeclareDsymbol(dsym); - } - else if (!ir.constInitList.empty()) { - dsym = ir.constInitList.front(); - ir.constInitList.pop_front(); - DtoConstInitDsymbol(dsym); - } - else if (!ir.defineList.empty()) { - dsym = ir.defineList.front(); - ir.defineList.pop_front(); - DtoDefineDsymbol(dsym); - } - else { - break; - } - } - + DtoEmptyAllLists(); // generate ModuleInfo genmoduleinfo(); + // do this again as moduleinfo might have pulled something in! + DtoEmptyAllLists(); gTargetData = 0; @@ -181,6 +156,72 @@ /* ================================================================== */ +// build module ctor + +static llvm::Function* build_module_ctor() +{ + if (gIR->ctors.empty()) + return NULL; + + size_t n = gIR->ctors.size(); + if (n == 1) + return llvm::cast(gIR->ctors[0]->llvmValue); + + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__ctorZ"); + + std::vector argsTy; + const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false); + llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); + fn->setCallingConv(llvm::CallingConv::Fast); + + llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn); + LLVMBuilder builder(bb); + + for (size_t i=0; i(gIR->ctors[i]->llvmValue); + llvm::CallInst* call = builder.CreateCall(f,""); + call->setCallingConv(llvm::CallingConv::Fast); + } + + builder.CreateRetVoid(); + return fn; +} + +// build module dtor + +static llvm::Function* build_module_dtor() +{ + if (gIR->dtors.empty()) + return NULL; + + size_t n = gIR->dtors.size(); + if (n == 1) + return llvm::cast(gIR->dtors[0]->llvmValue); + + std::string name("_D"); + name.append(gIR->dmodule->mangle()); + name.append("6__dtorZ"); + + std::vector argsTy; + const llvm::FunctionType* fnTy = llvm::FunctionType::get(llvm::Type::VoidTy,argsTy,false); + llvm::Function* fn = new llvm::Function(fnTy, llvm::GlobalValue::InternalLinkage, name, gIR->module); + fn->setCallingConv(llvm::CallingConv::Fast); + + llvm::BasicBlock* bb = new llvm::BasicBlock("entry", fn); + LLVMBuilder builder(bb); + + for (size_t i=0; i(gIR->dtors[i]->llvmValue); + llvm::CallInst* call = builder.CreateCall(f,""); + call->setCallingConv(llvm::CallingConv::Fast); + } + + builder.CreateRetVoid(); + return fn; +} + // Put out instance of ModuleInfo for this Module void Module::genmoduleinfo() @@ -198,139 +239,131 @@ // void *unitTest; // } - if (moduleinfo) { - Logger::println("moduleinfo"); - } - if (vmoduleinfo) { - Logger::println("vmoduleinfo"); - } - if (needModuleInfo()) { - Logger::attention("module info is needed but skipped"); - } + // resolve ModuleInfo + assert(moduleinfo); + DtoForceConstInitDsymbol(moduleinfo); + // moduleinfo llvm struct type + const llvm::StructType* moduleinfoTy = isaStruct(moduleinfo->type->llvmType->get()); - /* - Symbol *msym = toSymbol(); - unsigned offset; - unsigned sizeof_ModuleInfo = 12 * PTRSIZE; - - ////////////////////////////////////////////// - - csym->Sclass = SCglobal; - csym->Sfl = FLdata; + // classinfo llvm struct type + const llvm::StructType* classinfoTy = isaStruct(ClassDeclaration::classinfo->type->llvmType->get()); -// The layout is: -// { -// void **vptr; -// monitor_t monitor; -// char[] name; // class name -// ModuleInfo importedModules[]; -// ClassInfo localClasses[]; -// uint flags; // initialization state -// void *ctor; -// void *dtor; -// void *unitTest; -// } - dt_t *dt = NULL; + // initializer vector + std::vector initVec; + llvm::Constant* c = 0; + + // vtable + c = moduleinfo->llvmVtbl; + initVec.push_back(c); - if (moduleinfo) - dtxoff(&dt, moduleinfo->toVtblSymbol(), 0, TYnptr); // vtbl for ModuleInfo - else - dtdword(&dt, 0); // BUG: should be an assert() - dtdword(&dt, 0); // monitor - - // name[] - char *name = toPrettyChars(); - size_t namelen = strlen(name); - dtdword(&dt, namelen); - dtabytes(&dt, TYnptr, 0, namelen + 1, name); + // monitor + c = llvm::ConstantPointerNull::get(llvm::PointerType::get(llvm::Type::Int8Ty)); + initVec.push_back(c); - ClassDeclarations aclasses; - int i; - - //printf("members->dim = %d\n", members->dim); - for (i = 0; i < members->dim; i++) - { - Dsymbol *member; - - member = (Dsymbol *)members->data[i]; - //printf("\tmember '%s'\n", member->toChars()); - member->addLocalClass(&aclasses); - } + // name + char *name = toPrettyChars(); + c = DtoConstString(name); + initVec.push_back(c); // importedModules[] int aimports_dim = aimports.dim; - for (i = 0; i < aimports.dim; i++) - { Module *m = (Module *)aimports.data[i]; - if (!m->needModuleInfo()) - aimports_dim--; + std::vector importInits; + for (size_t i = 0; i < aimports.dim; i++) + { + Module *m = (Module *)aimports.data[i]; + if (!m->needModuleInfo()) + aimports_dim--; + else { // declare + // create name + std::string m_name("_D"); + m_name.append(m->mangle()); + m_name.append("8__ModuleZ"); + llvm::GlobalVariable* m_gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, NULL, m_name, gIR->module); + importInits.push_back(m_gvar); + } } - dtdword(&dt, aimports_dim); - if (aimports.dim) - dtxoff(&dt, csym, sizeof_ModuleInfo, TYnptr); + // has import array? + if (!importInits.empty()) { + const llvm::ArrayType* importArrTy = llvm::ArrayType::get(llvm::PointerType::get(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 = DtoConstSlice(DtoConstSize_t(importInits.size()), c); + } else - dtdword(&dt, 0); + c = moduleinfo->llvmInitZ->getOperand(3); + initVec.push_back(c); // localClasses[] - dtdword(&dt, aclasses.dim); - if (aclasses.dim) - dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYnptr); - else - dtdword(&dt, 0); - - if (needmoduleinfo) - dtdword(&dt, 0); // flags (4 means MIstandalone) - else - dtdword(&dt, 4); // flags (4 means MIstandalone) + ClassDeclarations aclasses; + //printf("members->dim = %d\n", members->dim); + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *member; - if (sctor) - dtxoff(&dt, sctor, 0, TYnptr); - else - dtdword(&dt, 0); - - if (sdtor) - dtxoff(&dt, sdtor, 0, TYnptr); - else - dtdword(&dt, 0); - - if (stest) - dtxoff(&dt, stest, 0, TYnptr); - else - dtdword(&dt, 0); - - ////////////////////////////////////////////// - - for (i = 0; i < aimports.dim; i++) + member = (Dsymbol *)members->data[i]; + //printf("\tmember '%s'\n", member->toChars()); + member->addLocalClass(&aclasses); + } + // fill inits + std::vector classInits; + for (size_t i = 0; i < aclasses.dim; i++) { - Module *m; + ClassDeclaration* cd = (ClassDeclaration*)aclasses.data[i]; + 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()); + 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 = DtoConstSlice(DtoConstSize_t(classInits.size()), c); + } + else + c = moduleinfo->llvmInitZ->getOperand(4); + initVec.push_back(c); - m = (Module *)aimports.data[i]; - if (m->needModuleInfo()) - { Symbol *s = m->toSymbol(); - s->Sflags |= SFLweak; - dtxoff(&dt, s, 0, TYnptr); - } - } - - for (i = 0; i < aclasses.dim; i++) - { - ClassDeclaration *cd; + // flags + if (needmoduleinfo) + c = DtoConstUint(0); // flags (4 means MIstandalone) + else + c = DtoConstUint(4); // flags (4 means MIstandalone) + initVec.push_back(c); - cd = (ClassDeclaration *)aclasses.data[i]; - dtxoff(&dt, cd->toSymbol(), 0, TYnptr); - } + // ctor + llvm::Function* fctor = build_module_ctor(); + c = fctor ? fctor : moduleinfo->llvmInitZ->getOperand(6); + initVec.push_back(c); + + // dtor + llvm::Function* fdtor = build_module_dtor(); + c = fdtor ? fdtor : moduleinfo->llvmInitZ->getOperand(7); + initVec.push_back(c); - csym->Sdt = dt; -#if ELFOBJ - // Cannot be CONST because the startup code sets flag bits in it - csym->Sseg = DATA; -#endif - outdata(csym); + // unitTest + c = moduleinfo->llvmInitZ->getOperand(8); + initVec.push_back(c); + + // create initializer + llvm::Constant* constMI = llvm::ConstantStruct::get(moduleinfoTy, initVec); - ////////////////////////////////////////////// + // create name + std::string MIname("_D"); + MIname.append(mangle()); + MIname.append("8__ModuleZ"); - obj_moduleinfo(msym); - */ + // declare + // flags will be modified at runtime so can't make it constant + llvm::GlobalVariable* gvar = new llvm::GlobalVariable(moduleinfoTy, false, llvm::GlobalValue::ExternalLinkage, constMI, MIname, gIR->module); } /* ================================================================== */ diff -r 5ba6d286c941 -r fd7ad91fd713 lphobos/internal/objectimpl.d --- a/lphobos/internal/objectimpl.d Sun Nov 25 03:58:55 2007 +0100 +++ b/lphobos/internal/objectimpl.d Sun Nov 25 18:55:52 2007 +0100 @@ -33,7 +33,8 @@ */ /* - * This copy is modified to work with LLVMDC by Tomas Lindquist Olsen 2007 + * This copy is modified to work with LLVMDC + * by Tomas Lindquist Olsen, September 2007 */ module object; @@ -1120,6 +1121,30 @@ } /** + * Information about each module. + */ +class ModuleInfo +{ + char[] name; + ModuleInfo[] importedModules; + ClassInfo[] localClasses; + + uint flags; // initialization state + + void function() ctor; + void function() dtor; + void function() unitTest; + + /****************** + * Return collection of all modules in the program. + */ + static ModuleInfo[] modules() + { + return std.moduleinit._moduleinfo_array; + } +} + +/** * All recoverable exceptions should be derived from class Exception. */ class Exception : Object diff -r 5ba6d286c941 -r fd7ad91fd713 lphobos/object.d --- a/lphobos/object.d Sun Nov 25 03:58:55 2007 +0100 +++ b/lphobos/object.d Sun Nov 25 18:55:52 2007 +0100 @@ -162,6 +162,22 @@ { } +class ModuleInfo +{ + char[] name; + ModuleInfo[] importedModules; + ClassInfo[] localClasses; + + uint flags; // initialization state + + void function() ctor; + void function() dtor; + void function() unitTest; + + // Return collection of all modules in the program. + static ModuleInfo[] modules(); +} + // Recoverable errors class Exception : Object diff -r 5ba6d286c941 -r fd7ad91fd713 lphobos/std/moduleinit.d --- a/lphobos/std/moduleinit.d Sun Nov 25 03:58:55 2007 +0100 +++ b/lphobos/std/moduleinit.d Sun Nov 25 18:55:52 2007 +0100 @@ -18,29 +18,8 @@ // ctors being done first } -/*********************** - * Information about each module. - */ -class ModuleInfo -{ - char[] name; - ModuleInfo[] importedModules; - ClassInfo[] localClasses; - - uint flags; // initialization state - - void function() ctor; - void function() dtor; - void function() unitTest; - - /****************** - * Return collection of all modules in the program. - */ - static ModuleInfo[] modules() - { - return _moduleinfo_array; - } -} +// had to move the class to object.d, as its declaration is needed in the compiler code, +// otherwise the DMDFE Module::moduleinfo member is NULL class ModuleCtorError : Exception { diff -r 5ba6d286c941 -r fd7ad91fd713 test/bug51.d --- a/test/bug51.d Sun Nov 25 03:58:55 2007 +0100 +++ b/test/bug51.d Sun Nov 25 18:55:52 2007 +0100 @@ -1,7 +1,10 @@ module bug51; -const ubyte[3] arr1 = 0; -const ubyte[3] arr2 = [0]; +const ubyte[3] arr1 = 1; +const ubyte[3] arr2 = [1]; const ubyte[3] arr3 = [1:1]; void main() { + assert(arr1 == [cast(ubyte)1,1,1][]); + assert(arr2 == [cast(ubyte)1,0,0][]); + assert(arr3 == [cast(ubyte)0,1,0][]); } diff -r 5ba6d286c941 -r fd7ad91fd713 test/moduleinfo1.d --- a/test/moduleinfo1.d Sun Nov 25 03:58:55 2007 +0100 +++ b/test/moduleinfo1.d Sun Nov 25 18:55:52 2007 +0100 @@ -1,11 +1,36 @@ module moduleinfo1; +// has static this +import std.outofmemory; + +static this() +{ +} + +static this() +{ +} + +static ~this() +{ +} + +static ~this() +{ +} + +unittest +{ +} + class C { } +class D : C +{ +} + void main() { - C c; } -