• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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