//
//===----------------------------------------------------------------------===//
-#include "llvm/Transforms/Linker.h"
-#include "llvm/Bytecode/Reader.h"
-#include "llvm/Bytecode/Writer.h"
+#include "llvm/Transforms/Utils/Linker.h"
#include "llvm/Module.h"
-#include "llvm/Method.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bytecode/Reader.h"
+#include "llvm/Bytecode/WriteBytecodePass.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
#include "Support/CommandLine.h"
+#include "Support/Signals.h"
#include <fstream>
#include <memory>
#include <algorithm>
#include <sys/types.h> // For FileExists
#include <sys/stat.h>
+using std::cerr;
+
+static cl::list<std::string>
+InputFilenames(cl::Positional, cl::desc("<input bytecode files>"),
+ cl::OneOrMore);
+
+static cl::opt<std::string>
+OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"),
+ cl::value_desc("filename"));
+
+static cl::opt<bool>
+Verbose("v", cl::desc("Print information about actions taken"));
+static cl::list<std::string>
+LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix,
+ cl::value_desc("directory"));
-cl::StringList InputFilenames("", "Load <arg> files, linking them together",
- cl::OneOrMore);
-cl::String OutputFilename("o", "Override output filename", cl::NoFlags,"a.out");
-cl::Flag Verbose ("v", "Print information about actions taken");
-cl::StringList LibPaths ("L", "Specify a library search path", cl::ZeroOrMore);
-cl::StringList Libraries ("l", "Specify libraries to link to", cl::ZeroOrMore);
+static cl::list<std::string>
+Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix,
+ cl::value_desc("library prefix"));
+
+static cl::opt<bool>
+Strip("s", cl::desc("Strip symbol info from executable"));
// FileExists - Return true if the specified string is an openable file...
if (Verbose) {
cerr << "Error opening bytecode file: '" << Filename << "'";
if (ErrorMessage.size()) cerr << ": " << ErrorMessage;
- cerr << endl;
+ cerr << "\n";
}
if (NextLibPathIdx == LibPaths.size()) break;
}
-
-
int main(int argc, char **argv) {
- cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n",
- cl::EnableSingleLetterArgValue |
- cl::DisableSingleLetterArgGrouping);
- assert(InputFilenames.size() > 0 && "OneOrMore is not working");
+ cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n");
unsigned BaseArg = 0;
std::string ErrorMessage;
if (!Libraries.empty()) {
// Sort libraries list...
- sort(Libraries.begin(), Libraries.end());
+ std::sort(Libraries.begin(), Libraries.end());
// Remove duplicate libraries entries...
Libraries.erase(unique(Libraries.begin(), Libraries.end()),
if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n";
if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) {
- cerr << "Error linking in '" << InputFilenames[i] << "': "
- << ErrorMessage << endl;
+ cerr << argv[0] << ": error linking in '" << InputFilenames[i] << "': "
+ << ErrorMessage << "\n";
return 1;
}
}
+ // In addition to just linking the input from GCC, we also want to spiff it up
+ // a little bit. Do this now.
+ //
+ PassManager Passes;
+
+ // Linking modules together can lead to duplicated global constants, only keep
+ // one copy of each constant...
+ //
+ Passes.add(createConstantMergePass());
+
+ // If the -s command line option was specified, strip the symbols out of the
+ // resulting program to make it smaller. -s is a GCC option that we are
+ // supporting.
+ //
+ if (Strip)
+ Passes.add(createSymbolStrippingPass());
+
+ // Often if the programmer does not specify proper prototypes for the
+ // functions they are calling, they end up calling a vararg version of the
+ // function that does not get a body filled in (the real function has typed
+ // arguments). This pass merges the two functions.
+ //
+ Passes.add(createFunctionResolvingPass());
+
+ // Now that composite has been compiled, scan through the module, looking for
+ // a main function. If main is defined, mark all other functions internal.
+ //
+ Passes.add(createInternalizePass());
+
+ // Now that we have optimized the program, discard unreachable functions...
+ //
+ Passes.add(createGlobalDCEPass());
+
+ // Add the pass that writes bytecode to the output file...
std::ofstream Out((OutputFilename+".bc").c_str());
if (!Out.good()) {
- cerr << "Error opening '" << OutputFilename << ".bc' for writing!\n";
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << ".bc' for writing!\n";
return 1;
}
+ Passes.add(new WriteBytecodePass(&Out)); // Write bytecode to file...
+
+ // Make sure that the Out file gets unlink'd from the disk if we get a SIGINT
+ RemoveFileOnSignal(OutputFilename+".bc");
- if (Verbose) cerr << "Writing bytecode...\n";
- WriteBytecodeToFile(Composite.get(), Out);
+ // Run our queue of passes all at once now, efficiently.
+ Passes.run(*Composite.get());
Out.close();
// Output the script to start the program...
std::ofstream Out2(OutputFilename.c_str());
if (!Out2.good()) {
- cerr << "Error openeing '" << OutputFilename << "' for writing!\n";
+ cerr << argv[0] << ": error opening '" << OutputFilename
+ << "' for writing!\n";
return 1;
}
Out2 << "#!/bin/sh\nlli -q $0.bc $*\n";