You've already forked linux-packaging-mono
							
							
		
			
				
	
	
		
			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
 |