1 | //===-- COFFDirectiveParser.cpp - JITLink coff directive parser --*- C++ -*===// |
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 | // MSVC COFF directive parser |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "COFFDirectiveParser.h" |
14 | |
15 | #include <array> |
16 | |
17 | using namespace llvm; |
18 | using namespace jitlink; |
19 | |
20 | #define DEBUG_TYPE "jitlink" |
21 | |
22 | // Create prefix string literals used in Options.td |
23 | #define PREFIX(NAME, VALUE) \ |
24 | static constexpr StringLiteral NAME##_init[] = VALUE; \ |
25 | static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ |
26 | std::size(NAME##_init) - 1); |
27 | #include "COFFOptions.inc" |
28 | #undef PREFIX |
29 | |
30 | static constexpr const StringLiteral PrefixTable_init[] = |
31 | #define PREFIX_UNION(VALUES) VALUES |
32 | #include "COFFOptions.inc" |
33 | #undef PREFIX_UNION |
34 | ; |
35 | static constexpr const ArrayRef<StringLiteral> |
36 | PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); |
37 | |
38 | // Create table mapping all options defined in COFFOptions.td |
39 | using namespace llvm::opt; |
40 | static constexpr opt::OptTable::Info infoTable[] = { |
41 | #define OPTION(...) \ |
42 | LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(COFF_OPT_, __VA_ARGS__), |
43 | #include "COFFOptions.inc" |
44 | #undef OPTION |
45 | }; |
46 | |
47 | class COFFOptTable : public opt::PrecomputedOptTable { |
48 | public: |
49 | COFFOptTable() : PrecomputedOptTable(infoTable, PrefixTable, true) {} |
50 | }; |
51 | |
52 | static COFFOptTable optTable; |
53 | |
54 | Expected<opt::InputArgList> COFFDirectiveParser::parse(StringRef Str) { |
55 | SmallVector<StringRef, 16> Tokens; |
56 | SmallVector<const char *, 16> Buffer; |
57 | cl::TokenizeWindowsCommandLineNoCopy(Source: Str, Saver&: saver, NewArgv&: Tokens); |
58 | for (StringRef Tok : Tokens) { |
59 | bool HasNul = Tok.end() != Str.end() && Tok.data()[Tok.size()] == '\0'; |
60 | Buffer.push_back(Elt: HasNul ? Tok.data() : saver.save(S: Tok).data()); |
61 | } |
62 | |
63 | unsigned missingIndex; |
64 | unsigned missingCount; |
65 | |
66 | auto Result = optTable.ParseArgs(Args: Buffer, MissingArgIndex&: missingIndex, MissingArgCount&: missingCount); |
67 | |
68 | if (missingCount) |
69 | return make_error<JITLinkError>(Args: Twine("COFF directive parsing failed: " ) + |
70 | Result.getArgString(Index: missingIndex) + |
71 | " missing argument" ); |
72 | LLVM_DEBUG({ |
73 | for (auto *arg : Result.filtered(COFF_OPT_UNKNOWN)) |
74 | dbgs() << "Unknown coff option argument: " << arg->getAsString(Result) |
75 | << "\n" ; |
76 | }); |
77 | return std::move(Result); |
78 | } |
79 | |