authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-17 16:39:45-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-18 19:17:20-07:00
log293d6bdc73c5fe01b07ebe3d09c9a78613fed093
treeff2ab85b168aa731fcdf1ddb530ed70d1c285245
parent841add6890d001d315591dc20f7d464c264d88bb

AstGen: back to index-based for loops


4 files changed, 106 insertions(+), 143 deletions(-)

src/AstGen.zig+71-88
...@@ -88,7 +88,6 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -88,7 +88,6 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {
88 Zir.Inst.BuiltinCall.Flags => @bitCast(u32, @field(extra, field.name)),88 Zir.Inst.BuiltinCall.Flags => @bitCast(u32, @field(extra, field.name)),
89 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),89 Zir.Inst.SwitchBlock.Bits => @bitCast(u32, @field(extra, field.name)),
90 Zir.Inst.FuncFancy.Bits => @bitCast(u32, @field(extra, field.name)),90 Zir.Inst.FuncFancy.Bits => @bitCast(u32, @field(extra, field.name)),
91 Zir.Inst.ElemPtrImm.Bits => @bitCast(u32, @field(extra, field.name)),
92 else => @compileError("bad field type"),91 else => @compileError("bad field type"),
93 };92 };
94 i += 1;93 i += 1;
...@@ -1566,9 +1565,7 @@ fn arrayInitExprRlPtrInner(...@@ -1566,9 +1565,7 @@ fn arrayInitExprRlPtrInner(
1566 for (elements) |elem_init, i| {1565 for (elements) |elem_init, i| {
1567 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{1566 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{
1568 .ptr = result_ptr,1567 .ptr = result_ptr,
1569 .bits = .{1568 .index = @intCast(u32, i),
1570 .index = @intCast(u31, i),
1571 },
1572 });1569 });
1573 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;1570 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1574 extra_index += 1;1571 extra_index += 1;
...@@ -2601,6 +2598,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2601,6 +2598,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2601 .field_base_ptr,2598 .field_base_ptr,
2602 .ret_ptr,2599 .ret_ptr,
2603 .ret_type,2600 .ret_type,
2601 .for_len,
2604 .@"try",2602 .@"try",
2605 .try_ptr,2603 .try_ptr,
2606 //.try_inline,2604 //.try_inline,
...@@ -2669,7 +2667,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As...@@ -2669,7 +2667,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As
2669 .validate_deref,2667 .validate_deref,
2670 .save_err_ret_index,2668 .save_err_ret_index,
2671 .restore_err_ret_index,2669 .restore_err_ret_index,
2672 .for_check_lens,
2673 => break :b true,2670 => break :b true,
26742671
2675 .@"defer" => unreachable,2672 .@"defer" => unreachable,
...@@ -6305,23 +6302,26 @@ fn forExpr(...@@ -6305,23 +6302,26 @@ fn forExpr(
6305 const node_data = tree.nodes.items(.data);6302 const node_data = tree.nodes.items(.data);
6306 const gpa = astgen.gpa;6303 const gpa = astgen.gpa;
63076304
6308 const allocs = try gpa.alloc(Zir.Inst.Ref, for_full.ast.inputs.len);6305 // For counters, this is the start value; for indexables, this is the base
6309 defer gpa.free(allocs);6306 // pointer that can be used with elem_ptr and similar instructions.
6307 // Special value `none` means that this is a counter and its start value is
6308 // zero, indicating that the main index counter can be used directly.
6309 const indexables = try gpa.alloc(Zir.Inst.Ref, for_full.ast.inputs.len);
6310 defer gpa.free(indexables);
6310 // elements of this array can be `none`, indicating no length check.6311 // elements of this array can be `none`, indicating no length check.
6311 const lens = try gpa.alloc(Zir.Inst.Ref, for_full.ast.inputs.len);6312 const lens = try gpa.alloc(Zir.Inst.Ref, for_full.ast.inputs.len);
6312 defer gpa.free(lens);6313 defer gpa.free(lens);
63136314
6314 const alloc_tag: Zir.Inst.Tag = if (is_inline) .alloc_comptime_mut else .alloc_mut;6315 // We will use a single zero-based counter no matter how many indexables there are.
6316 const index_ptr = blk: {
6317 const alloc_tag: Zir.Inst.Tag = if (is_inline) .alloc_comptime_mut else .alloc;
6318 const index_ptr = try parent_gz.addUnNode(alloc_tag, .usize_type, node);
6319 // initialize to zero
6320 _ = try parent_gz.addBin(.store, index_ptr, .zero_usize);
6321 break :blk index_ptr;
6322 };
63156323
6316 // Tracks the index of allocs/lens that has a length to be checked and is6324 var any_len_checks = false;
6317 // used for the end value.
6318 // If this is null, there are no len checks.
6319 var end_input_index: ?u32 = null;
6320 // This is a value to use to find out if the for loop has reached the end
6321 // yet. It prefers to use a counter since the end value is provided directly,
6322 // and otherwise falls back to adding ptr+len of a slice to compute end.
6323 // Corresponds to end_input_index and will be .none in case that value is null.
6324 var cond_end_val: Zir.Inst.Ref = .none;
63256325
6326 {6326 {
6327 var capture_token = for_full.payload_token;6327 var capture_token = for_full.payload_token;
...@@ -6341,10 +6341,8 @@ fn forExpr(...@@ -6341,10 +6341,8 @@ fn forExpr(
6341 if (capture_is_ref) {6341 if (capture_is_ref) {
6342 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});6342 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
6343 }6343 }
6344 const counter_ptr = try parent_gz.addUnNode(alloc_tag, .usize_type, node);
6345 const start_node = node_data[input].lhs;6344 const start_node = node_data[input].lhs;
6346 const start_val = try expr(parent_gz, scope, .{ .rl = .none }, start_node);6345 const start_val = try expr(parent_gz, scope, .{ .rl = .none }, start_node);
6347 _ = try parent_gz.addBin(.store, counter_ptr, start_val);
63486346
6349 const end_node = node_data[input].rhs;6347 const end_node = node_data[input].rhs;
6350 const end_val = if (end_node != 0)6348 const end_val = if (end_node != 0)
...@@ -6352,7 +6350,8 @@ fn forExpr(...@@ -6352,7 +6350,8 @@ fn forExpr(
6352 else6350 else
6353 .none;6351 .none;
63546352
6355 const range_len = if (end_val == .none or nodeIsTriviallyZero(tree, start_node))6353 const start_is_zero = nodeIsTriviallyZero(tree, start_node);
6354 const range_len = if (end_val == .none or start_is_zero)
6356 end_val6355 end_val
6357 else6356 else
6358 try parent_gz.addPlNode(.sub, input, Zir.Inst.Bin{6357 try parent_gz.addPlNode(.sub, input, Zir.Inst.Bin{
...@@ -6360,61 +6359,33 @@ fn forExpr(...@@ -6360,61 +6359,33 @@ fn forExpr(
6360 .rhs = start_val,6359 .rhs = start_val,
6361 });6360 });
63626361
6363 if (range_len != .none and cond_end_val == .none) {6362 any_len_checks = any_len_checks or range_len != .none;
6364 end_input_index = i;6363 indexables[i] = if (start_is_zero) .none else start_val;
6365 cond_end_val = end_val;
6366 }
6367
6368 allocs[i] = counter_ptr;
6369 lens[i] = range_len;6364 lens[i] = range_len;
6370 } else {6365 } else {
6371 const indexable = try expr(parent_gz, scope, .{ .rl = .none }, input);6366 const indexable = try expr(parent_gz, scope, .{ .rl = .none }, input);
6372 // This instruction has nice compile errors so we put it before the other ones6367 const indexable_len = try parent_gz.addUnNode(.indexable_ptr_len, indexable, input);
6373 // even though it is not needed until later in the block.
6374 const ptr_len = try parent_gz.addUnNode(.indexable_ptr_len, indexable, input);
6375 const base_ptr = try parent_gz.addPlNode(.elem_ptr_imm, input, Zir.Inst.ElemPtrImm{
6376 .ptr = indexable,
6377 .bits = .{
6378 .index = 0,
6379 .manyptr = true,
6380 },
6381 });
6382 const alloc_ty_inst = try parent_gz.addUnNode(.typeof, base_ptr, node);
6383 const alloc = try parent_gz.addUnNode(alloc_tag, alloc_ty_inst, node);
6384 _ = try parent_gz.addBin(.store, alloc, base_ptr);
6385
6386 if (end_input_index == null) {
6387 end_input_index = i;
6388 assert(cond_end_val == .none);
6389 }
63906368
6391 allocs[i] = alloc;6369 any_len_checks = true;
6392 lens[i] = ptr_len;6370 indexables[i] = indexable;
6371 lens[i] = indexable_len;
6393 }6372 }
6394 }6373 }
6395 }6374 }
63966375
6397 // In case there are no counters which already have an end computed, we
6398 // compute an end from base pointer plus length.
6399 if (end_input_index) |i| {
6400 if (cond_end_val == .none) {
6401 cond_end_val = try parent_gz.addPlNode(.add, for_full.ast.inputs[i], Zir.Inst.Bin{
6402 .lhs = allocs[i],
6403 .rhs = lens[i],
6404 });
6405 }
6406 }
6407
6408 // We use a dedicated ZIR instruction to assert the lengths to assist with6376 // We use a dedicated ZIR instruction to assert the lengths to assist with
6409 // nicer error reporting as well as fewer ZIR bytes emitted.6377 // nicer error reporting as well as fewer ZIR bytes emitted.
6410 if (end_input_index != null) {6378 const len: Zir.Inst.Ref = len: {
6379 if (!any_len_checks) break :len .none;
6380
6411 const lens_len = @intCast(u32, lens.len);6381 const lens_len = @intCast(u32, lens.len);
6412 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.MultiOp).Struct.fields.len + lens_len);6382 try astgen.extra.ensureUnusedCapacity(gpa, @typeInfo(Zir.Inst.MultiOp).Struct.fields.len + lens_len);
6413 _ = try parent_gz.addPlNode(.for_check_lens, node, Zir.Inst.MultiOp{6383 const len = try parent_gz.addPlNode(.for_len, node, Zir.Inst.MultiOp{
6414 .operands_len = lens_len,6384 .operands_len = lens_len,
6415 });6385 });
6416 appendRefsAssumeCapacity(astgen, lens);6386 appendRefsAssumeCapacity(astgen, lens);
6417 }6387 break :len len;
6388 };
64186389
6419 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;6390 const loop_tag: Zir.Inst.Tag = if (is_inline) .block_inline else .loop;
6420 const loop_block = try parent_gz.makeBlockInst(loop_tag, node);6391 const loop_block = try parent_gz.makeBlockInst(loop_tag, node);
...@@ -6429,22 +6400,14 @@ fn forExpr(...@@ -6429,22 +6400,14 @@ fn forExpr(
6429 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);6400 var cond_scope = parent_gz.makeSubBlock(&loop_scope.base);
6430 defer cond_scope.unstack();6401 defer cond_scope.unstack();
64316402
6432 // Load all the iterables.
6433 const loaded_ptrs = try gpa.alloc(Zir.Inst.Ref, allocs.len);
6434 defer gpa.free(loaded_ptrs);
6435 for (allocs) |alloc, i| {
6436 loaded_ptrs[i] = try cond_scope.addUnNode(.load, alloc, for_full.ast.inputs[i]);
6437 }
6438
6439 // Check the condition.6403 // Check the condition.
6440 const input_index = end_input_index orelse {6404 if (!any_len_checks) {
6441 return astgen.failNode(node, "TODO: handle infinite for loop", .{});6405 return astgen.failNode(node, "TODO: handle infinite for loop", .{});
6442 };6406 }
6443 assert(cond_end_val != .none);6407 const index = try cond_scope.addUnNode(.load, index_ptr, node);
64446408 const cond = try cond_scope.addPlNode(.cmp_lt, node, Zir.Inst.Bin{
6445 const cond = try cond_scope.addPlNode(.cmp_neq, for_full.ast.inputs[input_index], Zir.Inst.Bin{6409 .lhs = index,
6446 .lhs = loaded_ptrs[input_index],6410 .rhs = len,
6447 .rhs = cond_end_val,
6448 });6411 });
64496412
6450 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;6413 const condbr_tag: Zir.Inst.Tag = if (is_inline) .condbr_inline else .condbr;
...@@ -6455,14 +6418,12 @@ fn forExpr(...@@ -6455,14 +6418,12 @@ fn forExpr(
6455 // cond_block unstacked now, can add new instructions to loop_scope6418 // cond_block unstacked now, can add new instructions to loop_scope
6456 try loop_scope.instructions.append(gpa, cond_block);6419 try loop_scope.instructions.append(gpa, cond_block);
64576420
6458 // Increment the loop variables.6421 // Increment the index variable.
6459 for (allocs) |alloc, i| {6422 const index_plus_one = try loop_scope.addPlNode(.add, node, Zir.Inst.Bin{
6460 const incremented = try loop_scope.addPlNode(.add, node, Zir.Inst.Bin{6423 .lhs = index,
6461 .lhs = loaded_ptrs[i],6424 .rhs = .one_usize,
6462 .rhs = .one_usize,6425 });
6463 });6426 _ = try loop_scope.addBin(.store, index_ptr, index_plus_one);
6464 _ = try loop_scope.addBin(.store, alloc, incremented);
6465 }
6466 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;6427 const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
6467 _ = try loop_scope.addNode(repeat_tag, node);6428 _ = try loop_scope.addNode(repeat_tag, node);
64686429
...@@ -6500,21 +6461,43 @@ fn forExpr(...@@ -6500,21 +6461,43 @@ fn forExpr(
6500 const name_str_index = try astgen.identAsString(ident_tok);6461 const name_str_index = try astgen.identAsString(ident_tok);
6501 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);6462 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);
65026463
6503 const loaded = if (capture_is_ref)6464 const capture_inst = inst: {
6504 loaded_ptrs[i]6465 const is_counter = node_tags[input] == .for_range;
6505 else6466
6506 try then_scope.addUnNode(.load, loaded_ptrs[i], input);6467 if (indexables[i] == .none) {
6468 // Special case: the main index can be used directly.
6469 assert(is_counter);
6470 assert(!capture_is_ref);
6471 break :inst index;
6472 }
6473
6474 // For counters, we add the index variable to the start value; for
6475 // indexables, we use it as an element index. This is so similar
6476 // that they can share the same code paths, branching only on the
6477 // ZIR tag.
6478 const switch_cond = (@as(u2, @boolToInt(capture_is_ref)) << 1) | @boolToInt(is_counter);
6479 const tag: Zir.Inst.Tag = switch (switch_cond) {
6480 0b00 => .elem_val,
6481 0b01 => .add,
6482 0b10 => .elem_ptr,
6483 0b11 => unreachable, // compile error emitted already
6484 };
6485 break :inst try then_scope.addPlNode(tag, input, Zir.Inst.Bin{
6486 .lhs = indexables[i],
6487 .rhs = index,
6488 });
6489 };
65076490
6508 capture_scopes[i] = .{6491 capture_scopes[i] = .{
6509 .parent = capture_sub_scope,6492 .parent = capture_sub_scope,
6510 .gen_zir = &then_scope,6493 .gen_zir = &then_scope,
6511 .name = name_str_index,6494 .name = name_str_index,
6512 .inst = loaded,6495 .inst = capture_inst,
6513 .token_src = ident_tok,6496 .token_src = ident_tok,
6514 .id_cat = .capture,6497 .id_cat = .capture,
6515 };6498 };
65166499
6517 try then_scope.addDbgVar(.dbg_var_val, name_str_index, loaded);6500 try then_scope.addDbgVar(.dbg_var_val, name_str_index, capture_inst);
6518 capture_sub_scope = &capture_scopes[i].base;6501 capture_sub_scope = &capture_scopes[i].base;
6519 }6502 }
65206503
src/Sema.zig+26-37
...@@ -1035,6 +1035,7 @@ fn analyzeBodyInner(...@@ -1035,6 +1035,7 @@ fn analyzeBodyInner(
1035 .@"await" => try sema.zirAwait(block, inst),1035 .@"await" => try sema.zirAwait(block, inst),
1036 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),1036 .array_base_ptr => try sema.zirArrayBasePtr(block, inst),
1037 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),1037 .field_base_ptr => try sema.zirFieldBasePtr(block, inst),
1038 .for_len => try sema.zirForLen(block, inst),
10381039
1039 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),1040 .clz => try sema.zirBitCount(block, inst, .clz, Value.clz),
1040 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),1041 .ctz => try sema.zirBitCount(block, inst, .ctz, Value.ctz),
...@@ -1386,11 +1387,6 @@ fn analyzeBodyInner(...@@ -1386,11 +1387,6 @@ fn analyzeBodyInner(
1386 i += 1;1387 i += 1;
1387 continue;1388 continue;
1388 },1389 },
1389 .for_check_lens => {
1390 try sema.zirForCheckLens(block, inst);
1391 i += 1;
1392 continue;
1393 },
13941390
1395 // Special case instructions to handle comptime control flow.1391 // Special case instructions to handle comptime control flow.
1396 .@"break" => {1392 .@"break" => {
...@@ -3924,6 +3920,16 @@ fn zirFieldBasePtr(...@@ -3924,6 +3920,16 @@ fn zirFieldBasePtr(
3924 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType());3920 return sema.failWithStructInitNotSupported(block, src, sema.typeOf(start_ptr).childType());
3925}3921}
39263922
3923fn zirForLen(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
3924 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
3925 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
3926 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
3927 const src = inst_data.src();
3928
3929 _ = args;
3930 return sema.fail(block, src, "TODO implement zirForCheckLens", .{});
3931}
3932
3927fn validateArrayInitTy(3933fn validateArrayInitTy(
3928 sema: *Sema,3934 sema: *Sema,
3929 block: *Block,3935 block: *Block,
...@@ -9649,7 +9655,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9649,7 +9655,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
9649 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;9655 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
9650 const array_ptr = try sema.resolveInst(extra.lhs);9656 const array_ptr = try sema.resolveInst(extra.lhs);
9651 const elem_index = try sema.resolveInst(extra.rhs);9657 const elem_index = try sema.resolveInst(extra.rhs);
9652 return sema.elemPtr(block, src, array_ptr, elem_index, src, false, .One);9658 return sema.elemPtr(block, src, array_ptr, elem_index, src, false);
9653}9659}
96549660
9655fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9661fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9662,7 +9668,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9662,7 +9668,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
9662 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;9668 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
9663 const array_ptr = try sema.resolveInst(extra.lhs);9669 const array_ptr = try sema.resolveInst(extra.lhs);
9664 const elem_index = try sema.resolveInst(extra.rhs);9670 const elem_index = try sema.resolveInst(extra.rhs);
9665 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, .One);9671 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false);
9666}9672}
96679673
9668fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9674fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9673,9 +9679,8 @@ fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -9673,9 +9679,8 @@ fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
9673 const src = inst_data.src();9679 const src = inst_data.src();
9674 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;9680 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
9675 const array_ptr = try sema.resolveInst(extra.ptr);9681 const array_ptr = try sema.resolveInst(extra.ptr);
9676 const elem_index = try sema.addIntUnsigned(Type.usize, extra.bits.index);9682 const elem_index = try sema.addIntUnsigned(Type.usize, extra.index);
9677 const size: std.builtin.Type.Pointer.Size = if (extra.bits.manyptr) .Many else .One;9683 return sema.elemPtr(block, src, array_ptr, elem_index, src, true);
9678 return sema.elemPtr(block, src, array_ptr, elem_index, src, true, size);
9679}9684}
96809685
9681fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9686fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -17102,16 +17107,6 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)...@@ -17102,16 +17107,6 @@ fn zirRestoreErrRetIndex(sema: *Sema, start_block: *Block, inst: Zir.Inst.Index)
17102 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);17107 return sema.popErrorReturnTrace(start_block, src, operand, saved_index);
17103}17108}
1710417109
17105fn zirForCheckLens(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void {
17106 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
17107 const extra = sema.code.extraData(Zir.Inst.MultiOp, inst_data.payload_index);
17108 const args = sema.code.refSlice(extra.end, extra.data.operands_len);
17109 const src = inst_data.src();
17110
17111 _ = args;
17112 return sema.fail(block, src, "TODO implement zirForCheckLens", .{});
17113}
17114
17115fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {17110fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
17116 assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);17111 assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);
1711717112
...@@ -22906,7 +22901,7 @@ fn panicSentinelMismatch(...@@ -22906,7 +22901,7 @@ fn panicSentinelMismatch(
22906 const actual_sentinel = if (ptr_ty.isSlice())22901 const actual_sentinel = if (ptr_ty.isSlice())
22907 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)22902 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)
22908 else blk: {22903 else blk: {
22909 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null, .One);22904 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);
22910 const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty);22905 const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty);
22911 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);22906 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);
22912 };22907 };
...@@ -24073,7 +24068,6 @@ fn elemPtr(...@@ -24073,7 +24068,6 @@ fn elemPtr(
24073 elem_index: Air.Inst.Ref,24068 elem_index: Air.Inst.Ref,
24074 elem_index_src: LazySrcLoc,24069 elem_index_src: LazySrcLoc,
24075 init: bool,24070 init: bool,
24076 size: std.builtin.Type.Pointer.Size,
24077) CompileError!Air.Inst.Ref {24071) CompileError!Air.Inst.Ref {
24078 const indexable_ptr_src = src; // TODO better source location24072 const indexable_ptr_src = src; // TODO better source location
24079 const indexable_ptr_ty = sema.typeOf(indexable_ptr);24073 const indexable_ptr_ty = sema.typeOf(indexable_ptr);
...@@ -24100,12 +24094,13 @@ fn elemPtr(...@@ -24100,12 +24094,13 @@ fn elemPtr(
24100 const index_val = maybe_index_val orelse break :rs elem_index_src;24094 const index_val = maybe_index_val orelse break :rs elem_index_src;
24101 const index = @intCast(usize, index_val.toUnsignedInt(target));24095 const index = @intCast(usize, index_val.toUnsignedInt(target));
24102 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);24096 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);
24103 const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index, size);24097 const result_ty = try sema.elemPtrType(indexable_ty, index);
24104 return sema.addConstant(elem_ptr_ty, elem_ptr);24098 return sema.addConstant(result_ty, elem_ptr);
24105 };24099 };
24106 const elem_ptr_ty = try sema.elemPtrType(indexable_ty, null, size);24100 const result_ty = try sema.elemPtrType(indexable_ty, null);
24101
24107 try sema.requireRuntimeBlock(block, src, runtime_src);24102 try sema.requireRuntimeBlock(block, src, runtime_src);
24108 return block.addPtrElemPtr(indexable, elem_index, elem_ptr_ty);24103 return block.addPtrElemPtr(indexable, elem_index, result_ty);
24109 },24104 },
24110 .One => {24105 .One => {
24111 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable24106 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable
...@@ -24167,7 +24162,7 @@ fn elemVal(...@@ -24167,7 +24162,7 @@ fn elemVal(
24167 },24162 },
24168 .One => {24163 .One => {
24169 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable24164 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable
24170 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, .One);24165 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false);
24171 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);24166 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
24172 },24167 },
24173 },24168 },
...@@ -24405,7 +24400,7 @@ fn elemPtrArray(...@@ -24405,7 +24400,7 @@ fn elemPtrArray(
24405 break :o index;24400 break :o index;
24406 } else null;24401 } else null;
2440724402
24408 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset, .One);24403 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset);
2440924404
24410 if (maybe_undef_array_ptr_val) |array_ptr_val| {24405 if (maybe_undef_array_ptr_val) |array_ptr_val| {
24411 if (array_ptr_val.isUndef()) {24406 if (array_ptr_val.isUndef()) {
...@@ -24510,7 +24505,7 @@ fn elemPtrSlice(...@@ -24510,7 +24505,7 @@ fn elemPtrSlice(
24510 break :o index;24505 break :o index;
24511 } else null;24506 } else null;
2451224507
24513 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset, .One);24508 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset);
2451424509
24515 if (maybe_undef_slice_val) |slice_val| {24510 if (maybe_undef_slice_val) |slice_val| {
24516 if (slice_val.isUndef()) {24511 if (slice_val.isUndef()) {
...@@ -26240,7 +26235,7 @@ fn storePtr2(...@@ -26240,7 +26235,7 @@ fn storePtr2(
26240 const elem_src = operand_src; // TODO better source location26235 const elem_src = operand_src; // TODO better source location
26241 const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i);26236 const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i);
26242 const elem_index = try sema.addIntUnsigned(Type.usize, i);26237 const elem_index = try sema.addIntUnsigned(Type.usize, i);
26243 const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false, .One);26238 const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false);
26244 try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store);26239 try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store);
26245 }26240 }
26246 return;26241 return;
...@@ -33277,12 +33272,7 @@ fn compareVector(...@@ -33277,12 +33272,7 @@ fn compareVector(
33277/// For []T, returns *T33272/// For []T, returns *T
33278/// Handles const-ness and address spaces in particular.33273/// Handles const-ness and address spaces in particular.
33279/// This code is duplicated in `analyzePtrArithmetic`.33274/// This code is duplicated in `analyzePtrArithmetic`.
33280fn elemPtrType(33275fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
33281 sema: *Sema,
33282 ptr_ty: Type,
33283 offset: ?usize,
33284 size: std.builtin.Type.Pointer.Size,
33285) !Type {
33286 const ptr_info = ptr_ty.ptrInfo().data;33276 const ptr_info = ptr_ty.ptrInfo().data;
33287 const elem_ty = ptr_ty.elemType2();33277 const elem_ty = ptr_ty.elemType2();
33288 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;33278 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;
...@@ -33327,7 +33317,6 @@ fn elemPtrType(...@@ -33327,7 +33317,6 @@ fn elemPtrType(
33327 break :a new_align;33317 break :a new_align;
33328 };33318 };
33329 return try Type.ptr(sema.arena, sema.mod, .{33319 return try Type.ptr(sema.arena, sema.mod, .{
33330 .size = size,
33331 .pointee_type = elem_ty,33320 .pointee_type = elem_ty,
33332 .mutable = ptr_info.mutable,33321 .mutable = ptr_info.mutable,
33333 .@"addrspace" = ptr_info.@"addrspace",33322 .@"addrspace" = ptr_info.@"addrspace",
src/Zir.zig+7-14
...@@ -79,7 +79,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en...@@ -79,7 +79,6 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en
79 Inst.BuiltinCall.Flags => @bitCast(Inst.BuiltinCall.Flags, code.extra[i]),79 Inst.BuiltinCall.Flags => @bitCast(Inst.BuiltinCall.Flags, code.extra[i]),
80 Inst.SwitchBlock.Bits => @bitCast(Inst.SwitchBlock.Bits, code.extra[i]),80 Inst.SwitchBlock.Bits => @bitCast(Inst.SwitchBlock.Bits, code.extra[i]),
81 Inst.FuncFancy.Bits => @bitCast(Inst.FuncFancy.Bits, code.extra[i]),81 Inst.FuncFancy.Bits => @bitCast(Inst.FuncFancy.Bits, code.extra[i]),
82 Inst.ElemPtrImm.Bits => @bitCast(Inst.ElemPtrImm.Bits, code.extra[i]),
83 else => @compileError("bad field type"),82 else => @compileError("bad field type"),
84 };83 };
85 i += 1;84 i += 1;
...@@ -501,14 +500,14 @@ pub const Inst = struct {...@@ -501,14 +500,14 @@ pub const Inst = struct {
501 /// Uses the `node` field.500 /// Uses the `node` field.
502 repeat_inline,501 repeat_inline,
503 /// Asserts that all the lengths provided match. Used to build a for loop.502 /// Asserts that all the lengths provided match. Used to build a for loop.
504 /// Return value is always void.503 /// Return value is the length as a usize.
505 /// Uses the `pl_node` field with payload `MultiOp`.504 /// Uses the `pl_node` field with payload `MultiOp`.
506 /// There is exactly one item corresponding to each AST node inside the for505 /// There is exactly one item corresponding to each AST node inside the for
507 /// loop condition. Each item may be `none`, indicating an unbounded range.506 /// loop condition. Any item may be `none`, indicating an unbounded range.
508 /// Illegal behaviors:507 /// Illegal behaviors:
509 /// * If all lengths are unbounded ranges (always a compile error).508 /// * If all lengths are unbounded ranges (always a compile error).
510 /// * If any two lengths do not match each other.509 /// * If any two lengths do not match each other.
511 for_check_lens,510 for_len,
512 /// Merge two error sets into one, `E1 || E2`.511 /// Merge two error sets into one, `E1 || E2`.
513 /// Uses the `pl_node` field with payload `Bin`.512 /// Uses the `pl_node` field with payload `Bin`.
514 merge_error_sets,513 merge_error_sets,
...@@ -1254,7 +1253,7 @@ pub const Inst = struct {...@@ -1254,7 +1253,7 @@ pub const Inst = struct {
1254 .defer_err_code,1253 .defer_err_code,
1255 .save_err_ret_index,1254 .save_err_ret_index,
1256 .restore_err_ret_index,1255 .restore_err_ret_index,
1257 .for_check_lens,1256 .for_len,
1258 => false,1257 => false,
12591258
1260 .@"break",1259 .@"break",
...@@ -1322,7 +1321,6 @@ pub const Inst = struct {...@@ -1322,7 +1321,6 @@ pub const Inst = struct {
1322 .memcpy,1321 .memcpy,
1323 .memset,1322 .memset,
1324 .check_comptime_control_flow,1323 .check_comptime_control_flow,
1325 .for_check_lens,
1326 .@"defer",1324 .@"defer",
1327 .defer_err_code,1325 .defer_err_code,
1328 .restore_err_ret_index,1326 .restore_err_ret_index,
...@@ -1547,6 +1545,7 @@ pub const Inst = struct {...@@ -1547,6 +1545,7 @@ pub const Inst = struct {
1547 .repeat_inline,1545 .repeat_inline,
1548 .panic,1546 .panic,
1549 .panic_comptime,1547 .panic_comptime,
1548 .for_len,
1550 .@"try",1549 .@"try",
1551 .try_ptr,1550 .try_ptr,
1552 //.try_inline,1551 //.try_inline,
...@@ -1602,7 +1601,7 @@ pub const Inst = struct {...@@ -1602,7 +1601,7 @@ pub const Inst = struct {
1602 .@"break" = .@"break",1601 .@"break" = .@"break",
1603 .break_inline = .@"break",1602 .break_inline = .@"break",
1604 .check_comptime_control_flow = .un_node,1603 .check_comptime_control_flow = .un_node,
1605 .for_check_lens = .pl_node,1604 .for_len = .pl_node,
1606 .call = .pl_node,1605 .call = .pl_node,
1607 .cmp_lt = .pl_node,1606 .cmp_lt = .pl_node,
1608 .cmp_lte = .pl_node,1607 .cmp_lte = .pl_node,
...@@ -2975,13 +2974,7 @@ pub const Inst = struct {...@@ -2975,13 +2974,7 @@ pub const Inst = struct {
29752974
2976 pub const ElemPtrImm = struct {2975 pub const ElemPtrImm = struct {
2977 ptr: Ref,2976 ptr: Ref,
2978 bits: Bits,2977 index: u32,
2979
2980 pub const Bits = packed struct(u32) {
2981 index: u31,
2982 /// Controls whether the type returned is `*T` or `[*]T`.
2983 manyptr: bool = false,
2984 };
2985 };2978 };
29862979
2987 /// 0. multi_cases_len: u32 // If has_multi_cases is set.2980 /// 0. multi_cases_len: u32 // If has_multi_cases is set.
src/print_zir.zig+2-4
...@@ -355,7 +355,7 @@ const Writer = struct {...@@ -355,7 +355,7 @@ const Writer = struct {
355 .array_type,355 .array_type,
356 => try self.writePlNodeBin(stream, inst),356 => try self.writePlNodeBin(stream, inst),
357357
358 .for_check_lens => try self.writePlNodeMultiOp(stream, inst),358 .for_len => try self.writePlNodeMultiOp(stream, inst),
359359
360 .elem_ptr_imm => try self.writeElemPtrImm(stream, inst),360 .elem_ptr_imm => try self.writeElemPtrImm(stream, inst),
361361
...@@ -888,9 +888,7 @@ const Writer = struct {...@@ -888,9 +888,7 @@ const Writer = struct {
888 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;888 const extra = self.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
889889
890 try self.writeInstRef(stream, extra.ptr);890 try self.writeInstRef(stream, extra.ptr);
891 try stream.print(", {d}", .{extra.bits.index});891 try stream.print(", {d}) ", .{extra.index});
892 try self.writeFlag(stream, ", manyptr", extra.bits.manyptr);
893 try stream.writeAll(") ");
894 try self.writeSrc(stream, inst_data.src());892 try self.writeSrc(stream, inst_data.src());
895 }893 }
896894