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