Skip to content

Add const match#3626

Open
wsipak wants to merge 3 commits intogoogle:mainfrom
antmicro:88020-const-match
Open

Add const match#3626
wsipak wants to merge 3 commits intogoogle:mainfrom
antmicro:88020-const-match

Conversation

@wsipak
Copy link
Contributor

@wsipak wsipak commented Dec 30, 2025

This PR adds support for the constexpr match expression.

This is work in progress.
The aim of this PR is to add support for const match expressions, where the arm selection is performed in compilation time.

  • allow parsing const match, as a Match node with a boolean property indicating the const.
  • evaluate the matched value and enforce that it must be possible to evaluate in compilation time for const match
  • select the right arm for a const match in compilation time
  • test DSLX and IR
  • allow disparate types in the arms of a match / do not typecheck the unused arms
  • test generating SystemVerilog
  • test the formatter

@magancarz magancarz force-pushed the 88020-const-match branch 2 times, most recently from 58c0b2d to 6ba1ec9 Compare January 13, 2026 14:55
@magancarz
Copy link
Contributor

I've added formatting const match and rebased changes on main.

@magancarz
Copy link
Contributor

I've added handling different types for arms, fixed spawning procs using const match, changed emitting bytecode to only use selected branch and added more DSLX/C++ test cases.

@wsipak wsipak marked this pull request as ready for review January 20, 2026 13:11
@wsipak wsipak changed the title WIP: Add const match Add const match Jan 20, 2026
@magancarz
Copy link
Contributor

@richmckeever is there anything else required to add?

@magancarz
Copy link
Contributor

I've added proper handling of const match with proc-scoped channels by handling only the selected arm and included a fix from #3745 which allows proc-scoped channels tests with parametrized procs to pass.

std::vector<TypeAnnotation*> members;

for (MatchArm* arm : node->arms()) {
XLS_RETURN_IF_ERROR(
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be better to merge this logic into the for loop that is in HandleMatch. i.e. turn the body of that loop into "if (node->IsConst() { ... } else { ... }" perhaps with some common logic at the beginning or end of the loop body. This would be similar to how HandleConditional works.

We generally don't use InferenceTable in such a way that we configure a node the normal way and then reconfigure it if we are in some special case. Even if it happens to work, that is a brittle approach because the normal way could get more complicated later and start doing stuff you don't want for the const case.


const std::vector<MatchArm*>& arms() const { return arms_; }
Expr* matched() const { return matched_; }
Number* arm_idx() const { return arm_idx_; }
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it would be better to model the notion of the chosen arm with dedicated TypeInfo API functions, i.e. add the ability to say
type_info->SetConstActiveArmIndex(match_node, 3)

as opposed to modeling this as a sentinel AST node with a constexpr value. The reason not to use the AST node is that it's is always a bogus zero value, and using that directly would be an easy mistake.


XLS_ASSIGN_OR_RETURN(
InterpValue interp_match,
evaluator_.ConstMatchWhichArm(parametric_context, ti, match));
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think if we move the arm selection to CollectConstants (see other comment), we will be able to just ask TypeInfo for the chosen arm index here, Evaluator will not need a function for it, and we will not need to set anything in TI further down.

return NotConstantErrorStatus(expr->span(), expr, file_table);
}

/* static */ absl::StatusOr<InterpValue> ConstexprEvaluator::ConstMatchWhichArm(
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be more in line with the general data flow in type inference if we could put this logic in CollectConstants() because that function basically runs as soon as it's feasible to decide the constant(s) associated with some node. It relieves ConstexprEvaluator of type inference-related knowledge Ideally ConstexprEvaluator just farms math out to the bytecode interpreter and has minimal inference logic.

Perhaps in CollectConstants, we say after dispatching the node to the visitor: if node->parent() is a Match and node == match->matched(), do this logic and then set the chosen arm index in TypeInfo. It could be a helper function inside that file.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants