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, print, parse) #name 28 #include "AMDKernelCodeTInfo.h" 29 #undef RECORD 30 }; 31 return makeArrayRef(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 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 static 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 static void printField(StringRef Name, const amd_kernel_code_t &C, 59 raw_ostream &OS) { 60 printName(OS, Name) << (int)(C.*ptr); 61 } 62 63 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 64 static void printBitField(StringRef Name, const amd_kernel_code_t &c, 65 raw_ostream &OS) { 66 const auto Mask = (static_cast<T>(1) << width) - 1; 67 printName(OS, Name) << (int)((c.*ptr >> shift) & Mask); 68 } 69 70 typedef void(*PrintFx)(StringRef, 71 const amd_kernel_code_t &, 72 raw_ostream &); 73 74 static ArrayRef<PrintFx> getPrinterTable() { 75 static const PrintFx Table[] = { 76 #define RECORD(name, print, parse) print 77 #include "AMDKernelCodeTInfo.h" 78 #undef RECORD 79 }; 80 return makeArrayRef(Table); 81 } 82 83 void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C, 84 int FldIndex, 85 raw_ostream &OS) { 86 auto Printer = getPrinterTable()[FldIndex]; 87 if (Printer) 88 Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS); 89 } 90 91 void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C, 92 raw_ostream &OS, 93 const char *tab) { 94 const int Size = getPrinterTable().size(); 95 for (int i = 0; i < Size; ++i) { 96 OS << tab; 97 printAmdKernelCodeField(*C, i, OS); 98 OS << '\n'; 99 } 100 } 101 102 103 // Field parsing 104 105 static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) { 106 107 if (MCParser.getLexer().isNot(AsmToken::Equal)) { 108 Err << "expected '='"; 109 return false; 110 } 111 MCParser.getLexer().Lex(); 112 113 if (MCParser.parseAbsoluteExpression(Value)) { 114 Err << "integer absolute expression expected"; 115 return false; 116 } 117 return true; 118 } 119 120 template <typename T, T amd_kernel_code_t::*ptr> 121 static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser, 122 raw_ostream &Err) { 123 int64_t Value = 0; 124 if (!expectAbsExpression(MCParser, Value, Err)) 125 return false; 126 C.*ptr = (T)Value; 127 return true; 128 } 129 130 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 131 static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser, 132 raw_ostream &Err) { 133 int64_t Value = 0; 134 if (!expectAbsExpression(MCParser, Value, Err)) 135 return false; 136 const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift; 137 C.*ptr &= (T)~Mask; 138 C.*ptr |= (T)((Value << shift) & Mask); 139 return true; 140 } 141 142 typedef bool(*ParseFx)(amd_kernel_code_t &, 143 MCAsmParser &MCParser, 144 raw_ostream &Err); 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 makeArrayRef(Table); 153 } 154 155 bool llvm::parseAmdKernelCodeField(StringRef ID, 156 MCAsmParser &MCParser, 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, MCParser, Err) : false; 166 } 167