//===- main.cpp -----------------------------------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include <mcld/PreferenceOptions.h> #include <mcld/TripleOptions.h> #include <mcld/DynamicSectionOptions.h> #include <mcld/OutputFormatOptions.h> #include <mcld/SearchPathOptions.h> #include <mcld/OptimizationOptions.h> #include <mcld/SymbolOptions.h> #include <mcld/TargetControlOptions.h> #include <mcld/ScriptOptions.h> #include <mcld/PositionalOptions.h> #include <mcld/Module.h> #include <mcld/Environment.h> #include <mcld/LinkerConfig.h> #include <mcld/LinkerScript.h> #include <mcld/Linker.h> #include <mcld/IRBuilder.h> #include <mcld/MC/InputAction.h> #include <mcld/Support/raw_ostream.h> #include <mcld/Support/MsgHandling.h> #include <llvm/Support/ManagedStatic.h> #include <llvm/Support/Signals.h> #include <string> #include <cassert> /// configure linker static inline bool ConfigLinker(int pArgc, char* pArgv[], const char* pName, mcld::Module& pModule, mcld::LinkerScript& pScript, mcld::LinkerConfig& pConfig, mcld::IRBuilder& pBuilder, std::vector<mcld::InputAction*>& pInputActions) { mcld::PreferenceOptions preference; mcld::TripleOptions triple; mcld::DynamicSectionOptions dynamic_section; mcld::OutputFormatOptions output_format; mcld::SearchPathOptions search_path; mcld::OptimizationOptions optimization; mcld::SymbolOptions symbol; mcld::TargetControlOptions target_control; mcld::ScriptOptions script; mcld::PositionalOptions positional; llvm::cl::ParseCommandLineOptions(pArgc, pArgv, pName); if (!preference.parse(pConfig)) return false; if (!triple.parse(pArgc, pArgv, pConfig)) return false; if (!dynamic_section.parse(pConfig, pScript)) return false; if (!output_format.parse(pModule, pConfig)) return false; if (!search_path.parse(pConfig, pScript)) return false; if (!optimization.parse(pConfig)) return false; if (!symbol.parse(pConfig)) return false; if (!target_control.parse(pConfig)) return false; if (!script.parse(pScript)) return false; if (!positional.parse(pInputActions, pConfig, pScript)) return false; if (pConfig.options().soname().empty()) pConfig.options().setSOName(pModule.name()); return true; } static inline bool InitializeInputs(mcld::IRBuilder& pBuilder, std::vector<mcld::InputAction*>& pInputActions) { for (std::vector<mcld::InputAction*>::iterator action = pInputActions.begin(), actionEnd = pInputActions.end(); action != actionEnd; ++action) { assert(*action != NULL); (*action)->activate(pBuilder.getInputBuilder()); delete *action; } if (pBuilder.getInputBuilder().isInGroup()) { mcld::fatal(mcld::diag::fatal_forbid_nest_group); return false; } return true; } int main(int argc, char* argv[]) { llvm::sys::PrintStackTraceOnErrorSignal(); llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. mcld::Initialize(); mcld::LinkerScript script; mcld::LinkerConfig config; mcld::Module module(script); mcld::IRBuilder builder(module, config); std::vector<mcld::InputAction*> input_actions; if (!ConfigLinker(argc, argv, "MCLinker\n", module, script, config, builder, input_actions)) { mcld::errs() << argv[0] << ": failed to process linker options from command line!\n"; return 1; } mcld::Linker linker; if (!linker.emulate(script, config)) { mcld::errs() << argv[0] << ": failed to emulate target!\n"; return 1; } // FIXME: is it possible to have a lightweight MCLinker pass? if (!InitializeInputs(builder, input_actions)) { mcld::errs() << argv[0] << ": failed to initialize input tree!\n"; return 1; } if (!linker.link(module, builder)) { mcld::errs() << argv[0] << ": failed to link objects!\n"; return 1; } if (!linker.emit(module, module.name())) { mcld::errs() << argv[0] << ": failed to emit output!\n"; return 1; } mcld::Finalize(); return 0; }