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 |