Skip to content
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

Remove param_refs and implicit_param_refs #4479

Open
wants to merge 11 commits into
base: trunk
Choose a base branch
from

Conversation

geoffromer
Copy link
Contributor

@geoffromer geoffromer commented Nov 4, 2024

This introduces calling_convention_param_ids, a single block that consolidates all the information that was being used by consumers of param_refs and implicit_param_refs, in a form that's easier to produce and typically easier to consume.

See also this Discord discussion regarding the decision to keep the return slot last in the SemIR calling convention, even though it goes first in the LLVM calling convention.

Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the PR description have some more explanation, like a link to the discussion about this and a mention of what it's being replaced with?

@@ -97,18 +97,14 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
struct CalleeParamsInfo {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to note, #4452 is now merged

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect the merge conflicts to be pretty straightforward, but I can do the merge during the review instead of the end if you like.

Comment on lines 104 to 111
// A block containing, for each calling convention parameter (including the
// return slot), a reference to the instruction in the function's declaration
// block that represents that parameter. These instructions will be in the
// `AnyParam` category. This is not populated on imported entities, because it
// is relevant only for the function definition.
// TODO: can this be moved to `Function`, since it is not applicable to other
// kinds of entities?
InstBlockId calling_convention_params_id;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@zygoloid Can you just confirm that this is what you're expecting?

Copy link
Contributor

@jonmeow jonmeow Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to note, one thing I'd particularly want to be sure of is that you both understand what "calling convention parameter" is, that it's a term I'm just not familiar with. To me, that sounds distinctly qualified from "implicit" or "explicit", not a union. If you're still considering names, I would suggest something like "full parameters" or "signature parameters" for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See pattern_match.h for the definition of that term (such as it is). Do you think it would make sense to move that here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be the more central location to document a a term. However, I've also brought this up on #naming.

toolchain/sem_ir/entity_with_params_base.h Outdated Show resolved Hide resolved
toolchain/lower/file_context.cpp Outdated Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
toolchain/check/pattern_match.cpp Outdated Show resolved Hide resolved
toolchain/check/pattern_match.cpp Show resolved Hide resolved
toolchain/check/handle_impl.cpp Outdated Show resolved Hide resolved
toolchain/check/handle_function.cpp Show resolved Hide resolved
Copy link
Contributor Author

@geoffromer geoffromer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the PR description have some more explanation, like a link to the discussion about this and a mention of what it's being replaced with?

Good point, I've fleshed out the description, but what discussion are you referring to?

@@ -97,18 +97,14 @@ auto ConvertForExplicitAs(Context& context, Parse::NodeId as_node,
struct CalleeParamsInfo {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I expect the merge conflicts to be pretty straightforward, but I can do the merge during the review instead of the end if you like.

toolchain/check/handle_function.cpp Show resolved Hide resolved
toolchain/check/handle_impl.cpp Outdated Show resolved Hide resolved
toolchain/check/pattern_match.cpp Show resolved Hide resolved
toolchain/check/pattern_match.cpp Outdated Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
toolchain/lower/file_context.cpp Outdated Show resolved Hide resolved
toolchain/check/pattern_match.cpp Show resolved Hide resolved
toolchain/lower/file_context.cpp Outdated Show resolved Hide resolved
toolchain/check/pattern_match.cpp Outdated Show resolved Hide resolved
@jonmeow
Copy link
Contributor

jonmeow commented Nov 4, 2024

Should the PR description have some more explanation, like a link to the discussion about this and a mention of what it's being replaced with?

Good point, I've fleshed out the description, but what discussion are you referring to?

https://discord.com/channels/655572317891461132/655578254970716160/1300545448909738125

Comment on lines 106 to 107
// parameter. These parameters appear in declaration order: `self` (if
// present), then the explicit runtime parameters, then the return slot (which
Copy link
Contributor

@jonmeow jonmeow Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, the only implicit parameter the toolchain supports is self. However, once more are supported, won't those become part of the calling convention? Also, are you intending to exclude non-runtime explicit parameters (do we have those?)?

You might consider something like:

Suggested change
// parameter. These parameters appear in declaration order: `self` (if
// present), then the explicit runtime parameters, then the return slot (which
// parameter. Parameters are in declaration order: implicit parameters, explicit parameters, then the return slot (which

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm intending to exclude all non-runtime parameters, because they aren't part of the calling convention (i.e. they aren't passed as part of the function call). Unless I'm missing something, self is the only non-compile-time parameter that can appear in the implicit parameter list.

SemIR::InstBlockId param_patterns_id;

// The calling convention parameters of the function. These will all be
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// The calling convention parameters of the function. These will all be
// The calling convention parameters of the entity. These will all be

Won't this be set for all parameterized entities, not only functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe functions are the only entities that have a calling convention (because they're the only entities that can be called with runtime arguments).

Copy link
Contributor

@zygoloid zygoloid Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be reasonable to add a TODO similar to the one for the return slot fields here?

I think it'd also be useful to specify more explicitly what you mean by "calling convention parameters" here. Maybe overall something like:

The calling convention parameters of this entity, if it is a function. These are the parameters that correspond to the arguments in a Call instruction that calls this function. These will all be instances of AnyParam.

I also wonder if a shorter name like call_params_id or maybe call_inst_params_id might capture the same meaning. ("Calling convention" sounds to me like it might be talking about ABI, which I think is separate.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, or maybe this should reference EntityWithParamsBase for the full explanation of this field. I think the TODO and the change from "the function" to "the entity if it is a function" would still be useful here, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, and renamed to call_params_id as discussed at today's meeting.

Comment on lines 104 to 111
// A block containing, for each calling convention parameter (including the
// return slot), a reference to the instruction in the function's declaration
// block that represents that parameter. These instructions will be in the
// `AnyParam` category. This is not populated on imported entities, because it
// is relevant only for the function definition.
// TODO: can this be moved to `Function`, since it is not applicable to other
// kinds of entities?
InstBlockId calling_convention_params_id;
Copy link
Contributor

@jonmeow jonmeow Nov 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to note, one thing I'd particularly want to be sure of is that you both understand what "calling convention parameter" is, that it's a term I'm just not familiar with. To me, that sounds distinctly qualified from "implicit" or "explicit", not a union. If you're still considering names, I would suggest something like "full parameters" or "signature parameters" for this.

Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to note, I'm basically fine with this, but would like to make sure zygoloid is happy with this, particularly the naming (which throws me).

// instruction in the entity's pattern block that depends on all other
// pattern insts pertaining to that parameter.
InstBlockId param_patterns_id;
// A block containing, for each calling convention parameter, a reference to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be useful to explain what you mean by "calling convention parameter" here: that is, this list is the parameters corresponding to the arguments in a Call instruction.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At a high-level, I think we were particularly discussing "Call parameters", i.e. referring to the specific entity, rather than "call parameters". I think that makes a difference in documentation, with one example below. What do you think of changing how you're referring to that?

Comment on lines 105 to 107
// `AnyParam` insts that represent the function's call parameters. The "call
// parameters" are the parameters corresponding to the arguments that are
// passed to a `Call` inst, so they include `self` (if applicable) and the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this say "call parameters" instead of "Call"? Had you considered something like:

Suggested change
// `AnyParam` insts that represent the function's call parameters. The "call
// parameters" are the parameters corresponding to the arguments that are
// passed to a `Call` inst, so they include `self` (if applicable) and the
// `AnyParam` insts that represent the function's `Call` parameters. They include `self` (if applicable) and the

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to be a little more explicit about the fact that I'm defining this as a term of art, particularly so that it can be reused in places like name_component.h. It hadn't occurred to me to say "Call" instead of "call", but I suppose that works; done.

Copy link
Contributor

@jonmeow jonmeow Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think extra documentation can help, but I want to focus on this:

this block consists of references to the AnyParam insts that represent the function's Call parameters. The "Call parameters" are the parameters corresponding to the arguments that are passed to a Call inst

Isn't this just saying that the Call parameters are parameters to the Call instruction? I end up a little uncertain because, to me, when I see something that looks repetitive, I tend to assume that I'm actually misreading and missing a nuance. As a consequence, the repetition actually makes this harder for me to read, not easier. Maybe there's some more terse way of stating this, such as "Call inst parameters" if you're concerned about non-instruction interpretations of just "Call"?

Although, this also raises another question. Maybe this comment should be on Call so that when we say "Call parameters" the answer is found on Call without needing to say "look at EntityWithParamsBase"? Sorry about this, since I think this has already moved around a little.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this just saying that the Call parameters are parameters to the Call instruction?

I wouldn't put it that way, no. EntityWithParamsBase represents part of the declaration of a callable entity; it doesn't represent a particular call to that entity, so there's no Call inst in "scope" here. By the same token, Call doesn't have parameters, it has arguments. Does that make sense?

Although, this also raises another question. Maybe this comment should be on Call so that when we say "Call parameters" the answer is found on Call without needing to say "look at EntityWithParamsBase"? Sorry about this, since I think this has already moved around a little.

That could work, but I think it would be awkward, for the same reason: the Call inst represents a particular call to a callable entity, so I think it would feel like a non sequitur to talk about how that callable entity represents its parameters in its own IR.

(While looking at this I noticed that the Call documentation is out of date, so I fixed that.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this just saying that the Call parameters are parameters to the Call instruction?

I wouldn't put it that way, no. EntityWithParamsBase represents part of the declaration of a callable entity; it doesn't represent a particular call to that entity, so there's no Call inst in "scope" here. By the same token, Call doesn't have parameters, it has arguments. Does that make sense?

FWIW, here's a different phrasing that I don't know if it'd work for you:

`Call` parameters correspond to `Call::args_id`, but in parameter form.

I'll leave it to you whether to adopt something like that.

Although, this also raises another question. Maybe this comment should be on Call so that when we say "Call parameters" the answer is found on Call without needing to say "look at EntityWithParamsBase"? Sorry about this, since I think this has already moved around a little.

That could work, but I think it would be awkward, for the same reason: the Call inst represents a particular call to a callable entity, so I think it would feel like a non sequitur to talk about how that callable entity represents its parameters in its own IR.

(While looking at this I noticed that the Call documentation is out of date, so I fixed that.)

To be clear here, what I really mean is instead of having things like "(see entity_with_params_base.h for the definition of that term)." in pattern_match.h, maybe having it on Call would mean that people seeing "Call parameters" and wondering what that means would be able to find it on Call without the explicit reference. I'm not meaning to argue the detail in this half of the comment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, here's a different phrasing that I don't know if it'd work for you:

`Call` parameters correspond to `Call::args_id`, but in parameter form.

I'll leave it to you whether to adopt something like that.

I'm afraid the "in parameter form" part doesn't work for me -- they don't just have different forms, they have different content, because they represent categorically different entities.

That said, I don't want to just shoot down your suggestions; this concept is kind of subtle, so it's important for the explanation to be clear, and evidently it isn't. If you have any thoughts about how to fix it, I'm happy to iterate more in a follow-up PR.

Comment on lines 107 to 112
// passed to a `Call` inst, so they include `self` (if applicable) and the
// return slot, but do not include compile-time parameters.
//
// The parameters appear in declaration order: `self` (if present), then the
// explicit runtime parameters, then the return slot (which is "declared" by
// the function's return type declaration). This is not populated on imported
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You note the things which are included twice here, had you considered removing one of the mentions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought about it, but I couldn't find a way to do it without creating other problems. When I'm defining "Call parameters" it seems important to give examples of how it differs from other meanings of "parameters", and at some point I need to specify the parameter order fairly precisely since all the code that uses this field needs to agree on that, but combining the two forces me to front-load the ordering specification, which seems like it's dumping too much information on the reader all at once.

The self example in the first paragraph wasn't adding much, so I've at least removed that, but I'm not sure what else to do.

toolchain/lower/file_context.cpp Outdated Show resolved Hide resolved
toolchain/sem_ir/ids.h Outdated Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
Comment on lines +209 to +213
auto parameter_blocks =
CalleePatternMatch(context, *implicit_param_patterns_id,
SemIR::InstBlockId::Invalid, SemIR::InstId::Invalid);
CARBON_CHECK(parameter_blocks.call_params_id == SemIR::InstBlockId::Empty);
CARBON_CHECK(parameter_blocks.return_slot_id == SemIR::InstId::Invalid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate what's going on here? Previously, the result of parameter_blocks.implicit_params_id was retained. What's the effect of running it when the result is discarded?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The primary job of CalleePatternMatch is to emit the pattern-match IR, and we still want to do that here, even though we no longer use the return value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, what do you think of adding a comment here to explain the code? I've taken a stab above to try to clarify what I'm requesting.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, with somewhat different wording.

toolchain/sem_ir/entity_with_params_base.h Outdated Show resolved Hide resolved
Comment on lines 105 to 107
// `AnyParam` insts that represent the function's call parameters. The "call
// parameters" are the parameters corresponding to the arguments that are
// passed to a `Call` inst, so they include `self` (if applicable) and the
Copy link
Contributor

@jonmeow jonmeow Nov 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think extra documentation can help, but I want to focus on this:

this block consists of references to the AnyParam insts that represent the function's Call parameters. The "Call parameters" are the parameters corresponding to the arguments that are passed to a Call inst

Isn't this just saying that the Call parameters are parameters to the Call instruction? I end up a little uncertain because, to me, when I see something that looks repetitive, I tend to assume that I'm actually misreading and missing a nuance. As a consequence, the repetition actually makes this harder for me to read, not easier. Maybe there's some more terse way of stating this, such as "Call inst parameters" if you're concerned about non-instruction interpretations of just "Call"?

Although, this also raises another question. Maybe this comment should be on Call so that when we say "Call parameters" the answer is found on Call without needing to say "look at EntityWithParamsBase"? Sorry about this, since I think this has already moved around a little.

github-merge-queue bot pushed a commit that referenced this pull request Nov 15, 2024
This is at a point where it's getting difficult to read, and #4479 is
adding a large block comment. In order to more clearly delineate
members, add blank lines between.
Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Some lingering comments, including one more "call parameters" I noticed, but generally I think this is fine to merge. To be clear, feel free to merge regardless of how you resolve remaining comments. Sorry about the long review here.

Comment on lines +209 to +213
auto parameter_blocks =
CalleePatternMatch(context, *implicit_param_patterns_id,
SemIR::InstBlockId::Invalid, SemIR::InstId::Invalid);
CARBON_CHECK(parameter_blocks.call_params_id == SemIR::InstBlockId::Empty);
CARBON_CHECK(parameter_blocks.return_slot_id == SemIR::InstId::Invalid);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, what do you think of adding a comment here to explain the code? I've taken a stab above to try to clarify what I'm requesting.

toolchain/check/handle_impl.cpp Show resolved Hide resolved
toolchain/check/pattern_match.h Outdated Show resolved Hide resolved
Comment on lines 105 to 107
// `AnyParam` insts that represent the function's call parameters. The "call
// parameters" are the parameters corresponding to the arguments that are
// passed to a `Call` inst, so they include `self` (if applicable) and the
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this just saying that the Call parameters are parameters to the Call instruction?

I wouldn't put it that way, no. EntityWithParamsBase represents part of the declaration of a callable entity; it doesn't represent a particular call to that entity, so there's no Call inst in "scope" here. By the same token, Call doesn't have parameters, it has arguments. Does that make sense?

FWIW, here's a different phrasing that I don't know if it'd work for you:

`Call` parameters correspond to `Call::args_id`, but in parameter form.

I'll leave it to you whether to adopt something like that.

Although, this also raises another question. Maybe this comment should be on Call so that when we say "Call parameters" the answer is found on Call without needing to say "look at EntityWithParamsBase"? Sorry about this, since I think this has already moved around a little.

That could work, but I think it would be awkward, for the same reason: the Call inst represents a particular call to a callable entity, so I think it would feel like a non sequitur to talk about how that callable entity represents its parameters in its own IR.

(While looking at this I noticed that the Call documentation is out of date, so I fixed that.)

To be clear here, what I really mean is instead of having things like "(see entity_with_params_base.h for the definition of that term)." in pattern_match.h, maybe having it on Call would mean that people seeing "Call parameters" and wondering what that means would be able to find it on Call without the explicit reference. I'm not meaning to argue the detail in this half of the comment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants