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