Skip to content

Commit d939262

Browse files
authored
Add more testing of compound member access. (#3794)
Includes testing of indirect compound member access (`p->(M)`).
1 parent d0e8afc commit d939262

File tree

3 files changed

+295
-0
lines changed

3 files changed

+295
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
2+
// Exceptions. See /LICENSE for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
//
5+
// AUTOUPDATE
6+
7+
class Derived;
8+
9+
base class Base {
10+
fn F[self: Self]() -> i32;
11+
fn G[self: Derived]() -> i32;
12+
}
13+
14+
class Derived {
15+
extend base: Base;
16+
17+
fn F[self: Self]();
18+
fn G[self: Self]();
19+
}
20+
21+
fn Call(a: Derived) -> i32 {
22+
return a.(Base.F)();
23+
}
24+
25+
fn CallIndirect(p: Derived*) -> i32 {
26+
return p->(Base.F)();
27+
}
28+
29+
fn PassDerivedToBase(a: Derived) -> i32 {
30+
return a.(Base.G)();
31+
}
32+
33+
fn PassDerivedToBaseIndirect(p: Derived*) -> i32 {
34+
return p->(Base.G)();
35+
}
36+
37+
// CHECK:STDOUT: --- base_method_qualified.carbon
38+
// CHECK:STDOUT:
39+
// CHECK:STDOUT: constants {
40+
// CHECK:STDOUT: %Derived: type = class_type @Derived [template]
41+
// CHECK:STDOUT: %Base: type = class_type @Base [template]
42+
// CHECK:STDOUT: %.1: type = struct_type {} [template]
43+
// CHECK:STDOUT: %.2: type = tuple_type () [template]
44+
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
45+
// CHECK:STDOUT: %.4: type = unbound_element_type Derived, Base [template]
46+
// CHECK:STDOUT: %.5: type = struct_type {.base: Base} [template]
47+
// CHECK:STDOUT: %.6: type = struct_type {.base: {}*} [template]
48+
// CHECK:STDOUT: %.7: type = ptr_type {.base: Base} [template]
49+
// CHECK:STDOUT: %.8: type = ptr_type Derived [template]
50+
// CHECK:STDOUT: }
51+
// CHECK:STDOUT:
52+
// CHECK:STDOUT: file {
53+
// CHECK:STDOUT: package: <namespace> = namespace [template] {
54+
// CHECK:STDOUT: .Derived = %Derived.decl.loc7
55+
// CHECK:STDOUT: .Base = %Base.decl
56+
// CHECK:STDOUT: .Call = %Call
57+
// CHECK:STDOUT: .CallIndirect = %CallIndirect
58+
// CHECK:STDOUT: .PassDerivedToBase = %PassDerivedToBase
59+
// CHECK:STDOUT: .PassDerivedToBaseIndirect = %PassDerivedToBaseIndirect
60+
// CHECK:STDOUT: }
61+
// CHECK:STDOUT: %Derived.decl.loc7: type = class_decl @Derived [template = constants.%Derived] {}
62+
// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {}
63+
// CHECK:STDOUT: %Derived.decl.loc14: type = class_decl @Derived [template = constants.%Derived] {}
64+
// CHECK:STDOUT: %Call: <function> = fn_decl @Call [template] {
65+
// CHECK:STDOUT: %Derived.ref.loc21: type = name_ref Derived, %Derived.decl.loc7 [template = constants.%Derived]
66+
// CHECK:STDOUT: %a.loc21_9.1: Derived = param a
67+
// CHECK:STDOUT: @Call.%a: Derived = bind_name a, %a.loc21_9.1
68+
// CHECK:STDOUT: %return.var.loc21: ref i32 = var <return slot>
69+
// CHECK:STDOUT: }
70+
// CHECK:STDOUT: %CallIndirect: <function> = fn_decl @CallIndirect [template] {
71+
// CHECK:STDOUT: %Derived.ref.loc25: type = name_ref Derived, %Derived.decl.loc7 [template = constants.%Derived]
72+
// CHECK:STDOUT: %.loc25: type = ptr_type Derived [template = constants.%.8]
73+
// CHECK:STDOUT: %p.loc25_17.1: Derived* = param p
74+
// CHECK:STDOUT: @CallIndirect.%p: Derived* = bind_name p, %p.loc25_17.1
75+
// CHECK:STDOUT: %return.var.loc25: ref i32 = var <return slot>
76+
// CHECK:STDOUT: }
77+
// CHECK:STDOUT: %PassDerivedToBase: <function> = fn_decl @PassDerivedToBase [template] {
78+
// CHECK:STDOUT: %Derived.ref.loc29: type = name_ref Derived, %Derived.decl.loc7 [template = constants.%Derived]
79+
// CHECK:STDOUT: %a.loc29_22.1: Derived = param a
80+
// CHECK:STDOUT: @PassDerivedToBase.%a: Derived = bind_name a, %a.loc29_22.1
81+
// CHECK:STDOUT: %return.var.loc29: ref i32 = var <return slot>
82+
// CHECK:STDOUT: }
83+
// CHECK:STDOUT: %PassDerivedToBaseIndirect: <function> = fn_decl @PassDerivedToBaseIndirect [template] {
84+
// CHECK:STDOUT: %Derived.ref.loc33: type = name_ref Derived, %Derived.decl.loc7 [template = constants.%Derived]
85+
// CHECK:STDOUT: %.loc33: type = ptr_type Derived [template = constants.%.8]
86+
// CHECK:STDOUT: %p.loc33_30.1: Derived* = param p
87+
// CHECK:STDOUT: @PassDerivedToBaseIndirect.%p: Derived* = bind_name p, %p.loc33_30.1
88+
// CHECK:STDOUT: %return.var.loc33: ref i32 = var <return slot>
89+
// CHECK:STDOUT: }
90+
// CHECK:STDOUT: }
91+
// CHECK:STDOUT:
92+
// CHECK:STDOUT: class @Derived {
93+
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
94+
// CHECK:STDOUT: %.loc15: <unbound element of class Derived> = base_decl Base, element0 [template]
95+
// CHECK:STDOUT: %F: <function> = fn_decl @F.2 [template] {
96+
// CHECK:STDOUT: %Self.ref.loc17: type = name_ref Self, constants.%Derived [template = constants.%Derived]
97+
// CHECK:STDOUT: %self.loc17_8.1: Derived = param self
98+
// CHECK:STDOUT: %self.loc17_8.2: Derived = bind_name self, %self.loc17_8.1
99+
// CHECK:STDOUT: }
100+
// CHECK:STDOUT: %G: <function> = fn_decl @G.2 [template] {
101+
// CHECK:STDOUT: %Self.ref.loc18: type = name_ref Self, constants.%Derived [template = constants.%Derived]
102+
// CHECK:STDOUT: %self.loc18_8.1: Derived = param self
103+
// CHECK:STDOUT: %self.loc18_8.2: Derived = bind_name self, %self.loc18_8.1
104+
// CHECK:STDOUT: }
105+
// CHECK:STDOUT:
106+
// CHECK:STDOUT: !members:
107+
// CHECK:STDOUT: .Self = constants.%Derived
108+
// CHECK:STDOUT: .base = %.loc15
109+
// CHECK:STDOUT: .F = %F
110+
// CHECK:STDOUT: .G = %G
111+
// CHECK:STDOUT: extend name_scope1
112+
// CHECK:STDOUT: }
113+
// CHECK:STDOUT:
114+
// CHECK:STDOUT: class @Base {
115+
// CHECK:STDOUT: %F: <function> = fn_decl @F.1 [template] {
116+
// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%Base [template = constants.%Base]
117+
// CHECK:STDOUT: %self.loc10_8.1: Base = param self
118+
// CHECK:STDOUT: %self.loc10_8.2: Base = bind_name self, %self.loc10_8.1
119+
// CHECK:STDOUT: %return.var.loc10: ref i32 = var <return slot>
120+
// CHECK:STDOUT: }
121+
// CHECK:STDOUT: %G: <function> = fn_decl @G.1 [template] {
122+
// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl.loc7 [template = constants.%Derived]
123+
// CHECK:STDOUT: %self.loc11_8.1: Derived = param self
124+
// CHECK:STDOUT: %self.loc11_8.2: Derived = bind_name self, %self.loc11_8.1
125+
// CHECK:STDOUT: %return.var.loc11: ref i32 = var <return slot>
126+
// CHECK:STDOUT: }
127+
// CHECK:STDOUT:
128+
// CHECK:STDOUT: !members:
129+
// CHECK:STDOUT: .Self = constants.%Base
130+
// CHECK:STDOUT: .F = %F
131+
// CHECK:STDOUT: .G = %G
132+
// CHECK:STDOUT: }
133+
// CHECK:STDOUT:
134+
// CHECK:STDOUT: fn @F.1[@Base.%self.loc10_8.2: Base]() -> i32;
135+
// CHECK:STDOUT:
136+
// CHECK:STDOUT: fn @G.1[@Base.%self.loc11_8.2: Derived]() -> i32;
137+
// CHECK:STDOUT:
138+
// CHECK:STDOUT: fn @F.2[@Derived.%self.loc17_8.2: Derived]();
139+
// CHECK:STDOUT:
140+
// CHECK:STDOUT: fn @G.2[@Derived.%self.loc18_8.2: Derived]();
141+
// CHECK:STDOUT:
142+
// CHECK:STDOUT: fn @Call(%a: Derived) -> i32 {
143+
// CHECK:STDOUT: !entry:
144+
// CHECK:STDOUT: %a.ref: Derived = name_ref a, %a
145+
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
146+
// CHECK:STDOUT: %F.ref: <function> = name_ref F, @Base.%F [template = @Base.%F]
147+
// CHECK:STDOUT: %.loc22_11: <bound method> = bound_method %a.ref, %F.ref
148+
// CHECK:STDOUT: %.loc22_20.1: ref Base = class_element_access %a.ref, element0
149+
// CHECK:STDOUT: %.loc22_10.1: ref Base = converted %a.ref, %.loc22_20.1
150+
// CHECK:STDOUT: %.loc22_10.2: Base = bind_value %.loc22_10.1
151+
// CHECK:STDOUT: %.loc22_20.2: init i32 = call %.loc22_11(%.loc22_10.2)
152+
// CHECK:STDOUT: %.loc22_22: i32 = value_of_initializer %.loc22_20.2
153+
// CHECK:STDOUT: %.loc22_20.3: i32 = converted %.loc22_20.2, %.loc22_22
154+
// CHECK:STDOUT: return %.loc22_20.3
155+
// CHECK:STDOUT: }
156+
// CHECK:STDOUT:
157+
// CHECK:STDOUT: fn @CallIndirect(%p: Derived*) -> i32 {
158+
// CHECK:STDOUT: !entry:
159+
// CHECK:STDOUT: %p.ref: Derived* = name_ref p, %p
160+
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
161+
// CHECK:STDOUT: %F.ref: <function> = name_ref F, @Base.%F [template = @Base.%F]
162+
// CHECK:STDOUT: %.loc26_11.1: ref Derived = deref %p.ref
163+
// CHECK:STDOUT: %.loc26_11.2: <bound method> = bound_method %.loc26_11.1, %F.ref
164+
// CHECK:STDOUT: %.loc26_21.1: ref Base = class_element_access %.loc26_11.1, element0
165+
// CHECK:STDOUT: %.loc26_11.3: ref Base = converted %.loc26_11.1, %.loc26_21.1
166+
// CHECK:STDOUT: %.loc26_11.4: Base = bind_value %.loc26_11.3
167+
// CHECK:STDOUT: %.loc26_21.2: init i32 = call %.loc26_11.2(%.loc26_11.4)
168+
// CHECK:STDOUT: %.loc26_23: i32 = value_of_initializer %.loc26_21.2
169+
// CHECK:STDOUT: %.loc26_21.3: i32 = converted %.loc26_21.2, %.loc26_23
170+
// CHECK:STDOUT: return %.loc26_21.3
171+
// CHECK:STDOUT: }
172+
// CHECK:STDOUT:
173+
// CHECK:STDOUT: fn @PassDerivedToBase(%a: Derived) -> i32 {
174+
// CHECK:STDOUT: !entry:
175+
// CHECK:STDOUT: %a.ref: Derived = name_ref a, %a
176+
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
177+
// CHECK:STDOUT: %G.ref: <function> = name_ref G, @Base.%G [template = @Base.%G]
178+
// CHECK:STDOUT: %.loc30_11: <bound method> = bound_method %a.ref, %G.ref
179+
// CHECK:STDOUT: %.loc30_20.1: init i32 = call %.loc30_11(%a.ref)
180+
// CHECK:STDOUT: %.loc30_22: i32 = value_of_initializer %.loc30_20.1
181+
// CHECK:STDOUT: %.loc30_20.2: i32 = converted %.loc30_20.1, %.loc30_22
182+
// CHECK:STDOUT: return %.loc30_20.2
183+
// CHECK:STDOUT: }
184+
// CHECK:STDOUT:
185+
// CHECK:STDOUT: fn @PassDerivedToBaseIndirect(%p: Derived*) -> i32 {
186+
// CHECK:STDOUT: !entry:
187+
// CHECK:STDOUT: %p.ref: Derived* = name_ref p, %p
188+
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
189+
// CHECK:STDOUT: %G.ref: <function> = name_ref G, @Base.%G [template = @Base.%G]
190+
// CHECK:STDOUT: %.loc34_11.1: ref Derived = deref %p.ref
191+
// CHECK:STDOUT: %.loc34_11.2: <bound method> = bound_method %.loc34_11.1, %G.ref
192+
// CHECK:STDOUT: %.loc34_11.3: Derived = bind_value %.loc34_11.1
193+
// CHECK:STDOUT: %.loc34_21.1: init i32 = call %.loc34_11.2(%.loc34_11.3)
194+
// CHECK:STDOUT: %.loc34_23: i32 = value_of_initializer %.loc34_21.1
195+
// CHECK:STDOUT: %.loc34_21.2: i32 = converted %.loc34_21.1, %.loc34_23
196+
// CHECK:STDOUT: return %.loc34_21.2
197+
// CHECK:STDOUT: }
198+
// CHECK:STDOUT:

toolchain/check/testdata/class/compound_field.carbon

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ fn AccessBase(d: Derived) -> i32 {
2525
return d.(Base.b);
2626
}
2727

28+
fn AccessDerivedIndirect(p: Derived*) -> i32* {
29+
return &p->(Derived.d);
30+
}
31+
32+
fn AccessBaseIndirect(p: Derived*) -> i32* {
33+
return &p->(Base.b);
34+
}
35+
2836
// CHECK:STDOUT: --- compound_field.carbon
2937
// CHECK:STDOUT:
3038
// CHECK:STDOUT: constants {
@@ -39,6 +47,8 @@ fn AccessBase(d: Derived) -> i32 {
3947
// CHECK:STDOUT: %.7: type = struct_type {.base: {.a: i32, .b: i32, .c: i32}*, .d: i32, .e: i32} [template]
4048
// CHECK:STDOUT: %.8: type = ptr_type {.base: {.a: i32, .b: i32, .c: i32}*, .d: i32, .e: i32} [template]
4149
// CHECK:STDOUT: %.9: type = ptr_type {.base: Base, .d: i32, .e: i32} [template]
50+
// CHECK:STDOUT: %.10: type = ptr_type Derived [template]
51+
// CHECK:STDOUT: %.11: type = ptr_type i32 [template]
4252
// CHECK:STDOUT: }
4353
// CHECK:STDOUT:
4454
// CHECK:STDOUT: file {
@@ -47,6 +57,8 @@ fn AccessBase(d: Derived) -> i32 {
4757
// CHECK:STDOUT: .Derived = %Derived.decl
4858
// CHECK:STDOUT: .AccessDerived = %AccessDerived
4959
// CHECK:STDOUT: .AccessBase = %AccessBase
60+
// CHECK:STDOUT: .AccessDerivedIndirect = %AccessDerivedIndirect
61+
// CHECK:STDOUT: .AccessBaseIndirect = %AccessBaseIndirect
5062
// CHECK:STDOUT: }
5163
// CHECK:STDOUT: %Base.decl: type = class_decl @Base [template = constants.%Base] {}
5264
// CHECK:STDOUT: %Derived.decl: type = class_decl @Derived [template = constants.%Derived] {}
@@ -62,6 +74,22 @@ fn AccessBase(d: Derived) -> i32 {
6274
// CHECK:STDOUT: @AccessBase.%d: Derived = bind_name d, %d.loc24_15.1
6375
// CHECK:STDOUT: %return.var.loc24: ref i32 = var <return slot>
6476
// CHECK:STDOUT: }
77+
// CHECK:STDOUT: %AccessDerivedIndirect: <function> = fn_decl @AccessDerivedIndirect [template] {
78+
// CHECK:STDOUT: %Derived.ref.loc28: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
79+
// CHECK:STDOUT: %.loc28_36: type = ptr_type Derived [template = constants.%.10]
80+
// CHECK:STDOUT: %p.loc28_26.1: Derived* = param p
81+
// CHECK:STDOUT: @AccessDerivedIndirect.%p: Derived* = bind_name p, %p.loc28_26.1
82+
// CHECK:STDOUT: %.loc28_45: type = ptr_type i32 [template = constants.%.11]
83+
// CHECK:STDOUT: %return.var.loc28: ref i32* = var <return slot>
84+
// CHECK:STDOUT: }
85+
// CHECK:STDOUT: %AccessBaseIndirect: <function> = fn_decl @AccessBaseIndirect [template] {
86+
// CHECK:STDOUT: %Derived.ref.loc32: type = name_ref Derived, %Derived.decl [template = constants.%Derived]
87+
// CHECK:STDOUT: %.loc32_33: type = ptr_type Derived [template = constants.%.10]
88+
// CHECK:STDOUT: %p.loc32_23.1: Derived* = param p
89+
// CHECK:STDOUT: @AccessBaseIndirect.%p: Derived* = bind_name p, %p.loc32_23.1
90+
// CHECK:STDOUT: %.loc32_42: type = ptr_type i32 [template = constants.%.11]
91+
// CHECK:STDOUT: %return.var.loc32: ref i32* = var <return slot>
92+
// CHECK:STDOUT: }
6593
// CHECK:STDOUT: }
6694
// CHECK:STDOUT:
6795
// CHECK:STDOUT: class @Base {
@@ -112,3 +140,27 @@ fn AccessBase(d: Derived) -> i32 {
112140
// CHECK:STDOUT: return %.loc25_11.3
113141
// CHECK:STDOUT: }
114142
// CHECK:STDOUT:
143+
// CHECK:STDOUT: fn @AccessDerivedIndirect(%p: Derived*) -> i32* {
144+
// CHECK:STDOUT: !entry:
145+
// CHECK:STDOUT: %p.ref: Derived* = name_ref p, %p
146+
// CHECK:STDOUT: %Derived.ref: type = name_ref Derived, file.%Derived.decl [template = constants.%Derived]
147+
// CHECK:STDOUT: %d.ref: <unbound element of class Derived> = name_ref d, @Derived.%.loc16 [template = @Derived.%.loc16]
148+
// CHECK:STDOUT: %.loc29_12.1: ref Derived = deref %p.ref
149+
// CHECK:STDOUT: %.loc29_12.2: ref i32 = class_element_access %.loc29_12.1, element1
150+
// CHECK:STDOUT: %.loc29_10: i32* = addr_of %.loc29_12.2
151+
// CHECK:STDOUT: return %.loc29_10
152+
// CHECK:STDOUT: }
153+
// CHECK:STDOUT:
154+
// CHECK:STDOUT: fn @AccessBaseIndirect(%p: Derived*) -> i32* {
155+
// CHECK:STDOUT: !entry:
156+
// CHECK:STDOUT: %p.ref: Derived* = name_ref p, %p
157+
// CHECK:STDOUT: %Base.ref: type = name_ref Base, file.%Base.decl [template = constants.%Base]
158+
// CHECK:STDOUT: %b.ref: <unbound element of class Base> = name_ref b, @Base.%.loc9 [template = @Base.%.loc9]
159+
// CHECK:STDOUT: %.loc33_12.1: ref Derived = deref %p.ref
160+
// CHECK:STDOUT: %.loc33_12.2: ref Base = class_element_access %.loc33_12.1, element0
161+
// CHECK:STDOUT: %.loc33_12.3: ref Base = converted %.loc33_12.1, %.loc33_12.2
162+
// CHECK:STDOUT: %.loc33_12.4: ref i32 = class_element_access %.loc33_12.3, element1
163+
// CHECK:STDOUT: %.loc33_10: i32* = addr_of %.loc33_12.4
164+
// CHECK:STDOUT: return %.loc33_10
165+
// CHECK:STDOUT: }
166+
// CHECK:STDOUT:

toolchain/check/testdata/impl/compound.carbon

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ fn InstanceCall(n: i32) {
2222
n.(Simple.G)();
2323
}
2424

25+
fn NonInstanceCallIndirect(p: i32*) {
26+
p->(Simple.F)();
27+
}
28+
29+
fn InstanceCallIndirect(p: i32*) {
30+
p->(Simple.G)();
31+
}
32+
2533
// CHECK:STDOUT: --- compound.carbon
2634
// CHECK:STDOUT:
2735
// CHECK:STDOUT: constants {
@@ -31,13 +39,16 @@ fn InstanceCall(n: i32) {
3139
// CHECK:STDOUT: %.4: <associated <function> in Simple> = assoc_entity element1, @Simple.%G [template]
3240
// CHECK:STDOUT: %.5: <witness> = interface_witness (@impl.%F, @impl.%G) [template]
3341
// CHECK:STDOUT: %.6: type = tuple_type () [template]
42+
// CHECK:STDOUT: %.7: type = ptr_type i32 [template]
3443
// CHECK:STDOUT: }
3544
// CHECK:STDOUT:
3645
// CHECK:STDOUT: file {
3746
// CHECK:STDOUT: package: <namespace> = namespace [template] {
3847
// CHECK:STDOUT: .Simple = %Simple.decl
3948
// CHECK:STDOUT: .NonInstanceCall = %NonInstanceCall
4049
// CHECK:STDOUT: .InstanceCall = %InstanceCall
50+
// CHECK:STDOUT: .NonInstanceCallIndirect = %NonInstanceCallIndirect
51+
// CHECK:STDOUT: .InstanceCallIndirect = %InstanceCallIndirect
4152
// CHECK:STDOUT: }
4253
// CHECK:STDOUT: %Simple.decl: type = interface_decl @Simple [template = constants.%.1] {}
4354
// CHECK:STDOUT: impl_decl @impl {
@@ -51,6 +62,16 @@ fn InstanceCall(n: i32) {
5162
// CHECK:STDOUT: %n.loc21_17.1: i32 = param n
5263
// CHECK:STDOUT: @InstanceCall.%n: i32 = bind_name n, %n.loc21_17.1
5364
// CHECK:STDOUT: }
65+
// CHECK:STDOUT: %NonInstanceCallIndirect: <function> = fn_decl @NonInstanceCallIndirect [template] {
66+
// CHECK:STDOUT: %.loc25: type = ptr_type i32 [template = constants.%.7]
67+
// CHECK:STDOUT: %p.loc25_28.1: i32* = param p
68+
// CHECK:STDOUT: @NonInstanceCallIndirect.%p: i32* = bind_name p, %p.loc25_28.1
69+
// CHECK:STDOUT: }
70+
// CHECK:STDOUT: %InstanceCallIndirect: <function> = fn_decl @InstanceCallIndirect [template] {
71+
// CHECK:STDOUT: %.loc29: type = ptr_type i32 [template = constants.%.7]
72+
// CHECK:STDOUT: %p.loc29_25.1: i32* = param p
73+
// CHECK:STDOUT: @InstanceCallIndirect.%p: i32* = bind_name p, %p.loc29_25.1
74+
// CHECK:STDOUT: }
5475
// CHECK:STDOUT: }
5576
// CHECK:STDOUT:
5677
// CHECK:STDOUT: interface @Simple {
@@ -116,3 +137,27 @@ fn InstanceCall(n: i32) {
116137
// CHECK:STDOUT: return
117138
// CHECK:STDOUT: }
118139
// CHECK:STDOUT:
140+
// CHECK:STDOUT: fn @NonInstanceCallIndirect(%p: i32*) {
141+
// CHECK:STDOUT: !entry:
142+
// CHECK:STDOUT: %p.ref: i32* = name_ref p, %p
143+
// CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [template = constants.%.1]
144+
// CHECK:STDOUT: %F.ref: <associated <function> in Simple> = name_ref F, @Simple.%.loc8 [template = constants.%.3]
145+
// CHECK:STDOUT: %.loc26_4: ref i32 = deref %p.ref
146+
// CHECK:STDOUT: %.1: <function> = interface_witness_access @impl.%.1, element0 [template = @impl.%F]
147+
// CHECK:STDOUT: %.loc26_16: init () = call %.1()
148+
// CHECK:STDOUT: return
149+
// CHECK:STDOUT: }
150+
// CHECK:STDOUT:
151+
// CHECK:STDOUT: fn @InstanceCallIndirect(%p: i32*) {
152+
// CHECK:STDOUT: !entry:
153+
// CHECK:STDOUT: %p.ref: i32* = name_ref p, %p
154+
// CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [template = constants.%.1]
155+
// CHECK:STDOUT: %G.ref: <associated <function> in Simple> = name_ref G, @Simple.%.loc9_21 [template = constants.%.4]
156+
// CHECK:STDOUT: %.loc30_4.1: ref i32 = deref %p.ref
157+
// CHECK:STDOUT: %.1: <function> = interface_witness_access @impl.%.1, element1 [template = @impl.%G]
158+
// CHECK:STDOUT: %.loc30_4.2: <bound method> = bound_method %.loc30_4.1, %.1
159+
// CHECK:STDOUT: %.loc30_4.3: i32 = bind_value %.loc30_4.1
160+
// CHECK:STDOUT: %.loc30_16: init () = call %.loc30_4.2(%.loc30_4.3)
161+
// CHECK:STDOUT: return
162+
// CHECK:STDOUT: }
163+
// CHECK:STDOUT:

0 commit comments

Comments
 (0)