| 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. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 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), Errors(ErrorsString), |
| 34 Strict(false), ErrorCount(0) {} |
| 34 bool runOnFunction(Function &F); | 35 bool runOnFunction(Function &F); |
| 35 virtual void print(raw_ostream &O, const Module *M) const; | 36 virtual void print(raw_ostream &O, const Module *M) const; |
| 37 virtual void setStrict(bool Strict_) { Strict = Strict_; } |
| 38 virtual int getErrorCount() { return ErrorCount; } |
| 36 private: | 39 private: |
| 37 PNaClABITypeChecker TC; | 40 PNaClABITypeChecker TC; |
| 38 std::string ErrorsString; | 41 std::string ErrorsString; |
| 39 raw_string_ostream Errors; | 42 raw_string_ostream Errors; |
| 43 bool Strict; |
| 44 int ErrorCount; |
| 40 }; | 45 }; |
| 41 | 46 |
| 42 } // and anonymous namespace | 47 } // and anonymous namespace |
| 43 | 48 |
| 44 bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { | 49 bool PNaClABIVerifyFunctions::runOnFunction(Function &F) { |
| 45 // For now just start with new errors on each function; this may change | 50 // For now just start with new errors on each function; this may change |
| 46 // once we want to do something with them other than just calling print() | 51 // once we want to do something with them other than just calling print() |
| 47 ErrorsString.clear(); | 52 ErrorsString.clear(); |
| 53 ErrorCount = 0; |
| 48 // TODO: only report one error per instruction | 54 // TODO: only report one error per instruction |
| 49 for (Function::const_iterator FI = F.begin(), FE = F.end(); | 55 for (Function::const_iterator FI = F.begin(), FE = F.end(); |
| 50 FI != FE; ++FI) { | 56 FI != FE; ++FI) { |
| 51 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); | 57 for (BasicBlock::const_iterator BBI = FI->begin(), BBE = FI->end(); |
| 52 BBI != BBE; ++BBI) { | 58 BBI != BBE; ++BBI) { |
| 53 switch (BBI->getOpcode()) { | 59 switch (BBI->getOpcode()) { |
| 54 // Disallowed instructions. Default is to disallow. | 60 // Disallowed instructions. Default is to disallow. |
| 55 default: | 61 default: |
| 56 // indirectbr may interfere with streaming | 62 // indirectbr may interfere with streaming |
| 57 case Instruction::IndirectBr: | 63 case Instruction::IndirectBr: |
| 58 // No vector instructions yet | 64 // No vector instructions yet |
| 59 case Instruction::ExtractElement: | 65 case Instruction::ExtractElement: |
| 60 case Instruction::InsertElement: | 66 case Instruction::InsertElement: |
| 61 case Instruction::ShuffleVector: | 67 case Instruction::ShuffleVector: |
| 62 Errors << "Function " + F.getName() + | 68 Errors << "Function " + F.getName() + |
| 63 " has disallowed instruction: " + | 69 " has disallowed instruction: " + |
| 64 BBI->getOpcodeName() + "\n"; | 70 BBI->getOpcodeName() + "\n"; |
| 71 ErrorCount++; |
| 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Errors << "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"; |
| 139 ErrorCount++; |
| 132 } | 140 } |
| 133 | 141 |
| 134 // Check the instruction operands. Operands which are Instructions will | 142 // Check the instruction operands. Operands which are Instructions will |
| 135 // be checked on their own here, and GlobalValues will be checked by the | 143 // be checked on their own here, and GlobalValues will be checked by the |
| 136 // Module verifier. That leaves Constants. | 144 // Module verifier. That leaves Constants. |
| 137 // Switches are implemented in the in-memory IR with vectors, so don't | 145 // Switches are implemented in the in-memory IR with vectors, so don't |
| 138 // check them. | 146 // check them. |
| 139 if (!isa<SwitchInst>(*BBI)) | 147 if (!isa<SwitchInst>(*BBI)) |
| 140 for (User::const_op_iterator OI = BBI->op_begin(), OE = BBI->op_end(); | 148 for (User::const_op_iterator OI = BBI->op_begin(), OE = BBI->op_end(); |
| 141 OI != OE; OI++) { | 149 OI != OE; OI++) { |
| 142 if (isa<Constant>(OI) && !isa<GlobalValue>(OI)) { | 150 if (isa<Constant>(OI) && !isa<GlobalValue>(OI)) { |
| 143 Type *T = TC.checkTypesInConstant(cast<Constant>(*OI)); | 151 Type *T = TC.checkTypesInConstant(cast<Constant>(*OI)); |
| 144 if (T) | 152 if (T) { |
| 145 Errors << "Function " + F.getName() + | 153 Errors << "Function " + F.getName() + |
| 146 " has instruction operand with disallowed type: " + | 154 " has instruction operand with disallowed type: " + |
| 147 PNaClABITypeChecker::getTypeName(T) + "\n"; | 155 PNaClABITypeChecker::getTypeName(T) + "\n"; |
| 156 ErrorCount++; |
| 157 } |
| 148 } | 158 } |
| 149 } | 159 } |
| 150 | 160 |
| 151 // Get types hiding in metadata attached to the instruction | 161 // Get types hiding in metadata attached to the instruction |
| 152 SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; | 162 SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst; |
| 153 BBI->getAllMetadataOtherThanDebugLoc(MDForInst); | 163 BBI->getAllMetadataOtherThanDebugLoc(MDForInst); |
| 154 for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { | 164 for (unsigned i = 0, e = MDForInst.size(); i != e; i++) { |
| 155 Type *T = TC.checkTypesInMDNode(MDForInst[i].second); | 165 Type *T = TC.checkTypesInMDNode(MDForInst[i].second); |
| 156 if (T) | 166 if (T) { |
| 157 Errors << "Function " + F.getName() + | 167 Errors << "Function " + F.getName() + |
| 158 " has instruction metadata containing disallowed type: " + | 168 " has instruction metadata containing disallowed type: " + |
| 159 PNaClABITypeChecker::getTypeName(T) + "\n"; | 169 PNaClABITypeChecker::getTypeName(T) + "\n"; |
| 170 ErrorCount++; |
| 171 } |
| 160 } | 172 } |
| 161 } | 173 } |
| 162 } | 174 } |
| 163 | 175 |
| 164 Errors.flush(); | 176 Errors.flush(); |
| 177 if (Strict && ErrorCount > 0) { |
| 178 report_fatal_error("Function " + F.getName() + |
| 179 " is not valid PNaCl bitcode:\n" + ErrorsString); |
| 180 } |
| 165 return false; | 181 return false; |
| 166 } | 182 } |
| 167 | 183 |
| 168 void PNaClABIVerifyFunctions::print(llvm::raw_ostream &O, const Module *M) | 184 void PNaClABIVerifyFunctions::print(llvm::raw_ostream &O, const Module *M) |
| 169 const { | 185 const { |
| 170 O << ErrorsString; | 186 O << ErrorsString; |
| 171 } | 187 } |
| 172 | 188 |
| 173 char PNaClABIVerifyFunctions::ID = 0; | 189 char PNaClABIVerifyFunctions::ID = 0; |
| 174 | 190 |
| 175 static RegisterPass<PNaClABIVerifyFunctions> X("verify-pnaclabi-functions", | 191 static RegisterPass<PNaClABIVerifyFunctions> X("verify-pnaclabi-functions", |
| 176 "Verify functions for PNaCl", false, false); | 192 "Verify functions for PNaCl", false, false); |
| 177 | 193 |
| 178 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass() { | 194 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass(bool Strict) { |
| 179 return new PNaClABIVerifyFunctions(); | 195 PNaClABIVerifyFunctions *P = new PNaClABIVerifyFunctions(); |
| 196 P->setStrict(Strict); |
| 197 return P; |
| 180 } | 198 } |
| OLD | NEW |