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