1 //===- AMDKernelCodeTUtils.cpp --------------------------------------------===// 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 /// \file - utility functions to parse/print amd_kernel_code_t structure 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "AMDKernelCodeTUtils.h" 14 #include "AMDKernelCodeT.h" 15 #include "SIDefines.h" 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/StringMap.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/MC/MCParser/MCAsmLexer.h" 20 #include "llvm/MC/MCParser/MCAsmParser.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 using namespace llvm; 24 25 static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() { 26 static StringRef const Table[] = { 27 "", // not found placeholder 28 #define RECORD(name, altName, print, parse) #name 29 #include "AMDKernelCodeTInfo.h" 30 #undef RECORD 31 }; 32 return makeArrayRef(Table); 33 } 34 35 static ArrayRef<StringRef> get_amd_kernel_code_t_FldAltNames() { 36 static StringRef const Table[] = { 37 "", // not found placeholder 38 #define RECORD(name, altName, print, parse) #altName 39 #include "AMDKernelCodeTInfo.h" 40 #undef RECORD 41 }; 42 return makeArrayRef(Table); 43 } 44 45 static StringMap<int> createIndexMap(const ArrayRef<StringRef> &names, 46 const ArrayRef<StringRef> &altNames) { 47 StringMap<int> map; 48 assert(names.size() == altNames.size()); 49 for (unsigned i = 0; i < names.size(); ++i) { 50 map.insert(std::make_pair(names[i], i)); 51 map.insert(std::make_pair(altNames[i], i)); 52 } 53 return map; 54 } 55 56 static int get_amd_kernel_code_t_FieldIndex(StringRef name) { 57 static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(), 58 get_amd_kernel_code_t_FldAltNames()); 59 return map.lookup(name) - 1; // returns -1 if not found 60 } 61 62 static StringRef get_amd_kernel_code_t_FieldName(int index) { 63 return get_amd_kernel_code_t_FldNames()[index + 1]; 64 } 65 66 // Field printing 67 68 static raw_ostream &printName(raw_ostream &OS, StringRef Name) { 69 return OS << Name << " = "; 70 } 71 72 template <typename T, T amd_kernel_code_t::*ptr> 73 static void printField(StringRef Name, const amd_kernel_code_t &C, 74 raw_ostream &OS) { 75 printName(OS, Name) << (int)(C.*ptr); 76 } 77 78 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 79 static void printBitField(StringRef Name, const amd_kernel_code_t &c, 80 raw_ostream &OS) { 81 const auto Mask = (static_cast<T>(1) << width) - 1; 82 printName(OS, Name) << (int)((c.*ptr >> shift) & Mask); 83 } 84 85 using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &); 86 87 static ArrayRef<PrintFx> getPrinterTable() { 88 static const PrintFx Table[] = { 89 #define RECORD(name, altName, print, parse) print 90 #include "AMDKernelCodeTInfo.h" 91 #undef RECORD 92 }; 93 return makeArrayRef(Table); 94 } 95 96 void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C, 97 int FldIndex, 98 raw_ostream &OS) { 99 auto Printer = getPrinterTable()[FldIndex]; 100 if (Printer) 101 Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS); 102 } 103 104 void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C, 105 raw_ostream &OS, 106 const char *tab) { 107 const int Size = getPrinterTable().size(); 108 for (int i = 0; i < Size; ++i) { 109 OS << tab; 110 printAmdKernelCodeField(*C, i, OS); 111 OS << '\n'; 112 } 113 } 114 115 // Field parsing 116 117 static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) { 118 119 if (MCParser.getLexer().isNot(AsmToken::Equal)) { 120 Err << "expected '='"; 121 return false; 122 } 123 MCParser.getLexer().Lex(); 124 125 if (MCParser.parseAbsoluteExpression(Value)) { 126 Err << "integer absolute expression expected"; 127 return false; 128 } 129 return true; 130 } 131 132 template <typename T, T amd_kernel_code_t::*ptr> 133 static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser, 134 raw_ostream &Err) { 135 int64_t Value = 0; 136 if (!expectAbsExpression(MCParser, Value, Err)) 137 return false; 138 C.*ptr = (T)Value; 139 return true; 140 } 141 142 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 143 static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser, 144 raw_ostream &Err) { 145 int64_t Value = 0; 146 if (!expectAbsExpression(MCParser, Value, Err)) 147 return false; 148 const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift; 149 C.*ptr &= (T)~Mask; 150 C.*ptr |= (T)((Value << shift) & Mask); 151 return true; 152 } 153 154 using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser, 155 raw_ostream &Err); 156 157 static ArrayRef<ParseFx> getParserTable() { 158 static const ParseFx Table[] = { 159 #define RECORD(name, altName, print, parse) parse 160 #include "AMDKernelCodeTInfo.h" 161 #undef RECORD 162 }; 163 return makeArrayRef(Table); 164 } 165 166 bool llvm::parseAmdKernelCodeField(StringRef ID, 167 MCAsmParser &MCParser, 168 amd_kernel_code_t &C, 169 raw_ostream &Err) { 170 const int Idx = get_amd_kernel_code_t_FieldIndex(ID); 171 if (Idx < 0) { 172 Err << "unexpected amd_kernel_code_t field name " << ID; 173 return false; 174 } 175 auto Parser = getParserTable()[Idx]; 176 return Parser ? Parser(C, MCParser, Err) : false; 177 } 178