mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Trying to conform with #4009. Changes SemIR::LocIdAndInst construction to root out struct init cases with AddInst and related functions. I'm using templating of AddInst functions in order to avoid `AddInst(loc_id, InstName{...})` and instead have `AddInst<InstName>(loc_id, {...})` with I think similar readability results. There are a couple cases where inst construction is templated and so designated initializers couldn't be used, so this may be better for those in particular due to the extra type enforcement. This probably doesn't clean up every last case, but I was trying to get the bulk at once without bleeding over into less related changes. --------- Co-authored-by: Richard Smith <richard@metafoo.co.uk>
79 lines
2.7 KiB
C++
79 lines
2.7 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/check/convert.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
auto HandleIfConditionStart(Context& /*context*/,
|
|
Parse::IfConditionStartId /*node_id*/) -> bool {
|
|
return true;
|
|
}
|
|
|
|
auto HandleIfCondition(Context& context, Parse::IfConditionId node_id) -> bool {
|
|
// Convert the condition to `bool`.
|
|
auto cond_value_id = context.node_stack().PopExpr();
|
|
cond_value_id = ConvertToBoolValue(context, node_id, cond_value_id);
|
|
|
|
// Create the then block and the else block, and branch to the right one. If
|
|
// there is no `else`, the then block will terminate with a branch to the
|
|
// else block, which will be reused as the resumption block.
|
|
auto then_block_id =
|
|
context.AddDominatedBlockAndBranchIf(node_id, cond_value_id);
|
|
auto else_block_id = context.AddDominatedBlockAndBranch(node_id);
|
|
|
|
// Start emitting the `then` block.
|
|
context.inst_block_stack().Pop();
|
|
context.inst_block_stack().Push(then_block_id);
|
|
context.AddCurrentCodeBlockToFunction();
|
|
|
|
context.node_stack().Push(node_id, else_block_id);
|
|
return true;
|
|
}
|
|
|
|
auto HandleIfStatementElse(Context& context, Parse::IfStatementElseId node_id)
|
|
-> bool {
|
|
auto else_block_id = context.node_stack().Pop<Parse::NodeKind::IfCondition>();
|
|
|
|
// Switch to emitting the `else` block.
|
|
context.inst_block_stack().Push(else_block_id);
|
|
context.AddCurrentCodeBlockToFunction();
|
|
|
|
context.node_stack().Push(node_id);
|
|
return true;
|
|
}
|
|
|
|
auto HandleIfStatement(Context& context, Parse::IfStatementId node_id) -> bool {
|
|
switch (auto kind = context.node_stack().PeekNodeKind()) {
|
|
case Parse::NodeKind::IfCondition: {
|
|
// Branch from then block to else block, and start emitting the else
|
|
// block.
|
|
auto else_block_id =
|
|
context.node_stack().Pop<Parse::NodeKind::IfCondition>();
|
|
context.AddInst<SemIR::Branch>(node_id, {.target_id = else_block_id});
|
|
context.inst_block_stack().Pop();
|
|
context.inst_block_stack().Push(else_block_id);
|
|
break;
|
|
}
|
|
|
|
case Parse::NodeKind::IfStatementElse: {
|
|
// Branch from the then and else blocks to a new resumption block.
|
|
context.node_stack()
|
|
.PopAndDiscardSoloNodeId<Parse::NodeKind::IfStatementElse>();
|
|
context.AddConvergenceBlockAndPush(node_id, /*num_blocks=*/2);
|
|
break;
|
|
}
|
|
|
|
default: {
|
|
CARBON_FATAL() << "Unexpected parse node at start of `if`: " << kind;
|
|
}
|
|
}
|
|
|
|
context.AddCurrentCodeBlockToFunction();
|
|
return true;
|
|
}
|
|
|
|
} // namespace Carbon::Check
|