xref: /llvm-project/llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp (revision 9803de0e8e3abbbc94a4265d5847db435897a384)
1f5b36e56SScott Linder //===- AMDGPUMetadataVerifier.cpp - MsgPack Types ---------------*- C++ -*-===//
2f5b36e56SScott Linder //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f5b36e56SScott Linder //
7f5b36e56SScott Linder //===----------------------------------------------------------------------===//
8f5b36e56SScott Linder //
9f5b36e56SScott Linder /// \file
10f5b36e56SScott Linder /// Implements a verifier for AMDGPU HSA metadata.
11f5b36e56SScott Linder //
12f5b36e56SScott Linder //===----------------------------------------------------------------------===//
13f5b36e56SScott Linder 
14f5b36e56SScott Linder #include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"
15b58174d6Sserge-sans-paille 
16b58174d6Sserge-sans-paille #include "llvm/ADT/STLExtras.h"
17af450eabSReid Kleckner #include "llvm/ADT/StringSwitch.h"
18b58174d6Sserge-sans-paille #include "llvm/BinaryFormat/MsgPackDocument.h"
19b58174d6Sserge-sans-paille 
20b58174d6Sserge-sans-paille #include <utility>
21f5b36e56SScott Linder 
22f5b36e56SScott Linder namespace llvm {
23f5b36e56SScott Linder namespace AMDGPU {
24f5b36e56SScott Linder namespace HSAMD {
25f5b36e56SScott Linder namespace V3 {
26f5b36e56SScott Linder 
verifyScalar(msgpack::DocNode & Node,msgpack::Type SKind,function_ref<bool (msgpack::DocNode &)> verifyValue)27f5b36e56SScott Linder bool MetadataVerifier::verifyScalar(
28ed0b9af9STim Renouf     msgpack::DocNode &Node, msgpack::Type SKind,
29ed0b9af9STim Renouf     function_ref<bool(msgpack::DocNode &)> verifyValue) {
30ed0b9af9STim Renouf   if (!Node.isScalar())
31f5b36e56SScott Linder     return false;
32ed0b9af9STim Renouf   if (Node.getKind() != SKind) {
33f5b36e56SScott Linder     if (Strict)
34f5b36e56SScott Linder       return false;
35f5b36e56SScott Linder     // If we are not strict, we interpret string values as "implicitly typed"
36f5b36e56SScott Linder     // and attempt to coerce them to the expected type here.
37ed0b9af9STim Renouf     if (Node.getKind() != msgpack::Type::String)
38f5b36e56SScott Linder       return false;
39ed0b9af9STim Renouf     StringRef StringValue = Node.getString();
40ed0b9af9STim Renouf     Node.fromString(StringValue);
41ed0b9af9STim Renouf     if (Node.getKind() != SKind)
42f5b36e56SScott Linder       return false;
43f5b36e56SScott Linder   }
44f5b36e56SScott Linder   if (verifyValue)
45ed0b9af9STim Renouf     return verifyValue(Node);
46f5b36e56SScott Linder   return true;
47f5b36e56SScott Linder }
48f5b36e56SScott Linder 
verifyInteger(msgpack::DocNode & Node)49ed0b9af9STim Renouf bool MetadataVerifier::verifyInteger(msgpack::DocNode &Node) {
50ed0b9af9STim Renouf   if (!verifyScalar(Node, msgpack::Type::UInt))
51ed0b9af9STim Renouf     if (!verifyScalar(Node, msgpack::Type::Int))
52f5b36e56SScott Linder       return false;
53f5b36e56SScott Linder   return true;
54f5b36e56SScott Linder }
55f5b36e56SScott Linder 
verifyArray(msgpack::DocNode & Node,function_ref<bool (msgpack::DocNode &)> verifyNode,std::optional<size_t> Size)56f5b36e56SScott Linder bool MetadataVerifier::verifyArray(
57ed0b9af9STim Renouf     msgpack::DocNode &Node, function_ref<bool(msgpack::DocNode &)> verifyNode,
58bcf24026SKazu Hirata     std::optional<size_t> Size) {
59ed0b9af9STim Renouf   if (!Node.isArray())
60f5b36e56SScott Linder     return false;
61ed0b9af9STim Renouf   auto &Array = Node.getArray();
62f5b36e56SScott Linder   if (Size && Array.size() != *Size)
63f5b36e56SScott Linder     return false;
64c2bb9637SKazu Hirata   return llvm::all_of(Array, verifyNode);
65f5b36e56SScott Linder }
66f5b36e56SScott Linder 
verifyEntry(msgpack::MapDocNode & MapNode,StringRef Key,bool Required,function_ref<bool (msgpack::DocNode &)> verifyNode)67f5b36e56SScott Linder bool MetadataVerifier::verifyEntry(
68ed0b9af9STim Renouf     msgpack::MapDocNode &MapNode, StringRef Key, bool Required,
69ed0b9af9STim Renouf     function_ref<bool(msgpack::DocNode &)> verifyNode) {
70f5b36e56SScott Linder   auto Entry = MapNode.find(Key);
71f5b36e56SScott Linder   if (Entry == MapNode.end())
72f5b36e56SScott Linder     return !Required;
73ed0b9af9STim Renouf   return verifyNode(Entry->second);
74f5b36e56SScott Linder }
75f5b36e56SScott Linder 
verifyScalarEntry(msgpack::MapDocNode & MapNode,StringRef Key,bool Required,msgpack::Type SKind,function_ref<bool (msgpack::DocNode &)> verifyValue)76f5b36e56SScott Linder bool MetadataVerifier::verifyScalarEntry(
77ed0b9af9STim Renouf     msgpack::MapDocNode &MapNode, StringRef Key, bool Required,
78ed0b9af9STim Renouf     msgpack::Type SKind,
79ed0b9af9STim Renouf     function_ref<bool(msgpack::DocNode &)> verifyValue) {
80ed0b9af9STim Renouf   return verifyEntry(MapNode, Key, Required, [=](msgpack::DocNode &Node) {
81f5b36e56SScott Linder     return verifyScalar(Node, SKind, verifyValue);
82f5b36e56SScott Linder   });
83f5b36e56SScott Linder }
84f5b36e56SScott Linder 
verifyIntegerEntry(msgpack::MapDocNode & MapNode,StringRef Key,bool Required)85ed0b9af9STim Renouf bool MetadataVerifier::verifyIntegerEntry(msgpack::MapDocNode &MapNode,
86f5b36e56SScott Linder                                           StringRef Key, bool Required) {
87ed0b9af9STim Renouf   return verifyEntry(MapNode, Key, Required, [this](msgpack::DocNode &Node) {
88f5b36e56SScott Linder     return verifyInteger(Node);
89f5b36e56SScott Linder   });
90f5b36e56SScott Linder }
91f5b36e56SScott Linder 
verifyKernelArgs(msgpack::DocNode & Node)92ed0b9af9STim Renouf bool MetadataVerifier::verifyKernelArgs(msgpack::DocNode &Node) {
93ed0b9af9STim Renouf   if (!Node.isMap())
94f5b36e56SScott Linder     return false;
95ed0b9af9STim Renouf   auto &ArgsMap = Node.getMap();
96f5b36e56SScott Linder 
97f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".name", false,
98ed0b9af9STim Renouf                          msgpack::Type::String))
99f5b36e56SScott Linder     return false;
100f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".type_name", false,
101ed0b9af9STim Renouf                          msgpack::Type::String))
102f5b36e56SScott Linder     return false;
103f5b36e56SScott Linder   if (!verifyIntegerEntry(ArgsMap, ".size", true))
104f5b36e56SScott Linder     return false;
105f5b36e56SScott Linder   if (!verifyIntegerEntry(ArgsMap, ".offset", true))
106f5b36e56SScott Linder     return false;
107ca62b1dbSChangpeng Fang   if (!verifyScalarEntry(ArgsMap, ".value_kind", true, msgpack::Type::String,
108ed0b9af9STim Renouf                          [](msgpack::DocNode &SNode) {
109f5b36e56SScott Linder                            return StringSwitch<bool>(SNode.getString())
110f5b36e56SScott Linder                                .Case("by_value", true)
111f5b36e56SScott Linder                                .Case("global_buffer", true)
112f5b36e56SScott Linder                                .Case("dynamic_shared_pointer", true)
113f5b36e56SScott Linder                                .Case("sampler", true)
114f5b36e56SScott Linder                                .Case("image", true)
115f5b36e56SScott Linder                                .Case("pipe", true)
116f5b36e56SScott Linder                                .Case("queue", true)
1171194b9cdSChangpeng Fang                                .Case("hidden_block_count_x", true)
1181194b9cdSChangpeng Fang                                .Case("hidden_block_count_y", true)
1191194b9cdSChangpeng Fang                                .Case("hidden_block_count_z", true)
1201194b9cdSChangpeng Fang                                .Case("hidden_group_size_x", true)
1211194b9cdSChangpeng Fang                                .Case("hidden_group_size_y", true)
1221194b9cdSChangpeng Fang                                .Case("hidden_group_size_z", true)
1231194b9cdSChangpeng Fang                                .Case("hidden_remainder_x", true)
1241194b9cdSChangpeng Fang                                .Case("hidden_remainder_y", true)
1251194b9cdSChangpeng Fang                                .Case("hidden_remainder_z", true)
126f5b36e56SScott Linder                                .Case("hidden_global_offset_x", true)
127f5b36e56SScott Linder                                .Case("hidden_global_offset_y", true)
128f5b36e56SScott Linder                                .Case("hidden_global_offset_z", true)
1291194b9cdSChangpeng Fang                                .Case("hidden_grid_dims", true)
130f5b36e56SScott Linder                                .Case("hidden_none", true)
131f5b36e56SScott Linder                                .Case("hidden_printf_buffer", true)
13252c5014dSSameer Sahasrabuddhe                                .Case("hidden_hostcall_buffer", true)
133ca62b1dbSChangpeng Fang                                .Case("hidden_heap_v1", true)
134f5b36e56SScott Linder                                .Case("hidden_default_queue", true)
135f5b36e56SScott Linder                                .Case("hidden_completion_action", true)
136a6241352SYaxun Liu                                .Case("hidden_multigrid_sync_arg", true)
137*9803de0eSChaitanya                                .Case("hidden_dynamic_lds_size", true)
1381194b9cdSChangpeng Fang                                .Case("hidden_private_base", true)
1391194b9cdSChangpeng Fang                                .Case("hidden_shared_base", true)
1401194b9cdSChangpeng Fang                                .Case("hidden_queue_ptr", true)
141f5b36e56SScott Linder                                .Default(false);
142f5b36e56SScott Linder                          }))
143f5b36e56SScott Linder     return false;
144f5b36e56SScott Linder   if (!verifyIntegerEntry(ArgsMap, ".pointee_align", false))
145f5b36e56SScott Linder     return false;
146f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".address_space", false,
147ed0b9af9STim Renouf                          msgpack::Type::String,
148ed0b9af9STim Renouf                          [](msgpack::DocNode &SNode) {
149f5b36e56SScott Linder                            return StringSwitch<bool>(SNode.getString())
150f5b36e56SScott Linder                                .Case("private", true)
151f5b36e56SScott Linder                                .Case("global", true)
152f5b36e56SScott Linder                                .Case("constant", true)
153f5b36e56SScott Linder                                .Case("local", true)
154f5b36e56SScott Linder                                .Case("generic", true)
155f5b36e56SScott Linder                                .Case("region", true)
156f5b36e56SScott Linder                                .Default(false);
157f5b36e56SScott Linder                          }))
158f5b36e56SScott Linder     return false;
159f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".access", false,
160ed0b9af9STim Renouf                          msgpack::Type::String,
161ed0b9af9STim Renouf                          [](msgpack::DocNode &SNode) {
162f5b36e56SScott Linder                            return StringSwitch<bool>(SNode.getString())
163f5b36e56SScott Linder                                .Case("read_only", true)
164f5b36e56SScott Linder                                .Case("write_only", true)
165f5b36e56SScott Linder                                .Case("read_write", true)
166f5b36e56SScott Linder                                .Default(false);
167f5b36e56SScott Linder                          }))
168f5b36e56SScott Linder     return false;
169f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".actual_access", false,
170ed0b9af9STim Renouf                          msgpack::Type::String,
171ed0b9af9STim Renouf                          [](msgpack::DocNode &SNode) {
172f5b36e56SScott Linder                            return StringSwitch<bool>(SNode.getString())
173f5b36e56SScott Linder                                .Case("read_only", true)
174f5b36e56SScott Linder                                .Case("write_only", true)
175f5b36e56SScott Linder                                .Case("read_write", true)
176f5b36e56SScott Linder                                .Default(false);
177f5b36e56SScott Linder                          }))
178f5b36e56SScott Linder     return false;
179f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".is_const", false,
180ed0b9af9STim Renouf                          msgpack::Type::Boolean))
181f5b36e56SScott Linder     return false;
182f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".is_restrict", false,
183ed0b9af9STim Renouf                          msgpack::Type::Boolean))
184f5b36e56SScott Linder     return false;
185f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".is_volatile", false,
186ed0b9af9STim Renouf                          msgpack::Type::Boolean))
187f5b36e56SScott Linder     return false;
188f5b36e56SScott Linder   if (!verifyScalarEntry(ArgsMap, ".is_pipe", false,
189ed0b9af9STim Renouf                          msgpack::Type::Boolean))
190f5b36e56SScott Linder     return false;
191f5b36e56SScott Linder 
192f5b36e56SScott Linder   return true;
193f5b36e56SScott Linder }
194f5b36e56SScott Linder 
verifyKernel(msgpack::DocNode & Node)195ed0b9af9STim Renouf bool MetadataVerifier::verifyKernel(msgpack::DocNode &Node) {
196ed0b9af9STim Renouf   if (!Node.isMap())
197f5b36e56SScott Linder     return false;
198ed0b9af9STim Renouf   auto &KernelMap = Node.getMap();
199f5b36e56SScott Linder 
200f5b36e56SScott Linder   if (!verifyScalarEntry(KernelMap, ".name", true,
201ed0b9af9STim Renouf                          msgpack::Type::String))
202f5b36e56SScott Linder     return false;
203f5b36e56SScott Linder   if (!verifyScalarEntry(KernelMap, ".symbol", true,
204ed0b9af9STim Renouf                          msgpack::Type::String))
205f5b36e56SScott Linder     return false;
206f5b36e56SScott Linder   if (!verifyScalarEntry(KernelMap, ".language", false,
207ed0b9af9STim Renouf                          msgpack::Type::String,
208ed0b9af9STim Renouf                          [](msgpack::DocNode &SNode) {
209f5b36e56SScott Linder                            return StringSwitch<bool>(SNode.getString())
210f5b36e56SScott Linder                                .Case("OpenCL C", true)
211f5b36e56SScott Linder                                .Case("OpenCL C++", true)
212f5b36e56SScott Linder                                .Case("HCC", true)
213f5b36e56SScott Linder                                .Case("HIP", true)
214f5b36e56SScott Linder                                .Case("OpenMP", true)
215f5b36e56SScott Linder                                .Case("Assembler", true)
216f5b36e56SScott Linder                                .Default(false);
217f5b36e56SScott Linder                          }))
218f5b36e56SScott Linder     return false;
219f5b36e56SScott Linder   if (!verifyEntry(
220ed0b9af9STim Renouf           KernelMap, ".language_version", false, [this](msgpack::DocNode &Node) {
221f5b36e56SScott Linder             return verifyArray(
222f5b36e56SScott Linder                 Node,
223ed0b9af9STim Renouf                 [this](msgpack::DocNode &Node) { return verifyInteger(Node); }, 2);
224f5b36e56SScott Linder           }))
225f5b36e56SScott Linder     return false;
226ed0b9af9STim Renouf   if (!verifyEntry(KernelMap, ".args", false, [this](msgpack::DocNode &Node) {
227ed0b9af9STim Renouf         return verifyArray(Node, [this](msgpack::DocNode &Node) {
228f5b36e56SScott Linder           return verifyKernelArgs(Node);
229f5b36e56SScott Linder         });
230f5b36e56SScott Linder       }))
231f5b36e56SScott Linder     return false;
232f5b36e56SScott Linder   if (!verifyEntry(KernelMap, ".reqd_workgroup_size", false,
233ed0b9af9STim Renouf                    [this](msgpack::DocNode &Node) {
234f5b36e56SScott Linder                      return verifyArray(Node,
235ed0b9af9STim Renouf                                         [this](msgpack::DocNode &Node) {
236f5b36e56SScott Linder                                           return verifyInteger(Node);
237f5b36e56SScott Linder                                         },
238f5b36e56SScott Linder                                         3);
239f5b36e56SScott Linder                    }))
240f5b36e56SScott Linder     return false;
241f5b36e56SScott Linder   if (!verifyEntry(KernelMap, ".workgroup_size_hint", false,
242ed0b9af9STim Renouf                    [this](msgpack::DocNode &Node) {
243f5b36e56SScott Linder                      return verifyArray(Node,
244ed0b9af9STim Renouf                                         [this](msgpack::DocNode &Node) {
245f5b36e56SScott Linder                                           return verifyInteger(Node);
246f5b36e56SScott Linder                                         },
247f5b36e56SScott Linder                                         3);
248f5b36e56SScott Linder                    }))
249f5b36e56SScott Linder     return false;
250f5b36e56SScott Linder   if (!verifyScalarEntry(KernelMap, ".vec_type_hint", false,
251ed0b9af9STim Renouf                          msgpack::Type::String))
252f5b36e56SScott Linder     return false;
253f5b36e56SScott Linder   if (!verifyScalarEntry(KernelMap, ".device_enqueue_symbol", false,
254ed0b9af9STim Renouf                          msgpack::Type::String))
255f5b36e56SScott Linder     return false;
256f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".kernarg_segment_size", true))
257f5b36e56SScott Linder     return false;
258f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".group_segment_fixed_size", true))
259f5b36e56SScott Linder     return false;
260f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".private_segment_fixed_size", true))
261f5b36e56SScott Linder     return false;
262d96361d7SAbinav Puthan Purayil   if (!verifyScalarEntry(KernelMap, ".uses_dynamic_stack", false,
263d96361d7SAbinav Puthan Purayil                          msgpack::Type::Boolean))
264d96361d7SAbinav Puthan Purayil     return false;
2659fa46200SPierre van Houtryve   if (!verifyIntegerEntry(KernelMap, ".workgroup_processor_mode", false))
2669fa46200SPierre van Houtryve     return false;
267f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".kernarg_segment_align", true))
268f5b36e56SScott Linder     return false;
269f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".wavefront_size", true))
270f5b36e56SScott Linder     return false;
271f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".sgpr_count", true))
272f5b36e56SScott Linder     return false;
273f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".vgpr_count", true))
274f5b36e56SScott Linder     return false;
275f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".max_flat_workgroup_size", true))
276f5b36e56SScott Linder     return false;
277f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".sgpr_spill_count", false))
278f5b36e56SScott Linder     return false;
279f5b36e56SScott Linder   if (!verifyIntegerEntry(KernelMap, ".vgpr_spill_count", false))
280f5b36e56SScott Linder     return false;
28125d72330SVang Thao   if (!verifyIntegerEntry(KernelMap, ".uniform_work_group_size", false))
28225d72330SVang Thao     return false;
28325d72330SVang Thao 
284f5b36e56SScott Linder 
285f5b36e56SScott Linder   return true;
286f5b36e56SScott Linder }
287f5b36e56SScott Linder 
verify(msgpack::DocNode & HSAMetadataRoot)288ed0b9af9STim Renouf bool MetadataVerifier::verify(msgpack::DocNode &HSAMetadataRoot) {
289ed0b9af9STim Renouf   if (!HSAMetadataRoot.isMap())
290f5b36e56SScott Linder     return false;
291ed0b9af9STim Renouf   auto &RootMap = HSAMetadataRoot.getMap();
292f5b36e56SScott Linder 
293f5b36e56SScott Linder   if (!verifyEntry(
294ed0b9af9STim Renouf           RootMap, "amdhsa.version", true, [this](msgpack::DocNode &Node) {
295f5b36e56SScott Linder             return verifyArray(
296f5b36e56SScott Linder                 Node,
297ed0b9af9STim Renouf                 [this](msgpack::DocNode &Node) { return verifyInteger(Node); }, 2);
298f5b36e56SScott Linder           }))
299f5b36e56SScott Linder     return false;
300f5b36e56SScott Linder   if (!verifyEntry(
301ed0b9af9STim Renouf           RootMap, "amdhsa.printf", false, [this](msgpack::DocNode &Node) {
302ed0b9af9STim Renouf             return verifyArray(Node, [this](msgpack::DocNode &Node) {
303ed0b9af9STim Renouf               return verifyScalar(Node, msgpack::Type::String);
304f5b36e56SScott Linder             });
305f5b36e56SScott Linder           }))
306f5b36e56SScott Linder     return false;
307f5b36e56SScott Linder   if (!verifyEntry(RootMap, "amdhsa.kernels", true,
308ed0b9af9STim Renouf                    [this](msgpack::DocNode &Node) {
309ed0b9af9STim Renouf                      return verifyArray(Node, [this](msgpack::DocNode &Node) {
310f5b36e56SScott Linder                        return verifyKernel(Node);
311f5b36e56SScott Linder                      });
312f5b36e56SScott Linder                    }))
313f5b36e56SScott Linder     return false;
314f5b36e56SScott Linder 
315f5b36e56SScott Linder   return true;
316f5b36e56SScott Linder }
317f5b36e56SScott Linder 
318f5b36e56SScott Linder } // end namespace V3
319f5b36e56SScott Linder } // end namespace HSAMD
320f5b36e56SScott Linder } // end namespace AMDGPU
321f5b36e56SScott Linder } // end namespace llvm
322