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 //===----------------------------------------------------------------------===// 11 // 12 /// \file - utility functions to parse/print amd_kernel_code_t structure 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "AMDKernelCodeTUtils.h" 17 #include "SIDefines.h" 18 #include <llvm/MC/MCParser/MCAsmLexer.h> 19 #include <llvm/MC/MCParser/MCAsmParser.h> 20 #include <llvm/Support/raw_ostream.h> 21 22 using namespace llvm; 23 24 static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() { 25 static StringRef const Table[] = { 26 "", // not found placeholder 27 #define RECORD(name, altName, print, parse) #name 28 #include "AMDKernelCodeTInfo.h" 29 #undef RECORD 30 }; 31 return makeArrayRef(Table); 32 } 33 34 static ArrayRef<StringRef> get_amd_kernel_code_t_FldAltNames() { 35 static StringRef const Table[] = { 36 "", // not found placeholder 37 #define RECORD(name, altName, print, parse) #altName 38 #include "AMDKernelCodeTInfo.h" 39 #undef RECORD 40 }; 41 return makeArrayRef(Table); 42 } 43 44 static StringMap<int> createIndexMap(const ArrayRef<StringRef> &names, 45 const ArrayRef<StringRef> &altNames) { 46 StringMap<int> map; 47 assert(names.size() == altNames.size()); 48 for (unsigned i = 0; i < names.size(); ++i) { 49 map.insert(std::make_pair(names[i], i)); 50 map.insert(std::make_pair(altNames[i], i)); 51 } 52 return map; 53 } 54 55 static int get_amd_kernel_code_t_FieldIndex(StringRef name) { 56 static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(), 57 get_amd_kernel_code_t_FldAltNames()); 58 return map.lookup(name) - 1; // returns -1 if not found 59 } 60 61 static StringRef get_amd_kernel_code_t_FieldName(int index) { 62 return get_amd_kernel_code_t_FldNames()[index + 1]; 63 } 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 typedef void(*PrintFx)(StringRef, 86 const amd_kernel_code_t &, 87 raw_ostream &); 88 89 static ArrayRef<PrintFx> getPrinterTable() { 90 static const PrintFx Table[] = { 91 #define RECORD(name, altName, print, parse) print 92 #include "AMDKernelCodeTInfo.h" 93 #undef RECORD 94 }; 95 return makeArrayRef(Table); 96 } 97 98 void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C, 99 int FldIndex, 100 raw_ostream &OS) { 101 auto Printer = getPrinterTable()[FldIndex]; 102 if (Printer) 103 Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS); 104 } 105 106 void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C, 107 raw_ostream &OS, 108 const char *tab) { 109 const int Size = getPrinterTable().size(); 110 for (int i = 0; i < Size; ++i) { 111 OS << tab; 112 printAmdKernelCodeField(*C, i, OS); 113 OS << '\n'; 114 } 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 typedef bool(*ParseFx)(amd_kernel_code_t &, 158 MCAsmParser &MCParser, 159 raw_ostream &Err); 160 161 static ArrayRef<ParseFx> getParserTable() { 162 static const ParseFx Table[] = { 163 #define RECORD(name, altName, print, parse) parse 164 #include "AMDKernelCodeTInfo.h" 165 #undef RECORD 166 }; 167 return makeArrayRef(Table); 168 } 169 170 bool llvm::parseAmdKernelCodeField(StringRef ID, 171 MCAsmParser &MCParser, 172 amd_kernel_code_t &C, 173 raw_ostream &Err) { 174 const int Idx = get_amd_kernel_code_t_FieldIndex(ID); 175 if (Idx < 0) { 176 Err << "unexpected amd_kernel_code_t field name " << ID; 177 return false; 178 } 179 auto Parser = getParserTable()[Idx]; 180 return Parser ? Parser(C, MCParser, Err) : false; 181 } 182