From: Chris Lattner Date: Thu, 24 Jan 2002 19:12:12 +0000 (+0000) Subject: Initial Checkin of gccld X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=e7fca510f337be7fd32e037c6ea140350d7718a2;p=oota-llvm.git Initial Checkin of gccld git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@1578 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/gccld/Makefile b/tools/gccld/Makefile new file mode 100644 index 00000000000..2c02ad9e7f5 --- /dev/null +++ b/tools/gccld/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../.. + +TOOLNAME = gccld +USEDLIBS = transforms bcreader bcwriter asmwriter analysis vmcore asmwriter support + +include $(LEVEL)/Makefile.common diff --git a/tools/gccld/gccld.cpp b/tools/gccld/gccld.cpp new file mode 100644 index 00000000000..cde23f9d28f --- /dev/null +++ b/tools/gccld/gccld.cpp @@ -0,0 +1,131 @@ +//===----------------------------------------------------------------------===// +// LLVM 'GCCLD' UTILITY +// +// 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 to worried about this. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Linker.h" +#include "llvm/Bytecode/Reader.h" +#include "llvm/Bytecode/Writer.h" +#include "llvm/Module.h" +#include "llvm/Method.h" +#include "Support/CommandLine.h" +#include +#include +#include // For FileExists +#include + + +cl::StringList InputFilenames("", "Load files, linking them together", + cl::OneOrMore); +cl::String OutputFilename("o", "Override output filename", cl::NoFlags,"a.out"); +cl::Flag Verbose ("v", "Print information about actions taken"); +cl::StringList LibPaths ("L", "Specify a library search path", cl::ZeroOrMore); +cl::StringList Libraries ("l", "Specify libraries to link to", cl::ZeroOrMore); + + +// FileExists - Return true if the specified string is an openable file... +static inline bool FileExists(const std::string &FN) { + struct stat StatBuf; + return stat(FN.c_str(), &StatBuf) != -1; +} + +// LoadFile - Read the specified bytecode file in and return it. This routine +// searches the link path for the specified file to try to find it... +// +static inline std::auto_ptr LoadFile(const std::string &FN) { + std::string Filename = FN; + std::string ErrorMessage; + + unsigned NextLibPathIdx = 0; + bool FoundAFile = false; + + while (1) { + if (Verbose) cerr << "Loading '" << Filename << "'\n"; + if (FileExists(Filename)) FoundAFile = true; + Module *Result = ParseBytecodeFile(Filename, &ErrorMessage); + if (Result) return std::auto_ptr(Result); // Load successful! + + if (Verbose) { + cerr << "Error opening bytecode file: '" << Filename << "'"; + if (ErrorMessage.size()) cerr << ": " << ErrorMessage; + cerr << endl; + } + + if (NextLibPathIdx == LibPaths.size()) break; + Filename = LibPaths[NextLibPathIdx++] + "/" + FN; + } + + if (FoundAFile) + cerr << "Bytecode file '" << FN << "' corrupt! " + << "Use 'link -v ...' for more info.\n"; + else + cerr << "Could not locate bytecode file: '" << FN << "'\n"; + return std::auto_ptr(); +} + + + + +int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " llvm linker for GCC\n", + cl::EnableSingleLetterArgValue | + cl::DisableSingleLetterArgGrouping); + assert(InputFilenames.size() > 0 && "OneOrMore is not working"); + + unsigned BaseArg = 0; + std::string ErrorMessage; + + if (!Libraries.empty()) + cerr << "LLVM Linker Warning: Linking to libraries is unimplemented!\n"; + + std::auto_ptr Composite(LoadFile(InputFilenames[BaseArg])); + if (Composite.get() == 0) return 1; + + for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) { + std::auto_ptr M(LoadFile(InputFilenames[i])); + if (M.get() == 0) return 1; + + if (Verbose) cerr << "Linking in '" << InputFilenames[i] << "'\n"; + + if (LinkModules(Composite.get(), M.get(), &ErrorMessage)) { + cerr << "Error linking in '" << InputFilenames[i] << "': " + << ErrorMessage << endl; + return 1; + } + } + + std::ofstream Out((OutputFilename+".bc").c_str()); + if (!Out.good()) { + cerr << "Error opening '" << OutputFilename << ".bc' for writing!\n"; + return 1; + } + + if (Verbose) cerr << "Writing bytecode...\n"; + WriteBytecodeToFile(Composite.get(), Out); + Out.close(); + + // Output the script to start the program... + std::ofstream Out2(OutputFilename.c_str()); + if (!Out2.good()) { + cerr << "Error openeing '" << OutputFilename << "' for writing!\n"; + return 1; + } + Out2 << "#!/bin/sh\nlli -q $0.bc\n"; + Out2.close(); + + // Make the script executable... + chmod(OutputFilename.c_str(), 0755); + + return 0; +}