xref: /llvm-project/lldb/test/API/commands/expression/ir-interpreter/TestIRInterpreter.py (revision 7822e5dbf1cb4be2d73eb13da27b04de684c318b)
199451b44SJordan Rupprecht"""
299451b44SJordan RupprechtTest the IR interpreter
399451b44SJordan Rupprecht"""
499451b44SJordan Rupprecht
599451b44SJordan Rupprecht
699451b44SJordan Rupprechtimport lldb
799451b44SJordan Rupprechtfrom lldbsuite.test.decorators import *
899451b44SJordan Rupprechtfrom lldbsuite.test.lldbtest import *
999451b44SJordan Rupprechtfrom lldbsuite.test import lldbutil
1099451b44SJordan Rupprecht
1199451b44SJordan Rupprecht
1299451b44SJordan Rupprechtclass IRInterpreterTestCase(TestBase):
1399451b44SJordan Rupprecht    NO_DEBUG_INFO_TESTCASE = True
1499451b44SJordan Rupprecht
1559237bb5SJonas Devlieghere    def time_expression(self, expr, options):
1659237bb5SJonas Devlieghere        start = time.time()
1759237bb5SJonas Devlieghere        res = self.target.EvaluateExpression(expr, options)
1859237bb5SJonas Devlieghere        return res, time.time() - start
1959237bb5SJonas Devlieghere
2059237bb5SJonas Devlieghere    def test_interpreter_timeout(self):
2159237bb5SJonas Devlieghere        """Test the timeout logic in the IRInterpreter."""
2259237bb5SJonas Devlieghere        self.build()
2359237bb5SJonas Devlieghere        self.target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
2459237bb5SJonas Devlieghere        self.assertTrue(self.target, VALID_TARGET)
2559237bb5SJonas Devlieghere
2659237bb5SJonas Devlieghere        # A non-trivial infinite loop.
2759237bb5SJonas Devlieghere        inf_loop = "for (unsigned i = 0; i < 100; ++i) --i; 1"
2859237bb5SJonas Devlieghere        timeout_error = "Reached timeout while interpreting expression"
2959237bb5SJonas Devlieghere        options = lldb.SBExpressionOptions()
3059237bb5SJonas Devlieghere
3159237bb5SJonas Devlieghere        # This is an IRInterpreter specific test, so disable the JIT.
3259237bb5SJonas Devlieghere        options.SetAllowJIT(False)
3359237bb5SJonas Devlieghere
34*7822e5dbSwalter erquinigo        # We use a 500ms timeout.
35*7822e5dbSwalter erquinigo        options.SetTimeoutInMicroSeconds(500000)
3659237bb5SJonas Devlieghere        res, duration_sec = self.time_expression(inf_loop, options)
3759237bb5SJonas Devlieghere        self.assertIn(timeout_error, str(res.GetError()))
3859237bb5SJonas Devlieghere
3959237bb5SJonas Devlieghere        # Depending on the machine load the expression might take quite some
4059237bb5SJonas Devlieghere        # time, so give the time a generous upper bound.
4159237bb5SJonas Devlieghere        self.assertLess(duration_sec, 15)
4259237bb5SJonas Devlieghere
4359237bb5SJonas Devlieghere        # Try a simple one second timeout.
4459237bb5SJonas Devlieghere        options.SetTimeoutInMicroSeconds(1000000)
4559237bb5SJonas Devlieghere        res, duration_sec = self.time_expression(inf_loop, options)
4659237bb5SJonas Devlieghere        self.assertIn(timeout_error, str(res.GetError()))
4791a0e832SDavid Spickett        # Anything within 5% of 1s is fine, to account for machine differences.
4891a0e832SDavid Spickett        self.assertGreaterEqual(duration_sec, 0.95)
4959237bb5SJonas Devlieghere        self.assertLess(duration_sec, 30)
5059237bb5SJonas Devlieghere
5161af957aSJonas Devlieghere    def test_interpreter_interrupt(self):
5261af957aSJonas Devlieghere        """Test interrupting the IRInterpreter."""
5361af957aSJonas Devlieghere        self.build()
5461af957aSJonas Devlieghere        self.target = self.dbg.CreateTarget(self.getBuildArtifact("a.out"))
5561af957aSJonas Devlieghere        self.assertTrue(self.target, VALID_TARGET)
5661af957aSJonas Devlieghere
5761af957aSJonas Devlieghere        # A non-trivial infinite loop.
5861af957aSJonas Devlieghere        inf_loop = "for (unsigned i = 0; i < 100; ++i) --i; 1"
5961af957aSJonas Devlieghere
6061af957aSJonas Devlieghere        options = lldb.SBExpressionOptions()
6161af957aSJonas Devlieghere
6261af957aSJonas Devlieghere        # This is an IRInterpreter specific test, so disable the JIT.
6361af957aSJonas Devlieghere        options.SetAllowJIT(False)
6461af957aSJonas Devlieghere
6561af957aSJonas Devlieghere        # Make sure we have a pretty long (10s) timeout so we have a chance to
6661af957aSJonas Devlieghere        # interrupt the interpreted expression.
6761af957aSJonas Devlieghere        options.SetTimeoutInMicroSeconds(10000000)
6861af957aSJonas Devlieghere
6961af957aSJonas Devlieghere        self.dbg.RequestInterrupt()
7061af957aSJonas Devlieghere
7161af957aSJonas Devlieghere        self.dbg.SetAsync(True)
7261af957aSJonas Devlieghere        res = self.target.EvaluateExpression(inf_loop, options)
7361af957aSJonas Devlieghere        self.dbg.SetAsync(False)
7461af957aSJonas Devlieghere
7561af957aSJonas Devlieghere        # Be sure to turn this off again:
7661af957aSJonas Devlieghere        def cleanup():
7761af957aSJonas Devlieghere            if self.dbg.InterruptRequested():
7861af957aSJonas Devlieghere                self.dbg.CancelInterruptRequest()
7961af957aSJonas Devlieghere
8061af957aSJonas Devlieghere        self.addTearDownHook(cleanup)
8161af957aSJonas Devlieghere
8261af957aSJonas Devlieghere        interrupt_error = "Interrupted while interpreting expression"
8361af957aSJonas Devlieghere        self.assertIn(interrupt_error, str(res.GetError()))
8461af957aSJonas Devlieghere
8599451b44SJordan Rupprecht    def setUp(self):
8699451b44SJordan Rupprecht        # Call super's setUp().
8799451b44SJordan Rupprecht        TestBase.setUp(self)
8899451b44SJordan Rupprecht        # Find the line number to break for main.c.
892238dcc3SJonas Devlieghere        self.line = line_number("main.c", "// Set breakpoint here")
9099451b44SJordan Rupprecht
9199451b44SJordan Rupprecht        # Disable confirmation prompt to avoid infinite wait
9299451b44SJordan Rupprecht        self.runCmd("settings set auto-confirm true")
932238dcc3SJonas Devlieghere        self.addTearDownHook(lambda: self.runCmd("settings clear auto-confirm"))
9499451b44SJordan Rupprecht
9599451b44SJordan Rupprecht    def build_and_run(self):
9699451b44SJordan Rupprecht        """Test the IR interpreter"""
9799451b44SJordan Rupprecht        self.build()
9899451b44SJordan Rupprecht
9999451b44SJordan Rupprecht        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
10099451b44SJordan Rupprecht
10199451b44SJordan Rupprecht        lldbutil.run_break_set_by_file_and_line(
1022238dcc3SJonas Devlieghere            self, "main.c", self.line, num_expected_locations=1, loc_exact=False
1032238dcc3SJonas Devlieghere        )
10499451b44SJordan Rupprecht
10599451b44SJordan Rupprecht        self.runCmd("run", RUN_SUCCEEDED)
10699451b44SJordan Rupprecht
1072238dcc3SJonas Devlieghere    @add_test_categories(["pyapi"])
10899451b44SJordan Rupprecht    # getpid() is POSIX, among other problems, see bug
1092238dcc3SJonas Devlieghere    @expectedFailureAll(oslist=["windows"], bugnumber="http://llvm.org/pr21765")
11099451b44SJordan Rupprecht    def test_ir_interpreter(self):
11199451b44SJordan Rupprecht        self.build_and_run()
11299451b44SJordan Rupprecht
11399451b44SJordan Rupprecht        options = lldb.SBExpressionOptions()
11499451b44SJordan Rupprecht        options.SetLanguage(lldb.eLanguageTypeC_plus_plus)
11599451b44SJordan Rupprecht
1162238dcc3SJonas Devlieghere        set_up_expressions = [
1172238dcc3SJonas Devlieghere            "int $i = 9",
1182238dcc3SJonas Devlieghere            "int $j = 3",
1192238dcc3SJonas Devlieghere            "int $k = 5",
1202238dcc3SJonas Devlieghere            "unsigned long long $ull = -1",
1212238dcc3SJonas Devlieghere            "unsigned $u = -1",
1222238dcc3SJonas Devlieghere        ]
12399451b44SJordan Rupprecht
1242238dcc3SJonas Devlieghere        expressions = [
1252238dcc3SJonas Devlieghere            "$i + $j",
12699451b44SJordan Rupprecht            "$i - $j",
12799451b44SJordan Rupprecht            "$i * $j",
12899451b44SJordan Rupprecht            "$i / $j",
12999451b44SJordan Rupprecht            "$i % $k",
13099451b44SJordan Rupprecht            "$i << $j",
13199451b44SJordan Rupprecht            "$i & $j",
13299451b44SJordan Rupprecht            "$i | $j",
133b725142cSPavel Labath            "$i ^ $j",
1342238dcc3SJonas Devlieghere            "($ull & -1) == $u",
1352238dcc3SJonas Devlieghere        ]
13699451b44SJordan Rupprecht
13799451b44SJordan Rupprecht        for expression in set_up_expressions:
13899451b44SJordan Rupprecht            self.frame().EvaluateExpression(expression, options)
13999451b44SJordan Rupprecht
14099451b44SJordan Rupprecht        for expression in expressions:
14199451b44SJordan Rupprecht            interp_expression = expression
14299451b44SJordan Rupprecht            jit_expression = "(int)getpid(); " + expression
14399451b44SJordan Rupprecht
1442238dcc3SJonas Devlieghere            interp_result = (
1452238dcc3SJonas Devlieghere                self.frame()
1462238dcc3SJonas Devlieghere                .EvaluateExpression(interp_expression, options)
1472238dcc3SJonas Devlieghere                .GetValueAsSigned()
1482238dcc3SJonas Devlieghere            )
1492238dcc3SJonas Devlieghere            jit_result = (
1502238dcc3SJonas Devlieghere                self.frame()
1512238dcc3SJonas Devlieghere                .EvaluateExpression(jit_expression, options)
1522238dcc3SJonas Devlieghere                .GetValueAsSigned()
1532238dcc3SJonas Devlieghere            )
15499451b44SJordan Rupprecht
15599451b44SJordan Rupprecht            self.assertEqual(
1562238dcc3SJonas Devlieghere                interp_result, jit_result, "While evaluating " + expression
1572238dcc3SJonas Devlieghere            )
15899451b44SJordan Rupprecht
15999451b44SJordan Rupprecht    def test_type_conversions(self):
16099451b44SJordan Rupprecht        target = self.dbg.GetDummyTarget()
16199451b44SJordan Rupprecht        short_val = target.EvaluateExpression("(short)-1")
16299451b44SJordan Rupprecht        self.assertEqual(short_val.GetValueAsSigned(), -1)
16399451b44SJordan Rupprecht        long_val = target.EvaluateExpression("(long) " + short_val.GetName())
16499451b44SJordan Rupprecht        self.assertEqual(long_val.GetValueAsSigned(), -1)
165