llvm-native-gxx 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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. # set up defaults.
  5. $Verbose = 0;
  6. $SaveTemps = 1;
  7. $PreprocessOnly = 0;
  8. $CompileDontLink = 0;
  9. $Backend = 'cbe';
  10. chomp ($ProgramName = `basename $0`);
  11. sub boldprint {
  12. print "", @_, "";
  13. }
  14. # process command-line options.
  15. # most of these are passed on to llvm-gxx.
  16. $GCCOptions = "";
  17. for ($i = 0; $i <= $#ARGV; ++$i) {
  18. if ($ARGV[$i] =~ /-mllvm-backend=([a-z0-9]*)/) {
  19. $Backend = $1;
  20. if ($ProgramName =~ /llvm-native-gxx/) {
  21. splice (@ARGV, $i, 1);
  22. --$i;
  23. }
  24. } elsif ($ARGV[$i] eq "-E") {
  25. $PreprocessOnly = 1;
  26. } elsif ($ARGV[$i] eq "-c") {
  27. $GCCOptions .= " " . $ARGV[$i];
  28. $CompileDontLink = 1;
  29. } elsif ($ARGV[$i] eq "-v") {
  30. $GCCOptions .= " " . $ARGV[$i];
  31. $Verbose = 1;
  32. } elsif ($ARGV[$i] eq "-o") {
  33. $OutputFile = $ARGV[$i + 1];
  34. } elsif ($ARGV[$i] eq "-save-temps") {
  35. $GCCOptions .= " " . $ARGV[$i];
  36. $SaveTemps = 1;
  37. } elsif ($ARGV[$i] =~ /\.bc$/) {
  38. push (@BytecodeFiles, $ARGV[$i]);
  39. } elsif ($ARGV[$i] =~ /^-L/) {
  40. $GCCOptions .= " " . $ARGV[$i];
  41. push (@LibDirs, $ARGV[$i]);
  42. } elsif ($ARGV[$i] =~ /^-l/) {
  43. $GCCOptions .= " " . $ARGV[$i];
  44. push (@Libs, $ARGV[$i]);
  45. } elsif ($ARGV[$i] =~ /\.(c|cpp|cc|i|ii|C)$/) {
  46. $LastCFile = $ARGV[$i];
  47. }
  48. }
  49. sub GetDefaultOutputFileName {
  50. my $DefaultOutputFileBase;
  51. if ($ProgramName =~ /llvm-native-gxx/) {
  52. $DefaultOutputFileBase = $LastCFile;
  53. } elsif ($ProgramName =~ /native-build/) {
  54. $DefaultOutputFileBase = $BytecodeFiles[0];
  55. }
  56. my $def = $DefaultOutputFileBase;
  57. die "Can't figure out name of output file.\n"
  58. unless $DefaultOutputFileBase
  59. && (($ProgramName !~ /native-build/)
  60. || $#BytecodeFiles == 0);
  61. print "Warning: defaulting output file name ",
  62. "based on '$DefaultOutputFileBase'\n" if $Verbose;
  63. if ($ProgramName =~ /llvm-native-gxx/) {
  64. $def =~ s/\.(c|cpp|cc|i|ii|C)$/.o/;
  65. } elsif ($ProgramName =~ /native-build/) {
  66. $def =~ s/\.bc$/.$Backend/;
  67. if ($CompileDontLink) {
  68. $def .= ".o";
  69. }
  70. }
  71. return $def;
  72. }
  73. # run a command, optionally echoing, and quitting if it fails:
  74. sub run {
  75. my $command = join(" ", @_);
  76. print "$command\n" if $Verbose;
  77. $command =~ s/\"/\\\"/g;
  78. system $command and die "$0: $command failed";
  79. }
  80. sub LinkBytecodeFilesIntoTemporary {
  81. my $FinalOutputFileName = shift @_;
  82. my @BytecodeFiles = @_;
  83. my $BCFiles = join (" ", @BytecodeFiles);
  84. my $LinkedBCFile;
  85. if ($SaveTemps) {
  86. $LinkedBCFile = "${FinalOutputFileName}.llvm.bc";
  87. } else {
  88. $LinkedBCFile = "/tmp/nativebuild-$$.llvm.bc";
  89. }
  90. run "llvm-link -o $LinkedBCFile $BCFiles";
  91. return $LinkedBCFile;
  92. }
  93. sub CompileBytecodeToNative {
  94. my ($BCFile, $Backend, $OutputFile) = @_;
  95. my $GeneratedCode;
  96. if ($Backend eq 'cbe') {
  97. if ($SaveTemps) {
  98. $GeneratedCode = "${OutputFile}.c";
  99. } else {
  100. $GeneratedCode = "/tmp/nativebuild-$$.c";
  101. }
  102. run "llc -march=c -f -o $GeneratedCode $BCFile";
  103. } elsif ($Backend eq 'llc') {
  104. if ($SaveTemps) {
  105. $GeneratedCode = "${OutputFile}.s";
  106. } else {
  107. $GeneratedCode = "/tmp/nativebuild-$$.s";
  108. }
  109. run "llc -f -o $GeneratedCode $BCFile";
  110. }
  111. my $LibDirs = join (" ", @LibDirs);
  112. my $Libs = join (" ", @Libs);
  113. run "gcc $GCCOptions $GeneratedCode -o $OutputFile $LibDirs $Libs";
  114. run "rm $BCFile $GeneratedCode"
  115. unless $SaveTemps;
  116. }
  117. sub CompileCToNative {
  118. my ($LLVMGCCCommand, $Backend, $OutputFile) = @_;
  119. run $LLVMGCCCommand;
  120. if ($PreprocessOnly) {
  121. return;
  122. }
  123. my $BCFile = "${OutputFile}.llvm.bc";
  124. if ($CompileDontLink) {
  125. run "mv ${OutputFile} $BCFile";
  126. } else { # gccld messes with the output file name
  127. run "mv ${OutputFile}.bc $BCFile";
  128. }
  129. my $GeneratedCode;
  130. if ($Backend eq 'cbe') {
  131. $GeneratedCode = "${OutputFile}.cbe.c";
  132. run "llc -march=c -f -o $GeneratedCode $BCFile";
  133. } elsif ($Backend eq 'llc') {
  134. $GeneratedCode = "${OutputFile}.llc.s";
  135. run "llc -f -o $GeneratedCode $BCFile";
  136. }
  137. my $NativeGCCOptions = "";
  138. if ($CompileDontLink) {
  139. $NativeGCCOptions = "-c";
  140. }
  141. run "gcc $NativeGCCOptions $GeneratedCode -o $OutputFile";
  142. run "rm ${OutputFile}.llvm.bc $GeneratedCode"
  143. unless $SaveTemps;
  144. }
  145. # guess the name of the output file, if -o was not specified.
  146. $OutputFile = GetDefaultOutputFileName () unless $OutputFile;
  147. print "Output file is $OutputFile\n" if $Verbose;
  148. # do all the dirty work:
  149. if ($ProgramName eq /native-build/) {
  150. my $LinkedBCFile = LinkBytecodeFilesIntoTemporary (@BytecodeFiles);
  151. CompileBytecodeToNative ($LinkedBCFile, $Backend, $OutputFile);
  152. } elsif ($ProgramName =~ /llvm-native-gxx/) {
  153. # build the llvm-gxx command line.
  154. $LLVMGCCCommand = join (" ", ("llvm-g++", @ARGV));
  155. CompileCToNative ($LLVMGCCCommand, $Backend, $OutputFile);
  156. }
  157. # we're done.
  158. exit 0;
  159. __END__
  160. =pod
  161. =head1 NAME
  162. llvm-native-gxx
  163. =head1 SYNOPSIS
  164. llvm-native-g++ [OPTIONS...] FILE
  165. native-build [OPTIONS...] FILE
  166. =head1 DESCRIPTION
  167. llvm-native-g++ is a wrapper around the LLVM command-line tools which generates
  168. a native object (.o) file by compiling FILE with llvm-g++, and then running
  169. an LLVM back-end (CBE by default) over the resulting bitcode, and then
  170. compiling the resulting code to a native object file.
  171. If called as "native-build", it compiles bitcode to native code, and takes
  172. different options.
  173. =head1 OPTIONS
  174. llvm-native-g++ takes the same options as llvm-gcc. All options
  175. except -mllvm-backend=... are passed on to llvm-g++.
  176. =over 4
  177. =item -mllvm-backend=BACKEND
  178. Use BACKEND for native code generation.
  179. =item -v
  180. Print command lines that llvm-native-g++ runs.
  181. =item -o FILE
  182. llvm-native-g++ tries to guess the name of the llvm-g++ output file by looking
  183. for this option in the command line. If it can't find it, it finds the last C
  184. or C++ source file named on the command line, and turns its suffix into .o. See
  185. BUGS.
  186. =item -save-temps
  187. Save temporary files used by llvm-native-g++ (and llvm-g++, and g++).
  188. =back
  189. =head1 BUGS
  190. llvm-native-g++ only handles the case where llvm-g++ compiles a single
  191. file per invocation. llvm-native-g++ has weak command-line argument
  192. parsing and is a poor substitute for making g++/g++.c do this stuff.
  193. This manual page does not adequately document native-build mode.
  194. llvm-native-g++ is pretty gross because it represents the blind merging of two
  195. other scripts that predated it. It could use some code clean-up.
  196. =head1 SEE ALSO
  197. g++(1)
  198. =head1 AUTHOR
  199. Brian R. Gaeke
  200. =cut