diff --git a/build/Makefile.in b/build/Makefile.in index 2b67f6377e..012e68e7be 100644 --- a/build/Makefile.in +++ b/build/Makefile.in @@ -626,7 +626,9 @@ src/jit/x64/emit@obj@: src/jit/x64/emit.c $(DYNASM_HEADERS) src/jit/x64/emit.c: src/jit/x64/emit.dasc src/jit/x64/tiles.dasc $(MINILUA) $(DYNASM_SCRIPTS) # Expression list tables -src/jit/core_templates.h: src/jit/core_templates.expr src/jit/macro.expr tools/expr-template-compiler.pl src/core/oplist src/jit/expr_ops.h +src/jit/core_templates.h: src/jit/core_templates.expr src/jit/macro.expr \ + tools/expr-template-compiler.pl tools/sexpr.pm tools/expr_ops.pm tools/oplist.pm \ + src/core/oplist src/jit/expr_ops.h # Architecture-specific tiles src/jit/x64/tile_pattern.h: src/jit/x64/tile_pattern.tile tools/tiler-table-generator.pl src/jit/expr_ops.h diff --git a/src/jit/expr.c b/src/jit/expr.c index 6bb255a6b4..575068922f 100644 --- a/src/jit/expr.c +++ b/src/jit/expr.c @@ -331,7 +331,7 @@ static void check_template(MVMThreadContext *tc, const MVMJitExprTemplate *templ if (template->code[i] < 0 || (template->code[i] >= ins->info->num_operands && !ins_has_single_input_output_operand(ins))) - MVM_oops(tc, "JIT: Operand access out of bounds (instruction: %s)", ins->info->name); + MVM_oops(tc, "JIT: Operand access (%d) out of bounds (instruction: %s)", template->code[i], ins->info->name); break; default: continue; diff --git a/tools/expr-template-compiler.pl b/tools/expr-template-compiler.pl index 8a8e3e2a2f..fce6420b6c 100644 --- a/tools/expr-template-compiler.pl +++ b/tools/expr-template-compiler.pl @@ -14,6 +14,7 @@ use sexpr; use expr_ops; +use oplist; # Input: @@ -130,7 +131,7 @@ sub validate_template { die "Can't match up types"; } } - use Data::Dumper; + for (my $i = 0; $i < $nchild; $i++) { my $child = $template->[$offset+$i]; @@ -313,18 +314,8 @@ sub write_template { } - # first read the correct order of opcodes -my (@opcodes, %names); -{ - open( my $oplist, '<', $OPLIST ) or die $!; - while (<$oplist>) { - next unless (m/^\w+/); - my $opcode = substr $_, 0, $+[0]; - push @opcodes, $opcode; - $names{$opcode} = $#opcodes; - } - close( $oplist ) or die $!; -} +# first read the correct order of opcodes +my %OPNAMES = map { $OPLIST[$_][0] => $_ } keys @OPLIST; my %SEEN; @@ -347,10 +338,10 @@ sub parse_file { $opcode = substr $opcode, 0, -1; $flags |= 1; } - die "Opcode '$opcode' unknown" unless defined $names{$opcode}; + die "Opcode '$opcode' unknown" unless defined $OPNAMES{$opcode}; die "Opcode '$opcode' redefined" if defined $info{$opcode}; # Validate template for consistency with expr.h node definitions - validate_template($template); + validate_template($template, $OPLIST{$opcode}); my $compiled = compile_template($template); $info{$opcode} = { @@ -408,9 +399,10 @@ sub parse_file { } print "\n};\n"; print "static const MVMJitExprTemplate MVM_jit_expr_template_info[] = {\n"; -for (@opcodes) { - if (defined($info->{$_})) { - my $td = $info->{$_}; +for my $opcode (@OPLIST) { + my ($name) = @$opcode; + if (defined($info->{$name})) { + my $td = $info->{$name}; printf ' { MVM_jit_expr_templates + %d, "%s", %d, %d, %d },%s', $td->{idx}, $td->{info}, $td->{len}, $td->{root}, $td->{flags}, "\n"; } else { @@ -424,7 +416,7 @@ sub parse_file { print " $_,\n" for @constants; print "};\n"; -printf <<'FOOTER', scalar @opcodes; +printf <<'FOOTER', scalar @OPLIST; static const MVMJitExprTemplate * MVM_jit_get_template_for_opcode(MVMuint16 opcode) { if (opcode >= %d) return NULL; if (MVM_jit_expr_template_info[opcode].len < 0) return NULL; diff --git a/tools/oplist.pm b/tools/oplist.pm new file mode 100644 index 0000000000..03f841d06d --- /dev/null +++ b/tools/oplist.pm @@ -0,0 +1,50 @@ +package oplist; +use strict; +use warnings; +use Data::Dumper; +use File::Spec; +use constant OPLIST => do { + my ($path, $directory, $filename) = File::Spec->splitpath(__FILE__); + File::Spec->catpath($path, File::Spec->catdir($directory, File::Spec->updir(), qw(src core)), 'oplist'); +}; +# Parse MoarVM oplist file and stash it in @OPLIST and %OPLIST +sub parse_oplist { + my ($fh) = @_; + my @oplist; + while (<$fh>) { + # remove comments and skip empty strings + chomp and s/#.*$//; + next unless length; + my ($name, @meta) = split /\s+/; + my ($attribute, @operands, @adverbs); + for (@meta) { + if (m/^[-+.:*]\w$/) { + $attribute = $_; + } elsif (m/^:\w+$/) { + push @adverbs, $_; + } else { + push @operands, $_; + } + } + push @oplist, [ $name, $attribute, \@operands, \@adverbs ]; + } + return @oplist; +} + +sub import { + my ($class, $file) = (@_, OPLIST); + open my $fh, '<', $file or die $!; + my @oplist = parse_oplist($fh); + my %oplist = map { + $_->[0] => { attr => $_->[1], operands => $_->[2], adverbs => $_->[3] } + } @oplist; + my ($caller) = caller(); + { + no strict 'refs'; + *{$caller . '::OPLIST'} = \@oplist; + *{$caller . '::OPLIST'} = \%oplist; + } + close $fh; +} + +1;