Skip to content

Commit

Permalink
[clang][Interp] Make sure we push integers of the correct size
Browse files Browse the repository at this point in the history
Integers might not be 32 bits wide, so check the TargetInfo for their
size.

Differential Revision: https://reviews.llvm.org/D155568
  • Loading branch information
tbaederr committed Aug 17, 2023
1 parent c9f8aee commit 91af0d0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 19 deletions.
1 change: 1 addition & 0 deletions clang/lib/AST/Interp/Integral.h
Expand Up @@ -94,6 +94,7 @@ template <unsigned Bits, bool Signed> class Integral final {
explicit operator unsigned() const { return V; }
explicit operator int64_t() const { return V; }
explicit operator uint64_t() const { return V; }
explicit operator int32_t() const { return V; }

APSInt toAPSInt() const {
return APSInt(APInt(Bits, static_cast<uint64_t>(V), Signed), !Signed);
Expand Down
60 changes: 42 additions & 18 deletions clang/lib/AST/Interp/InterpBuiltin.cpp
Expand Up @@ -32,6 +32,30 @@ static APSInt peekToAPSInt(InterpStack &Stk, PrimType T) {
return R;
}

/// Pushes \p Val to the stack, as a target-dependent 'int'.
static void pushInt(InterpState &S, int32_t Val) {
const TargetInfo &TI = S.getCtx().getTargetInfo();
unsigned IntWidth = TI.getIntWidth();

if (IntWidth == 32)
S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Val));
else if (IntWidth == 16)
S.Stk.push<Integral<16, true>>(Integral<16, true>::from(Val));
else
llvm_unreachable("Int isn't 16 or 32 bit?");
}

static bool retInt(InterpState &S, CodePtr OpPC, APValue &Result) {
const TargetInfo &TI = S.getCtx().getTargetInfo();
unsigned IntWidth = TI.getIntWidth();

if (IntWidth == 32)
return Ret<PT_Sint32>(S, OpPC, Result);
else if (IntWidth == 16)
return Ret<PT_Sint16>(S, OpPC, Result);
llvm_unreachable("Int isn't 16 or 32 bit?");
}

static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame) {
const Pointer &A = getParam<Pointer>(Frame, 0);
Expand Down Expand Up @@ -67,7 +91,7 @@ static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
break;
}

S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Result));
pushInt(S, Result);
return true;
}

Expand Down Expand Up @@ -200,7 +224,7 @@ static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame, const Function *F) {
const Floating &Arg = S.Stk.peek<Floating>();

S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Arg.isNan()));
pushInt(S, Arg.isNan());
return true;
}

Expand All @@ -211,10 +235,9 @@ static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
bool IsInf = Arg.isInf();

if (CheckSign)
S.Stk.push<Integral<32, true>>(
Integral<32, true>::from(IsInf ? (Arg.isNegative() ? -1 : 1) : 0));
pushInt(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0);
else
S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Arg.isInf()));
pushInt(S, Arg.isInf());
return true;
}

Expand All @@ -223,7 +246,7 @@ static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
const Function *F) {
const Floating &Arg = S.Stk.peek<Floating>();

S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Arg.isFinite()));
pushInt(S, Arg.isFinite());
return true;
}

Expand All @@ -232,7 +255,7 @@ static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
const Function *F) {
const Floating &Arg = S.Stk.peek<Floating>();

S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Arg.isNormal()));
pushInt(S, Arg.isNormal());
return true;
}

Expand All @@ -249,12 +272,12 @@ static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,

int32_t Result =
static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue());
S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Result));
pushInt(S, Result);

return true;
}

/// Five int32 values followed by one floating value.
/// Five int values followed by one floating value.
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
const InterpFrame *Frame,
const Function *Func) {
Expand All @@ -280,8 +303,9 @@ static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
unsigned Offset = align(primSize(PT_Float)) +
((1 + (4 - Index)) * align(primSize(PT_Sint32)));

// FIXME: The size of the value we're peeking here is target-dependent.
const Integral<32, true> &I = S.Stk.peek<Integral<32, true>>(Offset);
S.Stk.push<Integral<32, true>>(I);
pushInt(S, static_cast<int32_t>(I));
return true;
}

Expand Down Expand Up @@ -312,7 +336,7 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
return RetVoid(S, OpPC, Dummy);
case Builtin::BI__builtin_strcmp:
if (interp__builtin_strcmp(S, OpPC, Frame))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_nan:
case Builtin::BI__builtin_nanf:
Expand Down Expand Up @@ -372,34 +396,34 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,

case Builtin::BI__builtin_isnan:
if (interp__builtin_isnan(S, OpPC, Frame, F))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;

case Builtin::BI__builtin_isinf:
if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;

case Builtin::BI__builtin_isinf_sign:
if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;

case Builtin::BI__builtin_isfinite:
if (interp__builtin_isfinite(S, OpPC, Frame, F))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_isnormal:
if (interp__builtin_isnormal(S, OpPC, Frame, F))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_isfpclass:
if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;
case Builtin::BI__builtin_fpclassify:
if (interp__builtin_fpclassify(S, OpPC, Frame, F))
return Ret<PT_Sint32>(S, OpPC, Dummy);
return retInt(S, OpPC, Dummy);
break;

case Builtin::BI__builtin_fabs:
Expand Down
10 changes: 9 additions & 1 deletion clang/test/AST/Interp/builtin-functions.cpp
Expand Up @@ -2,6 +2,8 @@
// RUN: %clang_cc1 -verify=ref %s -Wno-constant-evaluated
// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter %s -verify
// RUN: %clang_cc1 -std=c++20 -verify=ref %s -Wno-constant-evaluated
// RUN: %clang_cc1 -triple avr -std=c++20 -fexperimental-new-constant-interpreter %s -verify
// RUN: %clang_cc1 -triple avr -std=c++20 -verify=ref %s -Wno-constant-evaluated


namespace strcmp {
Expand Down Expand Up @@ -96,10 +98,12 @@ namespace isfpclass {
char isfpclass_pos_1 [!__builtin_isfpclass(1.0f, 0x0008) ? 1 : -1]; // fcNegNormal
char isfpclass_pos_2 [__builtin_isfpclass(1.0L, 0x01F8) ? 1 : -1]; // fcFinite
char isfpclass_pos_3 [!__builtin_isfpclass(1.0, 0x0003) ? 1 : -1]; // fcSNan|fcQNan
#ifndef __AVR__
char isfpclass_pdenorm_0[__builtin_isfpclass(1.0e-40f, 0x0080) ? 1 : -1]; // fcPosSubnormal
char isfpclass_pdenorm_1[__builtin_isfpclass(1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
char isfpclass_pdenorm_2[!__builtin_isfpclass(1.0e-40f, 0x003C) ? 1 : -1]; // fcNegative
char isfpclass_pdenorm_3[!__builtin_isfpclass(1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
#endif
char isfpclass_pzero_0 [__builtin_isfpclass(0.0f, 0x0060) ? 1 : -1]; // fcZero
char isfpclass_pzero_1 [__builtin_isfpclass(0.0, 0x01F8) ? 1 : -1]; // fcFinite
char isfpclass_pzero_2 [!__builtin_isfpclass(0.0L, 0x0020) ? 1 : -1]; // fcNegZero
Expand All @@ -109,9 +113,11 @@ namespace isfpclass {
char isfpclass_nzero_2 [!__builtin_isfpclass(-0.0L, 0x0040) ? 1 : -1]; // fcPosZero
char isfpclass_nzero_3 [!__builtin_isfpclass(-0.0, 0x0003) ? 1 : -1]; // fcNan
char isfpclass_ndenorm_0[__builtin_isfpclass(-1.0e-40f, 0x0010) ? 1 : -1]; // fcNegSubnormal
char isfpclass_ndenorm_1[__builtin_isfpclass(-1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
char isfpclass_ndenorm_2[!__builtin_isfpclass(-1.0e-40f, 0x03C0) ? 1 : -1]; // fcPositive
#ifndef __AVR__
char isfpclass_ndenorm_1[__builtin_isfpclass(-1.0e-310, 0x01F8) ? 1 : -1]; // fcFinite
char isfpclass_ndenorm_3[!__builtin_isfpclass(-1.0e-310, 0x0207) ? 1 : -1]; // ~fcFinite
#endif
char isfpclass_neg_0 [__builtin_isfpclass(-1.0, 0x0008) ? 1 : -1]; // fcNegNormal
char isfpclass_neg_1 [!__builtin_isfpclass(-1.0f, 0x00100) ? 1 : -1]; // fcPosNormal
char isfpclass_neg_2 [__builtin_isfpclass(-1.0L, 0x01F8) ? 1 : -1]; // fcFinite
Expand All @@ -136,9 +142,11 @@ namespace fpclassify {
char classify_inf [__builtin_fpclassify(-1, +1, -1, -1, -1, __builtin_inf())];
char classify_neg_inf [__builtin_fpclassify(-1, +1, -1, -1, -1, -__builtin_inf())];
char classify_normal [__builtin_fpclassify(-1, -1, +1, -1, -1, 1.539)];
#ifndef __AVR__
char classify_normal2 [__builtin_fpclassify(-1, -1, +1, -1, -1, 1e-307)];
char classify_denorm [__builtin_fpclassify(-1, -1, -1, +1, -1, 1e-308)];
char classify_denorm2 [__builtin_fpclassify(-1, -1, -1, +1, -1, -1e-308)];
#endif
char classify_zero [__builtin_fpclassify(-1, -1, -1, -1, +1, 0.0)];
char classify_neg_zero[__builtin_fpclassify(-1, -1, -1, -1, +1, -0.0)];
char classify_subnorm [__builtin_fpclassify(-1, -1, -1, +1, -1, 1.0e-38f)];
Expand Down

0 comments on commit 91af0d0

Please sign in to comment.