Changeset 1052:12ea38902e83
- 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
| r957 |
r1052 |
|
| 31 | 31 | struct DValue; |
|---|
| 32 | 32 | typedef DValue elem; |
|---|
| | 33 | namespace llvm { class Module; } |
|---|
| 33 | 34 | #else |
|---|
| 34 | 35 | #ifdef IN_GCC |
|---|
| … | … | |
| 134 | 135 | void genhdrfile(); // generate D import file |
|---|
| 135 | 136 | #endif |
|---|
| 136 | | void genobjfile(int multiobj); |
|---|
| 137 | 137 | // void gensymfile(); |
|---|
| 138 | 138 | void gendocfile(); |
|---|
| … | … | |
| 172 | 172 | |
|---|
| 173 | 173 | // LDC |
|---|
| | 174 | llvm::Module* genLLVMModule(int multiobj); |
|---|
| 174 | 175 | void buildTargetFiles(); |
|---|
| 175 | 176 | File* buildFilePath(char* forcename, char* path, char* ext); |
|---|
| r1033 |
r1052 |
|
| 5 | 5 | |
|---|
| 6 | 6 | #include "gen/llvm.h" |
|---|
| | 7 | #include "llvm/Linker.h" |
|---|
| 7 | 8 | #include "llvm/Target/SubtargetFeature.h" |
|---|
| 8 | 9 | #include "llvm/Target/TargetMachine.h" |
|---|
| … | … | |
| 33 | 34 | #include "gen/linker.h" |
|---|
| 34 | 35 | #include "gen/irstate.h" |
|---|
| | 36 | #include "gen/toobj.h" |
|---|
| 35 | 37 | |
|---|
| 36 | 38 | #include "gen/cl_options.h" |
|---|
| … | … | |
| 41 | 43 | extern void backend_init(); |
|---|
| 42 | 44 | extern void backend_term(); |
|---|
| | 45 | |
|---|
| | 46 | static cl::opt<bool> singleObj("singleobj", |
|---|
| | 47 | cl::desc("Create only a single output object file"), |
|---|
| | 48 | cl::ZeroOrMore); |
|---|
| 43 | 49 | |
|---|
| 44 | 50 | static cl::opt<bool> noDefaultLib("nodefaultlib", |
|---|
| … | … | |
| 797 | 803 | fatal(); |
|---|
| 798 | 804 | |
|---|
| | 805 | // collects llvm modules to be linked if singleobj is passed |
|---|
| | 806 | std::vector<llvm::Module*> llvmModules; |
|---|
| | 807 | |
|---|
| 799 | 808 | // Generate output files |
|---|
| 800 | 809 | for (int i = 0; i < modules.dim; i++) |
|---|
| … | … | |
| 805 | 814 | if (global.params.obj) |
|---|
| 806 | 815 | { |
|---|
| 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); |
|---|
| 809 | 826 | } |
|---|
| 810 | 827 | if (global.errors) |
|---|
| … | … | |
| 816 | 833 | } |
|---|
| 817 | 834 | } |
|---|
| 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 | |
|---|
| 819 | 863 | backend_term(); |
|---|
| 820 | 864 | if (global.errors) |
|---|
| r1026 |
r1052 |
|
| 71 | 71 | ////////////////////////////////////////////////////////////////////////////////////////// |
|---|
| 72 | 72 | |
|---|
| 73 | | void Module::genobjfile(int multiobj) |
|---|
| | 73 | llvm::Module* Module::genLLVMModule(int multiobj) |
|---|
| 74 | 74 | { |
|---|
| 75 | 75 | bool logenabled = Logger::enabled(); |
|---|
| … | … | |
| 85 | 85 | |
|---|
| 86 | 86 | assert(!global.errors); |
|---|
| 87 | | |
|---|
| 88 | | // start by deleting the old object file |
|---|
| 89 | | deleteObjFile(); |
|---|
| 90 | 87 | |
|---|
| 91 | 88 | // name the module |
|---|
| … | … | |
| 175 | 172 | } |
|---|
| 176 | 173 | |
|---|
| | 174 | gIR = NULL; |
|---|
| | 175 | |
|---|
| | 176 | if (llvmForceLogging && !logenabled) |
|---|
| | 177 | { |
|---|
| | 178 | Logger::disable(); |
|---|
| | 179 | } |
|---|
| | 180 | |
|---|
| | 181 | return ir.module; |
|---|
| | 182 | } |
|---|
| | 183 | |
|---|
| | 184 | void writeModule(llvm::Module* m, std::string filename) |
|---|
| | 185 | { |
|---|
| 177 | 186 | // 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); |
|---|
| 179 | 188 | |
|---|
| 180 | 189 | // verify the llvm |
|---|
| … | … | |
| 183 | 192 | Logger::println("Verifying module... again..."); |
|---|
| 184 | 193 | LOG_SCOPE; |
|---|
| 185 | | if (llvm::verifyModule(*ir.module,llvm::ReturnStatusAction,&verifyErr)) |
|---|
| | 194 | if (llvm::verifyModule(*m,llvm::ReturnStatusAction,&verifyErr)) |
|---|
| 186 | 195 | { |
|---|
| 187 | | error("%s", verifyErr.c_str()); |
|---|
| | 196 | //error("%s", verifyErr.c_str()); |
|---|
| 188 | 197 | fatal(); |
|---|
| 189 | 198 | } |
|---|
| … | … | |
| 198 | 207 | // write LLVM bitcode |
|---|
| 199 | 208 | if (global.params.output_bc) { |
|---|
| 200 | | LLPath bcpath = LLPath(objfile->name->toChars()); |
|---|
| | 209 | LLPath bcpath = LLPath(filename); |
|---|
| 201 | 210 | bcpath.eraseSuffix(); |
|---|
| 202 | 211 | bcpath.appendSuffix(std::string(global.bc_ext)); |
|---|
| 203 | 212 | Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); |
|---|
| 204 | 213 | std::ofstream bos(bcpath.c_str(), std::ios::binary); |
|---|
| 205 | | llvm::WriteBitcodeToFile(ir.module, bos); |
|---|
| | 214 | llvm::WriteBitcodeToFile(m, bos); |
|---|
| 206 | 215 | } |
|---|
| 207 | 216 | |
|---|
| 208 | 217 | // write LLVM IR |
|---|
| 209 | 218 | if (global.params.output_ll) { |
|---|
| 210 | | LLPath llpath = LLPath(objfile->name->toChars()); |
|---|
| | 219 | LLPath llpath = LLPath(filename); |
|---|
| 211 | 220 | llpath.eraseSuffix(); |
|---|
| 212 | 221 | llpath.appendSuffix(std::string(global.ll_ext)); |
|---|
| 213 | 222 | Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); |
|---|
| 214 | 223 | std::ofstream aos(llpath.c_str()); |
|---|
| 215 | | ir.module->print(aos, NULL); |
|---|
| | 224 | m->print(aos, NULL); |
|---|
| 216 | 225 | } |
|---|
| 217 | 226 | |
|---|
| 218 | 227 | // write native assembly |
|---|
| 219 | 228 | if (global.params.output_s || global.params.output_o) { |
|---|
| 220 | | LLPath spath = LLPath(objfile->name->toChars()); |
|---|
| | 229 | LLPath spath = LLPath(filename); |
|---|
| 221 | 230 | spath.eraseSuffix(); |
|---|
| 222 | 231 | spath.appendSuffix(std::string(global.s_ext)); |
|---|
| … | … | |
| 228 | 237 | { |
|---|
| 229 | 238 | 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); |
|---|
| 231 | 240 | } |
|---|
| 232 | 241 | |
|---|
| 233 | 242 | // call gcc to convert assembly to object file |
|---|
| 234 | 243 | if (global.params.output_o) { |
|---|
| 235 | | LLPath objpath = LLPath(objfile->name->toChars()); |
|---|
| | 244 | LLPath objpath = LLPath(filename); |
|---|
| 236 | 245 | assemble(spath, objpath); |
|---|
| 237 | 246 | } |
|---|
| … | … | |
| 240 | 249 | spath.eraseFromDisk(); |
|---|
| 241 | 250 | } |
|---|
| 242 | | } |
|---|
| 243 | | |
|---|
| 244 | | delete ir.module; |
|---|
| 245 | | gIR = NULL; |
|---|
| 246 | | |
|---|
| 247 | | if (llvmForceLogging && !logenabled) |
|---|
| 248 | | { |
|---|
| 249 | | Logger::disable(); |
|---|
| 250 | 251 | } |
|---|
| 251 | 252 | } |
|---|