mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 08:31:04 +01:00
Semantic analysis for if expressions (#2893)
Add semantic analysis and semantics IR building for `if` expressions, and add the first parts of control flow handling to semantics IR. After discussion with @chandlerc, use [block arguments](https://en.wikipedia.org/wiki/Static_single-assignment_form#Block_arguments) to convey values from the two arms of the `if` to the result. For now, only a single block argument is supported, but we should revisit this as we explore more of the requirements of the Semantics IR form. Functions can now contain multiple code blocks, so grab the entry block up-front instead of assuming the entry block will be at the top of the block stack when we reach the end of function emission. Add trivial support for `bool` type literal, because without it we can't write testcases.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeTypeType, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeInvalidType, type: typeInvalidType},
|
||||
// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeBoolType, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeIntegerType, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeFloatingPointType, type: typeTypeType},
|
||||
// CHECK:STDOUT: {kind: CrossReference, arg0: ir0, arg1: nodeStringType, type: typeTypeType},
|
||||
|
||||
@@ -121,6 +121,7 @@ CARBON_KEYWORD_TOKEN(Api, "api")
|
||||
CARBON_KEYWORD_TOKEN(As, "as")
|
||||
CARBON_KEYWORD_TOKEN(Auto, "auto")
|
||||
CARBON_KEYWORD_TOKEN(Base, "base")
|
||||
CARBON_KEYWORD_TOKEN(Bool, "bool")
|
||||
CARBON_KEYWORD_TOKEN(Break, "break")
|
||||
CARBON_KEYWORD_TOKEN(Case, "case")
|
||||
CARBON_KEYWORD_TOKEN(Class, "class")
|
||||
|
||||
@@ -37,6 +37,30 @@ auto LoweringHandleBindName(LoweringContext& /*context*/,
|
||||
// Probably need to do something here, but not necessary for now.
|
||||
}
|
||||
|
||||
auto LoweringHandleBlockArg(LoweringContext& /*context*/,
|
||||
SemanticsNodeId /*node_id*/, SemanticsNode node)
|
||||
-> void {
|
||||
CARBON_FATAL() << "TODO: Add support: " << node;
|
||||
}
|
||||
|
||||
auto LoweringHandleBranch(LoweringContext& /*context*/,
|
||||
SemanticsNodeId /*node_id*/, SemanticsNode node)
|
||||
-> void {
|
||||
CARBON_FATAL() << "TODO: Add support: " << node;
|
||||
}
|
||||
|
||||
auto LoweringHandleBranchIf(LoweringContext& /*context*/,
|
||||
SemanticsNodeId /*node_id*/, SemanticsNode node)
|
||||
-> void {
|
||||
CARBON_FATAL() << "TODO: Add support: " << node;
|
||||
}
|
||||
|
||||
auto LoweringHandleBranchWithArg(LoweringContext& /*context*/,
|
||||
SemanticsNodeId /*node_id*/,
|
||||
SemanticsNode node) -> void {
|
||||
CARBON_FATAL() << "TODO: Add support: " << node;
|
||||
}
|
||||
|
||||
auto LoweringHandleBuiltin(LoweringContext& /*context*/,
|
||||
SemanticsNodeId /*node_id*/, SemanticsNode node)
|
||||
-> void {
|
||||
|
||||
@@ -260,15 +260,15 @@ CARBON_PARSE_NODE_KIND_CHILD_COUNT(InfixOperator, 2)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(PostfixOperator, 1)
|
||||
|
||||
// `if` expression + `then` + `else`:
|
||||
// _external_: expression
|
||||
// _external_: expression
|
||||
// IfExpressionIf
|
||||
// _external_: expression
|
||||
// IfExpressionThen
|
||||
// _external_: expression
|
||||
// IfExpressionElse
|
||||
// _external_: expression
|
||||
// IfExpression
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpression, 5)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionThen, 0)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionElse, 0)
|
||||
// IfExpressionElse
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionIf, 1)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionThen, 1)
|
||||
CARBON_PARSE_NODE_KIND_CHILD_COUNT(IfExpressionElse, 3)
|
||||
|
||||
// Struct literals, such as `{.a = 0}`:
|
||||
// StructLiteralOrStructTypeLiteralStart
|
||||
|
||||
@@ -28,8 +28,8 @@ auto ParserHandleExpression(ParserContext& context) -> void {
|
||||
}
|
||||
|
||||
if (context.PositionIs(TokenKind::If)) {
|
||||
context.PushState(ParserState::ExpressionIfFinish);
|
||||
context.PushState(ParserState::ExpressionThen);
|
||||
context.PushState(ParserState::IfExpressionFinish);
|
||||
context.PushState(ParserState::IfExpressionFinishCondition);
|
||||
} else {
|
||||
context.PushStateForExpressionLoop(ParserState::ExpressionLoopForPrefix,
|
||||
state.ambient_precedence,
|
||||
@@ -64,6 +64,7 @@ auto ParserHandleExpressionInPostfix(ParserContext& context) -> void {
|
||||
case TokenKind::IntegerLiteral:
|
||||
case TokenKind::RealLiteral:
|
||||
case TokenKind::StringLiteral:
|
||||
case TokenKind::Bool:
|
||||
case TokenKind::IntegerTypeLiteral:
|
||||
case TokenKind::UnsignedIntegerTypeLiteral:
|
||||
case TokenKind::FloatingPointTypeLiteral:
|
||||
@@ -209,12 +210,15 @@ auto ParserHandleExpressionLoopForPrefix(ParserContext& context) -> void {
|
||||
context.PushState(state);
|
||||
}
|
||||
|
||||
auto ParserHandleExpressionThen(ParserContext& context) -> void {
|
||||
auto ParserHandleIfExpressionFinishCondition(ParserContext& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
if (context.ConsumeAndAddLeafNodeIf(TokenKind::Then,
|
||||
ParseNodeKind::IfExpressionThen)) {
|
||||
context.PushState(ParserState::ExpressionElse);
|
||||
context.AddNode(ParseNodeKind::IfExpressionIf, state.token,
|
||||
state.subtree_start, state.has_error);
|
||||
|
||||
if (context.PositionIs(TokenKind::Then)) {
|
||||
context.PushState(ParserState::IfExpressionFinishThen);
|
||||
context.ConsumeChecked(TokenKind::Then);
|
||||
context.PushStateForExpression(*PrecedenceGroup::ForLeading(TokenKind::If));
|
||||
} else {
|
||||
// TODO: Include the location of the `if` token.
|
||||
@@ -223,20 +227,24 @@ auto ParserHandleExpressionThen(ParserContext& context) -> void {
|
||||
if (!state.has_error) {
|
||||
context.emitter().Emit(*context.position(), ExpectedThenAfterIf);
|
||||
}
|
||||
// Add placeholders for `then expression else expression`.
|
||||
for (int i = 0; i != 4; ++i) {
|
||||
context.AddLeafNode(ParseNodeKind::InvalidParse, *context.position(),
|
||||
/*has_error=*/true);
|
||||
}
|
||||
// Add placeholders for `IfExpressionThen` and final `Expression`.
|
||||
context.AddLeafNode(ParseNodeKind::InvalidParse, *context.position(),
|
||||
/*has_error=*/true);
|
||||
context.AddLeafNode(ParseNodeKind::InvalidParse, *context.position(),
|
||||
/*has_error=*/true);
|
||||
context.ReturnErrorOnState();
|
||||
}
|
||||
}
|
||||
|
||||
auto ParserHandleExpressionElse(ParserContext& context) -> void {
|
||||
auto ParserHandleIfExpressionFinishThen(ParserContext& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
if (context.ConsumeAndAddLeafNodeIf(TokenKind::Else,
|
||||
ParseNodeKind::IfExpressionElse)) {
|
||||
context.AddNode(ParseNodeKind::IfExpressionThen, state.token,
|
||||
state.subtree_start, state.has_error);
|
||||
|
||||
if (context.PositionIs(TokenKind::Else)) {
|
||||
context.PushState(ParserState::IfExpressionFinishElse);
|
||||
context.ConsumeChecked(TokenKind::Else);
|
||||
context.PushStateForExpression(*PrecedenceGroup::ForLeading(TokenKind::If));
|
||||
} else {
|
||||
// TODO: Include the location of the `if` token.
|
||||
@@ -245,20 +253,28 @@ auto ParserHandleExpressionElse(ParserContext& context) -> void {
|
||||
if (!state.has_error) {
|
||||
context.emitter().Emit(*context.position(), ExpectedElseAfterIf);
|
||||
}
|
||||
// Add placeholders for `else expression`.
|
||||
for (int i = 0; i != 2; ++i) {
|
||||
context.AddLeafNode(ParseNodeKind::InvalidParse, *context.position(),
|
||||
/*has_error=*/true);
|
||||
}
|
||||
// Add placeholder for the final `Expression`.
|
||||
context.AddLeafNode(ParseNodeKind::InvalidParse, *context.position(),
|
||||
/*has_error=*/true);
|
||||
context.ReturnErrorOnState();
|
||||
}
|
||||
}
|
||||
|
||||
auto ParserHandleExpressionIfFinish(ParserContext& context) -> void {
|
||||
auto ParserHandleIfExpressionFinishElse(ParserContext& context) -> void {
|
||||
auto else_state = context.PopState();
|
||||
|
||||
// Propagate the location of `else`.
|
||||
auto if_state = context.PopState();
|
||||
if_state.token = else_state.token;
|
||||
if_state.has_error |= else_state.has_error;
|
||||
context.PushState(if_state);
|
||||
}
|
||||
|
||||
auto ParserHandleIfExpressionFinish(ParserContext& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
context.AddNode(ParseNodeKind::IfExpression, state.token, state.subtree_start,
|
||||
state.has_error);
|
||||
context.AddNode(ParseNodeKind::IfExpressionElse, state.token,
|
||||
state.subtree_start, state.has_error);
|
||||
}
|
||||
|
||||
auto ParserHandleExpressionStatementFinish(ParserContext& context) -> void {
|
||||
|
||||
@@ -183,8 +183,8 @@ CARBON_PARSER_STATE_VARIANTS2(Designator, Expression, Struct)
|
||||
//
|
||||
// If `If`:
|
||||
// 1. Expression
|
||||
// 2. ExpressionThen
|
||||
// 3. ExpressionIfFinish
|
||||
// 2. IfExpressionCondition
|
||||
// 3. IfExpressionFinish
|
||||
// Else if valid prefix operator:
|
||||
// 1. Expression
|
||||
// 2. ExpressionLoopForPrefix
|
||||
@@ -246,28 +246,36 @@ CARBON_PARSER_STATE(ExpressionLoopForBinary)
|
||||
// 1. ExpressionLoop
|
||||
CARBON_PARSER_STATE(ExpressionLoopForPrefix)
|
||||
|
||||
// Completes the condition of an `if` expression and handles the `then` token.
|
||||
//
|
||||
// If `Then`:
|
||||
// 1. Expression
|
||||
// 2. IfExpressionFinishThen
|
||||
// Else:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(IfExpressionFinishCondition)
|
||||
|
||||
// Completes the first alternative in an `if` expression and handles the `else`
|
||||
// token.
|
||||
//
|
||||
// If `Else`:
|
||||
// 1. Expression
|
||||
// 2. IfExpressionFinishElse
|
||||
// Else:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(IfExpressionFinishThen)
|
||||
|
||||
// Completes the second alternative in an `if` expression.
|
||||
//
|
||||
// Always:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(IfExpressionFinishElse)
|
||||
|
||||
// Completes an IfExpression.
|
||||
//
|
||||
// Always:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(ExpressionIfFinish)
|
||||
|
||||
// Handles the `then` token in an `if` expression.
|
||||
//
|
||||
// If `Then`:
|
||||
// 1. Expression
|
||||
// 2. ExpressionElse
|
||||
// Else:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(ExpressionThen)
|
||||
|
||||
// Handles the `else` token in an `if` expression.
|
||||
//
|
||||
// If `Else`:
|
||||
// 1. Expression
|
||||
// Else:
|
||||
// (state done)
|
||||
CARBON_PARSER_STATE(ExpressionElse)
|
||||
CARBON_PARSER_STATE(IfExpressionFinish)
|
||||
|
||||
// Handles the `;` for an expression statement, which is different from most
|
||||
// keyword statements.
|
||||
|
||||
+7
-7
@@ -8,7 +8,7 @@
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'F'},
|
||||
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ParameterListComma', text: ','},
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'x'},
|
||||
@@ -19,16 +19,16 @@
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 13},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'x'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'y'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 27},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', has_error: yes, subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'if', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 11},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 17},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: '1'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then', has_error: yes, subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -14,14 +14,13 @@
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'i32'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'VariableInitializer', text: '='},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: ';', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', has_error: yes, subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 18},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'if', has_error: yes, subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'VariableDeclaration', text: ';', subtree_size: 11},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 17},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
|
||||
+11
-11
@@ -8,25 +8,25 @@
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'F'},
|
||||
// CHECK:STDOUT: {kind: 'ParameterListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'DeclaredName', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'PatternBinding', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'bool'},
|
||||
// CHECK:STDOUT: {kind: 'ReturnType', text: '->', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 10},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatementStart', text: 'return'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionIf', text: 'if', subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperator', text: 'and', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionThen', text: 'then', subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'b'},
|
||||
// CHECK:STDOUT: {kind: 'InfixOperator', text: 'or', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'IfExpression', text: 'if', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'IfExpressionElse', text: 'else', subtree_size: 12},
|
||||
// CHECK:STDOUT: {kind: 'ReturnStatement', text: ';', subtree_size: 14},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 25},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
|
||||
@@ -50,6 +50,9 @@ CARBON_SEMANTICS_BUILTIN_KIND(InvalidType, "<unknown>")
|
||||
// Keeping distinct placeholders can help find usages for later fixes.
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
// The type of bool literals and branch conditions, bool.
|
||||
CARBON_SEMANTICS_BUILTIN_KIND(BoolType, "bool")
|
||||
|
||||
// The type of integer values and integer literals, currently always i32.
|
||||
CARBON_SEMANTICS_BUILTIN_KIND(IntegerType, "i32")
|
||||
|
||||
|
||||
@@ -61,7 +61,11 @@ auto SemanticsContext::VerifyOnFinish() -> void {
|
||||
}
|
||||
|
||||
auto SemanticsContext::AddNode(SemanticsNode node) -> SemanticsNodeId {
|
||||
auto block = node_block_stack_.PeekForAdd();
|
||||
return AddNodeToBlock(node_block_stack_.PeekForAdd(), node);
|
||||
}
|
||||
|
||||
auto SemanticsContext::AddNodeToBlock(SemanticsNodeBlockId block,
|
||||
SemanticsNode node) -> SemanticsNodeId {
|
||||
CARBON_VLOG() << "AddNode " << block << ": " << node << "\n";
|
||||
return semantics_ir_->AddNode(block, node);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ class SemanticsContext {
|
||||
// Adds a node to the current block, returning the produced ID.
|
||||
auto AddNode(SemanticsNode node) -> SemanticsNodeId;
|
||||
|
||||
// Adds a node to the given block, returning the produced ID.
|
||||
auto AddNodeToBlock(SemanticsNodeBlockId block, SemanticsNode node)
|
||||
-> SemanticsNodeId;
|
||||
|
||||
// Pushes a parse tree node onto the stack, storing the SemanticsNode as the
|
||||
// result.
|
||||
auto AddNodeAndPush(ParseTree::Node parse_node, SemanticsNode node) -> void;
|
||||
|
||||
@@ -178,21 +178,6 @@ auto SemanticsHandleIfConditionStart(SemanticsContext& context,
|
||||
return context.TODO(parse_node, "HandleIfConditionStart");
|
||||
}
|
||||
|
||||
auto SemanticsHandleIfExpression(SemanticsContext& context,
|
||||
ParseTree::Node parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleIfExpression");
|
||||
}
|
||||
|
||||
auto SemanticsHandleIfExpressionElse(SemanticsContext& context,
|
||||
ParseTree::Node parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleIfExpressionElse");
|
||||
}
|
||||
|
||||
auto SemanticsHandleIfExpressionThen(SemanticsContext& context,
|
||||
ParseTree::Node parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleIfExpressionThen");
|
||||
}
|
||||
|
||||
auto SemanticsHandleIfStatement(SemanticsContext& context,
|
||||
ParseTree::Node parse_node) -> bool {
|
||||
return context.TODO(parse_node, "HandleIfStatement");
|
||||
@@ -275,6 +260,10 @@ auto SemanticsHandleLiteral(SemanticsContext& context,
|
||||
id));
|
||||
break;
|
||||
}
|
||||
case TokenKind::Bool: {
|
||||
context.node_stack().Push(parse_node, SemanticsNodeId::BuiltinBoolType);
|
||||
break;
|
||||
}
|
||||
case TokenKind::IntegerTypeLiteral: {
|
||||
auto text = context.tokens().GetTokenText(token);
|
||||
if (text != "i32") {
|
||||
|
||||
@@ -18,17 +18,10 @@ auto SemanticsHandleFunctionDefinition(SemanticsContext& context,
|
||||
ParseNodeKind::FunctionDefinitionStart) {
|
||||
context.node_stack().PopAndIgnore();
|
||||
}
|
||||
auto function_id = context.node_stack().Pop<SemanticsFunctionId>(
|
||||
ParseNodeKind::FunctionDefinitionStart);
|
||||
|
||||
context.node_stack().PopAndDiscardId(ParseNodeKind::FunctionDefinitionStart);
|
||||
context.return_scope_stack().pop_back();
|
||||
context.PopScope();
|
||||
auto body_id = context.node_block_stack().Pop();
|
||||
auto& function = context.semantics_ir().GetFunction(function_id);
|
||||
CARBON_CHECK(!function.body_id.is_valid())
|
||||
<< "Already have function body: " << function.body_id;
|
||||
function.body_id = body_id;
|
||||
|
||||
context.node_block_stack().Pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -54,18 +47,21 @@ auto SemanticsHandleFunctionDefinitionStart(SemanticsContext& context,
|
||||
auto name_str = context.parse_tree().GetNodeText(name_node);
|
||||
auto name_id = context.semantics_ir().AddString(name_str);
|
||||
|
||||
// Add the callable, but with an invalid body for now. The body ID is only
|
||||
// finalized on function completion.
|
||||
// Create the entry block.
|
||||
auto outer_block = context.node_block_stack().PeekForAdd();
|
||||
context.node_block_stack().Push();
|
||||
|
||||
// Add the callable.
|
||||
auto function_id = context.semantics_ir().AddFunction(
|
||||
{.name_id = name_id,
|
||||
.param_refs_id = param_refs_id,
|
||||
.return_type_id = return_type_id,
|
||||
.body_id = SemanticsNodeBlockId::Invalid});
|
||||
auto decl_id = context.AddNode(
|
||||
.body_id = context.node_block_stack().PeekForAdd()});
|
||||
auto decl_id = context.AddNodeToBlock(
|
||||
outer_block,
|
||||
SemanticsNode::FunctionDeclaration::Make(fn_node, function_id));
|
||||
context.AddNameToLookup(name_node, name_id, decl_id);
|
||||
|
||||
context.node_block_stack().Push();
|
||||
context.PushScope();
|
||||
for (auto ref_id : context.semantics_ir().GetNodeBlock(param_refs_id)) {
|
||||
auto ref = context.semantics_ir().GetNode(ref_id);
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
// 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 SemanticsHandleIfExpressionIf(SemanticsContext& context,
|
||||
ParseTree::Node if_node) -> bool {
|
||||
auto cond_value_id = context.node_stack().Pop<SemanticsNodeId>();
|
||||
|
||||
context.node_stack().Push(if_node);
|
||||
|
||||
// Convert the condition to `bool`.
|
||||
cond_value_id = context.ImplicitAsRequired(
|
||||
if_node, cond_value_id,
|
||||
context.CanonicalizeType(SemanticsNodeId::BuiltinBoolType));
|
||||
|
||||
// Stop emitting the current block. We'll add some branch instructions to it
|
||||
// later, but we don't want it on the stack any more.
|
||||
auto if_block_id = context.node_block_stack().PeekForAdd();
|
||||
context.node_block_stack().Pop();
|
||||
|
||||
// Create the resumption block, `else` block, and `then` block, and branches
|
||||
// to them.
|
||||
context.node_block_stack().Push();
|
||||
auto else_block_id = context.node_block_stack().PushForAdd();
|
||||
auto then_block_id = context.node_block_stack().PushForAdd();
|
||||
context.AddNodeToBlock(
|
||||
if_block_id,
|
||||
SemanticsNode::BranchIf::Make(if_node, then_block_id, cond_value_id));
|
||||
context.AddNodeToBlock(if_block_id,
|
||||
SemanticsNode::Branch::Make(if_node, else_block_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
auto SemanticsHandleIfExpressionThen(SemanticsContext& context,
|
||||
ParseTree::Node then_node) -> bool {
|
||||
context.node_stack().Push(then_node, context.node_block_stack().Pop());
|
||||
return true;
|
||||
}
|
||||
|
||||
auto SemanticsHandleIfExpressionElse(SemanticsContext& context,
|
||||
ParseTree::Node else_node) -> bool {
|
||||
auto else_value_id = context.node_stack().Pop<SemanticsNodeId>();
|
||||
auto [then_node, then_end_block_id] =
|
||||
context.node_stack().PopWithParseNode<SemanticsNodeBlockId>(
|
||||
ParseNodeKind::IfExpressionThen);
|
||||
auto then_value_id = context.node_stack().Pop<SemanticsNodeId>();
|
||||
auto if_node =
|
||||
context.node_stack().PopForSoloParseNode(ParseNodeKind::IfExpressionIf);
|
||||
|
||||
// Convert the `else` value to the `then` value's type, and finish the `else`
|
||||
// block.
|
||||
// TODO: Find a common type, and convert both operands to it instead.
|
||||
auto result_type_id = context.semantics_ir().GetNode(then_value_id).type_id();
|
||||
else_value_id =
|
||||
context.ImplicitAsRequired(else_node, else_value_id, result_type_id);
|
||||
auto else_end_block_id = context.node_block_stack().Pop();
|
||||
|
||||
// Create branches to the resumption block.
|
||||
auto resume_block_id = context.node_block_stack().PeekForAdd();
|
||||
context.AddNodeToBlock(then_end_block_id,
|
||||
SemanticsNode::BranchWithArg::Make(
|
||||
then_node, resume_block_id, then_value_id));
|
||||
context.AddNodeToBlock(else_end_block_id,
|
||||
SemanticsNode::BranchWithArg::Make(
|
||||
else_node, resume_block_id, else_value_id));
|
||||
|
||||
// Obtain the value in the resumption block and push it.
|
||||
context.AddNodeAndPush(
|
||||
if_node, SemanticsNode::BlockArg::Make(if_node, result_type_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace Carbon
|
||||
@@ -198,6 +198,10 @@ auto SemanticsIR::StringifyType(SemanticsTypeId type_id) -> std::string {
|
||||
case SemanticsNodeKind::Assign:
|
||||
case SemanticsNodeKind::BinaryOperatorAdd:
|
||||
case SemanticsNodeKind::BindName:
|
||||
case SemanticsNodeKind::BlockArg:
|
||||
case SemanticsNodeKind::Branch:
|
||||
case SemanticsNodeKind::BranchIf:
|
||||
case SemanticsNodeKind::BranchWithArg:
|
||||
case SemanticsNodeKind::Builtin:
|
||||
case SemanticsNodeKind::Call:
|
||||
case SemanticsNodeKind::CodeBlock:
|
||||
|
||||
@@ -262,6 +262,19 @@ class SemanticsNode {
|
||||
SemanticsStringId /*name_id*/,
|
||||
SemanticsNodeId /*node_id*/>;
|
||||
|
||||
using BlockArg = Factory<SemanticsNodeKind::BlockArg>;
|
||||
|
||||
using Branch = FactoryNoType<SemanticsNodeKind::Branch,
|
||||
SemanticsNodeBlockId /*target_id*/>;
|
||||
|
||||
using BranchIf = FactoryNoType<SemanticsNodeKind::BranchIf,
|
||||
SemanticsNodeBlockId /*target_id*/,
|
||||
SemanticsNodeId /*cond_id*/>;
|
||||
|
||||
using BranchWithArg = FactoryNoType<SemanticsNodeKind::BranchWithArg,
|
||||
SemanticsNodeBlockId /*target_id*/,
|
||||
SemanticsNodeId /*arg*/>;
|
||||
|
||||
class Builtin {
|
||||
public:
|
||||
static auto Make(SemanticsBuiltinKind builtin_kind, SemanticsTypeId type_id)
|
||||
|
||||
@@ -27,6 +27,12 @@ class SemanticsNodeBlockStack {
|
||||
// order to support lazy allocation.
|
||||
auto Push() -> void;
|
||||
|
||||
// Allocates and pushes a new node block.
|
||||
auto PushForAdd() -> SemanticsNodeBlockId {
|
||||
Push();
|
||||
return PeekForAdd();
|
||||
}
|
||||
|
||||
// Peeks at the top node block. This does not trigger lazy allocation, so the
|
||||
// returned node block may be invalid.
|
||||
auto Peek() -> SemanticsNodeBlockId { return stack_.back(); }
|
||||
|
||||
@@ -23,6 +23,10 @@ CARBON_SEMANTICS_NODE_KIND(CrossReference)
|
||||
CARBON_SEMANTICS_NODE_KIND(Assign)
|
||||
CARBON_SEMANTICS_NODE_KIND(BinaryOperatorAdd)
|
||||
CARBON_SEMANTICS_NODE_KIND(BindName)
|
||||
CARBON_SEMANTICS_NODE_KIND(BlockArg)
|
||||
CARBON_SEMANTICS_NODE_KIND(Branch)
|
||||
CARBON_SEMANTICS_NODE_KIND(BranchIf)
|
||||
CARBON_SEMANTICS_NODE_KIND(BranchWithArg)
|
||||
CARBON_SEMANTICS_NODE_KIND(Builtin)
|
||||
CARBON_SEMANTICS_NODE_KIND(Call)
|
||||
CARBON_SEMANTICS_NODE_KIND(CodeBlock)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block2},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -26,6 +26,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Main() {
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block3, body: block0},
|
||||
// CHECK:STDOUT: {name: str4, param_refs: block5, body: block0},
|
||||
// CHECK:STDOUT: {name: str5, param_refs: block0, body: block6},
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block2},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block4, body: block5},
|
||||
// CHECK:STDOUT: {name: str4, param_refs: block7, body: block8},
|
||||
// CHECK:STDOUT: {name: str5, param_refs: block0, body: block9},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
@@ -66,6 +66,8 @@
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
@@ -73,6 +75,8 @@
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: node+6,
|
||||
@@ -83,6 +87,8 @@
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+12,
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -46,6 +46,8 @@
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str4, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str4, param_refs: block0, body: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
@@ -50,7 +50,7 @@
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+16, type: type0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int5, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+18, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block5, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -73,6 +73,8 @@
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
@@ -29,7 +29,7 @@
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block5, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -46,6 +46,8 @@
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: node+6,
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
@@ -30,10 +30,10 @@
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block5, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+7, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block7, arg1: function0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -50,6 +50,8 @@
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: node+6,
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block0, body: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
@@ -35,7 +35,7 @@
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+6, type: type0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block5, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -55,6 +55,8 @@
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block0, body: block5},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
@@ -37,12 +37,12 @@
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+6, type: type0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+8, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block5, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+11, type: type0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: type0},
|
||||
// CHECK:STDOUT: {kind: StubReference, arg0: node+13, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block6, arg1: function0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block7, arg1: function0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
@@ -62,6 +62,8 @@
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block0, body: block2},
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block2},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block0, body: block3},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -32,6 +32,8 @@
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -42,6 +42,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
// CHECK:STDERR: fail_param_name_conflict.carbon:[[@LINE+2]]:16: Redefining a in the same scope.
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block2},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block0, body: block3},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block0, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -34,6 +34,12 @@
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo() {}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -37,6 +37,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo(a: i32) {}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -37,6 +37,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo(a: i32,) {}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -43,6 +43,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo(a: i32, b: i32) {}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -43,6 +43,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo(a: i32, b: i32,) {}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block0},
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, body: block2},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -26,6 +26,8 @@
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo() {}
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block0},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block5, body: block0},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block2, body: block4},
|
||||
// CHECK:STDOUT: {name: str2, param_refs: block6, body: block7},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
@@ -44,12 +44,16 @@
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn Foo(a: i32) {}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
// 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
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block2, return_type: type1, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: real_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: strings: [
|
||||
// CHECK:STDOUT: b,
|
||||
// CHECK:STDOUT: n,
|
||||
// CHECK:STDOUT: m,
|
||||
// CHECK:STDOUT: F,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeBoolType,
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+0, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: type1},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+4, type: type1},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+0},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block5},
|
||||
// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+2, arg1: node+4, type: type1},
|
||||
// CHECK:STDOUT: {kind: BinaryOperatorAdd, arg0: node+4, arg1: node+2, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block7, arg1: node+9},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block7, arg1: node+10},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type1},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+13, type: type1},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn F(b: bool, n: i32, m: i32) -> i32 {
|
||||
return if b then n + m else m + n;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
// 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
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str0, param_refs: block0, return_type: type0, body: block2},
|
||||
// CHECK:STDOUT: {name: str1, param_refs: block0, return_type: type0, body: block3},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block5, return_type: type0, body: block6},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
// CHECK:STDOUT: 2,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: real_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: strings: [
|
||||
// CHECK:STDOUT: A,
|
||||
// CHECK:STDOUT: B,
|
||||
// CHECK:STDOUT: b,
|
||||
// CHECK:STDOUT: F,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: nodeBoolType,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type0},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+1, type: type0},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function1},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type0},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type1},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+6, type: type1},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function2},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block8, arg1: node+6},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block7},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0},
|
||||
// CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function1, type: type0},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+11},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+12},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type0},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+15, type: type0},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+15,
|
||||
// CHECK:STDOUT: node+16,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn A() -> i32 { return 1; }
|
||||
fn B() -> i32 { return 2; }
|
||||
|
||||
fn F(b: bool) -> i32 {
|
||||
return if b then A() else B();
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
// 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
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// CHECK:STDOUT: cross_reference_irs_size: 1
|
||||
// CHECK:STDOUT: functions: [
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block2, return_type: type1, body: block4},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: integer_literals: [
|
||||
// CHECK:STDOUT: 1,
|
||||
// CHECK:STDOUT: 2,
|
||||
// CHECK:STDOUT: 3,
|
||||
// CHECK:STDOUT: 4,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: real_literals: [
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: strings: [
|
||||
// CHECK:STDOUT: a,
|
||||
// CHECK:STDOUT: b,
|
||||
// CHECK:STDOUT: c,
|
||||
// CHECK:STDOUT: F,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: types: [
|
||||
// CHECK:STDOUT: nodeBoolType,
|
||||
// CHECK:STDOUT: nodeIntegerType,
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: nodes: [
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str0, arg1: node+0, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str1, arg1: node+2, type: type0},
|
||||
// CHECK:STDOUT: {kind: VarStorage, type: type0},
|
||||
// CHECK:STDOUT: {kind: BindName, arg0: str2, arg1: node+4, type: type0},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function0},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+0},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block5},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block8, arg1: node+2},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block7},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+11},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block9, arg1: node+12},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block11, arg1: node+4},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block10},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1},
|
||||
// CHECK:STDOUT: {kind: IntegerLiteral, arg0: int3, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block12, arg1: node+18},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block12, arg1: node+19},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block13, arg1: node+15},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block13, arg1: node+22},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type1},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+25, type: type1},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: node_blocks: [
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+0,
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+2,
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+4,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+1,
|
||||
// CHECK:STDOUT: node+3,
|
||||
// CHECK:STDOUT: node+5,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+6,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+16,
|
||||
// CHECK:STDOUT: node+17,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+15,
|
||||
// CHECK:STDOUT: node+23,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+19,
|
||||
// CHECK:STDOUT: node+21,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+18,
|
||||
// CHECK:STDOUT: node+20,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+22,
|
||||
// CHECK:STDOUT: node+24,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+25,
|
||||
// CHECK:STDOUT: node+26,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn F(a: bool, b: bool, c: bool) -> i32 {
|
||||
return if a then if b then 1 else 2 else if c then 3 else 4;
|
||||
}
|
||||
Reference in New Issue
Block a user