Home | History | Annotate | Line # | Download | only in Utils
      1 //===- AMDKernelCodeTUtils.cpp --------------------------------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 /// \file - utility functions to parse/print amd_kernel_code_t structure
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "AMDKernelCodeTUtils.h"
     14 #include "AMDKernelCodeT.h"
     15 #include "SIDefines.h"
     16 #include "llvm/ADT/ArrayRef.h"
     17 #include "llvm/ADT/StringMap.h"
     18 #include "llvm/ADT/StringRef.h"
     19 #include "llvm/MC/MCParser/MCAsmLexer.h"
     20 #include "llvm/MC/MCParser/MCAsmParser.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 
     23 using namespace llvm;
     24 
     25 static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() {
     26   static StringRef const Table[] = {
     27     "", // not found placeholder
     28 #define RECORD(name, altName, print, parse) #name
     29 #include "AMDKernelCodeTInfo.h"
     30 #undef RECORD
     31   };
     32   return makeArrayRef(Table);
     33 }
     34 
     35 static ArrayRef<StringRef> get_amd_kernel_code_t_FldAltNames() {
     36   static StringRef const Table[] = {
     37     "", // not found placeholder
     38 #define RECORD(name, altName, print, parse) #altName
     39 #include "AMDKernelCodeTInfo.h"
     40 #undef RECORD
     41   };
     42   return makeArrayRef(Table);
     43 }
     44 
     45 static StringMap<int> createIndexMap(const ArrayRef<StringRef> &names,
     46                                      const ArrayRef<StringRef> &altNames) {
     47   StringMap<int> map;
     48   assert(names.size() == altNames.size());
     49   for (unsigned i = 0; i < names.size(); ++i) {
     50     map.insert(std::make_pair(names[i], i));
     51     map.insert(std::make_pair(altNames[i], i));
     52   }
     53   return map;
     54 }
     55 
     56 static int get_amd_kernel_code_t_FieldIndex(StringRef name) {
     57   static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(),
     58                                          get_amd_kernel_code_t_FldAltNames());
     59   return map.lookup(name) - 1; // returns -1 if not found
     60 }
     61 
     62 static StringRef get_amd_kernel_code_t_FieldName(int index) {
     63   return get_amd_kernel_code_t_FldNames()[index + 1];
     64 }
     65 
     66 // Field printing
     67 
     68 static raw_ostream &printName(raw_ostream &OS, StringRef Name) {
     69   return OS << Name << " = ";
     70 }
     71 
     72 template <typename T, T amd_kernel_code_t::*ptr>
     73 static void printField(StringRef Name, const amd_kernel_code_t &C,
     74                        raw_ostream &OS) {
     75   printName(OS, Name) << (int)(C.*ptr);
     76 }
     77 
     78 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
     79 static void printBitField(StringRef Name, const amd_kernel_code_t &c,
     80                           raw_ostream &OS) {
     81   const auto Mask = (static_cast<T>(1) << width) - 1;
     82   printName(OS, Name) << (int)((c.*ptr >> shift) & Mask);
     83 }
     84 
     85 using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &);
     86 
     87 static ArrayRef<PrintFx> getPrinterTable() {
     88   static const PrintFx Table[] = {
     89 #define RECORD(name, altName, print, parse) print
     90 #include "AMDKernelCodeTInfo.h"
     91 #undef RECORD
     92   };
     93   return makeArrayRef(Table);
     94 }
     95 
     96 void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C,
     97                                    int FldIndex,
     98                                    raw_ostream &OS) {
     99   auto Printer = getPrinterTable()[FldIndex];
    100   if (Printer)
    101     Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS);
    102 }
    103 
    104 void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C,
    105                              raw_ostream &OS,
    106                              const char *tab) {
    107   const int Size = getPrinterTable().size();
    108   for (int i = 0; i < Size; ++i) {
    109     OS << tab;
    110     printAmdKernelCodeField(*C, i, OS);
    111     OS << '\n';
    112   }
    113 }
    114 
    115 // Field parsing
    116 
    117 static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) {
    118 
    119   if (MCParser.getLexer().isNot(AsmToken::Equal)) {
    120     Err << "expected '='";
    121     return false;
    122   }
    123   MCParser.getLexer().Lex();
    124 
    125   if (MCParser.parseAbsoluteExpression(Value)) {
    126     Err << "integer absolute expression expected";
    127     return false;
    128   }
    129   return true;
    130 }
    131 
    132 template <typename T, T amd_kernel_code_t::*ptr>
    133 static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser,
    134                        raw_ostream &Err) {
    135   int64_t Value = 0;
    136   if (!expectAbsExpression(MCParser, Value, Err))
    137     return false;
    138   C.*ptr = (T)Value;
    139   return true;
    140 }
    141 
    142 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
    143 static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser,
    144                           raw_ostream &Err) {
    145   int64_t Value = 0;
    146   if (!expectAbsExpression(MCParser, Value, Err))
    147     return false;
    148   const uint64_t Mask = ((UINT64_C(1)  << width) - 1) << shift;
    149   C.*ptr &= (T)~Mask;
    150   C.*ptr |= (T)((Value << shift) & Mask);
    151   return true;
    152 }
    153 
    154 using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser,
    155                         raw_ostream &Err);
    156 
    157 static ArrayRef<ParseFx> getParserTable() {
    158   static const ParseFx Table[] = {
    159 #define RECORD(name, altName, print, parse) parse
    160 #include "AMDKernelCodeTInfo.h"
    161 #undef RECORD
    162   };
    163   return makeArrayRef(Table);
    164 }
    165 
    166 bool llvm::parseAmdKernelCodeField(StringRef ID,
    167                                    MCAsmParser &MCParser,
    168                                    amd_kernel_code_t &C,
    169                                    raw_ostream &Err) {
    170   const int Idx = get_amd_kernel_code_t_FieldIndex(ID);
    171   if (Idx < 0) {
    172     Err << "unexpected amd_kernel_code_t field name " << ID;
    173     return false;
    174   }
    175   auto Parser = getParserTable()[Idx];
    176   return Parser ? Parser(C, MCParser, Err) : false;
    177 }
    178