Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Factor out machinery for forming int type literals. #4616

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions toolchain/check/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ cc_library(
"import.cpp",
"import_ref.cpp",
"inst_block_stack.cpp",
"literal.cpp",
"member_access.cpp",
"merge.cpp",
"modifiers.cpp",
Expand All @@ -54,6 +55,7 @@ cc_library(
"import_ref.h",
"inst_block_stack.h",
"keyword_modifier_set.h",
"literal.h",
"member_access.h",
"merge.h",
"modifiers.h",
Expand Down
11 changes: 0 additions & 11 deletions toolchain/check/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1377,17 +1377,6 @@ auto Context::GetGenericInterfaceType(SemIR::InterfaceId interface_id,
*this, interface_id, enclosing_specific_id);
}

auto Context::GetInt32Type() -> SemIR::TypeId {
auto bit_width_const_id = TryEvalInst(
*this, SemIR::InstId::Invalid,
SemIR::IntValue{
.type_id = GetBuiltinType(SemIR::BuiltinInstKind::IntLiteralType),
.int_id = ints().Add(32)});
return GetCompleteTypeImpl<SemIR::IntType>(
*this, SemIR::IntKind::Signed,
constant_values().GetInstId(bit_width_const_id));
}

auto Context::GetInterfaceType(SemIR::InterfaceId interface_id,
SemIR::SpecificId specific_id) -> SemIR::TypeId {
return GetTypeImpl<SemIR::FacetType>(
Expand Down
3 changes: 0 additions & 3 deletions toolchain/check/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,6 @@ class Context {
SemIR::SpecificId enclosing_specific_id)
-> SemIR::TypeId;

// Returns the type `i32`.
auto GetInt32Type() -> SemIR::TypeId;

// Gets the facet type corresponding to a particular interface.
auto GetInterfaceType(SemIR::InterfaceId interface_id,
SemIR::SpecificId specific_id) -> SemIR::TypeId;
Expand Down
8 changes: 6 additions & 2 deletions toolchain/check/handle_function.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "toolchain/check/handle.h"
#include "toolchain/check/import_ref.h"
#include "toolchain/check/interface.h"
#include "toolchain/check/literal.h"
#include "toolchain/check/merge.h"
#include "toolchain/check/modifiers.h"
#include "toolchain/check/name_component.h"
Expand Down Expand Up @@ -303,8 +304,11 @@ static auto BuildFunctionDecl(Context& context,
!function_info.param_patterns_id.is_valid() ||
!context.inst_blocks().Get(function_info.param_patterns_id).empty() ||
(return_type_id.is_valid() &&
return_type_id != context.GetInt32Type() &&
return_type_id != context.GetTupleType({}))) {
return_type_id != context.GetTupleType({}) &&
// TODO: Decide on valid return types for `Main.Run`. Perhaps we should
// have an interface for this.
return_type_id != MakeIntType(context, node_id, SemIR::IntKind::Signed,
context.ints().Add(32)))) {
CARBON_DIAGNOSTIC(InvalidMainRunSignature, Error,
"invalid signature for `Main.Run` function; expected "
"`fn ()` or `fn () -> i32`");
Expand Down
7 changes: 5 additions & 2 deletions toolchain/check/handle_if_expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "toolchain/check/context.h"
#include "toolchain/check/convert.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/literal.h"
#include "toolchain/sem_ir/builtin_inst_kind.h"

namespace Carbon::Check {
Expand Down Expand Up @@ -38,8 +39,10 @@ static auto DecayIntLiteralToSizedInt(Context& context, Parse::NodeId node_id,
-> SemIR::InstId {
if (context.types().GetInstId(context.insts().Get(operand_id).type_id()) ==
SemIR::InstId::BuiltinIntLiteralType) {
operand_id = ConvertToValueOfType(context, node_id, operand_id,
context.GetInt32Type());
operand_id = ConvertToValueOfType(
context, node_id, operand_id,
MakeIntType(context, node_id, SemIR::IntKind::Signed,
context.ints().Add(32)));
}
return operand_id;
}
Expand Down
6 changes: 5 additions & 1 deletion toolchain/check/handle_index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "toolchain/check/context.h"
#include "toolchain/check/convert.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/literal.h"
#include "toolchain/check/operator.h"
#include "toolchain/diagnostics/diagnostic.h"
#include "toolchain/sem_ir/builtin_inst_kind.h"
Expand Down Expand Up @@ -133,7 +134,10 @@ auto HandleParseNode(Context& context, Parse::IndexExprId node_id) -> bool {
case CARBON_KIND(SemIR::ArrayType array_type): {
auto index_loc_id = context.insts().GetLocId(index_inst_id);
auto cast_index_id = ConvertToValueOfType(
context, index_loc_id, index_inst_id, context.GetInt32Type());
context, index_loc_id, index_inst_id,
// TODO: Replace this with impl lookup rather than hardcoding `i32`.
MakeIntType(context, node_id, SemIR::IntKind::Signed,
context.ints().Add(32)));
auto array_cat =
SemIR::GetExprCategory(context.sem_ir(), operand_inst_id);
if (array_cat == SemIR::ExprCategory::Value) {
Expand Down
16 changes: 2 additions & 14 deletions toolchain/check/handle_literal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include "toolchain/check/call.h"
#include "toolchain/check/context.h"
#include "toolchain/check/handle.h"
#include "toolchain/check/literal.h"
#include "toolchain/diagnostics/format_providers.h"
#include "toolchain/sem_ir/typed_insts.h"

Expand All @@ -28,16 +29,6 @@ auto HandleParseNode(Context& context, Parse::BoolLiteralTrueId node_id)
return true;
}

// Forms an IntValue instruction with type `IntLiteral` for a given literal
// integer value, which is assumed to be unsigned.
static auto MakeIntLiteral(Context& context, Parse::NodeId node_id,
IntId int_id) -> SemIR::InstId {
return context.AddInst<SemIR::IntValue>(
node_id, {.type_id = context.GetBuiltinType(
SemIR::BuiltinInstKind::IntLiteralType),
.int_id = int_id});
}

auto HandleParseNode(Context& context, Parse::IntLiteralId node_id) -> bool {
auto int_literal_id = MakeIntLiteral(
context, node_id,
Expand Down Expand Up @@ -121,10 +112,7 @@ static auto HandleIntOrUnsignedIntTypeLiteral(Context& context,
node_id, IntWidthNotMultipleOf8, int_kind.is_signed(),
llvm::APSInt(context.ints().Get(size_id), /*isUnsigned=*/true));
}
auto width_id = MakeIntLiteral(context, node_id, size_id);
auto fn_inst_id = context.LookupNameInCore(
node_id, int_kind == SemIR::IntKind::Signed ? "Int" : "UInt");
auto type_inst_id = PerformCall(context, node_id, fn_inst_id, {width_id});
auto type_inst_id = MakeIntTypeLiteral(context, node_id, int_kind, size_id);
context.node_stack().Push(node_id, type_inst_id);
return true;
}
Expand Down
36 changes: 36 additions & 0 deletions toolchain/check/literal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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/literal.h"

#include "toolchain/check/call.h"
#include "toolchain/check/context.h"
#include "toolchain/check/convert.h"

namespace Carbon::Check {

auto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id)
-> SemIR::InstId {
return context.AddInst<SemIR::IntValue>(
node_id, {.type_id = context.GetBuiltinType(
SemIR::BuiltinInstKind::IntLiteralType),
.int_id = int_id});
}

auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,
SemIR::IntKind int_kind, IntId size_id)
-> SemIR::InstId {
auto width_id = MakeIntLiteral(context, node_id, size_id);
auto fn_inst_id = context.LookupNameInCore(
node_id, int_kind == SemIR::IntKind::Signed ? "Int" : "UInt");
return PerformCall(context, node_id, fn_inst_id, {width_id});
}

auto MakeIntType(Context& context, Parse::NodeId node_id,
SemIR::IntKind int_kind, IntId size_id) -> SemIR::TypeId {
auto type_inst_id = MakeIntTypeLiteral(context, node_id, int_kind, size_id);
return ExprAsType(context, node_id, type_inst_id).type_id;
}

} // namespace Carbon::Check
29 changes: 29 additions & 0 deletions toolchain/check/literal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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

#ifndef CARBON_TOOLCHAIN_CHECK_LITERAL_H_
#define CARBON_TOOLCHAIN_CHECK_LITERAL_H_

#include "toolchain/check/context.h"
#include "toolchain/sem_ir/ids.h"

namespace Carbon::Check {

// Forms an IntValue instruction with type `IntLiteral` for a given literal
// integer value, which is assumed to be unsigned.
auto MakeIntLiteral(Context& context, Parse::NodeId node_id, IntId int_id)
-> SemIR::InstId;

// Forms an integer type expression for either an `iN` or `uN` literal.
auto MakeIntTypeLiteral(Context& context, Parse::NodeId node_id,
SemIR::IntKind int_kind, IntId size_id)
-> SemIR::InstId;

// Forms an integer type of the specified kind and bit-width.
auto MakeIntType(Context& context, Parse::NodeId node_id,
SemIR::IntKind int_kind, IntId size_id) -> SemIR::TypeId;

} // namespace Carbon::Check

#endif // CARBON_TOOLCHAIN_CHECK_LITERAL_H_
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,19 @@ var b: i32 = a[{.index = 3}.index];
// CHECK:STDOUT: %struct: %.41 = struct_value (%.loc15_26) [template = constants.%struct]
// CHECK:STDOUT: %.loc15_27.2: %.41 = converted %.loc15_27.1, %struct [template = constants.%struct]
// CHECK:STDOUT: %.loc15_28.1: Core.IntLiteral = struct_access %.loc15_27.2, element0 [template = constants.%.2]
// CHECK:STDOUT: %.loc15_34.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc15_34.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc15_34.2: type = value_of_initializer %int.make_type_signed [template = constants.%i32]
// CHECK:STDOUT: %.loc15_34.3: type = converted %int.make_type_signed, %.loc15_34.2 [template = constants.%i32]
// CHECK:STDOUT: %.loc15_28.2: %Convert.type.2 = interface_witness_access constants.%.31, element0 [template = constants.%Convert.14]
// CHECK:STDOUT: %.loc15_28.3: <bound method> = bound_method %.loc15_28.1, %.loc15_28.2 [template = constants.%.38]
// CHECK:STDOUT: %.loc15_28.4: <specific function> = specific_function %.loc15_28.3, @Convert.2(constants.%.1) [template = constants.%.39]
// CHECK:STDOUT: %int.convert_checked.loc15: init %i32 = call %.loc15_28.4(%.loc15_28.1) [template = constants.%.40]
// CHECK:STDOUT: %.loc15_28.5: %i32 = value_of_initializer %int.convert_checked.loc15 [template = constants.%.40]
// CHECK:STDOUT: %.loc15_28.6: %i32 = converted %.loc15_28.1, %.loc15_28.5 [template = constants.%.40]
// CHECK:STDOUT: %.loc15_34.1: ref %i32 = array_index %a.ref, %.loc15_28.6 [template = <error>]
// CHECK:STDOUT: %.loc15_34.2: %i32 = bind_value %.loc15_34.1
// CHECK:STDOUT: assign file.%b.var, %.loc15_34.2
// CHECK:STDOUT: %.loc15_34.4: ref %i32 = array_index %a.ref, %.loc15_28.6 [template = <error>]
// CHECK:STDOUT: %.loc15_34.5: %i32 = bind_value %.loc15_34.4
// CHECK:STDOUT: assign file.%b.var, %.loc15_34.5
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
12 changes: 8 additions & 4 deletions toolchain/check/testdata/array/function_param.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,14 @@ fn G() -> i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %arr.ref: %.3 = name_ref arr, %arr
// CHECK:STDOUT: %i.ref: %i32 = name_ref i, %i
// CHECK:STDOUT: %.loc12_15.1: ref %.3 = value_as_ref %arr.ref
// CHECK:STDOUT: %.loc12_15.2: ref %i32 = array_index %.loc12_15.1, %i.ref
// CHECK:STDOUT: %.loc12_15.3: %i32 = bind_value %.loc12_15.2
// CHECK:STDOUT: return %.loc12_15.3
// CHECK:STDOUT: %.loc12_15.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed.loc12: init type = call constants.%Int(%.loc12_15.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc12_15.2: type = value_of_initializer %int.make_type_signed.loc12 [template = constants.%i32]
// CHECK:STDOUT: %.loc12_15.3: type = converted %int.make_type_signed.loc12, %.loc12_15.2 [template = constants.%i32]
// CHECK:STDOUT: %.loc12_15.4: ref %.3 = value_as_ref %arr.ref
// CHECK:STDOUT: %.loc12_15.5: ref %i32 = array_index %.loc12_15.4, %i.ref
// CHECK:STDOUT: %.loc12_15.6: %i32 = bind_value %.loc12_15.5
// CHECK:STDOUT: return %.loc12_15.6
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @G() -> %i32 {
Expand Down
10 changes: 7 additions & 3 deletions toolchain/check/testdata/array/index_not_literal.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,19 @@ var b: i32 = a[{.index = 2}.index];
// CHECK:STDOUT: %struct: %.41 = struct_value (%.loc12_26) [template = constants.%struct]
// CHECK:STDOUT: %.loc12_27.2: %.41 = converted %.loc12_27.1, %struct [template = constants.%struct]
// CHECK:STDOUT: %.loc12_28.1: Core.IntLiteral = struct_access %.loc12_27.2, element0 [template = constants.%.6]
// CHECK:STDOUT: %.loc12_34.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc12_34.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc12_34.2: type = value_of_initializer %int.make_type_signed [template = constants.%i32]
// CHECK:STDOUT: %.loc12_34.3: type = converted %int.make_type_signed, %.loc12_34.2 [template = constants.%i32]
// CHECK:STDOUT: %.loc12_28.2: %Convert.type.2 = interface_witness_access constants.%.31, element0 [template = constants.%Convert.14]
// CHECK:STDOUT: %.loc12_28.3: <bound method> = bound_method %.loc12_28.1, %.loc12_28.2 [template = constants.%.35]
// CHECK:STDOUT: %.loc12_28.4: <specific function> = specific_function %.loc12_28.3, @Convert.2(constants.%.1) [template = constants.%.36]
// CHECK:STDOUT: %int.convert_checked.loc12: init %i32 = call %.loc12_28.4(%.loc12_28.1) [template = constants.%.37]
// CHECK:STDOUT: %.loc12_28.5: %i32 = value_of_initializer %int.convert_checked.loc12 [template = constants.%.37]
// CHECK:STDOUT: %.loc12_28.6: %i32 = converted %.loc12_28.1, %.loc12_28.5 [template = constants.%.37]
// CHECK:STDOUT: %.loc12_34.1: ref %i32 = array_index %a.ref, %.loc12_28.6
// CHECK:STDOUT: %.loc12_34.2: %i32 = bind_value %.loc12_34.1
// CHECK:STDOUT: assign file.%b.var, %.loc12_34.2
// CHECK:STDOUT: %.loc12_34.4: ref %i32 = array_index %a.ref, %.loc12_28.6
// CHECK:STDOUT: %.loc12_34.5: %i32 = bind_value %.loc12_34.4
// CHECK:STDOUT: assign file.%b.var, %.loc12_34.5
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
9 changes: 9 additions & 0 deletions toolchain/check/testdata/basics/fail_bad_run.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ fn Run() -> String {}
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Run.type: type = fn_type @Run [template]
// CHECK:STDOUT: %Run: %Run.type = struct_value () [template]
// CHECK:STDOUT: %.1: Core.IntLiteral = int_value 32 [template]
// CHECK:STDOUT: %Int.type: type = fn_type @Int [template]
// CHECK:STDOUT: %Int: %Int.type = struct_value () [template]
// CHECK:STDOUT: %i32: type = int_type signed, %.1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .Int = %import_ref
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
Expand All @@ -44,6 +49,10 @@ fn Run() -> String {}
// CHECK:STDOUT: %return.param: ref String = out_param runtime_param0
// CHECK:STDOUT: %return: ref String = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc18_20.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc18_20.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc18_20.2: type = value_of_initializer %int.make_type_signed [template = constants.%i32]
// CHECK:STDOUT: %.loc18_20.3: type = converted %int.make_type_signed, %.loc18_20.2 [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() -> %return: String {
Expand Down
4 changes: 4 additions & 0 deletions toolchain/check/testdata/basics/run_i32.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ fn Run() -> i32 { return 0; }
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param0
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc11_17.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc11_17.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc11_17.2: type = value_of_initializer %int.make_type_signed [template = constants.%i32]
// CHECK:STDOUT: %.loc11_17.3: type = converted %int.make_type_signed, %.loc11_17.2 [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() -> %i32 {
Expand Down
4 changes: 4 additions & 0 deletions toolchain/check/testdata/class/basic.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ fn Run() -> i32 {
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param0
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc25_17.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc25_17.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc25_17.2: type = value_of_initializer %int.make_type_signed [template = constants.%i32]
// CHECK:STDOUT: %.loc25_17.3: type = converted %int.make_type_signed, %.loc25_17.2 [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Class {
Expand Down
4 changes: 4 additions & 0 deletions toolchain/check/testdata/class/static_method.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ fn Run() -> i32 {
// CHECK:STDOUT: %return.param: ref %i32 = out_param runtime_param0
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc15_17.1: Core.IntLiteral = int_value 32 [template = constants.%.1]
// CHECK:STDOUT: %int.make_type_signed: init type = call constants.%Int(%.loc15_17.1) [template = constants.%i32]
// CHECK:STDOUT: %.loc15_17.2: type = value_of_initializer %int.make_type_signed [template = constants.%i32]
// CHECK:STDOUT: %.loc15_17.3: type = converted %int.make_type_signed, %.loc15_17.2 [template = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Class {
Expand Down
Loading
Loading