authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-12 10:45:37-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-08-12 10:48:54-07:00
log55c6a784a5bdf37c90cc9d8f55e9a86d396b8af4
tree617bd6b751f54fb946c4233b48d3fac0867674b9
parentfc55814faa8970cc373b7bbf8479c3bc3934fb44

stage2 frontend improvements - `@ptrCast` and optionals

* AstGen: use coerced_ty ResultLoc on array types and rely on Sema doing type coercion, to reduce the size of the ZIR for these instructions. * Sema: implement `@ptrCast`. * Sema: implement coercion from `T` to `?T` with an intermediate coercion rather than equality check.

2 files changed, 32 insertions(+), 15 deletions(-)

src/AstGen.zig+3-3
...@@ -2791,7 +2791,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Z...@@ -2791,7 +2791,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Z
2791 {2791 {
2792 return astgen.failNode(len_node, "unable to infer array size", .{});2792 return astgen.failNode(len_node, "unable to infer array size", .{});
2793 }2793 }
2794 const len = try expr(gz, scope, .{ .ty = .usize_type }, len_node);2794 const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node);
2795 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);2795 const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
27962796
2797 const result = try gz.addBin(.array_type, len, elem_type);2797 const result = try gz.addBin(.array_type, len, elem_type);
...@@ -2812,9 +2812,9 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.I...@@ -2812,9 +2812,9 @@ fn arrayTypeSentinel(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.I
2812 {2812 {
2813 return astgen.failNode(len_node, "unable to infer array size", .{});2813 return astgen.failNode(len_node, "unable to infer array size", .{});
2814 }2814 }
2815 const len = try expr(gz, scope, .{ .ty = .usize_type }, len_node);2815 const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node);
2816 const elem_type = try typeExpr(gz, scope, extra.elem_type);2816 const elem_type = try typeExpr(gz, scope, extra.elem_type);
2817 const sentinel = try expr(gz, scope, .{ .ty = elem_type }, extra.sentinel);2817 const sentinel = try expr(gz, scope, .{ .coerced_ty = elem_type }, extra.sentinel);
28182818
2819 const result = try gz.addArrayTypeSentinel(len, elem_type, sentinel);2819 const result = try gz.addArrayTypeSentinel(len, elem_type, sentinel);
2820 return rvalue(gz, rl, result, node);2820 return rvalue(gz, rl, result, node);
src/Sema.zig+29-12
...@@ -3026,9 +3026,9 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE...@@ -3026,9 +3026,9 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
3026 defer tracy.end();3026 defer tracy.end();
30273027
3028 const bin_inst = sema.code.instructions.items(.data)[inst].bin;3028 const bin_inst = sema.code.instructions.items(.data)[inst].bin;
3029 const len = try sema.resolveInstConst(block, .unneeded, bin_inst.lhs);3029 const len = try sema.resolveInt(block, .unneeded, bin_inst.lhs, Type.initTag(.usize));
3030 const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs);3030 const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs);
3031 const array_ty = try Module.arrayType(sema.arena, len.val.toUnsignedInt(), null, elem_type);3031 const array_ty = try Module.arrayType(sema.arena, len, null, elem_type);
30323032
3033 return sema.addType(array_ty);3033 return sema.addType(array_ty);
3034}3034}
...@@ -3038,11 +3038,13 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)...@@ -3038,11 +3038,13 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
3038 defer tracy.end();3038 defer tracy.end();
30393039
3040 const inst_data = sema.code.instructions.items(.data)[inst].array_type_sentinel;3040 const inst_data = sema.code.instructions.items(.data)[inst].array_type_sentinel;
3041 const len = try sema.resolveInstConst(block, .unneeded, inst_data.len);3041 const len = try sema.resolveInt(block, .unneeded, inst_data.len, Type.initTag(.usize));
3042 const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;3042 const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
3043 const sentinel = try sema.resolveInstConst(block, .unneeded, extra.sentinel);
3044 const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);3043 const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);
3045 const array_ty = try Module.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);3044 const uncasted_sentinel = sema.resolveInst(extra.sentinel);
3045 const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, .unneeded);
3046 const sentinel_val = try sema.resolveConstValue(block, .unneeded, sentinel);
3047 const array_ty = try Module.arrayType(sema.arena, len, sentinel_val, elem_type);
30463048
3047 return sema.addType(array_ty);3049 return sema.addType(array_ty);
3048}3050}
...@@ -6774,8 +6776,26 @@ fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile...@@ -6774,8 +6776,26 @@ fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile
67746776
6775fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6777fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
6776 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;6778 const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
6777 const src = inst_data.src();6779 const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
6778 return sema.mod.fail(&block.base, src, "TODO: Sema.zirPtrCast", .{});6780 const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
6781 const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
6782 const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
6783 const operand = sema.resolveInst(extra.rhs);
6784 const operand_ty = sema.typeOf(operand);
6785 if (operand_ty.zigTypeTag() != .Pointer) {
6786 return sema.mod.fail(&block.base, operand_src, "expected pointer, found {s} type '{}'", .{
6787 @tagName(operand_ty.zigTypeTag()), operand_ty,
6788 });
6789 }
6790 if (dest_ty.zigTypeTag() != .Pointer) {
6791 return sema.mod.fail(&block.base, dest_ty_src, "expected pointer, found {s} type '{}'", .{
6792 @tagName(dest_ty.zigTypeTag()), dest_ty,
6793 });
6794 }
6795 if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
6796 return sema.addConstant(dest_ty, val);
6797 }
6798 return block.addTyOp(.bitcast, dest_ty, operand);
6779}6799}
67806800
6781fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {6801fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -8151,11 +8171,8 @@ fn coerce(...@@ -8151,11 +8171,8 @@ fn coerce(
8151 // T to ?T8171 // T to ?T
8152 var buf: Type.Payload.ElemType = undefined;8172 var buf: Type.Payload.ElemType = undefined;
8153 const child_type = dest_type.optionalChild(&buf);8173 const child_type = dest_type.optionalChild(&buf);
8154 if (child_type.eql(inst_ty)) {8174 const intermediate = try sema.coerce(block, child_type, inst, inst_src);
8155 return sema.wrapOptional(block, dest_type, inst, inst_src);8175 return sema.wrapOptional(block, dest_type, intermediate, inst_src);
8156 } else if (try sema.coerceNum(block, child_type, inst, inst_src)) |some| {
8157 return sema.wrapOptional(block, dest_type, some, inst_src);
8158 }
8159 },8176 },
8160 .Pointer => {8177 .Pointer => {
8161 // Coercions where the source is a single pointer to an array.8178 // Coercions where the source is a single pointer to an array.