aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-08-12 10:45:37 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-08-12 10:48:54 -0700
commit55c6a784a5bdf37c90cc9d8f55e9a86d396b8af4 (patch)
tree617bd6b751f54fb946c4233b48d3fac0867674b9
parentfc55814faa8970cc373b7bbf8479c3bc3934fb44 (diff)
downloadzig-55c6a784a5bdf37c90cc9d8f55e9a86d396b8af4.tar.gz
zig-55c6a784a5bdf37c90cc9d8f55e9a86d396b8af4.zip
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.
-rw-r--r--src/AstGen.zig6
-rw-r--r--src/Sema.zig41
2 files changed, 32 insertions, 15 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index ae37866b97..e3f33ec332 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -2791,7 +2791,7 @@ fn arrayType(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) !Z
{
return astgen.failNode(len_node, "unable to infer array size", .{});
}
- const len = try expr(gz, scope, .{ .ty = .usize_type }, len_node);
+ const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node);
const elem_type = try typeExpr(gz, scope, node_datas[node].rhs);
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
{
return astgen.failNode(len_node, "unable to infer array size", .{});
}
- const len = try expr(gz, scope, .{ .ty = .usize_type }, len_node);
+ const len = try expr(gz, scope, .{ .coerced_ty = .usize_type }, len_node);
const elem_type = try typeExpr(gz, scope, extra.elem_type);
- const sentinel = try expr(gz, scope, .{ .ty = elem_type }, extra.sentinel);
+ const sentinel = try expr(gz, scope, .{ .coerced_ty = elem_type }, extra.sentinel);
const result = try gz.addArrayTypeSentinel(len, elem_type, sentinel);
return rvalue(gz, rl, result, node);
diff --git a/src/Sema.zig b/src/Sema.zig
index a24ae97a4e..0813f749e2 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -3026,9 +3026,9 @@ fn zirArrayType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileE
defer tracy.end();
const bin_inst = sema.code.instructions.items(.data)[inst].bin;
- const len = try sema.resolveInstConst(block, .unneeded, bin_inst.lhs);
+ const len = try sema.resolveInt(block, .unneeded, bin_inst.lhs, Type.initTag(.usize));
const elem_type = try sema.resolveType(block, .unneeded, bin_inst.rhs);
- const array_ty = try Module.arrayType(sema.arena, len.val.toUnsignedInt(), null, elem_type);
+ const array_ty = try Module.arrayType(sema.arena, len, null, elem_type);
return sema.addType(array_ty);
}
@@ -3038,11 +3038,13 @@ fn zirArrayTypeSentinel(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index)
defer tracy.end();
const inst_data = sema.code.instructions.items(.data)[inst].array_type_sentinel;
- const len = try sema.resolveInstConst(block, .unneeded, inst_data.len);
+ const len = try sema.resolveInt(block, .unneeded, inst_data.len, Type.initTag(.usize));
const extra = sema.code.extraData(Zir.Inst.ArrayTypeSentinel, inst_data.payload_index).data;
- const sentinel = try sema.resolveInstConst(block, .unneeded, extra.sentinel);
const elem_type = try sema.resolveType(block, .unneeded, extra.elem_type);
- const array_ty = try Module.arrayType(sema.arena, len.val.toUnsignedInt(), sentinel.val, elem_type);
+ const uncasted_sentinel = sema.resolveInst(extra.sentinel);
+ const sentinel = try sema.coerce(block, elem_type, uncasted_sentinel, .unneeded);
+ const sentinel_val = try sema.resolveConstValue(block, .unneeded, sentinel);
+ const array_ty = try Module.arrayType(sema.arena, len, sentinel_val, elem_type);
return sema.addType(array_ty);
}
@@ -6774,8 +6776,26 @@ fn zirErrSetCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) Compile
fn zirPtrCast(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
- const src = inst_data.src();
- return sema.mod.fail(&block.base, src, "TODO: Sema.zirPtrCast", .{});
+ const dest_ty_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg1 = inst_data.src_node };
+ const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
+ const dest_ty = try sema.resolveType(block, dest_ty_src, extra.lhs);
+ const operand = sema.resolveInst(extra.rhs);
+ const operand_ty = sema.typeOf(operand);
+ if (operand_ty.zigTypeTag() != .Pointer) {
+ return sema.mod.fail(&block.base, operand_src, "expected pointer, found {s} type '{}'", .{
+ @tagName(operand_ty.zigTypeTag()), operand_ty,
+ });
+ }
+ if (dest_ty.zigTypeTag() != .Pointer) {
+ return sema.mod.fail(&block.base, dest_ty_src, "expected pointer, found {s} type '{}'", .{
+ @tagName(dest_ty.zigTypeTag()), dest_ty,
+ });
+ }
+ if (try sema.resolveMaybeUndefVal(block, operand_src, operand)) |val| {
+ return sema.addConstant(dest_ty, val);
+ }
+ return block.addTyOp(.bitcast, dest_ty, operand);
}
fn zirTruncate(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
@@ -8151,11 +8171,8 @@ fn coerce(
// T to ?T
var buf: Type.Payload.ElemType = undefined;
const child_type = dest_type.optionalChild(&buf);
- if (child_type.eql(inst_ty)) {
- return sema.wrapOptional(block, dest_type, inst, inst_src);
- } else if (try sema.coerceNum(block, child_type, inst, inst_src)) |some| {
- return sema.wrapOptional(block, dest_type, some, inst_src);
- }
+ const intermediate = try sema.coerce(block, child_type, inst, inst_src);
+ return sema.wrapOptional(block, dest_type, intermediate, inst_src);
},
.Pointer => {
// Coercions where the source is a single pointer to an array.