diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2011-10-17 21:44:23 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2011-10-17 21:44:23 +0000 |
commit | 454b57ac42c9ce0bed9b7a99c2ed5a18fbcd286b (patch) | |
tree | 8b8f859d007cf1ffeb2db932dc3886cc7f5fd432 /lib/AST/ExprConstant.cpp | |
parent | abf3ac7131ba8eab1a2ec99397a776fb0c75ff55 (diff) |
Initial implementation of __atomic_is_lock_free. The input is the size of an atomic type rather than an atomic type itself just to save some implementation pain; I can change that if it seems worthwhile.
I think this is the last hook needed for <atomic> besides defines for ATOMIC_CHAR_LOCK_FREE and friends.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142281 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/ExprConstant.cpp')
-rw-r--r-- | lib/AST/ExprConstant.cpp | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 3c21dc4472..c3cc78e053 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -1344,6 +1344,50 @@ bool IntExprEvaluator::VisitCallExpr(const CallExpr *E) { } return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + + case Builtin::BI__atomic_is_lock_free: { + APSInt SizeVal; + if (!EvaluateInteger(E->getArg(0), SizeVal, Info)) + return false; + + // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power + // of two less than the maximum inline atomic width, we know it is + // lock-free. If the size isn't a power of two, or greater than the + // maximum alignment where we promote atomics, we know it is not lock-free + // (at least not in the sense of atomic_is_lock_free). Otherwise, + // the answer can only be determined at runtime; for example, 16-byte + // atomics have lock-free implementations on some, but not all, + // x86-64 processors. + + // Check power-of-two. + CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); + if (!Size.isPowerOfTwo()) +#if 0 + // FIXME: Suppress this folding until the ABI for the promotion width + // settles. + return Success(0, E); +#else + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); +#endif + +#if 0 + // Check against promotion width. + // FIXME: Suppress this folding until the ABI for the promotion width + // settles. + unsigned PromoteWidthBits = + Info.Ctx.getTargetInfo().getMaxAtomicPromoteWidth(); + if (Size > Info.Ctx.toCharUnitsFromBits(PromoteWidthBits)) + return Success(0, E); +#endif + + // Check against inlining width. + unsigned InlineWidthBits = + Info.Ctx.getTargetInfo().getMaxAtomicInlineWidth(); + if (Size <= Info.Ctx.toCharUnitsFromBits(InlineWidthBits)) + return Success(1, E); + + return Error(E->getLocStart(), diag::note_invalid_subexpr_in_ice, E); + } } } |