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 "[1m", @_, "[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 bitcode, and then 197 compiling the resulting code to a native object file. 198 199 If called as "native-build", it compiles bitcode 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 250