MCLDTargetMachine.cpp revision 888f77e9c8f1a219b43e66dab21fcb45e6baa3e6
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
53using namespace mcld;
54using 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
63static cl::opt<cl::boolOrDefault>
64ArgEnableFastISelOption("lfast-isel", cl::Hidden,
65  cl::desc("Enable the \"fast\" instruction selector"));
66
67static cl::opt<bool>
68ArgShowMCEncoding("lshow-mc-encoding",
69                cl::Hidden,
70                cl::desc("Show encoding in .s output"));
71
72static cl::opt<bool>
73ArgShowMCInst("lshow-mc-inst",
74              cl::Hidden,
75              cl::desc("Show instruction structure in .s output"));
76
77static cl::opt<cl::boolOrDefault>
78ArgAsmVerbose("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
83static 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//===----------------------------------------------------------------------===//
96mcld::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
102mcld::MCLDTargetMachine::~MCLDTargetMachine() {
103  m_pTarget = 0;
104}
105
106const 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.
113static 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->getTargetLowering()));
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
140static 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
187bool 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
274bool 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
319bool 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
356bool 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. soname must be UTF-8 string.
369    pModule.setName(pOutput.handler()->path().filename().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