X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fgccld%2FGenerateCode.cpp;h=1144b92a643c8781c47d42094cbade3f9b36096e;hb=60896169465c278307df4d3c0defde20d64d6e2d;hp=6fd30c8d87e31123e537443cd08357c17cc45d96;hpb=548e813fa739e6a7ac0f9d1c3e19d96012f80e75;p=oota-llvm.git diff --git a/tools/gccld/GenerateCode.cpp b/tools/gccld/GenerateCode.cpp index 6fd30c8d87e..1144b92a643 100644 --- a/tools/gccld/GenerateCode.cpp +++ b/tools/gccld/GenerateCode.cpp @@ -17,15 +17,15 @@ #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Analysis/LoadValueNumbering.h" +#include "llvm/Analysis/Passes.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Bytecode/WriteBytecodePass.h" #include "llvm/Target/TargetData.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Utils/Linker.h" -#include "Support/SystemUtils.h" -#include "Support/CommandLine.h" - +#include "llvm/Support/Linker.h" +#include "llvm/Support/SystemUtils.h" +#include "llvm/Support/CommandLine.h" using namespace llvm; namespace { @@ -40,7 +40,83 @@ namespace { cl::desc("Do not run any optimization passes")); } -namespace llvm { +/// CopyEnv - This function takes an array of environment variables and makes a +/// copy of it. This copy can then be manipulated any way the caller likes +/// without affecting the process's real environment. +/// +/// Inputs: +/// envp - An array of C strings containing an environment. +/// +/// Return value: +/// NULL - An error occurred. +/// +/// Otherwise, a pointer to a new array of C strings is returned. Every string +/// in the array is a duplicate of the one in the original array (i.e. we do +/// not copy the char *'s from one array to another). +/// +static char ** CopyEnv(char ** const envp) { + // Count the number of entries in the old list; + unsigned entries; // The number of entries in the old environment list + for (entries = 0; envp[entries] != NULL; entries++) + /*empty*/; + + // Add one more entry for the NULL pointer that ends the list. + ++entries; + + // If there are no entries at all, just return NULL. + if (entries == 0) + return NULL; + + // Allocate a new environment list. + char **newenv = new char* [entries]; + if ((newenv = new char* [entries]) == NULL) + return NULL; + + // Make a copy of the list. Don't forget the NULL that ends the list. + entries = 0; + while (envp[entries] != NULL) { + newenv[entries] = new char[strlen (envp[entries]) + 1]; + strcpy (newenv[entries], envp[entries]); + ++entries; + } + newenv[entries] = NULL; + + return newenv; +} + + +/// RemoveEnv - Remove the specified environment variable from the environment +/// array. +/// +/// Inputs: +/// name - The name of the variable to remove. It cannot be NULL. +/// envp - The array of environment variables. It cannot be NULL. +/// +/// Notes: +/// This is mainly done because functions to remove items from the environment +/// are not available across all platforms. In particular, Solaris does not +/// seem to have an unsetenv() function or a setenv() function (or they are +/// undocumented if they do exist). +/// +static void RemoveEnv(const char * name, char ** const envp) { + for (unsigned index=0; envp[index] != NULL; index++) { + // Find the first equals sign in the array and make it an EOS character. + char *p = strchr (envp[index], '='); + if (p == NULL) + continue; + else + *p = '\0'; + + // Compare the two strings. If they are equal, zap this string. + // Otherwise, restore it. + if (!strcmp(name, envp[index])) + *envp[index] = '\0'; + else + *p = '='; + } + + return; +} static inline void addPass(PassManager &PM, Pass *P) { // Add the pass to the pass manager... @@ -58,13 +134,10 @@ static inline void addPass(PassManager &PM, Pass *P) { /// Internalize - Flags whether all symbols should be marked internal. /// Out - Pointer to file stream to which to write the output. /// -/// Outputs: -/// None. -/// /// Returns non-zero value on error. /// -int -GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) { +int llvm::GenerateBytecode(Module *M, bool Strip, bool Internalize, + std::ostream *Out) { // In addition to just linking the input from GCC, we also want to spiff it up // a little bit. Do this now. PassManager Passes; @@ -81,6 +154,16 @@ GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) { addPass(Passes, createFunctionResolvingPass()); if (!DisableOptimizations) { + if (Internalize) { + // Now that composite has been compiled, scan through the module, looking + // for a main function. If main is defined, mark all other functions + // internal. + addPass(Passes, createInternalizePass()); + } + + // Now that we internalized some globals, see if we can hack on them! + addPass(Passes, createGlobalOptimizerPass()); + // Linking modules together can lead to duplicated global constants, only // keep one copy of each constant... addPass(Passes, createConstantMergePass()); @@ -91,13 +174,6 @@ GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) { if (Strip) addPass(Passes, createSymbolStrippingPass()); - if (Internalize) { - // Now that composite has been compiled, scan through the module, looking - // for a main function. If main is defined, mark all other functions - // internal. - addPass(Passes, createInternalizePass()); - } - // Propagate constants at call sites into the functions they call. addPass(Passes, createIPConstantPropagationPass()); @@ -107,15 +183,28 @@ GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) { if (!DisableInline) addPass(Passes, createFunctionInliningPass()); // Inline small functions + addPass(Passes, createPruneEHPass()); // Remove dead EH info + addPass(Passes, createGlobalOptimizerPass()); // Optimize globals again. + addPass(Passes, createGlobalDCEPass()); // Remove dead functions + + // If we didn't decide to inline a function, check to see if we can + // transform it to pass arguments by value instead of by reference. + addPass(Passes, createArgumentPromotionPass()); + + // The IPO passes may leave cruft around. Clean up after them. + addPass(Passes, createInstructionCombiningPass()); + + addPass(Passes, createScalarReplAggregatesPass()); // Break up allocas + // Run a few AA driven optimizations here and now, to cleanup the code. - // Eventually we should put an IP AA in place here. + addPass(Passes, createGlobalsModRefPass()); // IP alias analysis addPass(Passes, createLICMPass()); // Hoist loop invariants addPass(Passes, createLoadValueNumberingPass()); // GVN for load instrs addPass(Passes, createGCSEPass()); // Remove common subexprs + addPass(Passes, createDeadStoreEliminationPass()); // Nuke dead stores - // The FuncResolve pass may leave cruft around if functions were prototyped - // differently than they were defined. Remove this cruft. + // Cleanup and simplify the code after the scalar optimizations. addPass(Passes, createInstructionCombiningPass()); // Delete basic blocks, which optimization passes may have killed... @@ -125,6 +214,9 @@ GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) { addPass(Passes, createGlobalDCEPass()); } + // Make sure everything is still good. + Passes.add(createVerifierPass()); + // Add the pass that writes bytecode to the output file... addPass(Passes, new WriteBytecodePass(Out)); @@ -143,30 +235,42 @@ GenerateBytecode (Module *M, bool Strip, bool Internalize, std::ostream *Out) { /// llc - The pathname to use for LLC. /// envp - The environment to use when running LLC. /// -/// Outputs: -/// None. -/// /// Return non-zero value on error. /// -int -GenerateAssembly(const std::string &OutputFilename, - const std::string &InputFilename, - const std::string &llc, - char ** const envp) -{ +int llvm::GenerateAssembly(const std::string &OutputFilename, + const std::string &InputFilename, + const std::string &llc, + char ** const envp) { // Run LLC to convert the bytecode file into assembly code. - const char *cmd[8]; - + const char *cmd[6]; cmd[0] = llc.c_str(); cmd[1] = "-f"; cmd[2] = "-o"; cmd[3] = OutputFilename.c_str(); cmd[4] = InputFilename.c_str(); - cmd[5] = NULL; + cmd[5] = 0; return ExecWait(cmd, envp); } +/// GenerateAssembly - generates a native assembly language source file from the +/// specified bytecode file. +int llvm::GenerateCFile(const std::string &OutputFile, + const std::string &InputFile, + const std::string &llc, char ** const envp) { + // Run LLC to convert the bytecode file into C. + const char *cmd[7]; + + cmd[0] = llc.c_str(); + cmd[1] = "-march=c"; + cmd[2] = "-f"; + cmd[3] = "-o"; + cmd[4] = OutputFile.c_str(); + cmd[5] = InputFile.c_str(); + cmd[6] = 0; + return ExecWait(cmd, envp); +} + /// GenerateNative - generates a native assembly language source file from the /// specified assembly source file. /// @@ -183,13 +287,11 @@ GenerateAssembly(const std::string &OutputFilename, /// /// Returns non-zero value on error. /// -int -GenerateNative(const std::string &OutputFilename, - const std::string &InputFilename, - const std::vector &Libraries, - const std::vector &LibPaths, - const std::string &gcc, - char ** const envp) { +int llvm::GenerateNative(const std::string &OutputFilename, + const std::string &InputFilename, + const std::vector &Libraries, + const std::vector &LibPaths, + const std::string &gcc, char ** const envp) { // Remove these environment variables from the environment of the // programs that we will execute. It appears that GCC sets these // environment variables so that the programs it uses can configure @@ -215,6 +317,8 @@ GenerateNative(const std::string &OutputFilename, // and linker because we don't know where to put the _start symbol. // GCC mysteriously knows how to do it. cmd.push_back(gcc.c_str()); + cmd.push_back("-fno-strict-aliasing"); + cmd.push_back("-O3"); cmd.push_back("-o"); cmd.push_back(OutputFilename.c_str()); cmd.push_back(InputFilename.c_str()); @@ -236,8 +340,10 @@ GenerateNative(const std::string &OutputFilename, // Add in the libraries to link. std::vector Libs(Libraries); for (unsigned index = 0; index < Libs.size(); index++) { - Libs[index] = "-l" + Libs[index]; - cmd.push_back(Libs[index].c_str()); + if (Libs[index] != "crtend") { + Libs[index] = "-l" + Libs[index]; + cmd.push_back(Libs[index].c_str()); + } } cmd.push_back(NULL); @@ -245,4 +351,3 @@ GenerateNative(const std::string &OutputFilename, return ExecWait(&(cmd[0]), clean_env); } -} // End llvm namespace