blob: 0333b0a14d29dd973526c9b7d083d06ae20e5e4c [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>
Valery Pykhtina852d692016-06-23 14:13:06 +000019#include <llvm/MC/MCParser/MCAsmParser.h>
Valery Pykhtin499a5c62016-03-06 13:27:13 +000020#include <llvm/Support/raw_ostream.h>
21
22using namespace llvm;
23
24static ArrayRef<StringRef> get_amd_kernel_code_t_FldNames() {
25 static StringRef const Table[] = {
26 "", // not found placeholder
Sam Koltona2e5c882016-09-09 10:08:02 +000027#define RECORD(name, altName, print, parse) #name
Valery Pykhtin499a5c62016-03-06 13:27:13 +000028#include "AMDKernelCodeTInfo.h"
29#undef RECORD
30 };
31 return makeArrayRef(Table);
32}
33
Sam Koltona2e5c882016-09-09 10:08:02 +000034static ArrayRef<StringRef> get_amd_kernel_code_t_FldAltNames() {
35 static StringRef const Table[] = {
36 "", // not found placeholder
37#define RECORD(name, altName, print, parse) #altName
38#include "AMDKernelCodeTInfo.h"
39#undef RECORD
40 };
41 return makeArrayRef(Table);
42}
43
44static StringMap<int> createIndexMap(const ArrayRef<StringRef> &names,
45 const ArrayRef<StringRef> &altNames) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000046 StringMap<int> map;
Sam Koltona2e5c882016-09-09 10:08:02 +000047 assert(names.size() == altNames.size());
48 for (unsigned i = 0; i < names.size(); ++i) {
49 map.insert(std::make_pair(names[i], i));
50 map.insert(std::make_pair(altNames[i], i));
51 }
Valery Pykhtin50cd3c42016-03-06 15:13:54 +000052 return map;
Valery Pykhtin499a5c62016-03-06 13:27:13 +000053}
54
55static int get_amd_kernel_code_t_FieldIndex(StringRef name) {
Sam Koltona2e5c882016-09-09 10:08:02 +000056 static const auto map = createIndexMap(get_amd_kernel_code_t_FldNames(),
57 get_amd_kernel_code_t_FldAltNames());
Valery Pykhtin499a5c62016-03-06 13:27:13 +000058 return map.lookup(name) - 1; // returns -1 if not found
59}
60
61static StringRef get_amd_kernel_code_t_FieldName(int index) {
62 return get_amd_kernel_code_t_FldNames()[index + 1];
63}
64
65
66// Field printing
67
Benjamin Kramer4fb78512016-04-07 10:10:09 +000068static raw_ostream &printName(raw_ostream &OS, StringRef Name) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000069 return OS << Name << " = ";
70}
71
72template <typename T, T amd_kernel_code_t::*ptr>
Benjamin Kramer4fb78512016-04-07 10:10:09 +000073static void printField(StringRef Name, const amd_kernel_code_t &C,
74 raw_ostream &OS) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000075 printName(OS, Name) << (int)(C.*ptr);
76}
77
Benjamin Kramer4fb78512016-04-07 10:10:09 +000078template <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) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +000081 const auto Mask = (static_cast<T>(1) << width) - 1;
82 printName(OS, Name) << (int)((c.*ptr >> shift) & Mask);
83}
84
85typedef void(*PrintFx)(StringRef,
Valery Pykhtin02e20862016-06-15 13:55:09 +000086 const amd_kernel_code_t &,
87 raw_ostream &);
Valery Pykhtin499a5c62016-03-06 13:27:13 +000088
89static ArrayRef<PrintFx> getPrinterTable() {
90 static const PrintFx Table[] = {
Sam Koltona2e5c882016-09-09 10:08:02 +000091#define RECORD(name, altName, print, parse) print
Valery Pykhtin499a5c62016-03-06 13:27:13 +000092#include "AMDKernelCodeTInfo.h"
93#undef RECORD
94 };
95 return makeArrayRef(Table);
96}
97
Valery Pykhtin02e20862016-06-15 13:55:09 +000098void llvm::printAmdKernelCodeField(const amd_kernel_code_t &C,
Valery Pykhtin499a5c62016-03-06 13:27:13 +000099 int FldIndex,
Valery Pykhtin02e20862016-06-15 13:55:09 +0000100 raw_ostream &OS) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000101 auto Printer = getPrinterTable()[FldIndex];
102 if (Printer)
103 Printer(get_amd_kernel_code_t_FieldName(FldIndex), C, OS);
104}
105
Valery Pykhtin02e20862016-06-15 13:55:09 +0000106void llvm::dumpAmdKernelCode(const amd_kernel_code_t *C,
107 raw_ostream &OS,
108 const char *tab) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000109 const int Size = getPrinterTable().size();
110 for (int i = 0; i < Size; ++i) {
111 OS << tab;
112 printAmdKernelCodeField(*C, i, OS);
113 OS << '\n';
114 }
115}
116
117
118// Field parsing
119
Valery Pykhtina852d692016-06-23 14:13:06 +0000120static bool expectAbsExpression(MCAsmParser &MCParser, int64_t &Value, raw_ostream& Err) {
121
122 if (MCParser.getLexer().isNot(AsmToken::Equal)) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000123 Err << "expected '='";
124 return false;
125 }
Valery Pykhtina852d692016-06-23 14:13:06 +0000126 MCParser.getLexer().Lex();
127
128 if (MCParser.parseAbsoluteExpression(Value)) {
129 Err << "integer absolute expression expected";
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000130 return false;
131 }
132 return true;
133}
134
135template <typename T, T amd_kernel_code_t::*ptr>
Valery Pykhtina852d692016-06-23 14:13:06 +0000136static bool parseField(amd_kernel_code_t &C, MCAsmParser &MCParser,
Benjamin Kramer4fb78512016-04-07 10:10:09 +0000137 raw_ostream &Err) {
Valery Pykhtina852d692016-06-23 14:13:06 +0000138 int64_t Value = 0;
139 if (!expectAbsExpression(MCParser, Value, Err))
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000140 return false;
Valery Pykhtina852d692016-06-23 14:13:06 +0000141 C.*ptr = (T)Value;
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000142 return true;
143}
144
145template <typename T, T amd_kernel_code_t::*ptr, int shift, int width = 1>
Valery Pykhtina852d692016-06-23 14:13:06 +0000146static bool parseBitField(amd_kernel_code_t &C, MCAsmParser &MCParser,
Benjamin Kramer4fb78512016-04-07 10:10:09 +0000147 raw_ostream &Err) {
Valery Pykhtina852d692016-06-23 14:13:06 +0000148 int64_t Value = 0;
149 if (!expectAbsExpression(MCParser, Value, Err))
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000150 return false;
151 const uint64_t Mask = ((UINT64_C(1) << width) - 1) << shift;
152 C.*ptr &= (T)~Mask;
Valery Pykhtina852d692016-06-23 14:13:06 +0000153 C.*ptr |= (T)((Value << shift) & Mask);
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000154 return true;
155}
156
Valery Pykhtin02e20862016-06-15 13:55:09 +0000157typedef bool(*ParseFx)(amd_kernel_code_t &,
Valery Pykhtina852d692016-06-23 14:13:06 +0000158 MCAsmParser &MCParser,
Valery Pykhtin02e20862016-06-15 13:55:09 +0000159 raw_ostream &Err);
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000160
161static ArrayRef<ParseFx> getParserTable() {
162 static const ParseFx Table[] = {
Sam Koltona2e5c882016-09-09 10:08:02 +0000163#define RECORD(name, altName, print, parse) parse
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000164#include "AMDKernelCodeTInfo.h"
165#undef RECORD
166 };
167 return makeArrayRef(Table);
168}
169
170bool llvm::parseAmdKernelCodeField(StringRef ID,
Valery Pykhtina852d692016-06-23 14:13:06 +0000171 MCAsmParser &MCParser,
Valery Pykhtin02e20862016-06-15 13:55:09 +0000172 amd_kernel_code_t &C,
173 raw_ostream &Err) {
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000174 const int Idx = get_amd_kernel_code_t_FieldIndex(ID);
175 if (Idx < 0) {
176 Err << "unexpected amd_kernel_code_t field name " << ID;
177 return false;
178 }
179 auto Parser = getParserTable()[Idx];
Valery Pykhtina852d692016-06-23 14:13:06 +0000180 return Parser ? Parser(C, MCParser, Err) : false;
Valery Pykhtin499a5c62016-03-06 13:27:13 +0000181}