Skip to content

Commit

Permalink
Add generic macro facility to tree expr builder
Browse files Browse the repository at this point in the history
Use any (constant) macro expression inline in the template, not
just offsetof and sizeof. The use of a macro is signaled by the
'&' prefix (like (&offsetof MVMException body.category)).
  • Loading branch information
bdw committed Jul 3, 2015
1 parent e87903c commit be79d75
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 23 deletions.
14 changes: 7 additions & 7 deletions src/jit/exprlist
Expand Up @@ -5,10 +5,10 @@
# opcode preprocessor inserts loads, and immediate nodes for arguments
# automatically.

const_i16: (copy $1)
const i64: (copy $1)
set: (copy $1)
add_i: (add $1 $2)
sp_getarg_o: (load (addr #args $1) #ptr)
sp_getarg_i: (load (addr #args $1) #ptr)
null_s: (imm 0)
const_i16: (copy $1)
const_i64: (copy $1)
set: (copy $1)
add_i: (add $1 $2)
sp_getarg_o: (load (addr fargs $1) (&sizeof MVMObject*))
sp_getarg_i: (load (addr fargs $1) (&sizeof MVMint64))
null_s: (imm 0 (&sizeof MVMString*))
30 changes: 14 additions & 16 deletions tools/tree-expr-compiler.pl
Expand Up @@ -53,7 +53,7 @@ sub parse_sexp {
} elsif (substr($expr, 0, 1) eq ')') {
$expr = substr $expr, 1;
last;
} elsif ($expr =~ m/^[#\$]?[\w\.\[\]_\*]+/) {
} elsif ($expr =~ m/^[&\$]?[\w\.\[\]_\*]+/) {
push @$tree, substr($expr, $-[0], $+[0] - $-[0]);
$expr = substr $expr, $+[0];
} else {
Expand Down Expand Up @@ -83,7 +83,7 @@ sub write_template {
my ($tree, $templ, $desc, $env) = @_;
die "Can't deal with an empty tree" unless @$tree; # we need at least some nodes
my $top = $tree->[0]; # get the first item, used for dispatch
die "First parameter must be a bareword" unless $top =~ m/^[a-z]\w*$/i;
die "First parameter must be a bareword or macro" unless $top =~ m/^&?[a-z]\w*$/i;
my (@items, @desc); # accumulate state
if ($top eq 'let') {
# deal with let declarations
Expand All @@ -99,15 +99,13 @@ sub write_template {
$env->{$stmt->[0]} = $child;
}
return write_template($expr, $templ, $desc, $env);
} elsif ($top eq 'sizeof') {
# Add sizeof expression for the compiler
die "Invalid sizeof expr" unless @$tree == 2;
return (sprintf('sizeof(%s)', $tree->[1]), '.');
} elsif ($top eq 'offsetof') {
# add offsetof
die "Invalid offsetof expr" unless @$tree == 3;
return (sprintf('offsetof(%s, %s)', $tree->[1], $tree->[2]), '.');
}
} elsif (substr($top, 0, 1) eq '&') {
# Add macro or sizeof/offsetof expression. these are not
# processed in at runtime! Must evaluate to constant
# expression.
return (sprintf('%s(%s)', substr($top, 1),
join(', ', @$tree[1..$#$tree])), '.');
}
# deal with a simple expression
for my $item (@$tree) {
if (ref($item) eq 'ARRAY') {
Expand Down Expand Up @@ -160,9 +158,9 @@ sub write_template {
check_parse('(0)', ['0']);
eval { compile_template(parse_sexp('()')) }; ok $@, 'Cannot compile empty template';
eval { compile_template(parse_sexp('(foo bar)')) }; ok !$@, 'a simple expression should work';
eval { compile_template(parse_sexp('(offsetof foo bar)')) };
eval { compile_template(parse_sexp('(&offsetof foo bar)')) };
ok $@, 'Template root must be simple expr';
eval { compile_template(parse_sexp('(foo (sizeof))')) }; ok $@, 'sizeof requires one child';
eval { compile_template(parse_sexp('(foo (&sizeof 1))')) }; ok !$@, 'use sizeof as a macro';
eval { compile_template(parse_sexp('(let (($foo (bar)) ($quix (quam $1))) (bar $foo $quix))')) };
ok !$@, 'let expressions should live and take more than one argument';
eval { compile_template(parse_sexp('(foo $bar)')) };
Expand All @@ -182,12 +180,12 @@ sub write_template {
is($subex->{root}, 2);
is($subex->{desc}, '.f..l', 'Fill subexpression, link to parent');
is_deeply($subex->{template}, [qw<MJ_BAZ 1 MJ_FOO MJ_BAR 0>]);
my $complex_sexp = '(let (($foo (bar $1))) (foo zum $2 (zaf $foo 3)))';
my $complex_sexp = '(let (($foo (bar $1))) (foo zum $2 (zaf $foo 3) (&sizeof int)))';
my ($complex_expr, $rest) = parse_sexp($complex_sexp);
my $complex = compile_template($complex_expr);
is ($complex->{root}, 5);
is ($complex->{desc}, '.f.l...fl');
is_deeply($complex->{template}, [qw(MJ_BAR 1 MJ_ZAF 0 3 MJ_FOO MJ_ZUM 2 2)]);
is ($complex->{desc}, '.f.l...fl.');
is_deeply($complex->{template}, [qw(MJ_BAR 1 MJ_ZAF 0 3 MJ_FOO MJ_ZUM 2 2 sizeof(int))]);
done_testing();
} else {
# first read the correct order of opcodes
Expand Down

0 comments on commit be79d75

Please sign in to comment.