| //===- 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; |
| } |