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" 191bd9f627fa0affb457507e86b0b6684c695fe726Stephen Hines#include "llvm/IR/LegacyPassManager.h" 20bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/IR/Module.h" 21c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray#include "llvm/IR/Verifier.h" 2286e4506416f974d3c717deaca2b17b0792cc2d49Stephen Hines#include "llvm/IRReader/IRReader.h" 23bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines#include "llvm/Pass.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 54c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines virtual void getAnalysisUsage(llvm::AnalysisUsage &AU) const override { 55c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines AU.setPreservesAll(); 56c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines } 57c754d49ee856be620e041348a9f2b3d5610a5a26Stephen Hines 58bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines bool runOnFunction(Function &F) { 59bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Remove any target-cpu and/or target-features attributes from each 60bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Function or Function declaration. 61bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (F.hasFnAttribute("target-cpu") || 62bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines F.hasFnAttribute("target-features")) { 63bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 64bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttrBuilder B; 65bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines B.addAttribute("target-cpu").addAttribute("target-features"); 66bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttributeSet ToStrip = AttributeSet::get(F.getContext(), 67bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines AttributeSet::FunctionIndex, B); 68bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines F.removeAttributes(AttributeSet::FunctionIndex, ToStrip); 69bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return true; 70bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 71bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return false; 72bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 73bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 74bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // We have to use a ModulePass, since a FunctionPass only gets run on 75bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // defined Functions (and not declared Functions). 76bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines virtual bool runOnModule(Module &M) { 77bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines bool Changed = false; 78bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { 79bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Changed |= runOnFunction(*I); 80bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 81bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return Changed; 82bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 83bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines }; 84bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 85bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines llvm::ModulePass * createStripAttributePass() { 86bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return new StripAttributes(); 87bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 88bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 89bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 90bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 91bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hineschar StripAttributes::ID = 0; 92bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesstatic RegisterPass<StripAttributes> RPSA("StripAttributes", 93bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines "Strip Function Attributes Pass"); 94bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 95bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 96c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murraystatic inline std::unique_ptr<Module> LoadFile(const char *argv0, 97c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray const std::string &FN, 98c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray LLVMContext& Context) { 99bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines SMDiagnostic Err; 100579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines std::unique_ptr<Module> Result = parseIRFile(FN, Err, Context); 101b10c3a7d91556ef31ce91ef018fee4722b783960Stephen Hines if (Result) { 102579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines return Result; // Load successful! 103b10c3a7d91556ef31ce91ef018fee4722b783960Stephen Hines } 104bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 105bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Err.print(argv0, errs()); 106c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray return std::unique_ptr<Module>(); 107bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 108bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 109bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 110bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hinesint main(int argc, char **argv) { 111bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Print a stack trace if we signal out. 112bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines sys::PrintStackTraceOnErrorSignal(); 113bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PrettyStackTraceProgram X(argc, argv); 114bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 115bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines LLVMContext &Context = getGlobalContext(); 116bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. 117bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines cl::ParseCommandLineOptions(argc, argv, "strip function attribute pass\n"); 118bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 119bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines std::string ErrorMessage; 120bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 121c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray std::unique_ptr<Module> M(LoadFile(argv[0], InputFilenames[0], Context)); 122bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (M.get() == 0) { 123bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << argv[0] << ": error loading file '" 124bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines << InputFilenames[0] << "'\n"; 125bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 126bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 127bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 128bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines // Perform the actual function attribute stripping. 1291bd9f627fa0affb457507e86b0b6684c695fe726Stephen Hines legacy::PassManager PM; 130bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PM.add(createStripAttributePass()); 131bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines PM.run(*M.get()); 132bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 133579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines std::error_code EC; 134579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines tool_output_file Out(OutputFilename.c_str(), EC, 135c2074caf075818abb6d3689ad924ca09f4a5ba1fTim Murray sys::fs::F_None); 136579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines if (EC) { 137579361346abc6696c805e3904a18178ebce4e4a3Stephen Hines errs() << EC.message() << '\n'; 138bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 139bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 140bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 141bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (verifyModule(*M)) { 142bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines errs() << argv[0] << ": stripped module is broken!\n"; 143bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 1; 144bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 145bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 146bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines if (OutputAssembly) { 147bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Out.os() << *M; 148bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } else if (!CheckBitcodeOutputToConsole(Out.os(), true)) { 149bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines WriteBitcodeToFile(M.get(), Out.os()); 150bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines } 151bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 152bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines Out.keep(); 153bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines 154bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines return 0; 155bfa9fc93c88510184399bb98e0faa8cc474061fbStephen Hines} 156