| OLD | NEW |
| 1 //===- PNaClABIVerifyFunctions.cpp - Verify PNaCl ABI rules --------===// | 1 //===- PNaClABIVerifyFunctions.cpp - Verify PNaCl ABI rules --------===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // Verify function-level PNaCl ABI requirements. | 10 // Verify function-level PNaCl ABI requirements. |
| 11 // | 11 // |
| 12 // | 12 // |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "llvm/Pass.h" | 15 #include "llvm/Pass.h" |
| 16 #include "llvm/ADT/Twine.h" | 16 #include "llvm/ADT/Twine.h" |
| 17 #include "llvm/Analysis/NaCl.h" |
| 17 #include "llvm/IR/Function.h" | 18 #include "llvm/IR/Function.h" |
| 18 #include "llvm/IR/Instructions.h" | 19 #include "llvm/IR/Instructions.h" |
| 19 #include "llvm/IR/Metadata.h" | 20 #include "llvm/IR/Metadata.h" |
| 20 #include "llvm/Support/raw_ostream.h" | 21 #include "llvm/Support/raw_ostream.h" |
| 21 #include "llvm/Analysis/NaCl.h" | |
| 22 | 22 |
| 23 #include "PNaClABITypeChecker.h" | 23 #include "PNaClABITypeChecker.h" |
| 24 using namespace llvm; | 24 using namespace llvm; |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // Checks that examine anything in the function body should be in | 28 // Checks that examine anything in the function body should be in |
| 29 // FunctionPasses to make them streaming-friendly | 29 // FunctionPasses to make them streaming-friendly |
| 30 class PNaClABIVerifyFunctions : public FunctionPass { | 30 class PNaClABIVerifyFunctions : public FunctionPass { |
| 31 public: | 31 public: |
| 32 static char ID; | 32 static char ID; |
| 33 PNaClABIVerifyFunctions() : FunctionPass(ID), Errors(ErrorsString) {} | 33 PNaClABIVerifyFunctions() : FunctionPass(ID), |
| 34 Reporter(new PNaClABIErrorReporter), |
| 35 ReporterIsOwned(true) {} |
| 36 explicit PNaClABIVerifyFunctions(PNaClABIErrorReporter *Reporter_) : |
| 37 FunctionPass(ID), |
| 38 Reporter(Reporter_), |
| 39 ReporterIsOwned(false) {} |
| 40 ~PNaClABIVerifyFunctions() { |
| 41 if (ReporterIsOwned) |
| 42 delete Reporter; |
| 43 } |
| 34 bool runOnFunction(Function &F); | 44 bool runOnFunction(Function &F); |
| 35 virtual void print(raw_ostream &O, const Module *M) const; | 45 virtual void print(raw_ostream &O, const Module *M) const; |
| 36 private: | 46 private: |
| 37 PNaClABITypeChecker TC; | 47 PNaClABITypeChecker TC; |
| 38 std::string ErrorsString; | 48 PNaClABIErrorReporter *Reporter; |
| 39 raw_string_ostream Errors; | 49 bool ReporterIsOwned; |
| 40 }; | 50 }; |
| 41 | 51 |
| 42 } // and anonymous namespace | 52 } // and anonymous namespace |
| 43 | 53 |
| 44 bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { | 54 bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { |
| 45 // For now just start with new errors on each function; this may change | 55 // TODO: only report one error per instruction? |
| 46 // once we want to do something with them other than just calling print() | |
| 47 ErrorsString.clear(); | |
| 48 // TODO: only report one error per instruction | |
| 49 for (Function::const_iterator FI = F.begin(), FE = F.end(); | 56 for (Function::const_iterator FI = F.begin(), FE = F.end(); |
| 50 FI != FE; ++FI) { | 57 FI != FE; ++FI) { |
| 51 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); | 58 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); |
| 52 BBI != BBE; ++BBI) { | 59 BBI != BBE; ++BBI) { |
| 53 switch (BBI->getOpcode()) { | 60 switch (BBI->getOpcode()) { |
| 54 // Disallowed instructions. Default is to disallow. | 61 // Disallowed instructions. Default is to disallow. |
| 55 default: | 62 default: |
| 56 // indirectbr may interfere with streaming | 63 // indirectbr may interfere with streaming |
| 57 case Instruction::IndirectBr: | 64 case Instruction::IndirectBr: |
| 58 // No vector instructions yet | 65 // No vector instructions yet |
| 59 case Instruction::ExtractElement: | 66 case Instruction::ExtractElement: |
| 60 case Instruction::InsertElement: | 67 case Instruction::InsertElement: |
| 61 case Instruction::ShuffleVector: | 68 case Instruction::ShuffleVector: |
| 62 Errors << "Function " + F.getName() + | 69 Reporter->addError() << "Function " << F.getName() << |
| 63 " has disallowed instruction: " + | 70 " has disallowed instruction: " << |
| 64 BBI->getOpcodeName() + "\n"; | 71 BBI->getOpcodeName() << "\n"; |
| 65 break; | 72 break; |
| 66 | 73 |
| 67 // Terminator instructions | 74 // Terminator instructions |
| 68 case Instruction::Ret: | 75 case Instruction::Ret: |
| 69 case Instruction::Br: | 76 case Instruction::Br: |
| 70 case Instruction::Switch: | 77 case Instruction::Switch: |
| 71 case Instruction::Resume: | 78 case Instruction::Resume: |
| 72 case Instruction::Unreachable: | 79 case Instruction::Unreachable: |
| 73 case Instruction::Invoke: | 80 case Instruction::Invoke: |
| 74 // Binary operations | 81 // Binary operations |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 119 case Instruction::FCmp: | 126 case Instruction::FCmp: |
| 120 case Instruction::PHI: | 127 case Instruction::PHI: |
| 121 case Instruction::Select: | 128 case Instruction::Select: |
| 122 case Instruction::Call: | 129 case Instruction::Call: |
| 123 case Instruction::VAArg: | 130 case Instruction::VAArg: |
| 124 case Instruction::LandingPad: | 131 case Instruction::LandingPad: |
| 125 break; | 132 break; |
| 126 } | 133 } |
| 127 // Check the types. First check the type of the instruction. | 134 // Check the types. First check the type of the instruction. |
| 128 if (!TC.isValidType(BBI->getType())) { | 135 if (!TC.isValidType(BBI->getType())) { |
| 129 Errors << "Function " + F.getName() + | 136 Reporter->addError() << "Function " << F.getName() << |
| 130 " has instruction with disallowed type: " + | 137 " has instruction with disallowed type: " << |
| 131 PNaClABITypeChecker::getTypeName(BBI->getType()) + "\n"; | 138 PNaClABITypeChecker::getTypeName(BBI->getType()) << "\n"; |
| 132 } | 139 } |
| 133 | 140 |
| 134 // Check the instruction operands. Operands which are Instructions will | 141 // Check the instruction operands. Operands which are Instructions will |
| 135 // be checked on their own here, and GlobalValues will be checked by the | 142 // be checked on their own here, and GlobalValues will be checked by the |
| 136 // Module verifier. That leaves Constants. | 143 // Module verifier. That leaves Constants. |
| 137 // Switches are implemented in the in-memory IR with vectors, so don't | 144 // Switches are implemented in the in-memory IR with vectors, so don't |
| 138 // check them. | 145 // check them. |
| 139 if (!isa<SwitchInst>(*BBI)) | 146 if (!isa<SwitchInst>(*BBI)) |
| 140 for (User::const_op_iterator OI = BBI->op_begin(), OE = BBI->op_end(); | 147 for (User::const_op_iterator OI = BBI->op_begin(), OE = BBI->op_end(); |
| 141 OI != OE; OI++) { | 148 OI != OE; OI++) { |
| 142 if (isa<Constant>(OI) && !isa<GlobalValue>(OI)) { | 149 if (isa<Constant>(OI) && !isa<GlobalValue>(OI)) { |
| 143 Type *T = TC.checkTypesInConstant(cast<Constant>(*OI)); | 150 Type *T = TC.checkTypesInConstant(cast<Constant>(*OI)); |
| 144 if (T) | 151 if (T) { |
| 145 Errors << "Function " + F.getName() + | 152 Reporter->addError() << "Function " << F.getName() << |
| 146 " has instruction operand with disallowed type: " + | 153 " has instruction operand with disallowed type: " << |
| 147 PNaClABITypeChecker::getTypeName(T) + "\n"; | 154 PNaClABITypeChecker::getTypeName(T) << "\n"; |
| 155 } |
| 148 } | 156 } |
| 149 } | 157 } |
| 150 | 158 |
| 151 // Get types hiding in metadata attached to the instruction | 159 // Get types hiding in metadata attached to the instruction |
| 152 SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; | 160 SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; |
| 153 BBI->getAllMetadataOtherThanDebugLoc(MDForInst); | 161 BBI->getAllMetadataOtherThanDebugLoc(MDForInst); |
| 154 for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { | 162 for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { |
| 155 Type *T = TC.checkTypesInMDNode(MDForInst[i].second); | 163 Type *T = TC.checkTypesInMDNode(MDForInst[i].second); |
| 156 if (T) | 164 if (T) { |
| 157 Errors << "Function " + F.getName() + | 165 Reporter->addError() << "Function " << F.getName() << |
| 158 " has instruction metadata containing disallowed type: " + | 166 " has instruction metadata containing disallowed type: " << |
| 159 PNaClABITypeChecker::getTypeName(T) + "\n"; | 167 PNaClABITypeChecker::getTypeName(T) << "\n"; |
| 168 } |
| 160 } | 169 } |
| 161 } | 170 } |
| 162 } | 171 } |
| 163 | 172 |
| 164 Errors.flush(); | |
| 165 return false; | 173 return false; |
| 166 } | 174 } |
| 167 | 175 |
| 176 // This method exists so that the passes can easily be run with opt -analyze. |
| 177 // In this case the default constructor is used and we want to reset the error |
| 178 // messages after each print. |
| 168 void PNaClABIVerifyFunctions::print(llvm::raw_ostream &O, const Module *M) | 179 void PNaClABIVerifyFunctions::print(llvm::raw_ostream &O, const Module *M) |
| 169 const { | 180 const { |
| 170 O << ErrorsString; | 181 Reporter->printErrors(O); |
| 182 Reporter->reset(); |
| 171 } | 183 } |
| 172 | 184 |
| 173 char PNaClABIVerifyFunctions::ID = 0; | 185 char PNaClABIVerifyFunctions::ID = 0; |
| 174 | 186 |
| 175 static RegisterPass<PNaClABIVerifyFunctions> X("verify-pnaclabi-functions", | 187 static RegisterPass<PNaClABIVerifyFunctions> X("verify-pnaclabi-functions", |
| 176 "Verify functions for PNaCl", false, false); | 188 "Verify functions for PNaCl", false, false); |
| 177 | 189 |
| 178 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass() { | 190 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( |
| 179 return new PNaClABIVerifyFunctions(); | 191 PNaClABIErrorReporter *Reporter) { |
| 192 return new PNaClABIVerifyFunctions(Reporter); |
| 180 } | 193 } |
| OLD | NEW |