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