tbaeder updated this revision to Diff 471814.
tbaeder added a comment.

Moved the tests to their own file and moved the `isConstantContext()` changes 
to `InterpState` to their own NFC commit.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D134859/new/

https://reviews.llvm.org/D134859

Files:
  clang/lib/AST/CMakeLists.txt
  clang/lib/AST/Interp/Boolean.h
  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/Integral.h
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpStack.h
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/PrimType.h
  clang/test/SemaCXX/rounding-math.cpp

Index: clang/test/SemaCXX/rounding-math.cpp
===================================================================
--- clang/test/SemaCXX/rounding-math.cpp
+++ clang/test/SemaCXX/rounding-math.cpp
@@ -1,5 +1,6 @@
 // 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))
Index: clang/lib/AST/Interp/PrimType.h
===================================================================
--- clang/lib/AST/Interp/PrimType.h
+++ clang/lib/AST/Interp/PrimType.h
@@ -13,11 +13,12 @@
 #ifndef LLVM_CLANG_AST_INTERP_TYPE_H
 #define LLVM_CLANG_AST_INTERP_TYPE_H
 
+#include "Boolean.h"
+#include "Floating.h"
+#include "Integral.h"
 #include <climits>
 #include <cstddef>
 #include <cstdint>
-#include "Boolean.h"
-#include "Integral.h"
 
 namespace clang {
 namespace interp {
@@ -35,6 +36,7 @@
   PT_Sint64,
   PT_Uint64,
   PT_Bool,
+  PT_Float,
   PT_Ptr,
 };
 
@@ -48,6 +50,7 @@
 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; };
 
@@ -70,6 +73,7 @@
   case PT_Uint32:
   case PT_Sint64:
   case PT_Uint64:
+  case PT_Float:
     return true;
   default:
     return false;
@@ -94,6 +98,7 @@
       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)                                              \
     }                                                                          \
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -25,6 +25,7 @@
 def Uint32 : Type;
 def Sint64 : Type;
 def Uint64 : Type;
+def Float : Type;
 def Ptr : Type;
 
 //===----------------------------------------------------------------------===//
@@ -40,12 +41,15 @@
 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 ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; }
+def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; }
+def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; }
 
 //===----------------------------------------------------------------------===//
 // Classes of types instructions operate on.
@@ -55,18 +59,21 @@
   list<Type> Types;
 }
 
-def NumberTypeClass : TypeClass {
+def IntegerTypeClass : TypeClass {
   let Types = [Sint8, Uint8, Sint16, Uint16, Sint32,
                Uint32, Sint64, Uint64];
 }
 
-def IntegerTypeClass : 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 AluTypeClass : TypeClass {
-  let Types = !listconcat(NumberTypeClass.Types, [Bool]);
+  let Types = !listconcat(IntegerTypeClass.Types, [Bool]);
 }
 
 def PtrTypeClass : TypeClass {
@@ -77,12 +84,16 @@
   let Types = [Bool];
 }
 
+def NonPtrTypeClass : TypeClass {
+  let Types = !listconcat(IntegerTypeClass.Types, [Bool], [Float]);
+}
+
 def AllTypeClass : TypeClass {
-  let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types);
+  let Types = !listconcat(AluTypeClass.Types, PtrTypeClass.Types, FloatTypeClass.Types);
 }
 
 def ComparableTypeClass : TypeClass {
-  let Types = !listconcat(AluTypeClass.Types, [Ptr]);
+  let Types = !listconcat(AluTypeClass.Types, [Ptr], [Float]);
 }
 
 class SingletonTypeClass<Type Ty> : TypeClass {
@@ -109,6 +120,11 @@
   let HasGroup = 1;
 }
 
+class FloatOpcode : Opcode {
+  let Types = [];
+  let Args = [ArgRoundingMode];
+}
+
 class IntegerOpcode : Opcode {
   let Types = [IntegerTypeClass];
   let HasGroup = 1;
@@ -194,6 +210,7 @@
 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]
@@ -406,13 +423,19 @@
 //===----------------------------------------------------------------------===//
 
 // [Real, Real] -> [Real]
-def Sub : AluOpcode;
-def Add : AluOpcode;
-def Mul : AluOpcode;
-def Rem : Opcode {
-  let Types = [NumberTypeClass];
-  let HasGroup = 1;
-}
+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 Shl : Opcode {
   let Types = [IntegerTypeClass, IntegerTypeClass];
@@ -424,14 +447,6 @@
   let HasGroup = 1;
 }
 
-def BitAnd : IntegerOpcode;
-def BitOr : IntegerOpcode;
-def Div : Opcode {
-  let Types = [NumberTypeClass];
-  let HasGroup = 1;
-}
-def BitXor : IntegerOpcode;
-
 //===----------------------------------------------------------------------===//
 // Unary operators.
 //===----------------------------------------------------------------------===//
@@ -449,20 +464,19 @@
 
 // [Real] -> [Real]
 def Neg: Opcode {
-  let Types = [AluTypeClass];
+  let Types = [NonPtrTypeClass];
   let HasGroup = 1;
 }
 
 // [Real] -> [Real]
 def Comp: Opcode {
-  let Types = [NumberTypeClass];
+  let Types = [IntegerTypeClass];
   let HasGroup = 1;
 }
 
 //===----------------------------------------------------------------------===//
-// Cast.
+// Cast, CastFP.
 //===----------------------------------------------------------------------===//
-// TODO: Expand this to handle casts between more types.
 
 def FromCastTypeClass : TypeClass {
   let Types = [Uint8, Sint8, Uint16, Sint16, Uint32, Sint32, Uint64, Sint64, Bool];
@@ -477,6 +491,25 @@
   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];
+  let HasGroup = 1;
+}
+
+// Cast a floating to an integer type
+def CastFloatingIntegral : Opcode {
+  let Types = [AluTypeClass];
+  let Args = [ArgRoundingMode];
+  let HasGroup = 1;
+}
+
 //===----------------------------------------------------------------------===//
 // Comparison opcodes.
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/InterpStack.h
===================================================================
--- clang/lib/AST/Interp/InterpStack.h
+++ clang/lib/AST/Interp/InterpStack.h
@@ -160,6 +160,8 @@
     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");
   }
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -94,6 +94,11 @@
 /// Checks that all fields are initialized after a constructor call.
 bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This);
 
+/// Checks if the result is a floating-point operation is valid
+/// in the current context.
+bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status,
+                      const Floating &Result);
+
 /// Checks if Div/Rem operation on LHS and RHS is valid.
 template <typename T>
 bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
@@ -164,6 +169,16 @@
   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, Result);
+}
+
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool Sub(InterpState &S, CodePtr OpPC) {
   const T &RHS = S.Stk.pop<T>();
@@ -172,6 +187,16 @@
   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, Result);
+}
+
 template <PrimType Name, class T = typename PrimConv<Name>::T>
 bool Mul(InterpState &S, CodePtr OpPC) {
   const T &RHS = S.Stk.pop<T>();
@@ -180,6 +205,15 @@
   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, Result);
+}
 /// 1) Pops the RHS from the stack.
 /// 2) Pops the LHS from the stack.
 /// 3) Pushes 'LHS & RHS' on the stack
@@ -271,6 +305,19 @@
   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, Result);
+}
+
 //===----------------------------------------------------------------------===//
 // Inv
 //===----------------------------------------------------------------------===//
@@ -1137,6 +1184,38 @@
   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) {
+  const T &From = S.Stk.pop<T>();
+  APSInt FromAP = From.toAPSInt();
+  Floating Result;
+
+  if (!Floating::fromIntegral(FromAP, *Sem, Result))
+    return false;
+
+  S.Stk.push<Floating>(Result);
+  return true;
+}
+
+template <PrimType Name, class T = typename PrimConv<Name>::T>
+bool CastFloatingIntegral(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
+  const Floating &F = S.Stk.pop<Floating>();
+  APSInt Result(std::max(8u, T::bitWidth()), T::isSigned());
+
+  if (!F.convertToInteger(RM, Result))
+    return false;
+
+  S.Stk.push<T>(T(Result));
+  return true;
+}
+
 //===----------------------------------------------------------------------===//
 // Zero, Nullptr
 //===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/Interp.cpp
===================================================================
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -479,6 +479,50 @@
   return CheckFieldsInitialized(S, OpPC, This, R);
 }
 
+bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status,
+                      const Floating &Result) {
+  // 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
Index: clang/lib/AST/Interp/Integral.h
===================================================================
--- clang/lib/AST/Interp/Integral.h
+++ clang/lib/AST/Interp/Integral.h
@@ -21,33 +21,14 @@
 #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
@@ -56,6 +37,16 @@
 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;
Index: clang/lib/AST/Interp/Descriptor.cpp
===================================================================
--- clang/lib/AST/Interp/Descriptor.cpp
+++ clang/lib/AST/Interp/Descriptor.cpp
@@ -167,6 +167,11 @@
 }
 
 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);
 }
 
Index: clang/lib/AST/Interp/Context.cpp
===================================================================
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -113,6 +113,9 @@
   if (T->isNullPtrType())
     return PT_Ptr;
 
+  if (T->isFloatingType())
+    return PT_Float;
+
   if (auto *AT = dyn_cast<AtomicType>(T))
     return classify(AT->getValueType());
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -62,6 +62,7 @@
   // 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);
@@ -257,6 +258,15 @@
     return T->getAsCXXRecordDecl();
   }
 
+  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;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -122,6 +122,41 @@
     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: {
+    Optional<PrimType> FromT = classify(SubExpr->getType());
+    if (!FromT)
+      return false;
+
+    if (!this->visit(SubExpr))
+      return false;
+
+    const auto *TargetSemantics =
+        &Ctx.getASTContext().getFloatTypeSemantics(CE->getType());
+    return this->emitCastIntegralFloating(*FromT, TargetSemantics, CE);
+  }
+
+  case CK_FloatingToBoolean:
+  case CK_FloatingToIntegral: {
+    llvm::RoundingMode RM = getRoundingMode(CE);
+    Optional<PrimType> ToT = classify(CE->getType());
+
+    if (!ToT)
+      return false;
+
+    if (!this->visit(SubExpr))
+      return false;
+
+    return this->emitCastFloatingIntegral(*ToT, RM, CE);
+  }
+
   case CK_ArrayToPointerDecay:
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
@@ -165,6 +200,14 @@
   return this->bail(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());
@@ -224,14 +267,22 @@
   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)
@@ -624,6 +675,8 @@
     return this->emitZeroUint64(E);
   case PT_Ptr:
     return this->emitNullPtr(E);
+  case PT_Float:
+    assert(false);
   }
   llvm_unreachable("unknown primitive type");
 }
@@ -788,6 +841,7 @@
   case PT_Bool:
     return this->emitConstBool(Value.getBoolValue(), E);
   case PT_Ptr:
+  case PT_Float:
     llvm_unreachable("Invalid integral type");
     break;
   }
Index: clang/lib/AST/Interp/Boolean.h
===================================================================
--- clang/lib/AST/Interp/Boolean.h
+++ clang/lib/AST/Interp/Boolean.h
@@ -33,6 +33,7 @@
  public:
   /// Zero-initializes a boolean.
   Boolean() : V(false) {}
+  Boolean(const APSInt I) : V(!I.isZero()) {}
 
   bool operator<(Boolean RHS) const { return V < RHS.V; }
   bool operator>(Boolean RHS) const { return V > RHS.V; }
Index: clang/lib/AST/CMakeLists.txt
===================================================================
--- clang/lib/AST/CMakeLists.txt
+++ clang/lib/AST/CMakeLists.txt
@@ -72,6 +72,7 @@
   Interp/EvalEmitter.cpp
   Interp/Frame.cpp
   Interp/Function.cpp
+  Interp/Floating.cpp
   Interp/Interp.cpp
   Interp/InterpBlock.cpp
   Interp/InterpFrame.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to