mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 18:40:16 +01:00
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:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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]
|
||||
|
||||
@@ -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: }
|
||||
|
||||
@@ -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
@@ -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
@@ -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: }
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 =
|
||||
|
||||
Reference in New Issue
Block a user