OLD | NEW |
---|---|
1 //===- PNaClABIVerifyModule.cpp - Verify PNaCl ABI rules ------------------===// | 1 //===- PNaClABIVerifyModule.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 module-level PNaCl ABI requirements (specifically those that do not | 10 // Verify module-level PNaCl ABI requirements (specifically those that do not |
11 // require looking at the function bodies) | 11 // require looking at the function bodies) |
12 // | 12 // |
13 // | 13 // |
14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
15 | 15 |
16 #include "llvm/Pass.h" | |
17 #include "llvm/ADT/Twine.h" | 16 #include "llvm/ADT/Twine.h" |
18 #include "llvm/Analysis/NaCl.h" | 17 #include "llvm/Analysis/NaCl.h" |
19 #include "llvm/IR/Constants.h" | 18 #include "llvm/IR/Constants.h" |
20 #include "llvm/IR/DerivedTypes.h" | 19 #include "llvm/IR/DerivedTypes.h" |
20 #include "llvm/IR/NaClIntrinsics.h" | |
21 #include "llvm/IR/Instructions.h" | |
21 #include "llvm/IR/Intrinsics.h" | 22 #include "llvm/IR/Intrinsics.h" |
22 #include "llvm/IR/Module.h" | 23 #include "llvm/IR/Module.h" |
24 #include "llvm/Pass.h" | |
23 #include "llvm/Support/Debug.h" | 25 #include "llvm/Support/Debug.h" |
24 #include "llvm/Support/raw_ostream.h" | 26 #include "llvm/Support/raw_ostream.h" |
25 | 27 |
26 #include "PNaClABITypeChecker.h" | 28 #include "PNaClABITypeChecker.h" |
27 using namespace llvm; | 29 using namespace llvm; |
28 | 30 |
29 namespace llvm { | 31 namespace llvm { |
30 cl::opt<bool> | 32 cl::opt<bool> |
31 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", | 33 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", |
32 cl::desc("Allow debug metadata during PNaCl ABI verification."), | 34 cl::desc("Allow debug metadata during PNaCl ABI verification."), |
(...skipping 26 matching lines...) Expand all Loading... | |
59 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); | 61 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); |
60 } | 62 } |
61 ~PNaClABIVerifyModule() { | 63 ~PNaClABIVerifyModule() { |
62 if (ReporterIsOwned) | 64 if (ReporterIsOwned) |
63 delete Reporter; | 65 delete Reporter; |
64 } | 66 } |
65 bool runOnModule(Module &M); | 67 bool runOnModule(Module &M); |
66 virtual void print(raw_ostream &O, const Module *M) const; | 68 virtual void print(raw_ostream &O, const Module *M) const; |
67 private: | 69 private: |
68 void checkGlobalValueCommon(const GlobalValue *GV); | 70 void checkGlobalValueCommon(const GlobalValue *GV); |
69 bool isWhitelistedIntrinsic(const Function *F, unsigned ID); | 71 bool isWhitelistedIntrinsic(const NaCl::AtomicIntrinsics *AI, |
72 const Function *F, Intrinsic::ID ID); | |
70 bool isWhitelistedMetadata(const NamedMDNode *MD); | 73 bool isWhitelistedMetadata(const NamedMDNode *MD); |
71 void checkGlobalIsFlattened(const GlobalVariable *GV); | 74 void checkGlobalIsFlattened(const GlobalVariable *GV); |
72 PNaClABIErrorReporter *Reporter; | 75 PNaClABIErrorReporter *Reporter; |
73 bool ReporterIsOwned; | 76 bool ReporterIsOwned; |
74 bool StreamingMode; | 77 bool StreamingMode; |
75 }; | 78 }; |
76 | 79 |
77 static const char *linkageName(GlobalValue::LinkageTypes LT) { | 80 static const char *linkageName(GlobalValue::LinkageTypes LT) { |
78 // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp | 81 // This logic is taken from PrintLinkage in lib/VMCore/AsmWriter.cpp |
79 switch (LT) { | 82 switch (LT) { |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
163 if (FT->getNumParams() != 1) | 166 if (FT->getNumParams() != 1) |
164 return false; | 167 return false; |
165 Type *ParamType = FT->getParamType(0); | 168 Type *ParamType = FT->getParamType(0); |
166 LLVMContext &C = F->getContext(); | 169 LLVMContext &C = F->getContext(); |
167 Type *AcceptableTypes[] = { Type::getInt16Ty(C), | 170 Type *AcceptableTypes[] = { Type::getInt16Ty(C), |
168 Type::getInt32Ty(C), | 171 Type::getInt32Ty(C), |
169 Type::getInt64Ty(C) }; | 172 Type::getInt64Ty(C) }; |
170 return TypeAcceptable(ParamType, AcceptableTypes); | 173 return TypeAcceptable(ParamType, AcceptableTypes); |
171 } | 174 } |
172 | 175 |
176 static bool isWhitelistedAtomic(const NaCl::AtomicIntrinsics *AI, | |
177 const Function *F, Intrinsic::ID ID) { | |
178 FunctionType *FT = F->getFunctionType(); | |
179 for (NaCl::AtomicIntrinsics::const_iterator I = AI->begin(ID), | |
180 E = AI->end(ID); | |
181 I != E; ++I) { | |
182 bool Match = true; | |
183 for (size_t P = 0; P != I->NumParams; ++P) | |
Mark Seaborn
2013/07/02 19:16:02
Start a "{" block here since the body is multi-lin
JF
2013/07/02 23:14:54
Done.
| |
184 if (I->Parameter(P) != FT->getParamType(P)) | |
185 Match = false; | |
186 if (Match) | |
187 return true; | |
188 } | |
189 return false; | |
190 } | |
191 | |
173 // We accept cttz, ctlz, and ctpop for a limited set of types (i32, i64). | 192 // We accept cttz, ctlz, and ctpop for a limited set of types (i32, i64). |
174 static bool isWhitelistedCountBits(const Function *F, unsigned num_params) { | 193 static bool isWhitelistedCountBits(const Function *F, unsigned num_params) { |
175 FunctionType *FT = F->getFunctionType(); | 194 FunctionType *FT = F->getFunctionType(); |
176 if (FT->getNumParams() != num_params) | 195 if (FT->getNumParams() != num_params) |
177 return false; | 196 return false; |
178 Type *ParamType = FT->getParamType(0); | 197 Type *ParamType = FT->getParamType(0); |
179 LLVMContext &C = F->getContext(); | 198 LLVMContext &C = F->getContext(); |
180 Type *AcceptableTypes[] = { Type::getInt32Ty(C), Type::getInt64Ty(C) }; | 199 Type *AcceptableTypes[] = { Type::getInt32Ty(C), Type::getInt64Ty(C) }; |
181 return TypeAcceptable(ParamType, AcceptableTypes); | 200 return TypeAcceptable(ParamType, AcceptableTypes); |
182 } | 201 } |
183 | 202 |
184 bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const Function *F, | 203 bool PNaClABIVerifyModule::isWhitelistedIntrinsic(const NaCl::AtomicIntrinsics * AI, |
Mark Seaborn
2013/07/02 19:16:02
Line is >80 chars
JF
2013/07/02 23:14:54
Done.
| |
185 unsigned ID) { | 204 const Function *F, |
205 Intrinsic::ID ID) { | |
186 // Keep 3 categories of intrinsics for now. | 206 // Keep 3 categories of intrinsics for now. |
187 // (1) Allowed always | 207 // (1) Allowed. |
188 // (2) Never allowed | 208 // (2) Never allowed. |
189 // (3) "Dev" intrinsics, which may or may not be allowed. | 209 // (3) "Dev" intrinsics, which may or may not be allowed. |
190 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag. | 210 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag. |
191 // Please keep these sorted or grouped in a sensible way, within | 211 // Please keep these sorted or grouped in a sensible way, within |
192 // each category. | 212 // each category. |
193 switch(ID) { | 213 switch(ID) { |
194 // Disallow by default. | 214 // Disallow by default. |
195 default: return false; | 215 default: return false; |
196 // (1) Always allowed. | 216 // (1) Allowed. |
217 case Intrinsic::memcpy: | |
Mark Seaborn
2013/07/02 19:16:02
You'll need to rebase this on top of recent change
| |
218 case Intrinsic::memmove: | |
219 case Intrinsic::memset: | |
220 case Intrinsic::nacl_setjmp: | |
221 case Intrinsic::nacl_longjmp: | |
222 case Intrinsic::nacl_read_tp: | |
223 case Intrinsic::trap: | |
224 return true; | |
225 case Intrinsic::nacl_atomic_load: | |
226 case Intrinsic::nacl_atomic_store: | |
227 case Intrinsic::nacl_atomic_rmw: | |
228 case Intrinsic::nacl_atomic_cmpxchg: | |
229 case Intrinsic::nacl_atomic_fence: | |
230 return isWhitelistedAtomic(AI, F, ID); | |
197 case Intrinsic::bswap: return isWhitelistedBswap(F); | 231 case Intrinsic::bswap: return isWhitelistedBswap(F); |
198 case Intrinsic::ctlz: | 232 case Intrinsic::ctlz: |
199 case Intrinsic::cttz: return isWhitelistedCountBits(F, 2); | 233 case Intrinsic::cttz: return isWhitelistedCountBits(F, 2); |
200 case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1); | 234 case Intrinsic::ctpop: return isWhitelistedCountBits(F, 1); |
201 case Intrinsic::memcpy: | |
202 case Intrinsic::memmove: | |
203 case Intrinsic::memset: | |
204 case Intrinsic::nacl_read_tp: | |
205 case Intrinsic::nacl_setjmp: | |
206 case Intrinsic::nacl_longjmp: | |
207 case Intrinsic::trap: | |
208 return true; | |
209 | 235 |
210 // (2) Known to be never allowed. | 236 // (2) Known to be never allowed. |
211 case Intrinsic::not_intrinsic: | 237 case Intrinsic::not_intrinsic: |
212 // Trampolines depend on a target-specific-sized/aligned buffer. | 238 // Trampolines depend on a target-specific-sized/aligned buffer. |
213 case Intrinsic::adjust_trampoline: | 239 case Intrinsic::adjust_trampoline: |
214 case Intrinsic::init_trampoline: | 240 case Intrinsic::init_trampoline: |
215 // CXX exception handling is not stable. | 241 // CXX exception handling is not stable. |
216 case Intrinsic::eh_dwarf_cfa: | 242 case Intrinsic::eh_dwarf_cfa: |
217 case Intrinsic::eh_return_i32: | 243 case Intrinsic::eh_return_i32: |
218 case Intrinsic::eh_return_i64: | 244 case Intrinsic::eh_return_i64: |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 } | 413 } |
388 } | 414 } |
389 | 415 |
390 // No aliases allowed for now. | 416 // No aliases allowed for now. |
391 for (Module::alias_iterator MI = M.alias_begin(), | 417 for (Module::alias_iterator MI = M.alias_begin(), |
392 E = M.alias_end(); MI != E; ++MI) { | 418 E = M.alias_end(); MI != E; ++MI) { |
393 Reporter->addError() << "Variable " << MI->getName() << | 419 Reporter->addError() << "Variable " << MI->getName() << |
394 " is an alias (disallowed)\n"; | 420 " is an alias (disallowed)\n"; |
395 } | 421 } |
396 | 422 |
423 NaCl::AtomicIntrinsics AI(M.getContext()); | |
397 for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { | 424 for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { |
398 if (MI->isIntrinsic()) { | 425 if (MI->isIntrinsic()) { |
399 // Check intrinsics. | 426 // Check intrinsics. |
400 if (!isWhitelistedIntrinsic(MI, MI->getIntrinsicID())) { | 427 Intrinsic::ID ID = (Intrinsic::ID) MI->getIntrinsicID(); |
428 if (!isWhitelistedIntrinsic(&AI, MI, ID)) { | |
401 Reporter->addError() << "Function " << MI->getName() | 429 Reporter->addError() << "Function " << MI->getName() |
402 << " is a disallowed LLVM intrinsic\n"; | 430 << " is a disallowed LLVM intrinsic\n"; |
403 } | 431 } |
404 } else { | 432 } else { |
405 // Check types of functions and their arguments. Not necessary | 433 // Check types of functions and their arguments. Not necessary |
406 // for intrinsics, whose types are fixed anyway, and which have | 434 // for intrinsics, whose types are fixed anyway, and which have |
407 // argument types that we disallow such as i8. | 435 // argument types that we disallow such as i8. |
408 if (!PNaClABITypeChecker::isValidFunctionType(MI->getFunctionType())) { | 436 if (!PNaClABITypeChecker::isValidFunctionType(MI->getFunctionType())) { |
409 Reporter->addError() << "Function " << MI->getName() | 437 Reporter->addError() << "Function " << MI->getName() |
410 << " has disallowed type: " | 438 << " has disallowed type: " |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
471 } | 499 } |
472 | 500 |
473 char PNaClABIVerifyModule::ID = 0; | 501 char PNaClABIVerifyModule::ID = 0; |
474 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", | 502 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", |
475 "Verify module for PNaCl", false, true) | 503 "Verify module for PNaCl", false, true) |
476 | 504 |
477 ModulePass *llvm::createPNaClABIVerifyModulePass( | 505 ModulePass *llvm::createPNaClABIVerifyModulePass( |
478 PNaClABIErrorReporter *Reporter, bool StreamingMode) { | 506 PNaClABIErrorReporter *Reporter, bool StreamingMode) { |
479 return new PNaClABIVerifyModule(Reporter, StreamingMode); | 507 return new PNaClABIVerifyModule(Reporter, StreamingMode); |
480 } | 508 } |
OLD | NEW |