1bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines/* 2bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * Copyright 2013, The Android Open Source Project 3bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * 4bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * Licensed under the Apache License, Version 2.0 (the "License"); 5bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * you may not use this file except in compliance with the License. 6bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * You may obtain a copy of the License at 7bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * 8bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * http://www.apache.org/licenses/LICENSE-2.0 9bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * 10bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * Unless required by applicable law or agreed to in writing, software 11bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * distributed under the License is distributed on an "AS IS" BASIS, 12bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * See the License for the specific language governing permissions and 14bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines * limitations under the License. 15bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines */ 16bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 17bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Analysis/Verifier.h" 18bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Bitcode/ReaderWriter.h" 19bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/IR/LLVMContext.h" 20bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/IR/Module.h" 21bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Pass.h" 22bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/PassManager.h" 23bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/CommandLine.h" 24bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/IRReader.h" 25bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/ManagedStatic.h" 26bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/PrettyStackTrace.h" 27bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/Signals.h" 28bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/SystemUtils.h" 29bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/ToolOutputFile.h" 30bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesusing namespace llvm; 31bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 32bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic cl::list<std::string> 33bfa9fc93c88510184399bb98e0faa8cc474061fbStephen HinesInputFilenames(cl::Positional, 34bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::desc("<input bitcode files>")); 35bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 36bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic cl::opt<std::string> 37bfa9fc93c88510184399bb98e0faa8cc474061fbStephen HinesOutputFilename("o", cl::desc("Override output filename"), cl::init("-"), 38bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::value_desc("filename")); 39bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 40bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic cl::opt<bool> 41bfa9fc93c88510184399bb98e0faa8cc474061fbStephen HinesOutputAssembly("S", 42bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::desc("Write output as LLVM assembly"), cl::Hidden); 43bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 44bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesnamespace { 45bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines class StripAttributes : public ModulePass { 46bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines public: 47bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines static char ID; 48bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 49bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines StripAttributes() : ModulePass(ID) { 50bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 51bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 52bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines bool runOnFunction(Function &F) { 53bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Remove any target-cpu and/or target-features attributes from each 54bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Function or Function declaration. 55bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (F.hasFnAttribute("target-cpu") || 56bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines F.hasFnAttribute("target-features")) { 57bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 58bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttrBuilder B; 59bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines B.addAttribute("target-cpu").addAttribute("target-features"); 60bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttributeSet ToStrip = AttributeSet::get(F.getContext(), 61bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttributeSet::FunctionIndex, B); 62bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines F.removeAttributes(AttributeSet::FunctionIndex, ToStrip); 63bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return true; 64bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 65bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return false; 66bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 67bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 68bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // We have to use a ModulePass, since a FunctionPass only gets run on 69bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // defined Functions (and not declared Functions). 70bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines virtual bool runOnModule(Module &M) { 71bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines bool Changed = false; 72bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 73bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Changed |= runOnFunction(*I); 74bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 75bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return Changed; 76bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 77bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines }; 78bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 79bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines llvm::ModulePass * createStripAttributePass() { 80bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return new StripAttributes(); 81bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 82bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 83bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 84bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 85bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hineschar StripAttributes::ID = 0; 86bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic RegisterPass<StripAttributes> RPSA("StripAttributes", 87bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines "Strip Function Attributes Pass"); 88bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 89bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 90bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic inline std::auto_ptr<Module> LoadFile(const char *argv0, 91bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines const std::string &FN, 92bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines LLVMContext& Context) { 93bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines sys::Path Filename; 94bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (!Filename.set(FN)) { 95bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << "Invalid file name: '" << FN << "'\n"; 96bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return std::auto_ptr<Module>(); 97bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 98bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 99bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines SMDiagnostic Err; 100bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Module* Result = 0; 101bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 102bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines const std::string &FNStr = Filename.str(); 103bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Result = ParseIRFile(FNStr, Err, Context); 104bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (Result) return std::auto_ptr<Module>(Result); // Load successful! 105bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 106bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Err.print(argv0, errs()); 107bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return std::auto_ptr<Module>(); 108bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 109bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 110bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 111bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesint main(int argc, char **argv) { 112bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Print a stack trace if we signal out. 113bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines sys::PrintStackTraceOnErrorSignal(); 114bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PrettyStackTraceProgram X(argc, argv); 115bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 116bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines LLVMContext &Context = getGlobalContext(); 117bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 118bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::ParseCommandLineOptions(argc, argv, "strip function attribute pass\n"); 119bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 120bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines std::string ErrorMessage; 121bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 122bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines std::auto_ptr<Module> M(LoadFile(argv[0], InputFilenames[0], Context)); 123bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (M.get() == 0) { 124bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << argv[0] << ": error loading file '" 125bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines << InputFilenames[0] << "'\n"; 126bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 127bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 128bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 129bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Perform the actual function attribute stripping. 130bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PassManager PM; 131bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PM.add(createStripAttributePass()); 132bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PM.run(*M.get()); 133bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 134bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines std::string ErrorInfo; 135bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines tool_output_file Out(OutputFilename.c_str(), ErrorInfo, 136bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines raw_fd_ostream::F_Binary); 137bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (!ErrorInfo.empty()) { 138bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << ErrorInfo << '\n'; 139bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 140bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 141bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 142bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (verifyModule(*M)) { 143bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << argv[0] << ": stripped module is broken!\n"; 144bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 145bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 146bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 147bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (OutputAssembly) { 148bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Out.os() << *M; 149bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } else if (!CheckBitcodeOutputToConsole(Out.os(), true)) { 150bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines WriteBitcodeToFile(M.get(), Out.os()); 151bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 152bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 153bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Out.keep(); 154bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 155bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 0; 156bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 157