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