diff gen/toobj.cpp @ 116:fd7ad91fd713 trunk

[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.
author lindquist
date Sun, 25 Nov 2007 18:55:52 +0100
parents 5ba6d286c941
children 56a21f3e5d3e
line wrap: on
line diff
--- 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<llvm::Function>(gIR->ctors[0]->llvmValue);
+
+    std::string name("_D");
+    name.append(gIR->dmodule->mangle());
+    name.append("6__ctorZ");
+
+    std::vector<const llvm::Type*> 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<n; i++) {
+        llvm::Function* f = llvm::cast<llvm::Function>(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<llvm::Function>(gIR->dtors[0]->llvmValue);
+
+    std::string name("_D");
+    name.append(gIR->dmodule->mangle());
+    name.append("6__dtorZ");
+
+    std::vector<const llvm::Type*> 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<n; i++) {
+        llvm::Function* f = llvm::cast<llvm::Function>(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<llvm::Constant*> 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<llvm::Constant*> 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<llvm::Constant*> 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);
 }
 
 /* ================================================================== */