1 //===- MCLDTargetMachine.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/Target/TargetMachine.h>
10
11 #include <mcld/Module.h>
12 #include <mcld/LinkerConfig.h>
13 #include <mcld/CodeGen/MCLinker.h>
14 #include <mcld/Support/raw_mem_ostream.h>
15 #include <mcld/Support/TargetRegistry.h>
16 #include <mcld/Support/ToolOutputFile.h>
17 #include <mcld/Support/MemoryArea.h>
18 #include <mcld/Target/TargetLDBackend.h>
19
20 #include <llvm/ADT/OwningPtr.h>
21 #include <llvm/Analysis/Passes.h>
22 #include <llvm/Analysis/Verifier.h>
23 #include <llvm/Assembly/PrintModulePass.h>
24 #include <llvm/CodeGen/AsmPrinter.h>
25 #include <llvm/CodeGen/MachineFunctionAnalysis.h>
26 #include <llvm/CodeGen/MachineModuleInfo.h>
27 #include <llvm/CodeGen/GCStrategy.h>
28 #include <llvm/CodeGen/Passes.h>
29 #include <llvm/IR/DataLayout.h>
30 #include <llvm/MC/MCAsmInfo.h>
31 #include <llvm/MC/MCStreamer.h>
32 #include <llvm/MC/MCInstrInfo.h>
33 #include <llvm/MC/MCSubtargetInfo.h>
34 #include <llvm/MC/MCObjectStreamer.h>
35 #include <llvm/MC/MCAssembler.h>
36 #include <llvm/MC/MCObjectWriter.h>
37 #include <llvm/MC/MCContext.h>
38 #include <llvm/PassManager.h>
39 #include <llvm/Support/CommandLine.h>
40 #include <llvm/Support/Debug.h>
41 #include <llvm/Support/TargetRegistry.h>
42 #include <llvm/Support/FormattedStream.h>
43 #include <llvm/Target/TargetInstrInfo.h>
44 #include <llvm/Target/TargetLowering.h>
45 #include <llvm/Target/TargetOptions.h>
46 #include <llvm/Target/TargetSubtargetInfo.h>
47 #include <llvm/Target/TargetLoweringObjectFile.h>
48 #include <llvm/Target/TargetRegisterInfo.h>
49 #include <llvm/Transforms/Scalar.h>
50
51 #include <string>
52
53 using namespace mcld;
54 using namespace llvm;
55
56 //===----------------------------------------------------------------------===//
57 /// Arguments
58 //===----------------------------------------------------------------------===//
59 // Enable or disable FastISel. Both options are needed, because
60 // FastISel is enabled by default with -fast, and we wish to be
61 // able to enable or disable fast-isel independently from -O0.
62
63 static cl::opt<cl::boolOrDefault>
64 ArgEnableFastISelOption("lfast-isel", cl::Hidden,
65 cl::desc("Enable the \"fast\" instruction selector"));
66
67 static cl::opt<bool>
68 ArgShowMCEncoding("lshow-mc-encoding",
69 cl::Hidden,
70 cl::desc("Show encoding in .s output"));
71
72 static cl::opt<bool>
73 ArgShowMCInst("lshow-mc-inst",
74 cl::Hidden,
75 cl::desc("Show instruction structure in .s output"));
76
77 static cl::opt<cl::boolOrDefault>
78 ArgAsmVerbose("fverbose-asm",
79 cl::desc("Put extra commentary information in the \
80 generated assembly code to make it more readable."),
81 cl::init(cl::BOU_UNSET));
82
getVerboseAsm()83 static bool getVerboseAsm() {
84 switch (ArgAsmVerbose) {
85 default:
86 case cl::BOU_UNSET: return TargetMachine::getAsmVerbosityDefault();
87 case cl::BOU_TRUE: return true;
88 case cl::BOU_FALSE: return false;
89 }
90 }
91
92
93 //===---------------------------------------------------------------------===//
94 /// MCLDTargetMachine
95 //===----------------------------------------------------------------------===//
MCLDTargetMachine(llvm::TargetMachine & pTM,const mcld::Target & pTarget,const std::string & pTriple)96 mcld::MCLDTargetMachine::MCLDTargetMachine(llvm::TargetMachine &pTM,
97 const mcld::Target& pTarget,
98 const std::string& pTriple)
99 : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) {
100 }
101
~MCLDTargetMachine()102 mcld::MCLDTargetMachine::~MCLDTargetMachine() {
103 m_pTarget = 0;
104 }
105
getTarget() const106 const mcld::Target& mcld::MCLDTargetMachine::getTarget() const
107 {
108 return *m_pTarget;
109 }
110
111 /// Turn exception handling constructs into something the code generators can
112 /// handle.
addPassesToHandleExceptions(llvm::TargetMachine * TM,PassManagerBase & PM)113 static void addPassesToHandleExceptions(llvm::TargetMachine *TM,
114 PassManagerBase &PM) {
115 switch (TM->getMCAsmInfo()->getExceptionHandlingType()) {
116 case llvm::ExceptionHandling::SjLj:
117 // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
118 // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
119 // catch info can get misplaced when a selector ends up more than one block
120 // removed from the parent invoke(s). This could happen when a landing
121 // pad is shared by multiple invokes and is also a target of a normal
122 // edge from elsewhere.
123 PM.add(createSjLjEHPreparePass(TM->getTargetLowering()));
124 // FALLTHROUGH
125 case llvm::ExceptionHandling::DwarfCFI:
126 case llvm::ExceptionHandling::ARM:
127 case llvm::ExceptionHandling::Win64:
128 PM.add(createDwarfEHPass(TM->getTargetLowering()));
129 break;
130 case llvm::ExceptionHandling::None:
131 PM.add(createLowerInvokePass(TM->getTargetLowering()));
132
133 // The lower invoke pass may create unreachable code. Remove it.
134 PM.add(createUnreachableBlockEliminationPass());
135 break;
136 }
137 }
138
139
addPassesToGenerateCode(llvm::LLVMTargetMachine * TM,PassManagerBase & PM,bool DisableVerify)140 static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
141 PassManagerBase &PM,
142 bool DisableVerify)
143 {
144 // Targets may override createPassConfig to provide a target-specific sublass.
145 TargetPassConfig *PassConfig = TM->createPassConfig(PM);
146
147 // Set PassConfig options provided by TargetMachine.
148 PassConfig->setDisableVerify(DisableVerify);
149
150 PM.add(PassConfig);
151
152 PassConfig->addIRPasses();
153
154 addPassesToHandleExceptions(TM, PM);
155
156 PassConfig->addISelPrepare();
157
158 // Install a MachineModuleInfo class, which is an immutable pass that holds
159 // all the per-module stuff we're generating, including MCContext.
160 MachineModuleInfo *MMI =
161 new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(),
162 &TM->getTargetLowering()->getObjFileLowering());
163 PM.add(MMI);
164 MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref.
165
166 // Set up a MachineFunction for the rest of CodeGen to work on.
167 PM.add(new MachineFunctionAnalysis(*TM));
168
169 // Enable FastISel with -fast, but allow that to be overridden.
170 if (ArgEnableFastISelOption == cl::BOU_TRUE ||
171 (TM->getOptLevel() == CodeGenOpt::None &&
172 ArgEnableFastISelOption != cl::BOU_FALSE))
173 TM->setFastISel(true);
174
175 // Ask the target for an isel.
176 if (PassConfig->addInstSelector())
177 return NULL;
178
179 PassConfig->addMachinePasses();
180
181 PassConfig->setInitialized();
182
183 return Context;
184
185 }
186
addPassesToEmitFile(PassManagerBase & pPM,mcld::ToolOutputFile & pOutput,mcld::CodeGenFileType pFileType,CodeGenOpt::Level pOptLvl,mcld::Module & pModule,LinkerConfig & pConfig,bool pDisableVerify)187 bool mcld::MCLDTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
188 mcld::ToolOutputFile& pOutput,
189 mcld::CodeGenFileType pFileType,
190 CodeGenOpt::Level pOptLvl,
191 mcld::Module& pModule,
192 LinkerConfig& pConfig,
193 bool pDisableVerify)
194 {
195
196 llvm::MCContext* Context =
197 addPassesToGenerateCode(static_cast<llvm::LLVMTargetMachine*>(&m_TM),
198 pPM, pDisableVerify);
199 if (!Context)
200 return true;
201
202 switch(pFileType) {
203 default:
204 case mcld::CGFT_NULLFile:
205 assert(0 && "fatal: file type is not set!");
206 break;
207 case CGFT_ASMFile: {
208 assert(Context != 0 && "Failed to get MCContext");
209
210 if (getTM().hasMCSaveTempLabels())
211 Context->setAllowTemporaryLabels(false);
212
213 if (addCompilerPasses(pPM,
214 pOutput.formatted_os(),
215 Context))
216 return true;
217 break;
218 }
219 case CGFT_OBJFile: {
220 assert(Context != 0 && "Failed to get MCContext");
221
222 if (getTM().hasMCSaveTempLabels())
223 Context->setAllowTemporaryLabels(false);
224 if (addAssemblerPasses(pPM,
225 pOutput.mem_os(),
226 Context))
227 return true;
228 break;
229 }
230 case CGFT_EXEFile: {
231 pConfig.setCodeGenType(LinkerConfig::Exec);
232 if (addLinkerPasses(pPM,
233 pConfig,
234 pModule,
235 pOutput.memory(),
236 Context))
237 return true;
238 break;
239 }
240 case CGFT_BINARY: {
241 pConfig.setCodeGenType(LinkerConfig::Binary);
242 if (addLinkerPasses(pPM,
243 pConfig,
244 pModule,
245 pOutput.memory(),
246 Context))
247 return true;
248 break;
249 }
250 case CGFT_DSOFile: {
251 pConfig.setCodeGenType(LinkerConfig::DynObj);
252 if (addLinkerPasses(pPM,
253 pConfig,
254 pModule,
255 pOutput.memory(),
256 Context))
257 return true;
258 break;
259 }
260 case CGFT_PARTIAL: {
261 pConfig.setCodeGenType(LinkerConfig::Object);
262 if (addLinkerPasses(pPM,
263 pConfig,
264 pModule,
265 pOutput.memory(),
266 Context))
267 return true;
268 break;
269 }
270 } // switch
271 return false;
272 }
273
addCompilerPasses(PassManagerBase & pPM,llvm::formatted_raw_ostream & pOutput,llvm::MCContext * & Context)274 bool mcld::MCLDTargetMachine::addCompilerPasses(PassManagerBase &pPM,
275 llvm::formatted_raw_ostream &pOutput,
276 llvm::MCContext *&Context)
277 {
278 const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
279 const MCInstrInfo &MII = *getTM().getInstrInfo();
280 const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
281 const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
282
283 MCInstPrinter *InstPrinter =
284 getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
285 MII,
286 Context->getRegisterInfo(), STI);
287
288 MCCodeEmitter* MCE = 0;
289 MCAsmBackend *MAB = 0;
290 if (ArgShowMCEncoding) {
291 MCE = getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
292 MAB = getTarget().get()->createMCAsmBackend(m_Triple,
293 getTM().getTargetCPU());
294 }
295
296
297 // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
298 OwningPtr<MCStreamer> AsmStreamer(
299 getTarget().get()->createAsmStreamer(*Context, pOutput,
300 getVerboseAsm(),
301 getTM().hasMCUseLoc(),
302 getTM().hasMCUseCFI(),
303 getTM().hasMCUseDwarfDirectory(),
304 InstPrinter,
305 MCE, MAB,
306 ArgShowMCInst));
307
308 llvm::MachineFunctionPass* funcPass =
309 getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer.get());
310
311 if (funcPass == 0)
312 return true;
313 // If successful, createAsmPrinter took ownership of AsmStreamer
314 AsmStreamer.take();
315 pPM.add(funcPass);
316 return false;
317 }
318
addAssemblerPasses(PassManagerBase & pPM,llvm::raw_ostream & pOutput,llvm::MCContext * & Context)319 bool mcld::MCLDTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
320 llvm::raw_ostream &pOutput,
321 llvm::MCContext *&Context)
322 {
323 // MCCodeEmitter
324 const MCInstrInfo &MII = *getTM().getInstrInfo();
325 const MCRegisterInfo &MRI = *getTM().getRegisterInfo();
326 const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
327 MCCodeEmitter* MCE =
328 getTarget().get()->createMCCodeEmitter(MII, MRI, STI, *Context);
329
330 // MCAsmBackend
331 MCAsmBackend* MAB =
332 getTarget().get()->createMCAsmBackend(m_Triple,getTM().getTargetCPU());
333 if (MCE == 0 || MAB == 0)
334 return true;
335
336 // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
337 OwningPtr<MCStreamer> AsmStreamer(getTarget().get()->createMCObjectStreamer(
338 m_Triple,
339 *Context,
340 *MAB,
341 pOutput,
342 MCE,
343 getTM().hasMCRelaxAll(),
344 getTM().hasMCNoExecStack()));
345 AsmStreamer.get()->InitSections();
346 MachineFunctionPass *funcPass = getTarget().get()->createAsmPrinter(getTM(),
347 *AsmStreamer.get());
348 if (funcPass == 0)
349 return true;
350 // If successful, createAsmPrinter took ownership of AsmStreamer
351 AsmStreamer.take();
352 pPM.add(funcPass);
353 return false;
354 }
355
addLinkerPasses(PassManagerBase & pPM,LinkerConfig & pConfig,mcld::Module & pModule,mcld::MemoryArea & pOutput,llvm::MCContext * & Context)356 bool mcld::MCLDTargetMachine::addLinkerPasses(PassManagerBase &pPM,
357 LinkerConfig& pConfig,
358 mcld::Module& pModule,
359 mcld::MemoryArea& pOutput,
360 llvm::MCContext *&Context)
361 {
362 if (NULL == pOutput.handler())
363 return true;
364
365 // set up output's SOName
366 if (pConfig.options().soname().empty()) {
367 // if the output is a shared object, and the option -soname was not
368 // enable, set soname as the output file name. soname must be UTF-8 string.
369 pModule.setName(pOutput.handler()->path().filename().native());
370 }
371 else {
372 pModule.setName(pConfig.options().soname());
373 }
374
375 MachineFunctionPass* funcPass = getTarget().createMCLinker(m_Triple,
376 pConfig,
377 pModule,
378 pOutput);
379 if (NULL == funcPass)
380 return true;
381
382 pPM.add(funcPass);
383 return false;
384 }
385
386