[clang] 264d828 - [clang][Interp][NFC] Redo returning values from builtin functions
Timm Bäder via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 26 07:48:41 PST 2024
Author: Timm Bäder
Date: 2024-02-26T16:46:23+01:00
New Revision: 264d828ea6399c31c210b67a050fbf084634da6a
URL: https://github.com/llvm/llvm-project/commit/264d828ea6399c31c210b67a050fbf084634da6a
DIFF: https://github.com/llvm/llvm-project/commit/264d828ea6399c31c210b67a050fbf084634da6a.diff
LOG: [clang][Interp][NFC] Redo returning values from builtin functions
Instead of having retInt/retLong/retSizeT/etc., just add retInteger,
which takes an APSInt and returns it in form of the given QualType.
This makes the code a little neater, but is also necessary since
some builtins have a different return type with -fms-extensions.
Added:
Modified:
clang/lib/AST/Interp/InterpBuiltin.cpp
clang/test/CodeGen/ms-intrinsics-other.c
Removed:
################################################################################
diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index 2fb076d7793a8d..8f45c789296b66 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -62,97 +62,32 @@ static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) {
return R;
}
-/// Pushes \p Val to the stack, as a target-dependent 'int'.
-static void pushInt(InterpState &S, int32_t Val) {
- PrimType IntType = getIntPrimType(S);
- if (IntType == PT_Sint32)
- S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Val));
- else if (IntType == PT_Sint16)
- S.Stk.push<Integral<16, true>>(Integral<16, true>::from(Val));
- else
- llvm_unreachable("Int isn't 16 or 32 bit?");
-}
-
-static void pushAPSInt(InterpState &S, const APSInt &Val) {
- bool Signed = Val.isSigned();
-
- if (Signed) {
- switch (Val.getBitWidth()) {
- case 64:
- S.Stk.push<Integral<64, true>>(
- Integral<64, true>::from(Val.getSExtValue()));
- break;
- case 32:
- S.Stk.push<Integral<32, true>>(
- Integral<32, true>::from(Val.getSExtValue()));
- break;
- case 16:
- S.Stk.push<Integral<16, true>>(
- Integral<16, true>::from(Val.getSExtValue()));
- break;
- case 8:
- S.Stk.push<Integral<8, true>>(
- Integral<8, true>::from(Val.getSExtValue()));
- break;
- default:
- llvm_unreachable("Invalid integer bitwidth");
- }
- return;
- }
-
- // Unsigned.
- switch (Val.getBitWidth()) {
- case 64:
- S.Stk.push<Integral<64, false>>(
- Integral<64, false>::from(Val.getZExtValue()));
- break;
- case 32:
- S.Stk.push<Integral<32, false>>(
- Integral<32, false>::from(Val.getZExtValue()));
- break;
- case 16:
- S.Stk.push<Integral<16, false>>(
- Integral<16, false>::from(Val.getZExtValue()));
- break;
- case 8:
- S.Stk.push<Integral<8, false>>(
- Integral<8, false>::from(Val.getZExtValue()));
- break;
- default:
- llvm_unreachable("Invalid integer bitwidth");
+/// Pushes \p Val on the stack as the type given by \p QT.
+static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
+ assert(QT->isSignedIntegerOrEnumerationType() ||
+ QT->isUnsignedIntegerOrEnumerationType());
+ std::optional<PrimType> T = S.getContext().classify(QT);
+ assert(T);
+
+ if (QT->isSignedIntegerOrEnumerationType()) {
+ int64_t V = Val.getSExtValue();
+ INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });
+ } else {
+ assert(QT->isUnsignedIntegerOrEnumerationType());
+ uint64_t V = Val.getZExtValue();
+ INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });
}
}
-/// Pushes \p Val to the stack, as a target-dependent 'long'.
-static void pushLong(InterpState &S, int64_t Val) {
- PrimType LongType = getLongPrimType(S);
- if (LongType == PT_Sint64)
- S.Stk.push<Integral<64, true>>(Integral<64, true>::from(Val));
- else if (LongType == PT_Sint32)
- S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Val));
- else if (LongType == PT_Sint16)
- S.Stk.push<Integral<16, true>>(Integral<16, true>::from(Val));
+template <typename T>
+static void pushInteger(InterpState &S, T Val, QualType QT) {
+ if constexpr (std::is_same_v<T, APInt>)
+ pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
else
- llvm_unreachable("Long isn't 16, 32 or 64 bit?");
-}
-
-static void pushSizeT(InterpState &S, uint64_t Val) {
- const TargetInfo &TI = S.getCtx().getTargetInfo();
- unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());
-
- switch (SizeTWidth) {
- case 64:
- S.Stk.push<Integral<64, false>>(Integral<64, false>::from(Val));
- break;
- case 32:
- S.Stk.push<Integral<32, false>>(Integral<32, false>::from(Val));
- break;
- case 16:
- S.Stk.push<Integral<16, false>>(Integral<16, false>::from(Val));
- break;
- default:
- llvm_unreachable("We don't handle this size_t size.");
- }
+ pushInteger(S,
+ APSInt(APInt(sizeof(T) * 8, Val, std::is_signed_v<T>),
+ !std::is_signed_v<T>),
+ QT);
}
static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) {
@@ -188,7 +123,8 @@ static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result,
}
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
- const InterpFrame *Frame) {
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
const Pointer &A = getParam<Pointer>(Frame, 0);
const Pointer &B = getParam<Pointer>(Frame, 1);
@@ -222,12 +158,13 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
break;
}
- pushInt(S, Result);
+ pushInteger(S, Result, Call->getType());
return true;
}
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
- const InterpFrame *Frame) {
+ const InterpFrame *Frame,
+ const CallExpr *Call) {
const Pointer &StrPtr = getParam<Pointer>(Frame, 0);
if (!CheckArray(S, OpPC, StrPtr))
@@ -253,7 +190,8 @@ static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
break;
}
- pushSizeT(S, Len);
+ pushInteger(S, Len, Call->getType());
+
return true;
}
@@ -383,68 +321,71 @@ static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
/// take a float, double, long double, etc.
/// But for us, that's all a Floating anyway.
static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
- const InterpFrame *Frame, const Function *F) {
+ const InterpFrame *Frame, const Function *F,
+ const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
- pushInt(S, Arg.isNan());
+ pushInteger(S, Arg.isNan(), Call->getType());
return true;
}
static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
- const Function *F) {
+ const Function *F,
+ const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
- pushInt(S, Arg.isSignaling());
+ pushInteger(S, Arg.isSignaling(), Call->getType());
return true;
}
static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const Function *F,
- bool CheckSign) {
+ bool CheckSign, const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
bool IsInf = Arg.isInf();
if (CheckSign)
- pushInt(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0);
+ pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType());
else
- pushInt(S, Arg.isInf());
+ pushInteger(S, Arg.isInf(), Call->getType());
return true;
}
static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
- const Function *F) {
+ const Function *F, const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
- pushInt(S, Arg.isFinite());
+ pushInteger(S, Arg.isFinite(), Call->getType());
return true;
}
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
- const Function *F) {
+ const Function *F, const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
- pushInt(S, Arg.isNormal());
+ pushInteger(S, Arg.isNormal(), Call->getType());
return true;
}
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
- const Function *F) {
+ const Function *F,
+ const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
- pushInt(S, Arg.isDenormal());
+ pushInteger(S, Arg.isDenormal(), Call->getType());
return true;
}
static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
- const InterpFrame *Frame,
- const Function *F) {
+ const InterpFrame *Frame, const Function *F,
+ const CallExpr *Call) {
const Floating &Arg = S.Stk.peek<Floating>();
- pushInt(S, Arg.isZero());
+ pushInteger(S, Arg.isZero(), Call->getType());
return true;
}
@@ -461,7 +402,7 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
int32_t Result =
static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue());
- pushInt(S, Result);
+ pushInteger(S, Result, Call->getType());
return true;
}
@@ -469,7 +410,8 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
/// Five int values followed by one floating value.
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
- const Function *Func) {
+ const Function *Func,
+ const CallExpr *Call) {
const Floating &Val = S.Stk.peek<Floating>();
unsigned Index;
@@ -495,7 +437,7 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize));
APSInt I = peekToAPSInt(S.Stk, getIntPrimType(S), Offset);
- pushInt(S, I.getZExtValue());
+ pushInteger(S, I, Call->getType());
return true;
}
@@ -517,9 +459,12 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func,
const CallExpr *Call) {
+
+ Func->getDecl()->dump();
+
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
- pushInt(S, Val.popcount());
+ pushInteger(S, APSInt(APInt(32, Val.popcount())), Call->getType());
return true;
}
@@ -528,7 +473,7 @@ static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,
const Function *Func, const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
- pushInt(S, Val.popcount() % 2);
+ pushInteger(S, Val.popcount() % 2, Call->getType());
return true;
}
@@ -537,7 +482,7 @@ static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
const Function *Func, const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
- pushInt(S, Val.getBitWidth() - Val.getSignificantBits());
+ pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
return true;
}
@@ -547,7 +492,8 @@ static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
const CallExpr *Call) {
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
APSInt Val = peekToAPSInt(S.Stk, ArgT);
- pushAPSInt(S, APSInt(Val.reverseBits(), /*IsUnsigned=*/true));
+ // pushAPSInt(S, APSInt(Val.reverseBits(), /*IsUnsigned=*/true));
+ pushInteger(S, Val.reverseBits(), Call->getType());
return true;
}
@@ -562,7 +508,7 @@ static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,
GCCTypeClass ResultClass =
EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts());
int32_t ReturnVal = static_cast<int32_t>(ResultClass);
- pushInt(S, ReturnVal);
+ pushInteger(S, ReturnVal, Call->getType());
return true;
}
@@ -582,7 +528,7 @@ static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,
Offset += align(primSize(PT_Float));
APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset);
- pushLong(S, Val.getSExtValue());
+ pushInteger(S, Val, Call->getType());
return true;
}
@@ -605,7 +551,8 @@ static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,
Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),
/*IsUnsigned=*/true);
- pushAPSInt(S, Result);
+ // pushAPSInt(S, Result);
+ pushInteger(S, Result, Call->getType());
return true;
}
@@ -616,7 +563,7 @@ static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
APSInt Value = peekToAPSInt(S.Stk, ArgT);
uint64_t N = Value.countr_zero();
- pushInt(S, N == Value.getBitWidth() ? 0 : N + 1);
+ pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
return true;
}
@@ -659,7 +606,7 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
int Result =
S.getCtx().getTargetInfo().getEHDataRegisterNumber(Arg.getZExtValue());
- pushInt(S, Result);
+ pushInteger(S, Result, Call->getType());
return true;
}
@@ -837,7 +784,8 @@ static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
CarryOutPtr.initialize();
assert(Call->getType() == Call->getArg(0)->getType());
- pushAPSInt(S, Result);
+ // pushAPSInt(S, Result);
+ pushInteger(S, Result, Call->getType());
return true;
}
@@ -857,7 +805,7 @@ static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
if (ZeroIsUndefined && Val == 0)
return false;
- pushInt(S, Val.countl_zero());
+ pushInteger(S, APSInt(APInt(32, Val.countl_zero())), Call->getType());
return true;
}
@@ -870,7 +818,7 @@ static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,
if (Val == 0)
return false;
- pushInt(S, Val.countr_zero());
+ pushInteger(S, Val.countr_zero(), Call->getType());
return true;
}
@@ -972,11 +920,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
case Builtin::BI__assume:
break;
case Builtin::BI__builtin_strcmp:
- if (!interp__builtin_strcmp(S, OpPC, Frame))
+ if (!interp__builtin_strcmp(S, OpPC, Frame, Call))
return false;
break;
case Builtin::BI__builtin_strlen:
- if (!interp__builtin_strlen(S, OpPC, Frame))
+ if (!interp__builtin_strlen(S, OpPC, Frame, Call))
return false;
break;
case Builtin::BI__builtin_nan:
@@ -1036,38 +984,38 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
break;
case Builtin::BI__builtin_isnan:
- if (!interp__builtin_isnan(S, OpPC, Frame, F))
+ if (!interp__builtin_isnan(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_issignaling:
- if (!interp__builtin_issignaling(S, OpPC, Frame, F))
+ if (!interp__builtin_issignaling(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_isinf:
- if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
+ if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false, Call))
return false;
break;
case Builtin::BI__builtin_isinf_sign:
- if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
+ if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true, Call))
return false;
break;
case Builtin::BI__builtin_isfinite:
- if (!interp__builtin_isfinite(S, OpPC, Frame, F))
+ if (!interp__builtin_isfinite(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_isnormal:
- if (!interp__builtin_isnormal(S, OpPC, Frame, F))
+ if (!interp__builtin_isnormal(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_issubnormal:
- if (!interp__builtin_issubnormal(S, OpPC, Frame, F))
+ if (!interp__builtin_issubnormal(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_iszero:
- if (!interp__builtin_iszero(S, OpPC, Frame, F))
+ if (!interp__builtin_iszero(S, OpPC, Frame, F, Call))
return false;
break;
case Builtin::BI__builtin_isfpclass:
@@ -1075,7 +1023,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return false;
break;
case Builtin::BI__builtin_fpclassify:
- if (!interp__builtin_fpclassify(S, OpPC, Frame, F))
+ if (!interp__builtin_fpclassify(S, OpPC, Frame, F, Call))
return false;
break;
diff --git a/clang/test/CodeGen/ms-intrinsics-other.c b/clang/test/CodeGen/ms-intrinsics-other.c
index 36c40dddcbb4f5..189000d3213ac1 100644
--- a/clang/test/CodeGen/ms-intrinsics-other.c
+++ b/clang/test/CodeGen/ms-intrinsics-other.c
@@ -1,38 +1,38 @@
// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple x86_64--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple x86_64--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s
// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple x86_64--linux -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple x86_64--linux -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s
// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple aarch64--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple aarch64--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM-ARM64
// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple aarch64--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple aarch64--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM
// RUN: %clang_cc1 -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple armv7--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple armv7--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM
// RUN: %clang_cc1 -x c++ -std=c++11 \
// RUN: -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple x86_64--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple x86_64--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s
// RUN: %clang_cc1 -x c++ -std=c++11 \
// RUN: -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple x86_64--linux -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple x86_64--linux -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s
// RUN: %clang_cc1 -x c++ -std=c++11 \
// RUN: -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple aarch64--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple aarch64--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM-ARM64
// RUN: %clang_cc1 -x c++ -std=c++11 \
// RUN: -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple aarch64--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple aarch64--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM
// RUN: %clang_cc1 -x c++ -std=c++11 \
// RUN: -ffreestanding -fms-extensions -Wno-implicit-function-declaration \
-// RUN: -triple armv7--darwin -Oz -emit-llvm %s -o - \
+// RUN: -fexperimental-new-constant-interpreter -triple armv7--darwin -Oz -emit-llvm %s -o - \
// RUN: | FileCheck %s --check-prefix=CHECK-ARM
// LP64 targets use 'long' as 'int' for MS intrinsics (-fms-extensions)
More information about the cfe-commits
mailing list