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'; 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 $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: 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 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; 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=pod 181 182=head1 NAME 183 184llvm-native-gxx 185 186=head1 SYNOPSIS 187 188llvm-native-g++ [OPTIONS...] FILE 189 190native-build [OPTIONS...] FILE 191 192=head1 DESCRIPTION 193 194llvm-native-g++ is a wrapper around the LLVM command-line tools which generates 195a 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 then 197compiling the resulting code to a native object file. 198 199If called as "native-build", it compiles bitcode to native code, and takes 200different options. 201 202=head1 OPTIONS 203 204llvm-native-g++ takes the same options as llvm-gcc. All options 205except -mllvm-backend=... are passed on to llvm-g++. 206 207=over 4 208 209=item -mllvm-backend=BACKEND 210 211Use BACKEND for native code generation. 212 213=item -v 214 215Print command lines that llvm-native-g++ runs. 216 217=item -o FILE 218 219llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking 220for this option in the command line. If it can't find it, it finds the last C 221or C++ source file named on the command line, and turns its suffix into .o. See 222BUGS. 223 224=item -save-temps 225 226Save temporary files used by llvm-native-g++ (and llvm-g++, and g++). 227 228=back 229 230=head1 BUGS 231 232llvm-native-g++ only handles the case where llvm-g++ compiles a single 233file per invocation. llvm-native-g++ has weak command-line argument 234parsing 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 two 239other scripts that predated it. It could use some code clean-up. 240 241=head1 SEE ALSO 242 243g++(1) 244 245=head1 AUTHOR 246 247Brian R. Gaeke 248 249=cut 250