Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Changeset 1052:12ea38902e83

Show
Ignore:
Timestamp:
03/07/09 13:38:00 (3 years ago)
Author:
Christian Kamm <kamm incasoftware de>
branch:
default
Message:

Add '-singleobj' command line switch that will tell LDC to link LLVM modules internally and only emit a single object file.

The switch allows the optimizer and inliner to run on all modules at once and opens the door for template instantiation improvements that should lower compile time and executable size.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • dmd/module.h

    r957 r1052  
    3131struct DValue; 
    3232typedef DValue elem; 
     33namespace llvm { class Module; } 
    3334#else 
    3435#ifdef IN_GCC 
     
    134135    void genhdrfile();  // generate D import file 
    135136#endif 
    136     void genobjfile(int multiobj); 
    137137//    void gensymfile(); 
    138138    void gendocfile(); 
     
    172172 
    173173    // LDC 
     174    llvm::Module* genLLVMModule(int multiobj); 
    174175    void buildTargetFiles(); 
    175176    File* buildFilePath(char* forcename, char* path, char* ext); 
  • gen/main.cpp

    r1033 r1052  
    55 
    66#include "gen/llvm.h" 
     7#include "llvm/Linker.h" 
    78#include "llvm/Target/SubtargetFeature.h" 
    89#include "llvm/Target/TargetMachine.h" 
     
    3334#include "gen/linker.h" 
    3435#include "gen/irstate.h" 
     36#include "gen/toobj.h" 
    3537 
    3638#include "gen/cl_options.h" 
     
    4143extern void backend_init(); 
    4244extern void backend_term(); 
     45 
     46static cl::opt<bool> singleObj("singleobj", 
     47    cl::desc("Create only a single output object file"), 
     48    cl::ZeroOrMore); 
    4349 
    4450static cl::opt<bool> noDefaultLib("nodefaultlib", 
     
    797803        fatal(); 
    798804 
     805    // collects llvm modules to be linked if singleobj is passed 
     806    std::vector<llvm::Module*> llvmModules; 
     807 
    799808    // Generate output files 
    800809    for (int i = 0; i < modules.dim; i++) 
     
    805814        if (global.params.obj) 
    806815        { 
    807             m->genobjfile(0); 
    808             global.params.objfiles->push(m->objfile->name->str); 
     816            llvm::Module* lm = m->genLLVMModule(0); 
     817            if (!singleObj) 
     818            { 
     819                m->deleteObjFile(); 
     820                writeModule(lm, m->objfile->name->str); 
     821                global.params.objfiles->push(m->objfile->name->str); 
     822                delete lm; 
     823            } 
     824            else 
     825                llvmModules.push_back(lm); 
    809826        } 
    810827        if (global.errors) 
     
    816833        } 
    817834    } 
    818  
     835     
     836    // internal linking for singleobj 
     837    if (singleObj && llvmModules.size() > 0) 
     838    { 
     839        Module* m = (Module*)modules.data[0]; 
     840        char* name = m->toChars(); 
     841        char* filename = m->objfile->name->str; 
     842         
     843        llvm::Linker linker(name, name); 
     844        std::string errormsg; 
     845        for (int i = 0; i < llvmModules.size(); i++) 
     846        { 
     847            if(linker.LinkInModule(llvmModules[i], &errormsg)) 
     848                error(errormsg.c_str()); 
     849            delete llvmModules[i]; 
     850        } 
     851         
     852        // workaround for llvm::Linker bug, see llvm #3749 
     853        llvm::GlobalVariable* ctors = linker.getModule()->getGlobalVariable("llvm.global_ctors"); 
     854        if (ctors) 
     855            while (ctors->getNumUses() > 0) 
     856                delete *ctors->use_begin(); 
     857         
     858        m->deleteObjFile(); 
     859        writeModule(linker.getModule(), filename); 
     860        global.params.objfiles->push(filename); 
     861    } 
     862     
    819863    backend_term(); 
    820864    if (global.errors) 
  • gen/toobj.cpp

    r1026 r1052  
    7171////////////////////////////////////////////////////////////////////////////////////////// 
    7272 
    73 void Module::genobjfile(int multiobj) 
     73llvm::Module* Module::genLLVMModule(int multiobj) 
    7474{ 
    7575    bool logenabled = Logger::enabled(); 
     
    8585 
    8686    assert(!global.errors); 
    87  
    88     // start by deleting the old object file 
    89     deleteObjFile(); 
    9087 
    9188    // name the module 
     
    175172    } 
    176173 
     174    gIR = NULL; 
     175     
     176    if (llvmForceLogging && !logenabled) 
     177    { 
     178        Logger::disable(); 
     179    } 
     180     
     181    return ir.module; 
     182} 
     183 
     184void writeModule(llvm::Module* m, std::string filename) 
     185{ 
    177186    // run optimizer 
    178     ldc_optimize_module(ir.module, global.params.optimizeLevel, global.params.llvmInline); 
     187    ldc_optimize_module(m, global.params.optimizeLevel, global.params.llvmInline); 
    179188 
    180189    // verify the llvm 
     
    183192        Logger::println("Verifying module... again..."); 
    184193        LOG_SCOPE; 
    185         if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) 
     194        if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr)) 
    186195        { 
    187             error("%s", verifyErr.c_str()); 
     196            //error("%s", verifyErr.c_str()); 
    188197            fatal(); 
    189198        } 
     
    198207    // write LLVM bitcode 
    199208    if (global.params.output_bc) { 
    200         LLPath bcpath = LLPath(objfile->name->toChars()); 
     209        LLPath bcpath = LLPath(filename); 
    201210        bcpath.eraseSuffix(); 
    202211        bcpath.appendSuffix(std::string(global.bc_ext)); 
    203212        Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); 
    204213        std::ofstream bos(bcpath.c_str(), std::ios::binary); 
    205         llvm::WriteBitcodeToFile(ir.module, bos); 
     214        llvm::WriteBitcodeToFile(m, bos); 
    206215    } 
    207216 
    208217    // write LLVM IR 
    209218    if (global.params.output_ll) { 
    210         LLPath llpath = LLPath(objfile->name->toChars()); 
     219        LLPath llpath = LLPath(filename); 
    211220        llpath.eraseSuffix(); 
    212221        llpath.appendSuffix(std::string(global.ll_ext)); 
    213222        Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); 
    214223        std::ofstream aos(llpath.c_str()); 
    215         ir.module->print(aos, NULL); 
     224        m->print(aos, NULL); 
    216225    } 
    217226 
    218227    // write native assembly 
    219228    if (global.params.output_s || global.params.output_o) { 
    220         LLPath spath = LLPath(objfile->name->toChars()); 
     229        LLPath spath = LLPath(filename); 
    221230        spath.eraseSuffix(); 
    222231        spath.appendSuffix(std::string(global.s_ext)); 
     
    228237        { 
    229238            llvm::raw_fd_ostream out(spath.c_str(), false, err); 
    230             write_asm_to_file(*gTargetMachine, *ir.module, out); 
     239            write_asm_to_file(*gTargetMachine, *m, out); 
    231240        } 
    232241 
    233242        // call gcc to convert assembly to object file 
    234243        if (global.params.output_o) { 
    235             LLPath objpath = LLPath(objfile->name->toChars()); 
     244            LLPath objpath = LLPath(filename); 
    236245            assemble(spath, objpath); 
    237246        } 
     
    240249            spath.eraseFromDisk(); 
    241250        } 
    242     } 
    243  
    244     delete ir.module; 
    245     gIR = NULL; 
    246      
    247     if (llvmForceLogging && !logenabled) 
    248     { 
    249         Logger::disable(); 
    250251    } 
    251252} 
Copyright © 2008, LDC Development Team.