| author | |
| committer | |
| log | 841add6890d001d315591dc20f7d464c264d88bb |
| tree | b2680e04e8e16c1ff52a317830c51398cc79c0bf |
| parent | faa44e2e5875036b105d8b7d38ccb2e93757a3c5 |
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); |
| 6310 | 6313 | ||
| 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; |
| 6312 | 6315 | ||
| 6313 | // Tracks the index of allocs/lens that has a length to be checked and is | 6316 | // 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; |
| 6322 | 6325 | ||
| 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); |
| 6329 | 6332 | ||
| 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; | ||
| 6334 | 6338 | ||
| 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); | ||
| 6373 | 6385 | ||
| 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 | } |
| 6378 | 6390 | ||
| 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(); |
| 6469 | 6481 | ||
| 6470 | const then_sub_scope = &then_scope.base; | 6482 | try then_scope.addDbgBlockBegin(); |
| 6471 | 6483 | ||
| 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 + 1 | 6490 | for (for_full.ast.inputs) |input, i_usize| { |
| 6479 | // else | 6491 | 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); |
| 6506 | 6518 | capture_sub_scope = &capture_scopes[i].base; | |
| 6507 | // const index_token = if (token_tags[ident + 1] == .comma) | 6519 | } |
| 6508 | // ident + 2 | 6520 | |
| 6509 | // else | 6521 | 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 | // }; | ||
| 6526 | 6523 | ||
| 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 | } |
| 9654 | 9654 | ||
| 9655 | fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 9655 | fn 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 | } |
| 9667 | 9667 | ||
| 9668 | fn zirElemPtrImm(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 9668 | fn 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 | } |
| 9679 | 9680 | ||
| 9680 | fn zirSliceStart(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 9681 | fn 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 location | 24078 | 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 isIndexable | 24111 | 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 isIndexable | 24169 | 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; |
| 24406 | 24407 | ||
| 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); |
| 24408 | 24409 | ||
| 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; |
| 24511 | 24512 | ||
| 24512 | const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset); | 24513 | const elem_ptr_ty = try sema.elemPtrType(slice_ty, offset, .One); |
| 24513 | 24514 | ||
| 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 location | 26240 | 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 *T | 33277 | /// 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`. |
| 33279 | fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type { | 33280 | fn 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 initialization | 390 | /// 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 { |
| 2972 | 2975 | ||
| 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 | }; |
| 2977 | 2986 | ||
| 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; |
| 889 | 889 | ||
| 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 | } |
| 894 | 896 |