blob: 0656040dc1b195cda88bef55cc26ca3f9d1f3a80 [file] [log] [blame]
Rui Ueyama9e568392013-05-28 18:13:31 +00001//===- lib/Driver/WinLinkDriver.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/// \file
11///
12/// Concrete instance of the Driver for Windows link.exe.
13///
14//===----------------------------------------------------------------------===//
15
16#include "llvm/Option/Arg.h"
17#include "llvm/Option/Option.h"
18
19#include "lld/Driver/Driver.h"
20#include "lld/ReaderWriter/PECOFFTargetInfo.h"
21
22namespace lld {
23
24namespace {
25
26// Create enum with OPT_xxx values for each option in WinLinkOptions.td
27enum WinLinkOpt {
28 OPT_INVALID = 0,
29#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, HELP, META) \
30 OPT_##ID,
31#include "WinLinkOptions.inc"
32 LastOption
33#undef OPTION
34};
35
36// Create prefix string literals used in WinLinkOptions.td
37#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
38#include "WinLinkOptions.inc"
39#undef PREFIX
40
41// Create table mapping all options defined in WinLinkOptions.td
42static const llvm::opt::OptTable::Info infoTable[] = {
43#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \
44 HELPTEXT, METAVAR) \
45 { PREFIX, NAME, HELPTEXT, METAVAR, OPT_##ID, llvm::opt::Option::KIND##Class, \
46 PARAM, FLAGS, OPT_##GROUP, OPT_##ALIAS },
47#include "WinLinkOptions.inc"
48#undef OPTION
49};
50
51// Create OptTable class for parsing actual command line arguments
52class WinLinkOptTable : public llvm::opt::OptTable {
53public:
54 WinLinkOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
55};
56
57// Returns the index of "--" or -1 if not found.
58int findDoubleDash(int argc, const char *argv[]) {
59 for (int i = 0; i < argc; ++i)
60 if (std::strcmp(argv[i], "--") == 0)
61 return i;
62 return -1;
63}
64
65} // namespace
66
67
68bool WinLinkDriver::linkPECOFF(int argc, const char *argv[],
69 raw_ostream &diagnostics) {
70 PECOFFTargetInfo info;
71 if (parse(argc, argv, info, diagnostics))
72 return true;
73 return link(info, diagnostics);
74}
75
76bool WinLinkDriver::parse(int argc, const char *argv[],
77 PECOFFTargetInfo &info, raw_ostream &diagnostics) {
78 // Arguments after "--" are interpreted as filenames even if they start with
79 // a hyphen or a slash. This is not compatible with link.exe but useful for
80 // us to test lld on Unix.
81 int doubleDashPosition = findDoubleDash(argc, argv);
82 int argEnd = (doubleDashPosition > 0) ? doubleDashPosition : argc;
83
84 // Parse command line options using WinLinkOptions.td
85 std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
86 WinLinkOptTable table;
87 unsigned missingIndex;
88 unsigned missingCount;
89 parsedArgs.reset(
90 table.ParseArgs(&argv[1], &argv[argEnd], missingIndex, missingCount));
91 if (missingCount) {
92 diagnostics << "error: missing arg value for '"
93 << parsedArgs->getArgString(missingIndex) << "' expected "
94 << missingCount << " argument(s).\n";
95 return true;
96 }
97
98 // Handle -help
99 if (parsedArgs->getLastArg(OPT_help)) {
100 table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
101 return true;
102 }
103
104 // Copy -mllvm
105 for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_mllvm),
106 ie = parsedArgs->filtered_end();
107 it != ie; ++it) {
108 info.appendLLVMOption((*it)->getValue());
109 }
110
111 // Add input files
112 for (llvm::opt::arg_iterator it = parsedArgs->filtered_begin(OPT_INPUT),
113 ie = parsedArgs->filtered_end();
114 it != ie; ++it) {
115 info.appendInputFile((*it)->getValue());
116 }
117
118 // Arguments after "--" are also input files
119 if (doubleDashPosition > 0)
120 for (int i = doubleDashPosition + 1; i < argc; ++i)
121 info.appendInputFile(argv[i]);
122
123 // Validate the combination of options used.
124 return info.validate(diagnostics);
125}
126
127} // namespace lld