1c8fbf6ffSEugene Zelenko //===- AMDKernelCodeTUtils.cpp --------------------------------------------===// 2499a5c63SValery Pykhtin // 3*2946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*2946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 5*2946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6499a5c63SValery Pykhtin // 7499a5c63SValery Pykhtin //===----------------------------------------------------------------------===// 8499a5c63SValery Pykhtin // 9499a5c63SValery Pykhtin /// \file - utility functions to parse/print amd_kernel_code_t structure 10499a5c63SValery Pykhtin // 11499a5c63SValery Pykhtin //===----------------------------------------------------------------------===// 12499a5c63SValery Pykhtin 13499a5c63SValery Pykhtin #include "AMDKernelCodeTUtils.h" 14499a5c63SValery Pykhtin #include "SIDefines.h" 15c8fbf6ffSEugene Zelenko #include "llvm/ADT/ArrayRef.h" 16c8fbf6ffSEugene Zelenko #include "llvm/ADT/StringMap.h" 17c8fbf6ffSEugene Zelenko #include "llvm/ADT/StringRef.h" 18c8fbf6ffSEugene Zelenko #include "llvm/MC/MCParser/MCAsmLexer.h" 19c8fbf6ffSEugene Zelenko #include "llvm/MC/MCParser/MCAsmParser.h" 20c8fbf6ffSEugene Zelenko #include "llvm/Support/raw_ostream.h" 21c8fbf6ffSEugene Zelenko #include <cassert> 22c8fbf6ffSEugene Zelenko #include <cstdint> 23c8fbf6ffSEugene Zelenko #include <utility> 24499a5c63SValery Pykhtin 25499a5c63SValery Pykhtin using namespace llvm; 26499a5c63SValery Pykhtin 27499a5c63SValery Pykhtin static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() { 28499a5c63SValery Pykhtin static StringRef const Table[] = { 29499a5c63SValery Pykhtin "", // not found placeholder 30a2e5c88bSSam Kolton #define RECORD(name, altName, print, parse) #name 31499a5c63SValery Pykhtin #include "AMDKernelCodeTInfo.h" 32499a5c63SValery Pykhtin #undef RECORD 33499a5c63SValery Pykhtin }; 34499a5c63SValery Pykhtin return makeArrayRef(Table); 35499a5c63SValery Pykhtin } 36499a5c63SValery Pykhtin 37a2e5c88bSSam Kolton static ArrayRef<StringRef> get_amd_kernel_code_t_FldAltNames() { 38a2e5c88bSSam Kolton static StringRef const Table[] = { 39a2e5c88bSSam Kolton "", // not found placeholder 40a2e5c88bSSam Kolton #define RECORD(name, altName, print, parse) #altName 41a2e5c88bSSam Kolton #include "AMDKernelCodeTInfo.h" 42a2e5c88bSSam Kolton #undef RECORD 43a2e5c88bSSam Kolton }; 44a2e5c88bSSam Kolton return makeArrayRef(Table); 45a2e5c88bSSam Kolton } 46a2e5c88bSSam Kolton 47a2e5c88bSSam Kolton static StringMap<int> createIndexMap(const ArrayRef<StringRef> &names, 48a2e5c88bSSam Kolton const ArrayRef<StringRef> &altNames) { 49499a5c63SValery Pykhtin StringMap<int> map; 50a2e5c88bSSam Kolton assert(names.size() == altNames.size()); 51a2e5c88bSSam Kolton for (unsigned i = 0; i < names.size(); ++i) { 52a2e5c88bSSam Kolton map.insert(std::make_pair(names[i], i)); 53a2e5c88bSSam Kolton map.insert(std::make_pair(altNames[i], i)); 54a2e5c88bSSam Kolton } 5550cd3c4eSValery Pykhtin return map; 56499a5c63SValery Pykhtin } 57499a5c63SValery Pykhtin 58499a5c63SValery Pykhtin static int get_amd_kernel_code_t_FieldIndex(StringRef name) { 59a2e5c88bSSam Kolton static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(), 60a2e5c88bSSam Kolton get_amd_kernel_code_t_FldAltNames()); 61499a5c63SValery Pykhtin return map.lookup(name) - 1; // returns -1 if not found 62499a5c63SValery Pykhtin } 63499a5c63SValery Pykhtin 64499a5c63SValery Pykhtin static StringRef get_amd_kernel_code_t_FieldName(int index) { 65499a5c63SValery Pykhtin return get_amd_kernel_code_t_FldNames()[index + 1]; 66499a5c63SValery Pykhtin } 67499a5c63SValery Pykhtin 68499a5c63SValery Pykhtin // Field printing 69499a5c63SValery Pykhtin 704fb78518SBenjamin Kramer static raw_ostream &printName(raw_ostream &OS, StringRef Name) { 71499a5c63SValery Pykhtin return OS << Name << " = "; 72499a5c63SValery Pykhtin } 73499a5c63SValery Pykhtin 74499a5c63SValery Pykhtin template <typename T, T amd_kernel_code_t::*ptr> 754fb78518SBenjamin Kramer static void printField(StringRef Name, const amd_kernel_code_t &C, 76499a5c63SValery Pykhtin raw_ostream &OS) { 77499a5c63SValery Pykhtin printName(OS, Name) << (int)(C.*ptr); 78499a5c63SValery Pykhtin } 79499a5c63SValery Pykhtin 80499a5c63SValery Pykhtin template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 814fb78518SBenjamin Kramer static void printBitField(StringRef Name, const amd_kernel_code_t &c, 82499a5c63SValery Pykhtin raw_ostream &OS) { 83499a5c63SValery Pykhtin const auto Mask = (static_cast<T>(1) << width) - 1; 84499a5c63SValery Pykhtin printName(OS, Name) << (int)((c.*ptr >> shift) & Mask); 85499a5c63SValery Pykhtin } 86499a5c63SValery Pykhtin 87c8fbf6ffSEugene Zelenko using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &); 88499a5c63SValery Pykhtin 89499a5c63SValery Pykhtin static ArrayRef<PrintFx> getPrinterTable() { 90499a5c63SValery Pykhtin static const PrintFx Table[] = { 91a2e5c88bSSam Kolton #define RECORD(name, altName, print, parse) print 92499a5c63SValery Pykhtin #include "AMDKernelCodeTInfo.h" 93499a5c63SValery Pykhtin #undef RECORD 94499a5c63SValery Pykhtin }; 95499a5c63SValery Pykhtin return makeArrayRef(Table); 96499a5c63SValery Pykhtin } 97499a5c63SValery Pykhtin 98499a5c63SValery Pykhtin void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C, 99499a5c63SValery Pykhtin int FldIndex, 100499a5c63SValery Pykhtin raw_ostream &OS) { 101499a5c63SValery Pykhtin auto Printer = getPrinterTable()[FldIndex]; 102499a5c63SValery Pykhtin if (Printer) 103499a5c63SValery Pykhtin Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS); 104499a5c63SValery Pykhtin } 105499a5c63SValery Pykhtin 106499a5c63SValery Pykhtin void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C, 107499a5c63SValery Pykhtin raw_ostream &OS, 108499a5c63SValery Pykhtin const char *tab) { 109499a5c63SValery Pykhtin const int Size = getPrinterTable().size(); 110499a5c63SValery Pykhtin for (int i = 0; i < Size; ++i) { 111499a5c63SValery Pykhtin OS << tab; 112499a5c63SValery Pykhtin printAmdKernelCodeField(*C, i, OS); 113499a5c63SValery Pykhtin OS << '\n'; 114499a5c63SValery Pykhtin } 115499a5c63SValery Pykhtin } 116499a5c63SValery Pykhtin 117499a5c63SValery Pykhtin // Field parsing 118499a5c63SValery Pykhtin 119a852d695SValery Pykhtin static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) { 120a852d695SValery Pykhtin 121a852d695SValery Pykhtin if (MCParser.getLexer().isNot(AsmToken::Equal)) { 122499a5c63SValery Pykhtin Err << "expected '='"; 123499a5c63SValery Pykhtin return false; 124499a5c63SValery Pykhtin } 125a852d695SValery Pykhtin MCParser.getLexer().Lex(); 126a852d695SValery Pykhtin 127a852d695SValery Pykhtin if (MCParser.parseAbsoluteExpression(Value)) { 128a852d695SValery Pykhtin Err << "integer absolute expression expected"; 129499a5c63SValery Pykhtin return false; 130499a5c63SValery Pykhtin } 131499a5c63SValery Pykhtin return true; 132499a5c63SValery Pykhtin } 133499a5c63SValery Pykhtin 134499a5c63SValery Pykhtin template <typename T, T amd_kernel_code_t::*ptr> 135a852d695SValery Pykhtin static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser, 136499a5c63SValery Pykhtin raw_ostream &Err) { 137a852d695SValery Pykhtin int64_t Value = 0; 138a852d695SValery Pykhtin if (!expectAbsExpression(MCParser, Value, Err)) 139499a5c63SValery Pykhtin return false; 140a852d695SValery Pykhtin C.*ptr = (T)Value; 141499a5c63SValery Pykhtin return true; 142499a5c63SValery Pykhtin } 143499a5c63SValery Pykhtin 144499a5c63SValery Pykhtin template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 145a852d695SValery Pykhtin static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser, 146499a5c63SValery Pykhtin raw_ostream &Err) { 147a852d695SValery Pykhtin int64_t Value = 0; 148a852d695SValery Pykhtin if (!expectAbsExpression(MCParser, Value, Err)) 149499a5c63SValery Pykhtin return false; 150499a5c63SValery Pykhtin const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift; 151499a5c63SValery Pykhtin C.*ptr &= (T)~Mask; 152a852d695SValery Pykhtin C.*ptr |= (T)((Value << shift) & Mask); 153499a5c63SValery Pykhtin return true; 154499a5c63SValery Pykhtin } 155499a5c63SValery Pykhtin 156c8fbf6ffSEugene Zelenko using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser, 157499a5c63SValery Pykhtin raw_ostream &Err); 158499a5c63SValery Pykhtin 159499a5c63SValery Pykhtin static ArrayRef<ParseFx> getParserTable() { 160499a5c63SValery Pykhtin static const ParseFx Table[] = { 161a2e5c88bSSam Kolton #define RECORD(name, altName, print, parse) parse 162499a5c63SValery Pykhtin #include "AMDKernelCodeTInfo.h" 163499a5c63SValery Pykhtin #undef RECORD 164499a5c63SValery Pykhtin }; 165499a5c63SValery Pykhtin return makeArrayRef(Table); 166499a5c63SValery Pykhtin } 167499a5c63SValery Pykhtin 168499a5c63SValery Pykhtin bool llvm::parseAmdKernelCodeField(StringRef ID, 169a852d695SValery Pykhtin MCAsmParser &MCParser, 170499a5c63SValery Pykhtin amd_kernel_code_t &C, 171499a5c63SValery Pykhtin raw_ostream &Err) { 172499a5c63SValery Pykhtin const int Idx = get_amd_kernel_code_t_FieldIndex(ID); 173499a5c63SValery Pykhtin if (Idx < 0) { 174499a5c63SValery Pykhtin Err << "unexpected amd_kernel_code_t field name " << ID; 175499a5c63SValery Pykhtin return false; 176499a5c63SValery Pykhtin } 177499a5c63SValery Pykhtin auto Parser = getParserTable()[Idx]; 178a852d695SValery Pykhtin return Parser ? Parser(C, MCParser, Err) : false; 179499a5c63SValery Pykhtin } 180