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.ule(NaCl::MemoryOrderInvalid) || I.uge(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"); | |
Jim Stichnoth
2015/01/07 21:21:01
Should these llvm_unreachable calls be stronger, i
JF
2015/01/07 21:33:57
This should truly be unreachable given the code ab
| |
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 |