aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode/InterpBuiltin.cpp
diff options
context:
space:
mode:
authorTimm Baeder <tbaeder@redhat.com>2025-06-05 07:36:25 +0200
committerGitHub <noreply@github.com>2025-06-05 07:36:25 +0200
commitc7a93efa50c777c4d0618a41f0c178edddc88db6 (patch)
treed6a574ad8e8e7c16e6b6cb30671940d60a638866 /clang/lib/AST/ByteCode/InterpBuiltin.cpp
parenta56442529cbd340ae9e2e73b236a3267906f93dd (diff)
downloadllvm-c7a93efa50c777c4d0618a41f0c178edddc88db6.zip
llvm-c7a93efa50c777c4d0618a41f0c178edddc88db6.tar.gz
llvm-c7a93efa50c777c4d0618a41f0c178edddc88db6.tar.bz2
[clang][bytecode] Pop builtin args from the stack while evaluating (#142832)
Instead of just peek()ing the values when evaluating the builtins and later classify()ing all the call args once again to remove them, just do it while evaluating. This saves quite a bit of code.
Diffstat (limited to 'clang/lib/AST/ByteCode/InterpBuiltin.cpp')
-rw-r--r--clang/lib/AST/ByteCode/InterpBuiltin.cpp718
1 files changed, 259 insertions, 459 deletions
diff --git a/clang/lib/AST/ByteCode/InterpBuiltin.cpp b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
index 89c626d..a7c3683 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltin.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltin.cpp
@@ -41,25 +41,12 @@ static bool isNoopBuiltin(unsigned ID) {
return false;
}
-static unsigned callArgSize(const InterpState &S, const CallExpr *C) {
- unsigned O = 0;
-
- for (const Expr *E : C->arguments()) {
- O += align(primSize(*S.getContext().classify(E)));
- }
-
- return O;
+static void discard(InterpStack &Stk, PrimType T) {
+ TYPE_SWITCH(T, { Stk.discard<T>(); });
}
-/// Peek an integer value from the stack into an APSInt.
-static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) {
- if (Offset == 0)
- Offset = align(primSize(T));
-
- APSInt R;
- INT_TYPE_SWITCH(T, R = Stk.peek<T>(Offset).toAPSInt());
-
- return R;
+static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {
+ INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt());
}
/// Pushes \p Val on the stack as the type given by \p QT.
@@ -94,68 +81,12 @@ static void pushInteger(InterpState &S, T Val, QualType QT) {
QT);
}
-static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) {
+static void assignInteger(const Pointer &Dest, PrimType ValueT,
+ const APSInt &Value) {
INT_TYPE_SWITCH_NO_BOOL(
ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
}
-template <PrimType Name, class V = typename PrimConv<Name>::T>
-static bool retBI(InterpState &S, const CallExpr *Call, unsigned BuiltinID) {
- // The return value of the function is already on the stack.
- // Remove it, get rid of all the arguments and add it back.
- const V &Val = S.Stk.pop<V>();
- if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
- for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) {
- const Expr *A = Call->getArg(I);
- PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr);
- TYPE_SWITCH(Ty, S.Stk.discard<T>());
- }
- }
- S.Stk.push<V>(Val);
- return true;
-}
-
-static bool retPrimValue(InterpState &S, CodePtr OpPC,
- std::optional<PrimType> &T, const CallExpr *Call,
- unsigned BuiltinID) {
- if (isNoopBuiltin(BuiltinID))
- return true;
-
- if (!T) {
- if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
- for (int32_t I = Call->getNumArgs() - 1; I >= 0; --I) {
- const Expr *A = Call->getArg(I);
- PrimType Ty = S.getContext().classify(A).value_or(PT_Ptr);
- TYPE_SWITCH(Ty, S.Stk.discard<T>());
- }
- }
-
- return true;
- }
-
-#define RET_CASE(X) \
- case X: \
- return retBI<X>(S, Call, BuiltinID);
- switch (*T) {
- RET_CASE(PT_Ptr);
- RET_CASE(PT_Float);
- RET_CASE(PT_Bool);
- RET_CASE(PT_Sint8);
- RET_CASE(PT_Uint8);
- RET_CASE(PT_Sint16);
- RET_CASE(PT_Uint16);
- RET_CASE(PT_Sint32);
- RET_CASE(PT_Uint32);
- RET_CASE(PT_Sint64);
- RET_CASE(PT_Uint64);
- RET_CASE(PT_IntAP);
- RET_CASE(PT_IntAPS);
- default:
- llvm_unreachable("Unsupported return type for builtin function");
- }
-#undef RET_CASE
-}
-
static QualType getElemType(const Pointer &P) {
const Descriptor *Desc = P.getFieldDesc();
QualType T = Desc->getType();
@@ -214,27 +145,30 @@ static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
return true;
}
+// __builtin_assume(int)
+static bool interp__builtin_assume(InterpState &S, CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ assert(Call->getNumArgs() == 1);
+ discard(S.Stk, *S.getContext().classify(Call->getArg(0)));
+ return true;
+}
+
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call, unsigned ID) {
- unsigned LimitSize =
- Call->getNumArgs() == 2
- ? 0
- : align(primSize(*S.getContext().classify(Call->getArg(2))));
- const Pointer &A =
- S.Stk.peek<Pointer>(align(primSize(PT_Ptr)) * 2 + LimitSize);
- const Pointer &B = S.Stk.peek<Pointer>(align(primSize(PT_Ptr)) + LimitSize);
-
- if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
- ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
- diagnoseNonConstexprBuiltin(S, OpPC, ID);
-
uint64_t Limit = ~static_cast<uint64_t>(0);
if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)
- Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
+ Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
.getZExtValue();
+ const Pointer &B = S.Stk.pop<Pointer>();
+ const Pointer &A = S.Stk.pop<Pointer>();
+ if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
+ ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
+ diagnoseNonConstexprBuiltin(S, OpPC, ID);
+
if (Limit == 0) {
pushInteger(S, 0, Call->getType());
return true;
@@ -305,7 +239,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call, unsigned ID) {
- const Pointer &StrPtr = S.Stk.peek<Pointer>();
+ const Pointer &StrPtr = S.Stk.pop<Pointer>();
if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
diagnoseNonConstexprBuiltin(S, OpPC, ID);
@@ -360,7 +294,7 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const CallExpr *Call,
bool Signaling) {
- const Pointer &Arg = S.Stk.peek<Pointer>();
+ const Pointer &Arg = S.Stk.pop<Pointer>();
if (!CheckLoad(S, OpPC, Arg))
return false;
@@ -432,8 +366,8 @@ static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
- const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
- const Floating &Arg2 = S.Stk.peek<Floating>();
+ const Floating &Arg2 = S.Stk.pop<Floating>();
+ const Floating &Arg1 = S.Stk.pop<Floating>();
APFloat Copy = Arg1.getAPFloat();
Copy.copySign(Arg2.getAPFloat());
@@ -444,8 +378,8 @@ static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool IsNumBuiltin) {
- const Floating &LHS = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
- const Floating &RHS = S.Stk.peek<Floating>();
+ const Floating &RHS = S.Stk.pop<Floating>();
+ const Floating &LHS = S.Stk.pop<Floating>();
if (IsNumBuiltin)
S.Stk.push<Floating>(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
@@ -456,8 +390,8 @@ static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool IsNumBuiltin) {
- const Floating &LHS = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
- const Floating &RHS = S.Stk.peek<Floating>();
+ const Floating &RHS = S.Stk.pop<Floating>();
+ const Floating &LHS = S.Stk.pop<Floating>();
if (IsNumBuiltin)
S.Stk.push<Floating>(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
@@ -472,7 +406,7 @@ static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isNan(), Call->getType());
return true;
@@ -481,7 +415,7 @@ static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isSignaling(), Call->getType());
return true;
@@ -490,7 +424,7 @@ static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,
static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, bool CheckSign,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
bool IsInf = Arg.isInf();
if (CheckSign)
@@ -503,7 +437,7 @@ static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isFinite(), Call->getType());
return true;
@@ -512,7 +446,7 @@ static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isNormal(), Call->getType());
return true;
@@ -521,7 +455,7 @@ static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isDenormal(), Call->getType());
return true;
@@ -530,7 +464,7 @@ static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,
static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isZero(), Call->getType());
return true;
@@ -539,7 +473,7 @@ static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg = S.Stk.peek<Floating>();
+ const Floating &Arg = S.Stk.pop<Floating>();
pushInteger(S, Arg.isNegative(), Call->getType());
return true;
@@ -547,8 +481,8 @@ static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,
static bool interp_floating_comparison(InterpState &S, CodePtr OpPC,
const CallExpr *Call, unsigned ID) {
- const Floating &RHS = S.Stk.peek<Floating>();
- const Floating &LHS = S.Stk.peek<Floating>(align(2u * primSize(PT_Float)));
+ const Floating &RHS = S.Stk.pop<Floating>();
+ const Floating &LHS = S.Stk.pop<Floating>();
pushInteger(
S,
@@ -584,9 +518,8 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
- APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT);
- const Floating &F =
- S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float)));
+ APSInt FPClassArg = popToAPSInt(S.Stk, FPClassArgT);
+ const Floating &F = S.Stk.pop<Floating>();
int32_t Result =
static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue());
@@ -596,10 +529,16 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
}
/// Five int values followed by one floating value.
+/// __builtin_fpclassify(int, int, int, int, int, float)
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Val = S.Stk.peek<Floating>();
+ const Floating &Val = S.Stk.pop<Floating>();
+
+ PrimType IntT = *S.getContext().classify(Call->getArg(0));
+ APSInt Values[5];
+ for (unsigned I = 0; I != 5; ++I)
+ Values[4 - I] = popToAPSInt(S.Stk, IntT);
unsigned Index;
switch (Val.getCategory()) {
@@ -619,13 +558,8 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
// The last argument is first on the stack.
assert(Index <= 4);
- PrimType IntT = *S.getContext().classify(Call->getArg(0));
- unsigned IntSize = primSize(IntT);
- unsigned Offset =
- align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize));
- APSInt I = peekToAPSInt(S.Stk, IntT, Offset);
- pushInteger(S, I, Call->getType());
+ pushInteger(S, Values[Index], Call->getType());
return true;
}
@@ -636,7 +570,7 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
// Reference, WG14 N2478 F.10.4.3
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
- const Floating &Val = S.Stk.peek<Floating>();
+ const Floating &Val = S.Stk.pop<Floating>();
S.Stk.push<Floating>(Floating::abs(Val));
return true;
@@ -646,7 +580,7 @@ static bool interp__builtin_abs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Val = peekToAPSInt(S.Stk, ArgT);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
if (Val ==
APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))
return false;
@@ -660,7 +594,7 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Val = peekToAPSInt(S.Stk, ArgT);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
pushInteger(S, Val.popcount(), Call->getType());
return true;
}
@@ -669,7 +603,7 @@ static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Val = peekToAPSInt(S.Stk, ArgT);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
pushInteger(S, Val.popcount() % 2, Call->getType());
return true;
}
@@ -678,7 +612,7 @@ static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Val = peekToAPSInt(S.Stk, ArgT);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
return true;
}
@@ -687,7 +621,7 @@ static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Val = peekToAPSInt(S.Stk, ArgT);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
pushInteger(S, Val.reverseBits(), Call->getType());
return true;
}
@@ -717,11 +651,11 @@ static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,
assert(NumArgs == 2 || NumArgs == 3);
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- unsigned Offset = align(ArgT) * 2;
if (NumArgs == 3)
- Offset += align(primSize(PT_Float));
+ S.Stk.discard<Floating>();
+ discard(S.Stk, ArgT);
- APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
pushInteger(S, Val, Call->getType());
return true;
}
@@ -733,9 +667,8 @@ static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,
PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());
PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Amount = peekToAPSInt(S.Stk, AmountT);
- APSInt Value = peekToAPSInt(
- S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT)));
+ APSInt Amount = popToAPSInt(S.Stk, AmountT);
+ APSInt Value = popToAPSInt(S.Stk, ValueT);
APSInt Result;
if (Right)
@@ -753,7 +686,7 @@ static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Value = peekToAPSInt(S.Stk, ArgT);
+ APSInt Value = popToAPSInt(S.Stk, ArgT);
uint64_t N = Value.countr_zero();
pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
@@ -782,7 +715,7 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Arg = peekToAPSInt(S.Stk, ArgT);
+ APSInt Arg = popToAPSInt(S.Stk, ArgT);
int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber(
Arg.getZExtValue());
@@ -794,17 +727,14 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
const CallExpr *Call,
unsigned BuiltinOp) {
- Pointer &ResultPtr = S.Stk.peek<Pointer>();
+ const Pointer &ResultPtr = S.Stk.pop<Pointer>();
if (ResultPtr.isDummy())
return false;
PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt RHS = peekToAPSInt(S.Stk, RHST,
- align(primSize(PT_Ptr)) + align(primSize(RHST)));
- APSInt LHS = peekToAPSInt(S.Stk, LHST,
- align(primSize(PT_Ptr)) + align(primSize(RHST)) +
- align(primSize(LHST)));
+ APSInt RHS = popToAPSInt(S.Stk, RHST);
+ APSInt LHS = popToAPSInt(S.Stk, LHST);
QualType ResultType = Call->getArg(2)->getType()->getPointeeType();
PrimType ResultT = *S.getContext().classify(ResultType);
bool Overflow;
@@ -887,7 +817,7 @@ static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
Result = Temp;
}
- // Write Result to ResultPtr and put Overflow on the stacl.
+ // Write Result to ResultPtr and put Overflow on the stack.
assignInteger(ResultPtr, ResultT, Result);
ResultPtr.initialize();
assert(Call->getDirectCallee()->getReturnType()->isBooleanType());
@@ -899,18 +829,13 @@ static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call, unsigned BuiltinOp) {
+ const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
- PrimType CarryT = *S.getContext().classify(Call->getArg(2)->getType());
- APSInt RHS = peekToAPSInt(S.Stk, RHST,
- align(primSize(PT_Ptr)) + align(primSize(CarryT)) +
- align(primSize(RHST)));
- APSInt LHS =
- peekToAPSInt(S.Stk, LHST,
- align(primSize(PT_Ptr)) + align(primSize(RHST)) +
- align(primSize(CarryT)) + align(primSize(LHST)));
- APSInt CarryIn = peekToAPSInt(
- S.Stk, LHST, align(primSize(PT_Ptr)) + align(primSize(CarryT)));
+ APSInt CarryIn = popToAPSInt(S.Stk, LHST);
+ APSInt RHS = popToAPSInt(S.Stk, RHST);
+ APSInt LHS = popToAPSInt(S.Stk, LHST);
+
APSInt CarryOut;
APSInt Result;
@@ -944,7 +869,6 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
// this is consistent.
CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);
- Pointer &CarryOutPtr = S.Stk.peek<Pointer>();
QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
PrimType CarryOutT = *S.getContext().classify(CarryOutType);
assignInteger(CarryOutPtr, CarryOutT, CarryOut);
@@ -958,9 +882,14 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const CallExpr *Call,
unsigned BuiltinOp) {
- unsigned CallSize = callArgSize(S, Call);
+
+ std::optional<APSInt> Fallback;
+ if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {
+ PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
+ Fallback = popToAPSInt(S.Stk, FallbackT);
+ }
PrimType ValT = *S.getContext().classify(Call->getArg(0));
- const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);
+ const APSInt &Val = popToAPSInt(S.Stk, ValT);
// When the argument is 0, the result of GCC builtins is undefined, whereas
// for Microsoft intrinsics, the result is the bit-width of the argument.
@@ -969,11 +898,8 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
BuiltinOp != Builtin::BI__lzcnt64;
if (Val == 0) {
- if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {
- // We have a fallback parameter.
- PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
- const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);
- pushInteger(S, Fallback, Call->getType());
+ if (Fallback) {
+ pushInteger(S, *Fallback, Call->getType());
return true;
}
@@ -988,16 +914,17 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const CallExpr *Call,
unsigned BuiltinID) {
- unsigned CallSize = callArgSize(S, Call);
+ std::optional<APSInt> Fallback;
+ if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {
+ PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
+ Fallback = popToAPSInt(S.Stk, FallbackT);
+ }
PrimType ValT = *S.getContext().classify(Call->getArg(0));
- const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);
+ const APSInt &Val = popToAPSInt(S.Stk, ValT);
if (Val == 0) {
- if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {
- // We have a fallback parameter.
- PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
- const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);
- pushInteger(S, Fallback, Call->getType());
+ if (Fallback) {
+ pushInteger(S, *Fallback, Call->getType());
return true;
}
return false;
@@ -1012,7 +939,7 @@ static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,
const CallExpr *Call) {
PrimType ReturnT = *S.getContext().classify(Call->getType());
PrimType ValT = *S.getContext().classify(Call->getArg(0));
- const APSInt &Val = peekToAPSInt(S.Stk, ValT);
+ const APSInt &Val = popToAPSInt(S.Stk, ValT);
assert(Val.getActiveBits() <= 64);
INT_TYPE_SWITCH(ReturnT,
@@ -1022,22 +949,19 @@ static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,
/// bool __atomic_always_lock_free(size_t, void const volatile*)
/// bool __atomic_is_lock_free(size_t, void const volatile*)
-/// bool __c11_atomic_is_lock_free(size_t)
static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call,
unsigned BuiltinOp) {
- PrimType ValT = *S.getContext().classify(Call->getArg(0));
- unsigned SizeValOffset = 0;
- if (BuiltinOp != Builtin::BI__c11_atomic_is_lock_free)
- SizeValOffset = align(primSize(ValT)) + align(primSize(PT_Ptr));
- const APSInt &SizeVal = peekToAPSInt(S.Stk, ValT, SizeValOffset);
-
auto returnBool = [&S](bool Value) -> bool {
S.Stk.push<Boolean>(Value);
return true;
};
+ PrimType ValT = *S.getContext().classify(Call->getArg(0));
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
+ const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
+
// For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power
// of two less than or equal to the maximum inline atomic width, we know it
// is lock-free. If the size isn't a power of two, or greater than the
@@ -1057,13 +981,11 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
// OK, we will inline appropriately-aligned operations of this size,
// and _Atomic(T) is appropriately-aligned.
- if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free ||
- Size == CharUnits::One())
+ if (Size == CharUnits::One())
return returnBool(true);
// Same for null pointers.
assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);
- const Pointer &Ptr = S.Stk.peek<Pointer>();
if (Ptr.isZero())
return returnBool(true);
@@ -1099,14 +1021,38 @@ static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
return false;
}
+/// bool __c11_atomic_is_lock_free(size_t)
+static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S,
+ CodePtr OpPC,
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
+ PrimType ValT = *S.getContext().classify(Call->getArg(0));
+ const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
+
+ auto returnBool = [&S](bool Value) -> bool {
+ S.Stk.push<Boolean>(Value);
+ return true;
+ };
+
+ CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
+ if (Size.isPowerOfTwo()) {
+ // Check against inlining width.
+ unsigned InlineWidthBits =
+ S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();
+ if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits))
+ return returnBool(true);
+ }
+
+ return false; // returnBool(false);
+}
+
/// __builtin_complex(Float A, float B);
static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg2 = S.Stk.peek<Floating>();
- const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
- Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 +
- align(primSize(PT_Ptr)));
+ const Floating &Arg2 = S.Stk.pop<Floating>();
+ const Floating &Arg1 = S.Stk.pop<Floating>();
+ Pointer &Result = S.Stk.peek<Pointer>();
Result.atIndex(0).deref<Floating>() = Arg1;
Result.atIndex(0).initialize();
@@ -1126,10 +1072,8 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call,
unsigned BuiltinOp) {
- unsigned CallSize = callArgSize(S, Call);
-
PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
- const APSInt &Alignment = peekToAPSInt(S.Stk, AlignmentT);
+ const APSInt &Alignment = popToAPSInt(S.Stk, AlignmentT);
if (Alignment < 0 || !Alignment.isPowerOf2()) {
S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
@@ -1148,7 +1092,7 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));
if (isIntegralType(FirstArgT)) {
- const APSInt &Src = peekToAPSInt(S.Stk, FirstArgT, CallSize);
+ const APSInt &Src = popToAPSInt(S.Stk, FirstArgT);
APSInt Align = Alignment.extOrTrunc(Src.getBitWidth());
if (BuiltinOp == Builtin::BI__builtin_align_up) {
APSInt AlignedVal =
@@ -1165,7 +1109,7 @@ static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
}
assert(FirstArgT == PT_Ptr);
- const Pointer &Ptr = S.Stk.peek<Pointer>(CallSize);
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
unsigned PtrOffset = Ptr.getByteOffset();
PtrOffset = Ptr.getIndex();
@@ -1233,25 +1177,12 @@ static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,
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)));
- }
+ if (Call->getNumArgs() == 3)
+ ExtraOffset = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));
+
+ APSInt Alignment = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());
@@ -1300,9 +1231,8 @@ static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
- APSInt Val = peekToAPSInt(S.Stk, ValT,
- align(primSize(ValT)) + align(primSize(IndexT)));
- APSInt Index = peekToAPSInt(S.Stk, IndexT);
+ APSInt Index = popToAPSInt(S.Stk, IndexT);
+ APSInt Val = popToAPSInt(S.Stk, ValT);
unsigned BitWidth = Val.getBitWidth();
uint64_t Shift = Index.extractBitsAsZExtValue(8, 0);
@@ -1333,9 +1263,8 @@ static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
- APSInt Val = peekToAPSInt(S.Stk, ValT,
- align(primSize(ValT)) + align(primSize(IndexT)));
- APSInt Idx = peekToAPSInt(S.Stk, IndexT);
+ APSInt Idx = popToAPSInt(S.Stk, IndexT);
+ APSInt Val = popToAPSInt(S.Stk, ValT);
unsigned BitWidth = Val.getBitWidth();
uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
@@ -1355,7 +1284,7 @@ static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
!Call->getArg(0)->getType()->isIntegerType())
return false;
- APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
+ APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
pushInteger(S, Val.countLeadingZeros(), CallType);
return true;
}
@@ -1368,7 +1297,7 @@ static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
!Call->getArg(0)->getType()->isIntegerType())
return false;
- APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
+ APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
pushInteger(S, Val.countTrailingZeros(), CallType);
return true;
}
@@ -1383,9 +1312,8 @@ static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
- APSInt Val =
- peekToAPSInt(S.Stk, ValT, align(primSize(ValT)) + align(primSize(MaskT)));
- APSInt Mask = peekToAPSInt(S.Stk, MaskT);
+ APSInt Mask = popToAPSInt(S.Stk, MaskT);
+ APSInt Val = popToAPSInt(S.Stk, ValT);
unsigned BitWidth = Val.getBitWidth();
APInt Result = APInt::getZero(BitWidth);
@@ -1407,9 +1335,8 @@ static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
- APSInt Val =
- peekToAPSInt(S.Stk, ValT, align(primSize(ValT)) + align(primSize(MaskT)));
- APSInt Mask = peekToAPSInt(S.Stk, MaskT);
+ APSInt Mask = popToAPSInt(S.Stk, MaskT);
+ APSInt Val = popToAPSInt(S.Stk, ValT);
unsigned BitWidth = Val.getBitWidth();
APInt Result = APInt::getZero(BitWidth);
@@ -1432,17 +1359,14 @@ static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
!Call->getArg(2)->getType()->isIntegerType())
return false;
+ const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
+
PrimType CarryInT = *S.getContext().classify(Call->getArg(0));
PrimType LHST = *S.getContext().classify(Call->getArg(1));
PrimType RHST = *S.getContext().classify(Call->getArg(2));
- unsigned PtrSize = align(primSize(PT_Ptr));
- APSInt CarryIn =
- peekToAPSInt(S.Stk, CarryInT,
- PtrSize + align(primSize(RHST)) + align(primSize(LHST)) +
- align(primSize(CarryInT)));
- APSInt LHS = peekToAPSInt(
- S.Stk, LHST, PtrSize + align(primSize(RHST)) + align(primSize(LHST)));
- APSInt RHS = peekToAPSInt(S.Stk, RHST, PtrSize + align(primSize(RHST)));
+ APSInt RHS = popToAPSInt(S.Stk, RHST);
+ APSInt LHS = popToAPSInt(S.Stk, LHST);
+ APSInt CarryIn = popToAPSInt(S.Stk, CarryInT);
bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
@@ -1457,7 +1381,6 @@ static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
APSInt CarryOut =
APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
- Pointer &CarryOutPtr = S.Stk.peek<Pointer>();
QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
PrimType CarryOutT = *S.getContext().classify(CarryOutType);
assignInteger(CarryOutPtr, CarryOutT, APSInt(Result, true));
@@ -1481,7 +1404,7 @@ static bool
interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const auto &Ptr = S.Stk.peek<Pointer>();
+ const auto &Ptr = S.Stk.pop<Pointer>();
assert(Ptr.getFieldDesc()->isPrimitiveArray());
// This should be created for a StringLiteral, so should alway shold at least
@@ -1500,6 +1423,7 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
// Walk up the call stack to find the appropriate caller and get the
// element type from it.
auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
+ APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
if (ElemType.isNull()) {
S.FFDiag(Call, S.getLangOpts().CPlusPlus20
@@ -1515,7 +1439,6 @@ static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
return false;
}
- APSInt Bytes = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
assert(!ElemSize.isZero());
// Divide the number of bytes by sizeof(ElemType), so we get the number of
@@ -1597,17 +1520,20 @@ static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,
const Expr *Source = nullptr;
const Block *BlockToDelete = nullptr;
- if (S.checkingPotentialConstantExpression())
+ if (S.checkingPotentialConstantExpression()) {
+ S.Stk.discard<Pointer>();
return false;
+ }
// This is permitted only within a call to std::allocator<T>::deallocate.
if (!S.getStdAllocatorCaller("deallocate")) {
S.FFDiag(Call);
+ S.Stk.discard<Pointer>();
return true;
}
{
- const Pointer &Ptr = S.Stk.peek<Pointer>();
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
if (Ptr.isZero()) {
S.CCEDiag(Call, diag::note_constexpr_deallocate_null);
@@ -1646,14 +1572,14 @@ static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,
static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
- const Floating &Arg0 = S.Stk.peek<Floating>();
+ const Floating &Arg0 = S.Stk.pop<Floating>();
S.Stk.push<Floating>(Arg0);
return true;
}
static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
const CallExpr *Call, unsigned ID) {
- const Pointer &Arg = S.Stk.peek<Pointer>();
+ const Pointer &Arg = S.Stk.pop<Pointer>();
assert(Arg.getFieldDesc()->isPrimitiveArray());
QualType ElemType = Arg.getFieldDesc()->getElemQualType();
@@ -1708,15 +1634,15 @@ static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 1);
if (Call->getArg(0)->getType()->isIntegerType()) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
- APSInt Val = peekToAPSInt(S.Stk, ArgT);
+ APSInt Val = popToAPSInt(S.Stk, ArgT);
pushInteger(S, Val.popcount(), Call->getType());
return true;
}
// Otherwise, the argument must be a vector.
assert(Call->getArg(0)->getType()->isVectorType());
- const Pointer &Arg = S.Stk.peek<Pointer>();
+ const Pointer &Arg = S.Stk.pop<Pointer>();
assert(Arg.getFieldDesc()->isPrimitiveArray());
- const Pointer &Dst = S.Stk.peek<Pointer>(primSize(PT_Ptr) * 2);
+ const Pointer &Dst = S.Stk.peek<Pointer>();
assert(Dst.getFieldDesc()->isPrimitiveArray());
assert(Arg.getFieldDesc()->getNumElems() ==
Dst.getFieldDesc()->getNumElems());
@@ -1743,11 +1669,9 @@ static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
assert(Call->getNumArgs() == 3);
const ASTContext &ASTCtx = S.getASTContext();
PrimType SizeT = *S.getContext().classify(Call->getArg(2));
- Pointer DestPtr = S.Stk.peek<Pointer>(align(primSize(SizeT)) +
- (align(primSize(PT_Ptr)) * 2));
- const Pointer SrcPtr = S.Stk.peek<Pointer>(align(primSize(SizeT)) +
- (align(primSize(PT_Ptr)) * 1));
- APSInt Size = peekToAPSInt(S.Stk, SizeT);
+ APSInt Size = popToAPSInt(S.Stk, SizeT);
+ const Pointer SrcPtr = S.Stk.pop<Pointer>();
+ const Pointer DestPtr = S.Stk.pop<Pointer>();
assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
@@ -1902,11 +1826,9 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
const CallExpr *Call, unsigned ID) {
assert(Call->getNumArgs() == 3);
PrimType SizeT = *S.getContext().classify(Call->getArg(2));
- const APSInt &Size = peekToAPSInt(S.Stk, SizeT);
- const Pointer &PtrA = S.Stk.peek<Pointer>(align(primSize(SizeT)) +
- (align(primSize(PT_Ptr)) * 2));
- const Pointer &PtrB = S.Stk.peek<Pointer>(align(primSize(SizeT)) +
- (align(primSize(PT_Ptr)) * 1));
+ const APSInt &Size = popToAPSInt(S.Stk, SizeT);
+ const Pointer &PtrB = S.Stk.pop<Pointer>();
+ const Pointer &PtrA = S.Stk.pop<Pointer>();
if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
ID == Builtin::BIwmemcmp)
@@ -2008,27 +1930,22 @@ static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
return false;
}
+// __builtin_memchr(ptr, int, int)
+// __builtin_strchr(ptr, int)
static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
const CallExpr *Call, unsigned ID) {
if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
diagnoseNonConstexprBuiltin(S, OpPC, ID);
- unsigned ArgOffset = 0;
- APSInt Desired;
std::optional<APSInt> MaxLength;
PrimType DesiredT = *S.getContext().classify(Call->getArg(1));
if (Call->getNumArgs() == 3) {
PrimType MaxT = *S.getContext().classify(Call->getArg(2));
- MaxLength = peekToAPSInt(S.Stk, MaxT);
-
- ArgOffset += align(primSize(MaxT)) + align(primSize(DesiredT));
- Desired = peekToAPSInt(S.Stk, DesiredT, ArgOffset);
- } else {
- Desired = peekToAPSInt(S.Stk, DesiredT);
- ArgOffset += align(primSize(DesiredT));
+ MaxLength = popToAPSInt(S.Stk, MaxT);
}
- const Pointer &Ptr = S.Stk.peek<Pointer>(ArgOffset + align(primSize(PT_Ptr)));
+ APSInt Desired = popToAPSInt(S.Stk, DesiredT);
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
if (MaxLength && MaxLength->isZero()) {
S.Stk.push<Pointer>();
@@ -2182,12 +2099,11 @@ static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const CallExpr *Call) {
PrimType KindT = *S.getContext().classify(Call->getArg(1));
- [[maybe_unused]] unsigned Kind = peekToAPSInt(S.Stk, KindT).getZExtValue();
+ [[maybe_unused]] unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
assert(Kind <= 3 && "unexpected kind");
- const Pointer &Ptr =
- S.Stk.peek<Pointer>(align(primSize(KindT)) + align(primSize(PT_Ptr)));
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
if (Ptr.isZero())
return false;
@@ -2212,7 +2128,7 @@ static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
if (!S.inConstantContext())
return false;
- const Pointer &Ptr = S.Stk.peek<Pointer>();
+ const Pointer &Ptr = S.Stk.pop<Pointer>();
auto Error = [&](int Diag) {
bool CalledFromStd = false;
@@ -2256,17 +2172,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
return Invalid(S, OpPC);
const InterpFrame *Frame = S.Current;
-
- std::optional<PrimType> ReturnT = S.getContext().classify(Call);
-
switch (BuiltinID) {
case Builtin::BI__builtin_is_constant_evaluated:
- if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_assume:
case Builtin::BI__assume:
- break;
+ return interp__builtin_assume(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_strcmp:
case Builtin::BIstrcmp:
case Builtin::BI__builtin_strncmp:
@@ -2275,32 +2188,27 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BIwcsncmp:
case Builtin::BI__builtin_wcscmp:
case Builtin::BIwcscmp:
- if (!interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);
+
case Builtin::BI__builtin_strlen:
case Builtin::BIstrlen:
case Builtin::BI__builtin_wcslen:
case Builtin::BIwcslen:
- if (!interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);
+
case Builtin::BI__builtin_nan:
case Builtin::BI__builtin_nanf:
case Builtin::BI__builtin_nanl:
case Builtin::BI__builtin_nanf16:
case Builtin::BI__builtin_nanf128:
- if (!interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false))
- return false;
- break;
+ return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);
+
case Builtin::BI__builtin_nans:
case Builtin::BI__builtin_nansf:
case Builtin::BI__builtin_nansl:
case Builtin::BI__builtin_nansf16:
case Builtin::BI__builtin_nansf128:
- if (!interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true))
- return false;
- break;
+ return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);
case Builtin::BI__builtin_huge_val:
case Builtin::BI__builtin_huge_valf:
@@ -2312,126 +2220,95 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_infl:
case Builtin::BI__builtin_inff16:
case Builtin::BI__builtin_inff128:
- if (!interp__builtin_inf(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_inf(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_copysign:
case Builtin::BI__builtin_copysignf:
case Builtin::BI__builtin_copysignl:
case Builtin::BI__builtin_copysignf128:
- if (!interp__builtin_copysign(S, OpPC, Frame))
- return false;
- break;
+ return interp__builtin_copysign(S, OpPC, Frame);
case Builtin::BI__builtin_fmin:
case Builtin::BI__builtin_fminf:
case Builtin::BI__builtin_fminl:
case Builtin::BI__builtin_fminf16:
case Builtin::BI__builtin_fminf128:
- if (!interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false))
- return false;
- break;
+ return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);
case Builtin::BI__builtin_fminimum_num:
case Builtin::BI__builtin_fminimum_numf:
case Builtin::BI__builtin_fminimum_numl:
case Builtin::BI__builtin_fminimum_numf16:
case Builtin::BI__builtin_fminimum_numf128:
- if (!interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true))
- return false;
- break;
+ return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);
case Builtin::BI__builtin_fmax:
case Builtin::BI__builtin_fmaxf:
case Builtin::BI__builtin_fmaxl:
case Builtin::BI__builtin_fmaxf16:
case Builtin::BI__builtin_fmaxf128:
- if (!interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false))
- return false;
- break;
+ return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);
case Builtin::BI__builtin_fmaximum_num:
case Builtin::BI__builtin_fmaximum_numf:
case Builtin::BI__builtin_fmaximum_numl:
case Builtin::BI__builtin_fmaximum_numf16:
case Builtin::BI__builtin_fmaximum_numf128:
- if (!interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true))
- return false;
- break;
+ return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
case Builtin::BI__builtin_isnan:
- if (!interp__builtin_isnan(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_isnan(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_issignaling:
- if (!interp__builtin_issignaling(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_issignaling(S, OpPC, Frame, Call);
case Builtin::BI__builtin_isinf:
- if (!interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call))
- return false;
- break;
+ return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);
case Builtin::BI__builtin_isinf_sign:
- if (!interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call))
- return false;
- break;
+ return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);
case Builtin::BI__builtin_isfinite:
- if (!interp__builtin_isfinite(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_isfinite(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_isnormal:
- if (!interp__builtin_isnormal(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_isnormal(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_issubnormal:
- if (!interp__builtin_issubnormal(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_issubnormal(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_iszero:
- if (!interp__builtin_iszero(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_iszero(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_signbit:
case Builtin::BI__builtin_signbitf:
case Builtin::BI__builtin_signbitl:
- if (!interp__builtin_signbit(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_signbit(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_isgreater:
case Builtin::BI__builtin_isgreaterequal:
case Builtin::BI__builtin_isless:
case Builtin::BI__builtin_islessequal:
case Builtin::BI__builtin_islessgreater:
case Builtin::BI__builtin_isunordered:
- if (!interp_floating_comparison(S, OpPC, Call, BuiltinID))
- return false;
- break;
+ return interp_floating_comparison(S, OpPC, Call, BuiltinID);
+
case Builtin::BI__builtin_isfpclass:
- if (!interp__builtin_isfpclass(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_isfpclass(S, OpPC, Frame, Call);
+
case Builtin::BI__builtin_fpclassify:
- if (!interp__builtin_fpclassify(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_fpclassify(S, OpPC, Frame, Call);
case Builtin::BI__builtin_fabs:
case Builtin::BI__builtin_fabsf:
case Builtin::BI__builtin_fabsl:
case Builtin::BI__builtin_fabsf128:
- if (!interp__builtin_fabs(S, OpPC, Frame))
- return false;
- break;
+ return interp__builtin_fabs(S, OpPC, Frame);
case Builtin::BI__builtin_abs:
case Builtin::BI__builtin_labs:
case Builtin::BI__builtin_llabs:
- if (!interp__builtin_abs(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_abs(S, OpPC, Frame, Call);
case Builtin::BI__builtin_popcount:
case Builtin::BI__builtin_popcountl:
@@ -2440,42 +2317,30 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__popcnt16: // Microsoft variants of popcount
case Builtin::BI__popcnt:
case Builtin::BI__popcnt64:
- if (!interp__builtin_popcount(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_popcount(S, OpPC, Frame, Call);
case Builtin::BI__builtin_parity:
case Builtin::BI__builtin_parityl:
case Builtin::BI__builtin_parityll:
- if (!interp__builtin_parity(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_parity(S, OpPC, Frame, Call);
case Builtin::BI__builtin_clrsb:
case Builtin::BI__builtin_clrsbl:
case Builtin::BI__builtin_clrsbll:
- if (!interp__builtin_clrsb(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_clrsb(S, OpPC, Frame, Call);
case Builtin::BI__builtin_bitreverse8:
case Builtin::BI__builtin_bitreverse16:
case Builtin::BI__builtin_bitreverse32:
case Builtin::BI__builtin_bitreverse64:
- if (!interp__builtin_bitreverse(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_bitreverse(S, OpPC, Frame, Call);
case Builtin::BI__builtin_classify_type:
- if (!interp__builtin_classify_type(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_classify_type(S, OpPC, Frame, Call);
case Builtin::BI__builtin_expect:
case Builtin::BI__builtin_expect_with_probability:
- if (!interp__builtin_expect(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_expect(S, OpPC, Frame, Call);
case Builtin::BI__builtin_rotateleft8:
case Builtin::BI__builtin_rotateleft16:
@@ -2486,9 +2351,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI_rotl:
case Builtin::BI_lrotl:
case Builtin::BI_rotl64:
- if (!interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/false))
- return false;
- break;
+ return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/false);
case Builtin::BI__builtin_rotateright8:
case Builtin::BI__builtin_rotateright16:
@@ -2499,23 +2362,18 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI_rotr:
case Builtin::BI_lrotr:
case Builtin::BI_rotr64:
- if (!interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/true))
- return false;
- break;
+ return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/true);
case Builtin::BI__builtin_ffs:
case Builtin::BI__builtin_ffsl:
case Builtin::BI__builtin_ffsll:
- if (!interp__builtin_ffs(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ffs(S, OpPC, Frame, Call);
+
case Builtin::BIaddressof:
case Builtin::BI__addressof:
case Builtin::BI__builtin_addressof:
assert(isNoopBuiltin(BuiltinID));
- if (!interp__builtin_addressof(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_addressof(S, OpPC, Frame, Call);
case Builtin::BIas_const:
case Builtin::BIforward:
@@ -2523,18 +2381,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BImove:
case Builtin::BImove_if_noexcept:
assert(isNoopBuiltin(BuiltinID));
- if (!interp__builtin_move(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_move(S, OpPC, Frame, Call);
case Builtin::BI__builtin_eh_return_data_regno:
- if (!interp__builtin_eh_return_data_regno(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_eh_return_data_regno(S, OpPC, Frame, Call);
case Builtin::BI__builtin_launder:
assert(isNoopBuiltin(BuiltinID));
- break;
+ return true;
case Builtin::BI__builtin_add_overflow:
case Builtin::BI__builtin_sub_overflow:
@@ -2557,9 +2411,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_smul_overflow:
case Builtin::BI__builtin_smull_overflow:
case Builtin::BI__builtin_smulll_overflow:
- if (!interp__builtin_overflowop(S, OpPC, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
case Builtin::BI__builtin_addcb:
case Builtin::BI__builtin_addcs:
@@ -2571,9 +2423,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__builtin_subc:
case Builtin::BI__builtin_subcl:
case Builtin::BI__builtin_subcll:
- if (!interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
case Builtin::BI__builtin_clz:
case Builtin::BI__builtin_clzl:
@@ -2583,141 +2433,101 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
case Builtin::BI__lzcnt:
case Builtin::BI__lzcnt64:
- if (!interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
case Builtin::BI__builtin_ctz:
case Builtin::BI__builtin_ctzl:
case Builtin::BI__builtin_ctzll:
case Builtin::BI__builtin_ctzs:
case Builtin::BI__builtin_ctzg:
- if (!interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
case Builtin::BI__builtin_bswap16:
case Builtin::BI__builtin_bswap32:
case Builtin::BI__builtin_bswap64:
- if (!interp__builtin_bswap(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_bswap(S, OpPC, Frame, Call);
case Builtin::BI__atomic_always_lock_free:
case Builtin::BI__atomic_is_lock_free:
+ return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
+
case Builtin::BI__c11_atomic_is_lock_free:
- if (!interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_c11_atomic_is_lock_free(S, OpPC, Frame, Call);
case Builtin::BI__builtin_complex:
- if (!interp__builtin_complex(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_complex(S, OpPC, Frame, Call);
case Builtin::BI__builtin_is_aligned:
case Builtin::BI__builtin_align_up:
case Builtin::BI__builtin_align_down:
- if (!interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
case Builtin::BI__builtin_assume_aligned:
- if (!interp__builtin_assume_aligned(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_bextr_u32:
case clang::X86::BI__builtin_ia32_bextr_u64:
case clang::X86::BI__builtin_ia32_bextri_u32:
case clang::X86::BI__builtin_ia32_bextri_u64:
- if (!interp__builtin_ia32_bextr(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ia32_bextr(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_bzhi_si:
case clang::X86::BI__builtin_ia32_bzhi_di:
- if (!interp__builtin_ia32_bzhi(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_lzcnt_u16:
case clang::X86::BI__builtin_ia32_lzcnt_u32:
case clang::X86::BI__builtin_ia32_lzcnt_u64:
- if (!interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_tzcnt_u16:
case clang::X86::BI__builtin_ia32_tzcnt_u32:
case clang::X86::BI__builtin_ia32_tzcnt_u64:
- if (!interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_pdep_si:
case clang::X86::BI__builtin_ia32_pdep_di:
- if (!interp__builtin_ia32_pdep(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ia32_pdep(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_pext_si:
case clang::X86::BI__builtin_ia32_pext_di:
- if (!interp__builtin_ia32_pext(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ia32_pext(S, OpPC, Frame, Call);
case clang::X86::BI__builtin_ia32_addcarryx_u32:
case clang::X86::BI__builtin_ia32_addcarryx_u64:
case clang::X86::BI__builtin_ia32_subborrow_u32:
case clang::X86::BI__builtin_ia32_subborrow_u64:
- if (!interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, Call,
- BuiltinID))
- return false;
- break;
+ return interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, Call,
+ BuiltinID);
case Builtin::BI__builtin_os_log_format_buffer_size:
- if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, Call);
case Builtin::BI__builtin_ptrauth_string_discriminator:
- if (!interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);
case Builtin::BI__noop:
pushInteger(S, 0, Call->getType());
- break;
+ return true;
case Builtin::BI__builtin_operator_new:
- if (!interp__builtin_operator_new(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_operator_new(S, OpPC, Frame, Call);
case Builtin::BI__builtin_operator_delete:
- if (!interp__builtin_operator_delete(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_operator_delete(S, OpPC, Frame, Call);
case Builtin::BI__arithmetic_fence:
- if (!interp__builtin_arithmetic_fence(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_arithmetic_fence(S, OpPC, Frame, Call);
case Builtin::BI__builtin_reduce_add:
case Builtin::BI__builtin_reduce_mul:
case Builtin::BI__builtin_reduce_and:
case Builtin::BI__builtin_reduce_or:
case Builtin::BI__builtin_reduce_xor:
- if (!interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
case Builtin::BI__builtin_elementwise_popcount:
- if (!interp__builtin_elementwise_popcount(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call);
case Builtin::BI__builtin_memcpy:
case Builtin::BImemcpy:
@@ -2727,9 +2537,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BImemmove:
case Builtin::BI__builtin_wmemmove:
case Builtin::BIwmemmove:
- if (!interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
case Builtin::BI__builtin_memcmp:
case Builtin::BImemcmp:
@@ -2737,9 +2545,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BIbcmp:
case Builtin::BI__builtin_wmemcmp:
case Builtin::BIwmemcmp:
- if (!interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
case Builtin::BImemchr:
case Builtin::BI__builtin_memchr:
@@ -2750,20 +2556,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
case Builtin::BIwcschr:
case Builtin::BI__builtin_wcschr:
case Builtin::BI__builtin_char_memchr:
- if (!interp__builtin_memchr(S, OpPC, Call, BuiltinID))
- return false;
- break;
+ return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
case Builtin::BI__builtin_object_size:
case Builtin::BI__builtin_dynamic_object_size:
- if (!interp__builtin_object_size(S, OpPC, Frame, Call))
- return false;
- break;
+ return interp__builtin_object_size(S, OpPC, Frame, Call);
case Builtin::BI__builtin_is_within_lifetime:
- if (!interp__builtin_is_within_lifetime(S, OpPC, Call))
- return false;
- break;
+ return interp__builtin_is_within_lifetime(S, OpPC, Call);
default:
S.FFDiag(S.Current->getLocation(OpPC),
@@ -2773,7 +2573,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
return false;
}
- return retPrimValue(S, OpPC, ReturnT, Call, BuiltinID);
+ llvm_unreachable("Unhandled builtin ID");
}
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,