250 lines · plain
1#!/usr/bin/env perl2# Wrapper around LLVM tools to generate a native .o from llvm-gxx using an3# 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';11chomp ($ProgramName = `basename $0`);12 13sub boldprint {14 print "[1m", @_, "[0m";15}16 17# process command-line options.18# most of these are passed on to llvm-gxx.19$GCCOptions = "";20for ($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 53sub 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 $DefaultOutputFileBase66 && (($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:85sub 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 92sub 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 107sub 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 133sub 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 name143 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;164print "Output file is $OutputFile\n" if $Verbose;165# do all the dirty work:166if ($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.176exit 0;177 178__END__179 180=pod181 182=head1 NAME183 184llvm-native-gxx185 186=head1 SYNOPSIS187 188llvm-native-g++ [OPTIONS...] FILE189 190native-build [OPTIONS...] FILE191 192=head1 DESCRIPTION193 194llvm-native-g++ is a wrapper around the LLVM command-line tools which generates195a native object (.o) file by compiling FILE with llvm-g++, and then running 196an LLVM back-end (CBE by default) over the resulting bitcode, and then197compiling the resulting code to a native object file.198 199If called as "native-build", it compiles bitcode to native code, and takes200different options.201 202=head1 OPTIONS203 204llvm-native-g++ takes the same options as llvm-gcc. All options205except -mllvm-backend=... are passed on to llvm-g++.206 207=over 4208 209=item -mllvm-backend=BACKEND210 211Use BACKEND for native code generation. 212 213=item -v214 215Print command lines that llvm-native-g++ runs.216 217=item -o FILE218 219llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking220for this option in the command line. If it can't find it, it finds the last C221or C++ source file named on the command line, and turns its suffix into .o. See222BUGS.223 224=item -save-temps225 226Save temporary files used by llvm-native-g++ (and llvm-g++, and g++).227 228=back229 230=head1 BUGS231 232llvm-native-g++ only handles the case where llvm-g++ compiles a single233file per invocation. llvm-native-g++ has weak command-line argument234parsing and is a poor substitute for making g++/g++.c do this stuff.235 236This manual page does not adequately document native-build mode.237 238llvm-native-g++ is pretty gross because it represents the blind merging of two239other scripts that predated it. It could use some code clean-up.240 241=head1 SEE ALSO242 243g++(1)244 245=head1 AUTHOR246 247Brian R. Gaeke248 249=cut250