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