From 0329b8387ce53574c42565322c191e7cc30eb3f7 Mon Sep 17 00:00:00 2001 From: xdBronch <51252236+xdBronch@users.noreply.github.com> Date: Thu, 12 Sep 2024 11:25:40 -0400 Subject: [PATCH 1/2] make decl literals work with single item pointers --- src/Sema.zig | 1 + test/behavior/decl_literals.zig | 49 +++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 0a609ff0f4..61501fa455 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8996,6 +8996,7 @@ fn zirDeclLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index, do_coerce: b while (true) switch (ty.zigTypeTag(zcu)) { .error_union => ty = ty.errorUnionPayload(zcu), .optional => ty = ty.optionalChild(zcu), + .pointer => ty = if (ty.isSinglePointer(zcu)) ty.childType(zcu) else break, .enum_literal, .error_set => { // Treat this as a normal enum literal. break :res Air.internedToRef(try pt.intern(.{ .enum_literal = name })); diff --git a/test/behavior/decl_literals.zig b/test/behavior/decl_literals.zig index 7956689122..b5961c2c13 100644 --- a/test/behavior/decl_literals.zig +++ b/test/behavior/decl_literals.zig @@ -12,6 +12,55 @@ test "decl literal" { try expect(val.x == 123); } +test "decl literal with optional" { + const S = struct { + x: u32, + const foo: ?@This() = .{ .x = 123 }; + }; + + const val: ?S = .foo; + try expect(val.?.x == 123); +} + +test "decl literal with pointer" { + const S = struct { + x: u32, + const foo: *const @This() = &.{ .x = 123 }; + }; + + const val: *const S = .foo; + try expect(val.x == 123); +} + +test "call decl literal with optional" { + if (builtin.zig_backend == .stage2_riscv64 or + builtin.zig_backend == .stage2_sparc64 or + builtin.zig_backend == .stage2_arm or + builtin.zig_backend == .stage2_aarch64 or + builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO + const S = struct { + x: u32, + fn init() ?@This() { + return .{ .x = 123 }; + } + }; + + const val: ?S = .init(); + try expect(val.?.x == 123); +} + +test "call decl literal with pointer" { + const S = struct { + x: u32, + fn init() *const @This() { + return &.{ .x = 123 }; + } + }; + + const val: *const S = .init(); + try expect(val.x == 123); +} + test "call decl literal" { const S = struct { x: u32, From bc161430b0006386ae19c51cfc574b5d8f8fef6e Mon Sep 17 00:00:00 2001 From: David Rubin Date: Thu, 12 Sep 2024 17:05:48 -0700 Subject: [PATCH 2/2] riscv: implement `optional_payload_ptr_set` --- src/arch/riscv64/CodeGen.zig | 32 +++++++++++++++++++++++++++++++- test/behavior/cast.zig | 1 - test/behavior/decl_literals.zig | 3 +-- test/behavior/optional.zig | 1 - test/behavior/struct.zig | 3 --- test/behavior/union.zig | 1 - 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index f887c6cb13..0c6da840eb 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -3364,8 +3364,38 @@ fn airOptionalPayloadPtr(func: *Func, inst: Air.Inst.Index) !void { } fn airOptionalPayloadPtrSet(func: *Func, inst: Air.Inst.Index) !void { + const zcu = func.pt.zcu; + const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; - const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else return func.fail("TODO implement .optional_payload_ptr_set for {}", .{func.target.cpu.arch}); + const result: MCValue = if (func.liveness.isUnused(inst)) .unreach else result: { + const dst_ty = func.typeOfIndex(inst); + const src_ty = func.typeOf(ty_op.operand); + const opt_ty = src_ty.childType(zcu); + const src_mcv = try func.resolveInst(ty_op.operand); + + if (opt_ty.optionalReprIsPayload(zcu)) { + break :result if (func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) + src_mcv + else + try func.copyToNewRegister(inst, src_mcv); + } + + const dst_mcv: MCValue = if (src_mcv.isRegister() and + func.reuseOperand(inst, ty_op.operand, 0, src_mcv)) + src_mcv + else + try func.copyToNewRegister(inst, src_mcv); + + const pl_ty = dst_ty.childType(zcu); + const pl_abi_size: i32 = @intCast(pl_ty.abiSize(zcu)); + try func.genSetMem( + .{ .reg = dst_mcv.getReg().? }, + pl_abi_size, + Type.bool, + .{ .immediate = 1 }, + ); + break :result dst_mcv; + }; return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); } diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index b414977ad6..7dca19d212 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -1875,7 +1875,6 @@ test "peer type resolution: vector and optional vector" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; var a: ?@Vector(3, u32) = .{ 0, 1, 2 }; var b: @Vector(3, u32) = .{ 3, 4, 5 }; diff --git a/test/behavior/decl_literals.zig b/test/behavior/decl_literals.zig index b5961c2c13..f2f7f8a81f 100644 --- a/test/behavior/decl_literals.zig +++ b/test/behavior/decl_literals.zig @@ -33,8 +33,7 @@ test "decl literal with pointer" { } test "call decl literal with optional" { - if (builtin.zig_backend == .stage2_riscv64 or - builtin.zig_backend == .stage2_sparc64 or + if (builtin.zig_backend == .stage2_sparc64 or builtin.zig_backend == .stage2_arm or builtin.zig_backend == .stage2_aarch64 or builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // TODO diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index 53738a107b..967bc8cf85 100644 --- a/test/behavior/optional.zig +++ b/test/behavior/optional.zig @@ -320,7 +320,6 @@ test "coerce an anon struct literal to optional struct" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { const Struct = struct { diff --git a/test/behavior/struct.zig b/test/behavior/struct.zig index 4694758e19..989da34ae7 100644 --- a/test/behavior/struct.zig +++ b/test/behavior/struct.zig @@ -1165,7 +1165,6 @@ test "anon init through error unions and optionals" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { a: u32, @@ -1193,7 +1192,6 @@ test "anon init through optional" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { a: u32, @@ -1503,7 +1501,6 @@ test "no dependency loop on pointer to optional struct" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { const A = struct { b: B }; diff --git a/test/behavior/union.zig b/test/behavior/union.zig index 9938c3c045..b0209c124e 100644 --- a/test/behavior/union.zig +++ b/test/behavior/union.zig @@ -1268,7 +1268,6 @@ test "extern union most-aligned field is smaller" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const U = extern union { in6: extern struct {