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
get_amd_kernel_code_t_FldNames()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
createIndexMap(const ArrayRef<StringRef> & a)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
get_amd_kernel_code_t_FieldIndex(StringRef name)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
get_amd_kernel_code_t_FieldName(int index)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
printName(raw_ostream & OS,StringRef Name)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>
printField(StringRef Name,const amd_kernel_code_t & C,raw_ostream & OS)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>
printBitField(StringRef Name,const amd_kernel_code_t & c,raw_ostream & OS)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
getPrinterTable()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
printAmdKernelCodeField(const amd_kernel_code_t & C,int FldIndex,raw_ostream & OS)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
dumpAmdKernelCode(const amd_kernel_code_t * C,raw_ostream & OS,const char * tab)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
expectAbsExpression(MCAsmParser & MCParser,int64_t & Value,raw_ostream & Err)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>
parseField(amd_kernel_code_t & C,MCAsmParser & MCParser,raw_ostream & Err)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>
parseBitField(amd_kernel_code_t & C,MCAsmParser & MCParser,raw_ostream & Err)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
getParserTable()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
parseAmdKernelCodeField(StringRef ID,MCAsmParser & MCParser,amd_kernel_code_t & C,raw_ostream & Err)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