| ... | @@ -4164,6 +4164,7 @@ fn validateStructInit( | ... | @@ -4164,6 +4164,7 @@ fn validateStructInit( |
| 4164 | // We expect to see something like this in the current block AIR: | 4164 | // We expect to see something like this in the current block AIR: |
| 4165 | // %a = field_ptr(...) | 4165 | // %a = field_ptr(...) |
| 4166 | // store(%a, %b) | 4166 | // store(%a, %b) |
| | 4167 | // With an optional bitcast between the store and the field_ptr. |
| 4167 | // If %b is a comptime operand, this field is comptime. | 4168 | // If %b is a comptime operand, this field is comptime. |
| 4168 | // | 4169 | // |
| 4169 | // However, in the case of a comptime-known pointer to a struct, the | 4170 | // However, in the case of a comptime-known pointer to a struct, the |
| ... | @@ -4374,75 +4375,65 @@ fn zirValidateArrayInit( | ... | @@ -4374,75 +4375,65 @@ fn zirValidateArrayInit( |
| 4374 | | 4375 | |
| 4375 | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; | 4376 | const elem_ptr_air_ref = sema.inst_map.get(elem_ptr).?; |
| 4376 | const elem_ptr_air_inst = Air.refToIndex(elem_ptr_air_ref).?; | 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 | |
| 4378 | // instruction after it within the same block. | 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 | // Possible performance enhancement: save the `block_index` between iterations | 4397 | // Possible performance enhancement: save the `block_index` between iterations |
| 4380 | // of the for loop. | 4398 | // of the for loop. |
| 4381 | var block_index = block.instructions.items.len - 1; | 4399 | var block_index = block.instructions.items.len - 1; |
| 4382 | while (block.instructions.items[block_index] != elem_ptr_air_inst) { | 4400 | while (block_index > 0) : (block_index -= 1) { |
| 4383 | if (block_index == 0) { | 4401 | const store_inst = block.instructions.items[block_index]; |
| | 4402 | if (store_inst == elem_ptr_air_inst) { |
| 4384 | array_is_comptime = false; | 4403 | array_is_comptime = false; |
| 4385 | continue :outer; | 4404 | continue :outer; |
| 4386 | } | 4405 | } |
| 4387 | block_index -= 1; | 4406 | if (air_tags[store_inst] != .store) continue; |
| 4388 | } | 4407 | const bin_op = air_datas[store_inst].bin_op; |
| 4389 | first_block_index = @min(first_block_index, block_index); | 4408 | var lhs = bin_op.lhs; |
| 4390 | | 4409 | { |
| 4391 | // If the next instructon is a store with a comptime operand, this element | 4410 | const lhs_index = Air.refToIndex(lhs) orelse continue; |
| 4392 | // is comptime. | 4411 | if (air_tags[lhs_index] == .bitcast) { |
| 4393 | const next_air_inst = block.instructions.items[block_index + 1]; | 4412 | lhs = air_datas[lhs_index].ty_op.operand; |
| 4394 | switch (air_tags[next_air_inst]) { | 4413 | block_index -= 1; |
| 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; | | |
| 4438 | } | 4414 | } |
| 4439 | continue; | 4415 | } |
| 4440 | }, | 4416 | if (lhs != elem_ptr_air_ref) continue; |
| 4441 | else => { | 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 | array_is_comptime = false; | 4431 | array_is_comptime = false; |
| 4443 | continue; | 4432 | } |
| 4444 | }, | 4433 | continue :outer; |
| 4445 | } | 4434 | } |
| | 4435 | array_is_comptime = false; |
| | 4436 | continue :outer; |
| 4446 | } | 4437 | } |
| 4447 | | 4438 | |
| 4448 | if (array_is_comptime) { | 4439 | if (array_is_comptime) { |