1 /* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <list> 18 #include <memory> 19 #include <string> 20 #include <vector> 21 22 #include "llvm/Analysis/Verifier.h" 23 24 #include "llvm/Bitcode/ReaderWriter.h" 25 26 #include "llvm/Linker.h" 27 #include "llvm/LLVMContext.h" 28 #include "llvm/Metadata.h" 29 #include "llvm/Module.h" 30 31 #include "llvm/Support/CommandLine.h" 32 #include "llvm/Support/ManagedStatic.h" 33 #include "llvm/Support/MemoryBuffer.h" 34 #include "llvm/Support/raw_ostream.h" 35 #include "llvm/Support/ToolOutputFile.h" 36 #include "llvm/Support/system_error.h" 37 38 #include "llvm/PassManager.h" 39 #include "llvm/Transforms/IPO.h" 40 #include "llvm/Transforms/IPO/PassManagerBuilder.h" 41 42 #include "llvm/Target/TargetData.h" 43 44 #include "slang_rs_metadata.h" 45 46 using llvm::errs; 47 using llvm::LLVMContext; 48 using llvm::MemoryBuffer; 49 using llvm::Module; 50 51 static llvm::cl::list<std::string> 52 InputFilenames(llvm::cl::Positional, llvm::cl::OneOrMore, 53 llvm::cl::desc("<input bitcode files>")); 54 55 static llvm::cl::list<std::string> 56 OutputFilenames("o", llvm::cl::desc("Override output filename"), 57 llvm::cl::value_desc("<output bitcode file>")); 58 59 static llvm::cl::opt<bool> 60 NoStdLib("nostdlib", llvm::cl::desc("Don't link RS default libraries")); 61 62 static llvm::cl::list<std::string> 63 AdditionalLibs("l", llvm::cl::Prefix, 64 llvm::cl::desc("Specify additional libraries to link to"), 65 llvm::cl::value_desc("<library bitcode>")); 66 67 static bool GetExportSymbolNames(llvm::NamedMDNode *N, 68 unsigned NameOpIdx, 69 std::vector<const char *> &Names) { 70 if (N == NULL) 71 return true; 72 73 for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) { 74 llvm::MDNode *V = N->getOperand(i); 75 if (V == NULL) 76 continue; 77 78 if (V->getNumOperands() < (NameOpIdx + 1)) { 79 errs() << "Invalid metadata spec of " << N->getName() 80 << " in Renderscript executable. (#op)\n"; 81 return false; 82 } 83 84 llvm::MDString *Name = 85 llvm::dyn_cast<llvm::MDString>(V->getOperand(NameOpIdx)); 86 if (Name == NULL) { 87 errs() << "Invalid metadata spec of " << N->getName() 88 << " in Renderscript executable. (#name)\n"; 89 return false; 90 } 91 92 Names.push_back(Name->getString().data()); 93 } 94 return true; 95 } 96 97 static bool GetExportSymbols(Module *M, std::vector<const char *> &Names) { 98 bool Result = true; 99 // Variables marked as export must be externally visible 100 if (llvm::NamedMDNode *EV = M->getNamedMetadata(RS_EXPORT_VAR_MN)) 101 Result |= GetExportSymbolNames(EV, RS_EXPORT_VAR_NAME, Names); 102 // So are those exported functions 103 if (llvm::NamedMDNode *EF = M->getNamedMetadata(RS_EXPORT_FUNC_MN)) 104 Result |= GetExportSymbolNames(EF, RS_EXPORT_FUNC_NAME, Names); 105 return Result; 106 } 107 108 static inline MemoryBuffer *LoadFileIntoMemory(const std::string &F) { 109 llvm::OwningPtr<MemoryBuffer> MB; 110 111 if (llvm::error_code EC = MemoryBuffer::getFile(F, MB)) { 112 errs() << "Failed to load `" << F << "' (" + EC.message() + ")\n"; 113 } 114 115 return MB.take(); 116 } 117 118 static inline Module *ParseBitcodeFromMemoryBuffer(MemoryBuffer *MB, 119 LLVMContext& Context) { 120 std::string Err; 121 Module *M = ParseBitcodeFile(MB, Context, &Err); 122 123 if (M == NULL) 124 errs() << "Corrupted bitcode file `" << MB->getBufferIdentifier() 125 << "' (" << Err << ")\n"; 126 127 return M; 128 } 129 130 // LoadBitcodeFile - Read the specified bitcode file in and return it. 131 static inline Module *LoadBitcodeFile(const std::string &F, 132 LLVMContext& Context) { 133 MemoryBuffer *MB = LoadFileIntoMemory(F); 134 if (MB == NULL) 135 return NULL; 136 137 Module *M = ParseBitcodeFromMemoryBuffer(MB, Context); 138 if (M == NULL) 139 delete MB; 140 141 return M; 142 } 143 144 extern const char rslib_bc[]; 145 extern unsigned rslib_bc_size; 146 147 static bool PreloadLibraries(bool NoStdLib, 148 const std::vector<std::string> &AdditionalLibs, 149 std::list<MemoryBuffer *> &LibBitcode) { 150 MemoryBuffer *MB; 151 152 LibBitcode.clear(); 153 154 if (!NoStdLib) { 155 // rslib.bc 156 MB = MemoryBuffer::getMemBuffer(llvm::StringRef(rslib_bc, rslib_bc_size), 157 "rslib.bc"); 158 if (MB == NULL) { 159 errs() << "Failed to load (in-memory) `rslib.bc'!\n"; 160 return false; 161 } 162 163 LibBitcode.push_back(MB); 164 } 165 166 // Load additional libraries 167 for (std::vector<std::string>::const_iterator 168 I = AdditionalLibs.begin(), E = AdditionalLibs.end(); 169 I != E; 170 I++) { 171 MB = LoadFileIntoMemory(*I); 172 if (MB == NULL) 173 return false; 174 LibBitcode.push_back(MB); 175 } 176 177 return true; 178 } 179 180 static void UnloadLibraries(std::list<MemoryBuffer *>& LibBitcode) { 181 for (std::list<MemoryBuffer *>::iterator 182 I = LibBitcode.begin(), E = LibBitcode.end(); 183 I != E; 184 I++) 185 delete *I; 186 LibBitcode.clear(); 187 return; 188 } 189 190 Module *PerformLinking(const std::string &InputFile, 191 const std::list<MemoryBuffer *> &LibBitcode, 192 LLVMContext &Context) { 193 std::string Err; 194 std::auto_ptr<Module> Composite(LoadBitcodeFile(InputFile, Context)); 195 196 if (Composite.get() == NULL) 197 return NULL; 198 199 for (std::list<MemoryBuffer *>::const_iterator I = LibBitcode.begin(), 200 E = LibBitcode.end(); 201 I != E; 202 I++) { 203 Module *Lib = ParseBitcodeFromMemoryBuffer(*I, Context); 204 if (Lib == NULL) 205 return NULL; 206 207 if (llvm::Linker::LinkModules(Composite.get(), Lib, 208 llvm::Linker::DestroySource, &Err)) { 209 errs() << "Failed to link `" << InputFile << "' with library bitcode `" 210 << (*I)->getBufferIdentifier() << "' (" << Err << ")\n"; 211 return NULL; 212 } 213 } 214 215 return Composite.release(); 216 } 217 218 bool OptimizeModule(Module *M) { 219 llvm::PassManager Passes; 220 221 const std::string &ModuleDataLayout = M->getDataLayout(); 222 if (!ModuleDataLayout.empty()) 223 if (llvm::TargetData *TD = new llvm::TargetData(ModuleDataLayout)) 224 Passes.add(TD); 225 226 // Some symbols must not be internalized 227 std::vector<const char *> ExportList; 228 ExportList.push_back("init"); 229 ExportList.push_back("root"); 230 ExportList.push_back(".rs.dtor"); 231 232 if (!GetExportSymbols(M, ExportList)) { 233 return false; 234 } 235 236 Passes.add(llvm::createInternalizePass(ExportList)); 237 238 // TODO(sliao): Do we need to run all LTO passes? 239 llvm::PassManagerBuilder PMBuilder; 240 PMBuilder.populateLTOPassManager(Passes, 241 /* Internalize = */false, 242 /* RunInliner = */true); 243 Passes.run(*M); 244 245 return true; 246 } 247 248 int main(int argc, char **argv) { 249 llvm::llvm_shutdown_obj X; // Call llvm_shutdown() on exit. 250 251 llvm::cl::ParseCommandLineOptions(argc, argv, "llvm-rs-link\n"); 252 253 std::list<MemoryBuffer *> LibBitcode; 254 255 if (!PreloadLibraries(NoStdLib, AdditionalLibs, LibBitcode)) 256 return 1; 257 258 // No libraries specified to be linked 259 if (LibBitcode.size() == 0) 260 return 0; 261 262 LLVMContext &Context = llvm::getGlobalContext(); 263 bool HasError = true; 264 std::string Err; 265 266 for (unsigned i = 0, e = InputFilenames.size(); i != e; i++) { 267 std::auto_ptr<Module> Linked( 268 PerformLinking(InputFilenames[i], LibBitcode, Context)); 269 270 // Failed to link with InputFilenames[i] with LibBitcode 271 if (Linked.get() == NULL) 272 break; 273 274 // Verify linked module 275 if (verifyModule(*Linked, llvm::ReturnStatusAction, &Err)) { 276 errs() << InputFilenames[i] << " linked, but does not verify as " 277 "correct! (" << Err << ")\n"; 278 break; 279 } 280 281 if (!OptimizeModule(Linked.get())) 282 break; 283 284 // Write out the module 285 llvm::tool_output_file Out(InputFilenames[i].c_str(), Err, 286 llvm::raw_fd_ostream::F_Binary); 287 288 if (!Err.empty()) { 289 errs() << InputFilenames[i] << " linked, but failed to write out! " 290 "(" << Err << ")\n"; 291 break; 292 } 293 294 WriteBitcodeToFile(Linked.get(), Out.os()); 295 296 Out.keep(); 297 Linked.reset(); 298 299 if (i == (InputFilenames.size() - 1)) 300 // This is the last file and no error occured. 301 HasError = false; 302 } 303 304 UnloadLibraries(LibBitcode); 305 306 return HasError; 307 } 308