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 ArrayRef(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 ArrayRef(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(KV: std::pair(names[i], i)); |
51 | map.insert(KV: std::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(names: get_amd_kernel_code_t_FldNames(), |
58 | altNames: get_amd_kernel_code_t_FldAltNames()); |
59 | return map.lookup(Key: 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 ArrayRef(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(index: 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: *C, FldIndex: 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(K: AsmToken::Equal)) { |
120 | Err << "expected '='" ; |
121 | return false; |
122 | } |
123 | MCParser.getLexer().Lex(); |
124 | |
125 | if (MCParser.parseAbsoluteExpression(Res&: 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 ArrayRef(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(name: 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 | |