diff gen/classes.cpp @ 1148:3d1b16dabd25

Eliminated the need for resolve, declare, const-init and define lists to drive code generation.
author Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
date Fri, 27 Mar 2009 21:50:32 +0100
parents dbe4af57b240
children 5ebe8224988b
line wrap: on
line diff
--- a/gen/classes.cpp	Fri Mar 27 17:54:27 2009 +0100
+++ b/gen/classes.cpp	Fri Mar 27 21:50:32 2009 +0100
@@ -124,6 +124,10 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
+static void DtoDeclareInterface(InterfaceDeclaration* cd);
+static void DtoConstInitInterface(InterfaceDeclaration* cd);
+static void DtoDefineInterface(InterfaceDeclaration* cd);
+
 static void DtoResolveInterface(InterfaceDeclaration* cd)
 {
     if (cd->ir.resolved) return;
@@ -156,7 +160,7 @@
             assert(id);
 
             DtoResolveInterface(id);
-    
+
             // add to interfaceInfos
             IrInterface* iri = new IrInterface(bc);
             irstruct->interfaceVec.push_back(iri);
@@ -170,7 +174,7 @@
     ts->ir.type = new LLPATypeHolder(getPtrToType(t));
 
     // request declaration
-    gIR->declareList.push_back(cd);
+    DtoDeclareInterface(cd);
 
     // handle members
     // like "nested" interfaces
@@ -193,14 +197,16 @@
         return;
     }
 
+    // make sure the base classes are processed first
+    if (cd->baseClass)
+        cd->baseClass->codegen(Type::sir);
+
     if (cd->ir.resolved) return;
     cd->ir.resolved = true;
 
     Logger::println("DtoResolveClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
     LOG_SCOPE;
 
-    //printf("resolve class: %s\n", cd->toPrettyChars());
-
     // get the TypeClass
     assert(cd->type->ty == Tclass);
     TypeClass* ts = (TypeClass*)cd->type;
@@ -221,10 +227,21 @@
         return;
     }
 
-    // resolve the base class
-    if (cd->baseClass) {
-        DtoResolveClass(cd->baseClass);
-    }
+    // create the symbols we're going to need
+    // avoids chicken egg problems
+    llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
+
+    // there is always a vtbl symbol
+    std::string varname("_D");
+    varname.append(cd->mangle());
+    varname.append("6__vtblZ");
+    irstruct->vtbl = new llvm::GlobalVariable(irstruct->vtblInitTy.get(), true, _linkage, NULL, varname, gIR->module);
+
+    // ... and initZ
+    std::string initname("_D");
+    initname.append(cd->mangle());
+    initname.append("6__initZ");
+    irstruct->init = new llvm::GlobalVariable(irstruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
 
     // push state
     gIR->structs.push_back(irstruct);
@@ -252,6 +269,7 @@
     llvm::PATypeHolder* spa = ts->ir.type;
     llvm::cast<llvm::OpaqueType>(spa->get())->refineAbstractTypeTo(structtype);
     structtype = isaStruct(spa->get());
+    assert(structtype);
 
     // name the type
     gIR->module->addTypeName(cd->mangle(), ts->ir.type->get());
@@ -269,13 +287,15 @@
     gIR->structs.pop_back();
 
     // queue declare
-    gIR->declareList.push_back(cd);
+    DtoDeclareClass(cd);
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
 static void DtoDeclareInterface(InterfaceDeclaration* cd)
 {
+    DtoResolveInterface(cd);
+
     if (cd->ir.declared) return;
     cd->ir.declared = true;
 
@@ -321,12 +341,12 @@
     DtoDeclareClassInfo(cd);
 
     // request const init
-    gIR->constInitList.push_back(cd);
+    DtoConstInitInterface(cd);
 
     // emit typeinfo and request definition
     if (mustDefineSymbol(cd))
     {
-        gIR->defineList.push_back(cd);
+        DtoDefineInterface(cd);
         DtoTypeInfoOf(cd->type, false);
     }
 }
@@ -343,6 +363,8 @@
         return;
     }
 
+    DtoResolveClass(cd);
+
     if (cd->ir.declared) return;
     cd->ir.declared = true;
 
@@ -366,12 +388,6 @@
 
     llvm::GlobalValue::LinkageTypes _linkage = DtoLinkage(cd);
 
-    // create vtbl symbol
-    std::string varname("_D");
-    varname.append(cd->mangle());
-    varname.append("6__vtblZ");
-    irstruct->vtbl = new llvm::GlobalVariable(irstruct->vtblInitTy.get(), true, _linkage, 0, varname, gIR->module);
-
     // get interface info type
     const llvm::StructType* infoTy = DtoInterfaceInfoType();
 
@@ -410,23 +426,14 @@
         idx++;
     }
 
-    // initZ init
-    std::string initname("_D");
-    initname.append(cd->mangle());
-    initname.append("6__initZ");
-
-    // initZ global
-    llvm::GlobalVariable* initvar = new llvm::GlobalVariable(irstruct->initOpaque.get(), true, _linkage, NULL, initname, gIR->module);
-    irstruct->init = initvar;
-
     gIR->structs.pop_back();
 
     // request const init
-    gIR->constInitList.push_back(cd);
+    DtoConstInitClass(cd);
 
     // define ? (set initializers)
     if (needs_definition)
-        gIR->defineList.push_back(cd);
+        DtoDefineClass(cd);
 
     // classinfo
     DtoDeclareClassInfo(cd);
@@ -544,6 +551,8 @@
 // build the vtable initializer for class cd
 static void init_class_vtbl_initializer(ClassDeclaration* cd)
 {
+    cd->codegen(Type::sir);
+
     // generate vtable initializer
     std::vector<LLConstant*> sinits(cd->vtbl.dim, NULL);
 
@@ -551,6 +560,8 @@
 
     assert(cd->vtbl.dim > 1);
 
+    DtoDeclareClassInfo(cd);
+
     // first entry always classinfo
     assert(irstruct->classInfo);
     sinits[0] = DtoBitCast(irstruct->classInfo, DtoType(ClassDeclaration::classinfo->type));
@@ -575,7 +586,9 @@
         }
         else
         {
-            DtoForceDeclareDsymbol(fd);
+            fd->codegen(Type::sir);
+            Logger::println("F = %s", fd->toPrettyChars());
+            assert(fd->ir.irFunc);
             assert(fd->ir.irFunc->func);
             sinits[k] = fd->ir.irFunc->func;
         }
@@ -645,7 +658,7 @@
                     inits[j] = getNullPtr(getVoidPtrType());
                 else
                 {
-                    DtoForceDeclareDsymbol(fd);
+                    fd->codegen(Type::sir);
 
                     assert(fd->ir.irFunc->func);
                     inits[j] = fd->ir.irFunc->func;
@@ -662,7 +675,7 @@
         // build the interface info for ClassInfo
         // generate interface info initializer
 
-        DtoForceDeclareDsymbol(iri->decl);
+        iri->decl->codegen(Type::sir);
 
         // classinfo
         IrStruct* iris = iri->decl->ir.irStruct;
@@ -698,6 +711,8 @@
 
 static void DtoConstInitInterface(InterfaceDeclaration* cd)
 {
+    DtoDeclareInterface(cd);
+
     if (cd->ir.initialized) return;
     cd->ir.initialized = true;
 
@@ -717,18 +732,14 @@
         return;
     }
 
+    DtoDeclareClass(cd);
+
     if (cd->ir.initialized) return;
     cd->ir.initialized = true;
 
     Logger::println("DtoConstInitClass(%s): %s", cd->toPrettyChars(), cd->loc.toChars());
     LOG_SCOPE;
 
-    assert(!cd->isInterfaceDeclaration());
-
-    // make sure the baseclass is const initialized
-    if (cd->baseClass)
-        DtoForceConstInitDsymbol(cd->baseClass);
-
     // get IrStruct
     IrStruct* irstruct = cd->ir.irStruct;
     gIR->structs.push_back(irstruct);
@@ -811,6 +822,8 @@
 
 static void DtoDefineInterface(InterfaceDeclaration* cd)
 {
+    DtoConstInitInterface(cd);
+
     if (cd->ir.defined) return;
     cd->ir.defined = true;
 
@@ -839,6 +852,8 @@
         return;
     }
 
+    DtoConstInitClass(cd);
+
     if (cd->ir.defined) return;
     cd->ir.defined = true;
 
@@ -898,7 +913,7 @@
 DValue* DtoNewClass(Loc loc, TypeClass* tc, NewExp* newexp)
 {
     // resolve type
-    DtoForceDeclareDsymbol(tc->sym);
+    tc->sym->codegen(Type::sir);
 
     // allocate
     LLValue* mem;
@@ -909,7 +924,7 @@
     // custom allocator
     else if (newexp->allocator)
     {
-        DtoForceDeclareDsymbol(newexp->allocator);
+        newexp->allocator->codegen(Type::sir);
         DFuncValue dfn(newexp->allocator, newexp->allocator->ir.irFunc->func);
         DValue* res = DtoCallFunction(newexp->loc, NULL, &dfn, newexp->newargs);
         mem = DtoBitCast(res->getRVal(), DtoType(tc), ".newclass_custom");
@@ -959,7 +974,7 @@
     {
         Logger::println("Calling constructor");
         assert(newexp->arguments != NULL);
-        DtoForceDeclareDsymbol(newexp->member);
+        newexp->member->codegen(Type::sir);
         DFuncValue dfn(newexp->member, newexp->member->ir.irFunc->func, mem);
         return DtoCallFunction(newexp->loc, tc, &dfn, newexp->arguments);
     }
@@ -972,7 +987,7 @@
 
 void DtoInitClass(TypeClass* tc, LLValue* dst)
 {
-    DtoForceConstInitDsymbol(tc->sym);
+    tc->sym->codegen(Type::sir);
 
     size_t presz = 2*getTypePaddedSize(DtoSize_t());
     uint64_t n = getTypePaddedSize(tc->ir.type->get()) - presz;
@@ -1122,8 +1137,8 @@
     // call:
     // Object _d_dynamic_cast(Object o, ClassInfo c)
 
-    DtoForceDeclareDsymbol(ClassDeclaration::object);
-    DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
+    ClassDeclaration::object->codegen(Type::sir);
+    ClassDeclaration::classinfo->codegen(Type::sir);
 
     llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_dynamic_cast");
     const llvm::FunctionType* funcTy = func->getFunctionType();
@@ -1137,7 +1152,7 @@
 
     // ClassInfo c
     TypeClass* to = (TypeClass*)_to->toBasetype();
-    DtoForceDeclareDsymbol(to->sym);
+    to->sym->codegen(Type::sir);
     assert(to->sym->ir.irStruct->classInfo);
     LLValue* cinfo = to->sym->ir.irStruct->classInfo;
     // unfortunately this is needed as the implementation of object differs somehow from the declaration
@@ -1187,8 +1202,8 @@
     // call:
     // Object _d_interface_cast(void* p, ClassInfo c)
 
-    DtoForceDeclareDsymbol(ClassDeclaration::object);
-    DtoForceDeclareDsymbol(ClassDeclaration::classinfo);
+    ClassDeclaration::object->codegen(Type::sir);
+    ClassDeclaration::classinfo->codegen(Type::sir);
 
     llvm::Function* func = LLVM_D_GetRuntimeFunction(gIR->module, "_d_interface_cast");
     const llvm::FunctionType* funcTy = func->getFunctionType();
@@ -1201,7 +1216,7 @@
 
     // ClassInfo c
     TypeClass* to = (TypeClass*)_to->toBasetype();
-    DtoForceDeclareDsymbol(to->sym);
+    to->sym->codegen(Type::sir);
     assert(to->sym->ir.irStruct->classInfo);
     LLValue* cinfo = to->sym->ir.irStruct->classInfo;
     // unfortunately this is needed as the implementation of object differs somehow from the declaration
@@ -1404,7 +1419,7 @@
     if (!dtor)
         return getNullPtr(getVoidPtrType());
 
-    DtoForceDeclareDsymbol(dtor);
+    dtor->codegen(Type::sir);
     return llvm::ConstantExpr::getBitCast(dtor->ir.irFunc->func, getPtrToType(LLType::Int8Ty));
 }
 
@@ -1480,7 +1495,7 @@
     std::vector<LLConstant*> inits;
 
     ClassDeclaration* cinfo = ClassDeclaration::classinfo;
-    DtoForceConstInitDsymbol(cinfo);
+    cinfo->codegen(Type::sir);
 
     LLConstant* c;
 
@@ -1575,7 +1590,7 @@
     const LLType* invTy = DtoType(invVar->type);
     if (cd->inv)
     {
-        DtoForceDeclareDsymbol(cd->inv);
+        cd->inv->codegen(Type::sir);
         c = cd->inv->ir.irFunc->func;
         c = DtoBitCast(c, invTy);
     }
@@ -1595,7 +1610,7 @@
     // deallocator
     if (cd->aggDelete)
     {
-        DtoForceDeclareDsymbol(cd->aggDelete);
+        cd->aggDelete->codegen(Type::sir);
         c = cd->aggDelete->ir.irFunc->func;
         c = DtoBitCast(c, voidPtr);
     }
@@ -1625,7 +1640,7 @@
     // default constructor
     if (cd->defaultCtor)
     {
-        DtoForceDeclareDsymbol(cd->defaultCtor);
+        cd->defaultCtor->codegen(Type::sir);
         c = isaConstant(cd->defaultCtor->ir.irFunc->func);
         c = DtoBitCast(c, voidPtr);
     }