Author: Timm Bäder Date: 2023-01-25T14:48:39+01:00 New Revision: b3b1d86137422dbdc9e8626925067f1b50734036
URL: https://github.com/llvm/llvm-project/commit/b3b1d86137422dbdc9e8626925067f1b50734036 DIFF: https://github.com/llvm/llvm-project/commit/b3b1d86137422dbdc9e8626925067f1b50734036.diff LOG: Revert "[clang][Interp] Support floating-point values" This reverts commit 62f43c3eae2460d4ca3da7897fd2d7c56920638c. This breaks a couple of builders, e.g. https://lab.llvm.org/buildbot/#/builders/139/builds/34925 Added: Modified: clang/lib/AST/CMakeLists.txt clang/lib/AST/Interp/Boolean.h clang/lib/AST/Interp/ByteCodeEmitter.cpp clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Context.cpp clang/lib/AST/Interp/Descriptor.cpp clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/Integral.h clang/lib/AST/Interp/Interp.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/InterpFrame.cpp clang/lib/AST/Interp/InterpStack.h clang/lib/AST/Interp/Opcodes.td clang/lib/AST/Interp/PrimType.cpp clang/lib/AST/Interp/PrimType.h clang/test/SemaCXX/rounding-math.cpp Removed: clang/lib/AST/Interp/Floating.cpp clang/lib/AST/Interp/Floating.h clang/lib/AST/Interp/Primitives.h clang/test/AST/Interp/const-fpfeatures.cpp clang/test/AST/Interp/floats.cpp ################################################################################ diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index 3d8d8cc077615..e4c1008fe34b1 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -74,7 +74,6 @@ add_clang_library(clangAST Interp/Frame.cpp Interp/Function.cpp Interp/InterpBuiltin.cpp - Interp/Floating.cpp Interp/Interp.cpp Interp/InterpBlock.cpp Interp/InterpFrame.cpp diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h index e496f70eb4117..3122388a49a55 100644 --- a/clang/lib/AST/Interp/Boolean.h +++ b/clang/lib/AST/Interp/Boolean.h @@ -27,10 +27,12 @@ class Boolean final { /// Underlying boolean. bool V; + /// Construct a wrapper from a boolean. + explicit Boolean(bool V) : V(V) {} + public: /// Zero-initializes a boolean. Boolean() : V(false) {} - explicit Boolean(bool V) : V(V) {} bool operator<(Boolean RHS) const { return V < RHS.V; } bool operator>(Boolean RHS) const { return V > RHS.V; } diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index be56348beca73..4633d1e0823b6 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -8,7 +8,6 @@ #include "ByteCodeEmitter.h" #include "Context.h" -#include "Floating.h" #include "Opcode.h" #include "Program.h" #include "clang/AST/DeclCXX.h" diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp b/clang/lib/AST/Interp/ByteCodeExprGen.cpp index 62ed09f078c18..ae8bf377d262f 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -11,7 +11,6 @@ #include "ByteCodeGenError.h" #include "ByteCodeStmtGen.h" #include "Context.h" -#include "Floating.h" #include "Function.h" #include "PrimType.h" #include "Program.h" @@ -96,41 +95,6 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) { return this->emitGetPtrBase(ToBase->Offset, CE); } - case CK_FloatingCast: { - if (!this->visit(SubExpr)) - return false; - const auto *TargetSemantics = - &Ctx.getASTContext().getFloatTypeSemantics(CE->getType()); - return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE); - } - - case CK_IntegralToFloating: { - std::optional<PrimType> FromT = classify(SubExpr->getType()); - if (!FromT) - return false; - - if (!this->visit(SubExpr)) - return false; - - const auto *TargetSemantics = - &Ctx.getASTContext().getFloatTypeSemantics(CE->getType()); - llvm::RoundingMode RM = getRoundingMode(CE); - return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE); - } - - case CK_FloatingToBoolean: - case CK_FloatingToIntegral: { - std::optional<PrimType> ToT = classify(CE->getType()); - - if (!ToT) - return false; - - if (!this->visit(SubExpr)) - return false; - - return this->emitCastFloatingIntegral(*ToT, CE); - } - case CK_ArrayToPointerDecay: case CK_AtomicToNonAtomic: case CK_ConstructorConversion: @@ -172,14 +136,6 @@ bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) { return this->emitConst(LE->getValue(), LE); } -template <class Emitter> -bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) { - if (DiscardResult) - return true; - - return this->emitConstFloat(E->getValue(), E); -} - template <class Emitter> bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) { return this->visit(PE->getSubExpr()); @@ -239,22 +195,14 @@ bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) { case BO_GE: return Discard(this->emitGE(*LT, BO)); case BO_Sub: - if (BO->getType()->isFloatingType()) - return Discard(this->emitSubf(getRoundingMode(BO), BO)); return Discard(this->emitSub(*T, BO)); case BO_Add: - if (BO->getType()->isFloatingType()) - return Discard(this->emitAddf(getRoundingMode(BO), BO)); return Discard(this->emitAdd(*T, BO)); case BO_Mul: - if (BO->getType()->isFloatingType()) - return Discard(this->emitMulf(getRoundingMode(BO), BO)); return Discard(this->emitMul(*T, BO)); case BO_Rem: return Discard(this->emitRem(*T, BO)); case BO_Div: - if (BO->getType()->isFloatingType()) - return Discard(this->emitDivf(getRoundingMode(BO), BO)); return Discard(this->emitDiv(*T, BO)); case BO_Assign: if (DiscardResult) @@ -567,9 +515,6 @@ bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator( assert(!E->getType()->isPointerType() && "Support pointer arithmethic in compound assignment operators"); - assert(!E->getType()->isFloatingType() && - "Support floating types in compound assignment operators"); - // Get LHS pointer, load its value and get RHS value. if (!visit(LHS)) return false; @@ -691,8 +636,6 @@ bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) { return this->emitZeroUint64(E); case PT_Ptr: return this->emitNullPtr(E); - case PT_Float: - assert(false); } llvm_unreachable("unknown primitive type"); } @@ -857,7 +800,6 @@ bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) { case PT_Bool: return this->emitConstBool(Value, E); case PT_Ptr: - case PT_Float: llvm_unreachable("Invalid integral type"); break; } diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.h b/clang/lib/AST/Interp/ByteCodeExprGen.h index 6b82818fe09ae..7af61695864c9 100644 --- a/clang/lib/AST/Interp/ByteCodeExprGen.h +++ b/clang/lib/AST/Interp/ByteCodeExprGen.h @@ -58,7 +58,6 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, // Expression visitors - result returned on interp stack. bool VisitCastExpr(const CastExpr *E); bool VisitIntegerLiteral(const IntegerLiteral *E); - bool VisitFloatingLiteral(const FloatingLiteral *E); bool VisitParenExpr(const ParenExpr *E); bool VisitBinaryOperator(const BinaryOperator *E); bool VisitPointerArithBinOp(const BinaryOperator *E); @@ -235,15 +234,6 @@ class ByteCodeExprGen : public ConstStmtVisitor<ByteCodeExprGen<Emitter>, bool>, return VD->hasGlobalStorage() || VD->isConstexpr(); } - llvm::RoundingMode getRoundingMode(const Expr *E) const { - FPOptions FPO = E->getFPFeaturesInEffect(Ctx.getLangOpts()); - - if (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) - return llvm::RoundingMode::NearestTiesToEven; - - return FPO.getRoundingMode(); - } - protected: /// Variable to storage mapping. llvm::DenseMap<const ValueDecl *, Scope::Local> Locals; diff --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp index 8d1c077e1817d..16471242f3282 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -113,9 +113,6 @@ std::optional<PrimType> Context::classify(QualType T) const { if (T->isNullPtrType()) return PT_Ptr; - if (T->isFloatingType()) - return PT_Float; - if (auto *AT = dyn_cast<AtomicType>(T)) return classify(AT->getValueType()); diff --git a/clang/lib/AST/Interp/Descriptor.cpp b/clang/lib/AST/Interp/Descriptor.cpp index e9fe159eccd4b..04bc8681dd6ec 100644 --- a/clang/lib/AST/Interp/Descriptor.cpp +++ b/clang/lib/AST/Interp/Descriptor.cpp @@ -8,7 +8,6 @@ #include "Descriptor.h" #include "Boolean.h" -#include "Floating.h" #include "Pointer.h" #include "PrimType.h" #include "Record.h" @@ -171,11 +170,6 @@ static void moveRecord(Block *B, char *Src, char *Dst, Descriptor *D) { } static BlockCtorFn getCtorPrim(PrimType Type) { - // Floating types are special. They are primitives, but need their - // constructor called. - if (Type == PT_Float) - return ctorTy<PrimConv<PT_Float>::T>; - COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr); } diff --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp index d362ccdc73282..d31e879d516fb 100644 --- a/clang/lib/AST/Interp/Disasm.cpp +++ b/clang/lib/AST/Interp/Disasm.cpp @@ -10,7 +10,6 @@ // //===----------------------------------------------------------------------===// -#include "Floating.h" #include "Function.h" #include "Opcode.h" #include "PrimType.h" diff --git a/clang/lib/AST/Interp/Floating.cpp b/clang/lib/AST/Interp/Floating.cpp deleted file mode 100644 index 922e17ad1450d..0000000000000 --- a/clang/lib/AST/Interp/Floating.cpp +++ /dev/null @@ -1,22 +0,0 @@ -//===---- Floating.cpp - Support for floating point values ------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "Floating.h" - -namespace clang { -namespace interp { - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F) { - F.print(OS); - return OS; -} - -Floating getSwappedBytes(Floating F) { return F; } - -} // namespace interp -} // namespace clang diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h deleted file mode 100644 index fb0884bb3b605..0000000000000 --- a/clang/lib/AST/Interp/Floating.h +++ /dev/null @@ -1,144 +0,0 @@ -//===--- Floating.h - Types for the constexpr VM ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Defines the VM types and helpers operating on types. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_INTERP_FLOATING_H -#define LLVM_CLANG_AST_INTERP_FLOATING_H - -#include "Primitives.h" -#include "clang/AST/APValue.h" -#include "llvm/ADT/APFloat.h" - -namespace clang { -namespace interp { - -using APFloat = llvm::APFloat; -using APSInt = llvm::APSInt; - -class Floating final { -private: - // The underlying value storage. - APFloat F; - -public: - /// Zero-initializes a Floating. - Floating() : F(0.0f) {} - Floating(const APFloat &F) : F(F) {} - - // Static constructors for special floating point values. - static Floating getInf(const llvm::fltSemantics &Sem) { - return Floating(APFloat::getInf(Sem)); - } - const APFloat &getAPFloat() const { return F; } - - bool operator<(Floating RHS) const { return F < RHS.F; } - bool operator>(Floating RHS) const { return F > RHS.F; } - bool operator<=(Floating RHS) const { return F <= RHS.F; } - bool operator>=(Floating RHS) const { return F >= RHS.F; } - bool operator==(Floating RHS) const { return F == RHS.F; } - bool operator!=(Floating RHS) const { return F != RHS.F; } - Floating operator-() const { return Floating(-F); } - - APFloat::opStatus convertToInteger(APSInt &Result) const { - bool IsExact; - return F.convertToInteger(Result, llvm::APFloat::rmTowardZero, &IsExact); - } - - Floating toSemantics(const llvm::fltSemantics *Sem, - llvm::RoundingMode RM) const { - APFloat Copy = F; - bool LosesInfo; - Copy.convert(*Sem, RM, &LosesInfo); - (void)LosesInfo; - return Floating(Copy); - } - - /// Convert this Floating to one with the same semantics as \Other. - Floating toSemantics(const Floating &Other, llvm::RoundingMode RM) const { - return toSemantics(&Other.F.getSemantics(), RM); - } - - APSInt toAPSInt(unsigned NumBits = 0) const { - return APSInt(F.bitcastToAPInt()); - } - APValue toAPValue() const { return APValue(F); } - void print(llvm::raw_ostream &OS) const { - // Can't use APFloat::print() since it appends a newline. - SmallVector<char, 16> Buffer; - F.toString(Buffer); - OS << Buffer; - } - - unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); } - - bool isSigned() const { return true; } - bool isNegative() const { return F.isNegative(); } - bool isPositive() const { return !F.isNegative(); } - bool isZero() const { return F.isZero(); } - bool isNonZero() const { return F.isNonZero(); } - bool isMin() const { return F.isSmallest(); } - bool isMinusOne() const { return F.isExactlyValue(-1.0); } - bool isNan() const { return F.isNaN(); } - bool isFinite() const { return F.isFinite(); } - - ComparisonCategoryResult compare(const Floating &RHS) const { - return Compare(F, RHS.F); - } - - static APFloat::opStatus fromIntegral(APSInt Val, - const llvm::fltSemantics &Sem, - llvm::RoundingMode RM, - Floating &Result) { - APFloat F = APFloat(Sem); - APFloat::opStatus Status = F.convertFromAPInt(Val, Val.isSigned(), RM); - Result = Floating(F); - return Status; - } - - // ------- - - static APFloat::opStatus add(Floating A, Floating B, llvm::RoundingMode RM, - Floating *R) { - *R = Floating(A.F); - return R->F.add(B.F, RM); - } - - static APFloat::opStatus sub(Floating A, Floating B, llvm::RoundingMode RM, - Floating *R) { - *R = Floating(A.F); - return R->F.subtract(B.F, RM); - } - - static APFloat::opStatus mul(Floating A, Floating B, llvm::RoundingMode RM, - Floating *R) { - *R = Floating(A.F); - return R->F.multiply(B.F, RM); - } - - static APFloat::opStatus div(Floating A, Floating B, llvm::RoundingMode RM, - Floating *R) { - *R = Floating(A.F); - return R->F.divide(B.F, RM); - } - - static bool neg(Floating A, Floating *R) { - *R = -A; - return false; - } -}; - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Floating F); -Floating getSwappedBytes(Floating F); - -} // namespace interp -} // namespace clang - -#endif diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h index d45bd89bb5a66..8a742333ae57e 100644 --- a/clang/lib/AST/Interp/Integral.h +++ b/clang/lib/AST/Interp/Integral.h @@ -21,14 +21,33 @@ #include <cstddef> #include <cstdint> -#include "Primitives.h" - namespace clang { namespace interp { using APInt = llvm::APInt; using APSInt = llvm::APSInt; +/// Helper to compare two comparable types. +template <typename T> +ComparisonCategoryResult Compare(const T &X, const T &Y) { + if (X < Y) + return ComparisonCategoryResult::Less; + if (X > Y) + return ComparisonCategoryResult::Greater; + return ComparisonCategoryResult::Equal; +} + +// Helper structure to select the representation. +template <unsigned Bits, bool Signed> struct Repr; +template <> struct Repr<8, false> { using Type = uint8_t; }; +template <> struct Repr<16, false> { using Type = uint16_t; }; +template <> struct Repr<32, false> { using Type = uint32_t; }; +template <> struct Repr<64, false> { using Type = uint64_t; }; +template <> struct Repr<8, true> { using Type = int8_t; }; +template <> struct Repr<16, true> { using Type = int16_t; }; +template <> struct Repr<32, true> { using Type = int32_t; }; +template <> struct Repr<64, true> { using Type = int64_t; }; + /// Wrapper around numeric types. /// /// These wrappers are required to shared an interface between APSint and @@ -37,16 +56,6 @@ using APSInt = llvm::APSInt; template <unsigned Bits, bool Signed> class Integral final { private: template <unsigned OtherBits, bool OtherSigned> friend class Integral; - // Helper structure to select the representation. - template <unsigned ReprBits, bool ReprSigned> struct Repr; - template <> struct Repr<8, false> { using Type = uint8_t; }; - template <> struct Repr<16, false> { using Type = uint16_t; }; - template <> struct Repr<32, false> { using Type = uint32_t; }; - template <> struct Repr<64, false> { using Type = uint64_t; }; - template <> struct Repr<8, true> { using Type = int8_t; }; - template <> struct Repr<16, true> { using Type = int16_t; }; - template <> struct Repr<32, true> { using Type = int32_t; }; - template <> struct Repr<64, true> { using Type = int64_t; }; // The primitive representing the integral. using ReprT = typename Repr<Bits, Signed>::Type; diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 648f63105985a..6a600b306bad4 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -473,49 +473,6 @@ bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) { return CheckFieldsInitialized(S, OpPC, This, R); } -bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) { - // In a constant context, assume that any dynamic rounding mode or FP - // exception state matches the default floating-point environment. - if (S.inConstantContext()) - return true; - - const SourceInfo &E = S.Current->getSource(OpPC); - FPOptions FPO = E.asExpr()->getFPFeaturesInEffect(S.Ctx.getLangOpts()); - - if ((Status & APFloat::opInexact) && - FPO.getRoundingMode() == llvm::RoundingMode::Dynamic) { - // Inexact result means that it depends on rounding mode. If the requested - // mode is dynamic, the evaluation cannot be made in compile time. - S.FFDiag(E, diag::note_constexpr_dynamic_rounding); - return false; - } - - if ((Status != APFloat::opOK) && - (FPO.getRoundingMode() == llvm::RoundingMode::Dynamic || - FPO.getExceptionMode() != LangOptions::FPE_Ignore || - FPO.getAllowFEnvAccess())) { - S.FFDiag(E, diag::note_constexpr_float_arithmetic_strict); - return false; - } - - if ((Status & APFloat::opStatus::opInvalidOp) && - FPO.getExceptionMode() != LangOptions::FPE_Ignore) { - // There is no usefully definable result. - S.FFDiag(E); - return false; - } - - return true; -} - -bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, - llvm::RoundingMode RM) { - Floating F = S.Stk.pop<Floating>(); - Floating Result = F.toSemantics(Sem, RM); - S.Stk.push<Floating>(Result); - return true; -} - bool Interpret(InterpState &S, APValue &Result) { // The current stack frame when we started Interpret(). // This is being used by the ops to determine wheter diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index 9613eafdb5911..7ee823ef130af 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -14,7 +14,6 @@ #define LLVM_CLANG_AST_INTERP_INTERP_H #include "Boolean.h" -#include "Floating.h" #include "Function.h" #include "InterpFrame.h" #include "InterpStack.h" @@ -138,10 +137,6 @@ bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) { return true; } -/// Checks if the result is a floating-point operation is valid -/// in the current context. -bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status); - /// Interpreter entry point. bool Interpret(InterpState &S, APValue &Result); @@ -193,16 +188,6 @@ bool Add(InterpState &S, CodePtr OpPC) { return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS); } -inline bool Addf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { - const Floating &RHS = S.Stk.pop<Floating>(); - const Floating &LHS = S.Stk.pop<Floating>(); - - Floating Result; - auto Status = Floating::add(LHS, RHS, RM, &Result); - S.Stk.push<Floating>(Result); - return CheckFloatResult(S, OpPC, Status); -} - template <PrimType Name, class T = typename PrimConv<Name>::T> bool Sub(InterpState &S, CodePtr OpPC) { const T &RHS = S.Stk.pop<T>(); @@ -211,16 +196,6 @@ bool Sub(InterpState &S, CodePtr OpPC) { return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS); } -inline bool Subf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { - const Floating &RHS = S.Stk.pop<Floating>(); - const Floating &LHS = S.Stk.pop<Floating>(); - - Floating Result; - auto Status = Floating::sub(LHS, RHS, RM, &Result); - S.Stk.push<Floating>(Result); - return CheckFloatResult(S, OpPC, Status); -} - template <PrimType Name, class T = typename PrimConv<Name>::T> bool Mul(InterpState &S, CodePtr OpPC) { const T &RHS = S.Stk.pop<T>(); @@ -229,15 +204,6 @@ bool Mul(InterpState &S, CodePtr OpPC) { return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS); } -inline bool Mulf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { - const Floating &RHS = S.Stk.pop<Floating>(); - const Floating &LHS = S.Stk.pop<Floating>(); - - Floating Result; - auto Status = Floating::mul(LHS, RHS, RM, &Result); - S.Stk.push<Floating>(Result); - return CheckFloatResult(S, OpPC, Status); -} /// 1) Pops the RHS from the stack. /// 2) Pops the LHS from the stack. /// 3) Pushes 'LHS & RHS' on the stack @@ -329,19 +295,6 @@ bool Div(InterpState &S, CodePtr OpPC) { return false; } -inline bool Divf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) { - const Floating &RHS = S.Stk.pop<Floating>(); - const Floating &LHS = S.Stk.pop<Floating>(); - - if (!CheckDivRem(S, OpPC, LHS, RHS)) - return false; - - Floating Result; - auto Status = Floating::div(LHS, RHS, RM, &Result); - S.Stk.push<Floating>(Result); - return CheckFloatResult(S, OpPC, Status); -} - //===----------------------------------------------------------------------===// // Inv //===----------------------------------------------------------------------===// @@ -1229,52 +1182,6 @@ template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) { return true; } -/// 1) Pops a Floating from the stack. -/// 2) Pushes a new floating on the stack that uses the given semantics. -/// Not templated, so implemented in Interp.cpp. -bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem, - llvm::RoundingMode RM); - -template <PrimType Name, class T = typename PrimConv<Name>::T> -bool CastIntegralFloating(InterpState &S, CodePtr OpPC, - const llvm::fltSemantics *Sem, - llvm::RoundingMode RM) { - const T &From = S.Stk.pop<T>(); - APSInt FromAP = From.toAPSInt(); - Floating Result; - - auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result); - S.Stk.push<Floating>(Result); - - return CheckFloatResult(S, OpPC, Status); -} - -template <PrimType Name, class T = typename PrimConv<Name>::T> -bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) { - const Floating &F = S.Stk.pop<Floating>(); - - if constexpr (std::is_same_v<T, Boolean>) { - S.Stk.push<T>(T(F.isNonZero())); - return true; - } else { - APSInt Result(std::max(8u, T::bitWidth() + 1), - /*IsUnsigned=*/!T::isSigned()); - auto Status = F.convertToInteger(Result); - - // Float-to-Integral overflow check. - if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite()) { - const Expr *E = S.Current->getExpr(OpPC); - QualType Type = E->getType(); - - S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type; - return S.noteUndefinedBehavior(); - } - - S.Stk.push<T>(T(Result)); - return CheckFloatResult(S, OpPC, Status); - } -} - //===----------------------------------------------------------------------===// // Zero, Nullptr //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/Interp/InterpFrame.cpp b/clang/lib/AST/Interp/InterpFrame.cpp index ee29997cfeccb..40644c538c6a7 100644 --- a/clang/lib/AST/Interp/InterpFrame.cpp +++ b/clang/lib/AST/Interp/InterpFrame.cpp @@ -8,7 +8,6 @@ #include "InterpFrame.h" #include "Boolean.h" -#include "Floating.h" #include "Function.h" #include "InterpStack.h" #include "InterpState.h" diff --git a/clang/lib/AST/Interp/InterpStack.h b/clang/lib/AST/Interp/InterpStack.h index 4987b2c33d6de..3adaad96515e0 100644 --- a/clang/lib/AST/Interp/InterpStack.h +++ b/clang/lib/AST/Interp/InterpStack.h @@ -160,8 +160,6 @@ class InterpStack final { else if constexpr (std::is_same_v<T, uint64_t> || std::is_same_v<T, Integral<64, false>>) return PT_Uint64; - else if constexpr (std::is_same_v<T, Floating>) - return PT_Float; llvm_unreachable("unknown type push()'ed into InterpStack"); } diff --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td index 54487e9d011b1..64582980b7e8c 100644 --- a/clang/lib/AST/Interp/Opcodes.td +++ b/clang/lib/AST/Interp/Opcodes.td @@ -25,7 +25,6 @@ def Sint32 : Type; def Uint32 : Type; def Sint64 : Type; def Uint64 : Type; -def Float : Type; def Ptr : Type; //===----------------------------------------------------------------------===// @@ -41,14 +40,11 @@ def ArgSint32 : ArgType { let Name = "int32_t"; } def ArgUint32 : ArgType { let Name = "uint32_t"; } def ArgSint64 : ArgType { let Name = "int64_t"; } def ArgUint64 : ArgType { let Name = "uint64_t"; } -def ArgFloat : ArgType { let Name = "Floating"; } def ArgBool : ArgType { let Name = "bool"; } def ArgFunction : ArgType { let Name = "const Function *"; } def ArgRecordDecl : ArgType { let Name = "const RecordDecl *"; } def ArgRecordField : ArgType { let Name = "const Record::Field *"; } -def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; } -def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; } //===----------------------------------------------------------------------===// // Classes of types instructions operate on. @@ -58,21 +54,18 @@ class TypeClass { list<Type> Types; } -def IntegerTypeClass : TypeClass { +def NumberTypeClass : TypeClass { let Types = [Sint8, Uint8, Sint16, Uint16, Sint32, Uint32, Sint64, Uint64]; } -def NumberTypeClass : TypeClass { - let Types = !listconcat(IntegerTypeClass.Types, [Float]); -} - -def FloatTypeClass : TypeClass { - let Types = [Float]; +def IntegerTypeClass : TypeClass { + let Types = [Sint8, Uint8, Sint16, Uint16, Sint32, + Uint32, Sint64, Uint64]; } def AluTypeClass : TypeClass { - let Types = !listconcat(IntegerTypeClass.Types, [Bool]); + let Types = !listconcat(NumberTypeClass.Types, [Bool]); } def PtrTypeClass : TypeClass { @@ -83,16 +76,12 @@ def BoolTypeClass : TypeClass { let Types = [Bool]; } -def NonPtrTypeClass : TypeClass { - let Types = !listconcat(IntegerTypeClass.Types, [Bool], [Float]); -} - def AllTypeClass : TypeClass { - let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types); + let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types); } def ComparableTypeClass : TypeClass { - let Types = !listconcat(AluTypeClass.Types, [Ptr], [Float]); + let Types = !listconcat(AluTypeClass.Types, [Ptr]); } class SingletonTypeClass<Type Ty> : TypeClass { @@ -119,11 +108,6 @@ class AluOpcode : Opcode { let HasGroup = 1; } -class FloatOpcode : Opcode { - let Types = []; - let Args = [ArgRoundingMode]; -} - class IntegerOpcode : Opcode { let Types = [IntegerTypeClass]; let HasGroup = 1; @@ -215,7 +199,6 @@ def ConstSint32 : ConstOpcode<Sint32, ArgSint32>; def ConstUint32 : ConstOpcode<Uint32, ArgUint32>; def ConstSint64 : ConstOpcode<Sint64, ArgSint64>; def ConstUint64 : ConstOpcode<Uint64, ArgUint64>; -def ConstFloat : ConstOpcode<Float, ArgFloat>; def ConstBool : ConstOpcode<Bool, ArgBool>; // [] -> [Integer] @@ -436,19 +419,13 @@ def DecPtr : Opcode { //===----------------------------------------------------------------------===// // [Real, Real] -> [Real] -def Add : AluOpcode; -def Addf : FloatOpcode; -def Sub : AluOpcode; -def Subf : FloatOpcode; -def Mul : AluOpcode; -def Mulf : FloatOpcode; -def Rem : IntegerOpcode; -def Div : IntegerOpcode; -def Divf : FloatOpcode; - -def BitAnd : IntegerOpcode; -def BitOr : IntegerOpcode; -def BitXor : IntegerOpcode; +def Sub : AluOpcode; +def Add : AluOpcode; +def Mul : AluOpcode; +def Rem : Opcode { + let Types = [NumberTypeClass]; + let HasGroup = 1; +} def Shl : Opcode { let Types = [IntegerTypeClass, IntegerTypeClass]; @@ -460,6 +437,14 @@ def Shr : Opcode { let HasGroup = 1; } +def BitAnd : IntegerOpcode; +def BitOr : IntegerOpcode; +def Div : Opcode { + let Types = [NumberTypeClass]; + let HasGroup = 1; +} +def BitXor : IntegerOpcode; + //===----------------------------------------------------------------------===// // Unary operators. //===----------------------------------------------------------------------===// @@ -477,19 +462,20 @@ def DecPop: IntegerOpcode; // [Real] -> [Real] def Neg: Opcode { - let Types = [NonPtrTypeClass]; + let Types = [AluTypeClass]; let HasGroup = 1; } // [Real] -> [Real] def Comp: Opcode { - let Types = [IntegerTypeClass]; + let Types = [NumberTypeClass]; let HasGroup = 1; } //===----------------------------------------------------------------------===// -// Cast, CastFP. +// Cast. //===----------------------------------------------------------------------===// +// TODO: Expand this to handle casts between more types. def FromCastTypeClass : TypeClass { let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool]; @@ -504,25 +490,6 @@ def Cast: Opcode { let HasGroup = 1; } -def CastFP : Opcode { - let Types = []; - let Args = [ArgFltSemantics, ArgRoundingMode]; -} - -// Cast an integer to a floating type -def CastIntegralFloating : Opcode { - let Types = [AluTypeClass]; - let Args = [ArgFltSemantics, ArgRoundingMode]; - let HasGroup = 1; -} - -// Cast a floating to an integer type -def CastFloatingIntegral : Opcode { - let Types = [AluTypeClass]; - let Args = []; - let HasGroup = 1; -} - //===----------------------------------------------------------------------===// // Comparison opcodes. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/Interp/PrimType.cpp b/clang/lib/AST/Interp/PrimType.cpp index da07b6f0fb0c6..eda90e1c36c20 100644 --- a/clang/lib/AST/Interp/PrimType.cpp +++ b/clang/lib/AST/Interp/PrimType.cpp @@ -8,7 +8,6 @@ #include "PrimType.h" #include "Boolean.h" -#include "Floating.h" #include "Pointer.h" using namespace clang; diff --git a/clang/lib/AST/Interp/PrimType.h b/clang/lib/AST/Interp/PrimType.h index 042325ad8428f..c8f2a600fb3ca 100644 --- a/clang/lib/AST/Interp/PrimType.h +++ b/clang/lib/AST/Interp/PrimType.h @@ -23,7 +23,6 @@ namespace interp { class Pointer; class Boolean; -class Floating; /// Enumeration of the primitive types of the VM. enum PrimType : unsigned { @@ -36,7 +35,6 @@ enum PrimType : unsigned { PT_Sint64, PT_Uint64, PT_Bool, - PT_Float, PT_Ptr, }; @@ -50,7 +48,6 @@ template <> struct PrimConv<PT_Sint32> { using T = Integral<32, true>; }; template <> struct PrimConv<PT_Uint32> { using T = Integral<32, false>; }; template <> struct PrimConv<PT_Sint64> { using T = Integral<64, true>; }; template <> struct PrimConv<PT_Uint64> { using T = Integral<64, false>; }; -template <> struct PrimConv<PT_Float> { using T = Floating; }; template <> struct PrimConv<PT_Bool> { using T = Boolean; }; template <> struct PrimConv<PT_Ptr> { using T = Pointer; }; @@ -80,7 +77,6 @@ inline bool isPrimitiveIntegral(PrimType Type) { case PT_Uint32: case PT_Sint64: case PT_Uint64: - case PT_Float: return true; default: return false; @@ -105,7 +101,6 @@ inline bool isPrimitiveIntegral(PrimType Type) { TYPE_SWITCH_CASE(PT_Uint32, B) \ TYPE_SWITCH_CASE(PT_Sint64, B) \ TYPE_SWITCH_CASE(PT_Uint64, B) \ - TYPE_SWITCH_CASE(PT_Float, B) \ TYPE_SWITCH_CASE(PT_Bool, B) \ TYPE_SWITCH_CASE(PT_Ptr, B) \ } \ diff --git a/clang/lib/AST/Interp/Primitives.h b/clang/lib/AST/Interp/Primitives.h deleted file mode 100644 index e935dbfd3691c..0000000000000 --- a/clang/lib/AST/Interp/Primitives.h +++ /dev/null @@ -1,36 +0,0 @@ -//===------ Primitives.h - Types for the constexpr VM -----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// Utilities and helper functions for all primitive types: -// - Integral -// - Floating -// - Boolean -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_AST_INTERP_PRIMITIVES_H -#define LLVM_CLANG_AST_INTERP_PRIMITIVES_H - -#include "clang/AST/ComparisonCategories.h" - -namespace clang { -namespace interp { - -/// Helper to compare two comparable types. -template <typename T> ComparisonCategoryResult Compare(const T &X, const T &Y) { - if (X < Y) - return ComparisonCategoryResult::Less; - if (X > Y) - return ComparisonCategoryResult::Greater; - return ComparisonCategoryResult::Equal; -} - -} // namespace interp -} // namespace clang - -#endif diff --git a/clang/test/AST/Interp/const-fpfeatures.cpp b/clang/test/AST/Interp/const-fpfeatures.cpp deleted file mode 100644 index 8f5d872916674..0000000000000 --- a/clang/test/AST/Interp/const-fpfeatures.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// RUN: %clang_cc1 -S -emit-llvm -triple i386-linux -std=c++2a -Wno-unknown-pragmas %s -o - | FileCheck %s -// RUN: %clang_cc1 -S -emit-llvm -triple i386-linux -fexperimental-new-constant-interpreter -std=c++2a -Wno-unknown-pragmas %s -o - | FileCheck %s - - -#pragma STDC FENV_ROUND FE_UPWARD - -float F1u = 1.0F + 0x0.000002p0F; -float F2u = 1.0F + 0x0.000001p0F; -float F3u = 0x1.000001p0; -// CHECK: @F1u = {{.*}} float 0x3FF0000020000000 -// CHECK: @F2u = {{.*}} float 0x3FF0000020000000 -// CHECK: @F3u = {{.*}} float 0x3FF0000020000000 - -float FI1u = 0xFFFFFFFFU; -// CHECK: @FI1u = {{.*}} float 0x41F0000000000000 - -#pragma STDC FENV_ROUND FE_DOWNWARD - -float F1d = 1.0F + 0x0.000002p0F; -float F2d = 1.0F + 0x0.000001p0F; -float F3d = 0x1.000001p0; - -// CHECK: @F1d = {{.*}} float 0x3FF0000020000000 -// CHECK: @F2d = {{.*}} float 1.000000e+00 -// CHECK: @F3d = {{.*}} float 1.000000e+00 - - -float FI1d = 0xFFFFFFFFU; -// CHECK: @FI1d = {{.*}} float 0x41EFFFFFE0000000 - -// nextUp(1.F) == 0x1.000002p0F - -constexpr float add_round_down(float x, float y) { - #pragma STDC FENV_ROUND FE_DOWNWARD - float res = x; - res = res + y; - return res; -} - -constexpr float add_round_up(float x, float y) { - #pragma STDC FENV_ROUND FE_UPWARD - float res = x; - res = res + y; - return res; -} - -float V1 = add_round_down(1.0F, 0x0.000001p0F); -float V2 = add_round_up(1.0F, 0x0.000001p0F); -// CHECK: @V1 = {{.*}} float 1.000000e+00 -// CHECK: @V2 = {{.*}} float 0x3FF0000020000000 - - -/// FIXME: The following tests need support for compound assign operators -/// with LHS and RHS of diff erent semantics. -#if 0 -constexpr float add_cast_round_down(float x, double y) { - #pragma STDC FENV_ROUND FE_DOWNWARD - float res = x; - res += y; - return res; -} - -constexpr float add_cast_round_up(float x, double y) { - #pragma STDC FENV_ROUND FE_UPWARD - float res = x; - res += y; - return res; -} - -float V3 = add_cast_round_down(1.0F, 0x0.000001p0F); -float V4 = add_cast_round_up(1.0F, 0x0.000001p0F); - - -#endif diff --git a/clang/test/AST/Interp/floats.cpp b/clang/test/AST/Interp/floats.cpp deleted file mode 100644 index 9c9831c3f10a0..0000000000000 --- a/clang/test/AST/Interp/floats.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s -// RUN: %clang_cc1 -verify=ref %s - -constexpr int i = 2; -constexpr float f = 1.0f; -static_assert(f == 1.0f, ""); - -constexpr float f2 = 1u * f; -static_assert(f2 == 1.0f, ""); - -constexpr float f3 = 1.5; -constexpr int i3 = f3; -static_assert(i3 == 1); - -constexpr bool b3 = f3; -static_assert(b3); - - -static_assert(1.0f + 3u == 4, ""); -static_assert(4.0f / 1.0f == 4, ""); -static_assert(10.0f * false == 0, ""); - -constexpr float floats[] = {1.0f, 2.0f, 3.0f, 4.0f}; - -constexpr float m = 5.0f / 0.0f; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{division by zero}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{division by zero}} - -static_assert(~2.0f == 3, ""); // ref-error {{invalid argument type 'float' to unary expression}} \ - // expected-error {{invalid argument type 'float' to unary expression}} - -/// Initialized by a double. -constexpr float df = 0.0; -/// The other way around. -constexpr double fd = 0.0f; - -static_assert(0.0f == -0.0f, ""); - -const int k = 3 * (1.0f / 3.0f); -static_assert(k == 1, ""); - -constexpr bool b = 1.0; -static_assert(b, ""); - -constexpr double db = true; -static_assert(db == 1.0, ""); - -constexpr float fa[] = {1.0f, 2.0, 1, false}; -constexpr double da[] = {1.0f, 2.0, 1, false}; - -constexpr float fm = __FLT_MAX__; -constexpr int someInt = fm; // ref-error {{must be initialized by a constant expression}} \ - // ref-note {{is outside the range of representable values}} \ - // expected-error {{must be initialized by a constant expression}} \ - // expected-note {{is outside the range of representable values}} diff --git a/clang/test/SemaCXX/rounding-math.cpp b/clang/test/SemaCXX/rounding-math.cpp index 73f9f10e6d594..867534e6a20da 100644 --- a/clang/test/SemaCXX/rounding-math.cpp +++ b/clang/test/SemaCXX/rounding-math.cpp @@ -1,6 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-linux -verify=norounding -Wno-unknown-pragmas %s // RUN: %clang_cc1 -triple x86_64-linux -verify=rounding %s -frounding-math -Wno-unknown-pragmas -// RUN: %clang_cc1 -triple x86_64-linux -verify=rounding %s -frounding-math -fexperimental-new-constant-interpreter -Wno-unknown-pragmas // rounding-no-diagnostics #define fold(x) (__builtin_constant_p(x) ? (x) : (x)) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits