]> git.rm.cloudns.org Git - xonotic/xonotic.git/commitdiff
better detect unused locals
authorRudolf Polzer <divverent@alientrap.org>
Mon, 30 Apr 2012 10:34:15 +0000 (12:34 +0200)
committerRudolf Polzer <divverent@alientrap.org>
Mon, 30 Apr 2012 10:34:15 +0000 (12:34 +0200)
misc/tools/progs-analyzer.pl

index 2ab6271758519d7b6bf0906cad46d0999de4a267..dccb68105a9f168d7d00f8a72d6453ba06ef428f 100644 (file)
@@ -573,7 +573,7 @@ sub find_uninitialized_locals($$)
                                elsif($type eq 'outglobal')
                                {
                                        $watchme{$ofs} |= WATCHME_W;
-                                       $write_places{$ip}{$_} = $_
+                                       $write_places{$ip}{$_} = [$ofs]
                                                if $watchme{$ofs} & WATCHME_X;
                                }
                                elsif($type eq 'outglobalvec')
@@ -581,8 +581,9 @@ sub find_uninitialized_locals($$)
                                        $watchme{$ofs} |= WATCHME_W;
                                        $watchme{$ofs+1} |= WATCHME_W;
                                        $watchme{$ofs+2} |= WATCHME_W;
-                                       $write_places{$ip}{$_} = 1
-                                               if ($watchme{$ofs} | $watchme{$ofs+1} | $watchme{$ofs+2}) & WATCHME_X;
+                                       my @l = grep { $watchme{$_} & WATCHME_X } $ofs .. ($ofs+2);
+                                       $write_places{$ip}{$_} = \@l
+                                               if @l;
                                }
                        }
 
@@ -654,12 +655,6 @@ sub find_uninitialized_locals($$)
                        {
                                # if $state is stronger or equal to $s, return 1
 
-                               # FIXME this is wrong now
-                               # when merging states, we also must somehow merge initialization sources
-                               # to become the union, EVEN for already analyzes future instructions!
-                               # maybe can do this by abusing references
-                               # and thereby adjusting the value after the fact
-
                                for(keys %$state)
                                {
                                        if($state->{$_}{valid}[0] < $s->{$_}[0])
@@ -787,14 +782,76 @@ sub find_uninitialized_locals($$)
                        return 0;
                };
 
-#      for my $ip(keys %write_places)
-#      {
-#              for(keys %{$write_places{$ip}})
-#              {
-#                      print "; Value is never used in $func->{debugname} at $ip.$_\n";
-#                      ++$warned{$ip}{$_};
-#              }
-#      }
+       my %writeplace_seen = ();
+       for my $ip(keys %write_places)
+       {
+               for my $operand(keys %{$write_places{$ip}})
+               {
+                       # TODO verify it
+                       my %left = map { $_ => 1 } @{$write_places{$ip}{$operand}};
+                       my $isread = 0;
+
+                       run_nfa $progs, $ip+1, \%left,
+                               sub
+                               {
+                                       return { %{$_[0]} };
+                               },
+                               sub
+                               {
+                                       my ($ip, $state) = @_;
+                                       return $writeplace_seen{"$ip " . join " ", sort keys %$state}++;
+                               },
+                               sub
+                               {
+                                       my ($ip, $state, $s, $c) = @_;
+                                       for(qw(a b c))
+                                       {
+                                               my $type = $c->{$_};
+                                               next
+                                                       unless defined $type;
+
+                                               my $ofs = $s->{$_};
+                                               if($type eq 'inglobal' || $type eq 'inglobalfunc')
+                                               {
+                                                       if($state->{$ofs})
+                                                       {
+                                                               $isread = 1;
+                                                               return -1; # exit TOTALLY
+                                                       }
+                                               }
+                                               elsif($type eq 'inglobalvec')
+                                               {
+                                                       if($state->{$ofs} || $state->{$ofs+1} || $state->{$ofs+2})
+                                                       {
+                                                               $isread = 1;
+                                                               return -1; # exit TOTALLY
+                                                       }
+                                               }
+                                               elsif($type eq 'outglobal')
+                                               {
+                                                       delete $state->{$ofs};
+                                                       return 1
+                                                               if !%$state;
+                                               }
+                                               elsif($type eq 'outglobalvec')
+                                               {
+                                                       delete $state->{$ofs};
+                                                       delete $state->{$ofs+1};
+                                                       delete $state->{$ofs+2};
+                                                       return 1
+                                                               if !%$state;
+                                               }
+                                       }
+                                       return 0;
+                               };
+
+                       if(!$isread)
+                       {
+                               print "; Value is never used in $func->{debugname} at $ip.$operand\n";
+                               ++$warned{$ip}{$operand};
+                       }
+               }
+       }
        
        disassemble_function($progs, $func, \%warned)
                if keys %warned;