1 #include "llvm/Bitcode/ReaderWriter.h"
2 #include "llvm/IR/Function.h"
3 #include "llvm/IR/GlobalVariable.h"
4 #include "llvm/IR/LLVMContext.h"
5 #include "llvm/IR/Module.h"
6 #include "llvm/Support/CommandLine.h"
7 #include "llvm/Support/ManagedStatic.h"
8 #include "llvm/Support/MemoryBuffer.h"
9 #include "llvm/Support/FileSystem.h"
10 #include "llvm/Support/raw_ostream.h"
11 #include "llvm/Support/ErrorOr.h"
12 #include "llvm/Support/ToolOutputFile.h"
13 #include "llvm/Config/config.h"
14 
15 #define LLVM_350_AND_NEWER \
16   (LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5))
17 
18 #if LLVM_350_AND_NEWER
19 #include <system_error>
20 
21 #define ERROR_CODE std::error_code
22 #define UNIQUE_PTR std::unique_ptr
23 #else
24 #include "llvm/ADT/OwningPtr.h"
25 #include "llvm/Support/system_error.h"
26 
27 #define ERROR_CODE error_code
28 #define UNIQUE_PTR OwningPtr
29 #endif
30 
31 using namespace llvm;
32 
33 static cl::opt<std::string>
34 InputFilename(cl::Positional, cl::desc("<input bitcode>"), cl::init("-"));
35 
36 static cl::opt<std::string>
37 OutputFilename("o", cl::desc("Output filename"),
38                cl::value_desc("filename"));
39 
40 int main(int argc, char **argv) {
41   LLVMContext &Context = getGlobalContext();
42   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.
43 
44   cl::ParseCommandLineOptions(argc, argv, "libclc builtin preparation tool\n");
45 
46   std::string ErrorMessage;
47   std::auto_ptr<Module> M;
48 
49   {
50     UNIQUE_PTR<MemoryBuffer> BufferPtr;
51     if (ERROR_CODE ec = MemoryBuffer::getFileOrSTDIN(InputFilename, BufferPtr))
52       ErrorMessage = ec.message();
53     else {
54 #if LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
55       ErrorOr<Module *> ModuleOrErr = parseBitcodeFile(BufferPtr.get(), Context);
56       if (ERROR_CODE ec = ModuleOrErr.getError())
57         ErrorMessage = ec.message();
58       M.reset(ModuleOrErr.get());
59 #else
60       M.reset(ParseBitcodeFile(BufferPtr.get(), Context, &ErrorMessage));
61 #endif
62     }
63   }
64 
65   if (M.get() == 0) {
66     errs() << argv[0] << ": ";
67     if (ErrorMessage.size())
68       errs() << ErrorMessage << "\n";
69     else
70       errs() << "bitcode didn't read correctly.\n";
71     return 1;
72   }
73 
74   // Set linkage of every external definition to linkonce_odr.
75   for (Module::iterator i = M->begin(), e = M->end(); i != e; ++i) {
76     if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage)
77       i->setLinkage(GlobalValue::LinkOnceODRLinkage);
78   }
79 
80   for (Module::global_iterator i = M->global_begin(), e = M->global_end();
81        i != e; ++i) {
82     if (!i->isDeclaration() && i->getLinkage() == GlobalValue::ExternalLinkage)
83       i->setLinkage(GlobalValue::LinkOnceODRLinkage);
84   }
85 
86   if (OutputFilename.empty()) {
87     errs() << "no output file\n";
88     return 1;
89   }
90 
91   std::string ErrorInfo;
92   UNIQUE_PTR<tool_output_file> Out
93   (new tool_output_file(OutputFilename.c_str(), ErrorInfo,
94 #if (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR == 4)
95                         sys::fs::F_Binary));
96 #elif LLVM_VERSION_MAJOR > 3 || (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 5)
97                         sys::fs::F_None));
98 #else
99                         raw_fd_ostream::F_Binary));
100 #endif
101   if (!ErrorInfo.empty()) {
102     errs() << ErrorInfo << '\n';
103     exit(1);
104   }
105 
106   WriteBitcodeToFile(M.get(), Out->os());
107 
108   // Declare success.
109   Out->keep();
110   return 0;
111 }
112 
113