From dda2cb17a36237f9100a7f1169dc01ea753632fb Mon Sep 17 00:00:00 2001 From: JF Bastien Date: Mon, 18 Apr 2016 18:01:49 +0000 Subject: [PATCH] NFC: unify clang / LLVM atomic ordering This makes the C11 / C++11 *ABI* atomic ordering accessible from LLVM, as discussed in http://reviews.llvm.org/D18200#inline-151433 This re-applies r266574 which I had reverted in r266575. Depends on http://reviews.llvm.org/D18875 Original review: http://reviews.llvm.org/D18876 llvm-svn: 266641 --- clang/include/clang/AST/Expr.h | 11 +-- clang/lib/CodeGen/CGAtomic.cpp | 166 ++++++++++++++++++---------------------- clang/lib/Sema/SemaChecking.cpp | 14 ++-- 3 files changed, 81 insertions(+), 110 deletions(-) diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 6b14c60..83b6e26 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -29,6 +29,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -4830,16 +4831,6 @@ public: BI_First = 0 }; - // The ABI values for various atomic memory orderings. - enum AtomicOrderingKind { - AO_ABI_memory_order_relaxed = 0, - AO_ABI_memory_order_consume = 1, - AO_ABI_memory_order_acquire = 2, - AO_ABI_memory_order_release = 3, - AO_ABI_memory_order_acq_rel = 4, - AO_ABI_memory_order_seq_cst = 5 - }; - private: enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; Stmt* SubExprs[END_EXPR]; diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp index 6a13224..aa5a32d 100644 --- a/clang/lib/CodeGen/CGAtomic.cpp +++ b/clang/lib/CodeGen/CGAtomic.cpp @@ -243,11 +243,6 @@ namespace { /// Materialize an atomic r-value in atomic-layout memory. Address materializeRValue(RValue rvalue) const; - /// \brief Translates LLVM atomic ordering to GNU atomic ordering for - /// libcalls. - static AtomicExpr::AtomicOrderingKind - translateAtomicOrdering(const llvm::AtomicOrdering AO); - /// \brief Creates temp alloca for intermediate operations on atomic value. Address CreateTempAlloca() const; private: @@ -292,25 +287,6 @@ namespace { }; } -AtomicExpr::AtomicOrderingKind -AtomicInfo::translateAtomicOrdering(const llvm::AtomicOrdering AO) { - switch (AO) { - case llvm::AtomicOrdering::Unordered: - case llvm::AtomicOrdering::NotAtomic: - case llvm::AtomicOrdering::Monotonic: - return AtomicExpr::AO_ABI_memory_order_relaxed; - case llvm::AtomicOrdering::Acquire: - return AtomicExpr::AO_ABI_memory_order_acquire; - case llvm::AtomicOrdering::Release: - return AtomicExpr::AO_ABI_memory_order_release; - case llvm::AtomicOrdering::AcquireRelease: - return AtomicExpr::AO_ABI_memory_order_acq_rel; - case llvm::AtomicOrdering::SequentiallyConsistent: - return AtomicExpr::AO_ABI_memory_order_seq_cst; - } - llvm_unreachable("Unhandled AtomicOrdering"); -} - Address AtomicInfo::CreateTempAlloca() const { Address TempAlloca = CGF.CreateMemTemp( (LVal.isBitField() && ValueSizeInBits > AtomicSizeInBits) ? ValueTy @@ -427,34 +403,39 @@ static void emitAtomicCmpXchg(CodeGenFunction &CGF, AtomicExpr *E, bool IsWeak, /// instructions to cope with the provided (but possibly only dynamically known) /// FailureOrder. static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E, - bool IsWeak, Address Dest, - Address Ptr, Address Val1, - Address Val2, + bool IsWeak, Address Dest, Address Ptr, + Address Val1, Address Val2, llvm::Value *FailureOrderVal, uint64_t Size, llvm::AtomicOrdering SuccessOrder) { llvm::AtomicOrdering FailureOrder; if (llvm::ConstantInt *FO = dyn_cast(FailureOrderVal)) { - switch (FO->getSExtValue()) { - default: + auto FOS = FO->getSExtValue(); + if (!llvm::isValidAtomicOrderingCABI(FOS)) FailureOrder = llvm::AtomicOrdering::Monotonic; - break; - case AtomicExpr::AO_ABI_memory_order_consume: - case AtomicExpr::AO_ABI_memory_order_acquire: - FailureOrder = llvm::AtomicOrdering::Acquire; - break; - case AtomicExpr::AO_ABI_memory_order_seq_cst: - FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent; - break; - } + else + switch ((llvm::AtomicOrderingCABI)FOS) { + case llvm::AtomicOrderingCABI::relaxed: + case llvm::AtomicOrderingCABI::release: + case llvm::AtomicOrderingCABI::acq_rel: + FailureOrder = llvm::AtomicOrdering::Monotonic; + break; + case llvm::AtomicOrderingCABI::consume: + case llvm::AtomicOrderingCABI::acquire: + FailureOrder = llvm::AtomicOrdering::Acquire; + break; + case llvm::AtomicOrderingCABI::seq_cst: + FailureOrder = llvm::AtomicOrdering::SequentiallyConsistent; + break; + } if (isStrongerThan(FailureOrder, SuccessOrder)) { // Don't assert on undefined behavior "failure argument shall be no // stronger than the success argument". FailureOrder = - llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder); + llvm::AtomicCmpXchgInst::getStrongestFailureOrdering(SuccessOrder); } - emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, - SuccessOrder, FailureOrder); + emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, + FailureOrder); return; } @@ -487,9 +468,9 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E, emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, llvm::AtomicOrdering::Acquire); CGF.Builder.CreateBr(ContBB); - SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume), + SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::consume), AcquireBB); - SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acquire), + SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire), AcquireBB); } if (SeqCstBB) { @@ -497,7 +478,7 @@ static void emitAtomicCmpXchgFailureSet(CodeGenFunction &CGF, AtomicExpr *E, emitAtomicCmpXchg(CGF, E, IsWeak, Dest, Ptr, Val1, Val2, Size, SuccessOrder, llvm::AtomicOrdering::SequentiallyConsistent); CGF.Builder.CreateBr(ContBB); - SI->addCase(CGF.Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst), + SI->addCase(CGF.Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst), SeqCstBB); } @@ -1044,40 +1025,39 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { E->getOp() == AtomicExpr::AO__atomic_load_n; if (isa(Order)) { - int ord = cast(Order)->getZExtValue(); - switch (ord) { - case AtomicExpr::AO_ABI_memory_order_relaxed: - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, - Size, llvm::AtomicOrdering::Monotonic); - break; - case AtomicExpr::AO_ABI_memory_order_consume: - case AtomicExpr::AO_ABI_memory_order_acquire: - if (IsStore) - break; // Avoid crashing on code with undefined behavior - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, - Size, llvm::AtomicOrdering::Acquire); - break; - case AtomicExpr::AO_ABI_memory_order_release: - if (IsLoad) - break; // Avoid crashing on code with undefined behavior - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, - Size, llvm::AtomicOrdering::Release); - break; - case AtomicExpr::AO_ABI_memory_order_acq_rel: - if (IsLoad || IsStore) - break; // Avoid crashing on code with undefined behavior - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, - Size, llvm::AtomicOrdering::AcquireRelease); - break; - case AtomicExpr::AO_ABI_memory_order_seq_cst: - EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, - Size, llvm::AtomicOrdering::SequentiallyConsistent); - break; - default: // invalid order - // We should not ever get here normally, but it's hard to - // enforce that in general. - break; - } + auto ord = cast(Order)->getZExtValue(); + // We should not ever get to a case where the ordering isn't a valid C ABI + // value, but it's hard to enforce that in general. + if (llvm::isValidAtomicOrderingCABI(ord)) + switch ((llvm::AtomicOrderingCABI)ord) { + case llvm::AtomicOrderingCABI::relaxed: + EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, + llvm::AtomicOrdering::Monotonic); + break; + case llvm::AtomicOrderingCABI::consume: + case llvm::AtomicOrderingCABI::acquire: + if (IsStore) + break; // Avoid crashing on code with undefined behavior + EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, + llvm::AtomicOrdering::Acquire); + break; + case llvm::AtomicOrderingCABI::release: + if (IsLoad) + break; // Avoid crashing on code with undefined behavior + EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, + llvm::AtomicOrdering::Release); + break; + case llvm::AtomicOrderingCABI::acq_rel: + if (IsLoad || IsStore) + break; // Avoid crashing on code with undefined behavior + EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, + llvm::AtomicOrdering::AcquireRelease); + break; + case llvm::AtomicOrderingCABI::seq_cst: + EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, + llvm::AtomicOrdering::SequentiallyConsistent); + break; + } if (RValTy->isVoidType()) return RValue::get(nullptr); @@ -1119,9 +1099,9 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, llvm::AtomicOrdering::Acquire); Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_consume), + SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::consume), AcquireBB); - SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acquire), + SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acquire), AcquireBB); } if (!IsLoad) { @@ -1129,7 +1109,7 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, llvm::AtomicOrdering::Release); Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_release), + SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::release), ReleaseBB); } if (!IsLoad && !IsStore) { @@ -1137,14 +1117,14 @@ RValue CodeGenFunction::EmitAtomicExpr(AtomicExpr *E) { EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, llvm::AtomicOrdering::AcquireRelease); Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_acq_rel), + SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::acq_rel), AcqRelBB); } Builder.SetInsertPoint(SeqCstBB); EmitAtomicOp(*this, E, Dest, Ptr, Val1, Val2, IsWeak, OrderFail, Size, llvm::AtomicOrdering::SequentiallyConsistent); Builder.CreateBr(ContBB); - SI->addCase(Builder.getInt32(AtomicExpr::AO_ABI_memory_order_seq_cst), + SI->addCase(Builder.getInt32((int)llvm::AtomicOrderingCABI::seq_cst), SeqCstBB); // Cleanup and return @@ -1264,9 +1244,9 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value *AddForLoaded, CGF.getContext().VoidPtrTy); Args.add(RValue::get(CGF.EmitCastToVoidPtr(AddForLoaded)), CGF.getContext().VoidPtrTy); - Args.add(RValue::get( - llvm::ConstantInt::get(CGF.IntTy, translateAtomicOrdering(AO))), - CGF.getContext().IntTy); + Args.add( + RValue::get(llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(AO))), + CGF.getContext().IntTy); emitAtomicLibcall(CGF, "__atomic_load", CGF.getContext().VoidTy, Args); } @@ -1482,11 +1462,11 @@ AtomicInfo::EmitAtomicCompareExchangeLibcall(llvm::Value *ExpectedAddr, CGF.getContext().VoidPtrTy); Args.add(RValue::get(CGF.EmitCastToVoidPtr(DesiredAddr)), CGF.getContext().VoidPtrTy); - Args.add(RValue::get(llvm::ConstantInt::get( - CGF.IntTy, translateAtomicOrdering(Success))), + Args.add(RValue::get( + llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Success))), CGF.getContext().IntTy); - Args.add(RValue::get(llvm::ConstantInt::get( - CGF.IntTy, translateAtomicOrdering(Failure))), + Args.add(RValue::get( + llvm::ConstantInt::get(CGF.IntTy, (int)llvm::toCABI(Failure))), CGF.getContext().IntTy); auto SuccessFailureRVal = emitAtomicLibcall(CGF, "__atomic_compare_exchange", CGF.getContext().BoolTy, Args); @@ -1793,9 +1773,9 @@ void CodeGenFunction::EmitAtomicStore(RValue rvalue, LValue dest, getContext().VoidPtrTy); args.add(RValue::get(EmitCastToVoidPtr(srcAddr.getPointer())), getContext().VoidPtrTy); - args.add(RValue::get(llvm::ConstantInt::get( - IntTy, AtomicInfo::translateAtomicOrdering(AO))), - getContext().IntTy); + args.add( + RValue::get(llvm::ConstantInt::get(IntTy, (int)llvm::toCABI(AO))), + getContext().IntTy); emitAtomicLibcall(*this, "__atomic_store", getContext().VoidTy, args); return; } diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 6047030..b508693 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -1791,10 +1791,10 @@ bool Sema::CheckOtherCall(CallExpr *TheCall, const FunctionProtoType *Proto) { } static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { - if (Ordering < AtomicExpr::AO_ABI_memory_order_relaxed || - Ordering > AtomicExpr::AO_ABI_memory_order_seq_cst) + if (!llvm::isValidAtomicOrderingCABI(Ordering)) return false; + auto OrderingCABI = (llvm::AtomicOrderingCABI)Ordering; switch (Op) { case AtomicExpr::AO__c11_atomic_init: llvm_unreachable("There is no ordering argument for an init"); @@ -1802,15 +1802,15 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { case AtomicExpr::AO__c11_atomic_load: case AtomicExpr::AO__atomic_load_n: case AtomicExpr::AO__atomic_load: - return Ordering != AtomicExpr::AO_ABI_memory_order_release && - Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + return OrderingCABI != llvm::AtomicOrderingCABI::release && + OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; case AtomicExpr::AO__c11_atomic_store: case AtomicExpr::AO__atomic_store: case AtomicExpr::AO__atomic_store_n: - return Ordering != AtomicExpr::AO_ABI_memory_order_consume && - Ordering != AtomicExpr::AO_ABI_memory_order_acquire && - Ordering != AtomicExpr::AO_ABI_memory_order_acq_rel; + return OrderingCABI != llvm::AtomicOrderingCABI::consume && + OrderingCABI != llvm::AtomicOrderingCABI::acquire && + OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; default: return true; -- 2.7.4