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
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)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
InitializeInputs(mcld::IRBuilder & pBuilder,std::vector<mcld::InputAction * > & pInputActions)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
main(int argc,char * argv[])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