From: Reid Spencer Date: Fri, 9 Feb 2007 15:21:02 +0000 (+0000) Subject: End of life for gccld. Remove its source code and enable the generation X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d748ea32dbb6a8c78c3181b9e8b117ee2514ab42;p=oota-llvm.git End of life for gccld. Remove its source code and enable the generation of a shell script to stand in its place. The shell script just pawns the execution off to llvm-ld. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@34090 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/gccld/GenerateCode.cpp b/tools/gccld/GenerateCode.cpp deleted file mode 100644 index 3f9923cd1b7..00000000000 --- a/tools/gccld/GenerateCode.cpp +++ /dev/null @@ -1,461 +0,0 @@ -//===- GenerateCode.cpp - Functions for generating executable files ------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// 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 "gccld.h" -#include "llvm/System/Program.h" -#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/Archive.h" -#include "llvm/Bytecode/WriteBytecodePass.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Transforms/IPO.h" -#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 - DisableInline("disable-inlining", cl::desc("Do not run the inliner pass")); - - cl::opt - Verify("verify", cl::desc("Verify intermediate results of all passes")); - - cl::opt - DisableOptimizations("disable-opt", - cl::desc("Do not run any optimization passes")); - - cl::opt - 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 -/// 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 = '='; - } -} - -static void dumpArgs(const char **args) { - cerr << *args++; - while (*args) - cerr << ' ' << *args++; - cerr << '\n' << std::flush; -} - -static inline void addPass(PassManager &PM, Pass *P) { - // Add the pass to the pass manager... - PM.add(P); - - // If we are verifying all of the intermediate steps, add the verifier... - if (Verify) PM.add(createVerifierPass()); -} - -static bool isBytecodeLibrary(const sys::Path &FullPath) { - // Check for a bytecode file - if (FullPath.isBytecodeFile()) return true; - // Check for a dynamic library file - if (FullPath.isDynamicLibrary()) return false; - // Check for a true bytecode archive file - if (FullPath.isArchive() ) { - std::string ErrorMessage; - Archive* ar = Archive::OpenAndLoadSymbols( FullPath, &ErrorMessage ); - return ar->isBytecodeArchive(); - } - return false; -} - -static bool isBytecodeLPath(const std::string &LibPath) { - sys::Path LPath(LibPath); - - // Make sure it exists and is a directory - sys::FileStatus Status; - if (LPath.getFileStatus(Status) || !Status.isDir) - return false; - - // Grab the contents of the -L path - std::set 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 - // or archives - std::set::iterator File = Files.begin(); - std::string dllsuffix = sys::Path::GetDLLSuffix(); - for (; File != Files.end(); ++File) { - - // 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 - // 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) - continue; - - // Finally, check to see if the file is a true bytecode file - if (isBytecodeLibrary(*File)) - return true; - } - return false; -} - -/// GenerateBytecode - generates a bytecode file from the specified module. -/// -/// Inputs: -/// M - The module for which bytecode should be generated. -/// StripLevel - 2 if we should strip all symbols, 1 if we should strip -/// debug info. -/// Internalize - Flags whether all symbols should be marked internal. -/// Out - Pointer to file stream to which to write the output. -/// -/// Returns non-zero value on error. -/// -int llvm::GenerateBytecode(Module *M, int StripLevel, 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; - - if (Verify) Passes.add(createVerifierPass()); - - // Add an appropriate TargetData instance for this module... - addPass(Passes, new TargetData(M)); - - if (!DisableOptimizations) { - // 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(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()); - - // Linking modules together can lead to duplicated global constants, only - // keep one copy of each constant... - addPass(Passes, createConstantMergePass()); - - // 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 - - 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. - 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 - - // Cleanup and simplify the code after the scalar optimizations. - addPass(Passes, createInstructionCombiningPass()); - - // Delete basic blocks, which optimization passes may have killed... - addPass(Passes, createCFGSimplificationPass()); - - // Now that we have optimized the program, discard unreachable functions... - addPass(Passes, createGlobalDCEPass()); - } - - // If the -s or -S command line options were specified, strip the symbols out - // of the resulting program to make it smaller. -s and -S are GLD options - // that we are supporting. - if (StripLevel) - addPass(Passes, createStripSymbolsPass(StripLevel == 1)); - - // Make sure everything is still good. - Passes.add(createVerifierPass()); - - // Add the pass that writes bytecode to the output file... - OStream L(*Out); - addPass(Passes, new WriteBytecodePass(&L, false, !NoCompress)); - - // Run our queue of passes all at once now, efficiently. - Passes.run(*M); - - return 0; -} - -/// GenerateAssembly - 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. -/// -/// Return non-zero value on error. -/// -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 args; - args.push_back(llc.c_str()); - args.push_back("-f"); - args.push_back("-o"); - args.push_back(OutputFilename.c_str()); - args.push_back(InputFilename.c_str()); - args.push_back(0); - if (Verbose) dumpArgs(&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 args; - args.push_back(llc.c_str()); - args.push_back("-march=c"); - args.push_back("-f"); - args.push_back("-o"); - args.push_back(OutputFile.c_str()); - args.push_back(InputFile.c_str()); - args.push_back(0); - if (Verbose) dumpArgs(&args[0]); - return sys::Program::ExecuteAndWait(llc, &args[0],0,0,0,&ErrMsg); -} - -/// GenerateNative - generates a native executable 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. -/// -/// Returns non-zero value on error. -/// -int llvm::GenerateNative(const std::string &OutputFilename, - const std::string &InputFilename, - const std::vector &LibPaths, - const std::vector &Libraries, - const sys::Path &gcc, char ** const envp, - bool Shared, - bool ExportAllAsDynamic, - const std::vector &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 - // 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 its 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); - - - // 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. - std::vector args; - args.push_back(gcc.c_str()); - args.push_back("-fno-strict-aliasing"); - args.push_back("-O3"); - args.push_back("-o"); - args.push_back(OutputFilename.c_str()); - args.push_back(InputFilename.c_str()); - - // StringsToDelete - We don't want to call c_str() on temporary strings. - // If we need a temporary string, copy it here so that the memory is not - // reclaimed until after the exec call. All of these strings are allocated - // with strdup. - std::vector StringsToDelete; - - if (Shared) args.push_back("-shared"); - if (ExportAllAsDynamic) args.push_back("-export-dynamic"); - if (!RPaths.empty()) { - for (std::vector::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; - StringsToDelete.push_back(strdup(so.c_str())); - args.push_back(StringsToDelete.back()); - } - - // Add in the libpaths to find the libraries. - // - // Note: - // When gccld is called from the llvm-gxx frontends, the -L paths for - // the LLVM cfrontend install paths are appended. We don't want the - // native linker to use these -L paths as they contain bytecode files. - // Further, we don't want any -L paths that contain bytecode shared - // libraries or true bytecode archive files. We omit them in all such - // cases. - for (unsigned index = 0; index < LibPaths.size(); index++) - if (!isBytecodeLPath(LibPaths[index])) { - std::string Tmp = "-L"+LibPaths[index]; - StringsToDelete.push_back(strdup(Tmp.c_str())); - args.push_back(StringsToDelete.back()); - } - - // Add in the libraries to link. - for (unsigned index = 0; index < Libraries.size(); index++) - // HACK: If this is libg, discard it. This gets added by the compiler - // driver when doing: 'llvm-gcc main.c -Wl,-native -o a.out -g'. Note that - // this should really be fixed by changing the llvm-gcc compiler driver. - if (Libraries[index] != "crtend" && Libraries[index] != "g") { - std::string Tmp = "-l"+Libraries[index]; - StringsToDelete.push_back(strdup(Tmp.c_str())); - args.push_back(StringsToDelete.back()); - } - args.push_back(0); // Null terminate. - - // 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,0,0,&ErrMsg); - - delete [] clean_env; - - while (!StringsToDelete.empty()) { - free(StringsToDelete.back()); - StringsToDelete.pop_back(); - } - return Res; -} - diff --git a/tools/gccld/Makefile b/tools/gccld/Makefile index 21adca217c0..345e646df3d 100644 --- a/tools/gccld/Makefile +++ b/tools/gccld/Makefile @@ -9,13 +9,8 @@ LEVEL = ../.. -TOOLNAME = gccld -LINK_COMPONENTS = bcreader bcwriter ipo scalaropts ipa linker -REQUIRES_EH := 1 - include $(LEVEL)/Makefile.common -ifdef DONT_USE_THIS install-local:: $(PROJ_bindir)/gccld $(PROJ_bindir)/gccld : gccld.sh Makefile @@ -32,4 +27,3 @@ $(ToolDir)/gccld : gccld.sh Makefile clean-local:: $(Verb)$(RM) -f $(ToolDir)/gccld -endif diff --git a/tools/gccld/gccld.cpp b/tools/gccld/gccld.cpp deleted file mode 100644 index c153f811247..00000000000 --- a/tools/gccld/gccld.cpp +++ /dev/null @@ -1,427 +0,0 @@ -//===- gccld.cpp - LLVM 'ld' compatible linker ----------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This utility is intended to be compatible with GCC, and follows standard -// system 'ld' conventions. As such, the default output file is ./a.out. -// Additionally, this program outputs a shell script that is used to invoke LLI -// to execute the program. In this manner, the generated executable (a.out for -// example), is directly executable, whereas the bytecode file actually lives in -// the a.out.bc file generated by this program. Also, Force is on by default. -// -// Note that if someone (or a script) deletes the executable program generated, -// the .bc file will be left around. Considering that this is a temporary hack, -// I'm not too worried about this. -// -//===----------------------------------------------------------------------===// - -#include "gccld.h" -#include "llvm/Linker.h" -#include "llvm/Module.h" -#include "llvm/PassManager.h" -#include "llvm/Bytecode/Reader.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Transforms/IPO.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/FileUtilities.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/Streams.h" -#include "llvm/System/Signals.h" -#include "llvm/Support/SystemUtils.h" -#include -#include -using namespace llvm; - -namespace { - cl::list - InputFilenames(cl::Positional, cl::desc(""), - cl::OneOrMore); - - cl::opt - OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"), - cl::value_desc("filename")); - - cl::opt - Verbose("v", cl::desc("Print information about actions taken")); - - cl::list - LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix, - cl::value_desc("directory")); - - cl::list - Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix, - cl::value_desc("library prefix")); - - cl::opt - Strip("strip-all", cl::desc("Strip all symbol info from executable")); - cl::opt - StripDebug("strip-debug", - cl::desc("Strip debugger symbol info from executable")); - - cl::opt - NoInternalize("disable-internalize", - cl::desc("Do not mark all symbols as internal")); - cl::alias - ExportDynamic("export-dynamic", cl::desc("Alias for -disable-internalize"), - cl::aliasopt(NoInternalize)); - - cl::opt - LinkAsLibrary("link-as-library", cl::desc("Link the .bc files together as a" - " library, not an executable")); - cl::alias - Relink("r", cl::desc("Alias for -link-as-library"), - cl::aliasopt(LinkAsLibrary)); - - cl::opt - Native("native", cl::ZeroOrMore, - cl::desc("Generate a native binary instead of a shell script")); - cl::opt - NativeCBE("native-cbe", cl::ZeroOrMore, - cl::desc("Generate a native binary with the C backend and GCC")); - - cl::opt - SaveTemps("save-temps", - cl::desc("Do not delete temporary files")); - - cl::list - RPath("rpath", - cl::desc("Set runtime shared library search path (requires -native or" - " -native-cbe)"), - cl::Prefix, cl::value_desc("directory")); - - cl::opt - SOName("soname", - cl::desc("Set internal name of shared library (requires -native or" - " -native-cbe)"), - cl::Prefix, cl::value_desc("name")); - - // Compatibility options that are ignored but supported by LD - cl::opt - CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt - CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt - CO6("h", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt - CO7("start-group", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt - CO8("end-group", cl::Hidden, cl::desc("Compatibility option: ignored")); - - cl::alias A0("s", cl::desc("Alias for --strip-all"), - cl::aliasopt(Strip)); - cl::alias A1("S", cl::desc("Alias for --strip-debug"), - cl::aliasopt(StripDebug)); - -} - -/// PrintAndReturn - Prints a message to standard error and returns true. -/// -/// Inputs: -/// progname - The name of the program (i.e. argv[0]). -/// Message - The message to print to standard error. -/// -static int PrintAndReturn(const char *progname, const std::string &Message) { - cerr << progname << ": " << Message << "\n"; - return 1; -} - -/// EmitShellScript - Output the wrapper file that invokes the JIT on the LLVM -/// bytecode file for the program. -static void EmitShellScript(char **argv) { -#if defined(_WIN32) || defined(__CYGWIN__) - // Windows doesn't support #!/bin/sh style shell scripts in .exe files. To - // support windows systems, we copy the llvm-stub.exe executable from the - // build tree to the destination file. - std::string ErrMsg; - sys::Path llvmstub = FindExecutable("llvm-stub.exe", argv[0]); - if (llvmstub.isEmpty()) { - cerr << "Could not find llvm-stub.exe executable!\n"; - exit(1); - } - if (0 != sys::CopyFile(sys::Path(OutputFilename), llvmstub, &ErrMsg)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - exit(1); - } - - return; -#endif - - // Output the script to start the program... - std::ofstream Out2(OutputFilename.c_str()); - if (!Out2.good()) - exit(PrintAndReturn(argv[0], "error opening '" + OutputFilename + - "' for writing!")); - - Out2 << "#!/bin/sh\n"; - // Allow user to setenv LLVMINTERP if lli is not in their PATH. - Out2 << "lli=${LLVMINTERP-lli}\n"; - Out2 << "exec $lli \\\n"; - - // We don't need to link in libc! In fact, /usr/lib/libc.so may not be a - // shared object at all! See RH 8: plain text. - std::vector::iterator libc = - std::find(Libraries.begin(), Libraries.end(), "c"); - if (libc != Libraries.end()) Libraries.erase(libc); - // List all the shared object (native) libraries this executable will need - // on the command line, so that we don't have to do this manually! - for (std::vector::iterator i = Libraries.begin(), - e = Libraries.end(); i != e; ++i) { - sys::Path FullLibraryPath = sys::Path::FindLibrary(*i); - if (!FullLibraryPath.isEmpty() && FullLibraryPath.isDynamicLibrary()) - Out2 << " -load=" << FullLibraryPath.toString() << " \\\n"; - } - Out2 << " $0.bc ${1+\"$@\"}\n"; - Out2.close(); -} - -// BuildLinkItems -- This function generates a LinkItemList for the LinkItems -// linker function by combining the Files and Libraries in the order they were -// declared on the command line. -static void BuildLinkItems( - Linker::ItemList& Items, - const cl::list& Files, - const cl::list& Libraries) { - - // Build the list of linkage items for LinkItems. - - cl::list::const_iterator fileIt = Files.begin(); - cl::list::const_iterator libIt = Libraries.begin(); - - int libPos = -1, filePos = -1; - while ( libIt != Libraries.end() || fileIt != Files.end() ) { - if (libIt != Libraries.end()) - libPos = Libraries.getPosition(libIt - Libraries.begin()); - else - libPos = -1; - if (fileIt != Files.end()) - filePos = Files.getPosition(fileIt - Files.begin()); - else - filePos = -1; - - if (filePos != -1 && (libPos == -1 || filePos < libPos)) { - // Add a source file - Items.push_back(std::make_pair(*fileIt++, false)); - } else if (libPos != -1 && (filePos == -1 || libPos < filePos)) { - // Add a library - Items.push_back(std::make_pair(*libIt++, true)); - } - } -} - -int main(int argc, char **argv, char **envp ) { - llvm_shutdown_obj X; // Call llvm_shutdown() on exit. - cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n"); - sys::PrintStackTraceOnErrorSignal(); - - int exitCode = 0; - - std::string ProgName = sys::Path(argv[0]).getBasename(); - Linker TheLinker(ProgName, OutputFilename, Verbose); - - try { - // Remove any consecutive duplicates of the same library... - Libraries.erase(std::unique(Libraries.begin(), Libraries.end()), - Libraries.end()); - - TheLinker.addPaths(LibPaths); - TheLinker.addSystemPaths(); - - if (LinkAsLibrary) { - std::vector Files; - for (unsigned i = 0; i < InputFilenames.size(); ++i ) - Files.push_back(sys::Path(InputFilenames[i])); - - if (TheLinker.LinkInFiles(Files)) - return 1; // Error already printed by linker - - // The libraries aren't linked in but are noted as "dependent" in the - // module. - for (cl::list::const_iterator I = Libraries.begin(), - E = Libraries.end(); I != E ; ++I) { - TheLinker.getModule()->addLibrary(*I); - } - - } else { - // Build a list of the items from our command line - Linker::ItemList Items; - Linker::ItemList NativeItems; - BuildLinkItems(Items, InputFilenames, Libraries); - - // Link all the items together - if (TheLinker.LinkInItems(Items,NativeItems)) - return 1; // Error already printed - - // Revise the Libraries based on the remaining (native) libraries that - // were not linked in to the bytecode. This ensures that we don't attempt - // to pass a bytecode library to the native linker - Libraries.clear(); // we've consumed the libraries except for native - if ((Native || NativeCBE) && !NativeItems.empty()) { - for (Linker::ItemList::const_iterator I = NativeItems.begin(), - E = NativeItems.end(); I != E; ++I) { - Libraries.push_back(I->first); - } - } - } - - // We're done with the Linker, so tell it to release its module - std::auto_ptr Composite(TheLinker.releaseModule()); - - // Create the output file. - std::string RealBytecodeOutput = OutputFilename; - if (!LinkAsLibrary || Native || NativeCBE) RealBytecodeOutput += ".bc"; - std::ios::openmode io_mode = std::ios::out | std::ios::trunc | - std::ios::binary; - std::ofstream Out(RealBytecodeOutput.c_str(), io_mode); - if (!Out.good()) - return PrintAndReturn(argv[0], "error opening '" + RealBytecodeOutput + - "' for writing!"); - - // Ensure that the bytecode file gets removed from the disk if we get a - // SIGINT signal. - sys::RemoveFileOnSignal(sys::Path(RealBytecodeOutput)); - - // Strip everything if Strip is set, otherwise if stripdebug is set, just - // strip debug info. - int StripLevel = Strip ? 2 : (StripDebug ? 1 : 0); - - // Internalize the module if neither -disable-internalize nor - // -link-as-library are passed in. - bool ShouldInternalize = !NoInternalize & !LinkAsLibrary; - - // Generate the bytecode file. - if (GenerateBytecode(Composite.get(), StripLevel, ShouldInternalize, &Out)){ - Out.close(); - return PrintAndReturn(argv[0], "error generating bytecode"); - } - - // Close the bytecode file. - Out.close(); - - // Generate either a native file or a JIT shell script. If the user wants - // to generate a native file, compile it from the bytecode file. Otherwise, - // if the target is not a library, create a script that will run the - // bytecode through the JIT. - if (Native) { - // Name of the Assembly Language output file - sys::Path AssemblyFile (OutputFilename); - AssemblyFile.appendSuffix("s"); - - // Mark the output files for removal if we get an interrupt. - sys::RemoveFileOnSignal(AssemblyFile); - sys::RemoveFileOnSignal(sys::Path(OutputFilename)); - - // Determine the locations of the llc and gcc programs. - sys::Path llc = FindExecutable("llc", argv[0]); - if (llc.isEmpty()) - return PrintAndReturn(argv[0], "Failed to find llc"); - - sys::Path gcc = FindExecutable("gcc", argv[0]); - if (gcc.isEmpty()) - return PrintAndReturn(argv[0], "Failed to find gcc"); - - // Generate an assembly language file for the bytecode. - if (Verbose) cout << "Generating Assembly Code\n"; - std::string ErrMsg; - if (0 != GenerateAssembly( - AssemblyFile.toString(), RealBytecodeOutput, llc, ErrMsg, Verbose)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 2; - } - if (Verbose) cout << "Generating Native Code\n"; - if (0 != GenerateNative(OutputFilename, AssemblyFile.toString(), - LibPaths, Libraries, gcc, envp, LinkAsLibrary, - NoInternalize, RPath, SOName, ErrMsg, Verbose) ) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 2; - } - - if (!SaveTemps) { - // Remove the assembly language file. - AssemblyFile.eraseFromDisk(); - // Remove the bytecode language file. - sys::Path(RealBytecodeOutput).eraseFromDisk(); - } - - } else if (NativeCBE) { - sys::Path CFile (OutputFilename); - CFile.appendSuffix("cbe.c"); - - // Mark the output files for removal if we get an interrupt. - sys::RemoveFileOnSignal(CFile); - sys::RemoveFileOnSignal(sys::Path(OutputFilename)); - - // Determine the locations of the llc and gcc programs. - sys::Path llc = FindExecutable("llc", argv[0]); - if (llc.isEmpty()) - return PrintAndReturn(argv[0], "Failed to find llc"); - - sys::Path gcc = FindExecutable("gcc", argv[0]); - if (gcc.isEmpty()) - return PrintAndReturn(argv[0], "Failed to find gcc"); - - // Generate an assembly language file for the bytecode. - if (Verbose) cout << "Generating C Source Code\n"; - std::string ErrMsg; - if (0 != GenerateCFile( - CFile.toString(), RealBytecodeOutput, llc, ErrMsg, Verbose)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 2; - } - if (Verbose) cout << "Generating Native Code\n"; - if (0 != GenerateNative(OutputFilename, CFile.toString(), - LibPaths, Libraries, gcc, envp, LinkAsLibrary, - NoInternalize, RPath, SOName, ErrMsg, Verbose)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 2; - } - - if (!SaveTemps) { - // Remove the assembly language file. - CFile.eraseFromDisk(); - // Remove the bytecode language file. - sys::Path(RealBytecodeOutput).eraseFromDisk(); - } - - } else if (!LinkAsLibrary) { - EmitShellScript(argv); - - // Make the bytecode file readable and directly executable in LLEE - std::string ErrMsg; - if (sys::Path(RealBytecodeOutput).makeExecutableOnDisk(&ErrMsg)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 1; - } - if (sys::Path(RealBytecodeOutput).makeReadableOnDisk(&ErrMsg)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 1; - } - } - - // Make the output, whether native or script, executable as well... - std::string ErrMsg; - if (sys::Path(OutputFilename).makeExecutableOnDisk(&ErrMsg)) { - cerr << argv[0] << ": " << ErrMsg << "\n"; - return 1; - } - } catch (const char*msg) { - cerr << argv[0] << ": " << msg << "\n"; - exitCode = 1; - } catch (const std::string& msg) { - cerr << argv[0] << ": " << msg << "\n"; - exitCode = 2; - } catch (...) { - // This really shouldn't happen, but just in case .... - cerr << argv[0] << ": An unexpected unknown exception occurred.\n"; - exitCode = 3; - } - - llvm_shutdown(); - return exitCode; -} diff --git a/tools/gccld/gccld.h b/tools/gccld/gccld.h deleted file mode 100644 index 62c058a2df5..00000000000 --- a/tools/gccld/gccld.h +++ /dev/null @@ -1,56 +0,0 @@ -//===- gccld.h - Utility functions header file ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file contains function prototypes for the functions in util.cpp. -// -//===----------------------------------------------------------------------===// - -#include "llvm/Module.h" -#include "llvm/Linker.h" - -#include -#include -#include - -namespace llvm { - -int -GenerateBytecode (Module *M, - int StripLevel, - bool Internalize, - std::ostream *Out); - -int -GenerateAssembly (const std::string &OutputFilename, - const std::string &InputFilename, - const sys::Path &llc, - std::string& ErrMsg, - bool Verbose=false); - -int -GenerateCFile (const std::string &OutputFile, - const std::string &InputFile, - const sys::Path &llc, - std::string& ErrMsg, - bool Verbose=false); -int -GenerateNative (const std::string &OutputFilename, - const std::string &InputFilename, - const std::vector &LibPaths, - const std::vector &Libraries, - const sys::Path &gcc, - char ** const envp, - bool Shared, - bool ExportAllAsDynamic, - const std::vector &RPath, - const std::string &SOName, - std::string& ErrMsg, - bool Verbose=false); - -} // End llvm namespace