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