Home | History | Annotate | Download | only in mcld
      1 //===- main.cpp -----------------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include <mcld/PreferenceOptions.h>
     10 #include <mcld/TripleOptions.h>
     11 #include <mcld/DynamicSectionOptions.h>
     12 #include <mcld/OutputFormatOptions.h>
     13 #include <mcld/SearchPathOptions.h>
     14 #include <mcld/OptimizationOptions.h>
     15 #include <mcld/SymbolOptions.h>
     16 #include <mcld/TargetControlOptions.h>
     17 #include <mcld/ScriptOptions.h>
     18 #include <mcld/PositionalOptions.h>
     19 
     20 #include <mcld/Module.h>
     21 #include <mcld/Environment.h>
     22 #include <mcld/LinkerConfig.h>
     23 #include <mcld/LinkerScript.h>
     24 #include <mcld/Linker.h>
     25 #include <mcld/IRBuilder.h>
     26 #include <mcld/MC/InputAction.h>
     27 #include <mcld/Support/raw_ostream.h>
     28 #include <mcld/Support/MsgHandling.h>
     29 #include <llvm/Support/ManagedStatic.h>
     30 #include <llvm/Support/Signals.h>
     31 #include <string>
     32 #include <cassert>
     33 
     34 /// configure linker
     35 static inline bool ConfigLinker(int pArgc,
     36                                 char* pArgv[],
     37                                 const char* pName,
     38                                 mcld::Module& pModule,
     39                                 mcld::LinkerScript& pScript,
     40                                 mcld::LinkerConfig& pConfig,
     41                                 mcld::IRBuilder& pBuilder,
     42                                 std::vector<mcld::InputAction*>& pInputActions)
     43 {
     44   mcld::PreferenceOptions     preference;
     45   mcld::TripleOptions         triple;
     46   mcld::DynamicSectionOptions dynamic_section;
     47   mcld::OutputFormatOptions   output_format;
     48   mcld::SearchPathOptions     search_path;
     49   mcld::OptimizationOptions   optimization;
     50   mcld::SymbolOptions         symbol;
     51   mcld::TargetControlOptions  target_control;
     52   mcld::ScriptOptions         script;
     53   mcld::PositionalOptions     positional;
     54 
     55   llvm::cl::ParseCommandLineOptions(pArgc, pArgv, pName);
     56 
     57   if (!preference.parse(pConfig))
     58     return false;
     59 
     60   if (!triple.parse(pArgc, pArgv, pConfig))
     61     return false;
     62 
     63   if (!dynamic_section.parse(pConfig, pScript))
     64     return false;
     65 
     66   if (!output_format.parse(pModule, pConfig))
     67     return false;
     68 
     69   if (!search_path.parse(pConfig, pScript))
     70     return false;
     71 
     72   if (!optimization.parse(pConfig))
     73     return false;
     74 
     75   if (!symbol.parse(pConfig))
     76     return false;
     77 
     78   if (!target_control.parse(pConfig))
     79     return false;
     80 
     81   if (!script.parse(pScript))
     82     return false;
     83 
     84   if (!positional.parse(pInputActions, pConfig, pScript))
     85     return false;
     86 
     87   if (pConfig.options().soname().empty())
     88     pConfig.options().setSOName(pModule.name());
     89 
     90   return true;
     91 }
     92 
     93 static
     94 inline bool InitializeInputs(mcld::IRBuilder& pBuilder,
     95                              std::vector<mcld::InputAction*>& pInputActions)
     96 {
     97   for (std::vector<mcld::InputAction*>::iterator action = pInputActions.begin(),
     98     actionEnd = pInputActions.end(); action != actionEnd; ++action) {
     99     assert(*action != NULL);
    100     (*action)->activate(pBuilder.getInputBuilder());
    101     delete *action;
    102   }
    103 
    104   if (pBuilder.getInputBuilder().isInGroup()) {
    105     mcld::fatal(mcld::diag::fatal_forbid_nest_group);
    106     return false;
    107   }
    108 
    109   return true;
    110 }
    111 
    112 int main(int argc, char* argv[])
    113 {
    114   llvm::sys::PrintStackTraceOnErrorSignal();
    115   llvm::llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
    116   mcld::Initialize();
    117 
    118   mcld::LinkerScript script;
    119   mcld::LinkerConfig config;
    120   mcld::Module module(script);
    121   mcld::IRBuilder builder(module, config);
    122   std::vector<mcld::InputAction*> input_actions;
    123 
    124   if (!ConfigLinker(argc, argv, "MCLinker\n", module, script, config, builder,
    125                     input_actions)) {
    126     mcld::errs() << argv[0]
    127                  << ": failed to process linker options from command line!\n";
    128     return 1;
    129   }
    130 
    131   mcld::Linker linker;
    132   if (!linker.emulate(script, config)) {
    133     mcld::errs() << argv[0]
    134                  << ": failed to emulate target!\n";
    135     return 1;
    136   }
    137 
    138   // FIXME: is it possible to have a lightweight MCLinker pass?
    139   if (!InitializeInputs(builder, input_actions)) {
    140     mcld::errs() << argv[0]
    141                  << ": failed to initialize input tree!\n";
    142     return 1;
    143   }
    144 
    145   if (!linker.link(module, builder)) {
    146     mcld::errs() << argv[0]
    147                  << ": failed to link objects!\n";
    148     return 1;
    149   }
    150 
    151   if (!linker.emit(module, module.name())) {
    152     mcld::errs() << argv[0]
    153                  << ": failed to emit output!\n";
    154     return 1;
    155   }
    156 
    157   mcld::Finalize();
    158 
    159   return 0;
    160 }
    161