//===- AMDKernelCodeTUtils.cpp --------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // /// \file - utility functions to parse/print amd_kernel_code_t structure // //===----------------------------------------------------------------------===// #include "AMDKernelCodeTUtils.h" #include "AMDKernelCodeT.h" #include "SIDefines.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; static ArrayRef get_amd_kernel_code_t_FldNames() { static StringRef const Table[] = { "", // not found placeholder #define RECORD(name, altName, print, parse) #name #include "AMDKernelCodeTInfo.h" #undef RECORD }; return makeArrayRef(Table); } static ArrayRef get_amd_kernel_code_t_FldAltNames() { static StringRef const Table[] = { "", // not found placeholder #define RECORD(name, altName, print, parse) #altName #include "AMDKernelCodeTInfo.h" #undef RECORD }; return makeArrayRef(Table); } static StringMap createIndexMap(const ArrayRef &names, const ArrayRef &altNames) { StringMap map; assert(names.size() == altNames.size()); for (unsigned i = 0; i < names.size(); ++i) { map.insert(std::make_pair(names[i], i)); map.insert(std::make_pair(altNames[i], i)); } return map; } static int get_amd_kernel_code_t_FieldIndex(StringRef name) { static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(), get_amd_kernel_code_t_FldAltNames()); return map.lookup(name) - 1; // returns -1 if not found } static StringRef get_amd_kernel_code_t_FieldName(int index) { return get_amd_kernel_code_t_FldNames()[index + 1]; } // Field printing static raw_ostream &printName(raw_ostream &OS, StringRef Name) { return OS << Name << " = "; } template static void printField(StringRef Name, const amd_kernel_code_t &C, raw_ostream &OS) { printName(OS, Name) << (int)(C.*ptr); } template static void printBitField(StringRef Name, const amd_kernel_code_t &c, raw_ostream &OS) { const auto Mask = (static_cast(1) << width) - 1; printName(OS, Name) << (int)((c.*ptr >> shift) & Mask); } using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &); static ArrayRef getPrinterTable() { static const PrintFx Table[] = { #define RECORD(name, altName, print, parse) print #include "AMDKernelCodeTInfo.h" #undef RECORD }; return makeArrayRef(Table); } void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C, int FldIndex, raw_ostream &OS) { auto Printer = getPrinterTable()[FldIndex]; if (Printer) Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS); } void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C, raw_ostream &OS, const char *tab) { const int Size = getPrinterTable().size(); for (int i = 0; i < Size; ++i) { OS << tab; printAmdKernelCodeField(*C, i, OS); OS << '\n'; } } // Field parsing static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) { if (MCParser.getLexer().isNot(AsmToken::Equal)) { Err << "expected '='"; return false; } MCParser.getLexer().Lex(); if (MCParser.parseAbsoluteExpression(Value)) { Err << "integer absolute expression expected"; return false; } return true; } template static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser, raw_ostream &Err) { int64_t Value = 0; if (!expectAbsExpression(MCParser, Value, Err)) return false; C.*ptr = (T)Value; return true; } template static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser, raw_ostream &Err) { int64_t Value = 0; if (!expectAbsExpression(MCParser, Value, Err)) return false; const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift; C.*ptr &= (T)~Mask; C.*ptr |= (T)((Value << shift) & Mask); return true; } using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser, raw_ostream &Err); static ArrayRef getParserTable() { static const ParseFx Table[] = { #define RECORD(name, altName, print, parse) parse #include "AMDKernelCodeTInfo.h" #undef RECORD }; return makeArrayRef(Table); } bool llvm::parseAmdKernelCodeField(StringRef ID, MCAsmParser &MCParser, amd_kernel_code_t &C, raw_ostream &Err) { const int Idx = get_amd_kernel_code_t_FieldIndex(ID); if (Idx < 0) { Err << "unexpected amd_kernel_code_t field name " << ID; return false; } auto Parser = getParserTable()[Idx]; return Parser ? Parser(C, MCParser, Err) : false; }