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 |