Codegen support (stripped out) for the annotate attribute.
[llvm-complete.git] / tools / llvm-config / find-cycles.pl
blob8156abd3f053bb069601306f1cb2c3e5395ed578
1 #!/usr/bin/perl
3 # Program: find-cycles.pl
5 # Synopsis: Given a list of possibly cyclic dependencies, merge all the
6 # cycles. This makes it possible to topologically sort the
7 # dependencies between different parts of LLVM.
9 # Syntax: find-cycles.pl < LibDeps.txt > FinalLibDeps.txt
11 # Input: cycmem1: cycmem2 dep1 dep2
12 # cycmem2: cycmem1 dep3 dep4
13 # boring: dep4
15 # Output: cycmem1 cycmem2: dep1 dep2 dep3 dep4
16 # boring: dep4
18 # This file was written by Eric Kidd, and is placed into the public domain.
21 use 5.006;
22 use strict;
23 use warnings;
25 my %DEPS;
26 my @CYCLES;
27 sub find_all_cycles;
29 # Read our dependency information.
30 while (<>) {
31 chomp;
32 my ($module, $dependency_str) = /^\s*([^:]+):\s*(.*)\s*$/;
33 die "Malformed data: $_" unless defined $dependency_str;
34 my @dependencies = split(/ /, $dependency_str);
35 $DEPS{$module} = \@dependencies;
38 # Partition our raw dependencies into sets of cyclically-connected nodes.
39 find_all_cycles();
41 # Print out the finished cycles, with their dependencies.
42 my @output;
43 my $cycles_found = 0;
44 foreach my $cycle (@CYCLES) {
45 my @modules = sort keys %{$cycle};
47 # Merge the dependencies of all modules in this cycle.
48 my %dependencies;
49 foreach my $module (@modules) {
50 @dependencies{@{$DEPS{$module}}} = 1;
53 # Prune the known cyclic dependencies.
54 foreach my $module (@modules) {
55 delete $dependencies{$module};
58 # Warn about possible linker problems.
59 my @archives = grep(/\.a$/, @modules);
60 if (@archives > 1) {
61 $cycles_found = $cycles_found + 1;
62 print STDERR "find-cycles.pl: Circular dependency between *.a files:\n";
63 print STDERR "find-cycles.pl: ", join(' ', @archives), "\n";
64 push @modules, @archives; # WORKAROUND: Duplicate *.a files. Ick.
67 # Add to our output. (@modules is already as sorted as we need it to be.)
68 push @output, (join(' ', @modules) . ': ' .
69 join(' ', sort keys %dependencies) . "\n");
71 print sort @output;
73 exit $cycles_found;
75 #==========================================================================
76 # Depedency Cycle Support
77 #==========================================================================
78 # For now, we have cycles in our dependency graph. Ideally, each cycle
79 # would be collapsed down to a single *.a file, saving us all this work.
81 # To understand this code, you'll need a working knowledge of Perl 5,
82 # and possibly some quality time with 'man perlref'.
84 my %SEEN;
85 my %CYCLES;
86 sub find_cycles ($@);
87 sub found_cycles ($@);
89 sub find_all_cycles {
90 # Find all multi-item cycles.
91 my @modules = sort keys %DEPS;
92 foreach my $module (@modules) { find_cycles($module); }
94 # Build fake one-item "cycles" for the remaining modules, so we can
95 # treat them uniformly.
96 foreach my $module (@modules) {
97 unless (defined $CYCLES{$module}) {
98 my %cycle = ($module, 1);
99 $CYCLES{$module} = \%cycle;
103 # Find all our unique cycles. We have to do this the hard way because
104 # we apparently can't store hash references as hash keys without making
105 # 'strict refs' sad.
106 my %seen;
107 foreach my $cycle (values %CYCLES) {
108 unless ($seen{$cycle}) {
109 $seen{$cycle} = 1;
110 push @CYCLES, $cycle;
115 # Walk through our graph depth-first (keeping a trail in @path), and report
116 # any cycles we find.
117 sub find_cycles ($@) {
118 my ($module, @path) = @_;
119 if (str_in_list($module, @path)) {
120 found_cycle($module, @path);
121 } else {
122 return if defined $SEEN{$module};
123 $SEEN{$module} = 1;
124 foreach my $dep (@{$DEPS{$module}}) {
125 find_cycles($dep, @path, $module);
130 # Give a cycle, attempt to merge it with pre-existing cycle data.
131 sub found_cycle ($@) {
132 my ($module, @path) = @_;
134 # Pop any modules which aren't part of our cycle.
135 while ($path[0] ne $module) { shift @path; }
136 #print join("->", @path, $module) . "\n";
138 # Collect the modules in our cycle into a hash.
139 my %cycle;
140 foreach my $item (@path) {
141 $cycle{$item} = 1;
142 if (defined $CYCLES{$item}) {
143 # Looks like we intersect with an existing cycle, so merge
144 # all those in, too.
145 foreach my $old_item (keys %{$CYCLES{$item}}) {
146 $cycle{$old_item} = 1;
151 # Update our global cycle table.
152 my $cycle_ref = \%cycle;
153 foreach my $item (keys %cycle) {
154 $CYCLES{$item} = $cycle_ref;
156 #print join(":", sort keys %cycle) . "\n";
159 sub str_in_list ($@) {
160 my ($str, @list) = @_;
161 foreach my $item (@list) {
162 return 1 if ($item eq $str);
164 return 0;