C++ version of llvm-native-gcc.
authorJohn Criswell <criswell@uiuc.edu>
Thu, 26 Feb 2004 23:01:21 +0000 (23:01 +0000)
committerJohn Criswell <criswell@uiuc.edu>
Thu, 26 Feb 2004 23:01:21 +0000 (23:01 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11887 91177308-0d34-0410-b5e6-96231b3b80d8

utils/llvm-native-gxx [new file with mode: 0755]

diff --git a/utils/llvm-native-gxx b/utils/llvm-native-gxx
new file mode 100755 (executable)
index 0000000..75164af
--- /dev/null
@@ -0,0 +1,249 @@
+#!/usr/bin/perl
+# Wrapper around LLVM tools to generate a native .o from llvm-gxx using an
+# LLVM back-end (CBE by default).
+
+# set up defaults.
+$Verbose = 0;
+$SaveTemps = 1;
+$PreprocessOnly = 0;
+$CompileDontLink = 0;
+$Backend = 'cbe';
+chomp ($ProgramName = `basename $0`);
+
+sub boldprint {
+       print "\e[1m", @_, "\e[0m";
+}
+
+# process command-line options.
+# most of these are passed on to llvm-gxx.
+$GCCOptions = "";
+for ($i = 0; $i <= $#ARGV; ++$i) {     
+       if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) {
+               $Backend = $1;
+               if ($ProgramName =~ /llvm-native-gxx/) {
+                       splice (@ARGV, $i, 1);
+                       --$i;
+               }
+       } elsif ($ARGV[$i] eq "-E") {
+               $PreprocessOnly = 1;
+       } elsif ($ARGV[$i] eq "-c") {
+               $GCCOptions .= " " . $ARGV[$i];
+               $CompileDontLink = 1;
+       } elsif ($ARGV[$i] eq "-v") {
+               $GCCOptions .= " " . $ARGV[$i];
+               $Verbose = 1;
+       } elsif ($ARGV[$i] eq "-o") {
+               $OutputFile = $ARGV[$i + 1];
+       } elsif ($ARGV[$i] eq "-save-temps") {
+               $GCCOptions .= " " . $ARGV[$i];
+               $SaveTemps = 1;
+       } elsif ($ARGV[$i] =~ /\.bc$/) {
+               push (@BytecodeFiles, $ARGV[$i]);
+       } elsif ($ARGV[$i] =~ /^-L/) {
+               $GCCOptions .= " " . $ARGV[$i];
+               push (@LibDirs, $ARGV[$i]);
+       } elsif ($ARGV[$i] =~ /^-l/) {
+               $GCCOptions .= " " . $ARGV[$i];
+               push (@Libs, $ARGV[$i]);
+       } elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) {
+               $LastCFile = $ARGV[$i];
+       }
+}
+
+sub GetDefaultOutputFileName {
+       my $DefaultOutputFileBase;
+
+       if ($ProgramName =~ /llvm-native-gxx/) {
+               $DefaultOutputFileBase = $LastCFile;
+       } elsif ($ProgramName =~ /native-build/) {
+               $DefaultOutputFileBase = $BytecodeFiles[0];
+       }
+
+       my $def = $DefaultOutputFileBase;
+
+       die "Can't figure out name of output file.\n"
+               unless $DefaultOutputFileBase
+                          && (($ProgramName !~ /native-build/)
+                                  || $#BytecodeFiles == 0);
+
+       print "Warning: defaulting output file name ",
+               "based on '$DefaultOutputFileBase'\n" if $Verbose;
+
+       if ($ProgramName =~ /llvm-native-gxx/) {
+               $def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/;
+       } elsif ($ProgramName =~ /native-build/) {
+               $def =~ s/\.bc$/.$Backend/;
+               if ($CompileDontLink) {
+                       $def .= ".o";
+               }
+       }
+
+       return $def;
+}
+
+# run a command, optionally echoing, and quitting if it fails:
+sub run {
+       my $command = join(" ", @_);
+       print "$command\n" if $Verbose;
+       $command =~ s/\"/\\\"/g;
+       system $command and die "$0: $command failed";
+}
+
+sub LinkBytecodeFilesIntoTemporary {
+       my $FinalOutputFileName = shift @_;
+       my @BytecodeFiles = @_;
+
+       my $BCFiles = join (" ", @BytecodeFiles);
+       my $LinkedBCFile;
+       if ($SaveTemps) {
+               $LinkedBCFile = "${FinalOutputFileName}.llvm.bc";
+       } else {
+               $LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc";
+       }
+       run "llvm-link -o $LinkedBCFile $BCFiles";
+       return $LinkedBCFile;
+}
+
+sub CompileBytecodeToNative {
+       my ($BCFile, $Backend, $OutputFile) = @_;
+
+       my $GeneratedCode;
+       if ($Backend eq 'cbe') {
+               if ($SaveTemps) {
+                       $GeneratedCode = "${OutputFile}.c";
+               } else {
+                       $GeneratedCode = "/tmp/nativebuild-$$.c";
+               }
+               run "llc -march=c -f -o $GeneratedCode $BCFile";
+       } elsif ($Backend eq 'llc') {
+               if ($SaveTemps) {
+                       $GeneratedCode = "${OutputFile}.s";
+               } else {
+                       $GeneratedCode = "/tmp/nativebuild-$$.s";
+               }
+               run "llc -f -o $GeneratedCode $BCFile";
+       }
+       my $LibDirs = join (" ", @LibDirs);
+       my $Libs = join (" ", @Libs);
+       run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs";
+       run "rm $BCFile $GeneratedCode"
+               unless $SaveTemps;
+}
+
+sub CompileCToNative {
+       my ($LLVMGCCCommand, $Backend, $OutputFile) = @_;
+       run $LLVMGCCCommand;
+       if ($PreprocessOnly) {
+               return;
+       }
+       my $BCFile = "${OutputFile}.llvm.bc";
+       if ($CompileDontLink) {
+               run "mv ${OutputFile} $BCFile";
+       } else { # gccld messes with the output file name
+               run "mv ${OutputFile}.bc $BCFile";
+       }
+       my $GeneratedCode;
+       if ($Backend eq 'cbe') {
+               $GeneratedCode = "${OutputFile}.cbe.c";
+               run "llc -march=c -f -o $GeneratedCode $BCFile";
+       } elsif ($Backend eq 'llc') {
+               $GeneratedCode = "${OutputFile}.llc.s";
+               run "llc -f -o $GeneratedCode $BCFile";
+       }
+       my $NativeGCCOptions = "";
+       if ($CompileDontLink) {
+               $NativeGCCOptions = "-c";
+       }
+       run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile";
+       run "rm ${OutputFile}.llvm.bc $GeneratedCode"
+               unless $SaveTemps;
+}
+
+# guess the name of the output file, if -o was not specified.
+$OutputFile = GetDefaultOutputFileName () unless $OutputFile;
+print "Output file is $OutputFile\n" if $Verbose;
+# do all the dirty work:
+if ($ProgramName eq /native-build/) {
+       my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles);
+       CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile);
+} elsif ($ProgramName =~ /llvm-native-gxx/) {
+       # build the llvm-gxx command line.
+       $LLVMGCCCommand = join (" ", ("llvm-g++", @ARGV));
+       CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile);
+}
+
+# we're done.
+exit 0;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+llvm-native-gxx
+
+=head1 SYNOPSIS
+
+llvm-native-g++ [OPTIONS...] FILE
+
+native-build [OPTIONS...] FILE
+
+=head1 DESCRIPTION
+
+llvm-native-g++ is a wrapper around the LLVM command-line tools which generates
+a native object (.o) file by compiling FILE with llvm-g++, and then running 
+an LLVM back-end (CBE by default) over the resulting bytecode, and then
+compiling the resulting code to a native object file.
+
+If called as "native-build", it compiles bytecode to native code, and takes
+different options.
+
+=head1 OPTIONS
+
+llvm-native-g++ takes the same options as llvm-gcc. All options
+except -mllvm-backend=... are passed on to llvm-g++.
+
+=over 4
+
+=item -mllvm-backend=BACKEND
+
+Use BACKEND for native code generation. 
+
+=item -v
+
+Print command lines that llvm-native-g++ runs.
+
+=item -o FILE
+
+llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking
+for this option in the command line. If it can't find it, it finds the last C
+or C++ source file named on the command line, and turns its suffix into .o. See
+BUGS.
+
+=item -save-temps
+
+Save temporary files used by llvm-native-g++ (and llvm-g++, and g++).
+
+=back
+
+=head1 BUGS
+
+llvm-native-g++ only handles the case where llvm-g++ compiles a single
+file per invocation.  llvm-native-g++ has weak command-line argument
+parsing and is a poor substitute for making g++/g++.c do this stuff.
+
+This manual page does not adequately document native-build mode.
+
+llvm-native-g++ is pretty gross because it represents the blind merging of two
+other scripts that predated it. It could use some code clean-up.
+
+=head1 SEE ALSO
+
+g++(1)
+
+=head1 AUTHOR
+
+Brian R. Gaeke
+
+=cut