Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / mini / genmdesc.pl
old mode 100644 (file)
new mode 100755 (executable)
index ef316ef..ae49ecb
@@ -6,21 +6,59 @@ use strict;
 no locale;
 
 # must keep in sync with mini.h
-my @spec_names = qw(dest src1 src2 src3 len clob);
+my @spec_names = qw(dest src1 src2 src3 len clob nacl);
 sub INST_DEST  () {return 0;}
 sub INST_SRC1  () {return 1;}
 sub INST_SRC2  () {return 2;}
 sub INST_SRC3  () {return 3;}
 sub INST_LEN   () {return 4;}
 sub INST_CLOB  () {return 5;}
+# making INST_NACL the same as INST_MAX is not a mistake,
+# INST_NACL writes over INST_LEN, it's not its own field
+sub INST_NACL  () {return 6;}
 sub INST_MAX   () {return 6;}
 
 # this must include all the #defines used in mini-ops.h
-my @defines = qw (__i386__ __x86_64__ __ppc__ __powerpc__ __arm__ 
-       __sparc__ sparc __s390__ s390 __ia64__ __alpha__ __mips__);
+my @defines = qw (__i386__ __x86_64__ __ppc__ __powerpc__ __ppc64__ __arm__ 
+       __sparc__ sparc __s390__ s390 __alpha__ __mips__ __aarch64__ __wasm__);
 my %table =();
+my %template_table =();
 my @opcodes = ();
 
+my $nacl = 0;
+
+sub parse_file
+{
+       my ($define, $file) = @_;
+       my @enabled = (1);
+       my $i = 0;
+       open (OPS, $file) || die "Cannot open $file: $!";
+       while (<OPS>) {
+               if (/^\s*#\s*if\s+(.*)/) {
+                       my $defines = $1;
+                       die "fix the genmdesc.pl cpp parser to handle all operators" if /(&&)|([!<>=])/;
+                       unshift @enabled, scalar ($defines =~ /defined\s*\(\s*$define\s*\)/);
+                       next;
+               }
+               if (/^\s*#\s*ifdef\s+(\S+)/) {
+                       my $defines = $1;
+                       unshift @enabled, $defines eq $define;
+                       next;
+               }
+               if (/^\s*#\s*endif/) {
+                       shift @enabled;
+                       next;
+               }
+               next unless $enabled [0];
+               next unless /MINI_OP3?\s*\(\s*(\S+?)\s*,\s*"(.*?)"/;
+               my ($sym, $name) = ($1, $2);
+               push @opcodes, [$sym, $name];
+               $table{$name} = {num => $i, name => $name};
+               $i++;
+       }
+       close (OPS);
+}
+
 sub load_opcodes
 {
        my ($srcdir, $arch) = @_;
@@ -37,7 +75,25 @@ sub load_opcodes
        }
        die "$arch arch is not supported.\n" unless $arch_found;
 
-       $cpp .= " -D$arch $srcdir/mini-ops.h|";
+       my $arch_define = $arch;
+       if ($arch =~ "__i386__") {
+               $arch_define = "TARGET_X86";
+       }
+       if ($arch =~ "__x86_64__") {
+               $arch_define = "TARGET_AMD64";
+       }
+       if ($arch =~ "__arm__") {
+               $arch_define = "TARGET_ARM";
+       }
+       if ($arch =~ "__aarch64__") {
+               $arch_define = "TARGET_ARM64";
+       }
+       if ($arch =~ "__wasm__") {
+               $arch_define = "TARGET_WASM";
+       }
+       parse_file ($arch_define, "$srcdir/mini-ops.h");
+       return;
+       $cpp .= " -D$arch_define $srcdir/mini-ops.h|";
        #print "Running: $cpp\n";
        open (OPS, $cpp) || die "Cannot execute cpp: $!";
        while (<OPS>) {
@@ -57,6 +113,7 @@ sub load_file {
 
        open (DESC, $name) || die "Cannot open $name: $!";
        while (<DESC>) {
+               my $is_template = 0;
                $line++;
                next if /^\s*$/;
                if (/^\s*(#.*)?$/) {
@@ -66,10 +123,16 @@ sub load_file {
                my @values = split (/\s+/);
                next unless ($values [0] =~ /(\S+?):/);
                my $name = $1;
-               my $desc = $table {$name};
+               my $desc;
+               if ($name eq "template") {
+                       $is_template = 1;
+                       $desc = {};
+               } else {
+                       $desc = $table {$name};
+                       die "Invalid opcode $name at line $line\n" unless defined $desc;
+                       die "Duplicated opcode $name at line $line\n" if $desc->{"desc"};
+               }
                shift @values;
-               die "Invalid opcode $name at line $line\n" unless defined $desc;
-               die "Duplicated opcode $name at line $line\n" if $desc->{"desc"};
                $desc->{"desc"} = $_;
                $desc->{"comment"} = $comment;
                $desc->{"spec"} = {};
@@ -77,9 +140,22 @@ sub load_file {
                #print "values for $name: " . join (' ', @values) . " num: " . int(@values), "\n";
                for my $val (@values) {
                        if ($val =~ /(\S+):(.*)/) {
-                               $desc->{"spec"}->{$1} = $2;
+                               if ($1 eq "name") {
+                                       die "name tag only valid in templates at line $line\n" unless $is_template;
+                                       die "Duplicated name tag in template $desc->{'name'} at line $line\n" if defined $desc->{'name'};
+                                       die "Duplicated template $2 at line $line\n" if defined $template_table {$2};
+                                       $desc->{'name'} = $2;
+                                       $template_table {$2} = $desc;
+                               } elsif ($1 eq "template") {
+                                       my $tdesc = $template_table {$2};
+                                       die "Invalid template name $2 at line $line\n" unless defined $tdesc;
+                                       $desc->{"spec"} = {%{$tdesc->{"spec"}}};
+                               } else {
+                                       $desc->{"spec"}->{$1} = $2;
+                               }
                        }
                }
+               die "Template without name at line $1" if ($is_template && !defined ($desc->{'name'}));
        }
        close (DESC);
 }
@@ -98,10 +174,19 @@ sub build_spec {
        }
        #print "vals: " . join (' ', @vals) . "\n";
        my $res = "";
+       my $n = 0;
        for (my $i = 0; $i < @vals; ++$i) {
+               next if $i == INST_NACL;
                if (defined $vals [$i]) {
                        if ($i == INST_LEN) {
-                               $res .= sprintf ("\\x%x\" \"", +$vals [$i]);
+                               $n = $vals [$i];
+                               if ($n =~ /[^0-9]/) {
+                                               die "Invalid instruction length $n\n";
+                               }
+                               if ((defined $vals [INST_NACL]) and $nacl == 1){
+                                   $n = $vals [INST_NACL];
+                               }
+                               $res .= sprintf ("\\x%x\" \"", + $n);
                        } else {
                                if ($vals [$i] =~ /^[a-zA-Z0-9]$/) {
                                        $res .= $vals [$i];
@@ -120,11 +205,11 @@ sub build_table {
        my ($fname, $name) = @_;
        my $i;
        my $idx;
-       my $idx_array = "const guint16 ${name}_idx [] = {\n";
+       my $idx_array = "const guint16 mono_${name}_idx [] = {\n";
 
        open (OUT, ">$fname") || die "Cannot open file $fname: $!";
        print OUT "/* File automatically generated by genmdesc, don't change */\n\n";
-       print OUT "const char $name [] = {\n";
+       print OUT "const char mono_$name [] = {\n";
        print OUT "\t\"" . ("\\x0" x INST_MAX) . "\"\t/* null entry */\n";
        $idx = 1;
 
@@ -149,12 +234,17 @@ sub build_table {
 }
 
 sub usage {
-       die "genmdesc.pl arch srcdir output name desc [desc2 ...]\n";
+       die "genmdesc.pl arch srcdir [--nacl] output name desc [desc2 ...]\n";
 }
 
 my $arch = shift || usage ();
 my $srcdir = shift || usage ();
 my $output = shift || usage ();
+if ($output eq "--nacl")
+{
+  $nacl = 1;  
+  $output = shift || usage();
+}
 my $name = shift || usage ();
 usage () unless @ARGV;
 my @files = @ARGV;