blob: e228092b867ed3c853983c3483abbe6a4b4416ca [file] [log] [blame]
Valery Pykhtin499a5c62016-03-06 13:27:13 +00001//===--------------------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/Support/raw_ostream.h>
20
21using namespace llvm;
22
23static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() {
24 static StringRef const Table[] = {
25 "", // not found placeholder
26#define RECORD(name, print, parse) #name
27#include "AMDKernelCodeTInfo.h"
28#undef RECORD
29 };
30 return makeArrayRef(Table);
31}
32
Valery Pykhtin02e20862016-06-15 13:55:09 +000033static StringMap<int> createIndexMap(const ArrayRef<StringRef> &a) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000034 StringMap<int> map;
35 for (auto Name : a)
36 map.insert(std::make_pair(Name, map.size()));
Valery Pykhtin50cd3c42016-03-06 15:13:54 +000037 return map;
Valery Pykhtin499a5c62016-03-06 13:27:13 +000038}
39
40static int get_amd_kernel_code_t_FieldIndex(StringRef name) {
41 static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames());
42 return map.lookup(name) - 1; // returns -1 if not found
43}
44
45static StringRef get_amd_kernel_code_t_FieldName(int index) {
46 return get_amd_kernel_code_t_FldNames()[index + 1];
47}
48
49
50// Field printing
51
Benjamin Kramer4fb78512016-04-07 10:10:09 +000052static raw_ostream &printName(raw_ostream &OS, StringRef Name) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000053 return OS << Name << " = ";
54}
55
56template <typename T, T amd_kernel_code_t::*ptr>
Benjamin Kramer4fb78512016-04-07 10:10:09 +000057static void printField(StringRef Name, const amd_kernel_code_t &C,
58 raw_ostream &OS) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000059 printName(OS, Name) << (int)(C.*ptr);
60}
61
Benjamin Kramer4fb78512016-04-07 10:10:09 +000062template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
63static void printBitField(StringRef Name, const amd_kernel_code_t &c,
64 raw_ostream &OS) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000065 const auto Mask = (static_cast<T>(1) << width) - 1;
66 printName(OS, Name) << (int)((c.*ptr >> shift) & Mask);
67}
68
69typedef void(*PrintFx)(StringRef,
Valery Pykhtin02e20862016-06-15 13:55:09 +000070 const amd_kernel_code_t &,
71 raw_ostream &);
Valery Pykhtin499a5c62016-03-06 13:27:13 +000072
73static ArrayRef<PrintFx> getPrinterTable() {
74 static const PrintFx Table[] = {
75#define RECORD(name, print, parse) print
76#include "AMDKernelCodeTInfo.h"
77#undef RECORD
78 };
79 return makeArrayRef(Table);
80}
81
Valery Pykhtin02e20862016-06-15 13:55:09 +000082void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C,
Valery Pykhtin499a5c62016-03-06 13:27:13 +000083 int FldIndex,
Valery Pykhtin02e20862016-06-15 13:55:09 +000084 raw_ostream &OS) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000085 auto Printer = getPrinterTable()[FldIndex];
86 if (Printer)
87 Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS);
88}
89
Valery Pykhtin02e20862016-06-15 13:55:09 +000090void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C,
91 raw_ostream &OS,
92 const char *tab) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000093 const int Size = getPrinterTable().size();
94 for (int i = 0; i < Size; ++i) {
95 OS << tab;
96 printAmdKernelCodeField(*C, i, OS);
97 OS << '\n';
98 }
99}
100
101
102// Field parsing
103
Valery Pykhtin02e20862016-06-15 13:55:09 +0000104static bool expectEqualInt(MCAsmLexer &Lexer, raw_ostream &Err) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000105 if (Lexer.isNot(AsmToken::Equal)) {
106 Err << "expected '='";
107 return false;
108 }
109 Lexer.Lex();
110 if (Lexer.isNot(AsmToken::Integer)) {
111 Err << "integer literal expected";
112 return false;
113 }
114 return true;
115}
116
117template <typename T, T amd_kernel_code_t::*ptr>
Benjamin Kramer4fb78512016-04-07 10:10:09 +0000118static bool parseField(amd_kernel_code_t &C, MCAsmLexer &Lexer,
119 raw_ostream &Err) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000120 if (!expectEqualInt(Lexer, Err))
121 return false;
122 C.*ptr = (T)Lexer.getTok().getIntVal();
123 return true;
124}
125
126template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
Benjamin Kramer4fb78512016-04-07 10:10:09 +0000127static bool parseBitField(amd_kernel_code_t &C, MCAsmLexer &Lexer,
128 raw_ostream &Err) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000129 if (!expectEqualInt(Lexer, Err))
130 return false;
131 const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift;
132 C.*ptr &= (T)~Mask;
133 C.*ptr |= (T)((Lexer.getTok().getIntVal() << shift) & Mask);
134 return true;
135}
136
Valery Pykhtin02e20862016-06-15 13:55:09 +0000137typedef bool(*ParseFx)(amd_kernel_code_t &,
138 MCAsmLexer &Lexer,
139 raw_ostream &Err);
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000140
141static ArrayRef<ParseFx> getParserTable() {
142 static const ParseFx Table[] = {
143#define RECORD(name, print, parse) parse
144#include "AMDKernelCodeTInfo.h"
145#undef RECORD
146 };
147 return makeArrayRef(Table);
148}
149
150bool llvm::parseAmdKernelCodeField(StringRef ID,
Valery Pykhtin02e20862016-06-15 13:55:09 +0000151 MCAsmLexer &Lexer,
152 amd_kernel_code_t &C,
153 raw_ostream &Err) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000154 const int Idx = get_amd_kernel_code_t_FieldIndex(ID);
155 if (Idx < 0) {
156 Err << "unexpected amd_kernel_code_t field name " << ID;
157 return false;
158 }
159 auto Parser = getParserTable()[Idx];
160 return Parser ? Parser(C, Lexer, Err) : false;
161}