1 | #if HAVE_LLVM > 0x0390 |
2 | #include "llvm/Bitcode/BitcodeReader.h" |
3 | #include "llvm/Bitcode/BitcodeWriter.h" |
4 | #else |
5 | #include "llvm/Bitcode/ReaderWriter.h" |
6 | #endif |
7 | |
8 | #include "llvm/Config/llvm-config.h" |
9 | #include "llvm/IR/Function.h" |
10 | #include "llvm/IR/GlobalVariable.h" |
11 | #include "llvm/IR/LLVMContext.h" |
12 | #include "llvm/IR/Module.h" |
13 | #include "llvm/IRReader/IRReader.h" |
14 | #include "llvm/Support/CommandLine.h" |
15 | #include "llvm/Support/ErrorOr.h" |
16 | #include "llvm/Support/FileSystem.h" |
17 | #include "llvm/Support/ManagedStatic.h" |
18 | #include "llvm/Support/MemoryBuffer.h" |
19 | #include "llvm/Support/SourceMgr.h" |
20 | #include "llvm/Support/ToolOutputFile.h" |
21 | #include "llvm/Support/raw_ostream.h" |
22 | |
23 | #include <system_error> |
24 | |
25 | using namespace llvm; |
26 | |
27 | static ExitOnError ExitOnErr; |
28 | |
29 | static cl::opt<std::string> |
30 | InputFilename(cl::Positional, cl::desc("<input bitcode>" ), cl::init(Val: "-" )); |
31 | |
32 | static cl::opt<std::string> |
33 | OutputFilename("o" , cl::desc("Output filename" ), |
34 | cl::value_desc("filename" )); |
35 | |
36 | static cl::opt<bool> TextualOut("S" , cl::desc("Emit LLVM textual assembly" ), |
37 | cl::init(Val: false)); |
38 | |
39 | int main(int argc, char **argv) { |
40 | LLVMContext Context; |
41 | llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. |
42 | |
43 | cl::ParseCommandLineOptions(argc, argv, Overview: "libclc builtin preparation tool\n" ); |
44 | |
45 | std::string ErrorMessage; |
46 | Module *M = nullptr; |
47 | |
48 | { |
49 | ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = |
50 | MemoryBuffer::getFile(Filename: InputFilename); |
51 | if (std::error_code ec = BufferOrErr.getError()) { |
52 | ErrorMessage = ec.message(); |
53 | } else { |
54 | std::unique_ptr<MemoryBuffer> &BufferPtr = BufferOrErr.get(); |
55 | SMDiagnostic Err; |
56 | std::unique_ptr<llvm::Module> MPtr = |
57 | #if HAVE_LLVM > 0x0390 |
58 | ExitOnErr(Expected<std::unique_ptr<llvm::Module>>( |
59 | parseIR(Buffer: BufferPtr.get()->getMemBufferRef(), Err, Context))); |
60 | #else |
61 | parseIR(BufferPtr.get()->getMemBufferRef(), Err, Context); |
62 | #endif |
63 | M = MPtr.release(); |
64 | } |
65 | } |
66 | |
67 | if (!M) { |
68 | errs() << argv[0] << ": " ; |
69 | if (ErrorMessage.size()) |
70 | errs() << ErrorMessage << "\n" ; |
71 | else |
72 | errs() << "bitcode didn't read correctly.\n" ; |
73 | return 1; |
74 | } |
75 | |
76 | // Strip the OpenCL version metadata. There are a lot of linked |
77 | // modules in the library build, each spamming the same |
78 | // version. This may also report a different version than the user |
79 | // program is using. This should probably be uniqued when linking. |
80 | if (NamedMDNode *OCLVersion = M->getNamedMetadata(Name: "opencl.ocl.version" )) |
81 | M->eraseNamedMetadata(NMD: OCLVersion); |
82 | |
83 | // Set linkage of every external definition to linkonce_odr. |
84 | for (Module::iterator i = M->begin(), e = M->end(); i != e; ++i) { |
85 | if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage) |
86 | i->setLinkage(GlobalValue::LinkOnceODRLinkage); |
87 | } |
88 | |
89 | for (Module::global_iterator i = M->global_begin(), e = M->global_end(); |
90 | i != e; ++i) { |
91 | if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage) |
92 | i->setLinkage(GlobalValue::LinkOnceODRLinkage); |
93 | } |
94 | |
95 | if (OutputFilename.empty()) { |
96 | errs() << "no output file\n" ; |
97 | return 1; |
98 | } |
99 | |
100 | std::error_code EC; |
101 | #if HAVE_LLVM >= 0x0600 |
102 | std::unique_ptr<ToolOutputFile> Out( |
103 | new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); |
104 | #else |
105 | std::unique_ptr<tool_output_file> Out( |
106 | new tool_output_file(OutputFilename, EC, sys::fs::OF_None)); |
107 | #endif |
108 | if (EC) { |
109 | errs() << EC.message() << '\n'; |
110 | exit(status: 1); |
111 | } |
112 | |
113 | if (TextualOut) |
114 | M->print(OS&: Out->os(), AAW: nullptr, ShouldPreserveUseListOrder: true); |
115 | else |
116 | #if HAVE_LLVM >= 0x0700 |
117 | WriteBitcodeToFile(M: *M, Out&: Out->os()); |
118 | #else |
119 | WriteBitcodeToFile(M, Out->os()); |
120 | #endif |
121 | |
122 | // Declare success. |
123 | Out->keep(); |
124 | return 0; |
125 | } |
126 | |