| 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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 const Constant *C = dyn_cast<Constant>(Operation); | 138 const Constant *C = dyn_cast<Constant>(Operation); |
| 139 if (!C) | 139 if (!C) |
| 140 return false; | 140 return false; |
| 141 const APInt &I = C->getUniqueInteger(); | 141 const APInt &I = C->getUniqueInteger(); |
| 142 if (I.ule(NaCl::AtomicInvalid) || I.uge(NaCl::AtomicNum)) | 142 if (I.ule(NaCl::AtomicInvalid) || I.uge(NaCl::AtomicNum)) |
| 143 return false; | 143 return false; |
| 144 } | 144 } |
| 145 return true; | 145 return true; |
| 146 } | 146 } |
| 147 | 147 |
| 148 static bool hasAllowedAtomicMemoryOrder( | 148 static bool |
| 149 const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, const CallInst *Call) { | 149 hasAllowedAtomicMemoryOrder(const NaCl::AtomicIntrinsics::AtomicIntrinsic *I, |
| 150 const CallInst *Call) { |
| 151 NaCl::MemoryOrder PreviousOrder = NaCl::MemoryOrderInvalid; |
| 152 |
| 150 for (size_t P = 0; P != I->NumParams; ++P) { | 153 for (size_t P = 0; P != I->NumParams; ++P) { |
| 151 if (I->ParamType[P] != NaCl::AtomicIntrinsics::Mem) | 154 if (I->ParamType[P] != NaCl::AtomicIntrinsics::Mem) |
| 152 continue; | 155 continue; |
| 153 | 156 |
| 154 const Value *MemoryOrder = Call->getOperand(P); | 157 NaCl::MemoryOrder Order = NaCl::MemoryOrderInvalid; |
| 155 if (!MemoryOrder) | 158 if (const Value *MemoryOrderOperand = Call->getOperand(P)) |
| 159 if (const Constant *C = dyn_cast<Constant>(MemoryOrderOperand)) { |
| 160 const APInt &I = C->getUniqueInteger(); |
| 161 if (I.ugt(NaCl::MemoryOrderInvalid) && I.ult(NaCl::MemoryOrderNum)) |
| 162 Order = static_cast<NaCl::MemoryOrder>(I.getLimitedValue()); |
| 163 } |
| 164 if (Order == NaCl::MemoryOrderInvalid) |
| 156 return false; | 165 return false; |
| 157 const Constant *C = dyn_cast<Constant>(MemoryOrder); | 166 |
| 158 if (!C) | 167 // Validate PNaCl restrictions. |
| 168 switch (Order) { |
| 169 case NaCl::MemoryOrderInvalid: |
| 170 case NaCl::MemoryOrderNum: |
| 171 llvm_unreachable("Invalid memory order"); |
| 172 case NaCl::MemoryOrderRelaxed: |
| 173 case NaCl::MemoryOrderConsume: |
| 174 // TODO(jfb) PNaCl doesn't allow relaxed or consume memory ordering. |
| 159 return false; | 175 return false; |
| 160 const APInt &I = C->getUniqueInteger(); | 176 case NaCl::MemoryOrderAcquire: |
| 161 if (I.ule(NaCl::MemoryOrderInvalid) || I.uge(NaCl::MemoryOrderNum)) | 177 case NaCl::MemoryOrderRelease: |
| 162 return false; | 178 case NaCl::MemoryOrderAcquireRelease: |
| 163 // TODO For now only sequential consistency is allowed. When more | 179 case NaCl::MemoryOrderSequentiallyConsistent: |
| 164 // are allowed we need to validate that the memory order is | 180 break; // Allowed by PNaCl. |
| 165 // allowed on the specific atomic operation (e.g. no store | 181 } |
| 166 // acquire, and relationship between success/failure memory | 182 |
| 167 // order on compare exchange). | 183 // Validate conformance to the C++11 memory model. |
| 168 if (I != NaCl::MemoryOrderSequentiallyConsistent) | 184 switch (I->ID) { |
| 169 return false; | 185 default: |
| 186 llvm_unreachable("unexpected atomic operation"); |
| 187 case Intrinsic::nacl_atomic_load: |
| 188 // C++11 [atomics.types.operations.req]: The order argument shall not be |
| 189 // release nor acq_rel. |
| 190 if (Order == NaCl::MemoryOrderRelease || |
| 191 Order == NaCl::MemoryOrderAcquireRelease) |
| 192 return false; |
| 193 break; |
| 194 case Intrinsic::nacl_atomic_store: |
| 195 // C++11 [atomics.types.operations.req]: The order argument shall not be |
| 196 // consume, acquire, nor acq_rel. |
| 197 if (Order == NaCl::MemoryOrderConsume || |
| 198 Order == NaCl::MemoryOrderAcquire || |
| 199 Order == NaCl::MemoryOrderAcquireRelease) |
| 200 return false; |
| 201 break; |
| 202 case Intrinsic::nacl_atomic_rmw: |
| 203 break; // No restriction. |
| 204 case Intrinsic::nacl_atomic_cmpxchg: |
| 205 // C++11 [atomics.types.operations.req]: The failure argument shall not be |
| 206 // release nor acq_rel. The failure argument shall be no stronger than the |
| 207 // success argument. |
| 208 // Where the partial ordering is: |
| 209 // relaxed < consume < acquire < acq_rel < seq_cst |
| 210 // relaxed < release < acq_rel < seq_cst |
| 211 if (PreviousOrder != NaCl::MemoryOrderInvalid) { // Failure ordering. |
| 212 NaCl::MemoryOrder Success = PreviousOrder, Failure = Order; |
| 213 if (Failure == NaCl::MemoryOrderRelease || |
| 214 Failure == NaCl::MemoryOrderAcquireRelease) |
| 215 return false; |
| 216 if ((Success < Failure) || (Success == NaCl::MemoryOrderRelease && |
| 217 Failure != NaCl::MemoryOrderRelaxed)) |
| 218 return false; |
| 219 } |
| 220 break; // Success ordering has no restriction. |
| 221 case Intrinsic::nacl_atomic_fence: |
| 222 case Intrinsic::nacl_atomic_fence_all: |
| 223 break; // No restrictions. |
| 224 } |
| 225 |
| 226 PreviousOrder = Order; |
| 170 } | 227 } |
| 228 |
| 171 return true; | 229 return true; |
| 172 } | 230 } |
| 173 | 231 |
| 174 static bool hasAllowedLockFreeByteSize(const CallInst *Call) { | 232 static bool hasAllowedLockFreeByteSize(const CallInst *Call) { |
| 175 if (!Call->getType()->isIntegerTy()) | 233 if (!Call->getType()->isIntegerTy()) |
| 176 return false; | 234 return false; |
| 177 const Value *Operation = Call->getOperand(0); | 235 const Value *Operation = Call->getOperand(0); |
| 178 if (!Operation) | 236 if (!Operation) |
| 179 return false; | 237 return false; |
| 180 const Constant *C = dyn_cast<Constant>(Operation); | 238 const Constant *C = dyn_cast<Constant>(Operation); |
| (...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 } | 620 } |
| 563 | 621 |
| 564 char PNaClABIVerifyFunctions::ID = 0; | 622 char PNaClABIVerifyFunctions::ID = 0; |
| 565 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", | 623 INITIALIZE_PASS(PNaClABIVerifyFunctions, "verify-pnaclabi-functions", |
| 566 "Verify functions for PNaCl", false, true) | 624 "Verify functions for PNaCl", false, true) |
| 567 | 625 |
| 568 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( | 626 FunctionPass *llvm::createPNaClABIVerifyFunctionsPass( |
| 569 PNaClABIErrorReporter *Reporter) { | 627 PNaClABIErrorReporter *Reporter) { |
| 570 return new PNaClABIVerifyFunctions(Reporter); | 628 return new PNaClABIVerifyFunctions(Reporter); |
| 571 } | 629 } |
| OLD | NEW |