blob: 7b14e26fb5fb386c88bd07f835785303104ce84d [file] [log] [blame]
zonr6315f762010-10-05 15:35:14 +08001#include <memory>
2#include <string>
3#include <vector>
4
Shih-wei Liao835a7b72010-08-06 02:29:11 -07005#include "llvm/Linker.h"
6#include "llvm/LLVMContext.h"
7#include "llvm/Metadata.h"
8#include "llvm/Module.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +08009
Shih-wei Liao835a7b72010-08-06 02:29:11 -070010#include "llvm/Analysis/Verifier.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080011
Shih-wei Liao835a7b72010-08-06 02:29:11 -070012#include "llvm/Bitcode/ReaderWriter.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080013
Shih-wei Liao835a7b72010-08-06 02:29:11 -070014#include "llvm/Support/CommandLine.h"
15#include "llvm/Support/ManagedStatic.h"
16#include "llvm/Support/MemoryBuffer.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070017#include "llvm/Support/StandardPasses.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070018#include "llvm/Support/raw_ostream.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080019
Shih-wei Liao835a7b72010-08-06 02:29:11 -070020#include "llvm/System/Signals.h"
21#include "llvm/System/Path.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080022
Shih-wei Liao835a7b72010-08-06 02:29:11 -070023#include "llvm/Target/TargetData.h"
Zonr Chang7f2f3852010-10-07 19:12:23 +080024
25#include "slang_rs_metadata.h"
Shih-wei Liao835a7b72010-08-06 02:29:11 -070026
27using namespace llvm;
28
29static cl::list<std::string>
30InputFilenames(cl::Positional, cl::OneOrMore,
31 cl::desc("<input bitcode files>"));
32
33static cl::opt<std::string>
34OutputFilename("o", cl::Required, cl::desc("Override output filename"),
35 cl::value_desc("<output bitcode file>"));
36
Zonr Chang7f2f3852010-10-07 19:12:23 +080037static bool GetExportSymbolNames(NamedMDNode *N,
38 unsigned NameOpIdx,
39 std::vector<const char *> &Names) {
40 if (N == NULL)
41 return true;
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -070042
Zonr Chang7f2f3852010-10-07 19:12:23 +080043 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
44 MDNode *V = N->getOperand(i);
45 if (V == NULL)
46 continue;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070047
Zonr Chang7f2f3852010-10-07 19:12:23 +080048 if (V->getNumOperands() < (NameOpIdx + 1)) {
49 errs() << "Invalid metadata spec of " << N->getName()
50 << " in RenderScript executable. (#op)\n";
51 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070052 }
53
Zonr Chang7f2f3852010-10-07 19:12:23 +080054 MDString *Name = dyn_cast<MDString>(V->getOperand(NameOpIdx));
55 if (Name == NULL) {
56 errs() << "Invalid metadata spec of " << N->getName()
57 << " in RenderScript executable. (#name)\n";
58 return false;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070059 }
60
Zonr Chang7f2f3852010-10-07 19:12:23 +080061 Names.push_back(Name->getString().data());
Shih-wei Liao835a7b72010-08-06 02:29:11 -070062 }
Zonr Chang7f2f3852010-10-07 19:12:23 +080063 return true;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070064}
65
Zonr Chang7f2f3852010-10-07 19:12:23 +080066static bool GetExportSymbols(Module *M, std::vector<const char *> &Names) {
67 bool Result = true;
68 // Variables marked as export must be externally visible
69 if (NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN))
70 Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names);
71 // So are those exported functions
72 if (NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN))
73 Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names);
74 return Result;
Shih-wei Liao835a7b72010-08-06 02:29:11 -070075}
76
77// LoadFile - Read the specified bitcode file in and return it. This routine
78// searches the link path for the specified file to try to find it...
79//
80static inline std::auto_ptr<Module> LoadFile(const char *argv0,
81 const std::string &FN,
82 LLVMContext& Context) {
83 sys::Path Filename;
84 if (!Filename.set(FN)) {
85 errs() << "Invalid file name: '" << FN << "'\n";
86 return std::auto_ptr<Module>();
87 }
88
89 std::string Err;
90 Module *Result = 0;
91
92 const std::string &FNStr = Filename.str();
93 MemoryBuffer *Buffer = MemoryBuffer::getFile(FNStr, &Err);
94 if (!Buffer) {
95 errs() << Err;
96 return std::auto_ptr<Module>();
97 }
98 Result = ParseBitcodeFile(Buffer, Context, &Err);
99 if (Result) return std::auto_ptr<Module>(Result); // Load successful!
100
101 errs() << Err;
102 return std::auto_ptr<Module>();
103}
104
105int main(int argc, char **argv) {
106 llvm_shutdown_obj X;
107
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -0700108 cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n");
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700109
110 LLVMContext &Context = getGlobalContext();
111 std::auto_ptr<Module> Composite = LoadFile(argv[0], InputFilenames[0],
112 Context);
113 std::string ErrorMessage;
114 if (Composite.get() == 0) {
115 errs() << argv[0] << ": error loading file '"
116 << InputFilenames[0] << "'\n";
117 return 1;
118 }
119 for (unsigned i = 1; i < InputFilenames.size(); ++i) {
120 std::auto_ptr<Module> M(LoadFile(argv[0], InputFilenames[i], Context));
121 if (M.get() == 0) {
Zonr Chang7f2f3852010-10-07 19:12:23 +0800122 errs() << argv[0] << ": error loading file '"
123 << InputFilenames[i] << "'\n";
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700124 return 1;
125 }
126 if (Linker::LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
127 errs() << argv[0] << ": link error in '" << InputFilenames[i]
128 << "': " << ErrorMessage << "\n";
129 return 1;
130 }
131 }
132
133 std::string ErrorInfo;
134 std::auto_ptr<raw_ostream>
Zonr Chang7f2f3852010-10-07 19:12:23 +0800135 Out(new raw_fd_ostream(OutputFilename.c_str(),
136 ErrorInfo,
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700137 raw_fd_ostream::F_Binary));
138 if (!ErrorInfo.empty()) {
139 errs() << ErrorInfo << '\n';
140 return 1;
141 }
142
143 if (verifyModule(*Composite)) {
144 errs() << argv[0] << ": linked module is broken!\n";
145 return 1;
146 }
147
148 PassManager Passes;
149
150 const std::string &ModuleDataLayout = Composite.get()->getDataLayout();
Zonr Chang7f2f3852010-10-07 19:12:23 +0800151 if (!ModuleDataLayout.empty())
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700152 if (TargetData *TD = new TargetData(ModuleDataLayout))
153 Passes.add(TD);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700154
Zonr Chang7f2f3852010-10-07 19:12:23 +0800155 // Some symbols must not be internalized
156 std::vector<const char *> ExportList;
157 ExportList.push_back("init");
158 ExportList.push_back("root");
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700159
Zonr Chang7f2f3852010-10-07 19:12:23 +0800160 if (!GetExportSymbols(Composite.get(), ExportList))
161 return 1;
Shih-wei Liao9c9bbc82010-08-18 03:08:44 -0700162
Zonr Chang7f2f3852010-10-07 19:12:23 +0800163 Passes.add(createInternalizePass(ExportList));
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700164
Zonr Chang7f2f3852010-10-07 19:12:23 +0800165 createStandardLTOPasses(&Passes,
166 /* Internalize = */false,
167 /* RunInliner = */true,
168 /* VerifyEach = */false);
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700169 Passes.run(*Composite.get());
170
171 WriteBitcodeToFile(Composite.get(), *Out);
Zonr Chang7f2f3852010-10-07 19:12:23 +0800172
Shih-wei Liao835a7b72010-08-06 02:29:11 -0700173 return 0;
174}