1 //===- AMDGPUMetadataVerifier.cpp - MsgPack Types ---------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
10 /// Implements a verifier for AMDGPU HSA metadata.
12 //===----------------------------------------------------------------------===//
14 #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringSwitch.h"
18 #include "llvm/BinaryFormat/MsgPackDocument.h"
27 bool MetadataVerifier::verifyScalar(
28 msgpack::DocNode
&Node
, msgpack::Type SKind
,
29 function_ref
<bool(msgpack::DocNode
&)> verifyValue
) {
32 if (Node
.getKind() != SKind
) {
35 // If we are not strict, we interpret string values as "implicitly typed"
36 // and attempt to coerce them to the expected type here.
37 if (Node
.getKind() != msgpack::Type::String
)
39 StringRef StringValue
= Node
.getString();
40 Node
.fromString(StringValue
);
41 if (Node
.getKind() != SKind
)
45 return verifyValue(Node
);
49 bool MetadataVerifier::verifyInteger(msgpack::DocNode
&Node
) {
50 if (!verifyScalar(Node
, msgpack::Type::UInt
))
51 if (!verifyScalar(Node
, msgpack::Type::Int
))
56 bool MetadataVerifier::verifyArray(
57 msgpack::DocNode
&Node
, function_ref
<bool(msgpack::DocNode
&)> verifyNode
,
58 std::optional
<size_t> Size
) {
61 auto &Array
= Node
.getArray();
62 if (Size
&& Array
.size() != *Size
)
64 return llvm::all_of(Array
, verifyNode
);
67 bool MetadataVerifier::verifyEntry(
68 msgpack::MapDocNode
&MapNode
, StringRef Key
, bool Required
,
69 function_ref
<bool(msgpack::DocNode
&)> verifyNode
) {
70 auto Entry
= MapNode
.find(Key
);
71 if (Entry
== MapNode
.end())
73 return verifyNode(Entry
->second
);
76 bool MetadataVerifier::verifyScalarEntry(
77 msgpack::MapDocNode
&MapNode
, StringRef Key
, bool Required
,
79 function_ref
<bool(msgpack::DocNode
&)> verifyValue
) {
80 return verifyEntry(MapNode
, Key
, Required
, [=](msgpack::DocNode
&Node
) {
81 return verifyScalar(Node
, SKind
, verifyValue
);
85 bool MetadataVerifier::verifyIntegerEntry(msgpack::MapDocNode
&MapNode
,
86 StringRef Key
, bool Required
) {
87 return verifyEntry(MapNode
, Key
, Required
, [this](msgpack::DocNode
&Node
) {
88 return verifyInteger(Node
);
92 bool MetadataVerifier::verifyKernelArgs(msgpack::DocNode
&Node
) {
95 auto &ArgsMap
= Node
.getMap();
97 if (!verifyScalarEntry(ArgsMap
, ".name", false,
98 msgpack::Type::String
))
100 if (!verifyScalarEntry(ArgsMap
, ".type_name", false,
101 msgpack::Type::String
))
103 if (!verifyIntegerEntry(ArgsMap
, ".size", true))
105 if (!verifyIntegerEntry(ArgsMap
, ".offset", true))
107 if (!verifyScalarEntry(ArgsMap
, ".value_kind", true, msgpack::Type::String
,
108 [](msgpack::DocNode
&SNode
) {
109 return StringSwitch
<bool>(SNode
.getString())
110 .Case("by_value", true)
111 .Case("global_buffer", true)
112 .Case("dynamic_shared_pointer", true)
113 .Case("sampler", true)
117 .Case("hidden_block_count_x", true)
118 .Case("hidden_block_count_y", true)
119 .Case("hidden_block_count_z", true)
120 .Case("hidden_group_size_x", true)
121 .Case("hidden_group_size_y", true)
122 .Case("hidden_group_size_z", true)
123 .Case("hidden_remainder_x", true)
124 .Case("hidden_remainder_y", true)
125 .Case("hidden_remainder_z", true)
126 .Case("hidden_global_offset_x", true)
127 .Case("hidden_global_offset_y", true)
128 .Case("hidden_global_offset_z", true)
129 .Case("hidden_grid_dims", true)
130 .Case("hidden_none", true)
131 .Case("hidden_printf_buffer", true)
132 .Case("hidden_hostcall_buffer", true)
133 .Case("hidden_heap_v1", true)
134 .Case("hidden_default_queue", true)
135 .Case("hidden_completion_action", true)
136 .Case("hidden_multigrid_sync_arg", true)
137 .Case("hidden_dynamic_lds_size", true)
138 .Case("hidden_private_base", true)
139 .Case("hidden_shared_base", true)
140 .Case("hidden_queue_ptr", true)
144 if (!verifyIntegerEntry(ArgsMap
, ".pointee_align", false))
146 if (!verifyScalarEntry(ArgsMap
, ".address_space", false,
147 msgpack::Type::String
,
148 [](msgpack::DocNode
&SNode
) {
149 return StringSwitch
<bool>(SNode
.getString())
150 .Case("private", true)
151 .Case("global", true)
152 .Case("constant", true)
154 .Case("generic", true)
155 .Case("region", true)
159 if (!verifyScalarEntry(ArgsMap
, ".access", false,
160 msgpack::Type::String
,
161 [](msgpack::DocNode
&SNode
) {
162 return StringSwitch
<bool>(SNode
.getString())
163 .Case("read_only", true)
164 .Case("write_only", true)
165 .Case("read_write", true)
169 if (!verifyScalarEntry(ArgsMap
, ".actual_access", false,
170 msgpack::Type::String
,
171 [](msgpack::DocNode
&SNode
) {
172 return StringSwitch
<bool>(SNode
.getString())
173 .Case("read_only", true)
174 .Case("write_only", true)
175 .Case("read_write", true)
179 if (!verifyScalarEntry(ArgsMap
, ".is_const", false,
180 msgpack::Type::Boolean
))
182 if (!verifyScalarEntry(ArgsMap
, ".is_restrict", false,
183 msgpack::Type::Boolean
))
185 if (!verifyScalarEntry(ArgsMap
, ".is_volatile", false,
186 msgpack::Type::Boolean
))
188 if (!verifyScalarEntry(ArgsMap
, ".is_pipe", false,
189 msgpack::Type::Boolean
))
195 bool MetadataVerifier::verifyKernel(msgpack::DocNode
&Node
) {
198 auto &KernelMap
= Node
.getMap();
200 if (!verifyScalarEntry(KernelMap
, ".name", true,
201 msgpack::Type::String
))
203 if (!verifyScalarEntry(KernelMap
, ".symbol", true,
204 msgpack::Type::String
))
206 if (!verifyScalarEntry(KernelMap
, ".language", false,
207 msgpack::Type::String
,
208 [](msgpack::DocNode
&SNode
) {
209 return StringSwitch
<bool>(SNode
.getString())
210 .Case("OpenCL C", true)
211 .Case("OpenCL C++", true)
214 .Case("OpenMP", true)
215 .Case("Assembler", true)
220 KernelMap
, ".language_version", false, [this](msgpack::DocNode
&Node
) {
223 [this](msgpack::DocNode
&Node
) { return verifyInteger(Node
); }, 2);
226 if (!verifyEntry(KernelMap
, ".args", false, [this](msgpack::DocNode
&Node
) {
227 return verifyArray(Node
, [this](msgpack::DocNode
&Node
) {
228 return verifyKernelArgs(Node
);
232 if (!verifyEntry(KernelMap
, ".reqd_workgroup_size", false,
233 [this](msgpack::DocNode
&Node
) {
234 return verifyArray(Node
,
235 [this](msgpack::DocNode
&Node
) {
236 return verifyInteger(Node
);
241 if (!verifyEntry(KernelMap
, ".workgroup_size_hint", false,
242 [this](msgpack::DocNode
&Node
) {
243 return verifyArray(Node
,
244 [this](msgpack::DocNode
&Node
) {
245 return verifyInteger(Node
);
250 if (!verifyScalarEntry(KernelMap
, ".vec_type_hint", false,
251 msgpack::Type::String
))
253 if (!verifyScalarEntry(KernelMap
, ".device_enqueue_symbol", false,
254 msgpack::Type::String
))
256 if (!verifyIntegerEntry(KernelMap
, ".kernarg_segment_size", true))
258 if (!verifyIntegerEntry(KernelMap
, ".group_segment_fixed_size", true))
260 if (!verifyIntegerEntry(KernelMap
, ".private_segment_fixed_size", true))
262 if (!verifyScalarEntry(KernelMap
, ".uses_dynamic_stack", false,
263 msgpack::Type::Boolean
))
265 if (!verifyIntegerEntry(KernelMap
, ".workgroup_processor_mode", false))
267 if (!verifyIntegerEntry(KernelMap
, ".kernarg_segment_align", true))
269 if (!verifyIntegerEntry(KernelMap
, ".wavefront_size", true))
271 if (!verifyIntegerEntry(KernelMap
, ".sgpr_count", true))
273 if (!verifyIntegerEntry(KernelMap
, ".vgpr_count", true))
275 if (!verifyIntegerEntry(KernelMap
, ".max_flat_workgroup_size", true))
277 if (!verifyIntegerEntry(KernelMap
, ".sgpr_spill_count", false))
279 if (!verifyIntegerEntry(KernelMap
, ".vgpr_spill_count", false))
281 if (!verifyIntegerEntry(KernelMap
, ".uniform_work_group_size", false))
288 bool MetadataVerifier::verify(msgpack::DocNode
&HSAMetadataRoot
) {
289 if (!HSAMetadataRoot
.isMap())
291 auto &RootMap
= HSAMetadataRoot
.getMap();
294 RootMap
, "amdhsa.version", true, [this](msgpack::DocNode
&Node
) {
297 [this](msgpack::DocNode
&Node
) { return verifyInteger(Node
); }, 2);
301 RootMap
, "amdhsa.printf", false, [this](msgpack::DocNode
&Node
) {
302 return verifyArray(Node
, [this](msgpack::DocNode
&Node
) {
303 return verifyScalar(Node
, msgpack::Type::String
);
307 if (!verifyEntry(RootMap
, "amdhsa.kernels", true,
308 [this](msgpack::DocNode
&Node
) {
309 return verifyArray(Node
, [this](msgpack::DocNode
&Node
) {
310 return verifyKernel(Node
);
318 } // end namespace V3
319 } // end namespace HSAMD
320 } // end namespace AMDGPU
321 } // end namespace llvm