]> git.xonotic.org Git - xonotic/xonotic.git/blobdiff - misc/tools/progs-analyzer.pl
stuff
[xonotic/xonotic.git] / misc / tools / progs-analyzer.pl
index d05031c0fb31e1662fac0c4335eae5eb537d743f..e1594f1d7939eb028a5f1950f9eaabd78ab78062 100644 (file)
@@ -127,7 +127,7 @@ use constant TYPES => {
        int => ['V', 4, signed 32],
        ushort => ['v', 2, id],
        short => ['v', 2, signed 16],
-       opcode => ['v', 2, sub { OPCODE_E->[$_[0]] or die "Invalid opcode: $_[0]"; }],
+       opcode => ['v', 2, sub { OPCODE_E->[$_[0]] or do { warn "Invalid opcode: $_[0]"; "INVALID#$_[0]"; }; }],
        float => ['f', 4, id],
        uchar8 => ['a8', 8, sub { [unpack 'C8', $_[0]] }],
        global => ['i', 4, sub { { int => $_[0], float => unpack "f", pack "L", $_[0] }; }],
@@ -249,16 +249,17 @@ sub run_nfa($$$$$$)
                no warnings 'recursion';
 
                my ($ip, $state) = @_;
+               my $ret = 0;
 
                for(;;)
                {
-                       return
+                       return $ret
                                if $state_checker->($ip, $state);
 
                        my $s = $statements->[$ip];
                        my $c = checkop $s->{op};
 
-                       if($instruction_handler->($ip, $state, $s, $c))
+                       if(($ret = $instruction_handler->($ip, $state, $s, $c)))
                        {
                                # abort execution
                                last;
@@ -268,13 +269,29 @@ sub run_nfa($$$$$$)
                        {
                                last;
                        }
+                       elsif($c->{iscall})
+                       {
+                               my $func = $s->{a};
+                               my $funcid = $progs->{globals}[$func]{v}{int};
+                               my $funcobj = $progs->{functions}[$funcid];
+                               if($funcobj && $funcobj->{first_statement} < 0) # builtin
+                               {
+                                       my $def = $progs->{globaldef_byoffset}->($func);
+                                       last
+                                               if $def->{debugname} eq '_error';
+                               }
+                               $ip += 1;
+                       }
                        elsif($c->{isjump})
                        {
                                if($c->{isconditional})
                                {
                                        if(rand 2)
                                        {
-                                               $nfa->($ip+$s->{$c->{isjump}}, $copy_handler->($state));
+                                               if(($ret = $nfa->($ip+$s->{$c->{isjump}}, $copy_handler->($state))) < 0)
+                                               {
+                                                       last;
+                                               }
                                                $ip += 1;
                                        }
                                        else
@@ -293,6 +310,8 @@ sub run_nfa($$$$$$)
                                $ip += 1;
                        }
                }
+
+               return $ret;
        };
 
        $nfa->($ip, $copy_handler->($state));
@@ -516,14 +535,6 @@ sub find_uninitialized_locals($$)
 {
        my ($progs, $func) = @_;
 
-#      TODO
-#      21:04:25      divVerent | just wondering how I can best detect "temp value is never used"
-#      21:04:33      divVerent | I know which vars are temps already
-#      21:04:59      divVerent | basically, looks like for each write, I will not just have to track that the new value is valid
-#      21:05:01      divVerent | but also its source
-#      21:05:12      divVerent | on each read, I'll remember that this source statement's value has been used
-#      21:05:21      divVerent | and will compare the list of sources in a step after "execution"
-#      21:05:27      divVerent | to the list of total write statements to the temp
 
        return
                if $func->{first_statement} < 0; # builtin
@@ -771,18 +782,11 @@ sub find_uninitialized_locals($$)
                                                }
                                        }
                                }
-                               else # builtin
-                               {
-                                       my $def = $progs->{globaldef_byoffset}->($func);
-                                       return 1
-                                               if $def->{debugname} eq 'error';
-                               }
                        }
 
                        return 0;
                };
 
-       my %writeplace_seen = ();
        for my $ip(keys %write_places)
        {
                for my $operand(keys %{$write_places{$ip}})
@@ -791,6 +795,7 @@ sub find_uninitialized_locals($$)
                        my %left = map { $_ => 1 } @{$write_places{$ip}{$operand}};
                        my $isread = 0;
 
+                       my %writeplace_seen = ();
                        run_nfa $progs, $ip+1, \%left,
                                sub
                                {
@@ -1017,7 +1022,7 @@ sub parse_progs($)
        {
                next
                        if $globaldefs{$_->{debugname}} <= 1;
-               print "Not unique: $_->{debugname} at $_->{ofs}\n";
+               #print "Not unique: $_->{debugname} at $_->{ofs}\n";
                $_->{debugname} .= "\@$_->{ofs}";
        }
        $p{globaldef_byoffset} = sub