Fix grammaro in a comment.
[oota-llvm.git] / utils / llvm-native-gxx
1 #!/usr/bin/perl
2 # Wrapper around LLVM tools to generate a native .o from llvm-gxx using an
3 # LLVM back-end (CBE by default).
4
5 # set up defaults.
6 $Verbose = 0;
7 $SaveTemps = 1;
8 $PreprocessOnly = 0;
9 $CompileDontLink = 0;
10 $Backend = 'cbe';
11 chomp ($ProgramName = `basename $0`);
12
13 sub boldprint {
14         print "\e[1m", @_, "\e[0m";
15 }
16
17 # process command-line options.
18 # most of these are passed on to llvm-gxx.
19 $GCCOptions = "";
20 for ($i = 0; $i <= $#ARGV; ++$i) {      
21         if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) {
22                 $Backend = $1;
23                 if ($ProgramName =~ /llvm-native-gxx/) {
24                         splice (@ARGV, $i, 1);
25                         --$i;
26                 }
27         } elsif ($ARGV[$i] eq "-E") {
28                 $PreprocessOnly = 1;
29         } elsif ($ARGV[$i] eq "-c") {
30                 $GCCOptions .= " " . $ARGV[$i];
31                 $CompileDontLink = 1;
32         } elsif ($ARGV[$i] eq "-v") {
33                 $GCCOptions .= " " . $ARGV[$i];
34                 $Verbose = 1;
35         } elsif ($ARGV[$i] eq "-o") {
36                 $OutputFile = $ARGV[$i + 1];
37         } elsif ($ARGV[$i] eq "-save-temps") {
38                 $GCCOptions .= " " . $ARGV[$i];
39                 $SaveTemps = 1;
40         } elsif ($ARGV[$i] =~ /\.bc$/) {
41                 push (@BytecodeFiles, $ARGV[$i]);
42         } elsif ($ARGV[$i] =~ /^-L/) {
43                 $GCCOptions .= " " . $ARGV[$i];
44                 push (@LibDirs, $ARGV[$i]);
45         } elsif ($ARGV[$i] =~ /^-l/) {
46                 $GCCOptions .= " " . $ARGV[$i];
47                 push (@Libs, $ARGV[$i]);
48         } elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) {
49                 $LastCFile = $ARGV[$i];
50         }
51 }
52
53 sub GetDefaultOutputFileName {
54         my $DefaultOutputFileBase;
55
56         if ($ProgramName =~ /llvm-native-gxx/) {
57                 $DefaultOutputFileBase = $LastCFile;
58         } elsif ($ProgramName =~ /native-build/) {
59                 $DefaultOutputFileBase = $BytecodeFiles[0];
60         }
61
62         my $def = $DefaultOutputFileBase;
63
64         die "Can't figure out name of output file.\n"
65                 unless $DefaultOutputFileBase
66                            && (($ProgramName !~ /native-build/)
67                                    || $#BytecodeFiles == 0);
68
69         print "Warning: defaulting output file name ",
70                 "based on '$DefaultOutputFileBase'\n" if $Verbose;
71
72         if ($ProgramName =~ /llvm-native-gxx/) {
73                 $def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/;
74         } elsif ($ProgramName =~ /native-build/) {
75                 $def =~ s/\.bc$/.$Backend/;
76                 if ($CompileDontLink) {
77                         $def .= ".o";
78                 }
79         }
80
81         return $def;
82 }
83
84 # run a command, optionally echoing, and quitting if it fails:
85 sub run {
86         my $command = join(" ", @_);
87         print "$command\n" if $Verbose;
88         $command =~ s/\"/\\\"/g;
89         system $command and die "$0: $command failed";
90 }
91
92 sub LinkBytecodeFilesIntoTemporary {
93         my $FinalOutputFileName = shift @_;
94         my @BytecodeFiles = @_;
95
96         my $BCFiles = join (" ", @BytecodeFiles);
97         my $LinkedBCFile;
98         if ($SaveTemps) {
99                 $LinkedBCFile = "${FinalOutputFileName}.llvm.bc";
100         } else {
101                 $LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc";
102         }
103         run "llvm-link -o $LinkedBCFile $BCFiles";
104         return $LinkedBCFile;
105 }
106
107 sub CompileBytecodeToNative {
108         my ($BCFile, $Backend, $OutputFile) = @_;
109
110         my $GeneratedCode;
111         if ($Backend eq 'cbe') {
112                 if ($SaveTemps) {
113                         $GeneratedCode = "${OutputFile}.c";
114                 } else {
115                         $GeneratedCode = "/tmp/nativebuild-$$.c";
116                 }
117                 run "llc -march=c -f -o $GeneratedCode $BCFile";
118         } elsif ($Backend eq 'llc') {
119                 if ($SaveTemps) {
120                         $GeneratedCode = "${OutputFile}.s";
121                 } else {
122                         $GeneratedCode = "/tmp/nativebuild-$$.s";
123                 }
124                 run "llc -f -o $GeneratedCode $BCFile";
125         }
126         my $LibDirs = join (" ", @LibDirs);
127         my $Libs = join (" ", @Libs);
128         run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs";
129         run "rm $BCFile $GeneratedCode"
130                 unless $SaveTemps;
131 }
132
133 sub CompileCToNative {
134         my ($LLVMGCCCommand, $Backend, $OutputFile) = @_;
135         run $LLVMGCCCommand;
136         if ($PreprocessOnly) {
137                 return;
138         }
139         my $BCFile = "${OutputFile}.llvm.bc";
140         if ($CompileDontLink) {
141                 run "mv ${OutputFile} $BCFile";
142         } else { # gccld messes with the output file name
143                 run "mv ${OutputFile}.bc $BCFile";
144         }
145         my $GeneratedCode;
146         if ($Backend eq 'cbe') {
147                 $GeneratedCode = "${OutputFile}.cbe.c";
148                 run "llc -march=c -f -o $GeneratedCode $BCFile";
149         } elsif ($Backend eq 'llc') {
150                 $GeneratedCode = "${OutputFile}.llc.s";
151                 run "llc -f -o $GeneratedCode $BCFile";
152         }
153         my $NativeGCCOptions = "";
154         if ($CompileDontLink) {
155                 $NativeGCCOptions = "-c";
156         }
157         run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile";
158         run "rm ${OutputFile}.llvm.bc $GeneratedCode"
159                 unless $SaveTemps;
160 }
161
162 # guess the name of the output file, if -o was not specified.
163 $OutputFile = GetDefaultOutputFileName () unless $OutputFile;
164 print "Output file is $OutputFile\n" if $Verbose;
165 # do all the dirty work:
166 if ($ProgramName eq /native-build/) {
167         my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles);
168         CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile);
169 } elsif ($ProgramName =~ /llvm-native-gxx/) {
170         # build the llvm-gxx command line.
171         $LLVMGCCCommand = join (" ", ("llvm-g++", @ARGV));
172         CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile);
173 }
174
175 # we're done.
176 exit 0;
177
178 __END__
179
180 =pod
181
182 =head1 NAME
183
184 llvm-native-gxx
185
186 =head1 SYNOPSIS
187
188 llvm-native-g++ [OPTIONS...] FILE
189
190 native-build [OPTIONS...] FILE
191
192 =head1 DESCRIPTION
193
194 llvm-native-g++ is a wrapper around the LLVM command-line tools which generates
195 a native object (.o) file by compiling FILE with llvm-g++, and then running 
196 an LLVM back-end (CBE by default) over the resulting bytecode, and then
197 compiling the resulting code to a native object file.
198
199 If called as "native-build", it compiles bytecode to native code, and takes
200 different options.
201
202 =head1 OPTIONS
203
204 llvm-native-g++ takes the same options as llvm-gcc. All options
205 except -mllvm-backend=... are passed on to llvm-g++.
206
207 =over 4
208
209 =item -mllvm-backend=BACKEND
210
211 Use BACKEND for native code generation. 
212
213 =item -v
214
215 Print command lines that llvm-native-g++ runs.
216
217 =item -o FILE
218
219 llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking
220 for this option in the command line. If it can't find it, it finds the last C
221 or C++ source file named on the command line, and turns its suffix into .o. See
222 BUGS.
223
224 =item -save-temps
225
226 Save temporary files used by llvm-native-g++ (and llvm-g++, and g++).
227
228 =back
229
230 =head1 BUGS
231
232 llvm-native-g++ only handles the case where llvm-g++ compiles a single
233 file per invocation.  llvm-native-g++ has weak command-line argument
234 parsing and is a poor substitute for making g++/g++.c do this stuff.
235
236 This manual page does not adequately document native-build mode.
237
238 llvm-native-g++ is pretty gross because it represents the blind merging of two
239 other scripts that predated it. It could use some code clean-up.
240
241 =head1 SEE ALSO
242
243 g++(1)
244
245 =head1 AUTHOR
246
247 Brian R. Gaeke
248
249 =cut