diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -94,6 +94,7 @@ 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(V), Signed), !Signed); diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp --- a/clang/lib/AST/Interp/InterpBuiltin.cpp +++ b/clang/lib/AST/Interp/InterpBuiltin.cpp @@ -32,6 +32,30 @@ 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>::from(Val)); + else if (IntWidth == 16) + S.Stk.push>(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(S, OpPC, Result); + else if (IntWidth == 16) + return Ret(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(Frame, 0); @@ -67,7 +91,7 @@ break; } - S.Stk.push>(Integral<32, true>::from(Result)); + pushInt(S, Result); return true; } @@ -200,7 +224,7 @@ const InterpFrame *Frame, const Function *F) { const Floating &Arg = S.Stk.peek(); - S.Stk.push>(Integral<32, true>::from(Arg.isNan())); + pushInt(S, Arg.isNan()); return true; } @@ -211,10 +235,9 @@ bool IsInf = Arg.isInf(); if (CheckSign) - S.Stk.push>( - 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>::from(Arg.isInf())); + pushInt(S, Arg.isInf()); return true; } @@ -223,7 +246,7 @@ const Function *F) { const Floating &Arg = S.Stk.peek(); - S.Stk.push>(Integral<32, true>::from(Arg.isFinite())); + pushInt(S, Arg.isFinite()); return true; } @@ -232,7 +255,7 @@ const Function *F) { const Floating &Arg = S.Stk.peek(); - S.Stk.push>(Integral<32, true>::from(Arg.isNormal())); + pushInt(S, Arg.isNormal()); return true; } @@ -249,12 +272,12 @@ int32_t Result = static_cast((F.classify() & FPClassArg).getZExtValue()); - S.Stk.push>(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) { @@ -280,8 +303,9 @@ 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>(Offset); - S.Stk.push>(I); + pushInt(S, static_cast(I)); return true; } @@ -312,7 +336,7 @@ return RetVoid(S, OpPC, Dummy); case Builtin::BI__builtin_strcmp: if (interp__builtin_strcmp(S, OpPC, Frame)) - return Ret(S, OpPC, Dummy); + return retInt(S, OpPC, Dummy); break; case Builtin::BI__builtin_nan: case Builtin::BI__builtin_nanf: @@ -372,34 +396,34 @@ case Builtin::BI__builtin_isnan: if (interp__builtin_isnan(S, OpPC, Frame, F)) - return Ret(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(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(S, OpPC, Dummy); + return retInt(S, OpPC, Dummy); break; case Builtin::BI__builtin_isfinite: if (interp__builtin_isfinite(S, OpPC, Frame, F)) - return Ret(S, OpPC, Dummy); + return retInt(S, OpPC, Dummy); break; case Builtin::BI__builtin_isnormal: if (interp__builtin_isnormal(S, OpPC, Frame, F)) - return Ret(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(S, OpPC, Dummy); + return retInt(S, OpPC, Dummy); break; case Builtin::BI__builtin_fpclassify: if (interp__builtin_fpclassify(S, OpPC, Frame, F)) - return Ret(S, OpPC, Dummy); + return retInt(S, OpPC, Dummy); break; case Builtin::BI__builtin_fabs: diff --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp --- a/clang/test/AST/Interp/builtin-functions.cpp +++ b/clang/test/AST/Interp/builtin-functions.cpp @@ -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 { @@ -96,10 +98,12 @@ 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 @@ -109,9 +113,11 @@ 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 @@ -136,9 +142,11 @@ 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)];