-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
stage2: remove operand from return instruction #5951
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
Comment on lines
-460
to
-470
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see what you're going for here, and I like it. I was thinking along the same lines of removing the operand from the return instruction. However I think we still need a "Set the return value" instruction which will happen in the else branch here. For an explanation of why see the review comments in codegen.zig on the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Consider: fn hello(cond: bool) T {
return if (cond) foo() else bar();
} Intended semantics are: the result location of I think the |
||
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 { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing a "set return value to void" instruction, which would be necessary for the "expected T, found void" compile error (when one forgets to return a value). I think we should keep the existing
returnvoid
instruction as well as the "return with an operand" instruction, and what this branch can do is add an additional "set the return value" instruction and "return control flow assuming the return value has already been set".Idea being that we can have IR instructions with overlapping responsibilities; it's easy to have them call the appropriate functions during semantic analysis. This is in the effort of lowering memory usage; adding another enum tag to
ir.Inst.Tag
is free, so we may as well minimize the data we are allocating for these instructions.However another observation is that once we do defers, it would make sense to have one canonical "exit the function" path from any scope. I think we should actually remove the return control flow instruction.
So, here's my proposal:
set_ret_val
instruction, which does no control flow.set_ret_void
instruction. Same asset_ret_val
but the operand is assumed to be the void value. (This is simply to reduce memory usage)return
andreturnvoid
instructions.There would be no more return control flow logic. It would be implied at the end of the main outer block of a function, and early-return control flow would be managed with breaks. I think this would work well with how to codegen defer expressions. Note, however, that the return value would either be set with
ret_ptr
and writing through the pointer, orset_ret_val
directly.The astgen for
return
syntax will need to change, to use a combination of the "break" and "set_ret_val" instructions rather than emitting the now-deleted "return" control flow instruction.