Index: lib/Transforms/NaCl/RewriteAtomics.cpp |
diff --git a/lib/Transforms/NaCl/RewriteAtomics.cpp b/lib/Transforms/NaCl/RewriteAtomics.cpp |
index 54a65ce33569113ceb7b952d3e03290cfe75d402..6b02dea276886ba3885d1efda51fbed3d30d360a 100644 |
--- a/lib/Transforms/NaCl/RewriteAtomics.cpp |
+++ b/lib/Transforms/NaCl/RewriteAtomics.cpp |
@@ -88,6 +88,9 @@ private: |
/// specified by the instruction \p I for stability purpose. |
template <class Instruction> |
ConstantInt *freezeMemoryOrder(const Instruction &I, AtomicOrdering O) const; |
+ std::pair<ConstantInt *, ConstantInt *> |
+ freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S, |
+ AtomicOrdering F) const; |
/// Sanity-check that instruction \p I which has pointer and value |
/// parameters have matching sizes \p BitSize for the type-pointed-to |
@@ -177,7 +180,6 @@ ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I, |
if (AO == NaCl::MemoryOrderInvalid) { |
switch (O) { |
- default: |
case NotAtomic: llvm_unreachable("unexpected memory order"); |
// Monotonic is a strict superset of Unordered. Both can therefore |
// map to Relaxed ordering, which is in the C11/C++11 standard. |
@@ -192,12 +194,28 @@ ConstantInt *AtomicVisitor::freezeMemoryOrder(const Instruction &I, |
} |
} |
- // TODO For now only sequential consistency is allowed. |
- AO = NaCl::MemoryOrderSequentiallyConsistent; |
+ // TODO For now only acquire/release/acq_rel/seq_cst are allowed. |
+ if (AO == NaCl::MemoryOrderRelaxed) |
+ AO = NaCl::MemoryOrderSequentiallyConsistent; |
return ConstantInt::get(Type::getInt32Ty(C), AO); |
} |
+std::pair<ConstantInt *, ConstantInt *> |
+AtomicVisitor::freezeMemoryOrder(const AtomicCmpXchgInst &I, AtomicOrdering S, |
+ AtomicOrdering F) const { |
+ if (S == Release || (S == AcquireRelease && F != Acquire)) |
+ // According to C++11's [atomics.types.operations.req], cmpxchg with release |
+ // success memory ordering must have relaxed failure memory ordering, which |
+ // PNaCl currently disallows. The next-strongest ordering is acq_rel which |
+ // is also an invalid failure ordering, we therefore have to change the |
+ // success ordering to seq_cst, which can then fail as seq_cst. |
+ S = F = SequentiallyConsistent; |
+ if (F == Unordered || F == Monotonic) // Both are treated as relaxed. |
+ F = AtomicCmpXchgInst::getStrongestFailureOrdering(S); |
+ return std::make_pair(freezeMemoryOrder(I, S), freezeMemoryOrder(I, F)); |
+} |
+ |
void AtomicVisitor::checkSizeMatchesType(const Instruction &I, unsigned BitSize, |
const Type *T) const { |
Type *IntType = Type::getIntNTy(C, BitSize); |
@@ -359,9 +377,10 @@ void AtomicVisitor::visitAtomicCmpXchgInst(AtomicCmpXchgInst &I) { |
findAtomicIntrinsic(I, Intrinsic::nacl_atomic_cmpxchg, PH.PET); |
checkSizeMatchesType(I, PH.BitSize, I.getCompareOperand()->getType()); |
checkSizeMatchesType(I, PH.BitSize, I.getNewValOperand()->getType()); |
+ auto Order = |
+ freezeMemoryOrder(I, I.getSuccessOrdering(), I.getFailureOrdering()); |
Value *Args[] = {PH.P, I.getCompareOperand(), I.getNewValOperand(), |
- freezeMemoryOrder(I, I.getSuccessOrdering()), |
- freezeMemoryOrder(I, I.getFailureOrdering())}; |
+ Order.first, Order.second}; |
replaceInstructionWithIntrinsicCall(I, Intrinsic, PH.OriginalPET, PH.PET, |
Args); |
} |