Index: lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/TestIRInterpreter.py =================================================================== --- lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/TestIRInterpreter.py +++ lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/TestIRInterpreter.py @@ -5,6 +5,7 @@ from __future__ import print_function import unittest2 +import ctypes import lldb from lldbsuite.test.decorators import * @@ -40,6 +41,37 @@ self.runCmd("run", RUN_SUCCEEDED) + class Variable: + def __init__(self, uid, type, value): + self.name = "$i_" + str(uid) + "_" + type.replace(" ", "_") + self.type = type + self.value = value + # The value may be different if it's negative and we have an + # unsigned type. Let's ask Python for the actual converted value on + # the current platform. + if type == "unsigned int": + self.value = ctypes.c_uint(self.value) + elif "unsigned" in type: + assert False, "Unsupported unsigned type: " + type + self.decl_expr = type + " " + self.name + " = " + str(self.value) + + class Operator: + def __init__(self, name): + self.name = name + + def can_handle_operands(self, lhs, rhs): + """True iff this operator can handle the variables as operands.""" + if self.name in ['<<', '>>']: + # Shifting negative values, shifting by negative values and + # shifting by too large values will make this test fail (as + # the interpreter will evaluate this differently than the JIT). + # FIXME: This is probably a bug in the IRInterpreter. + if lhs.value <= 0: + return False + if rhs.value <= 0 or rhs.value >= 32: + return False + return True + @add_test_categories(['pyapi']) # getpid() is POSIX, among other problems, see bug @expectedFailureAll( @@ -50,35 +82,74 @@ oslist=['linux'], archs=['arm'], bugnumber="llvm.org/pr27868") - def test_ir_interpreter(self): + def test_ir_interpreter_int_ops(self): self.build_and_run() + # Normal expression options we use for JITed expressions. options = lldb.SBExpressionOptions() options.SetLanguage(lldb.eLanguageTypeC_plus_plus) - set_up_expressions = ["int $i = 9", "int $j = 3", "int $k = 5"] - - expressions = ["$i + $j", - "$i - $j", - "$i * $j", - "$i / $j", - "$i % $k", - "$i << $j", - "$i & $j", - "$i | $j", - "$i ^ $j"] - - for expression in set_up_expressions: - self.frame().EvaluateExpression(expression, options) - - for expression in expressions: + # Expression options that prevent that we use the JIT. + nojit_options = lldb.SBExpressionOptions() + nojit_options.SetLanguage(lldb.eLanguageTypeC_plus_plus) + nojit_options.SetAllowJIT(False) + + # List of operators the interpreter supports and we want to test. + operators = ['+', '-', '*', '%', '/', + '<<', '>>', '&', '|', '^', + '>', '<', '>=', '<=', '!=', '=='] + operator_list = [] + for opname in operators: + operator_list.append(self.Operator(opname)) + + # Variable types that should be tested with the operators. + types_to_test = ['int', 'unsigned int'] + + # Values these variables can have. + values_to_test = [255, 256, -1, 0, 1, 255, 256] + + # Id for every variable to give them unique names. + uid = 0 + # Define a variable for every type and for every value in LLDB. + variable_list = [] + for t in types_to_test: + for value in values_to_test: + v = self.Variable(uid, t, value) + variable_list.append(v) + # FIXME: We should check for errors here, but declaring + # $variables just returns some empty error it seems... + self.frame().EvaluateExpression(v.decl_expr, nojit_options) + uid += 1 + + # Create a list of expressions that use every operator. + exprs_to_run = [] + for op in operator_list: + # Try all combinations of variables with the operator. + for var1 in variable_list: + for var2 in variable_list: + if not op.can_handle_operands(var1, var2): + continue + # Create an expression using the operator. + expr = var1.name + " " + op.name + " " + var2.name + # Resolve the variable values and add that as a comment + # to the expression. This will be shown when the test fails. + expr += " // " + str(var1.value) + " " + op.name + " " + str(var2.value) + exprs_to_run.append(expr) + + # Make sure we actually did generate a list of expressions. + assert len(exprs_to_run) != 0 + for expression in exprs_to_run: interp_expression = expression + # We call 'getpid()' as a trick to force the expression to JITed. + # FIXME: Find a non-hacky way to tell LLDB to enforce this. jit_expression = "(int)getpid(); " + expression + # Run the expression in the interpreter and in the JIT. Both + # should produce the same result. interp_result = self.frame().EvaluateExpression( - interp_expression, options).GetValueAsSigned() + interp_expression, nojit_options).GetValueAsUnsigned() jit_result = self.frame().EvaluateExpression( - jit_expression, options).GetValueAsSigned() + jit_expression, options).GetValueAsUnsigned() self.assertEqual( interp_result,