Home | History | Annotate | Download | only in utils
      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