Commit 570ed7b3bf

Andrew Kelley <andrew@ziglang.org>
2021-04-22 04:11:36
AstGen: implement `@bitCast` for other result location types
1 parent 4cfea2f
Changed files (3)
src/AstGen.zig
@@ -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,
src/Sema.zig
@@ -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 {
src/Zir.zig
@@ -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,