mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 09:41:08 +01:00
true and false support, and lowering for bool type. (#2896)
This commit is contained in:
@@ -131,6 +131,7 @@ CARBON_KEYWORD_TOKEN(Default, "default")
|
||||
CARBON_KEYWORD_TOKEN(Else, "else")
|
||||
CARBON_KEYWORD_TOKEN(Extends, "extends")
|
||||
CARBON_KEYWORD_TOKEN(External, "external")
|
||||
CARBON_KEYWORD_TOKEN(False, "false")
|
||||
CARBON_KEYWORD_TOKEN(Final, "final")
|
||||
CARBON_KEYWORD_TOKEN(Fn, "fn")
|
||||
CARBON_KEYWORD_TOKEN(For, "for")
|
||||
@@ -162,6 +163,7 @@ CARBON_KEYWORD_TOKEN(SelfValueIdentifier, "self")
|
||||
CARBON_KEYWORD_TOKEN(StringTypeLiteral, "String")
|
||||
CARBON_KEYWORD_TOKEN(Template, "template")
|
||||
CARBON_KEYWORD_TOKEN(Then, "then")
|
||||
CARBON_KEYWORD_TOKEN(True, "true")
|
||||
// Underscore is tokenized as a keyword because it's part of identifiers.
|
||||
CARBON_KEYWORD_TOKEN(Underscore, "_")
|
||||
CARBON_KEYWORD_TOKEN(Var, "var")
|
||||
|
||||
@@ -141,6 +141,10 @@ auto LoweringContext::BuildType(SemanticsNodeId node_id) -> llvm::Type* {
|
||||
case SemanticsBuiltinKind::IntegerType.AsInt():
|
||||
// TODO: Handle different sizes.
|
||||
return builder_.getInt32Ty();
|
||||
case SemanticsBuiltinKind::BoolType.AsInt():
|
||||
// TODO: We may want to have different representations for `bool` storage
|
||||
// (`i8`) versus for `bool` values (`i1`).
|
||||
return builder_.getInt1Ty();
|
||||
}
|
||||
|
||||
auto node = semantics_ir_->GetNode(node_id);
|
||||
|
||||
@@ -43,6 +43,14 @@ auto LoweringHandleBlockArg(LoweringContext& /*context*/,
|
||||
CARBON_FATAL() << "TODO: Add support: " << node;
|
||||
}
|
||||
|
||||
auto LoweringHandleBoolLiteral(LoweringContext& context,
|
||||
SemanticsNodeId node_id, SemanticsNode node)
|
||||
-> void {
|
||||
llvm::Value* v = llvm::ConstantInt::get(context.builder().getInt1Ty(),
|
||||
node.GetAsBoolLiteral().index);
|
||||
context.SetLocal(node_id, v);
|
||||
}
|
||||
|
||||
auto LoweringHandleBranch(LoweringContext& /*context*/,
|
||||
SemanticsNodeId /*node_id*/, SemanticsNode node)
|
||||
-> void {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// 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: ; ModuleID = 'false_true.carbon'
|
||||
// CHECK:STDOUT: source_filename = "false_true.carbon"
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define i1 @F() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: ret i1 false
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: define i1 @T() {
|
||||
// CHECK:STDOUT: entry:
|
||||
// CHECK:STDOUT: ret i1 true
|
||||
// CHECK:STDOUT: }
|
||||
|
||||
fn F() -> bool {
|
||||
return false;
|
||||
}
|
||||
|
||||
fn T() -> bool {
|
||||
return true;
|
||||
}
|
||||
@@ -61,6 +61,8 @@ auto ParserHandleExpressionInPostfix(ParserContext& context) -> void {
|
||||
context.PushState(state);
|
||||
break;
|
||||
}
|
||||
case TokenKind::False:
|
||||
case TokenKind::True:
|
||||
case TokenKind::IntegerLiteral:
|
||||
case TokenKind::RealLiteral:
|
||||
case TokenKind::StringLiteral:
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// 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: 'Literal', 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},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// 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: 'Literal', 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},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// 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: 'Literal', 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},
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// 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: 'Literal', 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},
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// CHECK:STDOUT: {kind: 'ParameterList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'IfConditionStart', text: 'if', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'NameReference', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'Literal', text: 'true'},
|
||||
// CHECK:STDOUT: {kind: 'IfCondition', text: 'if', has_error: yes, subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'CodeBlockStart', text: 'then', has_error: yes},
|
||||
// CHECK:STDOUT: {kind: 'InvalidParse', text: 'then', has_error: yes},
|
||||
|
||||
@@ -224,6 +224,17 @@ auto SemanticsHandleLiteral(SemanticsContext& context,
|
||||
ParseTree::Node parse_node) -> bool {
|
||||
auto token = context.parse_tree().node_token(parse_node);
|
||||
switch (auto token_kind = context.tokens().GetKind(token)) {
|
||||
case TokenKind::False:
|
||||
case TokenKind::True: {
|
||||
context.AddNodeAndPush(
|
||||
parse_node,
|
||||
SemanticsNode::BoolLiteral::Make(
|
||||
parse_node,
|
||||
context.CanonicalizeType(SemanticsNodeId::BuiltinBoolType),
|
||||
token_kind == TokenKind::True ? SemanticsBoolValue(1)
|
||||
: SemanticsBoolValue(0)));
|
||||
break;
|
||||
}
|
||||
case TokenKind::IntegerLiteral: {
|
||||
auto id = context.semantics_ir().AddIntegerLiteral(
|
||||
context.tokens().GetIntegerLiteral(token));
|
||||
|
||||
@@ -199,6 +199,7 @@ auto SemanticsIR::StringifyType(SemanticsTypeId type_id) -> std::string {
|
||||
case SemanticsNodeKind::BinaryOperatorAdd:
|
||||
case SemanticsNodeKind::BindName:
|
||||
case SemanticsNodeKind::BlockArg:
|
||||
case SemanticsNodeKind::BoolLiteral:
|
||||
case SemanticsNodeKind::Branch:
|
||||
case SemanticsNodeKind::BranchIf:
|
||||
case SemanticsNodeKind::BranchWithArg:
|
||||
|
||||
@@ -68,6 +68,23 @@ struct SemanticsCrossReferenceIRId : public IndexBase {
|
||||
}
|
||||
};
|
||||
|
||||
// A boolean value.
|
||||
struct SemanticsBoolValue : public IndexBase {
|
||||
using IndexBase::IndexBase;
|
||||
auto Print(llvm::raw_ostream& out) const -> void {
|
||||
switch (index) {
|
||||
case 0:
|
||||
out << "false";
|
||||
break;
|
||||
case 1:
|
||||
out << "true";
|
||||
break;
|
||||
default:
|
||||
CARBON_FATAL() << "Invalid bool value " << index;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The ID of an integer literal.
|
||||
struct SemanticsIntegerLiteralId : public IndexBase {
|
||||
using IndexBase::IndexBase;
|
||||
@@ -264,6 +281,9 @@ class SemanticsNode {
|
||||
|
||||
using BlockArg = Factory<SemanticsNodeKind::BlockArg>;
|
||||
|
||||
using BoolLiteral =
|
||||
Factory<SemanticsNodeKind::BoolLiteral, SemanticsBoolValue /*value*/>;
|
||||
|
||||
using Branch = FactoryNoType<SemanticsNodeKind::Branch,
|
||||
SemanticsNodeBlockId /*target_id*/>;
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ CARBON_SEMANTICS_NODE_KIND(Assign)
|
||||
CARBON_SEMANTICS_NODE_KIND(BinaryOperatorAdd)
|
||||
CARBON_SEMANTICS_NODE_KIND(BindName)
|
||||
CARBON_SEMANTICS_NODE_KIND(BlockArg)
|
||||
CARBON_SEMANTICS_NODE_KIND(BoolLiteral)
|
||||
CARBON_SEMANTICS_NODE_KIND(Branch)
|
||||
CARBON_SEMANTICS_NODE_KIND(BranchIf)
|
||||
CARBON_SEMANTICS_NODE_KIND(BranchWithArg)
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
// 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: str2, param_refs: block0, return_type: type0, body: block4},
|
||||
// CHECK:STDOUT: {name: str3, param_refs: block0, return_type: type0, body: block8},
|
||||
// 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: F,
|
||||
// CHECK:STDOUT: G,
|
||||
// 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: FunctionDeclaration, arg0: function2},
|
||||
// CHECK:STDOUT: {kind: BoolLiteral, arg0: true, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block6, arg1: node+7},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block5},
|
||||
// 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: block7, arg1: node+10},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block7, arg1: node+11},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type0},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+14, type: type0},
|
||||
// CHECK:STDOUT: {kind: FunctionDeclaration, arg0: function3},
|
||||
// CHECK:STDOUT: {kind: BoolLiteral, arg0: false, type: type1},
|
||||
// CHECK:STDOUT: {kind: BranchIf, arg0: block10, arg1: node+17},
|
||||
// CHECK:STDOUT: {kind: Branch, arg0: block9},
|
||||
// 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: block11, arg1: node+20},
|
||||
// CHECK:STDOUT: {kind: BranchWithArg, arg0: block11, arg1: node+21},
|
||||
// CHECK:STDOUT: {kind: BlockArg, type: type0},
|
||||
// CHECK:STDOUT: {kind: ReturnExpression, arg0: node+24, 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+6,
|
||||
// CHECK:STDOUT: node+16,
|
||||
// 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+7,
|
||||
// CHECK:STDOUT: node+8,
|
||||
// CHECK:STDOUT: node+9,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+11,
|
||||
// CHECK:STDOUT: node+13,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+10,
|
||||
// CHECK:STDOUT: node+12,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+14,
|
||||
// CHECK:STDOUT: node+15,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+17,
|
||||
// CHECK:STDOUT: node+18,
|
||||
// CHECK:STDOUT: node+19,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+21,
|
||||
// CHECK:STDOUT: node+23,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+20,
|
||||
// CHECK:STDOUT: node+22,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: [
|
||||
// CHECK:STDOUT: node+24,
|
||||
// CHECK:STDOUT: node+25,
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: ]
|
||||
|
||||
fn A() -> i32 { return 1; }
|
||||
fn B() -> i32 { return 2; }
|
||||
|
||||
fn F() -> i32 {
|
||||
return if true then A() else B();
|
||||
}
|
||||
|
||||
fn G() -> i32 {
|
||||
return if false then A() else B();
|
||||
}
|
||||
Reference in New Issue
Block a user