mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-28 10:10:09 +01:00
Previously, IR for arguments in calls and struct values was separated out. This merges it back in. Additionally, parameters for functions and struct types had their own IR; the block is still there, but there's a TODO to decide what to do with it. In the LLVM IR, this has the consequence of emitting expressions that are inputs to a call or struct value within the scope of the function, which is pretty much where it should be. Importantly it happens before the call is encountered. This change also tinkers with the int and real literal lowering. I'm pretty sure both are still wrong, but was having trouble figuring out a "better" way to do it, and this seems like it'll work for now.
128 lines
4.7 KiB
C++
128 lines
4.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/semantics/semantics_context.h"
|
|
|
|
namespace Carbon {
|
|
|
|
auto SemanticsHandleStructComma(SemanticsContext& context,
|
|
ParseTree::Node /*parse_node*/) -> bool {
|
|
context.ParamOrArgComma(
|
|
/*for_args=*/context.parse_tree().node_kind(
|
|
context.node_stack().PeekParseNode()) !=
|
|
ParseNodeKind::StructFieldType);
|
|
return true;
|
|
}
|
|
|
|
auto SemanticsHandleStructFieldDesignator(SemanticsContext& context,
|
|
ParseTree::Node /*parse_node*/)
|
|
-> bool {
|
|
// This leaves the designated name on top because the `.` isn't interesting.
|
|
CARBON_CHECK(
|
|
context.parse_tree().node_kind(context.node_stack().PeekParseNode()) ==
|
|
ParseNodeKind::DesignatedName);
|
|
return true;
|
|
}
|
|
|
|
auto SemanticsHandleStructFieldType(SemanticsContext& context,
|
|
ParseTree::Node parse_node) -> bool {
|
|
auto [type_node, type_id] = context.node_stack().PopForParseNodeAndNodeId();
|
|
SemanticsNodeId cast_type_id = context.ImplicitAsRequired(
|
|
type_node, type_id, SemanticsNodeId::BuiltinTypeType);
|
|
|
|
auto [name_node, name_id] = context.node_stack().PopForParseNodeAndNameId(
|
|
ParseNodeKind::DesignatedName);
|
|
|
|
context.AddNode(
|
|
SemanticsNode::StructTypeField::Make(name_node, cast_type_id, name_id));
|
|
context.node_stack().Push(parse_node);
|
|
return true;
|
|
}
|
|
|
|
auto SemanticsHandleStructFieldUnknown(SemanticsContext& context,
|
|
ParseTree::Node parse_node) -> bool {
|
|
return context.TODO(parse_node, "HandleStructFieldUnknown");
|
|
}
|
|
|
|
auto SemanticsHandleStructFieldValue(SemanticsContext& context,
|
|
ParseTree::Node parse_node) -> bool {
|
|
auto [value_parse_node, value_node_id] =
|
|
context.node_stack().PopForParseNodeAndNodeId();
|
|
auto [_, name_id] = context.node_stack().PopForParseNodeAndNameId(
|
|
ParseNodeKind::DesignatedName);
|
|
|
|
// Store the name for the type.
|
|
auto type_block_id = context.args_type_info_stack().PeekForAdd();
|
|
context.semantics().AddNode(
|
|
type_block_id,
|
|
SemanticsNode::StructTypeField::Make(
|
|
parse_node, context.semantics().GetNode(value_node_id).type_id(),
|
|
name_id));
|
|
|
|
// Push the value back on the stack as an argument.
|
|
context.node_stack().Push(parse_node, value_node_id);
|
|
return true;
|
|
}
|
|
|
|
auto SemanticsHandleStructLiteral(SemanticsContext& context,
|
|
ParseTree::Node parse_node) -> bool {
|
|
auto refs_id = context.ParamOrArgEnd(
|
|
/*for_args=*/true, ParseNodeKind::StructLiteralOrStructTypeLiteralStart);
|
|
|
|
context.PopScope();
|
|
context.node_stack().PopAndDiscardSoloParseNode(
|
|
ParseNodeKind::StructLiteralOrStructTypeLiteralStart);
|
|
auto type_block_id = context.args_type_info_stack().Pop();
|
|
|
|
// Special-case `{}`.
|
|
if (refs_id == SemanticsNodeBlockId::Empty) {
|
|
context.node_stack().Push(parse_node, SemanticsNodeId::BuiltinEmptyStruct);
|
|
return true;
|
|
}
|
|
|
|
// Construct a type for the literal.
|
|
auto refs = context.semantics().GetNodeBlock(refs_id);
|
|
auto type_id = context.AddNode(
|
|
SemanticsNode::StructType::Make(parse_node, type_block_id));
|
|
|
|
auto value_id = context.AddNode(
|
|
SemanticsNode::StructValue::Make(parse_node, type_id, refs_id));
|
|
context.node_stack().Push(parse_node, value_id);
|
|
return true;
|
|
}
|
|
|
|
auto SemanticsHandleStructLiteralOrStructTypeLiteralStart(
|
|
SemanticsContext& context, ParseTree::Node parse_node) -> bool {
|
|
context.PushScope();
|
|
context.node_stack().Push(parse_node);
|
|
// At this point we aren't sure whether this will be a value or type literal,
|
|
// so we push onto args irrespective. It just won't be used for a type
|
|
// literal.
|
|
context.args_type_info_stack().Push();
|
|
context.ParamOrArgStart();
|
|
return true;
|
|
}
|
|
|
|
auto SemanticsHandleStructTypeLiteral(SemanticsContext& context,
|
|
ParseTree::Node parse_node) -> bool {
|
|
auto refs_id = context.ParamOrArgEnd(
|
|
/*for_args=*/false, ParseNodeKind::StructLiteralOrStructTypeLiteralStart);
|
|
|
|
context.PopScope();
|
|
context.node_stack().PopAndDiscardSoloParseNode(
|
|
ParseNodeKind::StructLiteralOrStructTypeLiteralStart);
|
|
// This is only used for value literals.
|
|
context.args_type_info_stack().Pop();
|
|
|
|
CARBON_CHECK(refs_id != SemanticsNodeBlockId::Empty)
|
|
<< "{} is handled by StructLiteral.";
|
|
|
|
auto type_id =
|
|
context.AddNode(SemanticsNode::StructType::Make(parse_node, refs_id));
|
|
context.node_stack().Push(parse_node, type_id);
|
|
return true;
|
|
}
|
|
|
|
} // namespace Carbon
|