1 //===- llvm-extract.cpp - LLVM function extraction utility ----------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This utility changes the input module to only contain a single function, 11 // which is primarily used for debugging transformations. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/ADT/SetVector.h" 16 #include "llvm/ADT/SmallPtrSet.h" 17 #include "llvm/Bitcode/BitcodeWriterPass.h" 18 #include "llvm/IR/DataLayout.h" 19 #include "llvm/IR/IRPrintingPasses.h" 20 #include "llvm/IR/LLVMContext.h" 21 #include "llvm/IR/Module.h" 22 #include "llvm/IR/UseListOrder.h" 23 #include "llvm/IRReader/IRReader.h" 24 #include "llvm/IR/LegacyPassManager.h" 25 #include "llvm/Support/CommandLine.h" 26 #include "llvm/Support/FileSystem.h" 27 #include "llvm/Support/ManagedStatic.h" 28 #include "llvm/Support/PrettyStackTrace.h" 29 #include "llvm/Support/Regex.h" 30 #include "llvm/Support/Signals.h" 31 #include "llvm/Support/SourceMgr.h" 32 #include "llvm/Support/SystemUtils.h" 33 #include "llvm/Support/ToolOutputFile.h" 34 #include "llvm/Transforms/IPO.h" 35 #include <memory> 36 using namespace llvm; 37 38 // InputFilename - The filename to read from. 39 static cl::opt<std::string> 40 InputFilename(cl::Positional, cl::desc("<input bitcode file>"), 41 cl::init("-"), cl::value_desc("filename")); 42 43 static cl::opt<std::string> 44 OutputFilename("o", cl::desc("Specify output filename"), 45 cl::value_desc("filename"), cl::init("-")); 46 47 static cl::opt<bool> 48 Force("f", cl::desc("Enable binary output on terminals")); 49 50 static cl::opt<bool> 51 DeleteFn("delete", cl::desc("Delete specified Globals from Module")); 52 53 // ExtractFuncs - The functions to extract from the module. 54 static cl::list<std::string> 55 ExtractFuncs("func", cl::desc("Specify function to extract"), 56 cl::ZeroOrMore, cl::value_desc("function")); 57 58 // ExtractRegExpFuncs - The functions, matched via regular expression, to 59 // extract from the module. 60 static cl::list<std::string> 61 ExtractRegExpFuncs("rfunc", cl::desc("Specify function(s) to extract using a " 62 "regular expression"), 63 cl::ZeroOrMore, cl::value_desc("rfunction")); 64 65 // ExtractAlias - The alias to extract from the module. 66 static cl::list<std::string> 67 ExtractAliases("alias", cl::desc("Specify alias to extract"), 68 cl::ZeroOrMore, cl::value_desc("alias")); 69 70 71 // ExtractRegExpAliases - The aliases, matched via regular expression, to 72 // extract from the module. 73 static cl::list<std::string> 74 ExtractRegExpAliases("ralias", cl::desc("Specify alias(es) to extract using a " 75 "regular expression"), 76 cl::ZeroOrMore, cl::value_desc("ralias")); 77 78 // ExtractGlobals - The globals to extract from the module. 79 static cl::list<std::string> 80 ExtractGlobals("glob", cl::desc("Specify global to extract"), 81 cl::ZeroOrMore, cl::value_desc("global")); 82 83 // ExtractRegExpGlobals - The globals, matched via regular expression, to 84 // extract from the module... 85 static cl::list<std::string> 86 ExtractRegExpGlobals("rglob", cl::desc("Specify global(s) to extract using a " 87 "regular expression"), 88 cl::ZeroOrMore, cl::value_desc("rglobal")); 89 90 static cl::opt<bool> 91 OutputAssembly("S", 92 cl::desc("Write output as LLVM assembly"), cl::Hidden); 93 94 int main(int argc, char **argv) { 95 // Print a stack trace if we signal out. 96 sys::PrintStackTraceOnErrorSignal(); 97 PrettyStackTraceProgram X(argc, argv); 98 99 LLVMContext &Context = getGlobalContext(); 100 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 101 102 // Turn on -preserve-bc-uselistorder by default, but let the command-line 103 // override it. 104 setPreserveBitcodeUseListOrder(true); 105 106 cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); 107 108 // Use lazy loading, since we only care about selected global values. 109 SMDiagnostic Err; 110 std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); 111 112 if (!M.get()) { 113 Err.print(argv[0], errs()); 114 return 1; 115 } 116 117 // Use SetVector to avoid duplicates. 118 SetVector<GlobalValue *> GVs; 119 120 // Figure out which aliases we should extract. 121 for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { 122 GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); 123 if (!GA) { 124 errs() << argv[0] << ": program doesn't contain alias named '" 125 << ExtractAliases[i] << "'!\n"; 126 return 1; 127 } 128 GVs.insert(GA); 129 } 130 131 // Extract aliases via regular expression matching. 132 for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { 133 std::string Error; 134 Regex RegEx(ExtractRegExpAliases[i]); 135 if (!RegEx.isValid(Error)) { 136 errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " 137 "invalid regex: " << Error; 138 } 139 bool match = false; 140 for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); 141 GA != E; GA++) { 142 if (RegEx.match(GA->getName())) { 143 GVs.insert(&*GA); 144 match = true; 145 } 146 } 147 if (!match) { 148 errs() << argv[0] << ": program doesn't contain global named '" 149 << ExtractRegExpAliases[i] << "'!\n"; 150 return 1; 151 } 152 } 153 154 // Figure out which globals we should extract. 155 for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { 156 GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); 157 if (!GV) { 158 errs() << argv[0] << ": program doesn't contain global named '" 159 << ExtractGlobals[i] << "'!\n"; 160 return 1; 161 } 162 GVs.insert(GV); 163 } 164 165 // Extract globals via regular expression matching. 166 for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { 167 std::string Error; 168 Regex RegEx(ExtractRegExpGlobals[i]); 169 if (!RegEx.isValid(Error)) { 170 errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " 171 "invalid regex: " << Error; 172 } 173 bool match = false; 174 for (auto &GV : M->globals()) { 175 if (RegEx.match(GV.getName())) { 176 GVs.insert(&GV); 177 match = true; 178 } 179 } 180 if (!match) { 181 errs() << argv[0] << ": program doesn't contain global named '" 182 << ExtractRegExpGlobals[i] << "'!\n"; 183 return 1; 184 } 185 } 186 187 // Figure out which functions we should extract. 188 for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { 189 GlobalValue *GV = M->getFunction(ExtractFuncs[i]); 190 if (!GV) { 191 errs() << argv[0] << ": program doesn't contain function named '" 192 << ExtractFuncs[i] << "'!\n"; 193 return 1; 194 } 195 GVs.insert(GV); 196 } 197 // Extract functions via regular expression matching. 198 for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { 199 std::string Error; 200 StringRef RegExStr = ExtractRegExpFuncs[i]; 201 Regex RegEx(RegExStr); 202 if (!RegEx.isValid(Error)) { 203 errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " 204 "invalid regex: " << Error; 205 } 206 bool match = false; 207 for (Module::iterator F = M->begin(), E = M->end(); F != E; 208 F++) { 209 if (RegEx.match(F->getName())) { 210 GVs.insert(&*F); 211 match = true; 212 } 213 } 214 if (!match) { 215 errs() << argv[0] << ": program doesn't contain global named '" 216 << ExtractRegExpFuncs[i] << "'!\n"; 217 return 1; 218 } 219 } 220 221 // Materialize requisite global values. 222 if (!DeleteFn) 223 for (size_t i = 0, e = GVs.size(); i != e; ++i) { 224 GlobalValue *GV = GVs[i]; 225 if (std::error_code EC = GV->materialize()) { 226 errs() << argv[0] << ": error reading input: " << EC.message() << "\n"; 227 return 1; 228 } 229 } 230 else { 231 // Deleting. Materialize every GV that's *not* in GVs. 232 SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); 233 for (auto &G : M->globals()) { 234 if (!GVSet.count(&G)) { 235 if (std::error_code EC = G.materialize()) { 236 errs() << argv[0] << ": error reading input: " << EC.message() 237 << "\n"; 238 return 1; 239 } 240 } 241 } 242 for (auto &F : *M) { 243 if (!GVSet.count(&F)) { 244 if (std::error_code EC = F.materialize()) { 245 errs() << argv[0] << ": error reading input: " << EC.message() 246 << "\n"; 247 return 1; 248 } 249 } 250 } 251 } 252 253 // In addition to deleting all other functions, we also want to spiff it 254 // up a little bit. Do this now. 255 legacy::PassManager Passes; 256 257 std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end()); 258 259 Passes.add(createGVExtractionPass(Gvs, DeleteFn)); 260 if (!DeleteFn) 261 Passes.add(createGlobalDCEPass()); // Delete unreachable globals 262 Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info 263 Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls 264 265 std::error_code EC; 266 tool_output_file Out(OutputFilename, EC, sys::fs::F_None); 267 if (EC) { 268 errs() << EC.message() << '\n'; 269 return 1; 270 } 271 272 if (OutputAssembly) 273 Passes.add(createPrintModulePass(Out.os())); 274 else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) 275 Passes.add(createBitcodeWriterPass(Out.os())); 276 277 Passes.run(*M.get()); 278 279 // Declare success. 280 Out.keep(); 281 282 return 0; 283 } 284