-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[clang][bytecode] Implement __builtin_assume_aligned #111968
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
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) ChangesFull diff: https://github.com/llvm/llvm-project/pull/111968.diff 5 Files Affected:
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;
|
ad01583
to
1fa9d5d
Compare
DanielCChen
pushed a commit
to DanielCChen/llvm-project
that referenced
this pull request
Oct 16, 2024
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Labels
clang:frontend
Language frontend issues, e.g. anything involving "Sema"
clang
Clang issues not falling into any other category
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
No description provided.