aboutsummaryrefslogtreecommitdiff
path: root/tools/gccld/GenerateCode.cpp
diff options
context:
space:
mode:
authorJohn Criswell <criswell@uiuc.edu>2003-09-18 16:22:26 +0000
committerJohn Criswell <criswell@uiuc.edu>2003-09-18 16:22:26 +0000
commitdc0de4f07bc4971853ef8deacd3df540be96d505 (patch)
treeaf32a33ca0f43d2e66e98ca5886b0f6f91b37339 /tools/gccld/GenerateCode.cpp
parent521f1feb110e97b8015a84364f73303e1e6fd4f6 (diff)
Refactored gccld into three C++ source files.
Added code ignore bytecode link failures when generating native code. Moved native code and bytecode generation out of the main() function. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8595 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools/gccld/GenerateCode.cpp')
-rw-r--r--tools/gccld/GenerateCode.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/tools/gccld/GenerateCode.cpp b/tools/gccld/GenerateCode.cpp
new file mode 100644
index 0000000000..b9f7f3b8e1
--- /dev/null
+++ b/tools/gccld/GenerateCode.cpp
@@ -0,0 +1,228 @@
+//===- genexec.cpp - Functions for generating executable files ------------===//
+//
+// This file contains functions for generating executable files once linking
+// has finished. This includes generating a shell script to run the JIT or
+// a native executable derived from the bytecode.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Utils/Linker.h"
+#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Module.h"
+#include "llvm/PassManager.h"
+#include "llvm/Bytecode/WriteBytecodePass.h"
+#include "Support/SystemUtils.h"
+#include "util.h"
+
+#include <fstream>
+#include <string>
+#include <vector>
+
+//
+// Function: GenerateBytecode ()
+//
+// Description:
+// This function generates a bytecode file from the specified module.
+//
+// Inputs:
+// M - The module for which bytecode should be generated.
+// Strip - Flags whether symbols should be stripped from the output.
+// Internalize - Flags whether all symbols should be marked internal.
+// Out - Pointer to file stream to which to write the output.
+//
+// Outputs:
+// None.
+//
+// Return value:
+// 0 - No error.
+// 1 - Error.
+//
+int
+GenerateBytecode (Module * M,
+ bool Strip,
+ bool Internalize,
+ std::ofstream * 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;
+
+ // Add an appropriate TargetData instance for this module...
+ Passes.add(new TargetData("gccld", M));
+
+ // 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());
+
+ 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.
+ //
+ Passes.add(createInternalizePass());
+ }
+
+ // Remove unused arguments from functions...
+ //
+ Passes.add(createDeadArgEliminationPass());
+
+ // The FuncResolve pass may leave cruft around if functions were prototyped
+ // differently than they were defined. Remove this cruft.
+ //
+ Passes.add(createInstructionCombiningPass());
+
+ // Delete basic blocks, which optimization passes may have killed...
+ //
+ Passes.add(createCFGSimplificationPass());
+
+ // Now that we have optimized the program, discard unreachable functions...
+ //
+ Passes.add(createGlobalDCEPass());
+
+ // Add the pass that writes bytecode to the output file...
+ Passes.add(new WriteBytecodePass(Out));
+
+ // Run our queue of passes all at once now, efficiently.
+ Passes.run(*M);
+
+ return 0;
+}
+
+//
+// Function: generate_assembly ()
+//
+// Description:
+// This function generates a native assembly language source file from the
+// specified bytecode file.
+//
+// Inputs:
+// InputFilename - The name of the output bytecode file.
+// OutputFilename - The name of the file to generate.
+// llc - The pathname to use for LLC.
+// envp - The environment to use when running LLC.
+//
+// Outputs:
+// None.
+//
+// Return value:
+// 0 - Success
+// 1 - Failure
+//
+int
+generate_assembly (std::string OutputFilename,
+ std::string InputFilename,
+ std::string llc,
+ char ** const envp)
+{
+ //
+ // Run LLC to convert the bytecode file into assembly code.
+ //
+ const char * cmd[8];
+
+ cmd[0] = llc.c_str();
+ cmd[1] = "-f";
+ cmd[2] = "-o";
+ cmd[3] = OutputFilename.c_str();
+ cmd[4] = InputFilename.c_str();
+ cmd[5] = NULL;
+ if ((ExecWait (cmd, envp)) == -1)
+ {
+ return 1;
+ }
+
+ return 0;
+}
+
+//
+// Function: generate_native ()
+//
+// Description:
+// This function generates a native assembly language source file from the
+// specified assembly source file.
+//
+// Inputs:
+// InputFilename - The name of the output bytecode file.
+// OutputFilename - The name of the file to generate.
+// Libraries - The list of libraries with which to link.
+// gcc - The pathname to use for GGC.
+// envp - A copy of the process's current environment.
+//
+// Outputs:
+// None.
+//
+// Return value:
+// 0 - Success
+// 1 - Failure
+//
+int
+generate_native (std::string OutputFilename,
+ std::string InputFilename,
+ std::vector<std::string> Libraries,
+ 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
+ // themselves identically.
+ //
+ // However, when we invoke GCC below, we want it to use its normal
+ // configuration. Hence, we must sanitize it's environment.
+ //
+ char ** clean_env = copy_env (envp);
+ if (clean_env == NULL)
+ {
+ return 1;
+ }
+ remove_env ("LIBRARY_PATH", clean_env);
+ remove_env ("COLLECT_GCC_OPTIONS", clean_env);
+ remove_env ("GCC_EXEC_PREFIX", clean_env);
+ remove_env ("COMPILER_PATH", clean_env);
+ remove_env ("COLLECT_GCC", clean_env);
+
+ const char * cmd[8 + Libraries.size()];
+
+ //
+ // Run GCC to assemble and link the program into native code.
+ //
+ // Note:
+ // We can't just assemble and link the file with the system assembler
+ // and linker because we don't know where to put the _start symbol.
+ // GCC mysteriously knows how to do it.
+ //
+ unsigned int index=0;
+ cmd[index++] = gcc.c_str();
+ cmd[index++] = "-o";
+ cmd[index++] = OutputFilename.c_str();
+ cmd[index++] = InputFilename.c_str();
+ for (; (index - 4) < Libraries.size(); index++)
+ {
+ Libraries[index - 4] = "-l" + Libraries[index - 4];
+ cmd[index] = Libraries[index-4].c_str();
+ }
+ cmd[index++] = NULL;
+ if ((ExecWait (cmd, clean_env)) == -1)
+ {
+ return 1;
+ }
+
+ return 0;
+}