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