aboutsummaryrefslogtreecommitdiff
path: root/third_party/SPIRV-Tools/source/opt/inst_buff_addr_check_pass.h
blob: f07f98a0f2a04c7058afb009428205ac8d75df49 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) 2019 The Khronos Group Inc.
// Copyright (c) 2019 Valve Corporation
// Copyright (c) 2019 LunarG Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef LIBSPIRV_OPT_INST_BUFFER_ADDRESS_PASS_H_
#define LIBSPIRV_OPT_INST_BUFFER_ADDRESS_PASS_H_

#include "instrument_pass.h"

namespace spvtools {
namespace opt {

// This class/pass is designed to support the GPU-assisted validation layer of
// the Buffer Device Address (BDA) extension in
// https://github.com/KhronosGroup/Vulkan-ValidationLayers. The internal and
// external design of this class may change as the layer evolves.
class InstBuffAddrCheckPass : public InstrumentPass {
 public:
  // For test harness only
  InstBuffAddrCheckPass() : InstrumentPass(0, 23, false, true) {}
  // For all other interfaces
  InstBuffAddrCheckPass(uint32_t shader_id)
      : InstrumentPass(0, shader_id, false, true) {}

  ~InstBuffAddrCheckPass() override = default;

  // See optimizer.hpp for pass user documentation.
  Status Process() override;

  const char* name() const override { return "inst-buff-addr-check-pass"; }

 private:
  // Return byte length of type |type_id|. Must be int, float, vector, matrix,
  // struct, array or physical pointer. Uses std430 alignment and sizes.
  uint32_t GetTypeLength(uint32_t type_id);

  // Add |type_id| param to |input_func| and add id to |param_vec|.
  void AddParam(uint32_t type_id, std::vector<uint32_t>* param_vec,
                std::unique_ptr<Function>* input_func);

  // Return id for search and test function. Generate it if not already gen'd.
  uint32_t GetSearchAndTestFuncId();

  // Generate code into |builder| to do search of the BDA debug input buffer
  // for the buffer used by |ref_inst| and test that all bytes of reference
  // are within the buffer. Returns id of boolean value which is true if
  // search and test is successful, false otherwise.
  uint32_t GenSearchAndTest(Instruction* ref_inst, InstructionBuilder* builder,
                            uint32_t* ref_uptr_id, uint32_t stage_idx);

  // This function does checking instrumentation on a single
  // instruction which references through a physical storage buffer address.
  // GenBuffAddrCheckCode generates code that checks that all bytes that
  // are referenced fall within a buffer that was queried via
  // the Vulkan API call vkGetBufferDeviceAddressEXT().
  //
  // The function is designed to be passed to
  // InstrumentPass::InstProcessEntryPointCallTree(), which applies the
  // function to each instruction in a module and replaces the instruction
  // with instrumented code if warranted.
  //
  // If |ref_inst_itr| is a physical storage buffer reference, return in
  // |new_blocks| the result of instrumenting it with validation code within
  // its block at |ref_block_itr|.  The validation code first executes a check
  // for the specific condition called for. If the check passes, it executes
  // the remainder of the reference, otherwise writes a record to the debug
  // output buffer stream including |function_idx, instruction_idx, stage_idx|
  // and replaces the reference with the null value of the original type. The
  // block at |ref_block_itr| can just be replaced with the blocks in
  // |new_blocks|, which will contain at least two blocks. The last block will
  // comprise all instructions following |ref_inst_itr|,
  // preceded by a phi instruction if needed.
  //
  // This instrumentation function utilizes GenDebugStreamWrite() to write its
  // error records. The validation-specific part of the error record will
  // have the format:
  //
  //    Validation Error Code (=kInstErrorBuffAddr)
  //    Buffer Address (lowest 32 bits)
  //    Buffer Address (highest 32 bits)
  //
  void GenBuffAddrCheckCode(
      BasicBlock::iterator ref_inst_itr,
      UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
      std::vector<std::unique_ptr<BasicBlock>>* new_blocks);

  // Return true if |ref_inst| is a physical buffer address reference, false
  // otherwise.
  bool IsPhysicalBuffAddrReference(Instruction* ref_inst);

  // Clone original reference |ref_inst| into |builder| and return id of result
  uint32_t CloneOriginalReference(Instruction* ref_inst,
                                  InstructionBuilder* builder);

  // Generate instrumentation code for boolean test result |check_id|,
  // adding new blocks to |new_blocks|. Generate conditional branch to valid
  // or invalid reference blocks. Generate valid reference block which does
  // original reference |ref_inst|. Then generate invalid reference block which
  // writes debug error output utilizing |ref_inst|, |error_id| and
  // |stage_idx|. Generate merge block for valid and invalid reference blocks.
  // Kill original reference.
  void GenCheckCode(uint32_t check_id, Instruction* ref_inst,
                    std::vector<std::unique_ptr<BasicBlock>>* new_blocks);

  // Initialize state for instrumenting physical buffer address checking
  void InitInstBuffAddrCheck();

  // Apply GenBuffAddrCheckCode to every instruction in module.
  Pass::Status ProcessImpl();

  // Id of search and test function, if already gen'd, else zero.
  uint32_t search_test_func_id_;
};

}  // namespace opt
}  // namespace spvtools

#endif  // LIBSPIRV_OPT_INST_BUFFER_ADDRESS_PASS_H_