aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xutils/llvm-native-gxx249
1 files changed, 249 insertions, 0 deletions
diff --git a/utils/llvm-native-gxx b/utils/llvm-native-gxx
new file mode 100755
index 0000000000..75164af237
--- /dev/null
+++ b/utils/llvm-native-gxx
@@ -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 "", @_, "";
+}
+
+# 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