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/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 7956689122..f2f7f8a81f 100644 --- a/test/behavior/decl_literals.zig +++ b/test/behavior/decl_literals.zig @@ -12,6 +12,54 @@ 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_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, 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 {