1*bdd1243dSDimitry Andric //===-- COFFDirectiveParser.cpp - JITLink coff directive parser --*- C++ -*===// 2*bdd1243dSDimitry Andric // 3*bdd1243dSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*bdd1243dSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*bdd1243dSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*bdd1243dSDimitry Andric // 7*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 8*bdd1243dSDimitry Andric // 9*bdd1243dSDimitry Andric // MSVC COFF directive parser 10*bdd1243dSDimitry Andric // 11*bdd1243dSDimitry Andric //===----------------------------------------------------------------------===// 12*bdd1243dSDimitry Andric 13*bdd1243dSDimitry Andric #include "COFFDirectiveParser.h" 14*bdd1243dSDimitry Andric 15*bdd1243dSDimitry Andric #include <array> 16*bdd1243dSDimitry Andric 17*bdd1243dSDimitry Andric using namespace llvm; 18*bdd1243dSDimitry Andric using namespace jitlink; 19*bdd1243dSDimitry Andric 20*bdd1243dSDimitry Andric #define DEBUG_TYPE "jitlink" 21*bdd1243dSDimitry Andric 22*bdd1243dSDimitry Andric // Create prefix string literals used in Options.td 23*bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE) \ 24*bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 25*bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 26*bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 27*bdd1243dSDimitry Andric #include "COFFOptions.inc" 28*bdd1243dSDimitry Andric #undef PREFIX 29*bdd1243dSDimitry Andric 30*bdd1243dSDimitry Andric static constexpr const StringLiteral PrefixTable_init[] = 31*bdd1243dSDimitry Andric #define PREFIX_UNION(VALUES) VALUES 32*bdd1243dSDimitry Andric #include "COFFOptions.inc" 33*bdd1243dSDimitry Andric #undef PREFIX_UNION 34*bdd1243dSDimitry Andric ; 35*bdd1243dSDimitry Andric static constexpr const ArrayRef<StringLiteral> 36*bdd1243dSDimitry Andric PrefixTable(PrefixTable_init, std::size(PrefixTable_init) - 1); 37*bdd1243dSDimitry Andric 38*bdd1243dSDimitry Andric // Create table mapping all options defined in COFFOptions.td 39*bdd1243dSDimitry Andric static constexpr opt::OptTable::Info infoTable[] = { 40*bdd1243dSDimitry Andric #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 41*bdd1243dSDimitry Andric {X1, \ 42*bdd1243dSDimitry Andric X2, \ 43*bdd1243dSDimitry Andric X10, \ 44*bdd1243dSDimitry Andric X11, \ 45*bdd1243dSDimitry Andric COFF_OPT_##ID, \ 46*bdd1243dSDimitry Andric opt::Option::KIND##Class, \ 47*bdd1243dSDimitry Andric X9, \ 48*bdd1243dSDimitry Andric X8, \ 49*bdd1243dSDimitry Andric COFF_OPT_##GROUP, \ 50*bdd1243dSDimitry Andric COFF_OPT_##ALIAS, \ 51*bdd1243dSDimitry Andric X7, \ 52*bdd1243dSDimitry Andric X12}, 53*bdd1243dSDimitry Andric #include "COFFOptions.inc" 54*bdd1243dSDimitry Andric #undef OPTION 55*bdd1243dSDimitry Andric }; 56*bdd1243dSDimitry Andric 57*bdd1243dSDimitry Andric class COFFOptTable : public opt::PrecomputedOptTable { 58*bdd1243dSDimitry Andric public: 59*bdd1243dSDimitry Andric COFFOptTable() : PrecomputedOptTable(infoTable, PrefixTable, true) {} 60*bdd1243dSDimitry Andric }; 61*bdd1243dSDimitry Andric 62*bdd1243dSDimitry Andric static COFFOptTable optTable; 63*bdd1243dSDimitry Andric 64*bdd1243dSDimitry Andric Expected<opt::InputArgList> COFFDirectiveParser::parse(StringRef Str) { 65*bdd1243dSDimitry Andric SmallVector<StringRef, 16> Tokens; 66*bdd1243dSDimitry Andric SmallVector<const char *, 16> Buffer; 67*bdd1243dSDimitry Andric cl::TokenizeWindowsCommandLineNoCopy(Str, saver, Tokens); 68*bdd1243dSDimitry Andric for (StringRef Tok : Tokens) { 69*bdd1243dSDimitry Andric bool HasNul = Tok.end() != Str.end() && Tok.data()[Tok.size()] == '\0'; 70*bdd1243dSDimitry Andric Buffer.push_back(HasNul ? Tok.data() : saver.save(Tok).data()); 71*bdd1243dSDimitry Andric } 72*bdd1243dSDimitry Andric 73*bdd1243dSDimitry Andric unsigned missingIndex; 74*bdd1243dSDimitry Andric unsigned missingCount; 75*bdd1243dSDimitry Andric 76*bdd1243dSDimitry Andric auto Result = optTable.ParseArgs(Buffer, missingIndex, missingCount); 77*bdd1243dSDimitry Andric 78*bdd1243dSDimitry Andric if (missingCount) 79*bdd1243dSDimitry Andric return make_error<JITLinkError>(Twine("COFF directive parsing failed: ") + 80*bdd1243dSDimitry Andric Result.getArgString(missingIndex) + 81*bdd1243dSDimitry Andric " missing argument"); 82*bdd1243dSDimitry Andric LLVM_DEBUG({ 83*bdd1243dSDimitry Andric for (auto *arg : Result.filtered(COFF_OPT_UNKNOWN)) 84*bdd1243dSDimitry Andric dbgs() << "Unknown coff option argument: " << arg->getAsString(Result) 85*bdd1243dSDimitry Andric << "\n"; 86*bdd1243dSDimitry Andric }); 87*bdd1243dSDimitry Andric return std::move(Result); 88*bdd1243dSDimitry Andric } 89