From 56d2cff2a2f823497d4af8312e2f81967f48b3a9 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Thu, 4 Oct 2007 16:44:07 +0200 Subject: [PATCH] [svn r35] * Attributes on struct fields/methods now work * Updated object.d to 1.021 * Added -novalidate command line option. this is sometimes useful when debugging as it may let you read the .ll even if it's invalid. --- dmd/mars.c | 4 ++++ dmd/mars.h | 1 + gen/irstate.c | 2 ++ gen/irstate.h | 12 ++++-------- gen/tollvm.c | 5 +++-- gen/toobj.c | 50 ++++++++++++++++++++---------------------------- lphobos/object.d | 35 ++++++++++++++++++++++++++------- test/bug5.d | 17 ++++++++++++++++ 8 files changed, 80 insertions(+), 46 deletions(-) create mode 100644 test/bug5.d diff --git a/dmd/mars.c b/dmd/mars.c index a937cf3e..77ba03e3 100644 --- a/dmd/mars.c +++ b/dmd/mars.c @@ -188,6 +188,7 @@ Usage:\n\ x86 x86-64 ppc32 ppc64\n\ -nofloat do not emit reference to floating point\n\ -noruntime do not allow code that generates implicit runtime calls\n\ + -novalidate do not run the validation pass before writing bitcode\n\ -O optimize, same as -O2\n\ -On optimize at level n (0-5)\n\ -o- do not write object file\n\ @@ -279,6 +280,7 @@ int main(int argc, char *argv[]) global.params.llvmArch = 0; global.params.forceBE = 0; global.params.noruntime = 0; + global.params.novalidate = 0; global.params.optimizeLevel = 2; global.params.runtimeImppath = 0; @@ -370,6 +372,8 @@ int main(int argc, char *argv[]) global.params.forceBE = 1; else if (strcmp(p + 1, "noruntime") == 0) global.params.noruntime = 1; + else if (strcmp(p + 1, "novalidate") == 0) + global.params.novalidate = 1; else if (p[1] == 'o') { switch (p[2]) diff --git a/dmd/mars.h b/dmd/mars.h index c7841433..4ef57f6f 100644 --- a/dmd/mars.h +++ b/dmd/mars.h @@ -68,6 +68,7 @@ struct Param char cov; // generate code coverage data char nofloat; // code should not pull in floating point support char noruntime; // code is not allowed to make implicit calls to the runtime + char novalidate;// no bitcode validation char Dversion; // D version number char *argv0; // program name diff --git a/gen/irstate.c b/gen/irstate.c index 871df49c..03012007 100644 --- a/gen/irstate.c +++ b/gen/irstate.c @@ -98,12 +98,14 @@ IRStruct::IRStruct() : recty(llvm::OpaqueType::get()) { type = 0; + queueFuncs = true; } IRStruct::IRStruct(Type* t) : recty(llvm::OpaqueType::get()) { type = t; + queueFuncs = true; } IRStruct::~IRStruct() diff --git a/gen/irstate.h b/gen/irstate.h index f9dfb060..0514de8a 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -41,7 +41,7 @@ struct IRStruct : Object { typedef std::vector TypeVector; typedef std::vector ConstantVector; - typedef std::vector PATypeHolderVector; + typedef std::vector FuncDeclVec; public: IRStruct(); @@ -52,6 +52,8 @@ public: TypeVector fields; ConstantVector inits; llvm::PATypeHolder recty; + FuncDeclVec funcs; + bool queueFuncs; }; // represents the module @@ -79,13 +81,6 @@ struct IRState : Object typedef std::vector ClassDeclVec; ClassDeclVec classes; - typedef std::vector FuncDeclVec; - typedef std::vector ClassMethodVec; - ClassMethodVec classmethods; - - typedef std::vector BoolVec; - BoolVec queueClassMethods; - // D main function bool emitMain; llvm::Function* mainFunc; @@ -115,6 +110,7 @@ struct IRState : Object LvalVec arrays; // keeping track of the declaration for the current function body + typedef std::vector FuncDeclVec; FuncDeclVec funcdecls; }; diff --git a/gen/tollvm.c b/gen/tollvm.c index 1bcc037c..ae7b190c 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.c @@ -243,7 +243,7 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl) std::vector paramvec; if (retinptr) { - Logger::print("returning through pointer parameter\n"); + Logger::cout() << "returning through pointer parameter: " << *rettype << '\n'; paramvec.push_back(rettype); } @@ -251,7 +251,8 @@ const llvm::FunctionType* LLVM_DtoFunctionType(FuncDeclaration* fdecl) if (AggregateDeclaration* ad = fdecl->isMember()) { Logger::print("isMember = this is: %s\n", ad->type->toChars()); const llvm::Type* thisty = LLVM_DtoType(ad->type); - if (llvm::isa(thisty)) + Logger::cout() << "this llvm type: " << *thisty << '\n'; + if (llvm::isa(thisty) || thisty == gIR->topstruct().recty.get()) thisty = llvm::PointerType::get(thisty); paramvec.push_back(thisty); usesthis = true; diff --git a/gen/toobj.c b/gen/toobj.c index 5614d9e9..4fee0c31 100644 --- a/gen/toobj.c +++ b/gen/toobj.c @@ -87,15 +87,18 @@ Module::genobjfile() } // verify the llvm - std::string verifyErr; - Logger::println("Verifying module..."); - if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) - { - error("%s", verifyErr.c_str()); - fatal(); + if (!global.params.novalidate) { + std::string verifyErr; + Logger::println("Verifying module..."); + if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) + { + error("%s", verifyErr.c_str()); + fatal(); + } + else { + Logger::println("Verification passed!"); + } } - else - Logger::println("Verification passed!"); // run passes // TODO @@ -219,19 +222,9 @@ void StructDeclaration::toObjFile() gIR->structs.push_back(IRStruct(ts)); - std::vector mfs; - for (int k=0; k < members->dim; k++) { Dsymbol* dsym = (Dsymbol*)(members->data[k]); - - // need late generation of member functions - // they need the llvm::StructType to exist to take the 'this' parameter - if (FuncDeclaration* fd = dsym->isFuncDeclaration()) { - mfs.push_back(fd); - } - else { - dsym->toObjFile(); - } + dsym->toObjFile(); } if (gIR->topstruct().fields.empty()) @@ -293,7 +286,9 @@ void StructDeclaration::toObjFile() llvm::GlobalVariable* initvar = new llvm::GlobalVariable(ts->llvmType, true, _linkage, _init, initname, gIR->module); ts->llvmInit = initvar; - // generate member functions + // generate member function definitions + gIR->topstruct().queueFuncs = false; + IRState::FuncDeclVec& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); @@ -341,8 +336,6 @@ void ClassDeclaration::toObjFile() gIR->structs.push_back(IRStruct(ts)); gIR->classes.push_back(this); - gIR->classmethods.push_back(IRState::FuncDeclVec()); - gIR->queueClassMethods.push_back(true); // add vtable llvm::PATypeHolder pa = llvm::OpaqueType::get(); @@ -459,15 +452,13 @@ void ClassDeclaration::toObjFile() } // generate member function definitions - gIR->queueClassMethods.back() = false; - IRState::FuncDeclVec& mfs = gIR->classmethods.back(); + gIR->topstruct().queueFuncs = false; + IRState::FuncDeclVec& mfs = gIR->topstruct().funcs; size_t n = mfs.size(); for (size_t i=0; itoObjFile(); } - gIR->queueClassMethods.pop_back(); - gIR->classmethods.pop_back(); gIR->classes.pop_back(); gIR->structs.pop_back(); @@ -644,11 +635,10 @@ void FuncDeclaration::toObjFile() llvm::Function* func = LLVM_DtoDeclareFunction(this); - if (!gIR->queueClassMethods.empty() && gIR->queueClassMethods.back()) { + if (!gIR->structs.empty() && gIR->topstruct().queueFuncs) { if (!llvmQueued) { Logger::println("queueing %s", toChars()); - assert(!gIR->classmethods.empty()); - gIR->classmethods.back().push_back(this); + gIR->topstruct().funcs.push_back(this); llvmQueued = true; } return; // we wait with the definition as they might invoke a virtual method and the vtable is not yet complete @@ -699,6 +689,8 @@ void FuncDeclaration::toObjFile() // first make absolutely sure the type is up to date f->llvmType = llvmValue->getType()->getContainedType(0); + Logger::cout() << "func type: " << *f->llvmType << '\n'; + // this handling if (f->llvmUsesThis) { if (f->llvmRetInPtr) diff --git a/lphobos/object.d b/lphobos/object.d index edeb3a58..7720ca5c 100644 --- a/lphobos/object.d +++ b/lphobos/object.d @@ -10,8 +10,13 @@ alias typeof(int.sizeof) size_t; alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t; alias size_t hash_t; +alias char[] string; +alias wchar[] wstring; +alias dchar[] dstring; + extern (C) { int printf(char *, ...); + void trace_term(); } class Object @@ -24,13 +29,15 @@ class Object final void notifyRegister(void delegate(Object) dg); final void notifyUnRegister(void delegate(Object) dg); + + static Object factory(char[] classname); } struct Interface { ClassInfo classinfo; void *[] vtbl; - ptrdiff_t offset; // offset to Interface 'this' from Object 'this' + int offset; // offset to Interface 'this' from Object 'this' } class ClassInfo : Object @@ -46,8 +53,13 @@ class ClassInfo : Object // 1: // IUnknown // 2: // has no possible pointers into GC memory // 4: // has offTi[] member + // 8: // has constructors void *deallocator; OffsetTypeInfo[] offTi; + void* defaultConstructor; // default Constructor + + static ClassInfo find(char[] classname); + Object create(); } struct OffsetTypeInfo @@ -141,15 +153,24 @@ class TypeInfo_Tuple : TypeInfo TypeInfo[] elements; } +class TypeInfo_Const : TypeInfo +{ + TypeInfo next; +} + +class TypeInfo_Invariant : TypeInfo_Const +{ +} + // Recoverable errors class Exception : Object { - char[] msg; + string msg; - this(char[] msg); - void print(); - char[] toString(); + this(string msg); + override void print(); + override string toString(); } // Non-recoverable errors @@ -158,7 +179,7 @@ class Error : Exception { Error next; - this(char[] msg); - this(char[] msg, Error next); + this(string msg); + this(string msg, Error next); } diff --git a/test/bug5.d b/test/bug5.d new file mode 100644 index 00000000..9ac4bc17 --- /dev/null +++ b/test/bug5.d @@ -0,0 +1,17 @@ +module bug5; + +struct hah { + static hah f() + { + hah res; + return res; + } + hah g() + { + return hah.init; + } +} + +void main() +{ +}