kpdev42 updated this revision to Diff 450244.
kpdev42 added a comment.

Update test case so it compares JIT’ed  and interpreted FP division results and 
also check operations on float type. Patch doesn’t implement long double, 
because IR interpreter currently doesn’t support instruction argument size of 
more than 64 bit which includes both fp128 and int128. This deserves a separate 
patch, I think


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D126359

Files:
  lldb/source/Expression/IRInterpreter.cpp
  lldb/test/API/lang/c/fpeval/Makefile
  lldb/test/API/lang/c/fpeval/TestFPEval.py
  lldb/test/API/lang/c/fpeval/main.c

Index: lldb/test/API/lang/c/fpeval/main.c
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/fpeval/main.c
@@ -0,0 +1,16 @@
+double eval(double a, double b, int op) {
+  switch (op) {
+  case 0: return a+b;
+  case 1: return a-b;
+  case 2: return a/b;
+  case 3: return a*b;
+  default: return 0;
+  }
+}
+
+int main (int argc, char const *argv[])
+{
+    double a = 42.0, b = 2.0;
+    float f = 42.0, q = 2.0;
+    return 0; //// Set break point at this line.
+}
Index: lldb/test/API/lang/c/fpeval/TestFPEval.py
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/fpeval/TestFPEval.py
@@ -0,0 +1,101 @@
+"""Tests IR interpreter handling of basic floating point operations (fadd, fsub, etc)."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+class FPEvalTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+        self.jit_opts = lldb.SBExpressionOptions()
+        self.jit_opts.SetAllowJIT(True)
+        self.no_jit_opts = lldb.SBExpressionOptions()
+        self.no_jit_opts.SetAllowJIT(False)
+        # Find the line number to break inside main().
+        self.line = line_number('main.c', '// Set break point at this line.')
+
+    def test(self):
+        """Test floating point expressions while jitter is disabled."""
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+
+        # Break inside the main.
+        lldbutil.run_break_set_by_file_and_line(
+            self, "main.c", self.line, num_expected_locations=1, loc_exact=True)
+
+        
+        value = self.frame().EvaluateExpression("a + b", self.no_jit_opts)
+
+        self.runCmd("run", RUN_SUCCEEDED)
+        # test double
+        self.expect("expr --allow-jit false  -- a + b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['double', '44'])
+        self.expect("expr --allow-jit false  -- a - b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['double', '40'])
+        self.expect("expr --allow-jit false  -- a / b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['double', '21'])
+        self.expect("expr --allow-jit false  -- a * b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['double', '84'])
+        self.expect("expr --allow-jit false  -- a + 2", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['double', '44'])
+        self.expect("expr --allow-jit false  -- a > b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['true'])
+        self.expect("expr --allow-jit false  -- a >= b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['true'])
+        self.expect("expr --allow-jit false  -- a < b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['false'])
+        self.expect("expr --allow-jit false  -- a <= b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['false'])
+        self.expect("expr --allow-jit false  -- a == b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['false'])
+        self.expect("expr --allow-jit false  -- a != b", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['true'])
+        
+        # test single
+        self.expect("expr --allow-jit false  -- f + q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['float', '44'])
+        self.expect("expr --allow-jit false  -- f - q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['float', '40'])
+        self.expect("expr --allow-jit false  -- f / q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['float', '21'])
+        self.expect("expr --allow-jit false  -- f * q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['float', '84'])
+        self.expect("expr --allow-jit false  -- f + 2", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['float', '44'])
+        self.expect("expr --allow-jit false  -- f > q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['true'])
+        self.expect("expr --allow-jit false  -- f >= q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['true'])
+        self.expect("expr --allow-jit false  -- f < q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['false'])
+        self.expect("expr --allow-jit false  -- f <= q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['false'])
+        self.expect("expr --allow-jit false  -- f == q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['false'])
+        self.expect("expr --allow-jit false  -- f != q", VARIABLES_DISPLAYED_CORRECTLY,
+                    substrs=['true'])
+
+        # compare jit and interpreter output
+        self.assertTrue(self.process().IsValid())
+        thread = lldbutil.get_stopped_thread(self.process(), lldb.eStopReasonBreakpoint)
+        self.assertTrue(thread.IsValid())
+        frame = thread.GetSelectedFrame()
+        self.assertTrue(frame.IsValid())
+       
+        dividents = [42, 79, 666]
+        divisors = [1.618, 2.718281828, 3.1415926535, 6.62607015]
+
+        for x in dividents:
+            for y in divisors:
+                vardef = "double x = {0}, y = {1};".format(x, y) 
+                v1 = frame.EvaluateExpression("{0}; eval(x, y, 2)".format(vardef), self.jit_opts)
+                v2 = frame.EvaluateExpression("{0}; x / y".format(vardef), self.no_jit_opts)
+                self.assertTrue(v1.IsValid() and v2.IsValid())
+                self.assertTrue(str(v1.GetData()) == str(v2.GetData()))
+
Index: lldb/test/API/lang/c/fpeval/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/lang/c/fpeval/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+
+include Makefile.rules
Index: lldb/source/Expression/IRInterpreter.cpp
===================================================================
--- lldb/source/Expression/IRInterpreter.cpp
+++ lldb/source/Expression/IRInterpreter.cpp
@@ -167,6 +167,18 @@
     const Constant *constant = dyn_cast<Constant>(value);
 
     if (constant) {
+      if (constant->getValueID() == Value::ConstantFPVal) {
+        if (auto *cfp = dyn_cast<ConstantFP>(constant)) {
+          if (cfp->getType()->isDoubleTy())
+            scalar = cfp->getValueAPF().convertToDouble();
+          else if (cfp->getType()->isFloatTy())
+            scalar = cfp->getValueAPF().convertToFloat();
+          else
+            return false;
+          return true;
+        }
+        return false;
+      }
       APInt value_apint;
 
       if (!ResolveConstantValue(value_apint, constant))
@@ -189,9 +201,18 @@
 
     lldb::offset_t offset = 0;
     if (value_size <= 8) {
-      uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
-      return AssignToMatchType(scalar, llvm::APInt(64, u64value),
-                               value->getType());
+      Type *ty = value->getType();
+      if (ty->isDoubleTy()) {
+        scalar = value_extractor.GetDouble(&offset);
+        return true;
+      } else if (ty->isFloatTy()) {
+        scalar = value_extractor.GetFloat(&offset);
+        return true;
+      } else {
+        uint64_t u64value = value_extractor.GetMaxU64(&offset, value_size);
+        return AssignToMatchType(scalar, llvm::APInt(64, u64value),
+                                 value->getType());
+      }
     }
 
     return false;
@@ -205,11 +226,15 @@
       return false;
 
     lldb_private::Scalar cast_scalar;
-
-    scalar.MakeUnsigned();
-    if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
-                           value->getType()))
-      return false;
+    Type *vty = value->getType();
+    if (vty->isFloatTy() || vty->isDoubleTy()) {
+      cast_scalar = scalar;
+    } else {
+      scalar.MakeUnsigned();
+      if (!AssignToMatchType(cast_scalar, scalar.UInt128(llvm::APInt()),
+                             value->getType()))
+        return false;
+    }
 
     size_t value_byte_size = m_target_data.getTypeStoreSize(value->getType());
 
@@ -543,16 +568,17 @@
       } break;
       case Instruction::GetElementPtr:
         break;
+      case Instruction::FCmp:
       case Instruction::ICmp: {
-        ICmpInst *icmp_inst = dyn_cast<ICmpInst>(&ii);
+        CmpInst *cmp_inst = dyn_cast<CmpInst>(&ii);
 
-        if (!icmp_inst) {
+        if (!cmp_inst) {
           error.SetErrorToGenericError();
           error.SetErrorString(interpreter_internal_error);
           return false;
         }
 
-        switch (icmp_inst->getPredicate()) {
+        switch (cmp_inst->getPredicate()) {
         default: {
           LLDB_LOGF(log, "Unsupported ICmp predicate: %s",
                     PrintValue(&ii).c_str());
@@ -561,11 +587,17 @@
           error.SetErrorString(unsupported_opcode_error);
           return false;
         }
+        case CmpInst::FCMP_OEQ:
         case CmpInst::ICMP_EQ:
+        case CmpInst::FCMP_UNE:
         case CmpInst::ICMP_NE:
+        case CmpInst::FCMP_OGT:
         case CmpInst::ICMP_UGT:
+        case CmpInst::FCMP_OGE:
         case CmpInst::ICMP_UGE:
+        case CmpInst::FCMP_OLT:
         case CmpInst::ICMP_ULT:
+        case CmpInst::FCMP_OLE:
         case CmpInst::ICMP_ULE:
         case CmpInst::ICMP_SGT:
         case CmpInst::ICMP_SGE:
@@ -595,6 +627,11 @@
       case Instruction::Xor:
       case Instruction::ZExt:
         break;
+      case Instruction::FAdd:
+      case Instruction::FSub:
+      case Instruction::FMul:
+      case Instruction::FDiv:
+        break;
       }
 
       for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
@@ -709,7 +746,11 @@
     case Instruction::AShr:
     case Instruction::And:
     case Instruction::Or:
-    case Instruction::Xor: {
+    case Instruction::Xor:
+    case Instruction::FAdd:
+    case Instruction::FSub:
+    case Instruction::FMul:
+    case Instruction::FDiv: {
       const BinaryOperator *bin_op = dyn_cast<BinaryOperator>(inst);
 
       if (!bin_op) {
@@ -748,12 +789,15 @@
       default:
         break;
       case Instruction::Add:
+      case Instruction::FAdd:
         result = L + R;
         break;
       case Instruction::Mul:
+      case Instruction::FMul:
         result = L * R;
         break;
       case Instruction::Sub:
+      case Instruction::FSub:
         result = L - R;
         break;
       case Instruction::SDiv:
@@ -766,6 +810,9 @@
         R.MakeUnsigned();
         result = L / R;
         break;
+      case Instruction::FDiv:
+        result = L / R;
+        break;
       case Instruction::SRem:
         L.MakeSigned();
         R.MakeSigned();
@@ -1028,8 +1075,9 @@
         LLDB_LOGF(log, "  Poffset : %s", frame.SummarizeValue(inst).c_str());
       }
     } break;
+    case Instruction::FCmp:
     case Instruction::ICmp: {
-      const ICmpInst *icmp_inst = cast<ICmpInst>(inst);
+      const CmpInst *icmp_inst = cast<CmpInst>(inst);
 
       CmpInst::Predicate predicate = icmp_inst->getPredicate();
 
@@ -1059,9 +1107,11 @@
       default:
         return false;
       case CmpInst::ICMP_EQ:
+      case CmpInst::FCMP_OEQ:
         result = (L == R);
         break;
       case CmpInst::ICMP_NE:
+      case CmpInst::FCMP_UNE:
         result = (L != R);
         break;
       case CmpInst::ICMP_UGT:
@@ -1074,16 +1124,28 @@
         R.MakeUnsigned();
         result = (L >= R);
         break;
+      case CmpInst::FCMP_OGE:
+        result = (L >= R);
+        break;
+      case CmpInst::FCMP_OGT:
+        result = (L > R);
+        break;
       case CmpInst::ICMP_ULT:
         L.MakeUnsigned();
         R.MakeUnsigned();
         result = (L < R);
         break;
+      case CmpInst::FCMP_OLT:
+        result = (L < R);
+        break;
       case CmpInst::ICMP_ULE:
         L.MakeUnsigned();
         R.MakeUnsigned();
         result = (L <= R);
         break;
+      case CmpInst::FCMP_OLE:
+        result = (L <= R);
+        break;
       case CmpInst::ICMP_SGT:
         L.MakeSigned();
         R.MakeSigned();
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to