source: icGREP/icgrep-devel/icgrep/IR_Gen/llvm2ptx.h @ 5431

Last change on this file since 5431 was 5176, checked in by cameron, 3 years ago

Engine deletion causes segfaults with LLVM 3.9 changes

File size: 4.6 KB
Line 
1#include <string>
2#include <iostream>
3#include <fstream>
4#include <sys/stat.h>
5#include <fcntl.h>
6#include <unistd.h>
7#include <cassert>
8
9#include "llvm/ADT/Triple.h"
10#include "llvm/Analysis/TargetLibraryInfo.h"
11#include "llvm/CodeGen/CommandFlags.h"
12#include "llvm/CodeGen/LinkAllCodegenComponents.h"
13#include "llvm/CodeGen/MIRParser/MIRParser.h"
14#include "llvm/IR/DataLayout.h"
15#include "llvm/IR/LLVMContext.h"
16#include "llvm/IR/LegacyPassManager.h"
17#include "llvm/IR/Module.h"
18#include "llvm/IR/Verifier.h"
19#include "llvm/IRReader/IRReader.h"
20#include "llvm/Pass.h"
21#include "llvm/Support/CommandLine.h"
22#include "llvm/Support/FileSystem.h"
23#include "llvm/Support/FormattedStream.h"
24#include "llvm/Support/SourceMgr.h"
25#include "llvm/Support/TargetRegistry.h"
26#include "llvm/Support/TargetSelect.h"
27#include "llvm/Support/ToolOutputFile.h"
28#include "llvm/Target/TargetMachine.h"
29#include "llvm/Target/TargetSubtargetInfo.h"
30#include <memory>
31using namespace llvm;
32
33static int llvm2ptx(std::string IRFilename, std::string PTXFilename) {
34
35  LLVMContext Context;
36
37  // Load the module to be compiled...
38  SMDiagnostic Err;
39  std::unique_ptr<Module> M;
40  std::unique_ptr<MIRParser> MIR;
41  Triple TheTriple;
42
43  M = parseIRFile(IRFilename, Err, Context);
44  if (!M) {
45    errs() << IRFilename << ": Cannot parse input file!\n";
46    return 1;
47  }
48
49#ifndef NDEBUG
50  if (verifyModule(*M, &errs())) {
51    errs() << IRFilename << ": error: input module is broken!\n";
52    return 1;
53  }
54#endif
55
56  TheTriple = Triple(M->getTargetTriple());
57
58  if (TheTriple.getTriple().empty())
59    TheTriple.setTriple(sys::getDefaultTargetTriple());
60
61  // Get the target specific parser.
62  std::string Error;
63  const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple,
64                                                         Error);
65  if (!TheTarget) {
66    errs() << Error;
67    return 1;
68  }
69
70  std::string CPUStr = getCPUStr(), FeaturesStr = getFeaturesStr();
71
72  CodeGenOpt::Level OLvl = CodeGenOpt::Default;
73
74  TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
75
76  std::unique_ptr<TargetMachine> Target(
77      TheTarget->createTargetMachine(TheTriple.getTriple(), CPUStr, FeaturesStr,
78                                     Options, RelocModel, CMModel, OLvl));
79
80  assert(Target && "Could not allocate target machine!");
81
82  // Figure out where we are going to send the output.
83  std::error_code EC;
84  sys::fs::OpenFlags OpenFlags = sys::fs::F_None | sys::fs::F_Text;
85  std::unique_ptr<tool_output_file> Out = llvm::make_unique<tool_output_file>(PTXFilename, EC, OpenFlags);
86  if (EC) {
87    errs() << EC.message() << '\n';
88    return 1;
89  }
90
91  // Build up all of the passes that we want to do to the module.
92  legacy::PassManager PM;
93
94  // Add an appropriate TargetLibraryInfo pass for the module's triple.
95  TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
96
97  PM.add(new TargetLibraryInfoWrapperPass(TLII));
98
99  // Add the target data from the target machine, if it exists, or the module.
100  M->setDataLayout(Target->createDataLayout());
101
102  // Override function attributes based on CPUStr, FeaturesStr, and command line
103  // flags.
104  setFunctionAttributes(CPUStr, FeaturesStr, *M);
105
106  {
107    raw_pwrite_stream *OS = &Out->os();
108
109    AnalysisID StartBeforeID = nullptr;
110    AnalysisID StartAfterID = nullptr;
111    AnalysisID StopAfterID = nullptr;
112    const PassRegistry *PR = PassRegistry::getPassRegistry();
113    if (!RunPass.empty()) {
114      if (!StartAfter.empty() || !StopAfter.empty()) {
115        errs() << "start-after and/or stop-after passes are redundant when run-pass is specified.\n";
116        return 1;
117      }
118      const PassInfo *PI = PR->getPassInfo(RunPass);
119      if (!PI) {
120        errs() << "run-pass pass is not registered.\n";
121        return 1;
122      }
123      StopAfterID = StartBeforeID = PI->getTypeInfo();
124    } else {
125      if (!StartAfter.empty()) {
126        const PassInfo *PI = PR->getPassInfo(StartAfter);
127        if (!PI) {
128          errs() << "start-after pass is not registered.\n";
129          return 1;
130        }
131        StartAfterID = PI->getTypeInfo();
132      }
133      if (!StopAfter.empty()) {
134        const PassInfo *PI = PR->getPassInfo(StopAfter);
135        if (!PI) {
136          errs() << "stop-after pass is not registered.\n";
137          return 1;
138        }
139        StopAfterID = PI->getTypeInfo();
140      }
141    }
142
143    // Ask the target to add backend passes as necessary.
144    if (Target->addPassesToEmitFile(PM, *OS, FileType, false, StartBeforeID,
145                                    StartAfterID, StopAfterID, MIR.get())) {
146      errs() << " target does not support generation of this file type!\n";
147      return 1;
148    }
149
150    PM.run(*M);
151  }
152  // Declare success.
153  Out->keep();
154
155  return 0;
156}
Note: See TracBrowser for help on using the repository browser.