1 // Copyright (c) 2019 The Khronos Group Inc.
2 // Copyright (c) 2019 Valve Corporation
3 // Copyright (c) 2019 LunarG Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16
17 #include "inst_buff_addr_check_pass.h"
18
19 namespace spvtools {
20 namespace opt {
21
CloneOriginalReference(Instruction * ref_inst,InstructionBuilder * builder)22 uint32_t InstBuffAddrCheckPass::CloneOriginalReference(
23 Instruction* ref_inst, InstructionBuilder* builder) {
24 // Clone original ref with new result id (if load)
25 assert(
26 (ref_inst->opcode() == SpvOpLoad || ref_inst->opcode() == SpvOpStore) &&
27 "unexpected ref");
28 std::unique_ptr<Instruction> new_ref_inst(ref_inst->Clone(context()));
29 uint32_t ref_result_id = ref_inst->result_id();
30 uint32_t new_ref_id = 0;
31 if (ref_result_id != 0) {
32 new_ref_id = TakeNextId();
33 new_ref_inst->SetResultId(new_ref_id);
34 }
35 // Register new reference and add to new block
36 Instruction* added_inst = builder->AddInstruction(std::move(new_ref_inst));
37 uid2offset_[added_inst->unique_id()] = uid2offset_[ref_inst->unique_id()];
38 if (new_ref_id != 0)
39 get_decoration_mgr()->CloneDecorations(ref_result_id, new_ref_id);
40 return new_ref_id;
41 }
42
IsPhysicalBuffAddrReference(Instruction * ref_inst)43 bool InstBuffAddrCheckPass::IsPhysicalBuffAddrReference(Instruction* ref_inst) {
44 if (ref_inst->opcode() != SpvOpLoad && ref_inst->opcode() != SpvOpStore)
45 return false;
46 uint32_t ptr_id = ref_inst->GetSingleWordInOperand(0);
47 analysis::DefUseManager* du_mgr = get_def_use_mgr();
48 Instruction* ptr_inst = du_mgr->GetDef(ptr_id);
49 if (ptr_inst->opcode() != SpvOpAccessChain) return false;
50 uint32_t ptr_ty_id = ptr_inst->type_id();
51 Instruction* ptr_ty_inst = du_mgr->GetDef(ptr_ty_id);
52 if (ptr_ty_inst->GetSingleWordInOperand(0) !=
53 SpvStorageClassPhysicalStorageBufferEXT)
54 return false;
55 return true;
56 }
57
58 // TODO(greg-lunarg): Refactor with InstBindlessCheckPass::GenCheckCode() ??
GenCheckCode(uint32_t check_id,uint32_t error_id,uint32_t ref_uptr_id,uint32_t stage_idx,Instruction * ref_inst,std::vector<std::unique_ptr<BasicBlock>> * new_blocks)59 void InstBuffAddrCheckPass::GenCheckCode(
60 uint32_t check_id, uint32_t error_id, uint32_t ref_uptr_id,
61 uint32_t stage_idx, Instruction* ref_inst,
62 std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
63 BasicBlock* back_blk_ptr = &*new_blocks->back();
64 InstructionBuilder builder(
65 context(), back_blk_ptr,
66 IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
67 // Gen conditional branch on check_id. Valid branch generates original
68 // reference. Invalid generates debug output and zero result (if needed).
69 uint32_t merge_blk_id = TakeNextId();
70 uint32_t valid_blk_id = TakeNextId();
71 uint32_t invalid_blk_id = TakeNextId();
72 std::unique_ptr<Instruction> merge_label(NewLabel(merge_blk_id));
73 std::unique_ptr<Instruction> valid_label(NewLabel(valid_blk_id));
74 std::unique_ptr<Instruction> invalid_label(NewLabel(invalid_blk_id));
75 (void)builder.AddConditionalBranch(check_id, valid_blk_id, invalid_blk_id,
76 merge_blk_id, SpvSelectionControlMaskNone);
77 // Gen valid branch
78 std::unique_ptr<BasicBlock> new_blk_ptr(
79 new BasicBlock(std::move(valid_label)));
80 builder.SetInsertPoint(&*new_blk_ptr);
81 uint32_t new_ref_id = CloneOriginalReference(ref_inst, &builder);
82 (void)builder.AddBranch(merge_blk_id);
83 new_blocks->push_back(std::move(new_blk_ptr));
84 // Gen invalid block
85 new_blk_ptr.reset(new BasicBlock(std::move(invalid_label)));
86 builder.SetInsertPoint(&*new_blk_ptr);
87 // Convert uptr from uint64 to 2 uint32
88 Instruction* lo_uptr_inst =
89 builder.AddUnaryOp(GetUintId(), SpvOpUConvert, ref_uptr_id);
90 Instruction* rshift_uptr_inst =
91 builder.AddBinaryOp(GetUint64Id(), SpvOpShiftRightLogical, ref_uptr_id,
92 builder.GetUintConstantId(32));
93 Instruction* hi_uptr_inst = builder.AddUnaryOp(GetUintId(), SpvOpUConvert,
94 rshift_uptr_inst->result_id());
95 GenDebugStreamWrite(
96 uid2offset_[ref_inst->unique_id()], stage_idx,
97 {error_id, lo_uptr_inst->result_id(), hi_uptr_inst->result_id()},
98 &builder);
99 // Gen zero for invalid load. If pointer type, need to convert uint64
100 // zero to pointer; cannot create ConstantNull of pointer type.
101 uint32_t null_id = 0;
102 if (new_ref_id != 0) {
103 uint32_t ref_type_id = ref_inst->type_id();
104 analysis::TypeManager* type_mgr = context()->get_type_mgr();
105 analysis::Type* ref_type = type_mgr->GetType(ref_type_id);
106 if (ref_type->AsPointer() != nullptr) {
107 uint32_t null_u64_id = GetNullId(GetUint64Id());
108 Instruction* null_ptr_inst =
109 builder.AddUnaryOp(ref_type_id, SpvOpConvertUToPtr, null_u64_id);
110 null_id = null_ptr_inst->result_id();
111 } else {
112 null_id = GetNullId(ref_type_id);
113 }
114 }
115 (void)builder.AddBranch(merge_blk_id);
116 new_blocks->push_back(std::move(new_blk_ptr));
117 // Gen merge block
118 new_blk_ptr.reset(new BasicBlock(std::move(merge_label)));
119 builder.SetInsertPoint(&*new_blk_ptr);
120 // Gen phi of new reference and zero, if necessary, and replace the
121 // result id of the original reference with that of the Phi. Kill original
122 // reference.
123 if (new_ref_id != 0) {
124 Instruction* phi_inst =
125 builder.AddPhi(ref_inst->type_id(),
126 {new_ref_id, valid_blk_id, null_id, invalid_blk_id});
127 context()->ReplaceAllUsesWith(ref_inst->result_id(), phi_inst->result_id());
128 }
129 new_blocks->push_back(std::move(new_blk_ptr));
130 context()->KillInst(ref_inst);
131 }
132
GetTypeLength(uint32_t type_id)133 uint32_t InstBuffAddrCheckPass::GetTypeLength(uint32_t type_id) {
134 Instruction* type_inst = get_def_use_mgr()->GetDef(type_id);
135 switch (type_inst->opcode()) {
136 case SpvOpTypeFloat:
137 case SpvOpTypeInt:
138 return type_inst->GetSingleWordInOperand(0) / 8u;
139 case SpvOpTypeVector:
140 case SpvOpTypeMatrix:
141 return type_inst->GetSingleWordInOperand(1) *
142 GetTypeLength(type_inst->GetSingleWordInOperand(0));
143 case SpvOpTypePointer:
144 assert(type_inst->GetSingleWordInOperand(0) ==
145 SpvStorageClassPhysicalStorageBufferEXT &&
146 "unexpected pointer type");
147 return 8u;
148 default:
149 assert(false && "unexpected buffer reference type");
150 return 0;
151 }
152 }
153
AddParam(uint32_t type_id,std::vector<uint32_t> * param_vec,std::unique_ptr<Function> * input_func)154 void InstBuffAddrCheckPass::AddParam(uint32_t type_id,
155 std::vector<uint32_t>* param_vec,
156 std::unique_ptr<Function>* input_func) {
157 uint32_t pid = TakeNextId();
158 param_vec->push_back(pid);
159 std::unique_ptr<Instruction> param_inst(new Instruction(
160 get_module()->context(), SpvOpFunctionParameter, type_id, pid, {}));
161 get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
162 (*input_func)->AddParameter(std::move(param_inst));
163 }
164
GetSearchAndTestFuncId()165 uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
166 if (search_test_func_id_ == 0) {
167 // Generate function "bool search_and_test(uint64_t ref_ptr, uint32_t len)"
168 // which searches input buffer for buffer which most likely contains the
169 // pointer value |ref_ptr| and verifies that the entire reference of
170 // length |len| bytes is contained in the buffer.
171 search_test_func_id_ = TakeNextId();
172 analysis::TypeManager* type_mgr = context()->get_type_mgr();
173 std::vector<const analysis::Type*> param_types = {
174 type_mgr->GetType(GetUint64Id()), type_mgr->GetType(GetUintId())};
175 analysis::Function func_ty(type_mgr->GetType(GetBoolId()), param_types);
176 analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
177 std::unique_ptr<Instruction> func_inst(
178 new Instruction(get_module()->context(), SpvOpFunction, GetBoolId(),
179 search_test_func_id_,
180 {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
181 {SpvFunctionControlMaskNone}},
182 {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
183 {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
184 get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
185 std::unique_ptr<Function> input_func =
186 MakeUnique<Function>(std::move(func_inst));
187 std::vector<uint32_t> param_vec;
188 // Add ref_ptr and length parameters
189 AddParam(GetUint64Id(), ¶m_vec, &input_func);
190 AddParam(GetUintId(), ¶m_vec, &input_func);
191 // Empty first block.
192 uint32_t first_blk_id = TakeNextId();
193 std::unique_ptr<Instruction> first_blk_label(NewLabel(first_blk_id));
194 std::unique_ptr<BasicBlock> first_blk_ptr =
195 MakeUnique<BasicBlock>(std::move(first_blk_label));
196 InstructionBuilder builder(
197 context(), &*first_blk_ptr,
198 IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
199 uint32_t hdr_blk_id = TakeNextId();
200 // Branch to search loop header
201 std::unique_ptr<Instruction> hdr_blk_label(NewLabel(hdr_blk_id));
202 (void)builder.AddInstruction(MakeUnique<Instruction>(
203 context(), SpvOpBranch, 0, 0,
204 std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {hdr_blk_id}}}));
205 input_func->AddBasicBlock(std::move(first_blk_ptr));
206 // Linear search loop header block
207 // TODO(greg-lunarg): Implement binary search
208 std::unique_ptr<BasicBlock> hdr_blk_ptr =
209 MakeUnique<BasicBlock>(std::move(hdr_blk_label));
210 builder.SetInsertPoint(&*hdr_blk_ptr);
211 // Phi for search index. Starts with 1.
212 uint32_t cont_blk_id = TakeNextId();
213 std::unique_ptr<Instruction> cont_blk_label(NewLabel(cont_blk_id));
214 // Deal with def-use cycle caused by search loop index computation.
215 // Create Add and Phi instructions first, then do Def analysis on Add.
216 // Add Phi and Add instructions and do Use analysis later.
217 uint32_t idx_phi_id = TakeNextId();
218 uint32_t idx_inc_id = TakeNextId();
219 std::unique_ptr<Instruction> idx_inc_inst(new Instruction(
220 context(), SpvOpIAdd, GetUintId(), idx_inc_id,
221 {{spv_operand_type_t::SPV_OPERAND_TYPE_ID, {idx_phi_id}},
222 {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
223 {builder.GetUintConstantId(1u)}}}));
224 std::unique_ptr<Instruction> idx_phi_inst(new Instruction(
225 context(), SpvOpPhi, GetUintId(), idx_phi_id,
226 {{spv_operand_type_t::SPV_OPERAND_TYPE_ID,
227 {builder.GetUintConstantId(1u)}},
228 {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {first_blk_id}},
229 {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {idx_inc_id}},
230 {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {cont_blk_id}}}));
231 get_def_use_mgr()->AnalyzeInstDef(&*idx_inc_inst);
232 // Add (previously created) search index phi
233 (void)builder.AddInstruction(std::move(idx_phi_inst));
234 // LoopMerge
235 uint32_t bound_test_blk_id = TakeNextId();
236 std::unique_ptr<Instruction> bound_test_blk_label(
237 NewLabel(bound_test_blk_id));
238 (void)builder.AddInstruction(MakeUnique<Instruction>(
239 context(), SpvOpLoopMerge, 0, 0,
240 std::initializer_list<Operand>{
241 {SPV_OPERAND_TYPE_ID, {bound_test_blk_id}},
242 {SPV_OPERAND_TYPE_ID, {cont_blk_id}},
243 {SPV_OPERAND_TYPE_LITERAL_INTEGER, {SpvLoopControlMaskNone}}}));
244 // Branch to continue/work block
245 (void)builder.AddInstruction(MakeUnique<Instruction>(
246 context(), SpvOpBranch, 0, 0,
247 std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_blk_id}}}));
248 input_func->AddBasicBlock(std::move(hdr_blk_ptr));
249 // Continue/Work Block. Read next buffer pointer and break if greater
250 // than ref_ptr arg.
251 std::unique_ptr<BasicBlock> cont_blk_ptr =
252 MakeUnique<BasicBlock>(std::move(cont_blk_label));
253 builder.SetInsertPoint(&*cont_blk_ptr);
254 // Add (previously created) search index increment now.
255 (void)builder.AddInstruction(std::move(idx_inc_inst));
256 // Load next buffer address from debug input buffer
257 uint32_t ibuf_id = GetInputBufferId();
258 uint32_t ibuf_ptr_id = GetInputBufferPtrId();
259 Instruction* uptr_ac_inst = builder.AddTernaryOp(
260 ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
261 builder.GetUintConstantId(kDebugInputDataOffset), idx_inc_id);
262 uint32_t ibuf_type_id = GetInputBufferTypeId();
263 Instruction* uptr_load_inst =
264 builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, uptr_ac_inst->result_id());
265 // If loaded address greater than ref_ptr arg, break, else branch back to
266 // loop header
267 Instruction* uptr_test_inst =
268 builder.AddBinaryOp(GetBoolId(), SpvOpUGreaterThan,
269 uptr_load_inst->result_id(), param_vec[0]);
270 (void)builder.AddConditionalBranch(uptr_test_inst->result_id(),
271 bound_test_blk_id, hdr_blk_id,
272 kInvalidId, SpvSelectionControlMaskNone);
273 input_func->AddBasicBlock(std::move(cont_blk_ptr));
274 // Bounds test block. Read length of selected buffer and test that
275 // all len arg bytes are in buffer.
276 std::unique_ptr<BasicBlock> bound_test_blk_ptr =
277 MakeUnique<BasicBlock>(std::move(bound_test_blk_label));
278 builder.SetInsertPoint(&*bound_test_blk_ptr);
279 // Decrement index to point to previous/candidate buffer address
280 Instruction* cand_idx_inst = builder.AddBinaryOp(
281 GetUintId(), SpvOpISub, idx_inc_id, builder.GetUintConstantId(1u));
282 // Load candidate buffer address
283 Instruction* cand_ac_inst =
284 builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
285 builder.GetUintConstantId(kDebugInputDataOffset),
286 cand_idx_inst->result_id());
287 Instruction* cand_load_inst =
288 builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, cand_ac_inst->result_id());
289 // Compute offset of ref_ptr from candidate buffer address
290 Instruction* offset_inst = builder.AddBinaryOp(
291 ibuf_type_id, SpvOpISub, param_vec[0], cand_load_inst->result_id());
292 // Convert ref length to uint64
293 Instruction* ref_len_64_inst =
294 builder.AddUnaryOp(ibuf_type_id, SpvOpUConvert, param_vec[1]);
295 // Add ref length to ref offset to compute end of reference
296 Instruction* ref_end_inst =
297 builder.AddBinaryOp(ibuf_type_id, SpvOpIAdd, offset_inst->result_id(),
298 ref_len_64_inst->result_id());
299 // Load starting index of lengths in input buffer and convert to uint32
300 Instruction* len_start_ac_inst =
301 builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
302 builder.GetUintConstantId(kDebugInputDataOffset),
303 builder.GetUintConstantId(0u));
304 Instruction* len_start_load_inst = builder.AddUnaryOp(
305 ibuf_type_id, SpvOpLoad, len_start_ac_inst->result_id());
306 Instruction* len_start_32_inst = builder.AddUnaryOp(
307 GetUintId(), SpvOpUConvert, len_start_load_inst->result_id());
308 // Decrement search index to get candidate buffer length index
309 Instruction* cand_len_idx_inst =
310 builder.AddBinaryOp(GetUintId(), SpvOpISub, cand_idx_inst->result_id(),
311 builder.GetUintConstantId(1u));
312 // Add candidate length index to start index
313 Instruction* len_idx_inst = builder.AddBinaryOp(
314 GetUintId(), SpvOpIAdd, cand_len_idx_inst->result_id(),
315 len_start_32_inst->result_id());
316 // Load candidate buffer length
317 Instruction* len_ac_inst =
318 builder.AddTernaryOp(ibuf_ptr_id, SpvOpAccessChain, ibuf_id,
319 builder.GetUintConstantId(kDebugInputDataOffset),
320 len_idx_inst->result_id());
321 Instruction* len_load_inst =
322 builder.AddUnaryOp(ibuf_type_id, SpvOpLoad, len_ac_inst->result_id());
323 // Test if reference end within candidate buffer length
324 Instruction* len_test_inst = builder.AddBinaryOp(
325 GetBoolId(), SpvOpULessThanEqual, ref_end_inst->result_id(),
326 len_load_inst->result_id());
327 // Return test result
328 (void)builder.AddInstruction(MakeUnique<Instruction>(
329 context(), SpvOpReturnValue, 0, 0,
330 std::initializer_list<Operand>{
331 {SPV_OPERAND_TYPE_ID, {len_test_inst->result_id()}}}));
332 // Close block
333 input_func->AddBasicBlock(std::move(bound_test_blk_ptr));
334 // Close function and add function to module
335 std::unique_ptr<Instruction> func_end_inst(
336 new Instruction(get_module()->context(), SpvOpFunctionEnd, 0, 0, {}));
337 get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
338 input_func->SetFunctionEnd(std::move(func_end_inst));
339 context()->AddFunction(std::move(input_func));
340 }
341 return search_test_func_id_;
342 }
343
GenSearchAndTest(Instruction * ref_inst,InstructionBuilder * builder,uint32_t * ref_uptr_id)344 uint32_t InstBuffAddrCheckPass::GenSearchAndTest(Instruction* ref_inst,
345 InstructionBuilder* builder,
346 uint32_t* ref_uptr_id) {
347 // Enable Int64 if necessary
348 if (!get_feature_mgr()->HasCapability(SpvCapabilityInt64)) {
349 std::unique_ptr<Instruction> cap_int64_inst(new Instruction(
350 context(), SpvOpCapability, 0, 0,
351 std::initializer_list<Operand>{
352 {SPV_OPERAND_TYPE_CAPABILITY, {SpvCapabilityInt64}}}));
353 get_def_use_mgr()->AnalyzeInstDefUse(&*cap_int64_inst);
354 context()->AddCapability(std::move(cap_int64_inst));
355 }
356 // Convert reference pointer to uint64
357 uint32_t ref_ptr_id = ref_inst->GetSingleWordInOperand(0);
358 Instruction* ref_uptr_inst =
359 builder->AddUnaryOp(GetUint64Id(), SpvOpConvertPtrToU, ref_ptr_id);
360 *ref_uptr_id = ref_uptr_inst->result_id();
361 // Compute reference length in bytes
362 analysis::DefUseManager* du_mgr = get_def_use_mgr();
363 Instruction* ref_ptr_inst = du_mgr->GetDef(ref_ptr_id);
364 uint32_t ref_ptr_ty_id = ref_ptr_inst->type_id();
365 Instruction* ref_ptr_ty_inst = du_mgr->GetDef(ref_ptr_ty_id);
366 uint32_t ref_len = GetTypeLength(ref_ptr_ty_inst->GetSingleWordInOperand(1));
367 uint32_t ref_len_id = builder->GetUintConstantId(ref_len);
368 // Gen call to search and test function
369 const std::vector<uint32_t> args = {GetSearchAndTestFuncId(), *ref_uptr_id,
370 ref_len_id};
371 Instruction* call_inst =
372 builder->AddNaryOp(GetBoolId(), SpvOpFunctionCall, args);
373 uint32_t retval = call_inst->result_id();
374 return retval;
375 }
376
GenBuffAddrCheckCode(BasicBlock::iterator ref_inst_itr,UptrVectorIterator<BasicBlock> ref_block_itr,uint32_t stage_idx,std::vector<std::unique_ptr<BasicBlock>> * new_blocks)377 void InstBuffAddrCheckPass::GenBuffAddrCheckCode(
378 BasicBlock::iterator ref_inst_itr,
379 UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
380 std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
381 // Look for reference through indexed descriptor. If found, analyze and
382 // save components. If not, return.
383 Instruction* ref_inst = &*ref_inst_itr;
384 if (!IsPhysicalBuffAddrReference(ref_inst)) return;
385 // Move original block's preceding instructions into first new block
386 std::unique_ptr<BasicBlock> new_blk_ptr;
387 MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr);
388 InstructionBuilder builder(
389 context(), &*new_blk_ptr,
390 IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
391 new_blocks->push_back(std::move(new_blk_ptr));
392 uint32_t error_id = builder.GetUintConstantId(kInstErrorBuffAddrUnallocRef);
393 // Generate code to do search and test if all bytes of reference
394 // are within a listed buffer. Return reference pointer converted to uint64.
395 uint32_t ref_uptr_id;
396 uint32_t valid_id = GenSearchAndTest(ref_inst, &builder, &ref_uptr_id);
397 // Generate test of search results with true branch
398 // being full reference and false branch being debug output and zero
399 // for the referenced value.
400 GenCheckCode(valid_id, error_id, ref_uptr_id, stage_idx, ref_inst,
401 new_blocks);
402 // Move original block's remaining code into remainder/merge block and add
403 // to new blocks
404 BasicBlock* back_blk_ptr = &*new_blocks->back();
405 MovePostludeCode(ref_block_itr, back_blk_ptr);
406 }
407
InitInstBuffAddrCheck()408 void InstBuffAddrCheckPass::InitInstBuffAddrCheck() {
409 // Initialize base class
410 InitializeInstrument();
411 // Initialize class
412 search_test_func_id_ = 0;
413 }
414
ProcessImpl()415 Pass::Status InstBuffAddrCheckPass::ProcessImpl() {
416 // Perform bindless bounds check on each entry point function in module
417 InstProcessFunction pfn =
418 [this](BasicBlock::iterator ref_inst_itr,
419 UptrVectorIterator<BasicBlock> ref_block_itr, uint32_t stage_idx,
420 std::vector<std::unique_ptr<BasicBlock>>* new_blocks) {
421 return GenBuffAddrCheckCode(ref_inst_itr, ref_block_itr, stage_idx,
422 new_blocks);
423 };
424 bool modified = InstProcessEntryPointCallTree(pfn);
425 return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
426 }
427
Process()428 Pass::Status InstBuffAddrCheckPass::Process() {
429 if (!get_feature_mgr()->HasCapability(
430 SpvCapabilityPhysicalStorageBufferAddressesEXT))
431 return Status::SuccessWithoutChange;
432 InitInstBuffAddrCheck();
433 return ProcessImpl();
434 }
435
436 } // namespace opt
437 } // namespace spvtools
438