diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index c9fa2b993c1ece..64df2740145b75 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -12928,6 +12928,11 @@ class SequenceChecker : public ConstEvaluatedExprVisitor { } void VisitCallExpr(const CallExpr *CE) { + // FIXME: CXXNewExpr and CXXDeleteExpr implicitly call functions. + + if (CE->isUnevaluatedBuiltinCall(Context)) + return; + // C++11 [intro.execution]p15: // When calling a function [...], every value computation and side effect // associated with any argument expression, or with the postfix expression @@ -12935,10 +12940,41 @@ class SequenceChecker : public ConstEvaluatedExprVisitor { // expression or statement in the body of the function [and thus before // the value computation of its result]. SequencedSubexpression Sequenced(*this); - SemaRef.runWithSufficientStackSpace(CE->getExprLoc(), - [&] { Base::VisitCallExpr(CE); }); + SemaRef.runWithSufficientStackSpace(CE->getExprLoc(), [&] { + // C++17 [expr.call]p5 + // The postfix-expression is sequenced before each expression in the + // expression-list and any default argument. [...] + SequenceTree::Seq CalleeRegion; + SequenceTree::Seq OtherRegion; + if (SemaRef.getLangOpts().CPlusPlus17) { + CalleeRegion = Tree.allocate(Region); + OtherRegion = Tree.allocate(Region); + } else { + CalleeRegion = Region; + OtherRegion = Region; + } + SequenceTree::Seq OldRegion = Region; - // FIXME: CXXNewExpr and CXXDeleteExpr implicitly call functions. + // Visit the callee expression first. + Region = CalleeRegion; + if (SemaRef.getLangOpts().CPlusPlus17) { + SequencedSubexpression Sequenced(*this); + Visit(CE->getCallee()); + } else { + Visit(CE->getCallee()); + } + + // Then visit the argument expressions. + Region = OtherRegion; + for (const Expr *Argument : CE->arguments()) + Visit(Argument); + + Region = OldRegion; + if (SemaRef.getLangOpts().CPlusPlus17) { + Tree.merge(CalleeRegion); + Tree.merge(OtherRegion); + } + }); } void VisitCXXConstructExpr(const CXXConstructExpr *CCE) { diff --git a/clang/test/SemaCXX/warn-unsequenced.cpp b/clang/test/SemaCXX/warn-unsequenced.cpp index 62f725bd07124b..84b0f9fd5b2f90 100644 --- a/clang/test/SemaCXX/warn-unsequenced.cpp +++ b/clang/test/SemaCXX/warn-unsequenced.cpp @@ -15,7 +15,6 @@ struct S { int n; }; -// TODO: Implement the C++17 sequencing rules. void test() { int a; int xs[10]; @@ -256,6 +255,27 @@ void test() { p[i++] = (i = 42); // cxx11-warning {{multiple unsequenced modifications to 'i'}} p++[i++] = (i = p ? i++ : i++); // cxx11-warning {{unsequenced modification and access to 'p'}} // cxx11-warning@-1 {{multiple unsequenced modifications to 'i'}} + + (i++, f)(i++, 42); // cxx11-warning {{multiple unsequenced modifications to 'i'}} + (i++ + i++, f)(42, 42); // cxx11-warning {{multiple unsequenced modifications to 'i'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'i'}} + int (*pf)(int, int); + (pf = f)(pf != nullptr, pf != nullptr); // cxx11-warning {{unsequenced modification and access to 'pf'}} + pf((pf = f) != nullptr, 42); // cxx11-warning {{unsequenced modification and access to 'pf'}} + f((pf = f, 42), (pf = f, 42)); // cxx11-warning {{multiple unsequenced modifications to 'pf'}} + // cxx17-warning@-1 {{multiple unsequenced modifications to 'pf'}} + pf((pf = f) != nullptr, pf == nullptr); // cxx11-warning {{unsequenced modification and access to 'pf'}} + // cxx17-warning@-1 {{unsequenced modification and access to 'pf'}} +} + +namespace PR20819 { + struct foo { void bar(int); }; + foo get_foo(int); + + void g() { + int a = 0; + get_foo(a).bar(a++); // cxx11-warning {{unsequenced modification and access to 'a'}} + } } namespace members { diff --git a/d.diff b/d.diff deleted file mode 100644 index ffa4caadfb881e..00000000000000 --- a/d.diff +++ /dev/null @@ -1,712 +0,0 @@ -diff --git a/debuginfo-tests/dexter/Commands.md b/debuginfo-tests/dexter/Commands.md -index c30a0d7214c..2e2fecfed92 100644 ---- a/debuginfo-tests/dexter/Commands.md -+++ b/debuginfo-tests/dexter/Commands.md -@@ -173,6 +173,34 @@ Expect the source line this is found on will never be stepped on to. - [TODO] - - -+---- -+## DexLimitSteps -+ DexLimitSteps(expr, *values [, **from_line=1],[,**to_line=Max] -+ [,**on_line]) -+ -+ Args: -+ expr (str): variable or value to compare. -+ -+ Arg list: -+ values (str): At least one potential value the expr may evaluate to. -+ -+ Keyword args: -+ from_line (int): Define the start of the limited step range. -+ to_line (int): Define the end of the limited step range. -+ on_line (int): Define a range with length 1 starting and ending on the -+ same line. -+ -+### Description -+Define a limited stepping range that is predicated on a condition. When -+'(expr) == (values[n])', set a range of temporary, unconditional break points within -+the test file defined by the range from_line and to_line or on_line. -+ -+The condition is only evaluated on the line 'from_line' or 'on_line'. If the -+condition is not true at the start of the range, the whole range is ignored. -+ -+DexLimitSteps commands are useful for reducing the amount of steps gathered in -+large test cases that would normally take much longer to complete. -+ - ---- - ## DexLabel - DexLabel(name) -diff --git a/debuginfo-tests/dexter/dex/command/ParseCommand.py b/debuginfo-tests/dexter/dex/command/ParseCommand.py -index 4cc9ae12592..8246ea9e3cf 100644 ---- a/debuginfo-tests/dexter/dex/command/ParseCommand.py -+++ b/debuginfo-tests/dexter/dex/command/ParseCommand.py -@@ -24,6 +24,7 @@ from dex.command.commands.DexExpectStepOrder import DexExpectStepOrder - from dex.command.commands.DexExpectWatchType import DexExpectWatchType - from dex.command.commands.DexExpectWatchValue import DexExpectWatchValue - from dex.command.commands.DexLabel import DexLabel -+from dex.command.commands.DexLimitSteps import DexLimitSteps - from dex.command.commands.DexUnreachable import DexUnreachable - from dex.command.commands.DexWatch import DexWatch - from dex.utils import Timer -@@ -42,6 +43,7 @@ def _get_valid_commands(): - DexExpectWatchType.get_name() : DexExpectWatchType, - DexExpectWatchValue.get_name() : DexExpectWatchValue, - DexLabel.get_name() : DexLabel, -+ DexLimitSteps.get_name() : DexLimitSteps, - DexUnreachable.get_name() : DexUnreachable, - DexWatch.get_name() : DexWatch - } -diff --git a/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py b/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py -new file mode 100644 -index 00000000000..d66401b5599 ---- /dev/null -+++ b/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py -@@ -0,0 +1,54 @@ -+# DExTer : Debugging Experience Tester -+# ~~~~~~ ~ ~~ ~ ~~ -+# -+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+# See https://llvm.org/LICENSE.txt for license information. -+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+"""A Command that enables test writers to specify a limited number of break -+points using an start condition and range. -+""" -+ -+from dex.command.CommandBase import CommandBase -+ -+class DexLimitSteps(CommandBase): -+ def __init__(self, *args, **kwargs): -+ self.expression = args[0] -+ self.values = [str(arg) for arg in args[1:]] -+ try: -+ on_line = kwargs.pop('on_line') -+ self.from_line = on_line -+ self.to_line = on_line -+ except KeyError: -+ self.from_line = kwargs.pop('from_line', 1) -+ self.to_line = kwargs.pop('to_line', 999999) -+ if kwargs: -+ raise TypeError('unexpected named args: {}'.format( -+ ', '.join(kwargs))) -+ super(DexLimitSteps, self).__init__() -+ -+ def resolve_label(self, label_line_pair): -+ label, lineno = label_line_pair -+ if isinstance(self.from_line, str): -+ if self.from_line == label: -+ self.from_line = lineno -+ if isinstance(self.to_line, str): -+ if self.to_line == label: -+ self.to_line = lineno -+ -+ def has_labels(self): -+ return len(self.get_label_args()) > 0 -+ -+ def get_label_args(self): -+ return [label for label in (self.from_line, self.to_line) -+ if isinstance(label, str)] -+ -+ def eval(self): -+ raise NotImplementedError('DexLimitSteps commands cannot be evaled.') -+ -+ @staticmethod -+ def get_name(): -+ return __class__.__name__ -+ -+ @staticmethod -+ def get_subcommands() -> dict: -+ return None -diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py -index 2261396b94b..12f4f4ab7a0 100644 ---- a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py -+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py -@@ -120,6 +120,14 @@ class DebuggerBase(object, metaclass=abc.ABCMeta): - def add_breakpoint(self, file_, line): - pass - -+ @abc.abstractmethod -+ def add_conditional_breakpoint(self, file_, line, condition): -+ pass -+ -+ @abc.abstractmethod -+ def delete_conditional_breakpoint(self, file_, line, condition): -+ pass -+ - @abc.abstractmethod - def launch(self): - pass -diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py -new file mode 100644 -index 00000000000..4e4327b53f8 ---- /dev/null -+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py -@@ -0,0 +1,127 @@ -+# DExTer : Debugging Experience Tester -+# ~~~~~~ ~ ~~ ~ ~~ -+# -+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+# See https://llvm.org/LICENSE.txt for license information. -+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+"""Conditional Controller Class for DExTer.-""" -+ -+ -+import os -+import time -+from collections import defaultdict -+from itertools import chain -+ -+from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches -+from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase -+from dex.debugger.DebuggerBase import DebuggerBase -+from dex.utils.Exceptions import DebuggerException -+ -+ -+class ConditionalBpRange: -+ """Represents a conditional range of breakpoints within a source file descending from -+ one line to another.""" -+ -+ def __init__(self, expression: str, path: str, range_from: int, range_to: int, values: list): -+ self.expression = expression -+ self.path = path -+ self.range_from = range_from -+ self.range_to = range_to -+ self.conditional_values = values -+ -+ def get_conditional_expression_list(self): -+ conditional_list = [] -+ for value in self.conditional_values: -+ # () == () -+ conditional_expression = '({}) == ({})'.format(self.expression, value) -+ conditional_list.append(conditional_expression) -+ return conditional_list -+ -+ -+class ConditionalController(DebuggerControllerBase): -+ def __init__(self, context, step_collection): -+ self.context = context -+ self.step_collection = step_collection -+ self._conditional_bps = None -+ self._watches = set() -+ self._step_index = 0 -+ self._build_conditional_bps() -+ self._path_and_line_to_conditional_bp = defaultdict(list) -+ self._pause_between_steps = context.options.pause_between_steps -+ self._max_steps = context.options.max_steps -+ -+ def _build_conditional_bps(self): -+ commands = self.step_collection.commands -+ self._conditional_bps = [] -+ try: -+ limit_commands = commands['DexLimitSteps'] -+ for lc in limit_commands: -+ conditional_bp = ConditionalBpRange( -+ lc.expression, -+ lc.path, -+ lc.from_line, -+ lc.to_line, -+ lc.values) -+ self._conditional_bps.append(conditional_bp) -+ except KeyError: -+ raise DebuggerException('Missing DexLimitSteps commands, cannot conditionally step.') -+ -+ def _set_conditional_bps(self): -+ # When we break in the debugger we need a quick and easy way to look up -+ # which conditional bp we've breaked on. -+ for cbp in self._conditional_bps: -+ conditional_bp_list = self._path_and_line_to_conditional_bp[(cbp.path, cbp.range_from)] -+ conditional_bp_list.append(cbp) -+ -+ # Set break points only on the first line of any conditional range, we'll set -+ # more break points for a range when the condition is satisfied. -+ for cbp in self._conditional_bps: -+ for cond_expr in cbp.get_conditional_expression_list(): -+ self.debugger.add_conditional_breakpoint(cbp.path, cbp.range_from, cond_expr) -+ -+ def _conditional_met(self, cbp): -+ for cond_expr in cbp.get_conditional_expression_list(): -+ valueIR = self.debugger.evaluate_expression(cond_expr) -+ if valueIR.type_name == 'bool' and valueIR.value == 'true': -+ return True -+ return False -+ -+ def _run_debugger_custom(self): -+ # TODO: Add conditional and unconditional breakpoint support to dbgeng. -+ if self.debugger.get_name() == 'dbgeng': -+ raise DebuggerException('DexLimitSteps commands are not supported by dbgeng') -+ -+ self.step_collection.clear_steps() -+ self._set_conditional_bps() -+ -+ for command_obj in chain.from_iterable(self.step_collection.commands.values()): -+ self._watches.update(command_obj.get_watches()) -+ -+ self.debugger.launch() -+ time.sleep(self._pause_between_steps) -+ while not self.debugger.is_finished: -+ while self.debugger.is_running: -+ pass -+ -+ step_info = self.debugger.get_step_info(self._watches, self._step_index) -+ if step_info.current_frame: -+ self._step_index += 1 -+ update_step_watches(step_info, self._watches, self.step_collection.commands) -+ self.step_collection.new_step(self.context, step_info) -+ -+ loc = step_info.current_location -+ conditional_bp_key = (loc.path, loc.lineno) -+ if conditional_bp_key in self._path_and_line_to_conditional_bp: -+ -+ conditional_bps = self._path_and_line_to_conditional_bp[conditional_bp_key] -+ for cbp in conditional_bps: -+ if self._conditional_met(cbp): -+ # Unconditional range should ignore first line as that's the -+ # conditional bp we just hit and should be inclusive of final line -+ for line in range(cbp.range_from + 1, cbp.range_to + 1): -+ self.debugger.add_conditional_breakpoint(cbp.path, line, condition='') -+ -+ # Clear any uncondtional break points at this loc. -+ self.debugger.delete_conditional_breakpoint(file_=loc.path, line=loc.lineno, condition='') -+ self.debugger.go() -+ time.sleep(self._pause_between_steps) -diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py -new file mode 100644 -index 00000000000..adac7674aff ---- /dev/null -+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py -@@ -0,0 +1,37 @@ -+# DExTer : Debugging Experience Tester -+# ~~~~~~ ~ ~~ ~ ~~ -+# -+# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -+# See https://llvm.org/LICENSE.txt for license information. -+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -+ -+import os -+from itertools import chain -+ -+def in_source_file(source_files, step_info): -+ if not step_info.current_frame: -+ return False -+ if not step_info.current_location.path: -+ return False -+ if not os.path.exists(step_info.current_location.path): -+ return False -+ return any(os.path.samefile(step_info.current_location.path, f) \ -+ for f in source_files) -+ -+def update_step_watches(step_info, watches, commands): -+ watch_cmds = ['DexUnreachable', 'DexExpectStepOrder'] -+ towatch = chain.from_iterable(commands[x] -+ for x in watch_cmds -+ if x in commands) -+ try: -+ # Iterate over all watches of the types named in watch_cmds -+ for watch in towatch: -+ loc = step_info.current_location -+ if (os.path.exists(loc.path) -+ and os.path.samefile(watch.path, loc.path) -+ and watch.lineno == loc.lineno): -+ result = watch.eval(step_info) -+ step_info.watches.update(result) -+ break -+ except KeyError: -+ pass -diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py -index ff98baa2d0e..87b13fc7f3a 100644 ---- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py -+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py -@@ -4,7 +4,7 @@ - # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - # See https://llvm.org/LICENSE.txt for license information. - # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --"""Default class for controlling debuggers.""" -+"""Abstract Base class for controlling debuggers.""" - - import abc - -diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py -index 0077a19e601..c41a3eff0d3 100644 ---- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py -+++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py -@@ -4,61 +4,37 @@ - # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. - # See https://llvm.org/LICENSE.txt for license information. - # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception --"""Base class for controlling debuggers.""" -+"""Default class for controlling debuggers.""" - - from itertools import chain - import os - import time - - from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase --from dex.utils.Exceptions import DebuggerException -+from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches -+from dex.utils.Exceptions import DebuggerException, LoadDebuggerException - - class DefaultController(DebuggerControllerBase): - def __init__(self, context, step_collection): - self.context = context - self.step_collection = step_collection -+ self.source_files = self.context.options.source_files - self.watches = set() - self.step_index = 0 - -- def _update_step_watches(self, step_info): -- watch_cmds = ['DexUnreachable', 'DexExpectStepOrder'] -- towatch = chain.from_iterable(self.step_collection.commands[x] -- for x in watch_cmds -- if x in self.step_collection.commands) -- try: -- # Iterate over all watches of the types named in watch_cmds -- for watch in towatch: -- loc = step_info.current_location -- if (os.path.exists(loc.path) -- and os.path.samefile(watch.path, loc.path) -- and watch.lineno == loc.lineno): -- result = watch.eval(step_info) -- step_info.watches.update(result) -- break -- except KeyError: -- pass -- - def _break_point_all_lines(self): - for s in self.context.options.source_files: - with open(s, 'r') as fp: - num_lines = len(fp.readlines()) - for line in range(1, num_lines + 1): -- self.debugger.add_breakpoint(s, line) -- -- def _in_source_file(self, step_info): -- if not step_info.current_frame: -- return False -- if not step_info.current_location.path: -- return False -- if not os.path.exists(step_info.current_location.path): -- return False -- return any(os.path.samefile(step_info.current_location.path, f) \ -- for f in self.context.options.source_files) -+ try: -+ self.debugger.add_breakpoint(s, line) -+ except DebuggerException: -+ raise LoadDebuggerException(DebuggerException.msg) - - def _run_debugger_custom(self): - self.step_collection.debugger = self.debugger.debugger_info - self._break_point_all_lines() -- - self.debugger.launch() - - for command_obj in chain.from_iterable(self.step_collection.commands.values()): -@@ -76,10 +52,10 @@ class DefaultController(DebuggerControllerBase): - step_info = self.debugger.get_step_info(self.watches, self.step_index) - - if step_info.current_frame: -- self._update_step_watches(step_info) -+ update_step_watches(step_info, self.watches, self.step_collection.commands) - self.step_collection.new_step(self.context, step_info) - -- if self._in_source_file(step_info): -+ if in_source_file(self.source_files, step_info): - self.debugger.step() - else: - self.debugger.go() -diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py -index 0afc748aecb..d812fd974f7 100644 ---- a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py -+++ b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py -@@ -77,11 +77,21 @@ class DbgEng(DebuggerBase): - self.client.Control.RemoveBreakpoint(x) - - def add_breakpoint(self, file_, line): -- # This is something to implement in the future -- as it stands, Dexter -- # doesn't test for such things as "I can set a breakpoint on this line". -- # This is only called AFAICT right now to ensure we break on every step. -+ # Breakpoint setting/deleting is not supported by dbgeng at this moment -+ # but is something that should be considered in the future. -+ # TODO: this method is called in the DefaultController but has no effect. - pass - -+ def add_conditional_breakpoint(self, file_, line, condition): -+ # breakpoint setting/deleting is not supported by dbgeng at this moment -+ # but is something that should be considered in the future. -+ raise NotImplementedError('add_conditional_breakpoint is not yet implemented by dbgeng') -+ -+ def delete_conditional_breakpoint(self, file_, line, condition): -+ # breakpoint setting/deleting is not supported by dbgeng at this moment -+ # but is something that should be considered in the future. -+ raise NotImplementedError('delete_conditional_breakpoint is not yet implemented by dbgeng') -+ - def launch(self): - # We are, by this point, already launched. - self.step_info = probe_process.probe_state(self.client) -diff --git a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py -index a943431c888..c7bb74681d9 100644 ---- a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py -+++ b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py -@@ -105,9 +105,48 @@ class LLDB(DebuggerBase): - - def add_breakpoint(self, file_, line): - if not self._target.BreakpointCreateByLocation(file_, line): -- raise LoadDebuggerException( -+ raise DebuggerException( - 'could not add breakpoint [{}:{}]'.format(file_, line)) - -+ def add_conditional_breakpoint(self, file_, line, condition): -+ bp = self._target.BreakpointCreateByLocation(file_, line) -+ if bp: -+ bp.SetCondition(condition) -+ else: -+ raise DebuggerException( -+ 'could not add breakpoint [{}:{}]'.format(file_, line)) -+ -+ def delete_conditional_breakpoint(self, file_, line, condition): -+ bp_count = self._target.GetNumBreakpoints() -+ bps = [self._target.GetBreakpointAtIndex(ix) for ix in range(0, bp_count)] -+ -+ for bp in bps: -+ bp_cond = bp.GetCondition() -+ bp_cond = bp_cond if bp_cond is not None else '' -+ -+ if bp_cond != condition: -+ continue -+ -+ # If one of the bound bp locations for this bp is bound to the same -+ # line in file_ above, then delete the entire parent bp and all -+ # bp locs. -+ # https://lldb.llvm.org/python_reference/lldb.SBBreakpoint-class.html -+ for breakpoint_location in bp: -+ sb_address = breakpoint_location.GetAddress() -+ -+ sb_line_entry = sb_address.GetLineEntry() -+ bl_line = sb_line_entry.GetLine() -+ -+ sb_file_entry = sb_line_entry.GetFileSpec() -+ bl_dir = sb_file_entry.GetDirectory() -+ bl_file_name = sb_file_entry.GetFilename() -+ -+ bl_file_path = os.path.join(bl_dir, bl_file_name) -+ -+ if bl_file_path == file_ and bl_line == line: -+ self._target.BreakpointDelete(bp.GetID()) -+ break -+ - def launch(self): - self._process = self._target.LaunchSimple(None, None, os.getcwd()) - if not self._process or self._process.GetNumThreads() == 0: -diff --git a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py -index b9816f84f72..40a902bd205 100644 ---- a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py -+++ b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py -@@ -82,6 +82,9 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst - - @property - def _location(self): -+ #TODO: Find a better way of determining path, line and column info -+ # that doesn't require reading break points. This method requires -+ # all lines to have a break point on them. - bp = self._debugger.BreakpointLastHit - return { - 'path': getattr(bp, 'File', None), -@@ -111,8 +114,20 @@ class VisualStudio(DebuggerBase, metaclass=abc.ABCMeta): # pylint: disable=abst - def add_breakpoint(self, file_, line): - self._debugger.Breakpoints.Add('', file_, line) - -+ def add_conditional_breakpoint(self, file_, line, condition): -+ column = 1 -+ self._debugger.Breakpoints.Add('', file_, line, column, condition) -+ -+ def delete_conditional_breakpoint(self, file_, line, condition): -+ for bp in self._debugger.Breakpoints: -+ for bound_bp in bp.Children: -+ if (bound_bp.File == file_ and bound_bp.FileLine == line and -+ bound_bp.Condition == condition): -+ bp.Delete() -+ break -+ - def launch(self): -- self.step() -+ self._fn_go() - - def step(self): - self._fn_step() -diff --git a/debuginfo-tests/dexter/dex/tools/test/Tool.py b/debuginfo-tests/dexter/dex/tools/test/Tool.py -index a615c8cad90..43191fd44bd 100644 ---- a/debuginfo-tests/dexter/dex/tools/test/Tool.py -+++ b/debuginfo-tests/dexter/dex/tools/test/Tool.py -@@ -16,6 +16,7 @@ from dex.builder import run_external_build_script - from dex.command.ParseCommand import get_command_infos - from dex.debugger.Debuggers import run_debugger_subprocess - from dex.debugger.DebuggerControllers.DefaultController import DefaultController -+from dex.debugger.DebuggerControllers.ConditionalController import ConditionalController - from dex.dextIR.DextIR import DextIR - from dex.heuristic import Heuristic - from dex.tools import TestToolBase -@@ -136,9 +137,15 @@ class Tool(TestToolBase): - executable_path=self.context.options.executable, - source_paths=self.context.options.source_files, - dexter_version=self.context.version) -+ - step_collection.commands = get_command_infos( - self.context.options.source_files) -- debugger_controller = DefaultController(self.context, step_collection) -+ -+ if 'DexLimitSteps' in step_collection.commands: -+ debugger_controller = ConditionalController(self.context, step_collection) -+ else: -+ debugger_controller = DefaultController(self.context, step_collection) -+ - return debugger_controller - - def _get_steps(self, builderIR): -diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp -new file mode 100644 -index 00000000000..45683fced2d ---- /dev/null -+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp -@@ -0,0 +1,20 @@ -+// Purpose: -+// Check number of step lines are correctly reported in json output. -+// -+// REQUIRES: system-linux -+// -+// RUN: %dexter_regression_test --verbose -- %s | FileCheck %s -+// CHECK: limit_steps_check_json_step_count.cpp -+// CHECK: ## BEGIN ## -+// CHECK-COUNT-3: json_step_count.cpp", -+ -+int main() { -+ int result = 0; -+ for(int ix = 0; ix != 10; ++ix) { -+ int index = ix; -+ result += index; // DexLabel('check') -+ } -+} -+ -+// DexExpectWatchValue('index', 2, 7, 9, on_line='check') -+// DexLimitSteps('ix', 2, 7, 9, on_line='check') -diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp -new file mode 100644 -index 00000000000..5946fa6ba46 ---- /dev/null -+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp -@@ -0,0 +1,20 @@ -+// Purpose: -+// Check the DexLimit steps only gathers step info for 2 iterations of a -+// for loop. -+// -+// REQUIRES: system-linux -+// -+// RUN: %dexter_regression_test -- %s | FileCheck %s -+// CHECK: limit_steps_expect_loop.cpp: -+ -+int main(const int argc, const char * argv[]) { -+ unsigned int sum = 1; -+ for(unsigned int ix = 0; ix != 5; ++ix) { -+ unsigned thing_to_add = ix + ix - ix; // DexLabel('start') -+ sum += ix; // DexLabel('end') -+ } -+ return sum; -+} -+ -+// DexLimitSteps('ix', 0, 3, from_line='start', to_line='end') -+// DexExpectWatchValue('ix', 0, 3, from_line='start', to_line='end') -diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp -new file mode 100644 -index 00000000000..2715e28d66b ---- /dev/null -+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp -@@ -0,0 +1,18 @@ -+// Purpose: -+// Ensure that limited stepping breaks for all expected values. -+// -+// REQUIRES: system-linux -+// -+// RUN: %dexter_regression_test -- %s | FileCheck %s -+// CHECK: limit_steps_expect_value.cpp -+ -+int main() { -+ int i = 0; -+ i = 1; // DexLabel('from') -+ i = 2; -+ i = 3; -+ return 0; // DexLabel('long_range') -+} -+ -+// DexLimitSteps('i', '0', from_line='from', to_line='long_range') -+// DexExpectWatchValue('i', 0, 1, 2, 3, from_line='from', to_line='long_range') -diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp -new file mode 100644 -index 00000000000..3200fe0979b ---- /dev/null -+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp -@@ -0,0 +1,36 @@ -+// Purpose: -+// Ensure that multiple overlapping \DexLimitSteps ranges do not interfere. -+// -+// REQUIRES: system-linux -+// -+// RUN: %dexter_regression_test -- %s | FileCheck %s -+// CHECK: limit_steps_overlapping_ranges.cpp -+ -+int main() { -+ int val1; -+ int val2; -+ int placeholder; -+ for (int ix = 0; ix != 10; ++ix) { -+ placeholder=val1+val2; // DexLabel('from') -+ if (ix == 0) { -+ val1 = ix; -+ val2 = ix; // DexLabel('val1_check') -+ placeholder=val1+val2; // DexLabel('val1_check_to') -+ } -+ else if (ix == 2) { -+ val2 = ix; -+ val1 = ix; // DexLabel('val2_check') -+ placeholder=val1+val2; // DexLabel('val2_check_to') -+ } -+ placeholder=val1+val2; // DexLabel('to') -+ } -+ return val1 + val2; -+} -+ -+// DexExpectWatchValue('ix', 0, 2, 5, from_line='from', to_line='to') -+// DexExpectWatchValue('val1', 0, from_line='val1_check', to_line='val1_check_to') -+// DexExpectWatchValue('val2', 2, from_line='val2_check', to_line='val2_check_to') -+ -+// DexLimitSteps('ix', 5, from_line='from', to_line='to') -+// DexLimitSteps('val1', 0, from_line='val1_check', to_line='val1_check_to') -+// DexLimitSteps('val2', 2, from_line='val2_check', to_line='val2_check_to') -diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp -new file mode 100644 -index 00000000000..060ff0d5fe7 ---- /dev/null -+++ b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp -@@ -0,0 +1,26 @@ -+// Purpose: -+// Test that LimitStep commands can exist on the same from line. -+// -+// REQUIRES: system-linux -+// -+// RUN: %dexter_regression_test -- %s | FileCheck %s -+// CHECK: limit_steps_same_line_conditional.cpp -+ -+int main() { -+ int val1 = 0; -+ -+ int placeholder; -+ for(int ix = 0; ix != 4; ++ix) { -+ val1 = ix; -+ placeholder = ix; // DexLabel('from') -+ placeholder = ix; -+ val1 += 2; // DexLabel('to') -+ placeholder = ix; // DexLabel('extended_to') -+ } -+ return val1 + placeholder; -+} -+ -+// DexExpectWatchValue('val1', 0, 1, 3, from_line='from', to_line='extended_to') -+ -+// DexLimitSteps('ix', 0, from_line='from', to_line='to') -+// DexLimitSteps('ix', 1, from_line='from', to_line='extended_to') diff --git a/debuginfo-tests/dexter/Commands.md b/debuginfo-tests/dexter/Commands.md index 2e2fecfed929a7..c30a0d7214c916 100644 --- a/debuginfo-tests/dexter/Commands.md +++ b/debuginfo-tests/dexter/Commands.md @@ -173,34 +173,6 @@ Expect the source line this is found on will never be stepped on to. [TODO] ----- -## DexLimitSteps - DexLimitSteps(expr, *values [, **from_line=1],[,**to_line=Max] - [,**on_line]) - - Args: - expr (str): variable or value to compare. - - Arg list: - values (str): At least one potential value the expr may evaluate to. - - Keyword args: - from_line (int): Define the start of the limited step range. - to_line (int): Define the end of the limited step range. - on_line (int): Define a range with length 1 starting and ending on the - same line. - -### Description -Define a limited stepping range that is predicated on a condition. When -'(expr) == (values[n])', set a range of temporary, unconditional break points within -the test file defined by the range from_line and to_line or on_line. - -The condition is only evaluated on the line 'from_line' or 'on_line'. If the -condition is not true at the start of the range, the whole range is ignored. - -DexLimitSteps commands are useful for reducing the amount of steps gathered in -large test cases that would normally take much longer to complete. - ---- ## DexLabel DexLabel(name) diff --git a/debuginfo-tests/dexter/dex/command/ParseCommand.py b/debuginfo-tests/dexter/dex/command/ParseCommand.py index 8246ea9e3cf975..4cc9ae125920de 100644 --- a/debuginfo-tests/dexter/dex/command/ParseCommand.py +++ b/debuginfo-tests/dexter/dex/command/ParseCommand.py @@ -24,7 +24,6 @@ from dex.command.commands.DexExpectWatchType import DexExpectWatchType from dex.command.commands.DexExpectWatchValue import DexExpectWatchValue from dex.command.commands.DexLabel import DexLabel -from dex.command.commands.DexLimitSteps import DexLimitSteps from dex.command.commands.DexUnreachable import DexUnreachable from dex.command.commands.DexWatch import DexWatch from dex.utils import Timer @@ -43,7 +42,6 @@ def _get_valid_commands(): DexExpectWatchType.get_name() : DexExpectWatchType, DexExpectWatchValue.get_name() : DexExpectWatchValue, DexLabel.get_name() : DexLabel, - DexLimitSteps.get_name() : DexLimitSteps, DexUnreachable.get_name() : DexUnreachable, DexWatch.get_name() : DexWatch } diff --git a/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py b/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py deleted file mode 100644 index d66401b55995ba..00000000000000 --- a/debuginfo-tests/dexter/dex/command/commands/DexLimitSteps.py +++ /dev/null @@ -1,54 +0,0 @@ -# DExTer : Debugging Experience Tester -# ~~~~~~ ~ ~~ ~ ~~ -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -"""A Command that enables test writers to specify a limited number of break -points using an start condition and range. -""" - -from dex.command.CommandBase import CommandBase - -class DexLimitSteps(CommandBase): - def __init__(self, *args, **kwargs): - self.expression = args[0] - self.values = [str(arg) for arg in args[1:]] - try: - on_line = kwargs.pop('on_line') - self.from_line = on_line - self.to_line = on_line - except KeyError: - self.from_line = kwargs.pop('from_line', 1) - self.to_line = kwargs.pop('to_line', 999999) - if kwargs: - raise TypeError('unexpected named args: {}'.format( - ', '.join(kwargs))) - super(DexLimitSteps, self).__init__() - - def resolve_label(self, label_line_pair): - label, lineno = label_line_pair - if isinstance(self.from_line, str): - if self.from_line == label: - self.from_line = lineno - if isinstance(self.to_line, str): - if self.to_line == label: - self.to_line = lineno - - def has_labels(self): - return len(self.get_label_args()) > 0 - - def get_label_args(self): - return [label for label in (self.from_line, self.to_line) - if isinstance(label, str)] - - def eval(self): - raise NotImplementedError('DexLimitSteps commands cannot be evaled.') - - @staticmethod - def get_name(): - return __class__.__name__ - - @staticmethod - def get_subcommands() -> dict: - return None diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py index 12f4f4ab7a0259..2261396b94b4ae 100644 --- a/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py +++ b/debuginfo-tests/dexter/dex/debugger/DebuggerBase.py @@ -120,14 +120,6 @@ def clear_breakpoints(self): def add_breakpoint(self, file_, line): pass - @abc.abstractmethod - def add_conditional_breakpoint(self, file_, line, condition): - pass - - @abc.abstractmethod - def delete_conditional_breakpoint(self, file_, line, condition): - pass - @abc.abstractmethod def launch(self): pass diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py deleted file mode 100644 index 4e4327b53f826b..00000000000000 --- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ConditionalController.py +++ /dev/null @@ -1,127 +0,0 @@ -# DExTer : Debugging Experience Tester -# ~~~~~~ ~ ~~ ~ ~~ -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -"""Conditional Controller Class for DExTer.-""" - - -import os -import time -from collections import defaultdict -from itertools import chain - -from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches -from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase -from dex.debugger.DebuggerBase import DebuggerBase -from dex.utils.Exceptions import DebuggerException - - -class ConditionalBpRange: - """Represents a conditional range of breakpoints within a source file descending from - one line to another.""" - - def __init__(self, expression: str, path: str, range_from: int, range_to: int, values: list): - self.expression = expression - self.path = path - self.range_from = range_from - self.range_to = range_to - self.conditional_values = values - - def get_conditional_expression_list(self): - conditional_list = [] - for value in self.conditional_values: - # () == () - conditional_expression = '({}) == ({})'.format(self.expression, value) - conditional_list.append(conditional_expression) - return conditional_list - - -class ConditionalController(DebuggerControllerBase): - def __init__(self, context, step_collection): - self.context = context - self.step_collection = step_collection - self._conditional_bps = None - self._watches = set() - self._step_index = 0 - self._build_conditional_bps() - self._path_and_line_to_conditional_bp = defaultdict(list) - self._pause_between_steps = context.options.pause_between_steps - self._max_steps = context.options.max_steps - - def _build_conditional_bps(self): - commands = self.step_collection.commands - self._conditional_bps = [] - try: - limit_commands = commands['DexLimitSteps'] - for lc in limit_commands: - conditional_bp = ConditionalBpRange( - lc.expression, - lc.path, - lc.from_line, - lc.to_line, - lc.values) - self._conditional_bps.append(conditional_bp) - except KeyError: - raise DebuggerException('Missing DexLimitSteps commands, cannot conditionally step.') - - def _set_conditional_bps(self): - # When we break in the debugger we need a quick and easy way to look up - # which conditional bp we've breaked on. - for cbp in self._conditional_bps: - conditional_bp_list = self._path_and_line_to_conditional_bp[(cbp.path, cbp.range_from)] - conditional_bp_list.append(cbp) - - # Set break points only on the first line of any conditional range, we'll set - # more break points for a range when the condition is satisfied. - for cbp in self._conditional_bps: - for cond_expr in cbp.get_conditional_expression_list(): - self.debugger.add_conditional_breakpoint(cbp.path, cbp.range_from, cond_expr) - - def _conditional_met(self, cbp): - for cond_expr in cbp.get_conditional_expression_list(): - valueIR = self.debugger.evaluate_expression(cond_expr) - if valueIR.type_name == 'bool' and valueIR.value == 'true': - return True - return False - - def _run_debugger_custom(self): - # TODO: Add conditional and unconditional breakpoint support to dbgeng. - if self.debugger.get_name() == 'dbgeng': - raise DebuggerException('DexLimitSteps commands are not supported by dbgeng') - - self.step_collection.clear_steps() - self._set_conditional_bps() - - for command_obj in chain.from_iterable(self.step_collection.commands.values()): - self._watches.update(command_obj.get_watches()) - - self.debugger.launch() - time.sleep(self._pause_between_steps) - while not self.debugger.is_finished: - while self.debugger.is_running: - pass - - step_info = self.debugger.get_step_info(self._watches, self._step_index) - if step_info.current_frame: - self._step_index += 1 - update_step_watches(step_info, self._watches, self.step_collection.commands) - self.step_collection.new_step(self.context, step_info) - - loc = step_info.current_location - conditional_bp_key = (loc.path, loc.lineno) - if conditional_bp_key in self._path_and_line_to_conditional_bp: - - conditional_bps = self._path_and_line_to_conditional_bp[conditional_bp_key] - for cbp in conditional_bps: - if self._conditional_met(cbp): - # Unconditional range should ignore first line as that's the - # conditional bp we just hit and should be inclusive of final line - for line in range(cbp.range_from + 1, cbp.range_to + 1): - self.debugger.add_conditional_breakpoint(cbp.path, line, condition='') - - # Clear any uncondtional break points at this loc. - self.debugger.delete_conditional_breakpoint(file_=loc.path, line=loc.lineno, condition='') - self.debugger.go() - time.sleep(self._pause_between_steps) diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py deleted file mode 100644 index adac7674aff6ef..00000000000000 --- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/ControllerHelpers.py +++ /dev/null @@ -1,37 +0,0 @@ -# DExTer : Debugging Experience Tester -# ~~~~~~ ~ ~~ ~ ~~ -# -# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -# See https://llvm.org/LICENSE.txt for license information. -# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -import os -from itertools import chain - -def in_source_file(source_files, step_info): - if not step_info.current_frame: - return False - if not step_info.current_location.path: - return False - if not os.path.exists(step_info.current_location.path): - return False - return any(os.path.samefile(step_info.current_location.path, f) \ - for f in source_files) - -def update_step_watches(step_info, watches, commands): - watch_cmds = ['DexUnreachable', 'DexExpectStepOrder'] - towatch = chain.from_iterable(commands[x] - for x in watch_cmds - if x in commands) - try: - # Iterate over all watches of the types named in watch_cmds - for watch in towatch: - loc = step_info.current_location - if (os.path.exists(loc.path) - and os.path.samefile(watch.path, loc.path) - and watch.lineno == loc.lineno): - result = watch.eval(step_info) - step_info.watches.update(result) - break - except KeyError: - pass diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py index 87b13fc7f3a877..ff98baa2d0e21f 100644 --- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py +++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DebuggerControllerBase.py @@ -4,7 +4,7 @@ # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -"""Abstract Base class for controlling debuggers.""" +"""Default class for controlling debuggers.""" import abc diff --git a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py index c41a3eff0d3ab4..0077a19e601a67 100644 --- a/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py +++ b/debuginfo-tests/dexter/dex/debugger/DebuggerControllers/DefaultController.py @@ -4,37 +4,61 @@ # Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. # See https://llvm.org/LICENSE.txt for license information. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -"""Default class for controlling debuggers.""" +"""Base class for controlling debuggers.""" from itertools import chain import os import time from dex.debugger.DebuggerControllers.DebuggerControllerBase import DebuggerControllerBase -from dex.debugger.DebuggerControllers.ControllerHelpers import in_source_file, update_step_watches -from dex.utils.Exceptions import DebuggerException, LoadDebuggerException +from dex.utils.Exceptions import DebuggerException class DefaultController(DebuggerControllerBase): def __init__(self, context, step_collection): self.context = context self.step_collection = step_collection - self.source_files = self.context.options.source_files self.watches = set() self.step_index = 0 + def _update_step_watches(self, step_info): + watch_cmds = ['DexUnreachable', 'DexExpectStepOrder'] + towatch = chain.from_iterable(self.step_collection.commands[x] + for x in watch_cmds + if x in self.step_collection.commands) + try: + # Iterate over all watches of the types named in watch_cmds + for watch in towatch: + loc = step_info.current_location + if (os.path.exists(loc.path) + and os.path.samefile(watch.path, loc.path) + and watch.lineno == loc.lineno): + result = watch.eval(step_info) + step_info.watches.update(result) + break + except KeyError: + pass + def _break_point_all_lines(self): for s in self.context.options.source_files: with open(s, 'r') as fp: num_lines = len(fp.readlines()) for line in range(1, num_lines + 1): - try: - self.debugger.add_breakpoint(s, line) - except DebuggerException: - raise LoadDebuggerException(DebuggerException.msg) + self.debugger.add_breakpoint(s, line) + + def _in_source_file(self, step_info): + if not step_info.current_frame: + return False + if not step_info.current_location.path: + return False + if not os.path.exists(step_info.current_location.path): + return False + return any(os.path.samefile(step_info.current_location.path, f) \ + for f in self.context.options.source_files) def _run_debugger_custom(self): self.step_collection.debugger = self.debugger.debugger_info self._break_point_all_lines() + self.debugger.launch() for command_obj in chain.from_iterable(self.step_collection.commands.values()): @@ -52,10 +76,10 @@ def _run_debugger_custom(self): step_info = self.debugger.get_step_info(self.watches, self.step_index) if step_info.current_frame: - update_step_watches(step_info, self.watches, self.step_collection.commands) + self._update_step_watches(step_info) self.step_collection.new_step(self.context, step_info) - if in_source_file(self.source_files, step_info): + if self._in_source_file(step_info): self.debugger.step() else: self.debugger.go() diff --git a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py index d812fd974f79d8..0afc748aecb1cf 100644 --- a/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py +++ b/debuginfo-tests/dexter/dex/debugger/dbgeng/dbgeng.py @@ -77,21 +77,11 @@ def clear_breakpoints(self): self.client.Control.RemoveBreakpoint(x) def add_breakpoint(self, file_, line): - # Breakpoint setting/deleting is not supported by dbgeng at this moment - # but is something that should be considered in the future. - # TODO: this method is called in the DefaultController but has no effect. + # This is something to implement in the future -- as it stands, Dexter + # doesn't test for such things as "I can set a breakpoint on this line". + # This is only called AFAICT right now to ensure we break on every step. pass - def add_conditional_breakpoint(self, file_, line, condition): - # breakpoint setting/deleting is not supported by dbgeng at this moment - # but is something that should be considered in the future. - raise NotImplementedError('add_conditional_breakpoint is not yet implemented by dbgeng') - - def delete_conditional_breakpoint(self, file_, line, condition): - # breakpoint setting/deleting is not supported by dbgeng at this moment - # but is something that should be considered in the future. - raise NotImplementedError('delete_conditional_breakpoint is not yet implemented by dbgeng') - def launch(self): # We are, by this point, already launched. self.step_info = probe_process.probe_state(self.client) diff --git a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py index c7bb74681d9fd5..a943431c888770 100644 --- a/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py +++ b/debuginfo-tests/dexter/dex/debugger/lldb/LLDB.py @@ -105,48 +105,9 @@ def clear_breakpoints(self): def add_breakpoint(self, file_, line): if not self._target.BreakpointCreateByLocation(file_, line): - raise DebuggerException( + raise LoadDebuggerException( 'could not add breakpoint [{}:{}]'.format(file_, line)) - def add_conditional_breakpoint(self, file_, line, condition): - bp = self._target.BreakpointCreateByLocation(file_, line) - if bp: - bp.SetCondition(condition) - else: - raise DebuggerException( - 'could not add breakpoint [{}:{}]'.format(file_, line)) - - def delete_conditional_breakpoint(self, file_, line, condition): - bp_count = self._target.GetNumBreakpoints() - bps = [self._target.GetBreakpointAtIndex(ix) for ix in range(0, bp_count)] - - for bp in bps: - bp_cond = bp.GetCondition() - bp_cond = bp_cond if bp_cond is not None else '' - - if bp_cond != condition: - continue - - # If one of the bound bp locations for this bp is bound to the same - # line in file_ above, then delete the entire parent bp and all - # bp locs. - # https://lldb.llvm.org/python_reference/lldb.SBBreakpoint-class.html - for breakpoint_location in bp: - sb_address = breakpoint_location.GetAddress() - - sb_line_entry = sb_address.GetLineEntry() - bl_line = sb_line_entry.GetLine() - - sb_file_entry = sb_line_entry.GetFileSpec() - bl_dir = sb_file_entry.GetDirectory() - bl_file_name = sb_file_entry.GetFilename() - - bl_file_path = os.path.join(bl_dir, bl_file_name) - - if bl_file_path == file_ and bl_line == line: - self._target.BreakpointDelete(bp.GetID()) - break - def launch(self): self._process = self._target.LaunchSimple(None, None, os.getcwd()) if not self._process or self._process.GetNumThreads() == 0: diff --git a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py index 40a902bd205991..b9816f84f72386 100644 --- a/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py +++ b/debuginfo-tests/dexter/dex/debugger/visualstudio/VisualStudio.py @@ -82,9 +82,6 @@ def _dte_version(self): @property def _location(self): - #TODO: Find a better way of determining path, line and column info - # that doesn't require reading break points. This method requires - # all lines to have a break point on them. bp = self._debugger.BreakpointLastHit return { 'path': getattr(bp, 'File', None), @@ -114,20 +111,8 @@ def clear_breakpoints(self): def add_breakpoint(self, file_, line): self._debugger.Breakpoints.Add('', file_, line) - def add_conditional_breakpoint(self, file_, line, condition): - column = 1 - self._debugger.Breakpoints.Add('', file_, line, column, condition) - - def delete_conditional_breakpoint(self, file_, line, condition): - for bp in self._debugger.Breakpoints: - for bound_bp in bp.Children: - if (bound_bp.File == file_ and bound_bp.FileLine == line and - bound_bp.Condition == condition): - bp.Delete() - break - def launch(self): - self._fn_go() + self.step() def step(self): self._fn_step() diff --git a/debuginfo-tests/dexter/dex/tools/test/Tool.py b/debuginfo-tests/dexter/dex/tools/test/Tool.py index 43191fd44bd5ef..a615c8cad90c38 100644 --- a/debuginfo-tests/dexter/dex/tools/test/Tool.py +++ b/debuginfo-tests/dexter/dex/tools/test/Tool.py @@ -16,7 +16,6 @@ from dex.command.ParseCommand import get_command_infos from dex.debugger.Debuggers import run_debugger_subprocess from dex.debugger.DebuggerControllers.DefaultController import DefaultController -from dex.debugger.DebuggerControllers.ConditionalController import ConditionalController from dex.dextIR.DextIR import DextIR from dex.heuristic import Heuristic from dex.tools import TestToolBase @@ -137,15 +136,9 @@ def _init_debugger_controller(self): executable_path=self.context.options.executable, source_paths=self.context.options.source_files, dexter_version=self.context.version) - step_collection.commands = get_command_infos( self.context.options.source_files) - - if 'DexLimitSteps' in step_collection.commands: - debugger_controller = ConditionalController(self.context, step_collection) - else: - debugger_controller = DefaultController(self.context, step_collection) - + debugger_controller = DefaultController(self.context, step_collection) return debugger_controller def _get_steps(self, builderIR): diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp deleted file mode 100644 index 45683fced2d0b4..00000000000000 --- a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_check_json_step_count.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Purpose: -// Check number of step lines are correctly reported in json output. -// -// REQUIRES: system-linux -// -// RUN: %dexter_regression_test --verbose -- %s | FileCheck %s -// CHECK: limit_steps_check_json_step_count.cpp -// CHECK: ## BEGIN ## -// CHECK-COUNT-3: json_step_count.cpp", - -int main() { - int result = 0; - for(int ix = 0; ix != 10; ++ix) { - int index = ix; - result += index; // DexLabel('check') - } -} - -// DexExpectWatchValue('index', 2, 7, 9, on_line='check') -// DexLimitSteps('ix', 2, 7, 9, on_line='check') diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp deleted file mode 100644 index 5946fa6ba46eb4..00000000000000 --- a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_loop.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// Purpose: -// Check the DexLimit steps only gathers step info for 2 iterations of a -// for loop. -// -// REQUIRES: system-linux -// -// RUN: %dexter_regression_test -- %s | FileCheck %s -// CHECK: limit_steps_expect_loop.cpp: - -int main(const int argc, const char * argv[]) { - unsigned int sum = 1; - for(unsigned int ix = 0; ix != 5; ++ix) { - unsigned thing_to_add = ix + ix - ix; // DexLabel('start') - sum += ix; // DexLabel('end') - } - return sum; -} - -// DexLimitSteps('ix', 0, 3, from_line='start', to_line='end') -// DexExpectWatchValue('ix', 0, 3, from_line='start', to_line='end') diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp deleted file mode 100644 index 2715e28d66bf4d..00000000000000 --- a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_expect_value.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// Purpose: -// Ensure that limited stepping breaks for all expected values. -// -// REQUIRES: system-linux -// -// RUN: %dexter_regression_test -- %s | FileCheck %s -// CHECK: limit_steps_expect_value.cpp - -int main() { - int i = 0; - i = 1; // DexLabel('from') - i = 2; - i = 3; - return 0; // DexLabel('long_range') -} - -// DexLimitSteps('i', '0', from_line='from', to_line='long_range') -// DexExpectWatchValue('i', 0, 1, 2, 3, from_line='from', to_line='long_range') diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp deleted file mode 100644 index 3200fe0979b3a1..00000000000000 --- a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_overlapping_ranges.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// Purpose: -// Ensure that multiple overlapping \DexLimitSteps ranges do not interfere. -// -// REQUIRES: system-linux -// -// RUN: %dexter_regression_test -- %s | FileCheck %s -// CHECK: limit_steps_overlapping_ranges.cpp - -int main() { - int val1; - int val2; - int placeholder; - for (int ix = 0; ix != 10; ++ix) { - placeholder=val1+val2; // DexLabel('from') - if (ix == 0) { - val1 = ix; - val2 = ix; // DexLabel('val1_check') - placeholder=val1+val2; // DexLabel('val1_check_to') - } - else if (ix == 2) { - val2 = ix; - val1 = ix; // DexLabel('val2_check') - placeholder=val1+val2; // DexLabel('val2_check_to') - } - placeholder=val1+val2; // DexLabel('to') - } - return val1 + val2; -} - -// DexExpectWatchValue('ix', 0, 2, 5, from_line='from', to_line='to') -// DexExpectWatchValue('val1', 0, from_line='val1_check', to_line='val1_check_to') -// DexExpectWatchValue('val2', 2, from_line='val2_check', to_line='val2_check_to') - -// DexLimitSteps('ix', 5, from_line='from', to_line='to') -// DexLimitSteps('val1', 0, from_line='val1_check', to_line='val1_check_to') -// DexLimitSteps('val2', 2, from_line='val2_check', to_line='val2_check_to') diff --git a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp b/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp deleted file mode 100644 index 060ff0d5fe7063..00000000000000 --- a/debuginfo-tests/dexter/feature_tests/commands/perfect/limit_steps/limit_steps_same_line_conditional.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// Purpose: -// Test that LimitStep commands can exist on the same from line. -// -// REQUIRES: system-linux -// -// RUN: %dexter_regression_test -- %s | FileCheck %s -// CHECK: limit_steps_same_line_conditional.cpp - -int main() { - int val1 = 0; - - int placeholder; - for(int ix = 0; ix != 4; ++ix) { - val1 = ix; - placeholder = ix; // DexLabel('from') - placeholder = ix; - val1 += 2; // DexLabel('to') - placeholder = ix; // DexLabel('extended_to') - } - return val1 + placeholder; -} - -// DexExpectWatchValue('val1', 0, 1, 3, from_line='from', to_line='extended_to') - -// DexLimitSteps('ix', 0, from_line='from', to_line='to') -// DexLimitSteps('ix', 1, from_line='from', to_line='extended_to') diff --git a/lldb/bindings/CMakeLists.txt b/lldb/bindings/CMakeLists.txt index ace34191a3c575..a2e51c263f7e6c 100644 --- a/lldb/bindings/CMakeLists.txt +++ b/lldb/bindings/CMakeLists.txt @@ -48,7 +48,7 @@ if (LLDB_ENABLE_PYTHON) -o ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapPython.cpp ${LLDB_SOURCE_DIR}/bindings/python.swig VERBATIM - COMMENT "Builds LLDB Python wrapper") + COMMENT "Building LLDB Python wrapper") add_custom_target(swig_wrapper ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapPython.cpp @@ -69,7 +69,7 @@ if (LLDB_ENABLE_LUA) -o ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapLua.cpp ${LLDB_SOURCE_DIR}/bindings/lua.swig VERBATIM - COMMENT "Builds LLDB Lua wrapper") + COMMENT "Building LLDB Lua wrapper") add_custom_target(swig_wrapper_lua ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/LLDBWrapLua.cpp diff --git a/lldb/source/Utility/Scalar.cpp b/lldb/source/Utility/Scalar.cpp index b6db5ccaebc46f..e55aa2d4d5a49b 100644 --- a/lldb/source/Utility/Scalar.cpp +++ b/lldb/source/Utility/Scalar.cpp @@ -331,7 +331,7 @@ Scalar &Scalar::operator=(unsigned long v) { Scalar &Scalar::operator=(long long v) { m_type = e_slonglong; - m_integer = llvm::APInt(sizeof(long) * 8, v, true); + m_integer = llvm::APInt(sizeof(long long) * 8, v, true); return *this; } diff --git a/lldb/test/API/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py b/lldb/test/API/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py index 59473a3f924ec3..6e19aa830cd3a9 100644 --- a/lldb/test/API/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py +++ b/lldb/test/API/linux/thread/create_during_instruction_step/TestCreateDuringInstructionStep.py @@ -18,7 +18,7 @@ class CreateDuringInstructionStepTestCase(TestBase): @skipUnlessPlatform(['linux']) @expectedFailureAndroid('llvm.org/pr24737', archs=['arm']) - @expectedFlakeyLinux(bugnumber="llvm.org/pr24737") + @skipIf(oslist=["linux"], archs=["arm"], bugnumber="llvm.org/pr24737") def test_step_inst(self): self.build(dictionary=self.getBuildFlags()) exe = self.getBuildArtifact("a.out") diff --git a/lldb/unittests/Utility/ScalarTest.cpp b/lldb/unittests/Utility/ScalarTest.cpp index f62173fb1401ae..baf1de98c121f1 100644 --- a/lldb/unittests/Utility/ScalarTest.cpp +++ b/lldb/unittests/Utility/ScalarTest.cpp @@ -188,6 +188,16 @@ TEST(ScalarTest, GetValue) { ScalarGetValue(std::numeric_limits::max())); } +TEST(ScalarTest, LongLongAssigmentOperator) { + Scalar ull; + ull = std::numeric_limits::max(); + EXPECT_EQ(std::numeric_limits::max(), ull.ULongLong()); + + Scalar sll; + sll = std::numeric_limits::max(); + EXPECT_EQ(std::numeric_limits::max(), sll.SLongLong()); +} + TEST(ScalarTest, Division) { Scalar lhs(5.0); Scalar rhs(2.0); diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 7e1991c866eb8f..249b662be2a19a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2195,9 +2195,7 @@ SDValue SelectionDAG::GetDemandedBits(SDValue V, const APInt &DemandedBits, *this, 0); break; case ISD::Constant: { - auto *CV = cast(V.getNode()); - assert(CV && "Const value should be ConstSDNode."); - const APInt &CVal = CV->getAPIntValue(); + const APInt &CVal = cast(V)->getAPIntValue(); APInt NewVal = CVal & DemandedBits; if (NewVal != CVal) return getConstant(NewVal, SDLoc(V), V.getValueType()); diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index fc0154d414fb3b..9c317e3f8840f4 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -238,7 +238,7 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, case FK_Data_8: return IsPCRel ? setRTypes(ELF::R_MIPS_PC32, ELF::R_MIPS_64, ELF::R_MIPS_NONE) - : ELF::R_MIPS_64; + : (unsigned)ELF::R_MIPS_64; } if (IsPCRel) { diff --git a/llvm/lib/Target/VE/CMakeLists.txt b/llvm/lib/Target/VE/CMakeLists.txt index 4b9169da63c061..b37d00929cf440 100644 --- a/llvm/lib/Target/VE/CMakeLists.txt +++ b/llvm/lib/Target/VE/CMakeLists.txt @@ -2,6 +2,7 @@ set(LLVM_TARGET_DEFINITIONS VE.td) tablegen(LLVM VEGenRegisterInfo.inc -gen-register-info) tablegen(LLVM VEGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM VEGenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM VEGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM VEGenAsmWriter.inc -gen-asm-writer) tablegen(LLVM VEGenAsmMatcher.inc -gen-asm-matcher) @@ -24,5 +25,6 @@ add_llvm_target(VECodeGen ) add_subdirectory(AsmParser) +add_subdirectory(Disassembler) add_subdirectory(TargetInfo) add_subdirectory(MCTargetDesc) diff --git a/llvm/lib/Target/VE/Disassembler/CMakeLists.txt b/llvm/lib/Target/VE/Disassembler/CMakeLists.txt new file mode 100644 index 00000000000000..af1097d7912b72 --- /dev/null +++ b/llvm/lib/Target/VE/Disassembler/CMakeLists.txt @@ -0,0 +1,3 @@ +add_llvm_component_library(LLVMVEDisassembler + VEDisassembler.cpp + ) diff --git a/llvm/lib/Target/VE/Disassembler/LLVMBuild.txt b/llvm/lib/Target/VE/Disassembler/LLVMBuild.txt new file mode 100644 index 00000000000000..d1b581bb89310e --- /dev/null +++ b/llvm/lib/Target/VE/Disassembler/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./lib/Target/VE/Disassembler/LLVMBuild.txt ---------------*- Conf -*--===; +; +; Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +; See https://llvm.org/LICENSE.txt for license information. +; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = VEDisassembler +parent = VE +required_libraries = MCDisassembler VEInfo Support +add_to_library_groups = VE diff --git a/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp new file mode 100644 index 00000000000000..fbece1d758fca6 --- /dev/null +++ b/llvm/lib/Target/VE/Disassembler/VEDisassembler.cpp @@ -0,0 +1,280 @@ +//===- VEDisassembler.cpp - Disassembler for VE -----------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is part of the VE Disassembler. +// +//===----------------------------------------------------------------------===// + +#include "MCTargetDesc/VEMCTargetDesc.h" +#include "TargetInfo/VETargetInfo.h" +#include "VE.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCContext.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" +#include "llvm/MC/MCFixedLenDisassembler.h" +#include "llvm/MC/MCInst.h" +#include "llvm/Support/TargetRegistry.h" + +using namespace llvm; + +#define DEBUG_TYPE "ve-disassembler" + +typedef MCDisassembler::DecodeStatus DecodeStatus; + +namespace { + +/// A disassembler class for VE. +class VEDisassembler : public MCDisassembler { +public: + VEDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) + : MCDisassembler(STI, Ctx) {} + virtual ~VEDisassembler() {} + + DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, uint64_t Address, + raw_ostream &CStream) const override; +}; +} // namespace + +static MCDisassembler *createVEDisassembler(const Target &T, + const MCSubtargetInfo &STI, + MCContext &Ctx) { + return new VEDisassembler(STI, Ctx); +} + +extern "C" void LLVMInitializeVEDisassembler() { + // Register the disassembler. + TargetRegistry::RegisterMCDisassembler(getTheVETarget(), + createVEDisassembler); +} + +static const unsigned I32RegDecoderTable[] = { + VE::SW0, VE::SW1, VE::SW2, VE::SW3, VE::SW4, VE::SW5, VE::SW6, + VE::SW7, VE::SW8, VE::SW9, VE::SW10, VE::SW11, VE::SW12, VE::SW13, + VE::SW14, VE::SW15, VE::SW16, VE::SW17, VE::SW18, VE::SW19, VE::SW20, + VE::SW21, VE::SW22, VE::SW23, VE::SW24, VE::SW25, VE::SW26, VE::SW27, + VE::SW28, VE::SW29, VE::SW30, VE::SW31, VE::SW32, VE::SW33, VE::SW34, + VE::SW35, VE::SW36, VE::SW37, VE::SW38, VE::SW39, VE::SW40, VE::SW41, + VE::SW42, VE::SW43, VE::SW44, VE::SW45, VE::SW46, VE::SW47, VE::SW48, + VE::SW49, VE::SW50, VE::SW51, VE::SW52, VE::SW53, VE::SW54, VE::SW55, + VE::SW56, VE::SW57, VE::SW58, VE::SW59, VE::SW60, VE::SW61, VE::SW62, + VE::SW63}; + +static const unsigned I64RegDecoderTable[] = { + VE::SX0, VE::SX1, VE::SX2, VE::SX3, VE::SX4, VE::SX5, VE::SX6, + VE::SX7, VE::SX8, VE::SX9, VE::SX10, VE::SX11, VE::SX12, VE::SX13, + VE::SX14, VE::SX15, VE::SX16, VE::SX17, VE::SX18, VE::SX19, VE::SX20, + VE::SX21, VE::SX22, VE::SX23, VE::SX24, VE::SX25, VE::SX26, VE::SX27, + VE::SX28, VE::SX29, VE::SX30, VE::SX31, VE::SX32, VE::SX33, VE::SX34, + VE::SX35, VE::SX36, VE::SX37, VE::SX38, VE::SX39, VE::SX40, VE::SX41, + VE::SX42, VE::SX43, VE::SX44, VE::SX45, VE::SX46, VE::SX47, VE::SX48, + VE::SX49, VE::SX50, VE::SX51, VE::SX52, VE::SX53, VE::SX54, VE::SX55, + VE::SX56, VE::SX57, VE::SX58, VE::SX59, VE::SX60, VE::SX61, VE::SX62, + VE::SX63}; + +static const unsigned F32RegDecoderTable[] = { + VE::SF0, VE::SF1, VE::SF2, VE::SF3, VE::SF4, VE::SF5, VE::SF6, + VE::SF7, VE::SF8, VE::SF9, VE::SF10, VE::SF11, VE::SF12, VE::SF13, + VE::SF14, VE::SF15, VE::SF16, VE::SF17, VE::SF18, VE::SF19, VE::SF20, + VE::SF21, VE::SF22, VE::SF23, VE::SF24, VE::SF25, VE::SF26, VE::SF27, + VE::SF28, VE::SF29, VE::SF30, VE::SF31, VE::SF32, VE::SF33, VE::SF34, + VE::SF35, VE::SF36, VE::SF37, VE::SF38, VE::SF39, VE::SF40, VE::SF41, + VE::SF42, VE::SF43, VE::SF44, VE::SF45, VE::SF46, VE::SF47, VE::SF48, + VE::SF49, VE::SF50, VE::SF51, VE::SF52, VE::SF53, VE::SF54, VE::SF55, + VE::SF56, VE::SF57, VE::SF58, VE::SF59, VE::SF60, VE::SF61, VE::SF62, + VE::SF63}; + +static DecodeStatus DecodeI32RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 63) + return MCDisassembler::Fail; + unsigned Reg = I32RegDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeI64RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 63) + return MCDisassembler::Fail; + unsigned Reg = I64RegDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeF32RegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 63) + return MCDisassembler::Fail; + unsigned Reg = F32RegDecoderTable[RegNo]; + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeLoadI32(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeStoreI32(MCInst &Inst, uint64_t insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeLoadI64(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeStoreI64(MCInst &Inst, uint64_t insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeLoadF32(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder); +static DecodeStatus DecodeStoreF32(MCInst &Inst, uint64_t insn, + uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSIMM7(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder); + +#include "VEGenDisassemblerTables.inc" + +/// Read four bytes from the ArrayRef and return 32 bit word. +static DecodeStatus readInstruction64(ArrayRef Bytes, uint64_t Address, + uint64_t &Size, uint64_t &Insn, + bool IsLittleEndian) { + // We want to read exactly 8 Bytes of data. + if (Bytes.size() < 8) { + Size = 0; + return MCDisassembler::Fail; + } + + Insn = IsLittleEndian + ? ((uint64_t)Bytes[0] << 0) | ((uint64_t)Bytes[1] << 8) | + ((uint64_t)Bytes[2] << 16) | ((uint64_t)Bytes[3] << 24) | + ((uint64_t)Bytes[4] << 32) | ((uint64_t)Bytes[5] << 40) | + ((uint64_t)Bytes[6] << 48) | ((uint64_t)Bytes[7] << 56) + : ((uint64_t)Bytes[7] << 0) | ((uint64_t)Bytes[6] << 8) | + ((uint64_t)Bytes[5] << 16) | ((uint64_t)Bytes[4] << 24) | + ((uint64_t)Bytes[3] << 32) | ((uint64_t)Bytes[2] << 40) | + ((uint64_t)Bytes[1] << 48) | ((uint64_t)Bytes[0] << 56); + + return MCDisassembler::Success; +} + +DecodeStatus VEDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, + ArrayRef Bytes, + uint64_t Address, + raw_ostream &CStream) const { + uint64_t Insn; + bool isLittleEndian = getContext().getAsmInfo()->isLittleEndian(); + DecodeStatus Result = + readInstruction64(Bytes, Address, Size, Insn, isLittleEndian); + if (Result == MCDisassembler::Fail) + return MCDisassembler::Fail; + + // Calling the auto-generated decoder function. + + Result = decodeInstruction(DecoderTableVE64, Instr, Insn, Address, this, STI); + + if (Result != MCDisassembler::Fail) { + Size = 8; + return Result; + } + + return MCDisassembler::Fail; +} + +typedef DecodeStatus (*DecodeFunc)(MCInst &MI, unsigned RegNo, uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeASX(MCInst &MI, uint64_t insn, uint64_t Address, + const void *Decoder) { + unsigned sy = fieldFromInstruction(insn, 40, 7); + bool cy = fieldFromInstruction(insn, 47, 1); + unsigned sz = fieldFromInstruction(insn, 32, 7); + bool cz = fieldFromInstruction(insn, 39, 1); + uint64_t simm32 = SignExtend64<32>(fieldFromInstruction(insn, 0, 32)); + DecodeStatus status; + + // Decode sz. + if (cz) { + status = DecodeI64RegisterClass(MI, sz, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } else { + MI.addOperand(MCOperand::createImm(0)); + } + + // Decode sy. + if (cy) { + status = DecodeI64RegisterClass(MI, sy, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } else { + MI.addOperand(MCOperand::createImm(SignExtend32<7>(sy))); + } + + // Decode simm32. + MI.addOperand(MCOperand::createImm(simm32)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMem(MCInst &MI, uint64_t insn, uint64_t Address, + const void *Decoder, bool isLoad, + DecodeFunc DecodeSX) { + unsigned sx = fieldFromInstruction(insn, 48, 7); + + DecodeStatus status; + if (isLoad) { + status = DecodeSX(MI, sx, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } + + status = DecodeASX(MI, insn, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + + if (!isLoad) { + status = DecodeSX(MI, sx, Address, Decoder); + if (status != MCDisassembler::Success) + return status; + } + return MCDisassembler::Success; +} + +static DecodeStatus DecodeLoadI32(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, DecodeI32RegisterClass); +} + +static DecodeStatus DecodeStoreI32(MCInst &Inst, uint64_t insn, + uint64_t Address, const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, DecodeI32RegisterClass); +} + +static DecodeStatus DecodeLoadI64(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, DecodeI64RegisterClass); +} + +static DecodeStatus DecodeStoreI64(MCInst &Inst, uint64_t insn, + uint64_t Address, const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, DecodeI64RegisterClass); +} + +static DecodeStatus DecodeLoadF32(MCInst &Inst, uint64_t insn, uint64_t Address, + const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, true, DecodeF32RegisterClass); +} + +static DecodeStatus DecodeStoreF32(MCInst &Inst, uint64_t insn, + uint64_t Address, const void *Decoder) { + return DecodeMem(Inst, insn, Address, Decoder, false, DecodeF32RegisterClass); +} + +static DecodeStatus DecodeSIMM7(MCInst &MI, uint64_t insn, uint64_t Address, + const void *Decoder) { + uint64_t tgt = SignExtend64<7>(insn); + MI.addOperand(MCOperand::createImm(tgt)); + return MCDisassembler::Success; +} diff --git a/llvm/lib/Target/VE/LLVMBuild.txt b/llvm/lib/Target/VE/LLVMBuild.txt index f3169930771cf1..768caf0a2a17fb 100644 --- a/llvm/lib/Target/VE/LLVMBuild.txt +++ b/llvm/lib/Target/VE/LLVMBuild.txt @@ -15,7 +15,7 @@ ;===------------------------------------------------------------------------===; [common] -subdirectories = AsmParser MCTargetDesc TargetInfo +subdirectories = AsmParser Disassembler MCTargetDesc TargetInfo [component_0] type = TargetGroup @@ -23,6 +23,7 @@ name = VE parent = Target has_asmparser = 1 has_asmprinter = 1 +has_disassembler = 1 [component_1] type = Library diff --git a/llvm/lib/Target/VE/VEInstrInfo.td b/llvm/lib/Target/VE/VEInstrInfo.td index 0a37e52e0240e1..07aec99bac58ee 100644 --- a/llvm/lib/Target/VE/VEInstrInfo.td +++ b/llvm/lib/Target/VE/VEInstrInfo.td @@ -661,14 +661,13 @@ multiclass BCtgm opc, dag cond> { } multiclass BCm opc, RegisterClass RC, Operand immOp> { - let DecoderMethod = "DecodeBranchCondition" in defm r : BCtgm; - let DecoderMethod = "DecodeBranchCondition", cy = 0 in + let cy = 0 in defm i : BCtgm; - let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0, + let cy = 0, sy = 0, cf = 15 /* AT */, isBarrier = 1 in defm a : BCtgm; - let DecoderMethod = "DecodeBranchConditionAlways", cy = 0, sy = 0, + let cy = 0, sy = 0, cf = 0 /* AF */ in defm na : BCtgm; } @@ -793,15 +792,15 @@ let cx = 1, DecoderMethod = "DecodeLoadI32" in defm LDLZX : LOADm<"ldl.zx", 0x03, I32, i32, load>; // Section 8.2.5 - LD2B -let DecoderMethod = "DecodeLoadI16" in +let DecoderMethod = "DecodeLoadI32" in defm LD2BSX : LOADm<"ld2b.sx", 0x04, I32, i32, sextloadi16>; -let cx = 1, DecoderMethod = "DecodeLoadI16" in +let cx = 1, DecoderMethod = "DecodeLoadI32" in defm LD2BZX : LOADm<"ld2b.zx", 0x04, I32, i32, zextloadi16>; // Section 8.2.6 - LD1B -let DecoderMethod = "DecodeLoadI8" in +let DecoderMethod = "DecodeLoadI32" in defm LD1BSX : LOADm<"ld1b.sx", 0x05, I32, i32, sextloadi8>; -let cx = 1, DecoderMethod = "DecodeLoadI8" in +let cx = 1, DecoderMethod = "DecodeLoadI32" in defm LD1BZX : LOADm<"ld1b.zx", 0x05, I32, i32, zextloadi8>; // Multiclass for store instructions. @@ -842,11 +841,11 @@ let DecoderMethod = "DecodeStoreI32" in defm STL : STOREm<"stl", 0x13, I32, i32, store>; // Section 8.2.10 - ST2B -let DecoderMethod = "DecodeStoreI16" in +let DecoderMethod = "DecodeStoreI32" in defm ST2B : STOREm<"st2b", 0x14, I32, i32, truncstorei16>; // Section 8.2.11 - ST1B -let DecoderMethod = "DecodeStoreI8" in +let DecoderMethod = "DecodeStoreI32" in defm ST1B : STOREm<"st1b", 0x15, I32, i32, truncstorei8>; // Section 8.2.12 - DLDS @@ -1110,7 +1109,7 @@ let cx = 1, cx2 = 1 in defm BRCFS : BCRm<"br${cf}.s", "br.s", "braf.s", 0x18, F32, simm7fp>; // Section 8.8.5 - BSIC (Branch and Save IC) -let isCall = 1, hasSideEffects = 0, DecoderMethod = "DecodeCall" in +let isCall = 1, hasSideEffects = 0 in defm BSIC : RMm<"bsic", 0x08, I64>; // Call instruction is a special case of BSIC. diff --git a/llvm/lib/Transforms/Vectorize/VPlan.h b/llvm/lib/Transforms/Vectorize/VPlan.h index 1d07d5cff8a382..c3097e1e1f14f3 100644 --- a/llvm/lib/Transforms/Vectorize/VPlan.h +++ b/llvm/lib/Transforms/Vectorize/VPlan.h @@ -270,10 +270,20 @@ struct VPTransformState { return Callback.getOrCreateVectorValues(VPValue2Value[Def], Part); } - /// Get the generated Value for a given VPValue and given Part and Lane. Note - /// that as per-lane Defs are still created by ILV and managed in its ValueMap - /// this method currently just delegates the call to ILV. + /// Get the generated Value for a given VPValue and given Part and Lane. Value *get(VPValue *Def, const VPIteration &Instance) { + // If the Def is managed directly by VPTransformState, extract the lane from + // the relevant part. Note that currently only VPInstructions and external + // defs are managed by VPTransformState. Other Defs are still created by ILV + // and managed in its ValueMap. For those this method currently just + // delegates the call to ILV below. + if (Data.PerPartOutput.count(Def)) { + auto *VecPart = Data.PerPartOutput[Def][Instance.Part]; + // TODO: Cache created scalar values. + return Builder.CreateExtractElement(VecPart, + Builder.getInt32(Instance.Lane)); + } + return Callback.getOrCreateScalarValue(VPValue2Value[Def], Instance); } diff --git a/llvm/test/MC/VE/LD.s b/llvm/test/MC/VE/LD.s index 8f18a489db9367..94e2865a342a3d 100644 --- a/llvm/test/MC/VE/LD.s +++ b/llvm/test/MC/VE/LD.s @@ -1,45 +1,48 @@ -# RUN: llvm-mc -triple ve-unknown-unknown --show-encoding %s | FileCheck %s +# RUN: llvm-mc -triple=ve --show-encoding < %s \ +# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \ +# RUN: | FileCheck %s --check-prefixes=CHECK-INST -# CHECK: ld %s11, 8199 -# CHECK: encoding: [0x07,0x20,0x00,0x00,0x00,0x00,0x0b,0x01] +# CHECK-INST: ld %s11, 8199 +# CHECK-ENCODING: encoding: [0x07,0x20,0x00,0x00,0x00,0x00,0x0b,0x01] ld %s11, 8199 -# CHECK: ld %s11, 20(%s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x00,0x8b,0x0b,0x01] +# CHECK-INST: ld %s11, 20(%s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x00,0x8b,0x0b,0x01] ld %s11, 20(%s11) -# CHECK: ld %s11, -1(, %s11) -# CHECK: encoding: [0xff,0xff,0xff,0xff,0x8b,0x00,0x0b,0x01] +# CHECK-INST: ld %s11, -1(, %s11) +# CHECK-ENCODING: encoding: [0xff,0xff,0xff,0xff,0x8b,0x00,0x0b,0x01] ld %s11, -1(, %s11) -# CHECK: ld %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x01] +# CHECK-INST: ld %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x01] ld %s11, 20(%s10, %s11) -# CHECK: ldu %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x02] +# CHECK-INST: ldu %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x02] ldu %s11, 20(%s10, %s11) -# CHECK: ldl.sx %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x03] +# CHECK-INST: ldl.sx %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x03] ldl.sx %s11, 20(%s10, %s11) -# CHECK: ldl.zx %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x8b,0x03] +# CHECK-INST: ldl.zx %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x8b,0x03] ldl.zx %s11, 20(%s10, %s11) -# CHECK: ld2b.sx %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x04] +# CHECK-INST: ld2b.sx %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x04] ld2b.sx %s11, 20(%s10, %s11) -# CHECK: ld2b.zx %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x8b,0x04] +# CHECK-INST: ld2b.zx %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x8b,0x04] ld2b.zx %s11, 20(%s10, %s11) -# CHECK: ld1b.sx %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x05] +# CHECK-INST: ld1b.sx %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x05] ld1b.sx %s11, 20(%s10, %s11) -# CHECK: ld1b.zx %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x8b,0x05] +# CHECK-INST: ld1b.zx %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x8b,0x05] ld1b.zx %s11, 20(%s10, %s11) diff --git a/llvm/test/MC/VE/LEA.s b/llvm/test/MC/VE/LEA.s index fca99d59f57c03..15a26ce4c62b2f 100644 --- a/llvm/test/MC/VE/LEA.s +++ b/llvm/test/MC/VE/LEA.s @@ -1,29 +1,36 @@ -# RUN: llvm-mc -triple ve-unknown-unknown --show-encoding %s | FileCheck %s +# RUN: llvm-mc -triple=ve --show-encoding < %s \ +# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \ +# RUN: | FileCheck %s --check-prefixes=CHECK-INST -# CHECK: lea %s11, 23 -# CHECK: encoding: [0x17,0x00,0x00,0x00,0x00,0x00,0x0b,0x06] +# CHECK-INST: lea %s11, 23 +# CHECK-ENCODING: encoding: [0x17,0x00,0x00,0x00,0x00,0x00,0x0b,0x06] lea %s11, 23 -# CHECK: lea %s63, 324(, %s11) -# CHECK: encoding: [0x44,0x01,0x00,0x00,0x8b,0x00,0x3f,0x06] +# CHECK-INST: lea %s63, 324(, %s11) +# CHECK-ENCODING: encoding: [0x44,0x01,0x00,0x00,0x8b,0x00,0x3f,0x06] lea %s63, 324(,%s11) -# CHECK: lea %s11, 324(%s10) -# CHECK: encoding: [0x44,0x01,0x00,0x00,0x00,0x8a,0x0b,0x06] +# CHECK-INST: lea %s11, 324(%s10) +# CHECK-ENCODING: encoding: [0x44,0x01,0x00,0x00,0x00,0x8a,0x0b,0x06] lea %s11, 324(%s10 ) -# CHECK: lea %s11, 324(%s13, %s11) -# CHECK: encoding: [0x44,0x01,0x00,0x00,0x8b,0x8d,0x0b,0x06] +# CHECK-INST: lea %s11, 324(%s13, %s11) +# CHECK-ENCODING: encoding: [0x44,0x01,0x00,0x00,0x8b,0x8d,0x0b,0x06] lea %s11, 324 (%s13,%s11) -# CHECK: lea %s11, (%s10) -# CHECK: encoding: [0x00,0x00,0x00,0x00,0x00,0x8a,0x0b,0x06] +# CHECK-INST: lea %s11, (%s10) +# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x00,0x8a,0x0b,0x06] lea %s11, (%s10) -# CHECK: lea %s11, (, %s12) -# CHECK: encoding: [0x00,0x00,0x00,0x00,0x8c,0x00,0x0b,0x06] +# CHECK-INST: lea %s11, (, %s12) +# CHECK-ENCODING: encoding: [0x00,0x00,0x00,0x00,0x8c,0x00,0x0b,0x06] lea %s11, (,%s12) -# CHECK: lea.sl %s11, -1(%s13, %s11) -# CHECK: encoding: [0xff,0xff,0xff,0xff,0x8b,0x8d,0x8b,0x06] +# CHECK-INST: lea.sl %s11, -1(%s13, %s11) +# CHECK-ENCODING: encoding: [0xff,0xff,0xff,0xff,0x8b,0x8d,0x8b,0x06] lea.sl %s11, -1(%s13, %s11) + +# CHECK-INST: lea.sl %s11, -1(-64, %s11) +# CHECK-ENCODING: encoding: [0xff,0xff,0xff,0xff,0x8b,0x40,0x8b,0x06] +lea.sl %s11, -1(-64, %s11) diff --git a/llvm/test/MC/VE/ST.s b/llvm/test/MC/VE/ST.s index 33ac5024868a62..e005aa97ed9466 100644 --- a/llvm/test/MC/VE/ST.s +++ b/llvm/test/MC/VE/ST.s @@ -1,33 +1,36 @@ -# RUN: llvm-mc -triple ve-unknown-unknown --show-encoding %s | FileCheck %s +# RUN: llvm-mc -triple=ve --show-encoding < %s \ +# RUN: | FileCheck %s --check-prefixes=CHECK-ENCODING,CHECK-INST +# RUN: llvm-mc -triple=ve -filetype=obj < %s | llvm-objdump -d - \ +# RUN: | FileCheck %s --check-prefixes=CHECK-INST -# CHECK: st %s11, 32767 -# CHECK: encoding: [0xff,0x7f,0x00,0x00,0x00,0x00,0x0b,0x11] +# CHECK-INST: st %s11, 32767 +# CHECK-ENCODING: encoding: [0xff,0x7f,0x00,0x00,0x00,0x00,0x0b,0x11] st %s11, 32767 -# CHECK: st %s11, 20(%s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x00,0x8b,0x0b,0x11] +# CHECK-INST: st %s11, 20(%s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x00,0x8b,0x0b,0x11] st %s11, 20(%s11) -# CHECK: st %s11, -1(, %s11) -# CHECK: encoding: [0xff,0xff,0xff,0xff,0x8b,0x00,0x0b,0x11] +# CHECK-INST: st %s11, -1(, %s11) +# CHECK-ENCODING: encoding: [0xff,0xff,0xff,0xff,0x8b,0x00,0x0b,0x11] st %s11, -1(, %s11) -# CHECK: st %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x11] +# CHECK-INST: st %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x11] st %s11, 20(%s10, %s11) -# CHECK: stu %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x12] +# CHECK-INST: stu %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x12] stu %s11, 20(%s10, %s11) -# CHECK: stl %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x13] +# CHECK-INST: stl %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x13] stl %s11, 20(%s10, %s11) -# CHECK: st2b %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x14] +# CHECK-INST: st2b %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x14] st2b %s11, 20(%s10, %s11) -# CHECK: st1b %s11, 20(%s10, %s11) -# CHECK: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x15] +# CHECK-INST: st1b %s11, 20(%s10, %s11) +# CHECK-ENCODING: encoding: [0x14,0x00,0x00,0x00,0x8b,0x8a,0x0b,0x15] st1b %s11, 20(%s10, %s11) diff --git a/llvm/test/Transforms/InstCombine/or-xor.ll b/llvm/test/Transforms/InstCombine/or-xor.ll index 4663d196a281a9..6ee5999d1a363d 100644 --- a/llvm/test/Transforms/InstCombine/or-xor.ll +++ b/llvm/test/Transforms/InstCombine/or-xor.ll @@ -59,26 +59,6 @@ define i32 @test4(i32 %x, i32 %y) { ret i32 %z } -define i32 @test5(i32 %x, i32 %y) { -; CHECK-LABEL: @test5( -; CHECK-NEXT: ret i32 -1 -; - %and = and i32 %x, %y - %not = xor i32 %and, -1 - %z = or i32 %x, %not - ret i32 %z -} - -define i32 @test6(i32 %x, i32 %y) { -; CHECK-LABEL: @test6( -; CHECK-NEXT: ret i32 -1 -; - %and = and i32 %x, %y - %not = xor i32 %and, -1 - %z = or i32 %y, %not - ret i32 %z -} - define i32 @test7(i32 %x, i32 %y) { ; CHECK-LABEL: @test7( ; CHECK-NEXT: [[Z:%.*]] = or i32 [[X:%.*]], [[Y:%.*]] diff --git a/llvm/test/Transforms/InstSimplify/or.ll b/llvm/test/Transforms/InstSimplify/or.ll index 465b30c9cf948b..619c8eba554aac 100644 --- a/llvm/test/Transforms/InstSimplify/or.ll +++ b/llvm/test/Transforms/InstSimplify/or.ll @@ -243,3 +243,57 @@ define <2 x i399> @test8_apint(<2 x i399> %V, <2 x i399> %M) { %R = or <2 x i399> %D, %B ret <2 x i399> %R } + +; A | ~(A & B) = -1 + +define i1 @or_with_not_op_commute1(i1 %a, i1 %b) { +; CHECK-LABEL: @or_with_not_op_commute1( +; CHECK-NEXT: [[AB:%.*]] = and i1 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i1 [[AB]], true +; CHECK-NEXT: [[R:%.*]] = or i1 [[A]], [[NOT]] +; CHECK-NEXT: ret i1 [[R]] +; + %ab = and i1 %a, %b + %not = xor i1 %ab, -1 + %r = or i1 %a, %not + ret i1 %r +} + +; A | ~(B & A) = -1 + +define i8 @or_with_not_op_commute2(i8 %a, i8 %b) { +; CHECK-LABEL: @or_with_not_op_commute2( +; CHECK-NEXT: [[AB:%.*]] = and i8 [[B:%.*]], [[A:%.*]] +; CHECK-NEXT: [[NOT:%.*]] = xor i8 [[AB]], -1 +; CHECK-NEXT: [[R:%.*]] = or i8 [[A]], [[NOT]] +; CHECK-NEXT: ret i8 [[R]] +; + %ab = and i8 %b, %a + %not = xor i8 %ab, -1 + %r = or i8 %a, %not + ret i8 %r +} + +; ~(A & B) | A = -1 + +define <3 x i17> @or_with_not_op_commute3(<3 x i17> %a, <3 x i17> %b) { +; CHECK-LABEL: @or_with_not_op_commute3( +; CHECK-NEXT: ret <3 x i17> +; + %ab = and <3 x i17> %a, %b + %not = xor <3 x i17> %ab, + %r = or <3 x i17> %not, %a + ret <3 x i17> %r +} + +; ~(B & A) | A = -1 + +define <2 x i1> @or_with_not_op_commute4(<2 x i1> %a, <2 x i1> %b) { +; CHECK-LABEL: @or_with_not_op_commute4( +; CHECK-NEXT: ret <2 x i1> +; + %ab = and <2 x i1> %b, %a + %not = xor <2 x i1> %ab, + %r = or <2 x i1> %not, %a + ret <2 x i1> %r +}