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