llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> --- Full diff: https://github.com/llvm/llvm-project/pull/111968.diff 5 Files Affected: - (modified) clang/lib/AST/ByteCode/InterpBuiltin.cpp (+70-1) - (modified) clang/lib/AST/ExprConstShared.h (+8) - (modified) clang/lib/AST/ExprConstant.cpp (+17-18) - (modified) clang/test/Sema/builtin-assume-aligned.c (+2) - (modified) clang/test/SemaCXX/builtin-assume-aligned.cpp (+1) ``````````diff diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp index 1765193f5bebbc..27ba3a3654faf3 100644 --- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp +++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp @@ -38,7 +38,6 @@ static T getParam(const InterpFrame *Frame, unsigned Index) { return Frame->getParam<T>(Offset); } -// static APSInt getAPSIntParam(InterpStack &Stk, size_t Offset = 0) { static APSInt getAPSIntParam(const InterpFrame *Frame, unsigned Index) { APSInt R; unsigned Offset = Frame->getFunction()->getParamOffset(Index); @@ -1162,6 +1161,71 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, return false; } +/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset]) +static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC, + const InterpFrame *Frame, + const Function *Func, + const CallExpr *Call) { + assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3); + + // Might be called with function pointers in C. + std::optional<PrimType> PtrT = S.Ctx.classify(Call->getArg(0)); + if (PtrT != PT_Ptr) + return false; + + unsigned ArgSize = callArgSize(S, Call); + const Pointer &Ptr = S.Stk.peek<Pointer>(ArgSize); + std::optional<APSInt> ExtraOffset; + APSInt Alignment; + if (Call->getNumArgs() == 2) { + Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1))); + } else { + PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1)); + PrimType ExtraOffsetT = *S.Ctx.classify(Call->getArg(2)); + Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)), + align(primSize(AlignmentT)) + + align(primSize(ExtraOffsetT))); + ExtraOffset = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2))); + } + + CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); + + // If there is a base object, then it must have the correct alignment. + if (Ptr.isBlockPointer()) { + CharUnits BaseAlignment; + if (const auto *VD = Ptr.getDeclDesc()->asValueDecl()) + BaseAlignment = S.getASTContext().getDeclAlign(VD); + else if (const auto *E = Ptr.getDeclDesc()->asExpr()) + BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf); + + if (BaseAlignment < Align) { + S.CCEDiag(Call->getArg(0), + diag::note_constexpr_baa_insufficient_alignment) + << 0 << BaseAlignment.getQuantity() << Align.getQuantity(); + return false; + } + } + + APValue AV = Ptr.toAPValue(S.getASTContext()); + CharUnits AVOffset = AV.getLValueOffset(); + if (ExtraOffset) + AVOffset += CharUnits::fromQuantity(-ExtraOffset->getZExtValue()); + if (AVOffset.alignTo(Align) != AVOffset) { + if (Ptr.isBlockPointer()) + S.CCEDiag(Call->getArg(0), + diag::note_constexpr_baa_insufficient_alignment) + << 1 << AVOffset.getQuantity() << Align.getQuantity(); + else + S.CCEDiag(Call->getArg(0), + diag::note_constexpr_baa_value_insufficient_alignment) + << AVOffset.getQuantity() << Align.getQuantity(); + return false; + } + + S.Stk.push<Pointer>(Ptr); + return true; +} + static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, @@ -1905,6 +1969,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, return false; break; + case Builtin::BI__builtin_assume_aligned: + if (!interp__builtin_assume_aligned(S, OpPC, Frame, F, Call)) + return false; + break; + case clang::X86::BI__builtin_ia32_bextr_u32: case clang::X86::BI__builtin_ia32_bextr_u64: case clang::X86::BI__builtin_ia32_bextri_u32: diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h index efe8ee986d29b3..401ae629c86bfd 100644 --- a/clang/lib/AST/ExprConstShared.h +++ b/clang/lib/AST/ExprConstShared.h @@ -14,12 +14,17 @@ #ifndef LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H #define LLVM_CLANG_LIB_AST_EXPRCONSTSHARED_H +#include "clang/Basic/TypeTraits.h" + namespace llvm { class APFloat; } namespace clang { class QualType; class LangOptions; +class ASTContext; +class CharUnits; +class Expr; } // namespace clang using namespace clang; /// Values returned by __builtin_classify_type, chosen to match the values @@ -66,4 +71,7 @@ void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat B, llvm::APFloat C, llvm::APFloat D, llvm::APFloat &ResR, llvm::APFloat &ResI); +CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E, + UnaryExprOrTypeTrait ExprKind); + #endif diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 4d5af96093cfeb..1d607bd5a502d0 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9620,7 +9620,7 @@ bool PointerExprEvaluator::VisitCastExpr(const CastExpr *E) { return ExprEvaluatorBaseTy::VisitCastExpr(E); } -static CharUnits GetAlignOfType(EvalInfo &Info, QualType T, +static CharUnits GetAlignOfType(const ASTContext &Ctx, QualType T, UnaryExprOrTypeTrait ExprKind) { // C++ [expr.alignof]p3: // When alignof is applied to a reference type, the result is the @@ -9631,23 +9631,22 @@ static CharUnits GetAlignOfType(EvalInfo &Info, QualType T, return CharUnits::One(); const bool AlignOfReturnsPreferred = - Info.Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; + Ctx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7; // __alignof is defined to return the preferred alignment. // Before 8, clang returned the preferred alignment for alignof and _Alignof // as well. if (ExprKind == UETT_PreferredAlignOf || AlignOfReturnsPreferred) - return Info.Ctx.toCharUnitsFromBits( - Info.Ctx.getPreferredTypeAlign(T.getTypePtr())); + return Ctx.toCharUnitsFromBits(Ctx.getPreferredTypeAlign(T.getTypePtr())); // alignof and _Alignof are defined to return the ABI alignment. else if (ExprKind == UETT_AlignOf) - return Info.Ctx.getTypeAlignInChars(T.getTypePtr()); + return Ctx.getTypeAlignInChars(T.getTypePtr()); else llvm_unreachable("GetAlignOfType on a non-alignment ExprKind"); } -static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E, - UnaryExprOrTypeTrait ExprKind) { +CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E, + UnaryExprOrTypeTrait ExprKind) { E = E->IgnoreParens(); // The kinds of expressions that we have special-case logic here for @@ -9657,22 +9656,22 @@ static CharUnits GetAlignOfExpr(EvalInfo &Info, const Expr *E, // alignof decl is always accepted, even if it doesn't make sense: we default // to 1 in those cases. if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) - return Info.Ctx.getDeclAlign(DRE->getDecl(), - /*RefAsPointee*/true); + return Ctx.getDeclAlign(DRE->getDecl(), + /*RefAsPointee*/ true); if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) - return Info.Ctx.getDeclAlign(ME->getMemberDecl(), - /*RefAsPointee*/true); + return Ctx.getDeclAlign(ME->getMemberDecl(), + /*RefAsPointee*/ true); - return GetAlignOfType(Info, E->getType(), ExprKind); + return GetAlignOfType(Ctx, E->getType(), ExprKind); } static CharUnits getBaseAlignment(EvalInfo &Info, const LValue &Value) { if (const auto *VD = Value.Base.dyn_cast<const ValueDecl *>()) return Info.Ctx.getDeclAlign(VD); if (const auto *E = Value.Base.dyn_cast<const Expr *>()) - return GetAlignOfExpr(Info, E, UETT_AlignOf); - return GetAlignOfType(Info, Value.Base.getTypeInfoType(), UETT_AlignOf); + return GetAlignOfExpr(Info.Ctx, E, UETT_AlignOf); + return GetAlignOfType(Info.Ctx, Value.Base.getTypeInfoType(), UETT_AlignOf); } /// Evaluate the value of the alignment argument to __builtin_align_{up,down}, @@ -14478,11 +14477,11 @@ bool IntExprEvaluator::VisitUnaryExprOrTypeTraitExpr( case UETT_PreferredAlignOf: case UETT_AlignOf: { if (E->isArgumentType()) - return Success(GetAlignOfType(Info, E->getArgumentType(), E->getKind()), - E); + return Success( + GetAlignOfType(Info.Ctx, E->getArgumentType(), E->getKind()), E); else - return Success(GetAlignOfExpr(Info, E->getArgumentExpr(), E->getKind()), - E); + return Success( + GetAlignOfExpr(Info.Ctx, E->getArgumentExpr(), E->getKind()), E); } case UETT_PtrAuthTypeDiscriminator: { diff --git a/clang/test/Sema/builtin-assume-aligned.c b/clang/test/Sema/builtin-assume-aligned.c index c2e4f9d659dd4d..33e85578451529 100644 --- a/clang/test/Sema/builtin-assume-aligned.c +++ b/clang/test/Sema/builtin-assume-aligned.c @@ -1,5 +1,7 @@ // RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -Wno-strict-prototypes -triple x86_64-linux -verify %s // RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -triple i386-freebsd -verify %s +// RUN: %clang_cc1 -DSIZE_T_64 -fsyntax-only -Wno-strict-prototypes -triple x86_64-linux -verify %s -fexperimental-new-constant-interpreter +// RUN: %clang_cc1 -fsyntax-only -Wno-strict-prototypes -triple i386-freebsd -verify %s -fexperimental-new-constant-interpreter // __builtin_assume_aligned's second parameter is size_t, which may be 32 bits, // so test differently when size_t is 32 bits and when it is 64 bits. diff --git a/clang/test/SemaCXX/builtin-assume-aligned.cpp b/clang/test/SemaCXX/builtin-assume-aligned.cpp index 48bd8414fc50a1..85a7faee916181 100644 --- a/clang/test/SemaCXX/builtin-assume-aligned.cpp +++ b/clang/test/SemaCXX/builtin-assume-aligned.cpp @@ -1,4 +1,5 @@ // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -triple x86_64-linux-gnu %s -fexperimental-new-constant-interpreter int n; constexpr int *p = 0; `````````` </details> https://github.com/llvm/llvm-project/pull/111968 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits