John Criswell | 28ccd02 | 2004-02-26 23:01:21 +0000 | [diff] [blame] | 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 |
Duncan Sands | 18d52f2 | 2010-09-29 20:09:55 +0000 | [diff] [blame] | 196 | an LLVM back-end (CBE by default) over the resulting bitcode, and then |
John Criswell | 28ccd02 | 2004-02-26 23:01:21 +0000 | [diff] [blame] | 197 | compiling the resulting code to a native object file. |
| 198 | |
Duncan Sands | 18d52f2 | 2010-09-29 20:09:55 +0000 | [diff] [blame] | 199 | If called as "native-build", it compiles bitcode to native code, and takes |
John Criswell | 28ccd02 | 2004-02-26 23:01:21 +0000 | [diff] [blame] | 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 |