From b97b32759e4d04fe468d92d892e1e44b0818d05c Mon Sep 17 00:00:00 2001 From: Alexey Prokhin Date: Mon, 24 Oct 2011 12:16:56 +0400 Subject: [PATCH] Use LLVM Machine Code (MC) to emit object files. Finilize debug info --- gen/main.cpp | 2 +- gen/todebug.cpp | 7 +++ gen/todebug.h | 2 + gen/toobj.cpp | 112 +++++++++++++----------------------------------- 4 files changed, 39 insertions(+), 84 deletions(-) diff --git a/gen/main.cpp b/gen/main.cpp index fb8e7817..8fb984fc 100644 --- a/gen/main.cpp +++ b/gen/main.cpp @@ -438,9 +438,9 @@ int main(int argc, char** argv) llvm::InitializeAllTargetInfos(); llvm::InitializeAllTargets(); llvm::InitializeAllAsmPrinters(); + llvm::InitializeAllAsmParsers(); llvm::InitializeAllTargetMCs(); - const llvm::Target *theTarget = NULL; // Check whether the user has explicitly specified an architecture to compile for. if (mArch.empty()) diff --git a/gen/todebug.cpp b/gen/todebug.cpp index 906f4c72..18db8014 100644 --- a/gen/todebug.cpp +++ b/gen/todebug.cpp @@ -557,4 +557,11 @@ void DtoDwarfValue(LLValue* var, VarDeclaration* vd) instr->setDebugLoc(gIR->ir->getCurrentDebugLocation()); } +////////////////////////////////////////////////////////////////////////////////////////////////// + +void DtoDwarfModuleEnd() +{ + gIR->dibuilder.finalize(); +} + #endif diff --git a/gen/todebug.h b/gen/todebug.h index c78b666a..8518da56 100644 --- a/gen/todebug.h +++ b/gen/todebug.h @@ -48,6 +48,8 @@ void DtoDwarfLocalVariable(LLValue* ll, VarDeclaration* vd); */ llvm::DIGlobalVariable DtoDwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd); +void DtoDwarfModuleEnd(); + #endif // DISABLE_DEBUG_INFO diff --git a/gen/toobj.cpp b/gen/toobj.cpp index 25397fca..1e7737ed 100644 --- a/gen/toobj.cpp +++ b/gen/toobj.cpp @@ -67,8 +67,8 @@ static llvm::cl::opt noVerify("noverify", ////////////////////////////////////////////////////////////////////////////////////////// // fwd decl -void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out); -void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath); +void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& Out, + llvm::TargetMachine::CodeGenFileType fileType); ////////////////////////////////////////////////////////////////////////////////////////// @@ -158,6 +158,12 @@ llvm::Module* Module::genLLVMModule(llvm::LLVMContext& context, Ir* sir) } } + // finilize debugging + #ifndef DISABLE_DEBUG_INFO + if (global.params.symdebug) + DtoDwarfModuleEnd(); + #endif + // generate ModuleInfo genmoduleinfo(); @@ -244,20 +250,17 @@ void writeModule(llvm::Module* m, std::string filename) } // write native assembly - if (global.params.output_s || global.params.output_o) { + if (global.params.output_s) { LLPath spath = LLPath(filename); spath.eraseSuffix(); spath.appendSuffix(std::string(global.s_ext)); - if (!global.params.output_s) { - spath.createTemporaryFileOnDisk(); - } Logger::println("Writing native asm to: %s\n", spath.c_str()); std::string err; { llvm::raw_fd_ostream out(spath.c_str(), err); if (err.empty()) { - write_asm_to_file(*gTargetMachine, *m, out); + emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_AssemblyFile); } else { @@ -265,15 +268,23 @@ void writeModule(llvm::Module* m, std::string filename) fatal(); } } + } - // call gcc to convert assembly to object file - if (global.params.output_o) { - LLPath objpath = LLPath(filename); - assemble(spath, objpath); - } - - if (!global.params.output_s) { - spath.eraseFromDisk(); + if (global.params.output_o) { + LLPath objpath = LLPath(filename); + Logger::println("Writing object file to: %s\n", objpath.c_str()); + std::string err; + { + llvm::raw_fd_ostream out(objpath.c_str(), err); + if (err.empty()) + { + emit_file(*gTargetMachine, *m, out, llvm::TargetMachine::CGFT_ObjectFile); + } + else + { + error("cannot write object file: %s", err.c_str()); + fatal(); + } } } } @@ -281,7 +292,8 @@ void writeModule(llvm::Module* m, std::string filename) /* ================================================================== */ // based on llc code, University of Illinois Open Source License -void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out) +void emit_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_fd_ostream& out, + llvm::TargetMachine::CodeGenFileType fileType) { using namespace llvm; @@ -302,7 +314,7 @@ void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_f LastArg = CodeGenOpt::Aggressive; llvm::formatted_raw_ostream fout(out); - if (Target.addPassesToEmitFile(Passes, fout, TargetMachine::CGFT_AssemblyFile, LastArg)) + if (Target.addPassesToEmitFile(Passes, fout, fileType, LastArg)) assert(0 && "no support for asm output"); Passes.doInitialization(); @@ -320,72 +332,6 @@ void write_asm_to_file(llvm::TargetMachine &Target, llvm::Module& m, llvm::raw_f //assert(rmod); } -/* ================================================================== */ - -// uses gcc to make an obj out of an assembly file -// based on llvm-ld code, University of Illinois Open Source License -void assemble(const llvm::sys::Path& asmpath, const llvm::sys::Path& objpath) -{ - using namespace llvm; - - sys::Path gcc = getGcc(); - - // Run GCC to assemble and link the program into native code. - // - // Note: - // We can't just assemble and link the file with the system assembler - // and linker because we don't know where to put the _start symbol. - // GCC mysteriously knows how to do it. - std::vector args; - args.push_back(gcc.str()); - args.push_back("-fno-strict-aliasing"); - args.push_back("-O3"); - args.push_back("-c"); - args.push_back("-xassembler"); - args.push_back(asmpath.str()); - args.push_back("-o"); - args.push_back(objpath.str()); - - //FIXME: only use this if needed? - args.push_back("-fpic"); - - //FIXME: enforce 64 bit - if (global.params.is64bit) - args.push_back("-m64"); - else - // Assume 32-bit? - args.push_back("-m32"); - - // Now that "args" owns all the std::strings for the arguments, call the c_str - // method to get the underlying string array. We do this game so that the - // std::string array is guaranteed to outlive the const char* array. - std::vector Args; - for (unsigned i = 0, e = args.size(); i != e; ++i) - Args.push_back(args[i].c_str()); - Args.push_back(0); - - if (Logger::enabled()) { - Logger::println("Assembling with: "); - std::vector::const_iterator I = Args.begin(), E = Args.end(); - Stream logstr = Logger::cout(); - for (; I != E; ++I) - if (*I) - logstr << "'" << *I << "'" << " "; - logstr << "\n" << std::flush; - } - - // Run the compiler to assembly the program. - std::string ErrMsg; - int R = sys::Program::ExecuteAndWait( - gcc, &Args[0], 0, 0, 0, 0, &ErrMsg); - if (R) - { - error("Failed to invoke gcc. %s", ErrMsg.c_str()); - fatal(); - } -} - - /* ================================================================== */ static llvm::Function* build_module_function(const std::string &name, const std::list &funcs,