AstGen: implement @bitCast for other result location types

This commit is contained in:
Andrew Kelley 2021-04-21 19:11:36 -07:00
parent 4cfea2fbd5
commit 570ed7b3bf
3 changed files with 29 additions and 16 deletions

View File

@ -1125,7 +1125,7 @@ pub fn structInitExpr(
}
return init_inst;
},
.ref => unreachable, // struct literal not valid as l-value
.ref => return astgen.failNode(node, "cannot take address of struct literal", .{}),
.ty => |ty_inst| {
if (struct_init.ast.type_expr == 0) {
return structInitExprRlTy(gz, scope, rl, node, struct_init, ty_inst);
@ -5819,7 +5819,7 @@ fn bitCast(
const astgen = gz.astgen;
const dest_type = try typeExpr(gz, scope, lhs);
switch (rl) {
.none, .discard, .ty => {
.none, .none_or_ref, .discard, .ty => {
const operand = try expr(gz, scope, .none, rhs);
const result = try gz.addPlNode(.bitcast, node, Zir.Inst.Bin{
.lhs = dest_type,
@ -5827,21 +5827,34 @@ fn bitCast(
});
return rvalue(gz, scope, rl, result, node);
},
.ref, .none_or_ref => unreachable, // `@bitCast` is not allowed as an r-value.
.ptr => |result_ptr| {
const casted_result_ptr = try gz.addUnNode(.bitcast_result_ptr, result_ptr, node);
return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs);
.ref => {
return astgen.failNode(node, "cannot take address of `@bitCast` result", .{});
},
.block_ptr => |block_ptr| {
return astgen.failNode(node, "TODO implement @bitCast with result location inferred peer types", .{});
.ptr, .inferred_ptr => |result_ptr| {
return bitCastRlPtr(gz, scope, rl, node, dest_type, result_ptr, rhs);
},
.inferred_ptr => |result_alloc| {
// TODO here we should be able to resolve the inference; we now have a type for the result.
return astgen.failNode(node, "TODO implement @bitCast with inferred-type result location pointer", .{});
.block_ptr => |block| {
return bitCastRlPtr(gz, scope, rl, node, dest_type, block.rl_ptr, rhs);
},
}
}
fn bitCastRlPtr(
gz: *GenZir,
scope: *Scope,
rl: ResultLoc,
node: ast.Node.Index,
dest_type: Zir.Inst.Ref,
result_ptr: Zir.Inst.Ref,
rhs: ast.Node.Index,
) InnerError!Zir.Inst.Ref {
const casted_result_ptr = try gz.addPlNode(.bitcast_result_ptr, node, Zir.Inst.Bin{
.lhs = dest_type,
.rhs = result_ptr,
});
return expr(gz, scope, .{ .ptr = casted_result_ptr }, rhs);
}
fn typeOf(
gz: *GenZir,
scope: *Scope,

View File

@ -641,9 +641,9 @@ fn resolveInstConst(
}
fn zirBitcastResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
const tracy = trace(@src());
defer tracy.end();
return sema.mod.fail(&block.base, sema.src, "TODO implement zir_sema.zirBitcastResultPtr", .{});
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
const src = inst_data.src();
return sema.mod.fail(&block.base, src, "TODO implement zir_sema.zirBitcastResultPtr", .{});
}
fn zirCoerceResultPtr(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {

View File

@ -196,7 +196,7 @@ pub const Inst = struct {
bitcast,
/// A typed result location pointer is bitcasted to a new result location pointer.
/// The new result location pointer has an inferred type.
/// Uses the un_node field.
/// Uses the pl_node field with payload `Bin`.
bitcast_result_ptr,
/// Bitwise NOT. `~`
/// Uses `un_node`.
@ -2329,7 +2329,6 @@ const Writer = struct {
.byte_swap,
.bit_reverse,
.elem_type,
.bitcast_result_ptr,
=> try self.writeUnNode(stream, inst),
.ref,
@ -2450,6 +2449,7 @@ const Writer = struct {
.reduce,
.atomic_load,
.bitcast,
.bitcast_result_ptr,
=> try self.writePlNodeBin(stream, inst),
.call,