#include "llvm/Transforms/Scalar.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/CommandLine.h"
-
+#include "llvm/Support/Streams.h"
using namespace llvm;
namespace {
cl::opt<bool>
DisableOptimizations("disable-opt",
cl::desc("Do not run any optimization passes"));
+
+ cl::opt<bool>
+ NoCompress("disable-compression", cl::init(true),
+ cl::desc("Don't compress the generated bytecode"));
}
/// CopyEnv - This function takes an array of environment variables and makes a
}
static void dumpArgs(const char **args) {
- std::cerr << *args++;
+ cerr << *args++;
while (*args)
- std::cerr << ' ' << *args++;
- std::cerr << '\n' << std::flush;
+ cerr << ' ' << *args++;
+ cerr << '\n' << std::flush;
}
static inline void addPass(PassManager &PM, Pass *P) {
sys::Path LPath(LibPath);
// Make sure it exists and is a directory
- try {
- if (!LPath.exists() || !LPath.isDirectory())
- return false;
- } catch (std::string& xcptn) {
+ sys::FileStatus Status;
+ if (LPath.getFileStatus(Status) || !Status.isDir)
return false;
- }
// Grab the contents of the -L path
std::set<sys::Path> Files;
- LPath.getDirectoryContents(Files);
+ if (LPath.getDirectoryContents(Files, 0))
+ return false;
// Iterate over the contents one by one to determine
// if this -L path has any bytecode shared libraries
std::string dllsuffix = sys::Path::GetDLLSuffix();
for (; File != Files.end(); ++File) {
- if ( File->isDirectory() )
+ // Not a file?
+ if (File->getFileStatus(Status) || Status.isDir)
continue;
std::string path = File->toString();
- // Check for an ending '.dll,.so' or '.a' suffix as all
+ // Check for an ending '.dll', '.so' or '.a' suffix as all
// other files are not of interest to us here
if (path.find(dllsuffix, path.size()-dllsuffix.size()) == std::string::npos
&& path.find(".a", path.size()-2) == std::string::npos)
if (Verify) Passes.add(createVerifierPass());
// Add an appropriate TargetData instance for this module...
- addPass(Passes, new TargetData("gccld", M));
-
- // 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.
- addPass(Passes, createFunctionResolvingPass());
+ addPass(Passes, new TargetData(M));
if (!DisableOptimizations) {
// Now that composite has been compiled, scan through the module, looking
// internal.
addPass(Passes, createInternalizePass(Internalize));
+ // Propagate constants at call sites into the functions they call. This
+ // opens opportunities for globalopt (and inlining) by substituting function
+ // pointers passed as arguments to direct uses of functions.
+ addPass(Passes, createIPSCCPPass());
+
// Now that we internalized some globals, see if we can hack on them!
addPass(Passes, createGlobalOptimizerPass());
// keep one copy of each constant...
addPass(Passes, createConstantMergePass());
- // Propagate constants at call sites into the functions they call.
- addPass(Passes, createIPSCCPPass());
-
// Remove unused arguments from functions...
addPass(Passes, createDeadArgEliminationPass());
+ // Reduce the code after globalopt and ipsccp. Both can open up significant
+ // simplification opportunities, and both can propagate functions through
+ // function pointers. When this happens, we often have to resolve varargs
+ // calls, etc, so let instcombine do this.
+ addPass(Passes, createInstructionCombiningPass());
+
if (!DisableInline)
addPass(Passes, createFunctionInliningPass()); // Inline small functions
Passes.add(createVerifierPass());
// Add the pass that writes bytecode to the output file...
- addPass(Passes, new WriteBytecodePass(Out));
+ OStream L(*Out);
+ addPass(Passes, new WriteBytecodePass(&L, false, !NoCompress));
// Run our queue of passes all at once now, efficiently.
Passes.run(*M);
int llvm::GenerateAssembly(const std::string &OutputFilename,
const std::string &InputFilename,
const sys::Path &llc,
+ std::string& ErrMsg,
bool Verbose) {
// Run LLC to convert the bytecode file into assembly code.
std::vector<const char*> args;
args.push_back(InputFilename.c_str());
args.push_back(0);
if (Verbose) dumpArgs(&args[0]);
- return sys::Program::ExecuteAndWait(llc, &args[0]);
+ return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg);
}
/// GenerateCFile - generates a C source file from the specified bytecode file.
int llvm::GenerateCFile(const std::string &OutputFile,
const std::string &InputFile,
const sys::Path &llc,
+ std::string& ErrMsg,
bool Verbose) {
// Run LLC to convert the bytecode file into C.
std::vector<const char*> args;
args.push_back(InputFile.c_str());
args.push_back(0);
if (Verbose) dumpArgs(&args[0]);
- return sys::Program::ExecuteAndWait(llc, &args[0]);
+ return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg);
}
/// GenerateNative - generates a native executable file from the specified
const sys::Path &gcc, char ** const envp,
bool Shared,
bool ExportAllAsDynamic,
- const std::string &RPath,
+ const std::vector<std::string> &RPaths,
const std::string &SOName,
+ std::string& ErrMsg,
bool Verbose) {
// Remove these environment variables from the environment of the
// programs that we will execute. It appears that GCC sets these
if (Shared) args.push_back("-shared");
if (ExportAllAsDynamic) args.push_back("-export-dynamic");
- if (!RPath.empty()) {
- std::string rp = "-Wl,-rpath," + RPath;
- StringsToDelete.push_back(strdup(rp.c_str()));
- args.push_back(StringsToDelete.back());
+ if (!RPaths.empty()) {
+ for (std::vector<std::string>::const_iterator I = RPaths.begin(),
+ E = RPaths.end(); I != E; I++) {
+ std::string rp = "-Wl,-rpath," + *I;
+ StringsToDelete.push_back(strdup(rp.c_str()));
+ args.push_back(StringsToDelete.back());
+ }
}
if (!SOName.empty()) {
std::string so = "-Wl,-soname," + SOName;
// Run the compiler to assembly and link together the program.
if (Verbose) dumpArgs(&args[0]);
- int Res = sys::Program::ExecuteAndWait(gcc, &args[0], (const char**)clean_env);
+ int Res = sys::Program::ExecuteAndWait(
+ gcc, &args[0],(const char**)clean_env,0,0,&ErrMsg);
+
+ delete [] clean_env;
while (!StringsToDelete.empty()) {
free(StringsToDelete.back());