main.cpp revision 533eae20118036f425f27bf0536ef0ccbb090b65
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
35static 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
93static
94inline 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
112int 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