Skip to content

Commit

Permalink
Disallow repeated variables in transformations
Browse files Browse the repository at this point in the history
To make it more explicit what is happening, no longer allow
patterns such as:

    move R R => _

This transformation must now be written:

    move R1 R2 | equal(R1, R2) => _
  • Loading branch information
bjorng committed Feb 3, 2022
1 parent 07eb228 commit 9751032
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 28 deletions.
16 changes: 0 additions & 16 deletions erts/emulator/beam/beam_transform_engine.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,22 +128,6 @@ erts_transform_engine(LoaderState* st)
ap++;
break;
#endif
#if defined(TOP_is_same_var)
case TOP_is_same_var:
ASSERT(ap < instr->arity);
i = *pc++;
ASSERT(i < TE_MAX_VARS);
if (var[i].type != instr->a[ap].type)
goto restart;
switch (var[i].type) {
case TAG_n:
break;
default:
if (var[i].val != instr->a[ap].val)
goto restart;
}
break;
#endif
#if defined(TOP_is_bif)
case TOP_is_bif:
{
Expand Down
35 changes: 23 additions & 12 deletions erts/emulator/utils/beam_makeops
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ my $code_pointers_are_short = 0; # Whether code pointers (to C code) are short.
my $code_model = 'unknown';
my $jit = 'no';
my %defs; # Defines (from command line).
my $pending_errors = 0; # Number of pending errors.

# Intentionally unused macros, predicates, and generators.
my %intentionally_unused;
Expand Down Expand Up @@ -600,7 +601,6 @@ $num_file_opcodes = @gen_opname;
# or use forbidden types.
#

my $any_errors;
foreach my $key (keys %specific_op) {
my($arity) = (split('/', $key))[1];
my @specific_ops = @{$specific_op{$key}};
Expand All @@ -625,24 +625,28 @@ foreach my $key (keys %specific_op) {
my $cleaned_arg = $arg;
$cleaned_arg =~ s/[?]$//;
if ($jit ne 'no' and $cleaned_arg eq 'r') {
warn "specific instruction '$name @args' uses type 'r' which is is not supported for BeamAsm\n";
$any_errors = 1;
pending_error("specific instruction '$name @args' uses type " .
"'r' which is is not supported for BeamAsm");
} elsif ($forbidden_type{$cleaned_arg}) {
warn "specific instruction '$name @args' uses forbidden type '$arg'\n";
$any_errors = 1;
pending_error("specific instruction '$name @args' uses " .
"forbidden type '$arg'\n");
}
}
}
}

error("there were previous type errors") if $any_errors;
error("beam_makeops: terminating because there were previous errors")
if $pending_errors > 0;

#
# Produce output for the chosen target.
#

&$target();

error("beam_makeops: terminating because there were previous errors")
if $pending_errors > 0;

#
# Ensure that all C code implementations have been used.
#
Expand Down Expand Up @@ -1289,6 +1293,13 @@ sub parse_c_args {
@res;
}

sub pending_error {
my(@message) = @_;
my($where) = $. ? "$ARGV($.): " : "";
$pending_errors++;
warn $where, @message, "\n";
}

sub error {
my(@message) = @_;
my($where) = $. ? "$ARGV($.): " : "";
Expand Down Expand Up @@ -2760,14 +2771,14 @@ sub tr_gen_from {

if ($var ne '') {
if (defined $var{$var}) {
$ignored_var = '';
$may_fail = 1;
my $op = make_op($var, 'is_same_var', $var{$var});
op_slot_usage($op, $var{$var});
push(@code, $op);
my $msg = "variable $var used more than once\n" .
" (repeated variables in matching is not supported;\n" .
" use the predicate equal(Var1, Var2) " .
"to compare variables)";
pending_error($where, $msg);
} elsif ($type eq '*') {
foreach my $type (values %var_type) {
error("only one use of a '*' variable is " .
error($where, "only one use of a '*' variable is " .
"allowed on the left hand side of " .
"a transformation")
if $type eq 'array';
Expand Down

0 comments on commit 9751032

Please sign in to comment.