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 static constexpr opt::OptTable::Info infoTable[] = { 40 #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ 41 {X1, \ 42 X2, \ 43 X10, \ 44 X11, \ 45 COFF_OPT_##ID, \ 46 opt::Option::KIND##Class, \ 47 X9, \ 48 X8, \ 49 COFF_OPT_##GROUP, \ 50 COFF_OPT_##ALIAS, \ 51 X7, \ 52 X12}, 53 #include "COFFOptions.inc" 54 #undef OPTION 55 }; 56 57 class COFFOptTable : public opt::PrecomputedOptTable { 58 public: 59 COFFOptTable() : PrecomputedOptTable(infoTable, PrefixTable, true) {} 60 }; 61 62 static COFFOptTable optTable; 63 64 Expected<opt::InputArgList> COFFDirectiveParser::parse(StringRef Str) { 65 SmallVector<StringRef, 16> Tokens; 66 SmallVector<const char *, 16> Buffer; 67 cl::TokenizeWindowsCommandLineNoCopy(Str, saver, Tokens); 68 for (StringRef Tok : Tokens) { 69 bool HasNul = Tok.end() != Str.end() && Tok.data()[Tok.size()] == '\0'; 70 Buffer.push_back(HasNul ? Tok.data() : saver.save(Tok).data()); 71 } 72 73 unsigned missingIndex; 74 unsigned missingCount; 75 76 auto Result = optTable.ParseArgs(Buffer, missingIndex, missingCount); 77 78 if (missingCount) 79 return make_error<JITLinkError>(Twine("COFF directive parsing failed: ") + 80 Result.getArgString(missingIndex) + 81 " missing argument"); 82 LLVM_DEBUG({ 83 for (auto *arg : Result.filtered(COFF_OPT_UNKNOWN)) 84 dbgs() << "Unknown coff option argument: " << arg->getAsString(Result) 85 << "\n"; 86 }); 87 return std::move(Result); 88 } 89