Author: fperrad
Date: Thu May 8 10:05:14 2008
New Revision: 27393
Added:
trunk/languages/lua/luac2pir.pir (contents, props changed)
Modified:
trunk/MANIFEST
trunk/languages/lua/src/build/translator.pl
trunk/languages/lua/src/lib/luabytecode.pir
trunk/languages/lua/src/lib/luabytecode.rules
Log:
[Lua]
- skeleton of a bytecode translator
Modified: trunk/MANIFEST
==============================================================================
--- trunk/MANIFEST (original)
+++ trunk/MANIFEST Thu May 8 10:05:14 2008
@@ -1,7 +1,7 @@
# ex: set ro:
# $Id$
#
-# generated by tools/dev/mk_manifest_and_skip.pl Wed May 7 07:35:21 2008 UT
+# generated by tools/dev/mk_manifest_and_skip.pl Thu May 8 17:01:54 2008 UT
#
# See tools/dev/install_files.pl for documentation on the
# format of this file.
@@ -1579,6 +1579,7 @@
languages/lua/doc/status.pod [lua]
languages/lua/lua.pir [lua]
languages/lua/luac.pl [lua]
+languages/lua/luac2pir.pir [lua]
languages/lua/luad.pir [lua]
languages/lua/luap.pir [lua]
languages/lua/src/PASTGrammar.tg [lua]
Added: trunk/languages/lua/luac2pir.pir
==============================================================================
--- (empty file)
+++ trunk/languages/lua/luac2pir.pir Thu May 8 10:05:14 2008
@@ -0,0 +1,109 @@
+# Copyright (C) 2008, The Perl Foundation.
+# $Id$
+
+=head1 NAME
+
+luac2pir - Lua 5.1 VM bytecode to Parrot PIR Translator
+
+=head1 SYNOPSYS
+
+ parrot luac2pir.pir file.luac
+
+=head1 DESCRIPTION
+
+B<luac2pir> translates a Lua 5.1 VM bytecode file to Parrot PIR.
+
+=head1 SEE ALSO
+
+luad
+
+=head1 AUTHOR
+
+Francois Perrad.
+
+=cut
+
+.HLL '', 'lua_group'
+
+.sub 'main' :main
+ .param pmc argv
+ .local int argc
+ .local string progname
+ .local string filename
+ .local string content
+ argc = elements argv
+ if argc != 2 goto USAGE
+ progname = shift argv
+ filename = shift argv
+ content = load_file(filename)
+ unless content goto L1
+ .local pmc script
+# push_eh _handler
+ new $P0, 'LuaBytecode'
+ script = $P0.'undump'(content)
+ .local string gen_pir
+ gen_pir = script.translate()
+ save_pir(gen_pir, filename)
+ print gen_pir
+ end
+ _handler:
+ .local pmc e
+ .local string msg
+ .get_results (e, msg)
+ print msg
+ print "\n"
+ L1:
+ end
+ USAGE:
+ printerr "Usage: parrot luad.pir filename\n"
+ exit -1
+.end
+
+.sub 'load_file' :anon
+ .param string filename
+ .local pmc pio
+ .local string content
+ pio = getclass 'ParrotIO'
+ push_eh _handler
+ content = pio.'slurp'(filename)
+ if content goto L1
+ $S0 = err
+ print "Can't slurp '"
+ print filename
+ print "' ("
+ print $S0
+ print ")\n"
+ L1:
+ _handler:
+ .return (content)
+.end
+
+.sub 'save_pir' :anon
+ .param string gen_pir
+ .param string filename
+ .local string output
+ .local pmc fh
+ output = concat filename, '.pir'
+ fh = open output, '>'
+ if fh goto L1
+ $S0 = err
+ print "Can't open '"
+ print output
+ print "' ("
+ print $S0
+ print ")\n"
+ goto L2
+ L1:
+ print fh, gen_pir
+ close fh
+ L2:
+.end
+
+.include 'languages/lua/src/lib/luabytecode.pir'
+
+
+# Local Variables:
+# mode: pir
+# fill-column: 100
+# End:
+# vim: expandtab shiftwidth=4 ft=pir:
Modified: trunk/languages/lua/src/build/translator.pl
==============================================================================
--- trunk/languages/lua/src/build/translator.pl (original)
+++ trunk/languages/lua/src/build/translator.pl Thu May 8 10:05:14 2008
@@ -42,6 +42,19 @@
$pir .= generate_final_dump( $srm, $metavars );
+$pir .= generate_initial_code( $srm, [EMAIL PROTECTED], $metavars );
+
+# Emit translation dispatch table.
+$pir .= generate_dispatch_table( $srm, [EMAIL PROTECTED], $metavars );
+
+# Generate instruction translation code from rules.
+foreach (@rules) {
+ $pir .= generate_rule_code( $srm, $_, $metavars );
+}
+
+# Generate final translator code.
+$pir .= generate_final_code( $srm, $metavars );
+
# Finally, write generated PIR to output file.
open my $fh, '>', $output_file
or die "Unable to open $output_file: $!\n";
@@ -199,6 +212,10 @@
unless ( exists $rule->{format} ) {
die "Mandatory entry format missing in rule $name\n";
}
+ unless ( exists $rule->{pir} ) {
+ die "Mandatory entry pir missing in rule $name\n";
+ }
+
return;
}
@@ -213,6 +230,56 @@
PIRCODE
}
+# Generate the translator initialization code.
+# ############################################
+sub generate_initial_code {
+ my ( $srm, $rules, $mv ) = @_;
+
+ # Set up some more metavariables.
+ $mv->{INS} = 'gen_pir';
+ $mv->{PC} = 'pc';
+ $mv->{NEXTPC} = 'next_pc';
+
+ # Emit the dumper.
+ my $pir = <<'PIRCODE';
+.sub 'translate' :method
+ .param pmc func
+ .local string gen_pir
+ .local int pc, next_pc, bc_length, cur_ic, cur_op
+ .local int arg_a
+ .local int arg_b
+ .local int arg_c
+
+ bc_length = self
+ next_pc = 0
+
+PIRCODE
+
+ $pir .= <<'PIRCODE';
+ gen_pir = concat "\n# BEGIN OF TRANSLATED BYTECODE\n\n"
+
+ LOOP:
+ pc = next_pc
+ if pc >= bc_length goto COMPLETE
+ cur_ic = self[pc]
+ next_pc += 1
+ cur_op = cur_ic & 0x003f
+
+PIRCODE
+
+ # Emit label generation code.
+ $pir .= <<'PIRCODE';
+ $S0 = pc
+ gen_pir = concat "PC"
+ gen_pir = concat $S0
+ gen_pir = concat ": \n"
+
+PIRCODE
+
+ # Return generated code.
+ return $pir;
+}
+
# Generate the dumper initialization code.
# ########################################
sub generate_initial_dump {
@@ -339,6 +406,67 @@
return $pir;
}
+# Generate translation code relating to a rule.
+# #############################################
+sub generate_rule_code {
+ my ( $srm, $rule, $mv ) = @_;
+
+ # Emit dispatch label.
+ my $pir = <<"PIRCODE";
+ BDISPATCH_$rule->{name}:
+ # Translation code for $rule->{name} ($rule->{code})
+ gen_pir = concat " # $rule->{name}\\n"
+PIRCODE
+
+ # Emit code to read arguments for the op.
+ if ($rule->{format} =~ /^A/) {
+ $pir .= " arg_a = cur_ic >> 6\n";
+ $pir .= " arg_a &= 0x00ff\n";
+ }
+
+ if ($rule->{format} =~ /sBx$/) {
+ $pir .= " arg_b = cur_ic >>> 14\n";
+ $pir .= " arg_b -= 131071\n";
+ }
+ elsif ($rule->{format} =~ /Bx$/) {
+ $pir .= " arg_b = cur_ic >>> 14\n";
+ }
+ elsif ($rule->{format} =~ /B/) {
+ $pir .= " arg_b = cur_ic >> 23\n";
+ $pir .= " arg_b &= 0x01ff\n";
+ }
+
+ if ($rule->{format} =~ /C$/) {
+ $pir .= " arg_c = cur_ic >> 14\n";
+ $pir .= " arg_c &= 0x01ff\n";
+ }
+
+ $pir .= translation_code( $rule, $mv );
+
+ # Finally, emit code to go to translate next instruction.
+ $pir .= " goto LOOP\n\n";
+
+ # Return generated code.
+ return $pir;
+}
+
+sub translation_code {
+ my ( $rule, $mv ) = @_;
+
+ # If we have PIR for the instruction, just take that. If not, we need
+ # to generate it from the "to generate" instruction directive.
+ my $pir = "### translation\n";
+ if ( $rule->{pir} ) {
+ $pir .= sub_meta( $rule->{pir}, $mv, "pir for rule $rule->{name}" );
+ }
+ else {
+ $pir .= "# TODO\n";
+ }
+ $pir .= "### end translation\n";
+
+ return $pir;
+}
+
# Generate dump code relating to a rule.
# #############################################
sub generate_rule_dump {
@@ -420,6 +548,68 @@
return $pir;
}
+# Generate the translator trailer code.
+# #####################################
+sub generate_final_code {
+ my ( $srm, $mv ) = @_;
+
+ # Emit complete label.
+ # Emit label generation code.
+ my $pir = <<'PIRCODE';
+ COMPLETE:
+
+ $S0 = pc
+ gen_pir = concat "PC"
+ gen_pir = concat $S0
+ gen_pir = concat ": \n"
+
+ gen_pir = concat "\n# END OF TRANSLATED BYTECODE\n\n"
+
+PIRCODE
+
+ # Emit the end of the translator PIR.
+ $pir .= <<'PIRCODE';
+ .return (gen_pir)
+.end
+
+PIRCODE
+
+ # Return generated code.
+ return $pir;
+}
+
+# Substiture meta variables.
+# ##########################
+sub sub_meta {
+ my ( $pir, $mv, $code_source ) = @_;
+ $code_source ||= "(unknown)";
+
+ # Substiture in known meta-variables.
+ for ( keys %$mv ) {
+ $pir =~ s/\${$_}/$mv->{$_}/g;
+ }
+
+ # We need to automagically instantiate [INSP]_ARG_\d+ and [INSP]TEMP\d+.
+ while ( $pir =~ /\$\{([INS])TEMP(\d+)\}/g ) {
+ my $key = $1 . 'TEMP' . $2;
+ my $value = '$' . $1 . $2;
+ $pir =~ s/\$\{$key\}/$value/g;
+ }
+ while ( $pir =~ /\$\{PTEMP(\d+)\}/g ) {
+ my $key = 'PTEMP' . $1;
+ my $value = 'P_temp_' . $1;
+ $mv->{$key} = $value;
+ $pir =~ s/\$\{$key\}/$value/g;
+ }
+
+ # If we have any unsubstituted variables, error.
+ if ( $pir =~ /\$\{([^}]*)}/ ) {
+ warn "Unknown metavariable $1 used in $code_source\n";
+ }
+
+ return $pir;
+}
+
# Usage message.
# ##############
sub usage {
Modified: trunk/languages/lua/src/lib/luabytecode.pir
==============================================================================
--- trunk/languages/lua/src/lib/luabytecode.pir (original)
+++ trunk/languages/lua/src/lib/luabytecode.pir Thu May 8 10:05:14 2008
@@ -62,6 +62,38 @@
$P0.'brief'(0, 1)
.end
+.sub 'translate' :method
+ .local string pir
+ pir = <<'PIRCODE'
+.include 'interpinfo.pasm'
+.HLL 'Lua', 'lua_group'
+
+.namespace
+.sub '&start' :anon :main
+ .param pmc args :optional
+# print "start\n"
+ load_bytecode 'languages/lua/lua.pbc'
+ lua_openlibs()
+ .local pmc env
+ env = get_hll_global '_G'
+ .local pmc vararg
+ vararg = argstolua(env, args)
+ .const .Sub main = '&function_0'
+ main.'setfenv'(env)
+ ($I0, $P0) = docall(main, vararg :flat)
+ unless $I0 goto L1
+ printerr 'luac2pir: '
+ printerr $P0
+ L1:
+.end
+
+PIRCODE
+ $P0 = getattribute self, 'top'
+ $S0 = $P0.'translate'('&function_0', '&start')
+ pir .= $S0
+ .return (pir)
+.end
+
.namespace ['Lua::Function']
@@ -115,6 +147,56 @@
print "; end of function\n\n"
.end
+.sub 'translate' :method
+ .param string funcname
+ .param string outer
+ .local string pir
+ pir = ".sub '" . funcname
+ pir .= "' :anon :lex :outer('"
+ pir .= outer
+ pir .= "')\n"
+ .local int numparams
+ $P0 = getattribute self, 'numparams'
+ numparams = $P0
+ .local int i
+ i = 0
+ L1:
+ unless i < numparams goto L2
+ $S0 = i
+ pir .= " .param pmc arg_"
+ pir .= $S0
+ pir .= " :optional\n"
+ inc i
+ goto L1
+ L2:
+ .local int is_vararg
+ $P0 = getattribute self, 'is_vararg'
+ is_vararg = $P0
+ unless is_vararg goto L3
+ pir.= " .param pmc vararg :slurpy\n"
+ goto L4
+ L3:
+ pir .= " .param pmc extra :slurpy\n"
+ L4:
+ $P0 = getattribute self, 'locvars'
+ $S0 = $P0.'translate'()
+ pir .= $S0
+ $P0 = getattribute self, 'upvalues'
+ $S0 = $P0.'translate'()
+ pir .= $S0
+ $P0 = getattribute self, 'k'
+ $S0= $P0.'translate'()
+ pir .= $S0
+ $P0 = getattribute self, 'code'
+ $S0 = $P0.'translate'(self)
+ pir .= $S0
+ pir .= ".end\n\n"
+ $P0 = getattribute self, 'p'
+ $S0 = $P0.'translate'(funcname)
+ pir .= $S0
+ .return (pir)
+.end
+
.namespace ['Lua::ConstantList']
@@ -131,6 +213,23 @@
L2:
.end
+.sub 'translate' :method
+ .local string pir
+ .local int i, n
+ pir = ''
+ n = self
+ i = 0
+ L1:
+ unless i < n goto L2
+ $P0 = self[i]
+ $S0 = $P0.'translate'(i)
+ pir .= $S0
+ inc i
+ goto L1
+ L2:
+ .return (pir)
+.end
+
.namespace ['Lua::Nil']
@@ -141,6 +240,11 @@
print "\n"
.end
+.sub 'translate' :method
+ .param int i
+ .return ("; const nil\n")
+.end
+
.namespace ['Lua::Boolean']
@@ -153,6 +257,11 @@
print "\n"
.end
+.sub 'translate' :method
+ .param int i
+ .return ("; const bool\n")
+.end
+
.namespace ['Lua::Number']
@@ -165,6 +274,11 @@
print "\n"
.end
+.sub 'translate' :method
+ .param int i
+ .return ("; const number\n")
+.end
+
.namespace ['Lua::String']
@@ -179,6 +293,11 @@
print "\n"
.end
+.sub 'translate' :method
+ .param int i
+ .return ("; const string\n")
+.end
+
.namespace ['Lua::PrototypeList']
@@ -196,6 +315,28 @@
L2:
.end
+.sub 'translate' :method
+ .param string outer
+ .local string pir
+ .local int i, n
+ pir = ''
+ n = self
+ i = 0
+ L1:
+ unless i < n goto L2
+ .local string funcname
+ funcname = outer . '_'
+ $S0 = i
+ funcname .= $S0
+ $P0 = self[i]
+ $S0 = $P0.'translate'(funcname, outer)
+ pir .= $S0
+ inc i
+ goto L1
+ L2:
+ .return (pir)
+.end
+
.namespace ['Lua::LocalList']
@@ -212,6 +353,23 @@
L2:
.end
+.sub 'translate' :method
+ .local string pir
+ .local int i, n
+ pir = ''
+ n = self
+ i = 0
+ L1:
+ unless i < n goto L2
+ $P0 = self[i]
+ $S0 = $P0.'translate'(i)
+ pir .= $S0
+ inc i
+ goto L1
+ L2:
+ .return (pir)
+.end
+
.namespace ['Lua::Local']
@@ -224,6 +382,19 @@
print "\n"
.end
+.sub 'translate' :method
+ .param int i
+ .local string pir
+ pir = " .local pmc loc_"
+ $S0 = i
+ pir .= $S0
+ pir .= " ; "
+ $S0 = self
+ pir .= $S0
+ pir .= "\n"
+ .return (pir)
+.end
+
.namespace ['Lua::UpvalueList']
@@ -240,6 +411,23 @@
L2:
.end
+.sub 'translate' :method
+ .local string pir
+ .local int i, n
+ pir = ''
+ n = self
+ i = 0
+ L1:
+ unless i < n goto L2
+ $P0 = self[i]
+ $S0 = $P0.'translate'(i)
+ pir .= $S0
+ inc i
+ goto L1
+ L2:
+ .return (pir)
+.end
+
.namespace ['Lua::Upvalue']
@@ -252,6 +440,19 @@
print "\n"
.end
+.sub 'translate' :method
+ .param int i
+ .local string pir
+ pir = " .local pmc upv_"
+ $S0 = i
+ pir .= $S0
+ pir .= " ; "
+ $S0 = self
+ pir .= $S0
+ pir .= "\n"
+ .return (pir)
+.end
+
.include 'languages/lua/src/lib/luabytecode_gen.pir'
Modified: trunk/languages/lua/src/lib/luabytecode.rules
==============================================================================
--- trunk/languages/lua/src/lib/luabytecode.rules (original)
+++ trunk/languages/lua/src/lib/luabytecode.rules Thu May 8 10:05:14 2008
@@ -13,168 +13,245 @@
[MOVE]
code = 0
format = AB
+pir = <<PIR
+PIR
[LOADNIL]
code = 3
format = AB
+pir = <<PIR
+PIR
[LOADK]
code = 1
format = ABx
+pir = <<PIR
+PIR
[LOADBOOL]
code = 2
format = ABC
+pir = <<PIR
+PIR
## Upvalues and Globals
[GETUPVAL]
code = 4
format = AB
+pir = <<PIR
+PIR
[GETGLOBAL]
code = 5
format = ABx
+pir = <<PIR
+PIR
[SETGLOBAL]
code = 7
format = ABx
+pir = <<PIR
+PIR
[SETUPVAL]
code = 8
format = AB
+pir = <<PIR
+PIR
## Table Instructions
[GETTABLE]
code = 6
format = ABC
+pir = <<PIR
+PIR
[SETTABLE]
code = 9
format = ABC
+pir = <<PIR
+PIR
## Arithmetic and String Instructions
[ADD]
code = 12
format = ABC
+pir = <<PIR
+PIR
[SUB]
code = 13
format = ABC
+pir = <<PIR
+PIR
[MUL]
code = 14
format = ABC
+pir = <<PIR
+PIR
[DIV]
code = 15
format = ABC
+pir = <<PIR
+PIR
[MOD]
code = 16
format = ABC
+pir = <<PIR
+PIR
[POW]
code = 17
format = ABC
+pir = <<PIR
+PIR
[UNM]
code = 18
format = AB
+pir = <<PIR
+PIR
[NOT]
code = 19
format = AB
+pir = <<PIR
+PIR
[LEN]
code = 20
format = AB
+pir = <<PIR
+PIR
[CONCAT]
code = 21
format = ABC
+pir = <<PIR
+PIR
## Jumps and Calls
[JMP]
code = 22
format = sBx
+pir = <<PIR
+PIR
[CALL]
code = 28
format = ABC
+pir = <<PIR
+PIR
[TAILCALL]
code = 29
format = ABC
+pir = <<PIR
+PIR
[RETURN]
code = 30
format = AB
+pir = <<PIR
+ ${INS} = concat " not_translated()\n"
+PIR
[VARARG]
code = 37
format = AB
+pir = <<PIR
+PIR
[SELF]
code = 11
format = ABC
+pir = <<PIR
+PIR
## Relational and Logic Instructions
[EQ]
code = 23
format = ABC
+pir = <<PIR
+PIR
[LT]
code = 24
format = ABC
+pir = <<PIR
+PIR
[LE]
code = 25
format = ABC
+pir = <<PIR
+PIR
[TEST]
code = 26
format = AC
+pir = <<PIR
+PIR
[TESTSET]
code = 27
format = ABC
+pir = <<PIR
+PIR
## Loop Instructions
[FORLOOP]
code = 31
format = AsBx
+pir = <<PIR
+PIR
[FORPREP]
code = 32
format = AsBx
+pir = <<PIR
+PIR
[TFORLOOP]
code = 33
format = AC
+pir = <<PIR
+PIR
## Table Creation
[NEWTABLE]
code = 10
format = ABC
+pir = <<PIR
+PIR
[SETLIST]
code = 34
format = ABC
+pir = <<PIR
+PIR
## Closures and Closing
[CLOSE]
code = 35
format = A
+pir = <<PIR
+PIR
[CLOSURE]
code = 36
format = ABx
+pir = <<PIR
+PIR