| //===- 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 "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" |
| #include <cassert> |
| #include <cstdint> |
| #include <utility> |
| |
| using namespace llvm; |
| |
| static ArrayRef<StringRef> 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<StringRef> 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<int> createIndexMap(const ArrayRef<StringRef> &names, |
| const ArrayRef<StringRef> &altNames) { |
| StringMap<int> 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 <typename T, T amd_kernel_code_t::*ptr> |
| static void printField(StringRef Name, const amd_kernel_code_t &C, |
| raw_ostream &OS) { |
| printName(OS, Name) << (int)(C.*ptr); |
| } |
| |
| template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> |
| static void printBitField(StringRef Name, const amd_kernel_code_t &c, |
| raw_ostream &OS) { |
| const auto Mask = (static_cast<T>(1) << width) - 1; |
| printName(OS, Name) << (int)((c.*ptr >> shift) & Mask); |
| } |
| |
| using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &); |
| |
| static ArrayRef<PrintFx> 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 <typename T, T amd_kernel_code_t::*ptr> |
| 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 <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1> |
| 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<ParseFx> 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; |
| } |