-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[Clang] Re-write codegen for atomic_test_and_set and atomic_clear #121943
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3634,6 +3634,7 @@ static bool isValidOrderingForOp(int64_t Ordering, AtomicExpr::AtomicOp Op) { | |
| case AtomicExpr::AO__atomic_store_n: | ||
| case AtomicExpr::AO__scoped_atomic_store: | ||
| case AtomicExpr::AO__scoped_atomic_store_n: | ||
| case AtomicExpr::AO__atomic_clear: | ||
| return OrderingCABI != llvm::AtomicOrderingCABI::consume && | ||
| OrderingCABI != llvm::AtomicOrderingCABI::acquire && | ||
| OrderingCABI != llvm::AtomicOrderingCABI::acq_rel; | ||
|
|
@@ -3686,12 +3687,18 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| C11CmpXchg, | ||
|
|
||
| // bool __atomic_compare_exchange(A *, C *, CP, bool, int, int) | ||
| GNUCmpXchg | ||
| GNUCmpXchg, | ||
|
|
||
| // bool __atomic_test_and_set(A *, int) | ||
| TestAndSet, | ||
|
||
|
|
||
| // void __atomic_clear(A *, int) | ||
| Clear, | ||
| } Form = Init; | ||
|
|
||
| const unsigned NumForm = GNUCmpXchg + 1; | ||
| const unsigned NumArgs[] = { 2, 2, 3, 3, 3, 3, 4, 5, 6 }; | ||
| const unsigned NumVals[] = { 1, 0, 1, 1, 1, 1, 2, 2, 3 }; | ||
| const unsigned NumForm = Clear + 1; | ||
| const unsigned NumArgs[] = {2, 2, 3, 3, 3, 3, 4, 5, 6, 2, 2}; | ||
| const unsigned NumVals[] = {1, 0, 1, 1, 1, 1, 2, 2, 3, 0, 0}; | ||
| // where: | ||
| // C is an appropriate type, | ||
| // A is volatile _Atomic(C) for __c11 builtins and is C for GNU builtins, | ||
|
|
@@ -3852,6 +3859,14 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| case AtomicExpr::AO__scoped_atomic_compare_exchange_n: | ||
| Form = GNUCmpXchg; | ||
| break; | ||
|
|
||
| case AtomicExpr::AO__atomic_test_and_set: | ||
| Form = TestAndSet; | ||
| break; | ||
|
|
||
| case AtomicExpr::AO__atomic_clear: | ||
| Form = Clear; | ||
| break; | ||
| } | ||
|
|
||
| unsigned AdjustedNumArgs = NumArgs[Form]; | ||
|
|
@@ -3911,14 +3926,31 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| } | ||
| } | ||
|
|
||
| // Pointer to object of size zero is not allowed. | ||
| if (RequireCompleteType(Ptr->getBeginLoc(), AtomTy, | ||
| diag::err_incomplete_type)) | ||
| return ExprError(); | ||
| if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) { | ||
| Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer) | ||
| << Ptr->getType() << 1 << Ptr->getSourceRange(); | ||
| return ExprError(); | ||
| if (Form != TestAndSet && Form != Clear) { | ||
| // Pointer to object of size zero is not allowed. | ||
| if (RequireCompleteType(Ptr->getBeginLoc(), AtomTy, | ||
| diag::err_incomplete_type)) | ||
| return ExprError(); | ||
|
|
||
| if (Context.getTypeInfoInChars(AtomTy).Width.isZero()) { | ||
| Diag(ExprRange.getBegin(), diag::err_atomic_builtin_must_be_pointer) | ||
| << Ptr->getType() << 1 << Ptr->getSourceRange(); | ||
| return ExprError(); | ||
| } | ||
| } else { | ||
| // The __atomic_clear and __atomic_test_and_set intrinsics accept any | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I find this placement of the new code confusing, because we've already derived some values from the pointee-type. I think it'd be clearer to check
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've tried that, but it results in the block above, which reports an error is a const pointer is used, always printing a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks, SGTM! |
||
| // non-const pointer type, including void* and pointers to incomplete | ||
| // structs, but only access the first byte. | ||
| if (AtomTy.isVolatileQualified()) | ||
| Ptr = ImpCastExprToType( | ||
| Ptr, | ||
| Context.getPointerType(Context.getVolatileType(Context.CharTy)), | ||
| CK_BitCast) | ||
| .get(); | ||
| else | ||
| Ptr = ImpCastExprToType(Ptr, Context.getPointerType(Context.CharTy), | ||
| CK_BitCast) | ||
| .get(); | ||
| } | ||
|
|
||
| // For an arithmetic operation, the implied arithmetic must be well-formed. | ||
|
|
@@ -3963,8 +3995,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| return ExprError(); | ||
| } | ||
|
|
||
| if (!IsC11 && !AtomTy.isTriviallyCopyableType(Context) && | ||
| !AtomTy->isScalarType()) { | ||
| if (!IsC11 && Form != TestAndSet && Form != Clear && | ||
| !AtomTy.isTriviallyCopyableType(Context) && !AtomTy->isScalarType()) { | ||
|
||
| // For GNU atomics, require a trivially-copyable type. This is not part of | ||
| // the GNU atomics specification but we enforce it for consistency with | ||
| // other atomics which generally all require a trivially-copyable type. This | ||
|
|
@@ -3997,10 +4029,10 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| ValType.removeLocalVolatile(); | ||
| ValType.removeLocalConst(); | ||
| QualType ResultType = ValType; | ||
| if (Form == Copy || Form == LoadCopy || Form == GNUXchg || | ||
| Form == Init) | ||
| if (Form == Copy || Form == LoadCopy || Form == GNUXchg || Form == Init || | ||
| Form == Clear) | ||
| ResultType = Context.VoidTy; | ||
| else if (Form == C11CmpXchg || Form == GNUCmpXchg) | ||
| else if (Form == C11CmpXchg || Form == GNUCmpXchg || Form == TestAndSet) | ||
| ResultType = Context.BoolTy; | ||
|
|
||
| // The type of a parameter passed 'by value'. In the GNU atomics, such | ||
|
|
@@ -4045,6 +4077,10 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| APIOrderedArgs.push_back(Args[1]); // Order | ||
| APIOrderedArgs.push_back(Args[3]); // OrderFail | ||
| break; | ||
| case TestAndSet: | ||
| case Clear: | ||
| APIOrderedArgs.push_back(Args[1]); // Order | ||
| break; | ||
| } | ||
| } else | ||
| APIOrderedArgs.append(Args.begin(), Args.end()); | ||
|
|
@@ -4130,6 +4166,8 @@ ExprResult Sema::BuildAtomicExpr(SourceRange CallRange, SourceRange ExprRange, | |
| SubExprs.push_back(APIOrderedArgs[1]); // Val1 | ||
| break; | ||
| case Load: | ||
| case TestAndSet: | ||
| case Clear: | ||
| SubExprs.push_back(APIOrderedArgs[1]); // Order | ||
| break; | ||
| case LoadCopy: | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe doesn't matter, but shouldn't this be
bool(...)?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done