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
23using namespace llvm;
24
25static 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
35static 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
45static 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
56static 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
62static 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
68static raw_ostream &printName(raw_ostream &OS, StringRef Name) {
69 return OS << Name << " = ";
70}
71
72template <typename T, T amd_kernel_code_t::*ptr>
73static void printField(StringRef Name, const amd_kernel_code_t &C,
74 raw_ostream &OS) {
75 printName(OS, Name) << (int)(C.*ptr);
76}
77
78template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
79static 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
85using PrintFx = void(*)(StringRef, const amd_kernel_code_t &, raw_ostream &);
86
87static 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
96void 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
104void 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
117static 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
132template <typename T, T amd_kernel_code_t::*ptr>
133static 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
142template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
143static 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
154using ParseFx = bool(*)(amd_kernel_code_t &, MCAsmParser &MCParser,
155 raw_ostream &Err);
156
157static 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
166bool 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

source code of llvm/lib/Target/AMDGPU/Utils/AMDKernelCodeTUtils.cpp