diff options
Diffstat (limited to 'clang/lib/Sema/SemaARM.cpp')
-rw-r--r-- | clang/lib/Sema/SemaARM.cpp | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/clang/lib/Sema/SemaARM.cpp b/clang/lib/Sema/SemaARM.cpp index 8e27fab..e09c352 100644 --- a/clang/lib/Sema/SemaARM.cpp +++ b/clang/lib/Sema/SemaARM.cpp @@ -846,9 +846,9 @@ bool SemaARM::CheckARMCoprocessorImmediate(const TargetInfo &TI, return false; } -bool SemaARM::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, - CallExpr *TheCall, - unsigned MaxWidth) { +bool SemaARM::CheckARMBuiltinExclusiveCall(const TargetInfo &TI, + unsigned BuiltinID, + CallExpr *TheCall) { assert((BuiltinID == ARM::BI__builtin_arm_ldrex || BuiltinID == ARM::BI__builtin_arm_ldaex || BuiltinID == ARM::BI__builtin_arm_strex || @@ -923,12 +923,56 @@ bool SemaARM::CheckARMBuiltinExclusiveCall(unsigned BuiltinID, return true; } - // But ARM doesn't have instructions to deal with 128-bit versions. - if (Context.getTypeSize(ValType) > MaxWidth) { - assert(MaxWidth == 64 && "Diagnostic unexpectedly inaccurate"); - Diag(DRE->getBeginLoc(), diag::err_atomic_exclusive_builtin_pointer_size) - << PointerArg->getType() << PointerArg->getSourceRange(); - return true; + // Check whether the size of the type can be handled atomically on this + // target. + if (!TI.getTriple().isAArch64()) { + unsigned Mask = TI.getARMLDREXMask(); + unsigned Bits = Context.getTypeSize(ValType); + bool Supported = + (llvm::isPowerOf2_64(Bits)) && Bits >= 8 && (Mask & (Bits / 8)); + + if (!Supported) { + // Emit a diagnostic saying that this size isn't available. If _no_ size + // of exclusive access is supported on this target, we emit a diagnostic + // with special wording for that case, but otherwise, we emit + // err_atomic_exclusive_builtin_pointer_size and loop over `Mask` to + // control what subset of sizes it lists as legal. + if (Mask) { + auto D = Diag(DRE->getBeginLoc(), + diag::err_atomic_exclusive_builtin_pointer_size) + << PointerArg->getType(); + bool Started = false; + for (unsigned Size = 1; Size <= 8; Size <<= 1) { + // For each of the sizes 1,2,4,8, pass two integers into the + // diagnostic. The first selects a separator from the previous + // number: 0 for no separator at all, 1 for a comma, 2 for " or " + // which appears before the final number in a list of more than one. + // The second integer just indicates whether we print this size in + // the message at all. + if (!(Mask & Size)) { + // This size isn't one of the supported ones, so emit no separator + // text and don't print the size itself. + D << 0 << 0; + } else { + // This size is supported, so print it, and an appropriate + // separator. + Mask &= ~Size; + if (!Started) + D << 0; // No separator if this is the first size we've printed + else if (Mask) + D << 1; // "," if there's still another size to come + else + D << 2; // " or " if the size we're about to print is the last + D << 1; // print the size itself + Started = true; + } + } + } else { + Diag(DRE->getBeginLoc(), + diag::err_atomic_exclusive_builtin_pointer_size_none) + << PointerArg->getSourceRange(); + } + } } switch (ValType.getObjCLifetime()) { @@ -972,7 +1016,7 @@ bool SemaARM::CheckARMBuiltinFunctionCall(const TargetInfo &TI, BuiltinID == ARM::BI__builtin_arm_ldaex || BuiltinID == ARM::BI__builtin_arm_strex || BuiltinID == ARM::BI__builtin_arm_stlex) { - return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 64); + return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall); } if (BuiltinID == ARM::BI__builtin_arm_prefetch) { @@ -1053,7 +1097,7 @@ bool SemaARM::CheckAArch64BuiltinFunctionCall(const TargetInfo &TI, BuiltinID == AArch64::BI__builtin_arm_ldaex || BuiltinID == AArch64::BI__builtin_arm_strex || BuiltinID == AArch64::BI__builtin_arm_stlex) { - return CheckARMBuiltinExclusiveCall(BuiltinID, TheCall, 128); + return CheckARMBuiltinExclusiveCall(TI, BuiltinID, TheCall); } if (BuiltinID == AArch64::BI__builtin_arm_prefetch) { |