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

Compute specific constant values. #4128

Merged
merged 6 commits into from
Jul 16, 2024

Conversation

zygoloid
Copy link
Contributor

When forming a specific (previously called a generic instance), evaluate the eval block of the generic to determine the values of any constants used in that specific. The majority of the work here is updating eval.cpp so that it can use the results of prior evaluations in the same block when computing later values.

Include the computed results in the formatted SemIR output.

When forming a generic instance (soon to be called a specific), evaluate
the eval block of the generic to determine the values of any constants
used in that specific.

Include the computed results in the formatted SemIR output.
@zygoloid zygoloid closed this Jul 13, 2024
@zygoloid zygoloid deleted the toolchain-generic-1 branch July 13, 2024 00:04
@zygoloid zygoloid restored the toolchain-generic-1 branch July 13, 2024 00:05
@zygoloid zygoloid reopened this Jul 13, 2024
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.

Looks good... Please go ahead and merge when you're comfortable. While I'm interested in your thoughts about class-ifying eval.cpp, I expect you may want to split it out (if at all).


// Information about the context within which we are performing evaluation.
struct EvalContext {
auto GetInContext(SemIR::ConstantId const_id) -> SemIR::ConstantId {
Copy link
Contributor

Choose a reason for hiding this comment

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

Comment? It's not clear to me how this differs from the others, and it looks like a public API (though, if this is class-ified, should it be private?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added a comment.

};

// Information about the context within which we are performing evaluation.
struct EvalContext {
Copy link
Contributor

Choose a reason for hiding this comment

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

Noting how much of this is functions, should it be a class? Examining member uses, it looks like context and specific_id are part of the API, but file and specific_eval_info are not.

Though, thinking about this from a different perspective, had you considered making the static functions in eval.cpp be members of this class? I think we use the Context object elsewhere because we have a lot of different files we want to compose access from, but here, we have a scoped use-case. It'd also avoid the need to pass EvalContext as a parameter.

Without a class, file and sem_ir() in particular look like an odd match to me: why an accessor to return a public member?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My intent is to make this into a class, but I'm trying to keep this PR minimal. Will send a follow-up with that change.

Comment on lines 107 to 109
// A cached reference to the file, to avoid a double indirection when
// accessing its value stores.
SemIR::File& file = context.sem_ir();
Copy link
Contributor

Choose a reason for hiding this comment

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

To note, this feels odd to me: it's unusual, and seems like it'd have a negligible effect on performance. Maybe I'm thinking about that wrong though?

The flipside is that all the internal sem_ir() calls look odd; if you keep this, maybe change them to reference the cached reference directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed for now; we can re-add if we have evidence of this being an issue.

Comment on lines 1425 to 1433
SpecificEvalInfo eval_info = {
.region = region,
.values = result,
};
EvalContext eval_context = {
.context = context,
.specific_id = specific_id,
.specific_eval_info = &eval_info,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

FWIW, the extra struct from SpecificEvalInfo had made me expect it'd be replaced and/or separately used, but this is the only assignment I see other than nullptr. Given the way EvalContext is constructed, had you considered moving its members over, or perhaps making it std::optional instead of *?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Originally I was concerned about this being large (containing a SmallVector) and I didn't want to include it in EvalContext for that reason, but that ended up not being a problem. Turned into a std::optional.

toolchain/sem_ir/formatter.cpp Outdated Show resolved Hide resolved
Comment on lines 71 to 75
template <typename IdT>
auto GetConstantValueAsInst(IdT id) -> SemIR::Inst {
return insts().Get(
context.constant_values().GetInstId(GetConstantValue(id)));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

This call confuses me a little: should it be taking a TypeId as parameter? It looks like the templated version isn't used.

(or will more callers be added? for one caller, maybe this function should be inlined)

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've ungeneralized it. I'd prefer to not inline it; I found that having a name for this operation made it a lot easier to follow what the code was doing, and I am anticipating more callers.

@zygoloid zygoloid enabled auto-merge July 15, 2024 23:51
@zygoloid zygoloid added this pull request to the merge queue Jul 15, 2024
Merged via the queue into carbon-language:trunk with commit efea072 Jul 16, 2024
7 checks passed
@zygoloid zygoloid deleted the toolchain-generic-1 branch July 16, 2024 00:08
brymer-meneses pushed a commit to brymer-meneses/carbon-lang that referenced this pull request Aug 15, 2024
When forming a specific (previously called a generic instance), evaluate
the eval block of the generic to determine the values of any constants
used in that specific. The majority of the work here is updating
eval.cpp so that it can use the results of prior evaluations in the same
block when computing later values.

Include the computed results in the formatted SemIR output.

---------

Co-authored-by: Jon Ross-Perkins <[email protected]>
@jonmeow
Copy link
Contributor

jonmeow commented Aug 26, 2024

@Bonniemarie216 I see you approved a lot of different changes. Please don't do that anymore, because it's not contributing to the review, but it does create notifications for people who are monitoring repository activity. Thanks!

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