250 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			250 lines
		
	
	
		
			6.2 KiB
		
	
	
	
		
			Perl
		
	
	
		
			Executable File
		
	
	
#!/usr/bin/perl
 | 
						||
# Wrapper around LLVM tools to generate a native .o from llvm-gxx using an
 | 
						||
# LLVM back-end (CBE by default).
 | 
						||
 | 
						||
# set up defaults.
 | 
						||
$Verbose = 0;
 | 
						||
$SaveTemps = 1;
 | 
						||
$PreprocessOnly = 0;
 | 
						||
$CompileDontLink = 0;
 | 
						||
$Backend = 'cbe';
 | 
						||
chomp ($ProgramName = `basename $0`);
 | 
						||
 | 
						||
sub boldprint {
 | 
						||
	print "[1m", @_, "[0m";
 | 
						||
}
 | 
						||
 | 
						||
# process command-line options.
 | 
						||
# most of these are passed on to llvm-gxx.
 | 
						||
$GCCOptions = "";
 | 
						||
for ($i = 0; $i <= $#ARGV; ++$i) {	
 | 
						||
	if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) {
 | 
						||
		$Backend = $1;
 | 
						||
		if ($ProgramName =~ /llvm-native-gxx/) {
 | 
						||
			splice (@ARGV, $i, 1);
 | 
						||
			--$i;
 | 
						||
		}
 | 
						||
	} elsif ($ARGV[$i] eq "-E") {
 | 
						||
		$PreprocessOnly = 1;
 | 
						||
	} elsif ($ARGV[$i] eq "-c") {
 | 
						||
		$GCCOptions .= " " . $ARGV[$i];
 | 
						||
		$CompileDontLink = 1;
 | 
						||
	} elsif ($ARGV[$i] eq "-v") {
 | 
						||
		$GCCOptions .= " " . $ARGV[$i];
 | 
						||
		$Verbose = 1;
 | 
						||
	} elsif ($ARGV[$i] eq "-o") {
 | 
						||
		$OutputFile = $ARGV[$i + 1];
 | 
						||
	} elsif ($ARGV[$i] eq "-save-temps") {
 | 
						||
		$GCCOptions .= " " . $ARGV[$i];
 | 
						||
		$SaveTemps = 1;
 | 
						||
	} elsif ($ARGV[$i] =~ /\.bc$/) {
 | 
						||
		push (@BytecodeFiles, $ARGV[$i]);
 | 
						||
	} elsif ($ARGV[$i] =~ /^-L/) {
 | 
						||
		$GCCOptions .= " " . $ARGV[$i];
 | 
						||
		push (@LibDirs, $ARGV[$i]);
 | 
						||
	} elsif ($ARGV[$i] =~ /^-l/) {
 | 
						||
		$GCCOptions .= " " . $ARGV[$i];
 | 
						||
		push (@Libs, $ARGV[$i]);
 | 
						||
	} elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) {
 | 
						||
		$LastCFile = $ARGV[$i];
 | 
						||
	}
 | 
						||
}
 | 
						||
 | 
						||
sub GetDefaultOutputFileName {
 | 
						||
	my $DefaultOutputFileBase;
 | 
						||
 | 
						||
	if ($ProgramName =~ /llvm-native-gxx/) {
 | 
						||
		$DefaultOutputFileBase = $LastCFile;
 | 
						||
	} elsif ($ProgramName =~ /native-build/) {
 | 
						||
		$DefaultOutputFileBase = $BytecodeFiles[0];
 | 
						||
	}
 | 
						||
 | 
						||
	my $def = $DefaultOutputFileBase;
 | 
						||
 | 
						||
	die "Can't figure out name of output file.\n"
 | 
						||
		unless $DefaultOutputFileBase
 | 
						||
			   && (($ProgramName !~ /native-build/)
 | 
						||
				   || $#BytecodeFiles == 0);
 | 
						||
 | 
						||
	print "Warning: defaulting output file name ",
 | 
						||
		"based on '$DefaultOutputFileBase'\n" if $Verbose;
 | 
						||
 | 
						||
	if ($ProgramName =~ /llvm-native-gxx/) {
 | 
						||
		$def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/;
 | 
						||
	} elsif ($ProgramName =~ /native-build/) {
 | 
						||
		$def =~ s/\.bc$/.$Backend/;
 | 
						||
		if ($CompileDontLink) {
 | 
						||
			$def .= ".o";
 | 
						||
		}
 | 
						||
	}
 | 
						||
 | 
						||
	return $def;
 | 
						||
}
 | 
						||
 | 
						||
# run a command, optionally echoing, and quitting if it fails:
 | 
						||
sub run {
 | 
						||
	my $command = join(" ", @_);
 | 
						||
	print "$command\n" if $Verbose;
 | 
						||
	$command =~ s/\"/\\\"/g;
 | 
						||
	system $command and die "$0: $command failed";
 | 
						||
}
 | 
						||
 | 
						||
sub LinkBytecodeFilesIntoTemporary {
 | 
						||
	my $FinalOutputFileName = shift @_;
 | 
						||
	my @BytecodeFiles = @_;
 | 
						||
 | 
						||
	my $BCFiles = join (" ", @BytecodeFiles);
 | 
						||
	my $LinkedBCFile;
 | 
						||
	if ($SaveTemps) {
 | 
						||
		$LinkedBCFile = "${FinalOutputFileName}.llvm.bc";
 | 
						||
	} else {
 | 
						||
		$LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc";
 | 
						||
	}
 | 
						||
	run "llvm-link -o $LinkedBCFile $BCFiles";
 | 
						||
	return $LinkedBCFile;
 | 
						||
}
 | 
						||
 | 
						||
sub CompileBytecodeToNative {
 | 
						||
	my ($BCFile, $Backend, $OutputFile) = @_;
 | 
						||
 | 
						||
	my $GeneratedCode;
 | 
						||
	if ($Backend eq 'cbe') {
 | 
						||
		if ($SaveTemps) {
 | 
						||
			$GeneratedCode = "${OutputFile}.c";
 | 
						||
		} else {
 | 
						||
			$GeneratedCode = "/tmp/nativebuild-$$.c";
 | 
						||
		}
 | 
						||
		run "llc -march=c -f -o $GeneratedCode $BCFile";
 | 
						||
	} elsif ($Backend eq 'llc') {
 | 
						||
		if ($SaveTemps) {
 | 
						||
			$GeneratedCode = "${OutputFile}.s";
 | 
						||
		} else {
 | 
						||
			$GeneratedCode = "/tmp/nativebuild-$$.s";
 | 
						||
		}
 | 
						||
		run "llc -f -o $GeneratedCode $BCFile";
 | 
						||
	}
 | 
						||
	my $LibDirs = join (" ", @LibDirs);
 | 
						||
	my $Libs = join (" ", @Libs);
 | 
						||
	run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs";
 | 
						||
	run "rm $BCFile $GeneratedCode"
 | 
						||
		unless $SaveTemps;
 | 
						||
}
 | 
						||
 | 
						||
sub CompileCToNative {
 | 
						||
	my ($LLVMGCCCommand, $Backend, $OutputFile) = @_;
 | 
						||
	run $LLVMGCCCommand;
 | 
						||
	if ($PreprocessOnly) {
 | 
						||
		return;
 | 
						||
	}
 | 
						||
	my $BCFile = "${OutputFile}.llvm.bc";
 | 
						||
	if ($CompileDontLink) {
 | 
						||
		run "mv ${OutputFile} $BCFile";
 | 
						||
	} else { # gccld messes with the output file name
 | 
						||
		run "mv ${OutputFile}.bc $BCFile";
 | 
						||
	}
 | 
						||
	my $GeneratedCode;
 | 
						||
	if ($Backend eq 'cbe') {
 | 
						||
		$GeneratedCode = "${OutputFile}.cbe.c";
 | 
						||
		run "llc -march=c -f -o $GeneratedCode $BCFile";
 | 
						||
	} elsif ($Backend eq 'llc') {
 | 
						||
		$GeneratedCode = "${OutputFile}.llc.s";
 | 
						||
		run "llc -f -o $GeneratedCode $BCFile";
 | 
						||
	}
 | 
						||
	my $NativeGCCOptions = "";
 | 
						||
	if ($CompileDontLink) {
 | 
						||
		$NativeGCCOptions = "-c";
 | 
						||
	}
 | 
						||
	run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile";
 | 
						||
	run "rm ${OutputFile}.llvm.bc $GeneratedCode"
 | 
						||
		unless $SaveTemps;
 | 
						||
}
 | 
						||
 | 
						||
# guess the name of the output file, if -o was not specified.
 | 
						||
$OutputFile = GetDefaultOutputFileName () unless $OutputFile;
 | 
						||
print "Output file is $OutputFile\n" if $Verbose;
 | 
						||
# do all the dirty work:
 | 
						||
if ($ProgramName eq /native-build/) {
 | 
						||
	my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles);
 | 
						||
	CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile);
 | 
						||
} elsif ($ProgramName =~ /llvm-native-gxx/) {
 | 
						||
	# build the llvm-gxx command line.
 | 
						||
	$LLVMGCCCommand = join (" ", ("llvm-g++", @ARGV));
 | 
						||
	CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile);
 | 
						||
}
 | 
						||
 | 
						||
# we're done.
 | 
						||
exit 0;
 | 
						||
 | 
						||
__END__
 | 
						||
 | 
						||
=pod
 | 
						||
 | 
						||
=head1 NAME
 | 
						||
 | 
						||
llvm-native-gxx
 | 
						||
 | 
						||
=head1 SYNOPSIS
 | 
						||
 | 
						||
llvm-native-g++ [OPTIONS...] FILE
 | 
						||
 | 
						||
native-build [OPTIONS...] FILE
 | 
						||
 | 
						||
=head1 DESCRIPTION
 | 
						||
 | 
						||
llvm-native-g++ is a wrapper around the LLVM command-line tools which generates
 | 
						||
a native object (.o) file by compiling FILE with llvm-g++, and then running 
 | 
						||
an LLVM back-end (CBE by default) over the resulting bitcode, and then
 | 
						||
compiling the resulting code to a native object file.
 | 
						||
 | 
						||
If called as "native-build", it compiles bitcode to native code, and takes
 | 
						||
different options.
 | 
						||
 | 
						||
=head1 OPTIONS
 | 
						||
 | 
						||
llvm-native-g++ takes the same options as llvm-gcc. All options
 | 
						||
except -mllvm-backend=... are passed on to llvm-g++.
 | 
						||
 | 
						||
=over 4
 | 
						||
 | 
						||
=item -mllvm-backend=BACKEND
 | 
						||
 | 
						||
Use BACKEND for native code generation. 
 | 
						||
 | 
						||
=item -v
 | 
						||
 | 
						||
Print command lines that llvm-native-g++ runs.
 | 
						||
 | 
						||
=item -o FILE
 | 
						||
 | 
						||
llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking
 | 
						||
for this option in the command line. If it can't find it, it finds the last C
 | 
						||
or C++ source file named on the command line, and turns its suffix into .o. See
 | 
						||
BUGS.
 | 
						||
 | 
						||
=item -save-temps
 | 
						||
 | 
						||
Save temporary files used by llvm-native-g++ (and llvm-g++, and g++).
 | 
						||
 | 
						||
=back
 | 
						||
 | 
						||
=head1 BUGS
 | 
						||
 | 
						||
llvm-native-g++ only handles the case where llvm-g++ compiles a single
 | 
						||
file per invocation.  llvm-native-g++ has weak command-line argument
 | 
						||
parsing and is a poor substitute for making g++/g++.c do this stuff.
 | 
						||
 | 
						||
This manual page does not adequately document native-build mode.
 | 
						||
 | 
						||
llvm-native-g++ is pretty gross because it represents the blind merging of two
 | 
						||
other scripts that predated it. It could use some code clean-up.
 | 
						||
 | 
						||
=head1 SEE ALSO
 | 
						||
 | 
						||
g++(1)
 | 
						||
 | 
						||
=head1 AUTHOR
 | 
						||
 | 
						||
Brian R. Gaeke
 | 
						||
 | 
						||
=cut
 |