view cbctools/change_OP_to_cbc.pl @ 37:5b66cfffe9cd

update regex
author Takahiro SHIMIZU <anatofuz@cr.ie.u-ryukyu.ac.jp>
date Fri, 16 Nov 2018 17:55:10 +0900
parents 5577a26e56a9
children 2c51389684ca
line wrap: on
line source

#!/usr/bin/env perl
use strict;
use warnings;

my $cbc_file = shift or die; # src/core/cbc-interp.cbc

open my $fh, '<',$cbc_file;
my @cbc_lines= <$fh>;
close $fh;

my @rewritec = ();
my $indent = " " x 12;
my $none_left_blanket = 0;

my $i = 0;
our @regex_targets = qw/op cu cur_op tc cur_callsite bytecode_start/;

my @upside = ();
for (;$i < scalar(@cbc_lines); $i++){

    $cbc_lines[$i] = change_i($cbc_lines[$i]);

    #$cbc_lines[$i] =~ s/reg_base/i->reg_base/g;
    #$cbc_lines[$i] =~ s/tc/i->tc/g;
    #$cbc_lines[$i] =~ s/tc/i->tc/g;

    $cbc_lines[$i] =~ s/GET_(REG|LEX)\((.*?)\)/GET_$1($2,i)/g;

    push @upside,$cbc_lines[$i];
    if ($cbc_lines[$i+1] =~ /\/\* This is the interpreter run loop. We have one of these per thread. \*\//){
        last;
    }
}

my @middle = ();

for (;$i < scalar(@cbc_lines); $i++){

    if ($cbc_lines[$i] =~ /#if MVM_CGOTO/ && $cbc_lines[$i+1] =~ /#include/){
        while ( $cbc_lines[$i] !~ /Stash address/){
                $i++;
            }
    }

    push @middle,$cbc_lines[$i];
    if ($cbc_lines[$i] =~ /DISPATCH\(NEXT_OP\)/){ # DISPATCHの中身を書き換えるのでそこまで飛ばす
        $i++;
        last;
    }
}
my @dispatch = ();

for (;$i < scalar(@cbc_lines); $i++){
    # check OP(.*) {  codes

    if ($cbc_lines[$i] =~ /#if MVM_CGOTO/){
        $i--;
        last;
    }

    if ($cbc_lines[$i] =~ /^\s+OP\((.*)\):/ ){
        my $opcode = $1;
        #push @dispatch,"${indent}OP($opcode):\n";
        $none_left_blanket = $cbc_lines[$i] =~ /{/ ? 0 : 1;
        # transrate OP(HOGE) to __code hoge(INTERP *i){
        $cbc_lines[$i]  =  "__code "."cbc_$opcode"."(INTERP i){\n";
        #$cbc_lines[$i]  = $indent. "__code ".$opcode."(INTERP i){\n";
        push @rewritec,$cbc_lines[$i];

        # 次の行に移動
        $i++;

        # この行がOP()だった場合
        #  OP(DEPRECATED_4):
        #  OP(DEPRECATED_5): <- $i
        # このような宣言になっているので$iにgotoするように関数を書き直し
        # $iの部分の関数定義を次ループでするために一行戻して再ループ

        if ($cbc_lines[$i] =~ /^\s+OP\((.*)\):/){
            push @rewritec,"    goto cbc_$1(i);\n";
            #push @rewritec,"$indent   goto $1(i);\n";
            insert_right_blanket();
            $i--;
            next;
        }

        # 例外だったらかえってこないはずなのでgoto
        if ( $cbc_lines[$i] =~ /MVM_exception_throw_adhoc/ && $cbc_lines[$i+1] =~ /OP\(/){
            push @rewritec, change_i($cbc_lines[$i]);
            insert_cbc_next();
            insert_right_blanket();
            next;
        }
    }

    # 普通の行は変換してinsertする
    if ($cbc_lines[$i] =~ /}/){
        if ($cbc_lines[$i+1] =~ /OP/){
            $cbc_lines[$i] = "}\n";
        }
    }
    $cbc_lines[$i] =~ s/GET_(REG|LEX)\((.*?)\)/GET_$1($2,i)/g;
    push @rewritec,change_i($cbc_lines[$i]);


   if ($i != scalar(@cbc_lines)-1 && $cbc_lines[$i+1] =~ /OP/ && $none_left_blanket){
        insert_right_blanket();
        $none_left_blanket = 0;
    }
}

my @after = ();
insert_interp_constract();
map { push @after,$cbc_lines[$_]} ($i+1.. scalar(@cbc_lines)-1);
#map { print; } (@upside,@rewritec,@middle,@dispatch,@after);
map { print; } (@upside,@rewritec,@middle,@after);




sub change_i {
    my $str = shift;
    map { $str = substitution_regex($str,$_); } @regex_targets;
    #
    #for my $reg (@regex_targets){
    #    $str = substitution_regex($str,$reg);
    #}
    #$str =~ s/(\A)op|([\s,(])op/$2i->op/g;
    #$str =~ s/(\A)cu|([\s,(])cu/$2i->cu/g;
    #$str =~ s/(\A)cur_op|([\s,(])cur_op/$2i->cur_op/g;
    #$str =~ s/(\A)tc|([\s,(&])tc/$2i->tc/g;
    #$str =~ s/(\A)cur_callsite|([\s,(&])cur_callsite/$2i->cur_callsite/g;
    #$str =~ s/(\A)bytecode_start|([\s,(&])bytecode_start/$2i->bytecode_start/g;
    $str =~ s/NEXT;/cbc_next(i);/;
    $str =~ s/                /    /g;
    return $str;
}

sub substitution_regex {
    my ($str,$target) = @_;
    if ($str =~ /(\A)$target/){
        $str =~ s/(\A)$target/i->$target/g;
        return $str;
    }
    if ($str =~ /([\s,(&])$target/){
        $str =~ s/([\s,(&])$target/$1i->$target/g;
        return $str;
    }
    return $str;
}

sub insert_cbc_next{
    #push @rewritec,"$indent}\n";
    push @rewritec,"    goto cbc_next(i);\n";
}

sub insert_right_blanket {
    #push @rewritec,"$indent}\n";
    push @rewritec,"}\n";
}

sub insert_interp_constract {
my $msg = <<'EOF';
INTER inter = {0,NULL,NULL,NULL,NULL,NULL,tc};
INTERP i = &inter;
EOF
    push @after, $msg;
}