Skip to content

Commit

Permalink
Add a new tree-based IR between Op and CodeGen
Browse files Browse the repository at this point in the history
The goal is to eventually deduplicate Op/Decl/Body logic, create a nicer
syntax for low-level code, and allow more CodeGen refactoring.
  • Loading branch information
Stefan O'Rear committed Jul 15, 2010
1 parent 750e66a commit 040a58b
Show file tree
Hide file tree
Showing 5 changed files with 250 additions and 108 deletions.
5 changes: 2 additions & 3 deletions Body.pm
Expand Up @@ -23,7 +23,7 @@ use CodeGen ();
$self->codegen(CodeGen->new(name => $self->name, body => $self));
my $cg = $self->codegen;
$self->do_enter($cg);
$self->do->cg($cg, $self);
$self->do->code($self)->var_cg($cg);
# TODO: Bind a return value here to catch non-ro sub use
$cg->return(1) unless $cg->unreach;
return $cg;
Expand All @@ -35,8 +35,7 @@ use CodeGen ();
$_->do_enter($cg, $self) for @{ $self->decls };
$self->signature->gen_binder($cg) if $self->signature;
for (@{ $self->enter }) {
$_->cg($cg, $self);
$cg->drop;
CgOp::sink($_->code($self))->var_cg($cg);
}
}

Expand Down
182 changes: 182 additions & 0 deletions CgOp.pm
@@ -0,0 +1,182 @@
use 5.010;
use strict;
use warnings;


# for transition only!
{
package CgOp::NIL;
use Moose;

has ops => (isa => 'ArrayRef', is => 'ro');

sub var_cg {
my ($self, $cg) = @_;
for (@{ $self->ops }) {
if (blessed $_) {
$_->var_cg($cg);
} else {
my ($c, @o) = @$_;
$cg->$c(@o);
}
}
}

no Moose;
__PACKAGE__->meta->make_immutable;
}

{
package CgOp::Ternary;
use Moose;

has check => (is => 'ro');
has true => (is => 'ro');
has false => (is => 'ro');

sub var_cg {
my ($self, $cg) = @_;
my $l1 = $cg->label;
my $l2 = $cg->label;

$self->check->var_cg($cg);
$cg->ncgoto($l1);
$self->true->var_cg($cg);
$cg->goto($l2);
$cg->labelhere($l1);
$self->false->var_cg($cg);
$cg->labelhere($l2);
}

no Moose;
__PACKAGE__->meta->make_immutable;
}

{
package CgOp::While;
use Moose;

has check => (is => 'ro');
has body => (is => 'ro');
has once => (is => 'ro', isa => 'Bool');
has until => (is => 'ro', isa => 'Bool');

sub var_cg {
my ($self, $cg) = @_;
my $lagain = $cg->label;
my $lcheck = $self->once ? 0 : $cg->label;

$cg->goto($lcheck) unless $self->once;

$cg->labelhere($lagain);
$self->body->var_cg($cg);

$cg->labelhere($lcheck) unless $self->once;
$self->check->var_cg($cg);
if ($self->until) {
$cg->ncgoto($lagain);
} else {
$cg->cgoto($lagain);
}
}

no Moose;
__PACKAGE__->meta->make_immutable;
}

# just a bunch of smart constructors
{
package CgOp;

sub nil {
CgOp::NIL->new(ops => [ @_ ]);
}

sub null {
CgOp::NIL->new(ops => [[ push_null => $_[0] ]]);
}

sub prog {
CgOp::NIL->new(ops => [ @_ ]);
}

sub wrap {
CgOp::NIL->new(ops => [ $_[0], [ 'clr_wrap' ] ]);
}

sub sink {
CgOp::NIL->new(ops => [ $_[0], [ 'drop' ] ]);
}

sub fetch {
CgOp::NIL->new(ops => [ $_[0], [ 'fetch' ] ]);
}

sub how {
CgOp::NIL->new(ops => [ $_[0], [ 'how' ] ]);
}

sub getfield {
CgOp::NIL->new(ops => [ $_[1], [ 'clr_field_get', $_[0] ] ]);
}

sub cast {
CgOp::NIL->new(ops => [ $_[1], [ 'cast', $_[0] ] ]);
}

sub newscalar {
CgOp::NIL->new(ops => [ $_[0], [ 'newscalar' ] ]);
}

sub string_var {
CgOp::NIL->new(ops => [ [ 'string_var', $_[0] ] ]);
}

sub double {
CgOp::NIL->new(ops => [ [ 'clr_double', $_[0] ] ]);
}

sub unbox {
CgOp::NIL->new(ops => [ $_[1], [ 'unbox', $_[0] ] ]);
}

sub box {
CgOp::NIL->new(ops => [ $_[1], [ 'box', $_[0] ] ]);
}

sub bind {
CgOp::NIL->new(ops => [ $_[1], $_[2], [ 'bind', $_[0] ] ]);
}

sub scopedlex {
CgOp::NIL->new(ops => [[ scopelexget => $_[0] ]]);
}

sub subcall {
my ($sub, @args) = @_;
CgOp::NIL->new(ops => [ $sub, @args, [ 'call_sub', 1, scalar @args ] ]);
}

sub methodcall {
my ($obj, $name, @args) = @_;
CgOp::NIL->new(ops => [ $obj, [ 'dup_fetch' ], @args,
[ 'call_method', 1, $name, scalar @args ] ]);
}

sub ternary {
CgOp::Ternary->new(
check => $_[0],
true => $_[1],
false => $_[2]);
}

sub whileloop {
CgOp::While->new(
until => $_[0],
once => $_[1],
check => $_[2],
body => $_[3]);
}
}

1;
2 changes: 2 additions & 0 deletions Makefile
Expand Up @@ -11,6 +11,8 @@ test: $(COMPILER) test.pl Setting.dll
gmcs /r:Setting.dll Program.cs
prove -e 'mono --debug=casts' Program.exe

.DELETE_ON_ERROR:

Setting.cs: $(COMPILER) setting
perl -MCompilerDriver=:all -e 'header; setting' > Setting.cs

Expand Down
2 changes: 1 addition & 1 deletion Niecza/Actions.pm
Expand Up @@ -150,7 +150,7 @@ sub nibbler { my ($cl, $M) = @_;
if ($M->isa('STD::Regex')) {
$M->{_ast} = $M->{EXPR}{_ast};
} elsif ($M->isa('Niecza::Grammar::NIL')) {
$M->{_ast} = Op::NIL->new(code => [map { @{$_->{_ast}} } @{$M->{insn}}]);
$M->{_ast} = Op::NIL->new(ops => [map { @{$_->{_ast}} } @{$M->{insn}}]);
} else {
# garden variety nibbler
my $str = "";
Expand Down

0 comments on commit 040a58b

Please sign in to comment.