diff options
Diffstat (limited to 'tools/gccld/gccld.cpp')
-rw-r--r-- | tools/gccld/gccld.cpp | 427 |
1 files changed, 0 insertions, 427 deletions
diff --git a/tools/gccld/gccld.cpp b/tools/gccld/gccld.cpp deleted file mode 100644 index c153f81124..0000000000 --- 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 <fstream> -#include <memory> -using namespace llvm; - -namespace { - cl::list<std::string> - InputFilenames(cl::Positional, cl::desc("<input bytecode files>"), - cl::OneOrMore); - - cl::opt<std::string> - OutputFilename("o", cl::desc("Override output filename"), cl::init("a.out"), - cl::value_desc("filename")); - - cl::opt<bool> - Verbose("v", cl::desc("Print information about actions taken")); - - cl::list<std::string> - LibPaths("L", cl::desc("Specify a library search path"), cl::Prefix, - cl::value_desc("directory")); - - cl::list<std::string> - Libraries("l", cl::desc("Specify libraries to link to"), cl::Prefix, - cl::value_desc("library prefix")); - - cl::opt<bool> - Strip("strip-all", cl::desc("Strip all symbol info from executable")); - cl::opt<bool> - StripDebug("strip-debug", - cl::desc("Strip debugger symbol info from executable")); - - cl::opt<bool> - 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<bool> - 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<bool> - Native("native", cl::ZeroOrMore, - cl::desc("Generate a native binary instead of a shell script")); - cl::opt<bool> - NativeCBE("native-cbe", cl::ZeroOrMore, - cl::desc("Generate a native binary with the C backend and GCC")); - - cl::opt<bool> - SaveTemps("save-temps", - cl::desc("Do not delete temporary files")); - - cl::list<std::string> - RPath("rpath", - cl::desc("Set runtime shared library search path (requires -native or" - " -native-cbe)"), - cl::Prefix, cl::value_desc("directory")); - - cl::opt<std::string> - 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<std::string> - CO4("version-script", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt<bool> - CO5("eh-frame-hdr", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt<std::string> - CO6("h", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt<bool> - CO7("start-group", cl::Hidden, cl::desc("Compatibility option: ignored")); - cl::opt<bool> - 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<std::string>::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<std::string>::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<std::string>& Files, - const cl::list<std::string>& Libraries) { - - // Build the list of linkage items for LinkItems. - - cl::list<std::string>::const_iterator fileIt = Files.begin(); - cl::list<std::string>::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<sys::Path> 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<std::string>::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<Module> 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; -} |