blob: 93365060e0e93f0609c82a64bc91452cbdfd5d5d [file] [log] [blame]
Rui Ueyama411c63602015-05-28 19:09:30 +00001//===- Driver.cpp ---------------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "Config.h"
11#include "Driver.h"
12#include "InputFiles.h"
13#include "Memory.h"
14#include "SymbolTable.h"
15#include "Writer.h"
16#include "lld/Core/Error.h"
17#include "llvm/ADT/Optional.h"
18#include "llvm/ADT/STLExtras.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000019#include "llvm/Option/Arg.h"
20#include "llvm/Option/ArgList.h"
21#include "llvm/Option/Option.h"
22#include "llvm/Support/CommandLine.h"
23#include "llvm/Support/Debug.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000024#include "llvm/Support/Path.h"
Rui Ueyama411c63602015-05-28 19:09:30 +000025#include "llvm/Support/raw_ostream.h"
26#include <memory>
27
28using namespace llvm;
29
Rui Ueyama3500f662015-05-28 20:30:06 +000030namespace lld {
31namespace coff {
Rui Ueyama411c63602015-05-28 19:09:30 +000032
Rui Ueyama3500f662015-05-28 20:30:06 +000033Configuration *Config;
Rui Ueyama411c63602015-05-28 19:09:30 +000034
35static std::string getOutputPath(llvm::opt::InputArgList *Args) {
36 if (auto *Arg = Args->getLastArg(OPT_out))
37 return Arg->getValue();
38 for (auto *Arg : Args->filtered(OPT_INPUT)) {
39 if (!StringRef(Arg->getValue()).endswith_lower(".obj"))
40 continue;
41 SmallString<128> Val = StringRef(Arg->getValue());
42 llvm::sys::path::replace_extension(Val, ".exe");
43 return Val.str();
44 }
45 llvm_unreachable("internal error");
46}
47
Rui Ueyama411c63602015-05-28 19:09:30 +000048std::unique_ptr<InputFile> createFile(StringRef Path) {
49 if (StringRef(Path).endswith_lower(".lib"))
50 return llvm::make_unique<ArchiveFile>(Path);
51 return llvm::make_unique<ObjectFile>(Path);
52}
53
Rui Ueyama3500f662015-05-28 20:30:06 +000054namespace {
55class BumpPtrStringSaver : public llvm::cl::StringSaver {
56public:
57 BumpPtrStringSaver(lld::coff::StringAllocator *A) : Alloc(A) {}
58 const char *SaveString(const char *S) override {
59 return Alloc->save(S).data();
60 }
61 lld::coff::StringAllocator *Alloc;
62};
63}
64
Rui Ueyama411c63602015-05-28 19:09:30 +000065// Parses .drectve section contents and returns a list of files
66// specified by /defaultlib.
67std::error_code parseDirectives(StringRef S,
68 std::vector<std::unique_ptr<InputFile>> *Res,
69 StringAllocator *Alloc) {
70 SmallVector<const char *, 16> Tokens;
71 Tokens.push_back("link"); // argv[0] value. Will be ignored.
72 BumpPtrStringSaver Saver(Alloc);
73 llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
74 Tokens.push_back(nullptr);
75 int Argc = Tokens.size() - 1;
76 const char **Argv = &Tokens[0];
77
78 auto ArgsOrErr = parseArgs(Argc, Argv);
79 if (auto EC = ArgsOrErr.getError())
80 return EC;
81 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
82
83 for (auto *Arg : Args->filtered(OPT_defaultlib)) {
84 std::string Path = findLib(Arg->getValue());
85 if (!Config->insertFile(Path))
86 continue;
87 Res->push_back(llvm::make_unique<ArchiveFile>(Path));
88 }
89 return std::error_code();
90}
91
92bool link(int Argc, const char *Argv[]) {
93 // Parse command line options.
94 Config = new Configuration();
95 auto ArgsOrErr = parseArgs(Argc, Argv);
96 if (auto EC = ArgsOrErr.getError()) {
97 llvm::errs() << EC.message() << "\n";
98 return false;
99 }
100 std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
101
102 if (Args->filtered_begin(OPT_INPUT) == Args->filtered_end()) {
103 llvm::errs() << "no input files.\n";
104 return false;
105 }
106 if (Args->hasArg(OPT_verbose))
107 Config->Verbose = true;
108 if (auto *Arg = Args->getLastArg(OPT_entry))
109 Config->EntryName = Arg->getValue();
110
111 // Parse all input files and put all symbols to the symbol table.
112 // The symbol table will take care of name resolution.
113 SymbolTable Symtab;
114 for (auto *Arg : Args->filtered(OPT_INPUT)) {
115 std::string Path = findFile(Arg->getValue());
116 if (!Config->insertFile(Path))
117 continue;
118 if (auto EC = Symtab.addFile(createFile(Path))) {
119 llvm::errs() << Path << ": " << EC.message() << "\n";
120 return false;
121 }
122 }
123 if (Symtab.reportRemainingUndefines())
124 return false;
125
126 // Write the result.
127 Writer Out(&Symtab);
128 if (auto EC = Out.write(getOutputPath(Args.get()))) {
129 llvm::errs() << EC.message() << "\n";
130 return false;
131 }
132 return true;
133}
134
135} // namespace coff
136} // namespace lld