[MIPS GlobalISel] Select MSA vector generic and builtin add
[llvm-complete.git] / lib / ToolDrivers / llvm-dlltool / DlltoolDriver.cpp
blob19f253be7952f74d0d9187616525e64f0d53766e
1 //===- DlltoolDriver.cpp - dlltool.exe-compatible driver ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines an interface to a dlltool.exe-compatible driver.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/ToolDrivers/llvm-dlltool/DlltoolDriver.h"
14 #include "llvm/Object/COFF.h"
15 #include "llvm/Object/COFFImportFile.h"
16 #include "llvm/Object/COFFModuleDefinition.h"
17 #include "llvm/Option/Arg.h"
18 #include "llvm/Option/ArgList.h"
19 #include "llvm/Option/Option.h"
20 #include "llvm/Support/Path.h"
22 #include <vector>
24 using namespace llvm;
25 using namespace llvm::object;
26 using namespace llvm::COFF;
28 namespace {
30 enum {
31 OPT_INVALID = 0,
32 #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID,
33 #include "Options.inc"
34 #undef OPTION
37 #define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
38 #include "Options.inc"
39 #undef PREFIX
41 static const llvm::opt::OptTable::Info InfoTable[] = {
42 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
43 {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \
44 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
45 #include "Options.inc"
46 #undef OPTION
49 class DllOptTable : public llvm::opt::OptTable {
50 public:
51 DllOptTable() : OptTable(InfoTable, false) {}
54 } // namespace
56 // Opens a file. Path has to be resolved already.
57 static std::unique_ptr<MemoryBuffer> openFile(const Twine &Path) {
58 ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> MB = MemoryBuffer::getFile(Path);
60 if (std::error_code EC = MB.getError()) {
61 llvm::errs() << "cannot open file " << Path << ": " << EC.message() << "\n";
62 return nullptr;
65 return std::move(*MB);
68 static MachineTypes getEmulation(StringRef S) {
69 return StringSwitch<MachineTypes>(S)
70 .Case("i386", IMAGE_FILE_MACHINE_I386)
71 .Case("i386:x86-64", IMAGE_FILE_MACHINE_AMD64)
72 .Case("arm", IMAGE_FILE_MACHINE_ARMNT)
73 .Case("arm64", IMAGE_FILE_MACHINE_ARM64)
74 .Default(IMAGE_FILE_MACHINE_UNKNOWN);
77 int llvm::dlltoolDriverMain(llvm::ArrayRef<const char *> ArgsArr) {
78 DllOptTable Table;
79 unsigned MissingIndex;
80 unsigned MissingCount;
81 llvm::opt::InputArgList Args =
82 Table.ParseArgs(ArgsArr.slice(1), MissingIndex, MissingCount);
83 if (MissingCount) {
84 llvm::errs() << Args.getArgString(MissingIndex) << ": missing argument\n";
85 return 1;
88 // Handle when no input or output is specified
89 if (Args.hasArgNoClaim(OPT_INPUT) ||
90 (!Args.hasArgNoClaim(OPT_d) && !Args.hasArgNoClaim(OPT_l))) {
91 Table.PrintHelp(outs(), "llvm-dlltool [options] file...", "llvm-dlltool",
92 false);
93 llvm::outs() << "\nTARGETS: i386, i386:x86-64, arm, arm64\n";
94 return 1;
97 if (!Args.hasArgNoClaim(OPT_m) && Args.hasArgNoClaim(OPT_d)) {
98 llvm::errs() << "error: no target machine specified\n"
99 << "supported targets: i386, i386:x86-64, arm, arm64\n";
100 return 1;
103 for (auto *Arg : Args.filtered(OPT_UNKNOWN))
104 llvm::errs() << "ignoring unknown argument: " << Arg->getAsString(Args)
105 << "\n";
107 if (!Args.hasArg(OPT_d)) {
108 llvm::errs() << "no definition file specified\n";
109 return 1;
112 std::unique_ptr<MemoryBuffer> MB =
113 openFile(Args.getLastArg(OPT_d)->getValue());
114 if (!MB)
115 return 1;
117 if (!MB->getBufferSize()) {
118 llvm::errs() << "definition file empty\n";
119 return 1;
122 COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;
123 if (auto *Arg = Args.getLastArg(OPT_m))
124 Machine = getEmulation(Arg->getValue());
126 if (Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
127 llvm::errs() << "unknown target\n";
128 return 1;
131 Expected<COFFModuleDefinition> Def =
132 parseCOFFModuleDefinition(*MB, Machine, true);
134 if (!Def) {
135 llvm::errs() << "error parsing definition\n"
136 << errorToErrorCode(Def.takeError()).message();
137 return 1;
140 // Do this after the parser because parseCOFFModuleDefinition sets OutputFile.
141 if (auto *Arg = Args.getLastArg(OPT_D))
142 Def->OutputFile = Arg->getValue();
144 if (Def->OutputFile.empty()) {
145 llvm::errs() << "no DLL name specified\n";
146 return 1;
149 std::string Path = Args.getLastArgValue(OPT_l);
151 // If ExtName is set (if the "ExtName = Name" syntax was used), overwrite
152 // Name with ExtName and clear ExtName. When only creating an import
153 // library and not linking, the internal name is irrelevant. This avoids
154 // cases where writeImportLibrary tries to transplant decoration from
155 // symbol decoration onto ExtName.
156 for (COFFShortExport& E : Def->Exports) {
157 if (!E.ExtName.empty()) {
158 E.Name = E.ExtName;
159 E.ExtName.clear();
163 if (Machine == IMAGE_FILE_MACHINE_I386 && Args.getLastArg(OPT_k)) {
164 for (COFFShortExport& E : Def->Exports) {
165 if (!E.AliasTarget.empty() || (!E.Name.empty() && E.Name[0] == '?'))
166 continue;
167 E.SymbolName = E.Name;
168 // Trim off the trailing decoration. Symbols will always have a
169 // starting prefix here (either _ for cdecl/stdcall, @ for fastcall
170 // or ? for C++ functions). Vectorcall functions won't have any
171 // fixed prefix, but the function base name will still be at least
172 // one char.
173 E.Name = E.Name.substr(0, E.Name.find('@', 1));
174 // By making sure E.SymbolName != E.Name for decorated symbols,
175 // writeImportLibrary writes these symbols with the type
176 // IMPORT_NAME_UNDECORATE.
180 if (!Path.empty() &&
181 writeImportLibrary(Def->OutputFile, Path, Def->Exports, Machine, true))
182 return 1;
183 return 0;