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 22using namespace llvm; 23 24static 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 34static 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 41static 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 46static 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 53static raw_ostream &printName(raw_ostream &OS, StringRef Name) { 54 return OS << Name << " = "; 55} 56 57template <typename T, T amd_kernel_code_t::*ptr> 58static void printField(StringRef Name, const amd_kernel_code_t &C, 59 raw_ostream &OS) { 60 printName(OS, Name) << (int)(C.*ptr); 61} 62 63template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 64static 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 70typedef void(*PrintFx)(StringRef, 71 const amd_kernel_code_t &, 72 raw_ostream &); 73 74static 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 83void 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 91void 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 105static 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 120template <typename T, T amd_kernel_code_t::*ptr> 121static 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 130template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> 131static 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 142typedef bool(*ParseFx)(amd_kernel_code_t &, 143 MCAsmParser &MCParser, 144 raw_ostream &Err); 145 146static 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 155bool 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