Use TupleAccess instead of TupleIndex (#4318)

This change removes the `TupleIndex` instruction, and instead
consolidate it with the `TupleAccess` instruction, per this
[discussion](https://discord.com/channels/655572317891461132/655578254970716160/1271195835975204946).
This change, in turn removes `AnyAggregateIndex`.
This commit is contained in:
Brymer Meneses
2024-09-17 20:26:48 +00:00
committed by GitHub
parent da40c8b076
commit 7f930d0f58
34 changed files with 75 additions and 125 deletions
+5 -9
View File
@@ -480,9 +480,9 @@ static auto PerformAggregateAccess(EvalContext& eval_context, SemIR::Inst inst)
// Performs an index into a homogeneous aggregate, retrieving the specified
// element.
static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst)
static auto PerformArrayIndex(EvalContext& eval_context, SemIR::Inst inst)
-> SemIR::ConstantId {
auto index_inst = inst.As<SemIR::AnyAggregateIndex>();
auto index_inst = inst.As<SemIR::ArrayIndex>();
Phase phase = Phase::Template;
auto index_id = GetConstantValue(eval_context, index_inst.index_id, &phase);
@@ -500,7 +500,7 @@ static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst)
// regardless of whether the array itself is constant.
const auto& index_val = eval_context.ints().Get(index->int_id);
auto aggregate_type_id = eval_context.GetConstantValueAsType(
eval_context.insts().Get(index_inst.aggregate_id).type_id());
eval_context.insts().Get(index_inst.array_id).type_id());
if (auto array_type =
eval_context.types().TryGetAs<SemIR::ArrayType>(aggregate_type_id)) {
if (auto bound = eval_context.insts().TryGetAs<SemIR::IntLiteral>(
@@ -523,7 +523,7 @@ static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst)
}
auto aggregate_id =
GetConstantValue(eval_context, index_inst.aggregate_id, &phase);
GetConstantValue(eval_context, index_inst.array_id, &phase);
if (!aggregate_id.is_valid()) {
return MakeNonConstantResult(phase);
}
@@ -536,9 +536,6 @@ static auto PerformAggregateIndex(EvalContext& eval_context, SemIR::Inst inst)
}
auto elements = eval_context.inst_blocks().Get(aggregate->elements_id);
// We checked this for the array case above.
CARBON_CHECK(index_val.ult(elements.size()),
"Index out of bounds in tuple indexing");
return eval_context.GetConstantValue(elements[index_val.getZExtValue()]);
}
@@ -1336,8 +1333,7 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
case SemIR::TupleAccess::Kind:
return PerformAggregateAccess(eval_context, inst);
case SemIR::ArrayIndex::Kind:
case SemIR::TupleIndex::Kind:
return PerformAggregateIndex(eval_context, inst);
return PerformArrayIndex(eval_context, inst);
case CARBON_KIND(SemIR::Call call): {
return MakeConstantForCall(eval_context, inst_id, call);
+2 -2
View File
@@ -29,7 +29,7 @@ auto HandleParseNode(Context& context, Parse::MemberAccessExprId node_id)
auto tuple_inst_id = context.node_stack().PopExpr();
auto tuple_value_inst_id =
PerformTupleIndex(context, node_id, tuple_inst_id, index_inst_id);
PerformTupleAccess(context, node_id, tuple_inst_id, index_inst_id);
context.node_stack().Push(node_id, tuple_value_inst_id);
} else {
@@ -70,7 +70,7 @@ auto HandleParseNode(Context& context, Parse::PointerMemberAccessExprId node_id)
auto tuple_inst_id = PerformPointerDereference(
context, node_id, tuple_pointer_inst_id, diagnose_not_pointer);
auto tuple_value_inst_id =
PerformTupleIndex(context, node_id, tuple_inst_id, index_inst_id);
PerformTupleAccess(context, node_id, tuple_inst_id, index_inst_id);
context.node_stack().Push(node_id, tuple_value_inst_id);
} else {
+23 -20
View File
@@ -498,7 +498,7 @@ auto PerformCompoundMemberAccess(
member_id, missing_impl_diagnoser);
} else if (context.insts().Is<SemIR::TupleType>(
context.constant_values().GetInstId(base_type_const_id))) {
return PerformTupleIndex(context, loc_id, base_id, member_expr_id);
return PerformTupleAccess(context, loc_id, base_id, member_expr_id);
}
// Perform instance binding if we found an instance member.
@@ -518,9 +518,9 @@ auto PerformCompoundMemberAccess(
return member_id;
}
auto PerformTupleIndex(Context& context, SemIR::LocId loc_id,
SemIR::InstId tuple_inst_id, SemIR::InstId index_inst_id)
-> SemIR::InstId {
auto PerformTupleAccess(Context& context, SemIR::LocId loc_id,
SemIR::InstId tuple_inst_id,
SemIR::InstId index_inst_id) -> SemIR::InstId {
tuple_inst_id = ConvertToValueOrRefExpr(context, tuple_inst_id);
auto tuple_inst = context.insts().Get(tuple_inst_id);
auto tuple_type_id = tuple_inst.type_id();
@@ -542,29 +542,32 @@ auto PerformTupleIndex(Context& context, SemIR::LocId loc_id,
context.GetBuiltinType(SemIR::BuiltinInstKind::IntType));
auto index_const_id = context.constant_values().Get(index_inst_id);
if (index_const_id == SemIR::ConstantId::Error) {
index_inst_id = SemIR::InstId::BuiltinError;
return SemIR::InstId::BuiltinError;
} else if (!index_const_id.is_template()) {
// TODO: Decide what to do if the index is a symbolic constant.
CARBON_DIAGNOSTIC(TupleIndexNotConstant, Error,
"Tuple index must be a constant.");
context.emitter().Emit(loc_id, TupleIndexNotConstant);
index_inst_id = SemIR::InstId::BuiltinError;
} else {
auto index_literal = context.insts().GetAs<SemIR::IntLiteral>(
context.constant_values().GetInstId(index_const_id));
auto type_block = context.type_blocks().Get(tuple_type->elements_id);
if (const auto* index_val = ValidateTupleIndex(
context, loc_id, tuple_inst, index_literal, type_block.size())) {
element_type_id = type_block[index_val->getZExtValue()];
} else {
index_inst_id = SemIR::InstId::BuiltinError;
}
return SemIR::InstId::BuiltinError;
}
return context.AddInst<SemIR::TupleIndex>(loc_id,
{.type_id = element_type_id,
.tuple_id = tuple_inst_id,
.index_id = index_inst_id});
auto index_literal = context.insts().GetAs<SemIR::IntLiteral>(
context.constant_values().GetInstId(index_const_id));
auto type_block = context.type_blocks().Get(tuple_type->elements_id);
const auto* index_val = ValidateTupleIndex(context, loc_id, tuple_inst,
index_literal, type_block.size());
if (!index_val) {
return SemIR::InstId::BuiltinError;
}
// TODO: Handle the case when `index_val->getZExtValue()` has too many bits.
element_type_id = type_block[index_val->getZExtValue()];
auto tuple_index = SemIR::ElementIndex(index_val->getZExtValue());
return context.AddInst<SemIR::TupleAccess>(loc_id,
{.type_id = element_type_id,
.tuple_id = tuple_inst_id,
.index = tuple_index});
}
} // namespace Carbon::Check
+3 -3
View File
@@ -28,9 +28,9 @@ auto PerformCompoundMemberAccess(
// Creates SemIR to perform a tuple index with base expression `tuple_inst_id`
// and index expression `index_inst_id`. Returns the result of the access.
auto PerformTupleIndex(Context& context, SemIR::LocId loc_id,
SemIR::InstId tuple_inst_id, SemIR::InstId index_inst_id)
-> SemIR::InstId;
auto PerformTupleAccess(Context& context, SemIR::LocId loc_id,
SemIR::InstId tuple_inst_id,
SemIR::InstId index_inst_id) -> SemIR::InstId;
} // namespace Carbon::Check
+1 -1
View File
@@ -175,7 +175,7 @@ var struct_access: [i32; 1] = (0,) as [i32; {.a = 3, .b = 1}.b];
// CHECK:STDOUT: %.loc15_56: i32 = int_literal 2 [template = constants.%.6]
// CHECK:STDOUT: %tuple: %.20 = tuple_value (%.loc15_44, %.loc15_47, %.loc15_50, %.loc15_53) [template = constants.%tuple.2]
// CHECK:STDOUT: %.loc15_54.2: %.20 = converted %.loc15_54.1, %tuple [template = constants.%tuple.2]
// CHECK:STDOUT: %.loc15_55: i32 = tuple_index %.loc15_54.2, %.loc15_56 [template = constants.%.5]
// CHECK:STDOUT: %.loc15_55: i32 = tuple_access %.loc15_54.2, element2 [template = constants.%.5]
// CHECK:STDOUT: %.loc15_38.1: type = value_of_initializer %int.make_type_32.loc15 [template = i32]
// CHECK:STDOUT: %.loc15_38.2: type = converted %int.make_type_32.loc15, %.loc15_38.1 [template = i32]
// CHECK:STDOUT: %.loc15_57: type = array_type %.loc15_55, i32 [template = constants.%.13]
@@ -129,7 +129,7 @@ fn H() -> i32 {
// CHECK:STDOUT: %G.call: init %.3 = call %G.ref() to %.loc20_11.1
// CHECK:STDOUT: %.loc20_14: i32 = int_literal 0 [template = constants.%.5]
// CHECK:STDOUT: %.loc20_11.2: ref %.3 = temporary %.loc20_11.1, %G.call
// CHECK:STDOUT: %.loc20_13.1: ref i32 = tuple_index %.loc20_11.2, %.loc20_14
// CHECK:STDOUT: %.loc20_13.1: ref i32 = tuple_access %.loc20_11.2, element0
// CHECK:STDOUT: %.loc20_13.2: i32 = bind_value %.loc20_13.1
// CHECK:STDOUT: return %.loc20_13.2
// CHECK:STDOUT: }
@@ -95,7 +95,7 @@ fn Main() {
// CHECK:STDOUT: %Foo.ref: %Foo.type = name_ref Foo, file.%Foo.decl [template = constants.%Foo]
// CHECK:STDOUT: %x.ref: ref %.3 = name_ref x, %x
// CHECK:STDOUT: %.loc16_9: i32 = int_literal 0 [template = constants.%.5]
// CHECK:STDOUT: %.loc16_8.1: ref i32 = tuple_index %x.ref, %.loc16_9
// CHECK:STDOUT: %.loc16_8.1: ref i32 = tuple_access %x.ref, element0
// CHECK:STDOUT: %.loc16_12: i32 = int_literal 6 [template = constants.%.6]
// CHECK:STDOUT: %.loc16_8.2: i32 = bind_value %.loc16_8.1
// CHECK:STDOUT: %Foo.call: init %.1 = call %Foo.ref(%.loc16_8.2, %.loc16_12)
+1 -1
View File
@@ -209,7 +209,7 @@ fn D() {}
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %c.ref: %.3 = name_ref c, %c
// CHECK:STDOUT: %.loc6_47: i32 = int_literal 0 [template = constants.%.5]
// CHECK:STDOUT: %.loc6_46: i32 = tuple_index %c.ref, %.loc6_47
// CHECK:STDOUT: %.loc6_46: i32 = tuple_access %c.ref, element0
// CHECK:STDOUT: %.loc6_48: %.4 = struct_literal (%.loc6_46)
// CHECK:STDOUT: %struct: %.4 = struct_value (%.loc6_46)
// CHECK:STDOUT: %.loc6_49: %.4 = converted %.loc6_48, %struct
+1 -1
View File
@@ -114,7 +114,7 @@ fn F() -> i32 {
// CHECK:STDOUT: %w: %.3 = bind_name w, %.loc14_29
// CHECK:STDOUT: %w.ref: %.3 = name_ref w, %w
// CHECK:STDOUT: %.loc15_12: i32 = int_literal 1 [template = constants.%.5]
// CHECK:STDOUT: %.loc15_11: i32 = tuple_index %w.ref, %.loc15_12
// CHECK:STDOUT: %.loc15_11: i32 = tuple_access %w.ref, element1
// CHECK:STDOUT: return %.loc15_11
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -112,12 +112,12 @@ fn Main() {
// CHECK:STDOUT: assign %b.var, %.loc15_29
// CHECK:STDOUT: %b.ref.loc16: ref %.5 = name_ref b, %b
// CHECK:STDOUT: %.loc16_5: i32 = int_literal 0 [template = constants.%.9]
// CHECK:STDOUT: %.loc16_4: ref i32 = tuple_index %b.ref.loc16, %.loc16_5
// CHECK:STDOUT: %.loc16_4: ref i32 = tuple_access %b.ref.loc16, element0
// CHECK:STDOUT: %.loc16_9: i32 = int_literal 3 [template = constants.%.10]
// CHECK:STDOUT: assign %.loc16_4, %.loc16_9
// CHECK:STDOUT: %b.ref.loc17: ref %.5 = name_ref b, %b
// CHECK:STDOUT: %.loc17_5: i32 = int_literal 1 [template = constants.%.7]
// CHECK:STDOUT: %.loc17_4: ref i32 = tuple_index %b.ref.loc17, %.loc17_5
// CHECK:STDOUT: %.loc17_4: ref i32 = tuple_access %b.ref.loc17, element1
// CHECK:STDOUT: %.loc17_9: i32 = int_literal 4 [template = constants.%.11]
// CHECK:STDOUT: assign %.loc17_4, %.loc17_9
// CHECK:STDOUT: %int.make_type_32.loc19_15: init type = call constants.%Int32() [template = i32]
+2 -2
View File
@@ -147,7 +147,7 @@ fn F() {
// CHECK:STDOUT: %t0: ref %.6 = bind_name t0, %t0.var
// CHECK:STDOUT: %t.ref.loc19: ref %.8 = name_ref t, %t
// CHECK:STDOUT: %.loc19_21: i32 = int_literal 0 [template = constants.%.10]
// CHECK:STDOUT: %.loc19_20: ref i32 = tuple_index %t.ref.loc19, %.loc19_21
// CHECK:STDOUT: %.loc19_20: ref i32 = tuple_access %t.ref.loc19, element0
// CHECK:STDOUT: %.loc19_18: %.6 = addr_of %.loc19_20
// CHECK:STDOUT: assign %t0.var, %.loc19_18
// CHECK:STDOUT: %int.make_type_32.loc20: init type = call constants.%Int32() [template = i32]
@@ -158,7 +158,7 @@ fn F() {
// CHECK:STDOUT: %t1: ref %.6 = bind_name t1, %t1.var
// CHECK:STDOUT: %t.ref.loc20: ref %.8 = name_ref t, %t
// CHECK:STDOUT: %.loc20_21: i32 = int_literal 1 [template = constants.%.4]
// CHECK:STDOUT: %.loc20_20: ref i32 = tuple_index %t.ref.loc20, %.loc20_21
// CHECK:STDOUT: %.loc20_20: ref i32 = tuple_access %t.ref.loc20, element1
// CHECK:STDOUT: %.loc20_18: %.6 = addr_of %.loc20_20
// CHECK:STDOUT: assign %t1.var, %.loc20_18
// CHECK:STDOUT: return
@@ -278,7 +278,7 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT: %.loc92_12: i32 = int_literal 0 [template = constants.%.3]
// CHECK:STDOUT: %tuple: %.13 = tuple_value (%.loc92_6, %.loc92_9) [template = constants.%tuple]
// CHECK:STDOUT: %.loc92_10.2: %.13 = converted %.loc92_10.1, %tuple [template = constants.%tuple]
// CHECK:STDOUT: %.loc92_11: i32 = tuple_index %.loc92_10.2, %.loc92_12 [template = constants.%.11]
// CHECK:STDOUT: %.loc92_11: i32 = tuple_access %.loc92_10.2, element0 [template = constants.%.11]
// CHECK:STDOUT: %.loc92_3: %.4 = addr_of <error> [template = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -86,7 +86,7 @@ var c: i32 = b.0;
// CHECK:STDOUT: assign file.%b.var, %.loc12_18
// CHECK:STDOUT: %b.ref: ref %.3 = name_ref b, file.%b
// CHECK:STDOUT: %.loc13_16: i32 = int_literal 0 [template = constants.%.5]
// CHECK:STDOUT: %.loc13_15.1: ref i32 = tuple_index %b.ref, %.loc13_16
// CHECK:STDOUT: %.loc13_15.1: ref i32 = tuple_access %b.ref, element0
// CHECK:STDOUT: %.loc13_15.2: i32 = bind_value %.loc13_15.1
// CHECK:STDOUT: assign file.%c.var, %.loc13_15.2
// CHECK:STDOUT: return
@@ -83,7 +83,6 @@ var b: i32 = a.(oops);
// CHECK:STDOUT: assign file.%a.var, %.loc11_28
// CHECK:STDOUT: %a.ref: ref %.3 = name_ref a, file.%a
// CHECK:STDOUT: %oops.ref: <error> = name_ref oops, <error> [template = <error>]
// CHECK:STDOUT: %.loc15: ref <error> = tuple_index %a.ref, <error> [template = <error>]
// CHECK:STDOUT: assign file.%b.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -64,7 +64,6 @@ fn Run() {
// CHECK:STDOUT: %.loc17_7: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc17_4.1: ref %.1 = temporary_storage
// CHECK:STDOUT: %.loc17_4.2: ref %.1 = temporary %.loc17_4.1, %F.call
// CHECK:STDOUT: %.loc17_6: ref <error> = tuple_index %.loc17_4.2, <error> [template = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -100,12 +100,10 @@ var d: i32 = b.(0x7FFF_FFFF);
// CHECK:STDOUT: %.loc12_18: init %.3 = converted %a.ref, %.loc12_17.3
// CHECK:STDOUT: assign file.%b.var, %.loc12_18
// CHECK:STDOUT: %b.ref.loc17: ref %.3 = name_ref b, file.%b
// CHECK:STDOUT: %.loc17_16: i32 = int_literal 1 [template = constants.%.5]
// CHECK:STDOUT: %.loc17_15: ref <error> = tuple_index %b.ref.loc17, <error> [template = <error>]
// CHECK:STDOUT: %.loc17: i32 = int_literal 1 [template = constants.%.5]
// CHECK:STDOUT: assign file.%c.var, <error>
// CHECK:STDOUT: %b.ref.loc21: ref %.3 = name_ref b, file.%b
// CHECK:STDOUT: %.loc21_17: i32 = int_literal 2147483647 [template = constants.%.6]
// CHECK:STDOUT: %.loc21_15: ref <error> = tuple_index %b.ref.loc21, <error> [template = <error>]
// CHECK:STDOUT: %.loc21: i32 = int_literal 2147483647 [template = constants.%.6]
// CHECK:STDOUT: assign file.%d.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -108,9 +108,8 @@ var b: i32 = a.(-10);
// CHECK:STDOUT: %.loc11_28: init %.3 = converted %.loc11_27.1, %.loc11_27.6 [template = constants.%tuple]
// CHECK:STDOUT: assign file.%a.var, %.loc11_28
// CHECK:STDOUT: %a.ref: ref %.3 = name_ref a, file.%a
// CHECK:STDOUT: %.loc15_18: i32 = int_literal 10 [template = constants.%.7]
// CHECK:STDOUT: %.loc15: i32 = int_literal 10 [template = constants.%.7]
// CHECK:STDOUT: %Op.ref: %.9 = name_ref Op, imports.%import_ref.4 [template = constants.%.10]
// CHECK:STDOUT: %.loc15_15: ref <error> = tuple_index %a.ref, <error> [template = <error>]
// CHECK:STDOUT: assign file.%b.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -93,8 +93,7 @@ var c: i32 = a.(b);
// CHECK:STDOUT: assign file.%b.var, %.loc12
// CHECK:STDOUT: %a.ref: ref %.3 = name_ref a, file.%a
// CHECK:STDOUT: %b.ref: ref i32 = name_ref b, file.%b
// CHECK:STDOUT: %.loc16_17: i32 = bind_value %b.ref
// CHECK:STDOUT: %.loc16_15: ref <error> = tuple_index %a.ref, <error> [template = <error>]
// CHECK:STDOUT: %.loc16: i32 = bind_value %b.ref
// CHECK:STDOUT: assign file.%c.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -141,7 +141,6 @@ var b: i32 = a.(2.6);
// CHECK:STDOUT: %.loc18_17.3: %.12 = specific_constant imports.%import_ref.4, @ImplicitAs(i32) [template = constants.%.13]
// CHECK:STDOUT: %Convert.ref: %.12 = name_ref Convert, %.loc18_17.3 [template = constants.%.13]
// CHECK:STDOUT: %.loc18_17.4: i32 = converted %.loc18_17.1, <error> [template = <error>]
// CHECK:STDOUT: %.loc18_15: ref <error> = tuple_index %a.ref, <error> [template = <error>]
// CHECK:STDOUT: assign file.%b.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -83,8 +83,7 @@ var b: i32 = a.2;
// CHECK:STDOUT: %.loc11_28: init %.3 = converted %.loc11_27.1, %.loc11_27.6 [template = constants.%tuple]
// CHECK:STDOUT: assign file.%a.var, %.loc11_28
// CHECK:STDOUT: %a.ref: ref %.3 = name_ref a, file.%a
// CHECK:STDOUT: %.loc15_16: i32 = int_literal 2 [template = constants.%.7]
// CHECK:STDOUT: %.loc15_15: ref <error> = tuple_index %a.ref, <error> [template = <error>]
// CHECK:STDOUT: %.loc15: i32 = int_literal 2 [template = constants.%.7]
// CHECK:STDOUT: assign file.%b.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -90,7 +90,6 @@ var b: i32 = a.({.index = 2}.index);
// CHECK:STDOUT: %struct: %.8 = struct_value (%.loc15_27) [template = constants.%struct]
// CHECK:STDOUT: %.loc15_28.2: %.8 = converted %.loc15_28.1, %struct [template = constants.%struct]
// CHECK:STDOUT: %.loc15_29: i32 = struct_access %.loc15_28.2, element0 [template = constants.%.7]
// CHECK:STDOUT: %.loc15_15: ref <error> = tuple_index %a.ref, <error> [template = <error>]
// CHECK:STDOUT: assign file.%b.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
@@ -87,7 +87,7 @@ var b: i32 = a.({.index = 1}.index);
// CHECK:STDOUT: %struct: %.8 = struct_value (%.loc12_27) [template = constants.%struct]
// CHECK:STDOUT: %.loc12_28.2: %.8 = converted %.loc12_28.1, %struct [template = constants.%struct]
// CHECK:STDOUT: %.loc12_29: i32 = struct_access %.loc12_28.2, element0 [template = constants.%.7]
// CHECK:STDOUT: %.loc12_15.1: ref i32 = tuple_index %a.ref, %.loc12_29
// CHECK:STDOUT: %.loc12_15.1: ref i32 = tuple_access %a.ref, element1
// CHECK:STDOUT: %.loc12_15.2: i32 = bind_value %.loc12_15.1
// CHECK:STDOUT: assign file.%b.var, %.loc12_15.2
// CHECK:STDOUT: return
@@ -86,7 +86,7 @@ fn Run() -> i32 {
// CHECK:STDOUT: %.loc14_14: i32 = int_literal 0 [template = constants.%.4]
// CHECK:STDOUT: %.loc14_11.1: ref %.3 = temporary_storage
// CHECK:STDOUT: %.loc14_11.2: ref %.3 = temporary %.loc14_11.1, %F.call
// CHECK:STDOUT: %.loc14_13.1: ref i32 = tuple_index %.loc14_11.2, %.loc14_14
// CHECK:STDOUT: %.loc14_13.1: ref i32 = tuple_access %.loc14_11.2, element0
// CHECK:STDOUT: %.loc14_13.2: i32 = bind_value %.loc14_13.1
// CHECK:STDOUT: return %.loc14_13.2
// CHECK:STDOUT: }
@@ -41,8 +41,7 @@ fn Main() {
// CHECK:STDOUT: %.loc15_16.1: %.1 = tuple_literal ()
// CHECK:STDOUT: %tuple: %.1 = tuple_value () [template = constants.%tuple]
// CHECK:STDOUT: %.loc15_16.2: %.1 = converted %.loc15_16.1, %tuple [template = constants.%tuple]
// CHECK:STDOUT: %.loc15_17.1: <error> = tuple_index %.loc15_16.2, <error> [template = <error>]
// CHECK:STDOUT: %.loc15_17.2: %.2 = converted %.loc15_16.1, <error> [template = <error>]
// CHECK:STDOUT: %.loc15_17: %.2 = converted %.loc15_16.1, <error> [template = <error>]
// CHECK:STDOUT: assign %x.var, <error>
// CHECK:STDOUT: return
// CHECK:STDOUT: }
-10
View File
@@ -248,16 +248,6 @@ auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
inst.type_id, "tuple.elem"));
}
auto HandleInst(FunctionContext& context, SemIR::InstId inst_id,
SemIR::TupleIndex inst) -> void {
auto index_inst =
context.sem_ir().insts().GetAs<SemIR::IntLiteral>(inst.index_id);
auto index = context.sem_ir().ints().Get(index_inst.int_id).getZExtValue();
context.SetLocal(inst_id, GetAggregateElement(context, inst.tuple_id,
SemIR::ElementIndex(index),
inst.type_id, "tuple.index"));
}
auto HandleInst(FunctionContext& /*context*/, SemIR::InstId /*inst_id*/,
SemIR::TupleLiteral /*inst*/) -> void {
// A TupleLiteral should always be converted to a TupleInit or TupleValue if
+3 -3
View File
@@ -38,9 +38,9 @@ fn F(c: C) -> i32 {
// CHECK:STDOUT: store i32 %.loc19_11.5, ptr %tuple2, align 4, !dbg !7
// CHECK:STDOUT: %tuple3 = getelementptr inbounds nuw { i32, i32, i32 }, ptr %tuple, i32 0, i32 2, !dbg !7
// CHECK:STDOUT: store i32 %.loc19_11.7, ptr %tuple3, align 4, !dbg !7
// CHECK:STDOUT: %.loc19_13.tuple.index = getelementptr inbounds nuw { i32, i32, i32 }, ptr %tuple, i32 0, i32 1, !dbg !7
// CHECK:STDOUT: %.loc19_13.tuple.index.load = load i32, ptr %.loc19_13.tuple.index, align 4, !dbg !7
// CHECK:STDOUT: ret i32 %.loc19_13.tuple.index.load, !dbg !8
// CHECK:STDOUT: %.loc19_13.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %tuple, i32 0, i32 1, !dbg !7
// CHECK:STDOUT: %.loc19_13.tuple.elem.load = load i32, ptr %.loc19_13.tuple.elem, align 4, !dbg !7
// CHECK:STDOUT: ret i32 %.loc19_13.tuple.elem.load, !dbg !8
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
@@ -23,17 +23,17 @@ fn Main() {
// CHECK:STDOUT:
// CHECK:STDOUT: define void @_CF.Main(ptr sret({ i32, i32, i32 }) %return, { i32 } %b, ptr %c) !dbg !4 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc12_12.tuple.index = extractvalue { i32 } %b, 0, !dbg !7
// CHECK:STDOUT: %.loc12_17.tuple.index = getelementptr inbounds nuw { i32, i32 }, ptr %c, i32 0, i32 0, !dbg !8
// CHECK:STDOUT: %.loc12_17.tuple.index.load = load i32, ptr %.loc12_17.tuple.index, align 4, !dbg !8
// CHECK:STDOUT: %.loc12_22.tuple.index = getelementptr inbounds nuw { i32, i32 }, ptr %c, i32 0, i32 1, !dbg !9
// CHECK:STDOUT: %.loc12_22.tuple.index.load = load i32, ptr %.loc12_22.tuple.index, align 4, !dbg !9
// CHECK:STDOUT: %.loc12_12.tuple.elem = extractvalue { i32 } %b, 0, !dbg !7
// CHECK:STDOUT: %.loc12_17.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %c, i32 0, i32 0, !dbg !8
// CHECK:STDOUT: %.loc12_17.tuple.elem.load = load i32, ptr %.loc12_17.tuple.elem, align 4, !dbg !8
// CHECK:STDOUT: %.loc12_22.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %c, i32 0, i32 1, !dbg !9
// CHECK:STDOUT: %.loc12_22.tuple.elem.load = load i32, ptr %.loc12_22.tuple.elem, align 4, !dbg !9
// CHECK:STDOUT: %.loc12_24.2.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %return, i32 0, i32 0, !dbg !10
// CHECK:STDOUT: store i32 %.loc12_12.tuple.index, ptr %.loc12_24.2.tuple.elem, align 4, !dbg !10
// CHECK:STDOUT: store i32 %.loc12_12.tuple.elem, ptr %.loc12_24.2.tuple.elem, align 4, !dbg !10
// CHECK:STDOUT: %.loc12_24.4.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %return, i32 0, i32 1, !dbg !10
// CHECK:STDOUT: store i32 %.loc12_17.tuple.index.load, ptr %.loc12_24.4.tuple.elem, align 4, !dbg !10
// CHECK:STDOUT: store i32 %.loc12_17.tuple.elem.load, ptr %.loc12_24.4.tuple.elem, align 4, !dbg !10
// CHECK:STDOUT: %.loc12_24.6.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %return, i32 0, i32 2, !dbg !10
// CHECK:STDOUT: store i32 %.loc12_22.tuple.index.load, ptr %.loc12_24.6.tuple.elem, align 4, !dbg !10
// CHECK:STDOUT: store i32 %.loc12_22.tuple.elem.load, ptr %.loc12_24.6.tuple.elem, align 4, !dbg !10
// CHECK:STDOUT: ret void, !dbg !11
// CHECK:STDOUT: }
// CHECK:STDOUT:
+5 -5
View File
@@ -59,11 +59,11 @@ fn F() -> i32 {
// CHECK:STDOUT: store ptr %tuple.loc14_43, ptr %tuple.loc14_476, align 8, !dbg !15
// CHECK:STDOUT: %tuple.loc14_477 = getelementptr inbounds nuw { ptr, ptr }, ptr %tuple.loc14_47, i32 0, i32 1, !dbg !15
// CHECK:STDOUT: store ptr %tuple.loc14_46, ptr %tuple.loc14_477, align 8, !dbg !15
// CHECK:STDOUT: %.loc15_11.tuple.index = getelementptr inbounds nuw { ptr, ptr }, ptr %tuple.loc14_47, i32 0, i32 1, !dbg !16
// CHECK:STDOUT: %.loc15_11.tuple.index.load = load ptr, ptr %.loc15_11.tuple.index, align 8, !dbg !16
// CHECK:STDOUT: %.loc15_13.tuple.index = getelementptr inbounds nuw { i32, i32 }, ptr %.loc15_11.tuple.index.load, i32 0, i32 1, !dbg !16
// CHECK:STDOUT: %.loc15_13.tuple.index.load = load i32, ptr %.loc15_13.tuple.index, align 4, !dbg !16
// CHECK:STDOUT: ret i32 %.loc15_13.tuple.index.load, !dbg !17
// CHECK:STDOUT: %.loc15_11.tuple.elem = getelementptr inbounds nuw { ptr, ptr }, ptr %tuple.loc14_47, i32 0, i32 1, !dbg !16
// CHECK:STDOUT: %.loc15_11.tuple.elem.load = load ptr, ptr %.loc15_11.tuple.elem, align 8, !dbg !16
// CHECK:STDOUT: %.loc15_13.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %.loc15_11.tuple.elem.load, i32 0, i32 1, !dbg !16
// CHECK:STDOUT: %.loc15_13.tuple.elem.load = load i32, ptr %.loc15_13.tuple.elem, align 4, !dbg !16
// CHECK:STDOUT: ret i32 %.loc15_13.tuple.elem.load, !dbg !17
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
@@ -28,12 +28,12 @@ fn Run() -> i32 {
// CHECK:STDOUT: %.loc12_36.6.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %a.var, i32 0, i32 2, !dbg !8
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %a.var, ptr align 4 @tuple.loc12_37, i64 12, i1 false), !dbg !9
// CHECK:STDOUT: %b.var = alloca i32, align 4, !dbg !10
// CHECK:STDOUT: %.loc13_17.1.tuple.index = getelementptr inbounds nuw { i32, i32, i32 }, ptr %a.var, i32 0, i32 0, !dbg !11
// CHECK:STDOUT: %.loc13_17.2 = load i32, ptr %.loc13_17.1.tuple.index, align 4, !dbg !11
// CHECK:STDOUT: %.loc13_17.1.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %a.var, i32 0, i32 0, !dbg !11
// CHECK:STDOUT: %.loc13_17.2 = load i32, ptr %.loc13_17.1.tuple.elem, align 4, !dbg !11
// CHECK:STDOUT: store i32 %.loc13_17.2, ptr %b.var, align 4, !dbg !12
// CHECK:STDOUT: %c.var = alloca i32, align 4, !dbg !13
// CHECK:STDOUT: %.loc14_17.1.tuple.index = getelementptr inbounds nuw { i32, i32, i32 }, ptr %a.var, i32 0, i32 2, !dbg !14
// CHECK:STDOUT: %.loc14_17.2 = load i32, ptr %.loc14_17.1.tuple.index, align 4, !dbg !14
// CHECK:STDOUT: %.loc14_17.1.tuple.elem = getelementptr inbounds nuw { i32, i32, i32 }, ptr %a.var, i32 0, i32 2, !dbg !14
// CHECK:STDOUT: %.loc14_17.2 = load i32, ptr %.loc14_17.1.tuple.elem, align 4, !dbg !14
// CHECK:STDOUT: store i32 %.loc14_17.2, ptr %c.var, align 4, !dbg !15
// CHECK:STDOUT: ret i32 0, !dbg !16
// CHECK:STDOUT: }
@@ -32,8 +32,8 @@ fn Run() {
// CHECK:STDOUT: %t.var = alloca i32, align 4, !dbg !10
// CHECK:STDOUT: %.loc14_17.1.temp = alloca { i32, i32 }, align 8, !dbg !11
// CHECK:STDOUT: call void @_CF.Main(ptr %.loc14_17.1.temp), !dbg !11
// CHECK:STDOUT: %.loc14_19.1.tuple.index = getelementptr inbounds nuw { i32, i32 }, ptr %.loc14_17.1.temp, i32 0, i32 1, !dbg !11
// CHECK:STDOUT: %.loc14_19.2 = load i32, ptr %.loc14_19.1.tuple.index, align 4, !dbg !11
// CHECK:STDOUT: %.loc14_19.1.tuple.elem = getelementptr inbounds nuw { i32, i32 }, ptr %.loc14_17.1.temp, i32 0, i32 1, !dbg !11
// CHECK:STDOUT: %.loc14_19.2 = load i32, ptr %.loc14_19.1.tuple.elem, align 4, !dbg !11
// CHECK:STDOUT: store i32 %.loc14_19.2, ptr %t.var, align 4, !dbg !12
// CHECK:STDOUT: ret void, !dbg !13
// CHECK:STDOUT: }
-6
View File
@@ -462,7 +462,6 @@ static auto StringifyTypeExprImpl(const SemIR::File& outer_sem_ir,
case Temporary::Kind:
case TemporaryStorage::Kind:
case TupleAccess::Kind:
case TupleIndex::Kind:
case TupleLiteral::Kind:
case TupleInit::Kind:
case TupleValue::Kind:
@@ -631,11 +630,6 @@ auto GetExprCategory(const File& file, InstId inst_id) -> ExprCategory {
continue;
}
case CARBON_KIND(TupleIndex inst): {
inst_id = inst.tuple_id;
continue;
}
case CARBON_KIND(SpliceBlock inst): {
inst_id = inst.result_id;
continue;
+1
View File
@@ -710,6 +710,7 @@ constexpr TypeBlockId TypeBlockId::Invalid = TypeBlockId(InvalidIndex);
// An index for element access, for structs, tuples, and classes.
struct ElementIndex : public IndexBase, public Printable<ElementIndex> {
using IndexBase::IndexBase;
auto Print(llvm::raw_ostream& out) const -> void {
out << "element";
IndexBase::Print(out);
-1
View File
@@ -86,7 +86,6 @@ CARBON_SEM_IR_INST_KIND(StructValue)
CARBON_SEM_IR_INST_KIND(TemporaryStorage)
CARBON_SEM_IR_INST_KIND(Temporary)
CARBON_SEM_IR_INST_KIND(TupleAccess)
CARBON_SEM_IR_INST_KIND(TupleIndex)
CARBON_SEM_IR_INST_KIND(TupleInit)
CARBON_SEM_IR_INST_KIND(TupleLiteral)
CARBON_SEM_IR_INST_KIND(TupleType)
-23
View File
@@ -99,18 +99,6 @@ struct AnyAggregateAccess {
ElementIndex index;
};
// Common representation for aggregate index nodes, which access an element
// determined by evaluating an expression.
struct AnyAggregateIndex {
static constexpr InstKind Kinds[] = {InstKind::ArrayIndex,
InstKind::TupleIndex};
InstKind kind;
TypeId type_id;
InstId aggregate_id;
InstId index_id;
};
// Common representation for all kinds of aggregate initialization.
struct AnyAggregateInit {
static constexpr InstKind Kinds[] = {InstKind::ArrayInit, InstKind::ClassInit,
@@ -961,17 +949,6 @@ struct TupleAccess {
ElementIndex index;
};
// Access to a tuple member by index, such as `tuple[index]`.
struct TupleIndex {
// TODO: Make Parse::NodeId more specific.
static constexpr auto Kind =
InstKind::TupleIndex.Define<Parse::NodeId>({.ir_name = "tuple_index"});
TypeId type_id;
InstId tuple_id;
InstId index_id;
};
// Initializes the destination tuple with the given elements.
struct TupleInit {
static constexpr auto Kind =