Path: blob/main/contrib/llvm-project/llvm/lib/BinaryFormat/AMDGPUMetadataVerifier.cpp
35233 views
//===- AMDGPUMetadataVerifier.cpp - MsgPack Types ---------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8/// \file9/// Implements a verifier for AMDGPU HSA metadata.10//11//===----------------------------------------------------------------------===//1213#include "llvm/BinaryFormat/AMDGPUMetadataVerifier.h"1415#include "llvm/ADT/STLExtras.h"16#include "llvm/ADT/StringSwitch.h"17#include "llvm/BinaryFormat/MsgPackDocument.h"1819#include <utility>2021namespace llvm {22namespace AMDGPU {23namespace HSAMD {24namespace V3 {2526bool MetadataVerifier::verifyScalar(27msgpack::DocNode &Node, msgpack::Type SKind,28function_ref<bool(msgpack::DocNode &)> verifyValue) {29if (!Node.isScalar())30return false;31if (Node.getKind() != SKind) {32if (Strict)33return false;34// If we are not strict, we interpret string values as "implicitly typed"35// and attempt to coerce them to the expected type here.36if (Node.getKind() != msgpack::Type::String)37return false;38StringRef StringValue = Node.getString();39Node.fromString(StringValue);40if (Node.getKind() != SKind)41return false;42}43if (verifyValue)44return verifyValue(Node);45return true;46}4748bool MetadataVerifier::verifyInteger(msgpack::DocNode &Node) {49if (!verifyScalar(Node, msgpack::Type::UInt))50if (!verifyScalar(Node, msgpack::Type::Int))51return false;52return true;53}5455bool MetadataVerifier::verifyArray(56msgpack::DocNode &Node, function_ref<bool(msgpack::DocNode &)> verifyNode,57std::optional<size_t> Size) {58if (!Node.isArray())59return false;60auto &Array = Node.getArray();61if (Size && Array.size() != *Size)62return false;63return llvm::all_of(Array, verifyNode);64}6566bool MetadataVerifier::verifyEntry(67msgpack::MapDocNode &MapNode, StringRef Key, bool Required,68function_ref<bool(msgpack::DocNode &)> verifyNode) {69auto Entry = MapNode.find(Key);70if (Entry == MapNode.end())71return !Required;72return verifyNode(Entry->second);73}7475bool MetadataVerifier::verifyScalarEntry(76msgpack::MapDocNode &MapNode, StringRef Key, bool Required,77msgpack::Type SKind,78function_ref<bool(msgpack::DocNode &)> verifyValue) {79return verifyEntry(MapNode, Key, Required, [=](msgpack::DocNode &Node) {80return verifyScalar(Node, SKind, verifyValue);81});82}8384bool MetadataVerifier::verifyIntegerEntry(msgpack::MapDocNode &MapNode,85StringRef Key, bool Required) {86return verifyEntry(MapNode, Key, Required, [this](msgpack::DocNode &Node) {87return verifyInteger(Node);88});89}9091bool MetadataVerifier::verifyKernelArgs(msgpack::DocNode &Node) {92if (!Node.isMap())93return false;94auto &ArgsMap = Node.getMap();9596if (!verifyScalarEntry(ArgsMap, ".name", false,97msgpack::Type::String))98return false;99if (!verifyScalarEntry(ArgsMap, ".type_name", false,100msgpack::Type::String))101return false;102if (!verifyIntegerEntry(ArgsMap, ".size", true))103return false;104if (!verifyIntegerEntry(ArgsMap, ".offset", true))105return false;106if (!verifyScalarEntry(ArgsMap, ".value_kind", true, msgpack::Type::String,107[](msgpack::DocNode &SNode) {108return StringSwitch<bool>(SNode.getString())109.Case("by_value", true)110.Case("global_buffer", true)111.Case("dynamic_shared_pointer", true)112.Case("sampler", true)113.Case("image", true)114.Case("pipe", true)115.Case("queue", true)116.Case("hidden_block_count_x", true)117.Case("hidden_block_count_y", true)118.Case("hidden_block_count_z", true)119.Case("hidden_group_size_x", true)120.Case("hidden_group_size_y", true)121.Case("hidden_group_size_z", true)122.Case("hidden_remainder_x", true)123.Case("hidden_remainder_y", true)124.Case("hidden_remainder_z", true)125.Case("hidden_global_offset_x", true)126.Case("hidden_global_offset_y", true)127.Case("hidden_global_offset_z", true)128.Case("hidden_grid_dims", true)129.Case("hidden_none", true)130.Case("hidden_printf_buffer", true)131.Case("hidden_hostcall_buffer", true)132.Case("hidden_heap_v1", true)133.Case("hidden_default_queue", true)134.Case("hidden_completion_action", true)135.Case("hidden_multigrid_sync_arg", true)136.Case("hidden_dynamic_lds_size", true)137.Case("hidden_private_base", true)138.Case("hidden_shared_base", true)139.Case("hidden_queue_ptr", true)140.Default(false);141}))142return false;143if (!verifyIntegerEntry(ArgsMap, ".pointee_align", false))144return false;145if (!verifyScalarEntry(ArgsMap, ".address_space", false,146msgpack::Type::String,147[](msgpack::DocNode &SNode) {148return StringSwitch<bool>(SNode.getString())149.Case("private", true)150.Case("global", true)151.Case("constant", true)152.Case("local", true)153.Case("generic", true)154.Case("region", true)155.Default(false);156}))157return false;158if (!verifyScalarEntry(ArgsMap, ".access", false,159msgpack::Type::String,160[](msgpack::DocNode &SNode) {161return StringSwitch<bool>(SNode.getString())162.Case("read_only", true)163.Case("write_only", true)164.Case("read_write", true)165.Default(false);166}))167return false;168if (!verifyScalarEntry(ArgsMap, ".actual_access", false,169msgpack::Type::String,170[](msgpack::DocNode &SNode) {171return StringSwitch<bool>(SNode.getString())172.Case("read_only", true)173.Case("write_only", true)174.Case("read_write", true)175.Default(false);176}))177return false;178if (!verifyScalarEntry(ArgsMap, ".is_const", false,179msgpack::Type::Boolean))180return false;181if (!verifyScalarEntry(ArgsMap, ".is_restrict", false,182msgpack::Type::Boolean))183return false;184if (!verifyScalarEntry(ArgsMap, ".is_volatile", false,185msgpack::Type::Boolean))186return false;187if (!verifyScalarEntry(ArgsMap, ".is_pipe", false,188msgpack::Type::Boolean))189return false;190191return true;192}193194bool MetadataVerifier::verifyKernel(msgpack::DocNode &Node) {195if (!Node.isMap())196return false;197auto &KernelMap = Node.getMap();198199if (!verifyScalarEntry(KernelMap, ".name", true,200msgpack::Type::String))201return false;202if (!verifyScalarEntry(KernelMap, ".symbol", true,203msgpack::Type::String))204return false;205if (!verifyScalarEntry(KernelMap, ".language", false,206msgpack::Type::String,207[](msgpack::DocNode &SNode) {208return StringSwitch<bool>(SNode.getString())209.Case("OpenCL C", true)210.Case("OpenCL C++", true)211.Case("HCC", true)212.Case("HIP", true)213.Case("OpenMP", true)214.Case("Assembler", true)215.Default(false);216}))217return false;218if (!verifyEntry(219KernelMap, ".language_version", false, [this](msgpack::DocNode &Node) {220return verifyArray(221Node,222[this](msgpack::DocNode &Node) { return verifyInteger(Node); }, 2);223}))224return false;225if (!verifyEntry(KernelMap, ".args", false, [this](msgpack::DocNode &Node) {226return verifyArray(Node, [this](msgpack::DocNode &Node) {227return verifyKernelArgs(Node);228});229}))230return false;231if (!verifyEntry(KernelMap, ".reqd_workgroup_size", false,232[this](msgpack::DocNode &Node) {233return verifyArray(Node,234[this](msgpack::DocNode &Node) {235return verifyInteger(Node);236},2373);238}))239return false;240if (!verifyEntry(KernelMap, ".workgroup_size_hint", false,241[this](msgpack::DocNode &Node) {242return verifyArray(Node,243[this](msgpack::DocNode &Node) {244return verifyInteger(Node);245},2463);247}))248return false;249if (!verifyScalarEntry(KernelMap, ".vec_type_hint", false,250msgpack::Type::String))251return false;252if (!verifyScalarEntry(KernelMap, ".device_enqueue_symbol", false,253msgpack::Type::String))254return false;255if (!verifyIntegerEntry(KernelMap, ".kernarg_segment_size", true))256return false;257if (!verifyIntegerEntry(KernelMap, ".group_segment_fixed_size", true))258return false;259if (!verifyIntegerEntry(KernelMap, ".private_segment_fixed_size", true))260return false;261if (!verifyScalarEntry(KernelMap, ".uses_dynamic_stack", false,262msgpack::Type::Boolean))263return false;264if (!verifyIntegerEntry(KernelMap, ".workgroup_processor_mode", false))265return false;266if (!verifyIntegerEntry(KernelMap, ".kernarg_segment_align", true))267return false;268if (!verifyIntegerEntry(KernelMap, ".wavefront_size", true))269return false;270if (!verifyIntegerEntry(KernelMap, ".sgpr_count", true))271return false;272if (!verifyIntegerEntry(KernelMap, ".vgpr_count", true))273return false;274if (!verifyIntegerEntry(KernelMap, ".max_flat_workgroup_size", true))275return false;276if (!verifyIntegerEntry(KernelMap, ".sgpr_spill_count", false))277return false;278if (!verifyIntegerEntry(KernelMap, ".vgpr_spill_count", false))279return false;280if (!verifyIntegerEntry(KernelMap, ".uniform_work_group_size", false))281return false;282283284return true;285}286287bool MetadataVerifier::verify(msgpack::DocNode &HSAMetadataRoot) {288if (!HSAMetadataRoot.isMap())289return false;290auto &RootMap = HSAMetadataRoot.getMap();291292if (!verifyEntry(293RootMap, "amdhsa.version", true, [this](msgpack::DocNode &Node) {294return verifyArray(295Node,296[this](msgpack::DocNode &Node) { return verifyInteger(Node); }, 2);297}))298return false;299if (!verifyEntry(300RootMap, "amdhsa.printf", false, [this](msgpack::DocNode &Node) {301return verifyArray(Node, [this](msgpack::DocNode &Node) {302return verifyScalar(Node, msgpack::Type::String);303});304}))305return false;306if (!verifyEntry(RootMap, "amdhsa.kernels", true,307[this](msgpack::DocNode &Node) {308return verifyArray(Node, [this](msgpack::DocNode &Node) {309return verifyKernel(Node);310});311}))312return false;313314return true;315}316317} // end namespace V3318} // end namespace HSAMD319} // end namespace AMDGPU320} // end namespace llvm321322323