https://github.com/igorkudrin updated 
https://github.com/llvm/llvm-project/pull/175292

>From ba9318db283858884e395ec2329ef2f8891370b4 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <[email protected]>
Date: Thu, 8 Jan 2026 22:53:38 -0800
Subject: [PATCH 1/4] [lldb] Add FP conversion instructions to IR interpreter

This allows expressions that use these conversions to be executed when
JIT is not available.
---
 lldb/source/Expression/IRInterpreter.cpp      | 73 +++++++++++++++++++
 .../ir-interpreter/TestIRInterpreter.py       | 70 ++++++++++++++++++
 2 files changed, 143 insertions(+)

diff --git a/lldb/source/Expression/IRInterpreter.cpp 
b/lldb/source/Expression/IRInterpreter.cpp
index 91404831aeb9b..3c43646f51eff 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -611,6 +611,8 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, 
llvm::Function &function,
       } break;
       case Instruction::And:
       case Instruction::AShr:
+      case Instruction::FPToUI:
+      case Instruction::FPToSI:
       case Instruction::IntToPtr:
       case Instruction::PtrToInt:
       case Instruction::Load:
@@ -635,6 +637,18 @@ bool IRInterpreter::CanInterpret(llvm::Module &module, 
llvm::Function &function,
       case Instruction::FMul:
       case Instruction::FDiv:
         break;
+      case Instruction::UIToFP:
+      case Instruction::SIToFP:
+      case Instruction::FPTrunc:
+      case Instruction::FPExt:
+        if (!ii.getType()->isFloatTy() && !ii.getType()->isDoubleTy()) {
+          LLDB_LOGF(log, "Unsupported instruction: %s",
+                    PrintValue(&ii).c_str());
+          error =
+              lldb_private::Status::FromErrorString(unsupported_opcode_error);
+          return false;
+        }
+        break;
       }
 
       for (unsigned oi = 0, oe = ii.getNumOperands(); oi != oe; ++oi) {
@@ -1256,6 +1270,65 @@ bool IRInterpreter::Interpret(llvm::Module &module, 
llvm::Function &function,
         LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
       }
     } break;
+    case Instruction::FPToUI:
+    case Instruction::FPToSI: {
+      Value *src_operand = inst->getOperand(0);
+
+      lldb_private::Scalar S;
+      if (!frame.EvaluateValue(S, src_operand, module)) {
+        LLDB_LOGF(log, "Couldn't evaluate %s", 
PrintValue(src_operand).c_str());
+        error = lldb_private::Status::FromErrorString(bad_value_error);
+        return false;
+      }
+
+      assert(inst->getType()->isIntegerTy() && "Unexpected target type");
+      llvm::APSInt result(inst->getType()->getIntegerBitWidth(),
+                          /*isUnsigned=*/inst->getOpcode() ==
+                              Instruction::FPToUI);
+      assert(S.GetType() == lldb_private::Scalar::e_float &&
+             "Unexpected source type");
+      bool isExact;
+      S.GetAPFloat().convertToInteger(result, llvm::APFloat::rmTowardZero,
+                                      &isExact);
+      lldb_private::Scalar R(result);
+
+      frame.AssignValue(inst, R, module);
+      if (log) {
+        LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
+        LLDB_LOGF(log, "  Src : %s", 
frame.SummarizeValue(src_operand).c_str());
+        LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
+      }
+    } break;
+    case Instruction::UIToFP:
+    case Instruction::SIToFP:
+    case Instruction::FPTrunc:
+    case Instruction::FPExt: {
+      Value *src_operand = inst->getOperand(0);
+
+      lldb_private::Scalar S;
+      if (!frame.EvaluateValue(S, src_operand, module)) {
+        LLDB_LOGF(log, "Couldn't evaluate %s", 
PrintValue(src_operand).c_str());
+        error = lldb_private::Status::FromErrorString(bad_value_error);
+        return false;
+      }
+      lldb_private::Scalar R;
+
+      Type *result_type = inst->getType();
+      assert(
+          (result_type->isFloatTy() || result_type->isDoubleTy()) &&
+          "Unsupported result type; CanInterpret() should have checked that");
+      if (result_type->isFloatTy())
+        R = S.Float();
+      else
+        R = S.Double();
+
+      frame.AssignValue(inst, R, module);
+      if (log) {
+        LLDB_LOGF(log, "Interpreted a %s", inst->getOpcodeName());
+        LLDB_LOGF(log, "  Src : %s", 
frame.SummarizeValue(src_operand).c_str());
+        LLDB_LOGF(log, "  =   : %s", frame.SummarizeValue(inst).c_str());
+      }
+    } break;
     case Instruction::Load: {
       const LoadInst *load_inst = cast<LoadInst>(inst);
 
diff --git 
a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py 
b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
index 23188ef898d56..26be9ab952db7 100644
--- a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
+++ b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
@@ -172,3 +172,73 @@ def test_type_conversions(self):
         self.assertEqual(short_val.GetValueAsSigned(), -1)
         long_val = target.EvaluateExpression("(long) " + short_val.GetName())
         self.assertEqual(long_val.GetValueAsSigned(), -1)
+
+    def test_fpconv(self):
+        self.build_and_run()
+
+        interp_options = lldb.SBExpressionOptions()
+        interp_options.SetLanguage(lldb.eLanguageTypeC_plus_plus)
+        interp_options.SetAllowJIT(False)
+
+        jit_options = lldb.SBExpressionOptions()
+        jit_options.SetLanguage(lldb.eLanguageTypeC_plus_plus)
+        jit_options.SetAllowJIT(True)
+
+        set_up_expressions = [
+            "int $i = 3",
+            "int $n = -3",
+            "unsigned $u = 5",
+            "long $l = -7",
+            "float $f = 9.0625",
+            "double $d = 13.75",
+            "float $nf = -11.25",
+        ]
+
+        expressions = [
+            "$i + $f",
+            "$d - $n",
+            "$u + $f",
+            "$u + $d",
+            "(int)$d",
+            "(int)$f",
+            "(long)$d",
+            "(short)$f",
+            "(long)$nf",
+            "(unsigned short)$f",
+            "(unsigned)$d",
+            "(unsigned long)$d",
+            "(float)$d",
+            "(double)$f",
+            "(double)$nf",
+        ]
+
+        for expression in set_up_expressions:
+            self.frame().EvaluateExpression(expression, interp_options)
+
+        func_call = "(int)getpid()"
+        if lldbplatformutil.getPlatform() == "windows":
+            func_call = "(int)GetCurrentProcessId()"
+
+        for expression in expressions:
+            interp_expression = expression
+            jit_expression = func_call + "; " + expression
+
+            interp_result = (
+                self.frame()
+                .EvaluateExpression(interp_expression, interp_options)
+            )
+            jit_result = (
+                self.frame()
+                .EvaluateExpression(jit_expression, jit_options)
+            )
+
+            self.assertEqual(
+                interp_result.GetValue(),
+                jit_result.GetValue(),
+                "Values match for " + expression,
+            )
+            self.assertEqual(
+                interp_result.GetTypeName(),
+                jit_result.GetTypeName(),
+                "Types match for " + expression,
+            )

>From 61d9e3cf6757f853dabb1a7c6a72bb7b656ce325 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <[email protected]>
Date: Fri, 9 Jan 2026 22:43:53 -0800
Subject: [PATCH 2/4] fixup! formatting

---
 .../expression/ir-interpreter/TestIRInterpreter.py     | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git 
a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py 
b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
index 26be9ab952db7..3ce15d801818c 100644
--- a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
+++ b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
@@ -223,14 +223,10 @@ def test_fpconv(self):
             interp_expression = expression
             jit_expression = func_call + "; " + expression
 
-            interp_result = (
-                self.frame()
-                .EvaluateExpression(interp_expression, interp_options)
-            )
-            jit_result = (
-                self.frame()
-                .EvaluateExpression(jit_expression, jit_options)
+            interp_result = self.frame().EvaluateExpression(
+                interp_expression, interp_options
             )
+            jit_result = self.frame().EvaluateExpression(jit_expression, 
jit_options)
 
             self.assertEqual(
                 interp_result.GetValue(),

>From a3df8184cd2f364a463a0301ba64e61f897f542d Mon Sep 17 00:00:00 2001
From: Igor Kudrin <[email protected]>
Date: Mon, 12 Jan 2026 18:26:59 -0800
Subject: [PATCH 3/4] fixup! add comments to test expressions

---
 .../ir-interpreter/TestIRInterpreter.py       | 30 +++++++++----------
 1 file changed, 15 insertions(+), 15 deletions(-)

diff --git 
a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py 
b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
index 3ce15d801818c..2163d045ef872 100644
--- a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
+++ b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
@@ -195,21 +195,21 @@ def test_fpconv(self):
         ]
 
         expressions = [
-            "$i + $f",
-            "$d - $n",
-            "$u + $f",
-            "$u + $d",
-            "(int)$d",
-            "(int)$f",
-            "(long)$d",
-            "(short)$f",
-            "(long)$nf",
-            "(unsigned short)$f",
-            "(unsigned)$d",
-            "(unsigned long)$d",
-            "(float)$d",
-            "(double)$f",
-            "(double)$nf",
+            "$i + $f",  # sitofp i32 to float
+            "$d - $n",  # sitofp i32 to double
+            "$u + $f",  # uitofp i32 to float
+            "$u + $d",  # uitofp i32 to double
+            "(int)$d",  # fptosi double to i32
+            "(int)$f",  # fptosi float to i32
+            "(long)$d",  # fptosi double to i64
+            "(short)$f",  # fptosi float to i16
+            "(long)$nf",  # fptosi float to i64
+            "(unsigned short)$f",  # fptoui float to i16
+            "(unsigned)$d",  # fptoui double to i32
+            "(unsigned long)$d",  # fptoui double to i64
+            "(float)$d",  # fptrunc double to float
+            "(double)$f",  # fpext float to double
+            "(double)$nf",  # fpext float to double
         ]
 
         for expression in set_up_expressions:

>From 8480377627a33ebfa671e8a5be411eb8dcca7d00 Mon Sep 17 00:00:00 2001
From: Igor Kudrin <[email protected]>
Date: Mon, 12 Jan 2026 18:34:40 -0800
Subject: [PATCH 4/4] fixup! reject invalid conversions

---
 lldb/source/Expression/IRInterpreter.cpp      | 21 +++++++++++--
 .../ir-interpreter/TestIRInterpreter.py       | 31 +++++++++++++++++++
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/lldb/source/Expression/IRInterpreter.cpp 
b/lldb/source/Expression/IRInterpreter.cpp
index 3c43646f51eff..f6365ac948f37 100644
--- a/lldb/source/Expression/IRInterpreter.cpp
+++ b/lldb/source/Expression/IRInterpreter.cpp
@@ -70,6 +70,13 @@ static std::string PrintType(const Type *type, bool truncate 
= false) {
   return s;
 }
 
+static std::string PrintScalar(const lldb_private::Scalar &value) {
+  std::string s;
+  raw_string_ostream rso(s);
+  rso << value;
+  return s;
+}
+
 static bool CanIgnoreCall(const CallInst *call) {
   const llvm::Function *called_function = call->getCalledFunction();
 
@@ -477,6 +484,8 @@ static const char *timeout_error =
     "Reached timeout while interpreting expression";
 static const char *too_many_functions_error =
     "Interpreter doesn't handle modules with multiple function bodies.";
+static const char *bad_conversion_error =
+    "Interpreter couldn't convert a value";
 
 static bool CanResolveConstant(llvm::Constant *constant) {
   switch (constant->getValueID()) {
@@ -1288,8 +1297,16 @@ bool IRInterpreter::Interpret(llvm::Module &module, 
llvm::Function &function,
       assert(S.GetType() == lldb_private::Scalar::e_float &&
              "Unexpected source type");
       bool isExact;
-      S.GetAPFloat().convertToInteger(result, llvm::APFloat::rmTowardZero,
-                                      &isExact);
+      llvm::APFloatBase::opStatus status = S.GetAPFloat().convertToInteger(
+          result, llvm::APFloat::rmTowardZero, &isExact);
+      // Casting floating point values that are out of bounds of the target 
type
+      // is undefined behaviour.
+      if (status & llvm::APFloatBase::opInvalidOp) {
+        LLDB_LOGF(log, "Couldn't convert %s to %s", PrintScalar(S).c_str(),
+                  PrintType(inst->getType()).c_str());
+        error = lldb_private::Status::FromErrorString(bad_conversion_error);
+        return false;
+      }
       lldb_private::Scalar R(result);
 
       frame.AssignValue(inst, R, module);
diff --git 
a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py 
b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
index 2163d045ef872..e86089178d50b 100644
--- a/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
+++ b/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py
@@ -238,3 +238,34 @@ def test_fpconv(self):
                 jit_result.GetTypeName(),
                 "Types match for " + expression,
             )
+
+    def test_fpconv_ub(self):
+        target = self.dbg.GetDummyTarget()
+
+        set_up_expressions = [
+            "float $f = 3e9",
+            "double $d = 1e20",
+            "float $nf = -1.5",
+        ]
+
+        expressions = [
+            "(int)$f",
+            "(long)$d",
+            "(unsigned)$nf",
+        ]
+
+        for expression in set_up_expressions:
+            target.EvaluateExpression(expression)
+
+        # The IR Interpreter returns an error if a value cannot be converted.
+        for expression in expressions:
+            result = target.EvaluateExpression(expression)
+            self.assertIn(
+                "Interpreter couldn't convert a value", str(result.GetError())
+            )
+
+        # The conversion should succeed if the destination type can represent 
the result.
+        self.expect_expr(
+            "(unsigned)$f", result_type="unsigned int", 
result_value="3000000000"
+        )
+        self.expect_expr("(int)$nf", result_type="int", result_value="-1")

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to