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/Bitcode/ReaderWriter.h" 18bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/IR/LLVMContext.h" 19bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/IR/Module.h" 20c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray#include "llvm/IR/Verifier.h" 2186e4506416f974d3c717deaca2b17b0792cc2d49Stephen Hines#include "llvm/IRReader/IRReader.h" 22bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Pass.h" 23bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/PassManager.h" 24bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/CommandLine.h" 25a630078b32eb37a8de91ae09e26babf235d4fc9fStephen Hines#include "llvm/Support/FileSystem.h" 26bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/ManagedStatic.h" 27bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/PrettyStackTrace.h" 28bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/Signals.h" 2986e4506416f974d3c717deaca2b17b0792cc2d49Stephen Hines#include "llvm/Support/SourceMgr.h" 30bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/SystemUtils.h" 31bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Support/ToolOutputFile.h" 32bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesusing namespace llvm; 33bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 34bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic cl::list<std::string> 35bfa9fc93c88510184399bb98e0faa8cc474061fbStephen HinesInputFilenames(cl::Positional, 36bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::desc("<input bitcode files>")); 37bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 38bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic cl::opt<std::string> 39bfa9fc93c88510184399bb98e0faa8cc474061fbStephen HinesOutputFilename("o", cl::desc("Override output filename"), cl::init("-"), 40bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::value_desc("filename")); 41bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 42bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic cl::opt<bool> 43bfa9fc93c88510184399bb98e0faa8cc474061fbStephen HinesOutputAssembly("S", 44bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::desc("Write output as LLVM assembly"), cl::Hidden); 45bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 46bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesnamespace { 47bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines class StripAttributes : public ModulePass { 48bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines public: 49bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines static char ID; 50bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 51bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines StripAttributes() : ModulePass(ID) { 52bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 53bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 54bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines bool runOnFunction(Function &F) { 55bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Remove any target-cpu and/or target-features attributes from each 56bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Function or Function declaration. 57bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (F.hasFnAttribute("target-cpu") || 58bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines F.hasFnAttribute("target-features")) { 59bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 60bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttrBuilder B; 61bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines B.addAttribute("target-cpu").addAttribute("target-features"); 62bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttributeSet ToStrip = AttributeSet::get(F.getContext(), 63bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttributeSet::FunctionIndex, B); 64bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines F.removeAttributes(AttributeSet::FunctionIndex, ToStrip); 65bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return true; 66bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 67bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return false; 68bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 69bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 70bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // We have to use a ModulePass, since a FunctionPass only gets run on 71bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // defined Functions (and not declared Functions). 72bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines virtual bool runOnModule(Module &M) { 73bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines bool Changed = false; 74bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 75bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Changed |= runOnFunction(*I); 76bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 77bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return Changed; 78bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 79bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines }; 80bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 81bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines llvm::ModulePass * createStripAttributePass() { 82bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return new StripAttributes(); 83bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 84bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 85bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 86bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 87bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hineschar StripAttributes::ID = 0; 88bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic RegisterPass<StripAttributes> RPSA("StripAttributes", 89bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines "Strip Function Attributes Pass"); 90bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 91bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 92c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murraystatic inline std::unique_ptr<Module> LoadFile(const char *argv0, 93c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray const std::string &FN, 94c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray LLVMContext& Context) { 95bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines SMDiagnostic Err; 96b10c3a7d91556ef31ce91ef018fee4722b783960Stephen Hines Module* Result = ParseIRFile(FN, Err, Context); 97b10c3a7d91556ef31ce91ef018fee4722b783960Stephen Hines if (Result) { 98c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray return std::unique_ptr<Module>(Result); // Load successful! 99b10c3a7d91556ef31ce91ef018fee4722b783960Stephen Hines } 100bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 101bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Err.print(argv0, errs()); 102c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray return std::unique_ptr<Module>(); 103bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 104bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 105bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 106bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesint main(int argc, char **argv) { 107bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Print a stack trace if we signal out. 108bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines sys::PrintStackTraceOnErrorSignal(); 109bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PrettyStackTraceProgram X(argc, argv); 110bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 111bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines LLVMContext &Context = getGlobalContext(); 112bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 113bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::ParseCommandLineOptions(argc, argv, "strip function attribute pass\n"); 114bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 115bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines std::string ErrorMessage; 116bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 117c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray std::unique_ptr<Module> M(LoadFile(argv[0], InputFilenames[0], Context)); 118bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (M.get() == 0) { 119bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << argv[0] << ": error loading file '" 120bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines << InputFilenames[0] << "'\n"; 121bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 122bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 123bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 124bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Perform the actual function attribute stripping. 125bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PassManager PM; 126bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PM.add(createStripAttributePass()); 127bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PM.run(*M.get()); 128bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 129bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines std::string ErrorInfo; 130bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines tool_output_file Out(OutputFilename.c_str(), ErrorInfo, 131c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray sys::fs::F_None); 132bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (!ErrorInfo.empty()) { 133bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << ErrorInfo << '\n'; 134bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 135bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 136bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 137bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (verifyModule(*M)) { 138bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << argv[0] << ": stripped module is broken!\n"; 139bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 140bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 141bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 142bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (OutputAssembly) { 143bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Out.os() << *M; 144bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } else if (!CheckBitcodeOutputToConsole(Out.os(), true)) { 145bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines WriteBitcodeToFile(M.get(), Out.os()); 146bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 147bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 148bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Out.keep(); 149bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 150bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 0; 151bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 152