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/IRReader/IRReader.h" 23 #include "llvm/IR/LegacyPassManager.h" 24 #include "llvm/Support/CommandLine.h" 25 #include "llvm/Support/Error.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 static cl::opt<bool> PreserveBitcodeUseListOrder( 95 "preserve-bc-uselistorder", 96 cl::desc("Preserve use-list order when writing LLVM bitcode."), 97 cl::init(true), cl::Hidden); 98 99 static cl::opt<bool> PreserveAssemblyUseListOrder( 100 "preserve-ll-uselistorder", 101 cl::desc("Preserve use-list order when writing LLVM assembly."), 102 cl::init(false), cl::Hidden); 103 104 int main(int argc, char **argv) { 105 // Print a stack trace if we signal out. 106 sys::PrintStackTraceOnErrorSignal(argv[0]); 107 PrettyStackTraceProgram X(argc, argv); 108 109 LLVMContext Context; 110 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 111 cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); 112 113 // Use lazy loading, since we only care about selected global values. 114 SMDiagnostic Err; 115 std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); 116 117 if (!M.get()) { 118 Err.print(argv[0], errs()); 119 return 1; 120 } 121 122 // Use SetVector to avoid duplicates. 123 SetVector<GlobalValue *> GVs; 124 125 // Figure out which aliases we should extract. 126 for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { 127 GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); 128 if (!GA) { 129 errs() << argv[0] << ": program doesn't contain alias named '" 130 << ExtractAliases[i] << "'!\n"; 131 return 1; 132 } 133 GVs.insert(GA); 134 } 135 136 // Extract aliases via regular expression matching. 137 for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { 138 std::string Error; 139 Regex RegEx(ExtractRegExpAliases[i]); 140 if (!RegEx.isValid(Error)) { 141 errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " 142 "invalid regex: " << Error; 143 } 144 bool match = false; 145 for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); 146 GA != E; GA++) { 147 if (RegEx.match(GA->getName())) { 148 GVs.insert(&*GA); 149 match = true; 150 } 151 } 152 if (!match) { 153 errs() << argv[0] << ": program doesn't contain global named '" 154 << ExtractRegExpAliases[i] << "'!\n"; 155 return 1; 156 } 157 } 158 159 // Figure out which globals we should extract. 160 for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { 161 GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); 162 if (!GV) { 163 errs() << argv[0] << ": program doesn't contain global named '" 164 << ExtractGlobals[i] << "'!\n"; 165 return 1; 166 } 167 GVs.insert(GV); 168 } 169 170 // Extract globals via regular expression matching. 171 for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { 172 std::string Error; 173 Regex RegEx(ExtractRegExpGlobals[i]); 174 if (!RegEx.isValid(Error)) { 175 errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " 176 "invalid regex: " << Error; 177 } 178 bool match = false; 179 for (auto &GV : M->globals()) { 180 if (RegEx.match(GV.getName())) { 181 GVs.insert(&GV); 182 match = true; 183 } 184 } 185 if (!match) { 186 errs() << argv[0] << ": program doesn't contain global named '" 187 << ExtractRegExpGlobals[i] << "'!\n"; 188 return 1; 189 } 190 } 191 192 // Figure out which functions we should extract. 193 for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { 194 GlobalValue *GV = M->getFunction(ExtractFuncs[i]); 195 if (!GV) { 196 errs() << argv[0] << ": program doesn't contain function named '" 197 << ExtractFuncs[i] << "'!\n"; 198 return 1; 199 } 200 GVs.insert(GV); 201 } 202 // Extract functions via regular expression matching. 203 for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { 204 std::string Error; 205 StringRef RegExStr = ExtractRegExpFuncs[i]; 206 Regex RegEx(RegExStr); 207 if (!RegEx.isValid(Error)) { 208 errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " 209 "invalid regex: " << Error; 210 } 211 bool match = false; 212 for (Module::iterator F = M->begin(), E = M->end(); F != E; 213 F++) { 214 if (RegEx.match(F->getName())) { 215 GVs.insert(&*F); 216 match = true; 217 } 218 } 219 if (!match) { 220 errs() << argv[0] << ": program doesn't contain global named '" 221 << ExtractRegExpFuncs[i] << "'!\n"; 222 return 1; 223 } 224 } 225 226 // Use *argv instead of argv[0] to work around a wrong GCC warning. 227 ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: "); 228 229 auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); }; 230 231 // Materialize requisite global values. 232 if (!DeleteFn) { 233 for (size_t i = 0, e = GVs.size(); i != e; ++i) 234 Materialize(*GVs[i]); 235 } else { 236 // Deleting. Materialize every GV that's *not* in GVs. 237 SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); 238 for (auto &F : *M) { 239 if (!GVSet.count(&F)) 240 Materialize(F); 241 } 242 } 243 244 { 245 std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end()); 246 legacy::PassManager Extract; 247 Extract.add(createGVExtractionPass(Gvs, DeleteFn)); 248 Extract.run(*M); 249 250 // Now that we have all the GVs we want, mark the module as fully 251 // materialized. 252 // FIXME: should the GVExtractionPass handle this? 253 ExitOnErr(M->materializeAll()); 254 } 255 256 // In addition to deleting all other functions, we also want to spiff it 257 // up a little bit. Do this now. 258 legacy::PassManager Passes; 259 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( 274 createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder)); 275 else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) 276 Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder)); 277 278 Passes.run(*M.get()); 279 280 // Declare success. 281 Out.keep(); 282 283 return 0; 284 } 285