xref: /llvm-project/llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp (revision 6c8c74969a152a62ffce0f83e3a45ea54b4655b4)
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 "AMDKernelCodeT.h"
17 #include "AMDKernelCodeTUtils.h"
18 #include "SIDefines.h"
19 #include <llvm/MC/MCParser/MCAsmLexer.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 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 std::move(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 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 void printField(StringRef Name,
59                 const amd_kernel_code_t &C,
60                 raw_ostream &OS) {
61   printName(OS, Name) << (int)(C.*ptr);
62 }
63 
64 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width=1>
65 void printBitField(StringRef Name,
66                    const amd_kernel_code_t &c,
67                    raw_ostream &OS) {
68   const auto Mask = (static_cast<T>(1) << width) - 1;
69   printName(OS, Name) << (int)((c.*ptr >> shift) & Mask);
70 }
71 
72 typedef void(*PrintFx)(StringRef,
73                        const amd_kernel_code_t&,
74                        raw_ostream&);
75 
76 static ArrayRef<PrintFx> getPrinterTable() {
77   static const PrintFx table[] = {
78 #define RECORD(name, print, parse) print
79 #include "AMDKernelCodeTInfo.h"
80 #undef RECORD
81   };
82   return table;
83 }
84 
85 void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C,
86                                    int FldIndex,
87                                    raw_ostream &OS) {
88   auto Printer = getPrinterTable()[FldIndex];
89   if (Printer)
90     Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS);
91 }
92 
93 void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C,
94                              raw_ostream &OS,
95                              const char *tab) {
96   const int Size = getPrinterTable().size();
97   for (int i = 0; i < Size; ++i) {
98     OS << tab;
99     printAmdKernelCodeField(*C, i, OS);
100     OS << '\n';
101   }
102 }
103 
104 
105 // Field parsing
106 
107 static bool expectEqualInt(MCAsmLexer &Lexer, raw_ostream &Err) {
108   if (Lexer.isNot(AsmToken::Equal)) {
109     Err << "expected '='";
110     return false;
111   }
112   Lexer.Lex();
113   if (Lexer.isNot(AsmToken::Integer)) {
114     Err << "integer literal expected";
115     return false;
116   }
117   return true;
118 }
119 
120 template <typename T, T amd_kernel_code_t::*ptr>
121 bool parseField(amd_kernel_code_t &C,
122                 MCAsmLexer &Lexer,
123                 raw_ostream &Err) {
124   if (!expectEqualInt(Lexer, Err))
125     return false;
126   C.*ptr = (T)Lexer.getTok().getIntVal();
127   return true;
128 }
129 
130 template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
131 bool parseBitField(amd_kernel_code_t &C,
132                    MCAsmLexer &Lexer,
133                    raw_ostream &Err) {
134   if (!expectEqualInt(Lexer, Err))
135     return false;
136   const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift;
137   C.*ptr &= (T)~Mask;
138   C.*ptr |= (T)((Lexer.getTok().getIntVal() << shift) & Mask);
139   return true;
140 }
141 
142 typedef bool(*ParseFx)(amd_kernel_code_t&,
143                        MCAsmLexer&,
144                        raw_ostream&);
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 table;
153 }
154 
155 bool llvm::parseAmdKernelCodeField(StringRef ID,
156                                    MCAsmLexer &Lexer,
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, Lexer, Err) : false;
166 }
167