• 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/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));
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.
369     pModule.setName(pOutput.handler()->path().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