| ... | ... | @@ -4164,6 +4164,7 @@ fn validateStructInit( |
| 4164 | 4164 | // We expect to see something like this in the current block AIR: |
| 4165 | 4165 | // %a = field_ptr(...) |
| 4166 | 4166 | // store(%a, %b) |
| 4167 | // With an optional bitcast between the store and the field_ptr. |
| 4167 | 4168 | // If %b is a comptime operand, this field is comptime. |
| 4168 | 4169 | // |
| 4169 | 4170 | // However, in the case of a comptime-known pointer to a struct, the |
| ... | ... | @@ -4374,75 +4375,65 @@ fn zirValidateArrayInit( |
| 4374 | 4375 | |
| 4375 | 4376 | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; |
| 4376 | 4377 | const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?; |
| 4377 | | // Find the block index of the elem_ptr so that we can look at the next |
| 4378 | | // instruction after it within the same block. |
| 4378 | |
| 4379 | // We expect to see something like this in the current block AIR: |
| 4380 | // %a = elem_ptr(...) |
| 4381 | // store(%a, %b) |
| 4382 | // With an optional bitcast between the store and the elem_ptr. |
| 4383 | // If %b is a comptime operand, this element is comptime. |
| 4384 | // |
| 4385 | // However, in the case of a comptime-known pointer to an array, the |
| 4386 | // the elem_ptr instruction is missing, so we have to pattern-match |
| 4387 | // based only on the store instructions. |
| 4388 | // `first_block_index` needs to point to the `elem_ptr` if it exists; |
| 4389 | // the `store` otherwise. |
| 4390 | // |
| 4391 | // It's also possible for there to be no store instruction, in the case |
| 4392 | // of nested `coerce_result_ptr` instructions. If we see the `elem_ptr` |
| 4393 | // but we have not found a `store`, treat as a runtime-known element. |
| 4394 | // |
| 4395 | // This is nearly identical to similar logic in `validateStructInit`. |
| 4396 | |
| 4379 | 4397 | // Possible performance enhancement: save the `block_index` between iterations |
| 4380 | 4398 | // of the for loop. |
| 4381 | 4399 | var block_index = block.instructions.items.len - 1; |
| 4382 | | while (block.instructions.items[block_index] != elem_ptr_air_inst) { |
| 4383 | | if (block_index == 0) { |
| 4400 | while (block_index > 0) : (block_index -= 1) { |
| 4401 | const store_inst = block.instructions.items[block_index]; |
| 4402 | if (store_inst == elem_ptr_air_inst) { |
| 4384 | 4403 | array_is_comptime = false; |
| 4385 | 4404 | continue :outer; |
| 4386 | 4405 | } |
| 4387 | | block_index -= 1; |
| 4388 | | } |
| 4389 | | first_block_index = @min(first_block_index, block_index); |
| 4390 | | |
| 4391 | | // If the next instructon is a store with a comptime operand, this element |
| 4392 | | // is comptime. |
| 4393 | | const next_air_inst = block.instructions.items[block_index + 1]; |
| 4394 | | switch (air_tags[next_air_inst]) { |
| 4395 | | .store => { |
| 4396 | | const bin_op = air_datas[next_air_inst].bin_op; |
| 4397 | | var lhs = bin_op.lhs; |
| 4398 | | if (Air.refToIndex(lhs)) |lhs_index| { |
| 4399 | | if (air_tags[lhs_index] == .bitcast) { |
| 4400 | | lhs = air_datas[lhs_index].ty_op.operand; |
| 4401 | | block_index -= 1; |
| 4402 | | } |
| 4403 | | } |
| 4404 | | if (lhs != elem_ptr_air_ref) { |
| 4405 | | array_is_comptime = false; |
| 4406 | | continue; |
| 4407 | | } |
| 4408 | | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| { |
| 4409 | | element_vals[i] = val; |
| 4410 | | } else { |
| 4411 | | array_is_comptime = false; |
| 4412 | | } |
| 4413 | | continue; |
| 4414 | | }, |
| 4415 | | .bitcast => { |
| 4416 | | // %a = bitcast(*arr_ty, %array_base) |
| 4417 | | // %b = ptr_elem_ptr(%a, %index) |
| 4418 | | // %c = bitcast(*elem_ty, %b) |
| 4419 | | // %d = store(%c, %val) |
| 4420 | | if (air_datas[next_air_inst].ty_op.operand != elem_ptr_air_ref) { |
| 4421 | | array_is_comptime = false; |
| 4422 | | continue; |
| 4423 | | } |
| 4424 | | const store_inst = block.instructions.items[block_index + 2]; |
| 4425 | | if (air_tags[store_inst] != .store) { |
| 4426 | | array_is_comptime = false; |
| 4427 | | continue; |
| 4428 | | } |
| 4429 | | const bin_op = air_datas[store_inst].bin_op; |
| 4430 | | if (bin_op.lhs != Air.indexToRef(next_air_inst)) { |
| 4431 | | array_is_comptime = false; |
| 4432 | | continue; |
| 4433 | | } |
| 4434 | | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| { |
| 4435 | | element_vals[i] = val; |
| 4436 | | } else { |
| 4437 | | array_is_comptime = false; |
| 4406 | if (air_tags[store_inst] != .store) continue; |
| 4407 | const bin_op = air_datas[store_inst].bin_op; |
| 4408 | var lhs = bin_op.lhs; |
| 4409 | { |
| 4410 | const lhs_index = Air.refToIndex(lhs) orelse continue; |
| 4411 | if (air_tags[lhs_index] == .bitcast) { |
| 4412 | lhs = air_datas[lhs_index].ty_op.operand; |
| 4413 | block_index -= 1; |
| 4438 | 4414 | } |
| 4439 | | continue; |
| 4440 | | }, |
| 4441 | | else => { |
| 4415 | } |
| 4416 | if (lhs != elem_ptr_air_ref) continue; |
| 4417 | while (block_index > 0) : (block_index -= 1) { |
| 4418 | const block_inst = block.instructions.items[block_index - 1]; |
| 4419 | if (air_tags[block_inst] != .dbg_stmt) break; |
| 4420 | } |
| 4421 | if (block_index > 0 and |
| 4422 | elem_ptr_air_inst == block.instructions.items[block_index - 1]) |
| 4423 | { |
| 4424 | first_block_index = @min(first_block_index, block_index - 1); |
| 4425 | } else { |
| 4426 | first_block_index = @min(first_block_index, block_index); |
| 4427 | } |
| 4428 | if (try sema.resolveMaybeUndefValAllowVariablesMaybeRuntime(block, elem_src, bin_op.rhs, &make_runtime)) |val| { |
| 4429 | element_vals[i] = val; |
| 4430 | } else { |
| 4442 | 4431 | array_is_comptime = false; |
| 4443 | | continue; |
| 4444 | | }, |
| 4432 | } |
| 4433 | continue :outer; |
| 4445 | 4434 | } |
| 4435 | array_is_comptime = false; |
| 4436 | continue :outer; |
| 4446 | 4437 | } |
| 4447 | 4438 | |
| 4448 | 4439 | if (array_is_comptime) { |