authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-17 13:44:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-02-18 19:17:20-07:00
log841add6890d001d315591dc20f7d464c264d88bb
treeb2680e04e8e16c1ff52a317830c51398cc79c0bf
parentfaa44e2e5875036b105d8b7d38ccb2e93757a3c5

AstGen: finish multi-object for loops

This strategy uses pointer arithmetic to iterate through the loop. This has a problem, however, which is tuples. AstGen does not know whether a given indexable is a tuple or can be iterated based on contiguous memory. Tuples unlike other indexables cannot be represented as a many-item pointer that is incremented as the loop counter. So, after this commit, I will modify AstGen back closer to how @vexu had it before, using a counter and array element access.

4 files changed, 103 insertions(+), 88 deletions(-)

src/AstGen.zig+68-71
...@@ -88,6 +88,7 @@ fn setExtra(astgen: *AstGen, index: usize, extra: anytype) void {...@@ -88,6 +88,7 @@ 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)),
91 else => @compileError("bad field type"),92 else => @compileError("bad field type"),
92 };93 };
93 i += 1;94 i += 1;
...@@ -1565,7 +1566,9 @@ fn arrayInitExprRlPtrInner(...@@ -1565,7 +1566,9 @@ fn arrayInitExprRlPtrInner(
1565 for (elements) |elem_init, i| {1566 for (elements) |elem_init, i| {
1566 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{1567 const elem_ptr = try gz.addPlNode(.elem_ptr_imm, elem_init, Zir.Inst.ElemPtrImm{
1567 .ptr = result_ptr,1568 .ptr = result_ptr,
1568 .index = @intCast(u32, i),1569 .bits = .{
1570 .index = @intCast(u31, i),
1571 },
1569 });1572 });
1570 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;1573 astgen.extra.items[extra_index] = refToIndex(elem_ptr).?;
1571 extra_index += 1;1574 extra_index += 1;
...@@ -6308,7 +6311,7 @@ fn forExpr(...@@ -6308,7 +6311,7 @@ fn forExpr(
6308 const lens = try gpa.alloc(Zir.Inst.Ref, for_full.ast.inputs.len);6311 const lens = try gpa.alloc(Zir.Inst.Ref, for_full.ast.inputs.len);
6309 defer gpa.free(lens);6312 defer gpa.free(lens);
63106313
6311 const counter_alloc_tag: Zir.Inst.Tag = if (is_inline) .alloc_comptime_mut else .alloc;6314 const alloc_tag: Zir.Inst.Tag = if (is_inline) .alloc_comptime_mut else .alloc_mut;
63126315
6313 // Tracks the index of allocs/lens that has a length to be checked and is6316 // Tracks the index of allocs/lens that has a length to be checked and is
6314 // used for the end value.6317 // used for the end value.
...@@ -6321,23 +6324,24 @@ fn forExpr(...@@ -6321,23 +6324,24 @@ fn forExpr(
6321 var cond_end_val: Zir.Inst.Ref = .none;6324 var cond_end_val: Zir.Inst.Ref = .none;
63226325
6323 {6326 {
6324 var payload = for_full.payload_token;6327 var capture_token = for_full.payload_token;
6325 for (for_full.ast.inputs) |input, i_usize| {6328 for (for_full.ast.inputs) |input, i_usize| {
6326 const i = @intCast(u32, i_usize);6329 const i = @intCast(u32, i_usize);
6327 const payload_is_ref = token_tags[payload] == .asterisk;6330 const capture_is_ref = token_tags[capture_token] == .asterisk;
6328 const ident_tok = payload + @boolToInt(payload_is_ref);6331 const ident_tok = capture_token + @boolToInt(capture_is_ref);
63296332
6330 if (mem.eql(u8, tree.tokenSlice(ident_tok), "_") and payload_is_ref) {6333 if (mem.eql(u8, tree.tokenSlice(ident_tok), "_") and capture_is_ref) {
6331 return astgen.failTok(payload, "pointer modifier invalid on discard", .{});6334 return astgen.failTok(capture_token, "pointer modifier invalid on discard", .{});
6332 }6335 }
6333 payload = ident_tok + @as(u32, 2);6336 // Skip over the comma, and on to the next capture (or the ending pipe character).
6337 capture_token = ident_tok + 2;
63346338
6335 try emitDbgNode(parent_gz, input);6339 try emitDbgNode(parent_gz, input);
6336 if (node_tags[input] == .for_range) {6340 if (node_tags[input] == .for_range) {
6337 if (payload_is_ref) {6341 if (capture_is_ref) {
6338 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});6342 return astgen.failTok(ident_tok, "cannot capture reference to range", .{});
6339 }6343 }
6340 const counter_ptr = try parent_gz.addUnNode(counter_alloc_tag, .usize_type, node);6344 const counter_ptr = try parent_gz.addUnNode(alloc_tag, .usize_type, node);
6341 const start_node = node_data[input].lhs;6345 const start_node = node_data[input].lhs;
6342 const start_val = try expr(parent_gz, scope, .{ .rl = .none }, start_node);6346 const start_val = try expr(parent_gz, scope, .{ .rl = .none }, start_node);
6343 _ = try parent_gz.addBin(.store, counter_ptr, start_val);6347 _ = try parent_gz.addBin(.store, counter_ptr, start_val);
...@@ -6364,20 +6368,28 @@ fn forExpr(...@@ -6364,20 +6368,28 @@ fn forExpr(
6364 allocs[i] = counter_ptr;6368 allocs[i] = counter_ptr;
6365 lens[i] = range_len;6369 lens[i] = range_len;
6366 } else {6370 } else {
6367 const cond_ri: ResultInfo = .{ .rl = if (payload_is_ref) .ref else .none };6371 const indexable = try expr(parent_gz, scope, .{ .rl = .none }, input);
6368 const indexable = try expr(parent_gz, scope, cond_ri, input);6372 // This instruction has nice compile errors so we put it before the other ones
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);
6369 const base_ptr = try parent_gz.addPlNode(.elem_ptr_imm, input, Zir.Inst.ElemPtrImm{6375 const base_ptr = try parent_gz.addPlNode(.elem_ptr_imm, input, Zir.Inst.ElemPtrImm{
6370 .ptr = indexable,6376 .ptr = indexable,
6371 .index = 0,6377 .bits = .{
6378 .index = 0,
6379 .manyptr = true,
6380 },
6372 });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);
63736385
6374 if (end_input_index == null) {6386 if (end_input_index == null) {
6375 end_input_index = i;6387 end_input_index = i;
6376 assert(cond_end_val == .none);6388 assert(cond_end_val == .none);
6377 }6389 }
63786390
6379 allocs[i] = base_ptr;6391 allocs[i] = alloc;
6380 lens[i] = try parent_gz.addUnNode(.indexable_ptr_len, indexable, input);6392 lens[i] = ptr_len;
6381 }6393 }
6382 }6394 }
6383 }6395 }
...@@ -6467,62 +6479,47 @@ fn forExpr(...@@ -6467,62 +6479,47 @@ fn forExpr(
6467 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);6479 var then_scope = parent_gz.makeSubBlock(&cond_scope.base);
6468 defer then_scope.unstack();6480 defer then_scope.unstack();
64696481
6470 const then_sub_scope = &then_scope.base;6482 try then_scope.addDbgBlockBegin();
64716483
6472 // try then_scope.addDbgBlockBegin();6484 const capture_scopes = try gpa.alloc(Scope.LocalVal, for_full.ast.inputs.len);
6473 // var payload_val_scope: Scope.LocalVal = undefined;6485 defer gpa.free(capture_scopes);
6474 // var index_scope: Scope.LocalPtr = undefined;6486
6475 // const then_sub_scope = blk: {6487 const then_sub_scope = blk: {
6476 // const payload_token = for_full.payload_token.?;6488 var capture_token = for_full.payload_token;
6477 // const ident = if (token_tags[payload_token] == .asterisk)6489 var capture_sub_scope: *Scope = &then_scope.base;
6478 // payload_token + 16490 for (for_full.ast.inputs) |input, i_usize| {
6479 // else6491 const i = @intCast(u32, i_usize);
6480 // payload_token;6492 const capture_is_ref = token_tags[capture_token] == .asterisk;
6481 // const is_ptr = ident != payload_token;6493 const ident_tok = capture_token + @boolToInt(capture_is_ref);
6482 // const value_name = tree.tokenSlice(ident);6494 const capture_name = tree.tokenSlice(ident_tok);
6483 // var payload_sub_scope: *Scope = undefined;6495 // Skip over the comma, and on to the next capture (or the ending pipe character).
6484 // if (!mem.eql(u8, value_name, "_")) {6496 capture_token = ident_tok + 2;
6485 // const name_str_index = try astgen.identAsString(ident);6497
6486 // const tag: Zir.Inst.Tag = if (is_ptr) .elem_ptr else .elem_val;6498 if (mem.eql(u8, capture_name, "_")) continue;
6487 // const payload_inst = try then_scope.addPlNode(tag, for_full.ast.cond_expr, Zir.Inst.Bin{6499
6488 // .lhs = array_ptr,6500 const name_str_index = try astgen.identAsString(ident_tok);
6489 // .rhs = index,6501 try astgen.detectLocalShadowing(capture_sub_scope, name_str_index, ident_tok, capture_name, .capture);
6490 // });6502
6491 // try astgen.detectLocalShadowing(&then_scope.base, name_str_index, ident, value_name, .capture);6503 const loaded = if (capture_is_ref)
6492 // payload_val_scope = .{6504 loaded_ptrs[i]
6493 // .parent = &then_scope.base,6505 else
6494 // .gen_zir = &then_scope,6506 try then_scope.addUnNode(.load, loaded_ptrs[i], input);
6495 // .name = name_str_index,6507
6496 // .inst = payload_inst,6508 capture_scopes[i] = .{
6497 // .token_src = ident,6509 .parent = capture_sub_scope,
6498 // .id_cat = .capture,6510 .gen_zir = &then_scope,
6499 // };6511 .name = name_str_index,
6500 // try then_scope.addDbgVar(.dbg_var_val, name_str_index, payload_inst);6512 .inst = loaded,
6501 // payload_sub_scope = &payload_val_scope.base;6513 .token_src = ident_tok,
6502 // } else if (is_ptr) {6514 .id_cat = .capture,
6503 // } else {6515 };
6504 // payload_sub_scope = &then_scope.base;6516
6505 // }6517 try then_scope.addDbgVar(.dbg_var_val, name_str_index, loaded);
65066518 capture_sub_scope = &capture_scopes[i].base;
6507 // const index_token = if (token_tags[ident + 1] == .comma)6519 }
6508 // ident + 26520
6509 // else6521 break :blk capture_sub_scope;
6510 // break :blk payload_sub_scope;6522 };
6511 // const token_bytes = tree.tokenSlice(index_token);
6512 // const index_name = try astgen.identAsString(index_token);
6513 // try astgen.detectLocalShadowing(payload_sub_scope, index_name, index_token, token_bytes, .@"loop index capture");
6514 // index_scope = .{
6515 // .parent = payload_sub_scope,
6516 // .gen_zir = &then_scope,
6517 // .name = index_name,
6518 // .ptr = index_ptr,
6519 // .token_src = index_token,
6520 // .maybe_comptime = is_inline,
6521 // .id_cat = .@"loop index capture",
6522 // };
6523 // try then_scope.addDbgVar(.dbg_var_val, index_name, index_ptr);
6524 // break :blk &index_scope.base;
6525 // };
65266523
6527 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr);6524 const then_result = try expr(&then_scope, then_sub_scope, .{ .rl = .none }, for_full.ast.then_expr);
6528 _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr);6525 _ = try addEnsureResult(&then_scope, then_result, for_full.ast.then_expr);
src/Sema.zig+22-15
...@@ -9649,7 +9649,7 @@ fn zirElemPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air...@@ -9649,7 +9649,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;9649 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
9650 const array_ptr = try sema.resolveInst(extra.lhs);9650 const array_ptr = try sema.resolveInst(extra.lhs);
9651 const elem_index = try sema.resolveInst(extra.rhs);9651 const elem_index = try sema.resolveInst(extra.rhs);
9652 return sema.elemPtr(block, src, array_ptr, elem_index, src, false);9652 return sema.elemPtr(block, src, array_ptr, elem_index, src, false, .One);
9653}9653}
96549654
9655fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9655fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9662,7 +9662,7 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError...@@ -9662,7 +9662,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;9662 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
9663 const array_ptr = try sema.resolveInst(extra.lhs);9663 const array_ptr = try sema.resolveInst(extra.lhs);
9664 const elem_index = try sema.resolveInst(extra.rhs);9664 const elem_index = try sema.resolveInst(extra.rhs);
9665 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false);9665 return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, .One);
9666}9666}
96679667
9668fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9668fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -9673,8 +9673,9 @@ fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!...@@ -9673,8 +9673,9 @@ fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!
9673 const src = inst_data.src();9673 const src = inst_data.src();
9674 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;9674 const extra = sema.code.extraData(Zir.Inst.ElemPtrImm, inst_data.payload_index).data;
9675 const array_ptr = try sema.resolveInst(extra.ptr);9675 const array_ptr = try sema.resolveInst(extra.ptr);
9676 const elem_index = try sema.addIntUnsigned(Type.usize, extra.index);9676 const elem_index = try sema.addIntUnsigned(Type.usize, extra.bits.index);
9677 return sema.elemPtr(block, src, array_ptr, elem_index, src, true);9677 const size: std.builtin.Type.Pointer.Size = if (extra.bits.manyptr) .Many else .One;
9678 return sema.elemPtr(block, src, array_ptr, elem_index, src, true, size);
9678}9679}
96799680
9680fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {9681fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -22905,7 +22906,7 @@ fn panicSentinelMismatch(...@@ -22905,7 +22906,7 @@ fn panicSentinelMismatch(
22905 const actual_sentinel = if (ptr_ty.isSlice())22906 const actual_sentinel = if (ptr_ty.isSlice())
22906 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)22907 try parent_block.addBinOp(.slice_elem_val, ptr, sentinel_index)
22907 else blk: {22908 else blk: {
22908 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null);22909 const elem_ptr_ty = try sema.elemPtrType(ptr_ty, null, .One);
22909 const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty);22910 const sentinel_ptr = try parent_block.addPtrElemPtr(ptr, sentinel_index, elem_ptr_ty);
22910 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);22911 break :blk try parent_block.addTyOp(.load, sentinel_ty, sentinel_ptr);
22911 };22912 };
...@@ -24072,6 +24073,7 @@ fn elemPtr(...@@ -24072,6 +24073,7 @@ fn elemPtr(
24072 elem_index: Air.Inst.Ref,24073 elem_index: Air.Inst.Ref,
24073 elem_index_src: LazySrcLoc,24074 elem_index_src: LazySrcLoc,
24074 init: bool,24075 init: bool,
24076 size: std.builtin.Type.Pointer.Size,
24075) CompileError!Air.Inst.Ref {24077) CompileError!Air.Inst.Ref {
24076 const indexable_ptr_src = src; // TODO better source location24078 const indexable_ptr_src = src; // TODO better source location
24077 const indexable_ptr_ty = sema.typeOf(indexable_ptr);24079 const indexable_ptr_ty = sema.typeOf(indexable_ptr);
...@@ -24098,13 +24100,12 @@ fn elemPtr(...@@ -24098,13 +24100,12 @@ fn elemPtr(
24098 const index_val = maybe_index_val orelse break :rs elem_index_src;24100 const index_val = maybe_index_val orelse break :rs elem_index_src;
24099 const index = @intCast(usize, index_val.toUnsignedInt(target));24101 const index = @intCast(usize, index_val.toUnsignedInt(target));
24100 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);24102 const elem_ptr = try ptr_val.elemPtr(indexable_ty, sema.arena, index, sema.mod);
24101 const result_ty = try sema.elemPtrType(indexable_ty, index);24103 const elem_ptr_ty = try sema.elemPtrType(indexable_ty, index, size);
24102 return sema.addConstant(result_ty, elem_ptr);24104 return sema.addConstant(elem_ptr_ty, elem_ptr);
24103 };24105 };
24104 const result_ty = try sema.elemPtrType(indexable_ty, null);24106 const elem_ptr_ty = try sema.elemPtrType(indexable_ty, null, size);
24105
24106 try sema.requireRuntimeBlock(block, src, runtime_src);24107 try sema.requireRuntimeBlock(block, src, runtime_src);
24107 return block.addPtrElemPtr(indexable, elem_index, result_ty);24108 return block.addPtrElemPtr(indexable, elem_index, elem_ptr_ty);
24108 },24109 },
24109 .One => {24110 .One => {
24110 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable24111 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable
...@@ -24166,7 +24167,7 @@ fn elemVal(...@@ -24166,7 +24167,7 @@ fn elemVal(
24166 },24167 },
24167 .One => {24168 .One => {
24168 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable24169 assert(indexable_ty.childType().zigTypeTag() == .Array); // Guaranteed by isIndexable
24169 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false);24170 const elem_ptr = try sema.elemPtr(block, indexable_src, indexable, elem_index, elem_index_src, false, .One);
24170 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);24171 return sema.analyzeLoad(block, indexable_src, elem_ptr, elem_index_src);
24171 },24172 },
24172 },24173 },
...@@ -24404,7 +24405,7 @@ fn elemPtrArray(...@@ -24404,7 +24405,7 @@ fn elemPtrArray(
24404 break :o index;24405 break :o index;
24405 } else null;24406 } else null;
2440624407
24407 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset);24408 const elem_ptr_ty = try sema.elemPtrType(array_ptr_ty, offset, .One);
2440824409
24409 if (maybe_undef_array_ptr_val) |array_ptr_val| {24410 if (maybe_undef_array_ptr_val) |array_ptr_val| {
24410 if (array_ptr_val.isUndef()) {24411 if (array_ptr_val.isUndef()) {
...@@ -24509,7 +24510,7 @@ fn elemPtrSlice(...@@ -24509,7 +24510,7 @@ fn elemPtrSlice(
24509 break :o index;24510 break :o index;
24510 } else null;24511 } else null;
2451124512
24512 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset);24513 const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset, .One);
2451324514
24514 if (maybe_undef_slice_val) |slice_val| {24515 if (maybe_undef_slice_val) |slice_val| {
24515 if (slice_val.isUndef()) {24516 if (slice_val.isUndef()) {
...@@ -26239,7 +26240,7 @@ fn storePtr2(...@@ -26239,7 +26240,7 @@ fn storePtr2(
26239 const elem_src = operand_src; // TODO better source location26240 const elem_src = operand_src; // TODO better source location
26240 const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i);26241 const elem = try sema.tupleField(block, operand_src, uncasted_operand, elem_src, i);
26241 const elem_index = try sema.addIntUnsigned(Type.usize, i);26242 const elem_index = try sema.addIntUnsigned(Type.usize, i);
26242 const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false);26243 const elem_ptr = try sema.elemPtr(block, ptr_src, ptr, elem_index, elem_src, false, .One);
26243 try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store);26244 try sema.storePtr2(block, src, elem_ptr, elem_src, elem, elem_src, .store);
26244 }26245 }
26245 return;26246 return;
...@@ -33276,7 +33277,12 @@ fn compareVector(...@@ -33276,7 +33277,12 @@ fn compareVector(
33276/// For []T, returns *T33277/// For []T, returns *T
33277/// Handles const-ness and address spaces in particular.33278/// Handles const-ness and address spaces in particular.
33278/// This code is duplicated in `analyzePtrArithmetic`.33279/// This code is duplicated in `analyzePtrArithmetic`.
33279fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {33280fn elemPtrType(
33281 sema: *Sema,
33282 ptr_ty: Type,
33283 offset: ?usize,
33284 size: std.builtin.Type.Pointer.Size,
33285) !Type {
33280 const ptr_info = ptr_ty.ptrInfo().data;33286 const ptr_info = ptr_ty.ptrInfo().data;
33281 const elem_ty = ptr_ty.elemType2();33287 const elem_ty = ptr_ty.elemType2();
33282 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;33288 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;
...@@ -33321,6 +33327,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {...@@ -33321,6 +33327,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
33321 break :a new_align;33327 break :a new_align;
33322 };33328 };
33323 return try Type.ptr(sema.arena, sema.mod, .{33329 return try Type.ptr(sema.arena, sema.mod, .{
33330 .size = size,
33324 .pointee_type = elem_ty,33331 .pointee_type = elem_ty,
33325 .mutable = ptr_info.mutable,33332 .mutable = ptr_info.mutable,
33326 .@"addrspace" = ptr_info.@"addrspace",33333 .@"addrspace" = ptr_info.@"addrspace",
src/Zir.zig+10-1
...@@ -79,6 +79,7 @@ pub fn extraData(code: Zir, comptime T: type, index: usize) struct { data: T, en...@@ -79,6 +79,7 @@ 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]),
82 else => @compileError("bad field type"),83 else => @compileError("bad field type"),
83 };84 };
84 i += 1;85 i += 1;
...@@ -388,6 +389,8 @@ pub const Inst = struct {...@@ -388,6 +389,8 @@ pub const Inst = struct {
388 /// as a reference to another ZIR instruction.389 /// as a reference to another ZIR instruction.
389 /// Uses the `pl_node` union field. AST node is an element inside array initialization390 /// Uses the `pl_node` union field. AST node is an element inside array initialization
390 /// syntax. Payload is `ElemPtrImm`.391 /// syntax. Payload is `ElemPtrImm`.
392 /// This instruction has a way to set the result type to be a
393 /// single-pointer or a many-pointer.
391 elem_ptr_imm,394 elem_ptr_imm,
392 /// Given an array, slice, or pointer, returns the element at the provided index.395 /// Given an array, slice, or pointer, returns the element at the provided index.
393 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.396 /// Uses the `pl_node` union field. AST node is a[b] syntax. Payload is `Bin`.
...@@ -2972,7 +2975,13 @@ pub const Inst = struct {...@@ -2972,7 +2975,13 @@ pub const Inst = struct {
29722975
2973 pub const ElemPtrImm = struct {2976 pub const ElemPtrImm = struct {
2974 ptr: Ref,2977 ptr: Ref,
2975 index: u32,2978 bits: Bits,
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 };
2976 };2985 };
29772986
2978 /// 0. multi_cases_len: u32 // If has_multi_cases is set.2987 /// 0. multi_cases_len: u32 // If has_multi_cases is set.
src/print_zir.zig+3-1
...@@ -888,7 +888,9 @@ const Writer = struct {...@@ -888,7 +888,9 @@ 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.index});891 try stream.print(", {d}", .{extra.bits.index});
892 try self.writeFlag(stream, ", manyptr", extra.bits.manyptr);
893 try stream.writeAll(") ");
892 try self.writeSrc(stream, inst_data.src());894 try self.writeSrc(stream, inst_data.src());
893 }895 }
894896