diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 864cd66d32d4..7227776efb35 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -1240,7 +1240,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { .return_type = return_type_inst, .param_types = param_types, }, .{}); - _ = try astgen.addZIRUnOp(self, &fn_type_scope.base, fn_src, .@"return", fn_type_inst); + _ = try astgen.addZIRUnOp(self, &fn_type_scope.base, fn_src, .ret_value, fn_type_inst); // We need the memory for the Type to go into the arena for the Decl var decl_arena = std.heap.ArenaAllocator.init(self.gpa); @@ -1309,7 +1309,7 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())) { const src = tree.token_locs[body_block.rbrace].start; - _ = try astgen.addZIRNoOp(self, &gen_scope.base, src, .returnvoid); + _ = try astgen.addZIRNoOp(self, &gen_scope.base, src, .@"return"); } const fn_zir = try gen_scope_arena.allocator.create(Fn.ZIR); diff --git a/src-self-hosted/astgen.zig b/src-self-hosted/astgen.zig index 3f08d1272d94..e2a3bf79cb16 100644 --- a/src-self-hosted/astgen.zig +++ b/src-self-hosted/astgen.zig @@ -457,18 +457,10 @@ fn ret(mod: *Module, scope: *Scope, cfe: *ast.Node.ControlFlowExpression) InnerE const tree = scope.tree(); const src = tree.token_locs[cfe.ltoken].start; if (cfe.getRHS()) |rhs_node| { - if (nodeMayNeedMemoryLocation(rhs_node)) { - const ret_ptr = try addZIRNoOp(mod, scope, src, .ret_ptr); - const operand = try expr(mod, scope, .{ .ptr = ret_ptr }, rhs_node); - return addZIRUnOp(mod, scope, src, .@"return", operand); - } else { - const fn_ret_ty = try addZIRNoOp(mod, scope, src, .ret_type); - const operand = try expr(mod, scope, .{ .ty = fn_ret_ty }, rhs_node); - return addZIRUnOp(mod, scope, src, .@"return", operand); - } - } else { - return addZIRNoOp(mod, scope, src, .returnvoid); + const result = try expr(mod, scope, .none, rhs_node); + _ = try addZIRUnOp(mod, scope, src, .ret_value, result); } + return addZIRNoOp(mod, scope, src, .@"return"); } fn identifier(mod: *Module, scope: *Scope, rl: ResultLoc, ident: *ast.Node.OneToken) InnerError!*zir.Inst { diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig index 2ea255bf7fb7..44ae0fc8d132 100644 --- a/src-self-hosted/codegen.zig +++ b/src-self-hosted/codegen.zig @@ -552,7 +552,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { .ptrtoint => return self.genPtrToInt(inst.castTag(.ptrtoint).?), .ref => return self.genRef(inst.castTag(.ref).?), .ret => return self.genRet(inst.castTag(.ret).?), - .retvoid => return self.genRetVoid(inst.castTag(.retvoid).?), + .ret_value => return self.genRetVal(inst.castTag(.ret_value).?), .store => return self.genStore(inst.castTag(.store).?), .sub => return self.genSub(inst.castTag(.sub).?), .unreach => return MCValue{ .unreach = {} }, @@ -1044,9 +1044,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { } } - fn ret(self: *Self, src: usize, mcv: MCValue) !MCValue { - const ret_ty = self.fn_type.fnReturnType(); - try self.setRegOrMem(src, ret_ty, self.ret_mcv, mcv); + fn genRet(self: *Self, inst: *ir.Inst.NoOp) !MCValue { switch (arch) { .i386 => { try self.code.append(0xc3); // ret @@ -1059,18 +1057,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { self.code.items[self.code.items.len - 5] = 0xe9; // jmp rel32 try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4); }, - else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}), + else => return self.fail(inst.base.src, "TODO implement return for {}", .{self.target.cpu.arch}), } return .unreach; } - fn genRet(self: *Self, inst: *ir.Inst.UnOp) !MCValue { + fn genRetVal(self: *Self, inst: *ir.Inst.UnOp) !MCValue { const operand = try self.resolveInst(inst.operand); - return self.ret(inst.base.src, operand); - } - - fn genRetVoid(self: *Self, inst: *ir.Inst.NoOp) !MCValue { - return self.ret(inst.base.src, .none); + const ret_ty = self.fn_type.fnReturnType(); + try self.setRegOrMem(inst.base.src, ret_ty, self.ret_mcv, operand); + return .unreach; } fn genCmp(self: *Self, inst: *ir.Inst.BinOp, op: math.CompareOperator) !MCValue { diff --git a/src-self-hosted/codegen/c.zig b/src-self-hosted/codegen/c.zig index 509491677a19..8cbe42003247 100644 --- a/src-self-hosted/codegen/c.zig +++ b/src-self-hosted/codegen/c.zig @@ -94,8 +94,7 @@ fn genFn(file: *C, decl: *Decl) !void { switch (inst.tag) { .assembly => try genAsm(file, inst.castTag(.assembly).?, decl), .call => try genCall(file, inst.castTag(.call).?, decl), - .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()), - .retvoid => try file.main.writer().print("return;", .{}), + .ret => try file.main.writer().print("return;", .{}), else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}), } } @@ -105,10 +104,6 @@ fn genFn(file: *C, decl: *Decl) !void { try writer.writeAll("}\n\n"); } -fn genRet(file: *C, inst: *Inst.UnOp, decl: *Decl, expected_return_type: Type) !void { - return file.fail(decl.src(), "TODO return {}", .{expected_return_type}); -} - fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { const writer = file.main.writer(); const header = file.header.writer(); diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig index deb0a91cec19..502ef85084ea 100644 --- a/src-self-hosted/ir.zig +++ b/src-self-hosted/ir.zig @@ -72,7 +72,7 @@ pub const Inst = struct { ptrtoint, ref, ret, - retvoid, + ret_value, /// Write a value to a pointer. LHS is pointer, RHS is value. store, sub, @@ -84,14 +84,13 @@ pub const Inst = struct { pub fn Type(tag: Tag) type { return switch (tag) { .alloc, - .retvoid, .unreach, .arg, .breakpoint, + .ret, => NoOp, .ref, - .ret, .bitcast, .not, .isnonnull, @@ -100,6 +99,7 @@ pub const Inst = struct { .floatcast, .intcast, .load, + .ret_value, => UnOp, .add, diff --git a/src-self-hosted/zir.zig b/src-self-hosted/zir.zig index 318c4bdc8eee..a345857c6b24 100644 --- a/src-self-hosted/zir.zig +++ b/src-self-hosted/zir.zig @@ -171,14 +171,12 @@ pub const Inst = struct { /// the memory location is in the stack frame, local to the scope containing the /// instruction. ref, - /// Obtains a pointer to the return value. - ret_ptr, /// Obtains the return type of the in-scope function. ret_type, - /// Sends control flow back to the function's callee. Takes an operand as the return value. + /// Sets the return value. + ret_value, + /// Sends control flow back to the function's callee. @"return", - /// Same as `return` but there is no operand; the operand is implicitly the void value. - returnvoid, /// Integer shift-left. Zeroes are shifted in from the right hand side. shl, /// Integer shift-right. Arithmetic or logical depending on the signedness of the integer type. @@ -211,17 +209,15 @@ pub const Inst = struct { return switch (tag) { .arg, .breakpoint, - .returnvoid, .alloc_inferred, - .ret_ptr, .ret_type, .unreach_nocheck, .@"unreachable", + .@"return", => NoOp, .boolnot, .deref, - .@"return", .isnull, .isnonnull, .ptrtoint, @@ -234,6 +230,7 @@ pub const Inst = struct { .typeof, .single_const_ptr_type, .single_mut_ptr_type, + .ret_value, => UnOp, .add, @@ -350,7 +347,7 @@ pub const Inst = struct { .primitive, .ptrtoint, .ref, - .ret_ptr, + .ret_value, .ret_type, .shl, .shr, @@ -369,7 +366,6 @@ pub const Inst = struct { .condbr, .compileerror, .@"return", - .returnvoid, .unreach_nocheck, .@"unreachable", => true, @@ -1842,10 +1838,10 @@ const EmitZIR = struct { .arg => try self.emitNoOp(inst.src, .arg), .breakpoint => try self.emitNoOp(inst.src, .breakpoint), .unreach => try self.emitNoOp(inst.src, .@"unreachable"), - .retvoid => try self.emitNoOp(inst.src, .returnvoid), + .ret => try self.emitNoOp(inst.src, .@"return"), + .ret_value => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret_value).?, .ret_value), .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot), - .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"), .ptrtoint => try self.emitUnOp(inst.src, new_body, inst.castTag(.ptrtoint).?, .ptrtoint), .isnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnull).?, .isnull), .isnonnull => try self.emitUnOp(inst.src, new_body, inst.castTag(.isnonnull).?, .isnonnull), diff --git a/src-self-hosted/zir_sema.zig b/src-self-hosted/zir_sema.zig index 6bd4159e36ee..39ddab8b7cd6 100644 --- a/src-self-hosted/zir_sema.zig +++ b/src-self-hosted/zir_sema.zig @@ -48,7 +48,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .ensure_result_used => return analyzeInstEnsureResultUsed(mod, scope, old_inst.castTag(.ensure_result_used).?), .ensure_result_non_error => return analyzeInstEnsureResultNonError(mod, scope, old_inst.castTag(.ensure_result_non_error).?), .ref => return analyzeInstRef(mod, scope, old_inst.castTag(.ref).?), - .ret_ptr => return analyzeInstRetPtr(mod, scope, old_inst.castTag(.ret_ptr).?), + .ret_value => return analyzeInstRetVal(mod, scope, old_inst.castTag(.ret_value).?), .ret_type => return analyzeInstRetType(mod, scope, old_inst.castTag(.ret_type).?), .single_const_ptr_type => return analyzeInstSingleConstPtrType(mod, scope, old_inst.castTag(.single_const_ptr_type).?), .single_mut_ptr_type => return analyzeInstSingleMutPtrType(mod, scope, old_inst.castTag(.single_mut_ptr_type).?), @@ -68,7 +68,6 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError! .@"unreachable" => return analyzeInstUnreachable(mod, scope, old_inst.castTag(.@"unreachable").?), .unreach_nocheck => return analyzeInstUnreachNoChk(mod, scope, old_inst.castTag(.unreach_nocheck).?), .@"return" => return analyzeInstRet(mod, scope, old_inst.castTag(.@"return").?), - .returnvoid => return analyzeInstRetVoid(mod, scope, old_inst.castTag(.returnvoid).?), .@"fn" => return analyzeInstFn(mod, scope, old_inst.castTag(.@"fn").?), .@"export" => return analyzeInstExport(mod, scope, old_inst.castTag(.@"export").?), .primitive => return analyzeInstPrimitive(mod, scope, old_inst.castTag(.primitive).?), @@ -115,7 +114,7 @@ pub fn analyzeBody(mod: *Module, scope: *Scope, body: zir.Module.Body) !void { pub fn analyzeBodyValueAsType(mod: *Module, block_scope: *Scope.Block, body: zir.Module.Body) !Type { try analyzeBody(mod, &block_scope.base, body); for (block_scope.instructions.items) |inst| { - if (inst.castTag(.ret)) |ret| { + if (inst.castTag(.ret_value)) |ret| { const val = try mod.resolveConstValue(&block_scope.base, ret.operand); return val.toType(); } else { @@ -296,8 +295,13 @@ fn analyzeInstCoerceToPtrElem(mod: *Module, scope: *Scope, inst: *zir.Inst.Coerc return mod.coerce(scope, ptr.ty.elemType(), operand); } -fn analyzeInstRetPtr(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { - return mod.fail(scope, inst.base.src, "TODO implement analyzeInstRetPtr", .{}); +fn analyzeInstRetVal(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { + const b = try mod.requireRuntimeBlock(scope, inst.base.src); + const operand = try resolveInst(mod, scope, inst.positionals.operand); + + // TODO analyze this into a store to .ret_ptr in callconv(.Unspecified) + // if the value is larger than pointer sized + return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret_value, operand); } fn analyzeInstRef(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { @@ -1091,15 +1095,9 @@ fn analyzeInstUnreachable(mod: *Module, scope: *Scope, unreach: *zir.Inst.NoOp) return mod.analyzeUnreach(scope, unreach.base.src); } -fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.UnOp) InnerError!*Inst { - const operand = try resolveInst(mod, scope, inst.positionals.operand); - const b = try mod.requireRuntimeBlock(scope, inst.base.src); - return mod.addUnOp(b, inst.base.src, Type.initTag(.noreturn), .ret, operand); -} - -fn analyzeInstRetVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { +fn analyzeInstRet(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst { const b = try mod.requireRuntimeBlock(scope, inst.base.src); - return mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .retvoid); + return try mod.addNoOp(b, inst.base.src, Type.initTag(.noreturn), .ret); } fn floatOpAllowed(tag: zir.Inst.Tag) bool { diff --git a/test/stage2/zir.zig b/test/stage2/zir.zig index f77c950052d9..3f4f074d2fbc 100644 --- a/test/stage2/zir.zig +++ b/test/stage2/zir.zig @@ -17,7 +17,7 @@ pub fn addCases(ctx: *TestContext) !void { \\@11 = export(@9, "entry") \\ \\@entry = fn(@fnty, { - \\ %11 = returnvoid() + \\ %11 = return() \\}) , \\@void = primitive(void) @@ -28,7 +28,7 @@ pub fn addCases(ctx: *TestContext) !void { \\@unnamed$5 = export(@unnamed$4, "entry") \\@unnamed$6 = fntype([], @void, cc=C) \\@entry = fn(@unnamed$6, { - \\ %0 = returnvoid() + \\ %0 = return() \\}) \\ ); @@ -58,7 +58,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ %expected = int(69) \\ %ok = cmp_eq(%result, %expected) \\ %10 = condbr(%ok, { - \\ %11 = returnvoid() + \\ %11 = return() \\ }, { \\ %12 = breakpoint() \\ }) @@ -75,7 +75,7 @@ pub fn addCases(ctx: *TestContext) !void { \\@3 = int(3) \\@unnamed$6 = fntype([], @void, cc=C) \\@entry = fn(@unnamed$6, { - \\ %0 = returnvoid() + \\ %0 = return() \\}) \\@entry__anon_1 = str("2\x08\x01\n") \\@9 = declref("9__anon_0") @@ -96,17 +96,17 @@ pub fn addCases(ctx: *TestContext) !void { \\ \\@entry = fn(@fnty, { \\ %0 = call(@a, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\ \\@a = fn(@fnty, { \\ %0 = call(@b, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\ \\@b = fn(@fnty, { \\ %0 = call(@a, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) , \\@void = primitive(void) @@ -118,17 +118,17 @@ pub fn addCases(ctx: *TestContext) !void { \\@unnamed$6 = fntype([], @void, cc=C) \\@entry = fn(@unnamed$6, { \\ %0 = call(@a, [], modifier=auto) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\@unnamed$8 = fntype([], @void, cc=C) \\@a = fn(@unnamed$8, { \\ %0 = call(@b, [], modifier=auto) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\@unnamed$10 = fntype([], @void, cc=C) \\@b = fn(@unnamed$10, { \\ %0 = call(@a, [], modifier=auto) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\ ); @@ -142,18 +142,18 @@ pub fn addCases(ctx: *TestContext) !void { \\ \\@entry = fn(@fnty, { \\ %0 = call(@a, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\ \\@a = fn(@fnty, { \\ %0 = call(@b, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\ \\@b = fn(@fnty, { \\ %9 = compileerror("message") \\ %0 = call(@a, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) , &[_][]const u8{ @@ -171,18 +171,18 @@ pub fn addCases(ctx: *TestContext) !void { \\@11 = export(@9, "entry") \\ \\@entry = fn(@fnty, { - \\ %0 = returnvoid() + \\ %0 = return() \\}) \\ \\@a = fn(@fnty, { \\ %0 = call(@b, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) \\ \\@b = fn(@fnty, { \\ %9 = compileerror("message") \\ %0 = call(@a, []) - \\ %1 = returnvoid() + \\ %1 = return() \\}) , \\@void = primitive(void) @@ -193,7 +193,7 @@ pub fn addCases(ctx: *TestContext) !void { \\@unnamed$5 = export(@unnamed$4, "entry") \\@unnamed$6 = fntype([], @void, cc=C) \\@entry = fn(@unnamed$6, { - \\ %0 = returnvoid() + \\ %0 = return() \\}) \\ );