[Lldb-commits] [lldb] r269340 - [LLDB] Added support for PHI nodes to IR interpreter

Marianne Mailhot-Sarrasin via lldb-commits lldb-commits at lists.llvm.org
Thu May 12 13:00:54 PDT 2016


Author: mamai
Date: Thu May 12 15:00:53 2016
New Revision: 269340

URL: http://llvm.org/viewvc/llvm-project?rev=269340&view=rev
Log:
[LLDB] Added support for PHI nodes to IR interpreter

This allows expressions such as 'i == 1 || i == 2` to be executed using the IR interpreter, instead of relying on JIT code injection (which may not be available on some platforms).

Patch by cameron314

Differential Revision: http://reviews.llvm.org/D19124

Added:
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py
    lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp
Modified:
    lldb/trunk/source/Commands/CommandObjectExpression.cpp
    lldb/trunk/source/Commands/CommandObjectExpression.h
    lldb/trunk/source/Expression/IRInterpreter.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py?rev=269340&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py Thu May 12 15:00:53 2016
@@ -0,0 +1,40 @@
+"""
+Test PHI nodes work in the IR interpreter.
+"""
+
+import os, os.path
+
+import lldb
+from lldbsuite.test.lldbtest import *
+import lldbsuite.test.lldbutil as lldbutil
+
+class IRInterpreterPHINodesTestCase(TestBase):
+    mydir = TestBase.compute_mydir(__file__)
+
+    def test_phi_node_support(self):
+        """Test support for PHI nodes in the IR interpreter."""
+        
+        self.build()
+        exe = os.path.join(os.getcwd(), 'a.out')
+        self.runCmd('file ' + exe, CURRENT_EXECUTABLE_SET)
+        
+        # Break on the first assignment to i
+        line = line_number('main.cpp', 'i = 5')
+        lldbutil.run_break_set_by_file_and_line(self, 'main.cpp', line, num_expected_locations=1, loc_exact=True)
+        
+        self.runCmd('run', RUN_SUCCEEDED)
+        
+        # The stop reason of the thread should be breakpoint
+        self.expect('thread list', STOPPED_DUE_TO_BREAKPOINT,
+            substrs = ['stopped', 'stop reason = breakpoint'])
+        
+        self.runCmd('s')
+        
+        # The logical 'or' causes a PHI node to be generated. Execute without JIT
+        # to test that the interpreter can handle this
+        self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['true'])
+        
+        self.runCmd('s')
+        self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['false'])
+        self.runCmd('s')
+        self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['true'])

Added: lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp?rev=269340&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/ir-interpreter-phi-nodes/main.cpp Thu May 12 15:00:53 2016
@@ -0,0 +1,17 @@
+//===-- main.cpp ------------------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+int main()
+{
+    int i;
+    i = 5;
+    i = 2;
+    i = 3;
+    return 0;
+}

Modified: lldb/trunk/source/Commands/CommandObjectExpression.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.cpp?rev=269340&r1=269339&r2=269340&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.cpp Thu May 12 15:00:53 2016
@@ -63,7 +63,8 @@ CommandObjectExpression::CommandOptions:
     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language",           'l', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage,   "Specifies the Language to use when parsing the expression.  If not set the target.language setting is used." },
     { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits",       'X', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeLanguage,   "If true, simple FixIt hints will be automatically applied to the expression." },
     { LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, g_description_verbosity_type, 0, eArgTypeDescriptionVerbosity,        "How verbose should the output of this expression be, if the object description is asked for."},
-    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level",          'p', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone,       "Interpret the expression as top-level definitions rather than code to be immediately executed."}
+    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level",          'p', OptionParser::eNoArgument      , NULL, NULL, 0, eArgTypeNone,       "Interpret the expression as top-level definitions rather than code to be immediately executed."},
+    { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit",          'j', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeBoolean,    "Controls whether the expression can fall back to being JITted if it's not supported by the interpreter (defaults to true)."}
 };
 
 uint32_t
@@ -111,6 +112,18 @@ CommandObjectExpression::CommandOptions:
                 error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
             break;
         }
+
+    case 'j':
+        {
+            bool success;
+            bool tmp_value = Args::StringToBoolean(option_arg, true, &success);
+            if (success)
+                allow_jit = tmp_value;
+            else
+                error.SetErrorStringWithFormat("could not convert \"%s\" to a boolean value.", option_arg);
+            break;
+        }
+
     case 't':
         {
             bool success;
@@ -197,6 +210,7 @@ CommandObjectExpression::CommandOptions:
     m_verbosity = eLanguageRuntimeDescriptionDisplayVerbosityCompact;
     auto_apply_fixits = eLazyBoolCalculate;
     top_level = false;
+    allow_jit = true;
 }
 
 const OptionDefinition*
@@ -325,6 +339,9 @@ CommandObjectExpression::EvaluateExpress
         options.SetTryAllThreads(m_command_options.try_all_threads);
         options.SetDebug(m_command_options.debug);
         options.SetLanguage(m_command_options.language);
+        options.SetExecutionPolicy(m_command_options.allow_jit ?
+            EvaluateExpressionOptions::default_execution_policy :
+            lldb_private::eExecutionPolicyNever);
         
         bool auto_apply_fixits;
         if (m_command_options.auto_apply_fixits == eLazyBoolCalculate)

Modified: lldb/trunk/source/Commands/CommandObjectExpression.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectExpression.h?rev=269340&r1=269339&r2=269340&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectExpression.h (original)
+++ lldb/trunk/source/Commands/CommandObjectExpression.h Thu May 12 15:00:53 2016
@@ -57,6 +57,7 @@ public:
         bool        top_level;
         bool        unwind_on_error;
         bool        ignore_breakpoints;
+        bool        allow_jit;
         bool        show_types;
         bool        show_summary;
         bool        debug;

Modified: lldb/trunk/source/Expression/IRInterpreter.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/IRInterpreter.cpp?rev=269340&r1=269339&r2=269340&view=diff
==============================================================================
--- lldb/trunk/source/Expression/IRInterpreter.cpp (original)
+++ lldb/trunk/source/Expression/IRInterpreter.cpp Thu May 12 15:00:53 2016
@@ -106,6 +106,7 @@ public:
     DataLayout                             &m_target_data;
     lldb_private::IRExecutionUnit          &m_execution_unit;
     const BasicBlock                       *m_bb;
+    const BasicBlock                       *m_prev_bb;
     BasicBlock::const_iterator              m_ii;
     BasicBlock::const_iterator              m_ie;
 
@@ -121,7 +122,9 @@ public:
                            lldb::addr_t stack_frame_bottom,
                            lldb::addr_t stack_frame_top) :
         m_target_data (target_data),
-        m_execution_unit (execution_unit)
+        m_execution_unit (execution_unit),
+        m_bb (nullptr),
+        m_prev_bb (nullptr)
     {
         m_byte_order = (target_data.isLittleEndian() ? lldb::eByteOrderLittle : lldb::eByteOrderBig);
         m_addr_byte_size = (target_data.getPointerSize(0));
@@ -137,6 +140,7 @@ public:
 
     void Jump (const BasicBlock *bb)
     {
+        m_prev_bb = m_bb;
         m_bb = bb;
         m_ii = m_bb->begin();
         m_ie = m_bb->end();
@@ -569,6 +573,7 @@ IRInterpreter::CanInterpret (llvm::Modul
             case Instruction::Alloca:
             case Instruction::BitCast:
             case Instruction::Br:
+            case Instruction::PHI:
                 break;
             case Instruction::Call:
                 {
@@ -1063,6 +1068,46 @@ IRInterpreter::Interpret (llvm::Module &
                 }
             }
                 continue;
+            case Instruction::PHI:
+            {
+                const PHINode *phi_inst = dyn_cast<PHINode>(inst);
+
+                if (!phi_inst)
+                {
+                    if (log)
+                        log->Printf("getOpcode() returns PHI, but instruction is not a PHINode");
+                    error.SetErrorToGenericError();
+                    error.SetErrorString(interpreter_internal_error);
+                    return false;
+                }
+                if (!frame.m_prev_bb)
+                {
+                    if (log)
+                        log->Printf("Encountered PHI node without having jumped from another basic block");
+                    error.SetErrorToGenericError();
+                    error.SetErrorString(interpreter_internal_error);
+                    return false;
+                }
+
+                Value* value = phi_inst->getIncomingValueForBlock(frame.m_prev_bb);
+                lldb_private::Scalar result;
+                if (!frame.EvaluateValue(result, value, module))
+                {
+                    if (log)
+                        log->Printf("Couldn't evaluate %s", PrintValue(value).c_str());
+                    error.SetErrorToGenericError();
+                    error.SetErrorString(bad_value_error);
+                    return false;
+                }
+                frame.AssignValue(inst, result, module);
+
+                if (log)
+                {
+                    log->Printf("Interpreted a %s", inst->getOpcodeName());
+                    log->Printf("  Incoming value : %s", frame.SummarizeValue(value).c_str());
+                }
+            }
+            break;
             case Instruction::GetElementPtr:
             {
                 const GetElementPtrInst *gep_inst = dyn_cast<GetElementPtrInst>(inst);




More information about the lldb-commits mailing list