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 |