10b57cec5SDimitry Andric //===- AMDKernelCodeTUtils.cpp --------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file - utility functions to parse/print amd_kernel_code_t structure
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "AMDKernelCodeTUtils.h"
14e8d8bef9SDimitry Andric #include "AMDKernelCodeT.h"
150b57cec5SDimitry Andric #include "SIDefines.h"
160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
170b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
210b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
220b57cec5SDimitry Andric 
230b57cec5SDimitry Andric using namespace llvm;
240b57cec5SDimitry Andric 
get_amd_kernel_code_t_FldNames()250b57cec5SDimitry Andric static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() {
260b57cec5SDimitry Andric   static StringRef const Table[] = {
270b57cec5SDimitry Andric     "", // not found placeholder
280b57cec5SDimitry Andric #define RECORD(name, altName, print, parse) #name
290b57cec5SDimitry Andric #include "AMDKernelCodeTInfo.h"
300b57cec5SDimitry Andric #undef RECORD
310b57cec5SDimitry Andric   };
32bdd1243dSDimitry Andric   return ArrayRef(Table);
330b57cec5SDimitry Andric }
340b57cec5SDimitry Andric 
get_amd_kernel_code_t_FldAltNames()350b57cec5SDimitry Andric static ArrayRef<StringRef> get_amd_kernel_code_t_FldAltNames() {
360b57cec5SDimitry Andric   static StringRef const Table[] = {
370b57cec5SDimitry Andric     "", // not found placeholder
380b57cec5SDimitry Andric #define RECORD(name, altName, print, parse) #altName
390b57cec5SDimitry Andric #include "AMDKernelCodeTInfo.h"
400b57cec5SDimitry Andric #undef RECORD
410b57cec5SDimitry Andric   };
42bdd1243dSDimitry Andric   return ArrayRef(Table);
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
createIndexMap(const ArrayRef<StringRef> & names,const ArrayRef<StringRef> & altNames)450b57cec5SDimitry Andric static StringMap<int> createIndexMap(const ArrayRef<StringRef> &names,
460b57cec5SDimitry Andric                                      const ArrayRef<StringRef> &altNames) {
470b57cec5SDimitry Andric   StringMap<int> map;
480b57cec5SDimitry Andric   assert(names.size() == altNames.size());
490b57cec5SDimitry Andric   for (unsigned i = 0; i < names.size(); ++i) {
50bdd1243dSDimitry Andric     map.insert(std::pair(names[i], i));
51bdd1243dSDimitry Andric     map.insert(std::pair(altNames[i], i));
520b57cec5SDimitry Andric   }
530b57cec5SDimitry Andric   return map;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric 
get_amd_kernel_code_t_FieldIndex(StringRef name)560b57cec5SDimitry Andric static int get_amd_kernel_code_t_FieldIndex(StringRef name) {
570b57cec5SDimitry Andric   static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(),
580b57cec5SDimitry Andric                                          get_amd_kernel_code_t_FldAltNames());
590b57cec5SDimitry Andric   return map.lookup(name) - 1; // returns -1 if not found
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric 
get_amd_kernel_code_t_FieldName(int index)620b57cec5SDimitry Andric static StringRef get_amd_kernel_code_t_FieldName(int index) {
630b57cec5SDimitry Andric   return get_amd_kernel_code_t_FldNames()[index + 1];
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // Field printing
670b57cec5SDimitry Andric 
printName(raw_ostream & OS,StringRef Name)680b57cec5SDimitry Andric static raw_ostream &printName(raw_ostream &OS, StringRef Name) {
690b57cec5SDimitry Andric   return OS << Name << " = ";
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric 
720b57cec5SDimitry Andric template <typename T, T amd_kernel_code_t::*ptr>
printField(StringRef Name,const amd_kernel_code_t & C,raw_ostream & OS)730b57cec5SDimitry Andric static void printField(StringRef Name, const amd_kernel_code_t &C,
740b57cec5SDimitry Andric                        raw_ostream &OS) {
750b57cec5SDimitry Andric   printName(OS, Name) << (int)(C.*ptr);
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
printBitField(StringRef Name,const amd_kernel_code_t & c,raw_ostream & OS)790b57cec5SDimitry Andric static void printBitField(StringRef Name, const amd_kernel_code_t &c,
800b57cec5SDimitry Andric                           raw_ostream &OS) {
810b57cec5SDimitry Andric   const auto Mask = (static_cast<T>(1) << width) - 1;
820b57cec5SDimitry Andric   printName(OS, Name) << (int)((c.*ptr >> shift) & Mask);
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &);
860b57cec5SDimitry Andric 
getPrinterTable()870b57cec5SDimitry Andric static ArrayRef<PrintFx> getPrinterTable() {
880b57cec5SDimitry Andric   static const PrintFx Table[] = {
890b57cec5SDimitry Andric #define RECORD(name, altName, print, parse) print
900b57cec5SDimitry Andric #include "AMDKernelCodeTInfo.h"
910b57cec5SDimitry Andric #undef RECORD
920b57cec5SDimitry Andric   };
93bdd1243dSDimitry Andric   return ArrayRef(Table);
940b57cec5SDimitry Andric }
950b57cec5SDimitry Andric 
printAmdKernelCodeField(const amd_kernel_code_t & C,int FldIndex,raw_ostream & OS)960b57cec5SDimitry Andric void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C,
970b57cec5SDimitry Andric                                    int FldIndex,
980b57cec5SDimitry Andric                                    raw_ostream &OS) {
990b57cec5SDimitry Andric   auto Printer = getPrinterTable()[FldIndex];
1000b57cec5SDimitry Andric   if (Printer)
1010b57cec5SDimitry Andric     Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS);
1020b57cec5SDimitry Andric }
1030b57cec5SDimitry Andric 
dumpAmdKernelCode(const amd_kernel_code_t * C,raw_ostream & OS,const char * tab)1040b57cec5SDimitry Andric void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C,
1050b57cec5SDimitry Andric                              raw_ostream &OS,
1060b57cec5SDimitry Andric                              const char *tab) {
1070b57cec5SDimitry Andric   const int Size = getPrinterTable().size();
1080b57cec5SDimitry Andric   for (int i = 0; i < Size; ++i) {
1090b57cec5SDimitry Andric     OS << tab;
1100b57cec5SDimitry Andric     printAmdKernelCodeField(*C, i, OS);
1110b57cec5SDimitry Andric     OS << '\n';
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric // Field parsing
1160b57cec5SDimitry Andric 
expectAbsExpression(MCAsmParser & MCParser,int64_t & Value,raw_ostream & Err)1170b57cec5SDimitry Andric static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) {
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric   if (MCParser.getLexer().isNot(AsmToken::Equal)) {
1200b57cec5SDimitry Andric     Err << "expected '='";
1210b57cec5SDimitry Andric     return false;
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric   MCParser.getLexer().Lex();
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   if (MCParser.parseAbsoluteExpression(Value)) {
1260b57cec5SDimitry Andric     Err << "integer absolute expression expected";
1270b57cec5SDimitry Andric     return false;
1280b57cec5SDimitry Andric   }
1290b57cec5SDimitry Andric   return true;
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric template <typename T, T amd_kernel_code_t::*ptr>
parseField(amd_kernel_code_t & C,MCAsmParser & MCParser,raw_ostream & Err)1330b57cec5SDimitry Andric static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser,
1340b57cec5SDimitry Andric                        raw_ostream &Err) {
1350b57cec5SDimitry Andric   int64_t Value = 0;
1360b57cec5SDimitry Andric   if (!expectAbsExpression(MCParser, Value, Err))
1370b57cec5SDimitry Andric     return false;
1380b57cec5SDimitry Andric   C.*ptr = (T)Value;
1390b57cec5SDimitry Andric   return true;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
parseBitField(amd_kernel_code_t & C,MCAsmParser & MCParser,raw_ostream & Err)1430b57cec5SDimitry Andric static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser,
1440b57cec5SDimitry Andric                           raw_ostream &Err) {
1450b57cec5SDimitry Andric   int64_t Value = 0;
1460b57cec5SDimitry Andric   if (!expectAbsExpression(MCParser, Value, Err))
1470b57cec5SDimitry Andric     return false;
1480b57cec5SDimitry Andric   const uint64_t Mask = ((UINT64_C(1)  << width) - 1) << shift;
1490b57cec5SDimitry Andric   C.*ptr &= (T)~Mask;
1500b57cec5SDimitry Andric   C.*ptr |= (T)((Value << shift) & Mask);
1510b57cec5SDimitry Andric   return true;
1520b57cec5SDimitry Andric }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser,
1550b57cec5SDimitry Andric                         raw_ostream &Err);
1560b57cec5SDimitry Andric 
getParserTable()1570b57cec5SDimitry Andric static ArrayRef<ParseFx> getParserTable() {
1580b57cec5SDimitry Andric   static const ParseFx Table[] = {
1590b57cec5SDimitry Andric #define RECORD(name, altName, print, parse) parse
1600b57cec5SDimitry Andric #include "AMDKernelCodeTInfo.h"
1610b57cec5SDimitry Andric #undef RECORD
1620b57cec5SDimitry Andric   };
163bdd1243dSDimitry Andric   return ArrayRef(Table);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric 
parseAmdKernelCodeField(StringRef ID,MCAsmParser & MCParser,amd_kernel_code_t & C,raw_ostream & Err)1660b57cec5SDimitry Andric bool llvm::parseAmdKernelCodeField(StringRef ID,
1670b57cec5SDimitry Andric                                    MCAsmParser &MCParser,
1680b57cec5SDimitry Andric                                    amd_kernel_code_t &C,
1690b57cec5SDimitry Andric                                    raw_ostream &Err) {
1700b57cec5SDimitry Andric   const int Idx = get_amd_kernel_code_t_FieldIndex(ID);
1710b57cec5SDimitry Andric   if (Idx < 0) {
1720b57cec5SDimitry Andric     Err << "unexpected amd_kernel_code_t field name " << ID;
1730b57cec5SDimitry Andric     return false;
1740b57cec5SDimitry Andric   }
1750b57cec5SDimitry Andric   auto Parser = getParserTable()[Idx];
1760b57cec5SDimitry Andric   return Parser ? Parser(C, MCParser, Err) : false;
1770b57cec5SDimitry Andric }
178