Mercurial > projects > ldc
comparison gen/toobj.cpp @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 299a6b634178 |
children |
comparison
equal
deleted
inserted
replaced
1649:36da40ecbbe0 | 1650:40bd4a0d4870 |
---|---|
12 | 12 |
13 #include "gen/llvm.h" | 13 #include "gen/llvm.h" |
14 #include "llvm/Analysis/Verifier.h" | 14 #include "llvm/Analysis/Verifier.h" |
15 #include "llvm/Bitcode/ReaderWriter.h" | 15 #include "llvm/Bitcode/ReaderWriter.h" |
16 #include "llvm/Module.h" | 16 #include "llvm/Module.h" |
17 #include "llvm/ModuleProvider.h" | |
18 #include "llvm/PassManager.h" | 17 #include "llvm/PassManager.h" |
19 #include "llvm/LinkAllPasses.h" | 18 #include "llvm/LinkAllPasses.h" |
20 #include "llvm/System/Program.h" | 19 #include "llvm/System/Program.h" |
21 #include "llvm/Support/raw_ostream.h" | 20 #include "llvm/Support/raw_ostream.h" |
22 #include "llvm/Support/CommandLine.h" | 21 #include "llvm/Support/CommandLine.h" |
23 #include "llvm/Support/FormattedStream.h" | 22 #include "llvm/Support/FormattedStream.h" |
24 #include "llvm/Target/TargetMachine.h" | 23 #include "llvm/Target/TargetMachine.h" |
24 #include "llvm/CodeGen/MachineCodeEmitter.h" | |
25 | 25 |
26 #include "mars.h" | 26 #include "mars.h" |
27 #include "module.h" | 27 #include "module.h" |
28 #include "mtype.h" | 28 #include "mtype.h" |
29 #include "declaration.h" | 29 #include "declaration.h" |
112 Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n'; | 112 Logger::cout() << "Final data layout: " << global.params.dataLayout << '\n'; |
113 | 113 |
114 // allocate the target abi | 114 // allocate the target abi |
115 gABI = TargetABI::getTarget(); | 115 gABI = TargetABI::getTarget(); |
116 | 116 |
117 #ifndef DISABLE_DEBUG_INFO | |
117 // debug info | 118 // debug info |
118 if (global.params.symdebug) { | 119 if (global.params.symdebug) { |
119 RegisterDwarfSymbols(ir.module); | 120 RegisterDwarfSymbols(ir.module); |
120 DtoDwarfCompileUnit(this); | 121 DtoDwarfCompileUnit(this); |
121 } | 122 } |
123 #endif | |
122 | 124 |
123 // handle invalid 'objectø module | 125 // handle invalid 'objectø module |
124 if (!ClassDeclaration::object) { | 126 if (!ClassDeclaration::object) { |
125 error("is missing 'class Object'"); | 127 error("is missing 'class Object'"); |
126 fatal(); | 128 fatal(); |
127 } | 129 } |
128 if (!ClassDeclaration::classinfo) { | 130 if (!ClassDeclaration::classinfo) { |
129 error("is missing 'class ClassInfo'"); | 131 error("is missing 'class ClassInfo'"); |
130 fatal(); | 132 fatal(); |
131 } | 133 } |
132 | 134 |
133 LLVM_D_InitRuntime(); | 135 LLVM_D_InitRuntime(); |
134 | 136 |
135 // process module members | 137 // process module members |
136 for (int k=0; k < members->dim; k++) { | 138 for (int k=0; k < members->dim; k++) { |
137 Dsymbol* dsym = (Dsymbol*)(members->data[k]); | 139 Dsymbol* dsym = (Dsymbol*)(members->data[k]); |
223 if (global.params.output_bc) { | 225 if (global.params.output_bc) { |
224 LLPath bcpath = LLPath(filename); | 226 LLPath bcpath = LLPath(filename); |
225 bcpath.eraseSuffix(); | 227 bcpath.eraseSuffix(); |
226 bcpath.appendSuffix(std::string(global.bc_ext)); | 228 bcpath.appendSuffix(std::string(global.bc_ext)); |
227 Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); | 229 Logger::println("Writing LLVM bitcode to: %s\n", bcpath.c_str()); |
228 std::ofstream bos(bcpath.c_str(), std::ios::binary); | 230 std::string errinfo; |
229 if (bos.fail()) | 231 llvm::raw_fd_ostream bos(bcpath.c_str(), errinfo, llvm::raw_fd_ostream::F_Binary); |
232 if (bos.has_error()) | |
230 { | 233 { |
231 error("cannot write LLVM bitcode, failed to open file '%s'", bcpath.c_str()); | 234 error("cannot write LLVM bitcode file '%s': %s", bcpath.c_str(), errinfo.c_str()); |
232 fatal(); | 235 fatal(); |
233 } | 236 } |
234 llvm::WriteBitcodeToFile(m, bos); | 237 llvm::WriteBitcodeToFile(m, bos); |
235 } | 238 } |
236 | 239 |
238 if (global.params.output_ll) { | 241 if (global.params.output_ll) { |
239 LLPath llpath = LLPath(filename); | 242 LLPath llpath = LLPath(filename); |
240 llpath.eraseSuffix(); | 243 llpath.eraseSuffix(); |
241 llpath.appendSuffix(std::string(global.ll_ext)); | 244 llpath.appendSuffix(std::string(global.ll_ext)); |
242 Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); | 245 Logger::println("Writing LLVM asm to: %s\n", llpath.c_str()); |
243 std::ofstream aos(llpath.c_str()); | 246 std::string errinfo; |
244 if (aos.fail()) | 247 llvm::raw_fd_ostream aos(llpath.c_str(), errinfo); |
248 if (aos.has_error()) | |
245 { | 249 { |
246 error("cannot write LLVM asm, failed to open file '%s'", llpath.c_str()); | 250 error("cannot write LLVM asm file '%s': %s", llpath.c_str(), errinfo.c_str()); |
247 fatal(); | 251 fatal(); |
248 } | 252 } |
249 m->print(aos, NULL); | 253 m->print(aos, NULL); |
250 } | 254 } |
251 | 255 |
258 spath.createTemporaryFileOnDisk(); | 262 spath.createTemporaryFileOnDisk(); |
259 } | 263 } |
260 Logger::println("Writing native asm to: %s\n", spath.c_str()); | 264 Logger::println("Writing native asm to: %s\n", spath.c_str()); |
261 std::string err; | 265 std::string err; |
262 { | 266 { |
263 llvm::raw_fd_ostream out(spath.c_str(), false, true, err); | 267 llvm::raw_fd_ostream out(spath.c_str(), err); |
264 if (err.empty()) | 268 if (err.empty()) |
265 { | 269 { |
266 write_asm_to_file(*gTargetMachine, *m, out); | 270 write_asm_to_file(*gTargetMachine, *m, out); |
267 } | 271 } |
268 else | 272 else |
290 void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out) | 294 void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out) |
291 { | 295 { |
292 using namespace llvm; | 296 using namespace llvm; |
293 | 297 |
294 // Build up all of the passes that we want to do to the module. | 298 // Build up all of the passes that we want to do to the module. |
295 ExistingModuleProvider Provider(&m); | 299 FunctionPassManager Passes(&m); |
296 FunctionPassManager Passes(&Provider); | |
297 | 300 |
298 if (const TargetData *TD = Target.getTargetData()) | 301 if (const TargetData *TD = Target.getTargetData()) |
299 Passes.add(new TargetData(*TD)); | 302 Passes.add(new TargetData(*TD)); |
300 else | 303 else |
301 Passes.add(new TargetData(&m)); | 304 Passes.add(new TargetData(&m)); |
302 | |
303 // Ask the target to add backend passes as necessary. | |
304 MachineCodeEmitter *MCE = 0; | |
305 | 305 |
306 // Last argument is enum CodeGenOpt::Level OptLevel | 306 // Last argument is enum CodeGenOpt::Level OptLevel |
307 // debug info doesn't work properly with OptLevel != None! | 307 // debug info doesn't work properly with OptLevel != None! |
308 CodeGenOpt::Level LastArg = CodeGenOpt::Default; | 308 CodeGenOpt::Level LastArg = CodeGenOpt::Default; |
309 if (global.params.symdebug || !optimize()) | 309 if (global.params.symdebug || !optimize()) |
310 LastArg = CodeGenOpt::None; | 310 LastArg = CodeGenOpt::None; |
311 else if (optLevel() >= 3) | 311 else if (optLevel() >= 3) |
312 LastArg = CodeGenOpt::Aggressive; | 312 LastArg = CodeGenOpt::Aggressive; |
313 | 313 |
314 llvm::formatted_raw_ostream fout(out); | 314 llvm::formatted_raw_ostream fout(out); |
315 FileModel::Model mod = Target.addPassesToEmitFile(Passes, fout, TargetMachine::AssemblyFile, LastArg); | 315 if (Target.addPassesToEmitFile(Passes, fout, TargetMachine::CGFT_AssemblyFile, LastArg)) |
316 assert(mod == FileModel::AsmFile); | 316 assert(0 && "no support for asm output"); |
317 | |
318 bool err = Target.addPassesToEmitFileFinish(Passes, MCE, LastArg); | |
319 assert(!err); | |
320 | 317 |
321 Passes.doInitialization(); | 318 Passes.doInitialization(); |
322 | 319 |
323 // Run our queue of passes all at once now, efficiently. | 320 // Run our queue of passes all at once now, efficiently. |
324 for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I) | 321 for (llvm::Module::iterator I = m.begin(), E = m.end(); I != E; ++I) |
326 Passes.run(*I); | 323 Passes.run(*I); |
327 | 324 |
328 Passes.doFinalization(); | 325 Passes.doFinalization(); |
329 | 326 |
330 // release module from module provider so we can delete it ourselves | 327 // release module from module provider so we can delete it ourselves |
331 std::string Err; | 328 //std::string Err; |
332 llvm::Module* rmod = Provider.releaseModule(&Err); | 329 //llvm::Module* rmod = Provider.releaseModule(&Err); |
333 assert(rmod); | 330 //assert(rmod); |
334 } | 331 } |
335 | 332 |
336 /* ================================================================== */ | 333 /* ================================================================== */ |
337 | 334 |
338 // uses gcc to make an obj out of an assembly file | 335 // uses gcc to make an obj out of an assembly file |
348 // Note: | 345 // Note: |
349 // We can't just assemble and link the file with the system assembler | 346 // We can't just assemble and link the file with the system assembler |
350 // and linker because we don't know where to put the _start symbol. | 347 // and linker because we don't know where to put the _start symbol. |
351 // GCC mysteriously knows how to do it. | 348 // GCC mysteriously knows how to do it. |
352 std::vector<std::string> args; | 349 std::vector<std::string> args; |
353 args.push_back(gcc.toString()); | 350 args.push_back(gcc.str()); |
354 args.push_back("-fno-strict-aliasing"); | 351 args.push_back("-fno-strict-aliasing"); |
355 args.push_back("-O3"); | 352 args.push_back("-O3"); |
356 args.push_back("-c"); | 353 args.push_back("-c"); |
357 args.push_back("-xassembler"); | 354 args.push_back("-xassembler"); |
358 args.push_back(asmpath.toString()); | 355 args.push_back(asmpath.str()); |
359 args.push_back("-o"); | 356 args.push_back("-o"); |
360 args.push_back(objpath.toString()); | 357 args.push_back(objpath.str()); |
361 | 358 |
362 //FIXME: only use this if needed? | 359 //FIXME: only use this if needed? |
363 args.push_back("-fpic"); | 360 args.push_back("-fpic"); |
364 | 361 |
365 //FIXME: enforce 64 bit | 362 //FIXME: enforce 64 bit |
429 | 426 |
430 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); | 427 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); |
431 IRBuilder<> builder(bb); | 428 IRBuilder<> builder(bb); |
432 | 429 |
433 // debug info | 430 // debug info |
431 #ifndef DISABLE_DEBUG_INFO | |
434 LLGlobalVariable* subprog; | 432 LLGlobalVariable* subprog; |
435 if(global.params.symdebug) { | 433 if(global.params.symdebug) { |
436 subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV(); | 434 subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV(); |
437 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); | 435 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); |
438 } | 436 } |
437 #endif | |
439 | 438 |
440 for (size_t i=0; i<n; i++) { | 439 for (size_t i=0; i<n; i++) { |
441 llvm::Function* f = gIR->ctors[i]->ir.irFunc->func; | 440 llvm::Function* f = gIR->ctors[i]->ir.irFunc->func; |
442 llvm::CallInst* call = builder.CreateCall(f,""); | 441 llvm::CallInst* call = builder.CreateCall(f,""); |
443 call->setCallingConv(DtoCallingConv(0, LINKd)); | 442 call->setCallingConv(DtoCallingConv(0, LINKd)); |
444 } | 443 } |
445 | 444 |
446 // debug info end | 445 // debug info end |
446 #ifndef DISABLE_DEBUG_INFO | |
447 if(global.params.symdebug) | 447 if(global.params.symdebug) |
448 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); | 448 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); |
449 #endif | |
449 | 450 |
450 builder.CreateRetVoid(); | 451 builder.CreateRetVoid(); |
451 return fn; | 452 return fn; |
452 } | 453 } |
453 | 454 |
473 fn->setCallingConv(DtoCallingConv(0, LINKd)); | 474 fn->setCallingConv(DtoCallingConv(0, LINKd)); |
474 | 475 |
475 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); | 476 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); |
476 IRBuilder<> builder(bb); | 477 IRBuilder<> builder(bb); |
477 | 478 |
479 #ifndef DISABLE_DEBUG_INFO | |
478 // debug info | 480 // debug info |
479 LLGlobalVariable* subprog; | 481 LLGlobalVariable* subprog; |
480 if(global.params.symdebug) { | 482 if(global.params.symdebug) { |
481 subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV(); | 483 subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV(); |
482 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); | 484 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); |
483 } | 485 } |
486 #endif | |
484 | 487 |
485 for (size_t i=0; i<n; i++) { | 488 for (size_t i=0; i<n; i++) { |
486 llvm::Function* f = gIR->dtors[i]->ir.irFunc->func; | 489 llvm::Function* f = gIR->dtors[i]->ir.irFunc->func; |
487 llvm::CallInst* call = builder.CreateCall(f,""); | 490 llvm::CallInst* call = builder.CreateCall(f,""); |
488 call->setCallingConv(DtoCallingConv(0, LINKd)); | 491 call->setCallingConv(DtoCallingConv(0, LINKd)); |
489 } | 492 } |
490 | 493 |
494 #ifndef DISABLE_DEBUG_INFO | |
491 // debug info end | 495 // debug info end |
492 if(global.params.symdebug) | 496 if(global.params.symdebug) |
493 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); | 497 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); |
498 #endif | |
494 | 499 |
495 builder.CreateRetVoid(); | 500 builder.CreateRetVoid(); |
496 return fn; | 501 return fn; |
497 } | 502 } |
498 | 503 |
518 fn->setCallingConv(DtoCallingConv(0, LINKd)); | 523 fn->setCallingConv(DtoCallingConv(0, LINKd)); |
519 | 524 |
520 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); | 525 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "entry", fn); |
521 IRBuilder<> builder(bb); | 526 IRBuilder<> builder(bb); |
522 | 527 |
528 #ifndef DISABLE_DEBUG_INFO | |
523 // debug info | 529 // debug info |
524 LLGlobalVariable* subprog; | 530 LLGlobalVariable* subprog; |
525 if(global.params.symdebug) { | 531 if(global.params.symdebug) { |
526 subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV(); | 532 subprog = DtoDwarfSubProgramInternal(name.c_str(), name.c_str()).getGV(); |
527 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); | 533 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); |
528 } | 534 } |
535 #endif | |
529 | 536 |
530 for (size_t i=0; i<n; i++) { | 537 for (size_t i=0; i<n; i++) { |
531 llvm::Function* f = gIR->unitTests[i]->ir.irFunc->func; | 538 llvm::Function* f = gIR->unitTests[i]->ir.irFunc->func; |
532 llvm::CallInst* call = builder.CreateCall(f,""); | 539 llvm::CallInst* call = builder.CreateCall(f,""); |
533 call->setCallingConv(DtoCallingConv(0, LINKd)); | 540 call->setCallingConv(DtoCallingConv(0, LINKd)); |
534 } | 541 } |
535 | 542 |
543 #ifndef DISABLE_DEBUG_INFO | |
536 // debug info end | 544 // debug info end |
537 if(global.params.symdebug) | 545 if(global.params.symdebug) |
538 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); | 546 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); |
547 #endif | |
539 | 548 |
540 builder.CreateRetVoid(); | 549 builder.CreateRetVoid(); |
541 return fn; | 550 return fn; |
542 } | 551 } |
543 | 552 |
576 // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list | 585 // make the function insert this moduleinfo as the beginning of the _Dmodule_ref linked list |
577 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor); | 586 llvm::BasicBlock* bb = llvm::BasicBlock::Create(gIR->context(), "moduleinfoCtorEntry", ctor); |
578 IRBuilder<> builder(bb); | 587 IRBuilder<> builder(bb); |
579 | 588 |
580 // debug info | 589 // debug info |
590 #ifndef DISABLE_DEBUG_INFO | |
581 LLGlobalVariable* subprog; | 591 LLGlobalVariable* subprog; |
582 if(global.params.symdebug) { | 592 if(global.params.symdebug) { |
583 subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()).getGV(); | 593 subprog = DtoDwarfSubProgramInternal(fname.c_str(), fname.c_str()).getGV(); |
584 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); | 594 builder.CreateCall(gIR->module->getFunction("llvm.dbg.func.start"), DBG_CAST(subprog)); |
585 } | 595 } |
596 #endif | |
586 | 597 |
587 // get current beginning | 598 // get current beginning |
588 LLValue* curbeg = builder.CreateLoad(mref, "current"); | 599 LLValue* curbeg = builder.CreateLoad(mref, "current"); |
589 | 600 |
590 // put current beginning as the next of this one | 601 // put current beginning as the next of this one |
592 builder.CreateStore(curbeg, gep); | 603 builder.CreateStore(curbeg, gep); |
593 | 604 |
594 // replace beginning | 605 // replace beginning |
595 builder.CreateStore(thismref, mref); | 606 builder.CreateStore(thismref, mref); |
596 | 607 |
608 #ifndef DISABLE_DEBUG_INFO | |
597 // debug info end | 609 // debug info end |
598 if(global.params.symdebug) | 610 if(global.params.symdebug) |
599 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); | 611 builder.CreateCall(gIR->module->getFunction("llvm.dbg.region.end"), DBG_CAST(subprog)); |
612 #endif | |
600 | 613 |
601 // return | 614 // return |
602 builder.CreateRetVoid(); | 615 builder.CreateRetVoid(); |
603 | 616 |
604 return ctor; | 617 return ctor; |
612 // { | 625 // { |
613 // char[] name; | 626 // char[] name; |
614 // ModuleInfo[] importedModules; | 627 // ModuleInfo[] importedModules; |
615 // ClassInfo[] localClasses; | 628 // ClassInfo[] localClasses; |
616 // uint flags; | 629 // uint flags; |
617 // | 630 // |
618 // void function() ctor; | 631 // void function() ctor; |
619 // void function() dtor; | 632 // void function() dtor; |
620 // void function() unitTest; | 633 // void function() unitTest; |
621 // | 634 // |
622 // void* xgetMembers; | 635 // void* xgetMembers; |
623 // void function() ictor; | 636 // void function() ictor; |
624 // | 637 // |
625 // version(D_Version2) | 638 // version(D_Version2) |
626 // void*[4] reserved; // useless to us | 639 // void*[4] reserved; // useless to us |