Chromium Code Reviews| 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 |