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/MCBitcodeInterceptor.h"
13#include "mcld/MC/MCLDFile.h"
14#include "mcld/Support/RealPath.h"
15#include "mcld/Support/TargetRegistry.h"
16#include "mcld/Target/TargetMachine.h"
17#include "mcld/Target/TargetLDBackend.h"
18
19#include <llvm/ADT/OwningPtr.h>
20#include <llvm/Analysis/Passes.h>
21#include <llvm/Analysis/Verifier.h>
22#include <llvm/Assembly/PrintModulePass.h>
23#include <llvm/CodeGen/AsmPrinter.h>
24#include <llvm/CodeGen/MachineFunctionAnalysis.h>
25#include <llvm/CodeGen/MachineModuleInfo.h>
26#include <llvm/CodeGen/GCStrategy.h>
27#include <llvm/CodeGen/Passes.h>
28#include <llvm/MC/MCAsmInfo.h>
29#include <llvm/MC/MCStreamer.h>
30#include <llvm/MC/MCInstrInfo.h>
31#include <llvm/MC/MCSubtargetInfo.h>
32#include <llvm/MC/MCObjectStreamer.h>
33#include <llvm/MC/MCAssembler.h>
34#include <llvm/MC/MCObjectWriter.h>
35#include <llvm/MC/MCContext.h>
36#include <llvm/PassManager.h>
37#include <llvm/Support/CommandLine.h>
38#include <llvm/Support/Debug.h>
39#include <llvm/Support/TargetRegistry.h>
40#include <llvm/Support/FormattedStream.h>
41#include <llvm/Support/ToolOutputFile.h>
42#include <llvm/Target/TargetData.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// 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
94mcld::LLVMTargetMachine::LLVMTargetMachine(llvm::TargetMachine &pTM,
95                                           const mcld::Target& pTarget,
96                                           const std::string& pTriple )
97  : m_TM(pTM), m_pTarget(&pTarget), m_Triple(pTriple) {
98}
99
100mcld::LLVMTargetMachine::~LLVMTargetMachine() {
101  m_pTarget = 0;
102}
103
104const mcld::Target& mcld::LLVMTargetMachine::getTarget() const
105{
106  return *m_pTarget;
107}
108
109/// Turn exception handling constructs into something the code generators can
110/// handle.
111static void addPassesToHandleExceptions(llvm::TargetMachine *TM,
112                                        PassManagerBase &PM) {
113  switch (TM->getMCAsmInfo()->getExceptionHandlingType()) {
114  case llvm::ExceptionHandling::SjLj:
115    // SjLj piggy-backs on dwarf for this bit. The cleanups done apply to both
116    // Dwarf EH prepare needs to be run after SjLj prepare. Otherwise,
117    // catch info can get misplaced when a selector ends up more than one block
118    // removed from the parent invoke(s). This could happen when a landing
119    // pad is shared by multiple invokes and is also a target of a normal
120    // edge from elsewhere.
121    PM.add(createSjLjEHPreparePass(TM->getTargetLowering()));
122    // FALLTHROUGH
123  case llvm::ExceptionHandling::DwarfCFI:
124  case llvm::ExceptionHandling::ARM:
125  case llvm::ExceptionHandling::Win64:
126    PM.add(createDwarfEHPass(TM));
127    break;
128  case llvm::ExceptionHandling::None:
129    PM.add(createLowerInvokePass(TM->getTargetLowering()));
130
131    // The lower invoke pass may create unreachable code. Remove it.
132    PM.add(createUnreachableBlockEliminationPass());
133    break;
134  }
135}
136
137
138static llvm::MCContext *addPassesToGenerateCode(llvm::LLVMTargetMachine *TM,
139                                     PassManagerBase &PM,
140                                     bool DisableVerify)
141{
142  // Targets may override createPassConfig to provide a target-specific sublass.
143  TargetPassConfig *PassConfig = TM->createPassConfig(PM);
144
145  // Set PassConfig options provided by TargetMachine.
146  PassConfig->setDisableVerify(DisableVerify);
147
148  PM.add(PassConfig);
149
150  PassConfig->addIRPasses();
151
152  addPassesToHandleExceptions(TM, PM);
153
154  PassConfig->addISelPrepare();
155
156  // Install a MachineModuleInfo class, which is an immutable pass that holds
157  // all the per-module stuff we're generating, including MCContext.
158  MachineModuleInfo *MMI =
159    new MachineModuleInfo(*TM->getMCAsmInfo(), *TM->getRegisterInfo(),
160                          &TM->getTargetLowering()->getObjFileLowering());
161  PM.add(MMI);
162  MCContext *Context = &MMI->getContext(); // Return the MCContext by-ref.
163
164  // Set up a MachineFunction for the rest of CodeGen to work on.
165  PM.add(new MachineFunctionAnalysis(*TM));
166
167  // Enable FastISel with -fast, but allow that to be overridden.
168  if (ArgEnableFastISelOption == cl::BOU_TRUE ||
169      (TM->getOptLevel() == CodeGenOpt::None &&
170       ArgEnableFastISelOption != cl::BOU_FALSE))
171    TM->setFastISel(true);
172
173  // Ask the target for an isel.
174  if (PassConfig->addInstSelector())
175    return NULL;
176
177  PassConfig->addMachinePasses();
178
179  PassConfig->setInitialized();
180
181  return Context;
182
183}
184
185bool mcld::LLVMTargetMachine::addPassesToEmitFile(PassManagerBase &pPM,
186                                             formatted_raw_ostream &Out,
187                                             const std::string& pOutputFilename,
188                                             mcld::CodeGenFileType pFileType,
189                                             CodeGenOpt::Level pOptLvl,
190                                             SectLinkerOption *pLinkerOpt,
191                                             bool pDisableVerify)
192{
193
194  llvm::MCContext* Context =
195          addPassesToGenerateCode(static_cast<llvm::LLVMTargetMachine*>(&m_TM),
196                                  pPM, pDisableVerify);
197  if (!Context)
198    return true;
199
200  switch(pFileType) {
201  default:
202  case mcld::CGFT_NULLFile:
203    assert(0 && "fatal: file type is not set!");
204    break;
205  case CGFT_ASMFile: {
206    assert(Context != 0 && "Failed to get MCContext");
207
208    if (getTM().hasMCSaveTempLabels())
209      Context->setAllowTemporaryLabels(false);
210
211    if (addCompilerPasses(pPM,
212                          Out,
213                          pOutputFilename,
214                          Context))
215      return true;
216
217    pPM.add(createGCInfoDeleter()); // not in addPassesToMC
218    break;
219  }
220  case CGFT_OBJFile: {
221    assert(Context != 0 && "Failed to get MCContext");
222
223    if (getTM().hasMCSaveTempLabels())
224      Context->setAllowTemporaryLabels(false);
225    if (addAssemblerPasses(pPM,
226                           Out,
227                           pOutputFilename,
228                           Context))
229      return true;
230
231    pPM.add(createGCInfoDeleter()); // not in addPassesToMC
232    break;
233  }
234  case CGFT_ARCFile: {
235    assert(0 && "Output to archive file has not been supported yet!");
236    break;
237  }
238  case CGFT_EXEFile: {
239    if (pLinkerOpt == NULL)
240      return true;
241
242    if (addLinkerPasses(pPM,
243                        pLinkerOpt,
244                        pOutputFilename,
245                        MCLDFile::Exec,
246                        Context))
247      return true;
248    break;
249  }
250  case CGFT_DSOFile: {
251    if (pLinkerOpt == NULL)
252      return true;
253
254    if (addLinkerPasses(pPM,
255                        pLinkerOpt,
256                        pOutputFilename,
257                        MCLDFile::DynObj,
258                        Context))
259      return true;
260    break;
261  }
262  } // switch
263  return false;
264}
265
266bool mcld::LLVMTargetMachine::addCompilerPasses(PassManagerBase &pPM,
267                                                formatted_raw_ostream &Out,
268                                                const std::string& pOutputFilename,
269                                                llvm::MCContext *&Context)
270{
271  const MCAsmInfo &MAI = *getTM().getMCAsmInfo();
272  const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
273
274  MCInstPrinter *InstPrinter =
275    getTarget().get()->createMCInstPrinter(MAI.getAssemblerDialect(), MAI,
276                                           *(getTM().getInstrInfo()),
277                                           Context->getRegisterInfo(), STI);
278
279  MCCodeEmitter* MCE = 0;
280  MCAsmBackend *MAB = 0;
281  if (ArgShowMCEncoding) {
282    MCE = getTarget().get()->createMCCodeEmitter(*(getTM().getInstrInfo()), STI, *Context);
283    MAB = getTarget().get()->createMCAsmBackend(m_Triple);
284  }
285
286
287  // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
288  OwningPtr<MCStreamer> AsmStreamer(
289    getTarget().get()->createAsmStreamer(*Context, Out,
290                                         getVerboseAsm(),
291                                         getTM().hasMCUseLoc(),
292                                         getTM().hasMCUseCFI(),
293                                         getTM().hasMCUseDwarfDirectory(),
294                                         InstPrinter,
295                                         MCE, MAB,
296                                         ArgShowMCInst));
297
298  llvm::MachineFunctionPass* funcPass =
299    getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer.get());
300
301  if (funcPass == 0)
302    return true;
303  // If successful, createAsmPrinter took ownership of AsmStreamer
304  AsmStreamer.take();
305  pPM.add(funcPass);
306  return false;
307}
308
309bool mcld::LLVMTargetMachine::addAssemblerPasses(PassManagerBase &pPM,
310                                                 formatted_raw_ostream &Out,
311                                                 const std::string& pOutputFilename,
312                                                 llvm::MCContext *&Context)
313{
314  // MCCodeEmitter
315  const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
316  MCCodeEmitter* MCE = getTarget().get()->createMCCodeEmitter(*getTM().getInstrInfo(), STI, *Context);
317
318  // MCAsmBackend
319  MCAsmBackend* MAB = getTarget().get()->createMCAsmBackend(m_Triple);
320  if (MCE == 0 || MAB == 0)
321    return true;
322
323  // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
324  OwningPtr<MCStreamer> AsmStreamer(getTarget().get()->createMCObjectStreamer(
325                                                              m_Triple,
326                                                              *Context,
327                                                              *MAB,
328                                                              Out,
329                                                              MCE,
330                                                              getTM().hasMCRelaxAll(),
331                                                              getTM().hasMCNoExecStack()));
332  AsmStreamer.get()->InitSections();
333  MachineFunctionPass *funcPass = getTarget().get()->createAsmPrinter(getTM(),
334                                                                      *AsmStreamer.get());
335  if (funcPass == 0)
336    return true;
337  // If successful, createAsmPrinter took ownership of AsmStreamer
338  AsmStreamer.take();
339  pPM.add(funcPass);
340  return false;
341}
342
343bool mcld::LLVMTargetMachine::addLinkerPasses(PassManagerBase &pPM,
344                                              SectLinkerOption *pLinkerOpt,
345                                              const std::string &pOutputFilename,
346                                              MCLDFile::Type pOutputLinkType,
347                                              llvm::MCContext *&Context)
348{
349// FIXME: when MCLinker can directly turn bitcode into shared object, turn on this
350// block of code.
351#if 0
352  // Initialize MCAsmStreamer first, than chain its output into SectLinker.
353  // MCCodeEmitter
354  const MCSubtargetInfo &STI = getTM().getSubtarget<MCSubtargetInfo>();
355  MCCodeEmitter* MCE = getTarget().get()->createMCCodeEmitter(*getTM().getInstrInfo(),
356                                                              STI,
357                                                              *Context);
358  // MCAsmBackend
359  MCAsmBackend *MAB = getTarget().get()->createMCAsmBackend(m_Triple);
360  if (MCE == 0 || MAB == 0)
361    return true;
362
363  // now, we have MCCodeEmitter and MCAsmBackend, we can create AsmStreamer.
364  MCStreamer* AsmStreamer =
365    getTarget().get()->createMCObjectStreamer(m_Triple,
366                                              *Context,
367                                              *MAB,
368                                              llvm::nulls(),
369                                              MCE,
370                                              getTM().hasMCRelaxAll(),
371                                              getTM().hasMCNoExecStack());
372  if (0 == AsmStreamer)
373    return true;
374
375  AsmStreamer->InitSections();
376  AsmPrinter* printer = getTarget().get()->createAsmPrinter(getTM(), *AsmStreamer);
377  if (0 == printer)
378    return true;
379  pPM.add(printer);
380#endif
381  TargetLDBackend* ldBackend = getTarget().createLDBackend(*getTarget().get(), m_Triple);
382  if (0 == ldBackend)
383    return true;
384
385// FIXME: when MCLinker can directly turn bitcode into shared object, turn on this
386// block of code.
387#if 0
388  MCBitcodeInterceptor* objReader = new MCBitcodeInterceptor(
389                                 static_cast<MCObjectStreamer&>(*AsmStreamer),
390                                 *ldBackend,
391                                 getLDInfo());
392#endif
393  // set up output's SOName
394  if (pOutputLinkType == MCLDFile::DynObj &&
395      pLinkerOpt->info().output().name().empty()) {
396    // if the output is a shared object, and the option -soname was not
397    // enable, set soname as the output file name.
398    pLinkerOpt->info().output().setSOName(pOutputFilename);
399  }
400
401  pLinkerOpt->info().output().setPath(sys::fs::RealPath(pOutputFilename));
402  pLinkerOpt->info().output().setType(pOutputLinkType);
403
404  MachineFunctionPass* funcPass = getTarget().createSectLinker(m_Triple,
405                                                               *pLinkerOpt,
406                                                               *ldBackend);
407  if (0 == funcPass)
408    return true;
409
410  pPM.add(funcPass);
411  return false;
412}
413