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
52using namespace mcld;
53using 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
62static cl::opt<cl::boolOrDefault>
63ArgEnableFastISelOption("lfast-isel", cl::Hidden,
64  cl::desc("Enable the \"fast\" instruction selector"));
65
66static cl::opt<bool>
67ArgShowMCEncoding("lshow-mc-encoding",
68                cl::Hidden,
69                cl::desc("Show encoding in .s output"));
70
71static cl::opt<bool>
72ArgShowMCInst("lshow-mc-inst",
73              cl::Hidden,
74              cl::desc("Show instruction structure in .s output"));
75
76static cl::opt<cl::boolOrDefault>
77ArgAsmVerbose("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
82static 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//===----------------------------------------------------------------------===//
95mcld::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
101mcld::LLVMTargetMachine::~LLVMTargetMachine() {
102  m_pTarget = 0;
103}
104
105const 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.
112static 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
139static 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
186bool 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
263bool 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
308bool 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
345bool 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