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" | 16 #include "llvm/ADT/STLExtras.h" |
| 17 #include "llvm/ADT/StringMap.h" | 17 #include "llvm/ADT/StringMap.h" |
| 18 #include "llvm/ADT/Twine.h" | 18 #include "llvm/ADT/Twine.h" |
| 19 #include "llvm/Analysis/NaCl.h" | 19 #include "llvm/Analysis/NaCl.h" |
| 20 #include "llvm/IR/Constants.h" | 20 #include "llvm/IR/Constants.h" |
| 21 #include "llvm/IR/DerivedTypes.h" | 21 #include "llvm/IR/DerivedTypes.h" |
| 22 #include "llvm/IR/Instructions.h" | |
| 22 #include "llvm/IR/Intrinsics.h" | 23 #include "llvm/IR/Intrinsics.h" |
| 23 #include "llvm/IR/Module.h" | 24 #include "llvm/IR/Module.h" |
| 25 #include "llvm/IR/NaClIntrinsics.h" | |
| 26 #include "llvm/Pass.h" | |
| 24 #include "llvm/Support/Debug.h" | 27 #include "llvm/Support/Debug.h" |
| 25 #include "llvm/Support/raw_ostream.h" | 28 #include "llvm/Support/raw_ostream.h" |
| 26 | 29 |
| 27 #include "PNaClABITypeChecker.h" | 30 #include "PNaClABITypeChecker.h" |
| 28 using namespace llvm; | 31 using namespace llvm; |
| 29 | 32 |
| 30 namespace llvm { | 33 namespace llvm { |
| 31 cl::opt<bool> | 34 cl::opt<bool> |
| 32 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", | 35 PNaClABIAllowDebugMetadata("pnaclabi-allow-debug-metadata", |
| 33 cl::desc("Allow debug metadata during PNaCl ABI verification."), | 36 cl::desc("Allow debug metadata during PNaCl ABI verification."), |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 60 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); | 63 initializePNaClABIVerifyModulePass(*PassRegistry::getPassRegistry()); |
| 61 } | 64 } |
| 62 ~PNaClABIVerifyModule() { | 65 ~PNaClABIVerifyModule() { |
| 63 if (ReporterIsOwned) | 66 if (ReporterIsOwned) |
| 64 delete Reporter; | 67 delete Reporter; |
| 65 } | 68 } |
| 66 bool runOnModule(Module &M); | 69 bool runOnModule(Module &M); |
| 67 virtual void print(raw_ostream &O, const Module *M) const; | 70 virtual void print(raw_ostream &O, const Module *M) const; |
| 68 private: | 71 private: |
| 69 void checkGlobalValueCommon(const GlobalValue *GV); | 72 void checkGlobalValueCommon(const GlobalValue *GV); |
| 73 bool isWhitelistedIntrinsic(const NaCl::AtomicIntrinsics *AI, | |
|
Mark Seaborn
2013/07/03 04:55:20
This isn't defined any more after rebasing
JF
2013/07/03 15:06:13
Done, and the include up top.
| |
| 74 const Function *F, Intrinsic::ID ID); | |
| 70 bool isWhitelistedMetadata(const NamedMDNode *MD); | 75 bool isWhitelistedMetadata(const NamedMDNode *MD); |
| 71 | 76 |
| 72 /// Returns whether \p GV is an allowed external symbol in stable bitcode. | 77 /// Returns whether \p GV is an allowed external symbol in stable bitcode. |
| 73 bool isWhitelistedExternal(const GlobalValue *GV); | 78 bool isWhitelistedExternal(const GlobalValue *GV); |
| 74 | 79 |
| 75 void checkGlobalIsFlattened(const GlobalVariable *GV); | 80 void checkGlobalIsFlattened(const GlobalVariable *GV); |
| 76 PNaClABIErrorReporter *Reporter; | 81 PNaClABIErrorReporter *Reporter; |
| 77 bool ReporterIsOwned; | 82 bool ReporterIsOwned; |
| 78 bool StreamingMode; | 83 bool StreamingMode; |
| 79 }; | 84 }; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 166 // definitions, but that should be done by user-toolchain | 171 // definitions, but that should be done by user-toolchain |
| 167 // optimization passes, not by the PNaCl translator. | 172 // optimization passes, not by the PNaCl translator. |
| 168 if (GV->hasUnnamedAddr()) { | 173 if (GV->hasUnnamedAddr()) { |
| 169 Reporter->addError() << GVTypeName << GV->getName() | 174 Reporter->addError() << GVTypeName << GV->getName() |
| 170 << " has disallowed \"unnamed_addr\" attribute\n"; | 175 << " has disallowed \"unnamed_addr\" attribute\n"; |
| 171 } | 176 } |
| 172 } | 177 } |
| 173 | 178 |
| 174 AllowedIntrinsics::AllowedIntrinsics(LLVMContext *Context) : Context(Context) { | 179 AllowedIntrinsics::AllowedIntrinsics(LLVMContext *Context) : Context(Context) { |
| 175 Type *I8Ptr = Type::getInt8PtrTy(*Context); | 180 Type *I8Ptr = Type::getInt8PtrTy(*Context); |
| 181 Type *I8 = Type::getInt8Ty(*Context); | |
| 176 Type *I16 = Type::getInt16Ty(*Context); | 182 Type *I16 = Type::getInt16Ty(*Context); |
| 177 Type *I32 = Type::getInt32Ty(*Context); | 183 Type *I32 = Type::getInt32Ty(*Context); |
| 178 Type *I64 = Type::getInt64Ty(*Context); | 184 Type *I64 = Type::getInt64Ty(*Context); |
| 179 | 185 |
| 180 // We accept bswap for a limited set of types (i16, i32, i64). The | 186 // We accept bswap for a limited set of types (i16, i32, i64). The |
| 181 // various backends are able to generate instructions to implement | 187 // various backends are able to generate instructions to implement |
| 182 // the intrinsic. Also, i16 and i64 are easy to implement as along | 188 // the intrinsic. Also, i16 and i64 are easy to implement as along |
| 183 // as there is a way to do i32. | 189 // as there is a way to do i32. |
| 184 addIntrinsic(Intrinsic::bswap, I16); | 190 addIntrinsic(Intrinsic::bswap, I16); |
| 185 addIntrinsic(Intrinsic::bswap, I32); | 191 addIntrinsic(Intrinsic::bswap, I32); |
| 186 addIntrinsic(Intrinsic::bswap, I64); | 192 addIntrinsic(Intrinsic::bswap, I64); |
| 187 | 193 |
| 188 // We accept cttz, ctlz, and ctpop for a limited set of types (i32, i64). | 194 // We accept cttz, ctlz, and ctpop for a limited set of types (i32, i64). |
| 189 addIntrinsic(Intrinsic::ctlz, I32); | 195 addIntrinsic(Intrinsic::ctlz, I32); |
| 190 addIntrinsic(Intrinsic::ctlz, I64); | 196 addIntrinsic(Intrinsic::ctlz, I64); |
| 191 addIntrinsic(Intrinsic::cttz, I32); | 197 addIntrinsic(Intrinsic::cttz, I32); |
| 192 addIntrinsic(Intrinsic::cttz, I64); | 198 addIntrinsic(Intrinsic::cttz, I64); |
| 193 addIntrinsic(Intrinsic::ctpop, I32); | 199 addIntrinsic(Intrinsic::ctpop, I32); |
| 194 addIntrinsic(Intrinsic::ctpop, I64); | 200 addIntrinsic(Intrinsic::ctpop, I64); |
| 195 | 201 |
| 196 addIntrinsic(Intrinsic::nacl_read_tp); | 202 addIntrinsic(Intrinsic::nacl_read_tp); |
| 197 addIntrinsic(Intrinsic::nacl_longjmp); | 203 addIntrinsic(Intrinsic::nacl_longjmp); |
| 198 addIntrinsic(Intrinsic::nacl_setjmp); | 204 addIntrinsic(Intrinsic::nacl_setjmp); |
| 199 | 205 |
| 206 Type *AtomicTypes[] = { I8, I16, I32, I64 }; | |
| 207 for (Type **T = &AtomicTypes[0], **E = T + array_lengthof(AtomicTypes); | |
| 208 T != E; ++T) { | |
| 209 addIntrinsic(Intrinsic::nacl_atomic_load, *T); | |
| 210 addIntrinsic(Intrinsic::nacl_atomic_store, *T); | |
| 211 addIntrinsic(Intrinsic::nacl_atomic_rmw, *T); | |
| 212 addIntrinsic(Intrinsic::nacl_atomic_cmpxchg, *T); | |
| 213 } | |
| 214 addIntrinsic(Intrinsic::nacl_atomic_fence); | |
| 215 | |
| 200 // Stack save and restore are used to support C99 VLAs. | 216 // Stack save and restore are used to support C99 VLAs. |
| 201 addIntrinsic(Intrinsic::stacksave); | 217 addIntrinsic(Intrinsic::stacksave); |
| 202 addIntrinsic(Intrinsic::stackrestore); | 218 addIntrinsic(Intrinsic::stackrestore); |
| 203 | 219 |
| 204 addIntrinsic(Intrinsic::trap); | 220 addIntrinsic(Intrinsic::trap); |
| 205 | 221 |
| 206 // We only allow the variants of memcpy/memmove/memset with an i32 | 222 // We only allow the variants of memcpy/memmove/memset with an i32 |
| 207 // "len" argument, not an i64 argument. | 223 // "len" argument, not an i64 argument. |
| 208 Type *MemcpyTypes[] = { I8Ptr, I8Ptr, I32 }; | 224 Type *MemcpyTypes[] = { I8Ptr, I8Ptr, I32 }; |
| 209 addIntrinsic(Intrinsic::memcpy, MemcpyTypes); | 225 addIntrinsic(Intrinsic::memcpy, MemcpyTypes); |
| 210 addIntrinsic(Intrinsic::memmove, MemcpyTypes); | 226 addIntrinsic(Intrinsic::memmove, MemcpyTypes); |
| 211 Type *MemsetTypes[] = { I8Ptr, I32 }; | 227 Type *MemsetTypes[] = { I8Ptr, I32 }; |
| 212 addIntrinsic(Intrinsic::memset, MemsetTypes); | 228 addIntrinsic(Intrinsic::memset, MemsetTypes); |
| 213 } | 229 } |
| 214 | 230 |
| 215 bool AllowedIntrinsics::isAllowed(const Function *Func) { | 231 bool AllowedIntrinsics::isAllowed(const Function *Func) { |
| 216 // Keep 3 categories of intrinsics for now. | 232 // Keep 3 categories of intrinsics for now. |
| 217 // (1) Allowed always, provided the exact name and type match. | 233 // (1) Allowed always, provided the exact name and type match. |
| 218 // (2) Never allowed | 234 // (2) Never allowed. |
| 219 // (3) "Dev" intrinsics, which may or may not be allowed. | 235 // (3) "Dev" intrinsics, which may or may not be allowed. |
| 220 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag. | 236 // "Dev" intrinsics are controlled by the PNaClABIAllowDevIntrinsics flag. |
| 221 // Please keep these sorted or grouped in a sensible way, within | 237 // Please keep these sorted or grouped in a sensible way, within |
| 222 // each category. | 238 // each category. |
| 223 | 239 |
| 224 // (1) Allowed always, provided the exact name and type match. | 240 // (1) Allowed always, provided the exact name and type match. |
| 225 if (Mapping.count(Func->getName()) == 1) | 241 if (Mapping.count(Func->getName()) == 1) |
| 226 return Func->getFunctionType() == Mapping[Func->getName()]; | 242 return Func->getFunctionType() == Mapping[Func->getName()]; |
| 227 | 243 |
| 228 switch (Func->getIntrinsicID()) { | 244 switch (Func->getIntrinsicID()) { |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 502 } | 518 } |
| 503 | 519 |
| 504 char PNaClABIVerifyModule::ID = 0; | 520 char PNaClABIVerifyModule::ID = 0; |
| 505 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", | 521 INITIALIZE_PASS(PNaClABIVerifyModule, "verify-pnaclabi-module", |
| 506 "Verify module for PNaCl", false, true) | 522 "Verify module for PNaCl", false, true) |
| 507 | 523 |
| 508 ModulePass *llvm::createPNaClABIVerifyModulePass( | 524 ModulePass *llvm::createPNaClABIVerifyModulePass( |
| 509 PNaClABIErrorReporter *Reporter, bool StreamingMode) { | 525 PNaClABIErrorReporter *Reporter, bool StreamingMode) { |
| 510 return new PNaClABIVerifyModule(Reporter, StreamingMode); | 526 return new PNaClABIVerifyModule(Reporter, StreamingMode); |
| 511 } | 527 } |
| OLD | NEW |