llvm-6502/tools/gccld/GenerateCode.cpp
John Criswell 71478b7f72 Removed linking functionality from gccld.cpp and moved it to linker.cpp.
Renamed functions that were all lower-case.
Moved functions from util.cpp into linker.cpp or gccld.cpp.
Removed util.h and created gccld.h.
Refactored the linker functionality in linker.cpp so that it is easier to
follow, easier to modify, and it's library/object file search behavior is
easier to understand and document.
Added code to include library paths when doing native linking, but this
causes problems and is currently #ifdef'd out.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8609 91177308-0d34-0410-b5e6-96231b3b80d8
2003-09-19 20:24:23 +00:00

246 lines
7.1 KiB
C++

//===- gencode.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 "gccld.h"
//
// 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::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;
// 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: GenerateAssembly ()
//
// 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
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];
cmd[0] = llc.c_str();
cmd[1] = "-f";
cmd[2] = "-o";
cmd[3] = OutputFilename.c_str();
cmd[4] = InputFilename.c_str();
cmd[5] = NULL;
return (ExecWait (cmd, envp));
}
//
// Function: GenerateNative ()
//
// 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.
// LibPaths - The list of directories in which to find libraries.
// 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
GenerateNative (const std::string & OutputFilename,
const std::string & InputFilename,
const std::vector<std::string> & Libraries,
const std::vector<std::string> & 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
// 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 = CopyEnv (envp);
if (clean_env == NULL)
{
return 1;
}
RemoveEnv ("LIBRARY_PATH", clean_env);
RemoveEnv ("COLLECT_GCC_OPTIONS", clean_env);
RemoveEnv ("GCC_EXEC_PREFIX", clean_env);
RemoveEnv ("COMPILER_PATH", clean_env);
RemoveEnv ("COLLECT_GCC", clean_env);
std::vector<const char *> cmd;
//
// 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.
//
cmd.push_back (gcc.c_str());
cmd.push_back ("-o");
cmd.push_back (OutputFilename.c_str());
cmd.push_back (InputFilename.c_str());
//
// JTC:
// Adding the library paths creates a problem for native generation. If we
// include the search paths from llvmgcc, then we'll be telling normal gcc
// to look inside of llvmgcc's library directories for libraries. This is
// bad because those libraries hold only bytecode files (not native object
// files). In the end, we attempt to link the bytecode libgcc into a native
// program.
//
#ifdef ndef
//
// Add in the library path options.
//
for (unsigned index=0; index < LibPaths.size(); index++)
{
cmd.push_back ("-L");
cmd.push_back (LibPaths[index].c_str());
}
#endif
//
// Add in the libraries to link.
//
std::vector<std::string> Libs (Libraries);
for (unsigned index = 0; index < Libs.size(); index++)
{
Libs[index] = "-l" + Libs[index];
cmd.push_back (Libs[index].c_str());
}
cmd.push_back (NULL);
//
// Run the compiler to assembly and link together the program.
//
return (ExecWait (&(cmd[0]), clean_env));
}