llvm-6502/tools/gccld/gccld.cpp
Chris Lattner 2fbfdcffd3 Change references to the Method class to be references to the Function
class.  The Method class is obsolete (renamed) and all references to it
are being converted over to Function.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@2144 91177308-0d34-0410-b5e6-96231b3b80d8
2002-04-07 20:49:59 +00:00

151 lines
4.9 KiB
C++

//===----------------------------------------------------------------------===//
// 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 "Support/CommandLine.h"
#include <fstream>
#include <memory>
#include <algorithm>
#include <sys/types.h> // For FileExists
#include <sys/stat.h>
cl::StringList InputFilenames("", "Load <arg> 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<Module> 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<Module>(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 'gccld -v ...' for more info.\n";
else
cerr << "Could not locate bytecode file: '" << FN << "'\n";
return std::auto_ptr<Module>();
}
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()) {
// Sort libraries list...
sort(Libraries.begin(), Libraries.end());
// Remove duplicate libraries entries...
Libraries.erase(unique(Libraries.begin(), Libraries.end()),
Libraries.end());
// Add all of the libraries to the end of the link line...
for (unsigned i = 0; i < Libraries.size(); ++i)
InputFilenames.push_back("lib" + Libraries[i] + ".bc");
}
std::auto_ptr<Module> Composite(LoadFile(InputFilenames[BaseArg]));
if (Composite.get() == 0) return 1;
for (unsigned i = BaseArg+1; i < InputFilenames.size(); ++i) {
std::auto_ptr<Module> 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;
}
}
// Now that composite has been compiled, scan through the module, looking for
// a main function. If main is defined, mark all other functions internal.
//
// Next run globaldce...
// next ?
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;
}