mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 22:02:55 +01:00
When making a direct call to a thunk, inline the call in SemIR. (#5642)
This preserves the constant values of the arguments to the thunk, which is important if the thunk requires conversion of an `IntLiteral` to some other type. This should become unnecessary once we have form support, but avoiding the indirection through a thunk function seems valuable even once that support is in place. To support this, track whether a function is a thunk on the Function object, and if so, what the callee of the thunk is. This information is also included in formatted SemIR when dumping the thunk.
This commit is contained in:
+5
-3
@@ -148,7 +148,7 @@ fn InstanceCall(n: i32) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @G.2(%self.param: <error>);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @G.3(%self.param: %i32) {
|
||||
// CHECK:STDOUT: fn @G.3(%self.param: %i32) [thunk @impl.006.%G.decl.loc23_27.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %G.ref: %G.type.c9825d.1 = name_ref G, @impl.006.%G.decl.loc23_27.1 [concrete = constants.%G.e73e91.1]
|
||||
// CHECK:STDOUT: %self.ref: %i32 = name_ref self, %self.param
|
||||
@@ -161,10 +161,12 @@ fn InstanceCall(n: i32) {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %n.ref: %i32 = name_ref n, %n
|
||||
// CHECK:STDOUT: %Simple.ref: type = name_ref Simple, file.%Simple.decl [concrete = constants.%Simple.type]
|
||||
// CHECK:STDOUT: %G.ref: %Simple.assoc_type = name_ref G, @Simple.%assoc0 [concrete = constants.%assoc0.db2]
|
||||
// CHECK:STDOUT: %G.ref.loc27_12: %Simple.assoc_type = name_ref G, @Simple.%assoc0 [concrete = constants.%assoc0.db2]
|
||||
// CHECK:STDOUT: %impl.elem0: %.8e6 = impl_witness_access constants.%Simple.impl_witness, element0 [concrete = constants.%G.e73e91.2]
|
||||
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %n.ref, %impl.elem0
|
||||
// CHECK:STDOUT: %G.call: init %empty_tuple.type = call %bound_method(%n.ref)
|
||||
// CHECK:STDOUT: %G.ref.loc27_16: %G.type.c9825d.1 = name_ref G, @impl.006.%G.decl.loc23_27.1 [concrete = constants.%G.e73e91.1]
|
||||
// CHECK:STDOUT: %G.bound: <bound method> = bound_method %n.ref, %G.ref.loc27_16
|
||||
// CHECK:STDOUT: %G.call: init %empty_tuple.type = call %G.bound(<error>)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+23
-15
@@ -1199,7 +1199,7 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%b.param: bool);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3() {
|
||||
// CHECK:STDOUT: fn @F.3() [thunk @impl.ddd.%F.decl.loc68_18.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.44ef8c.1 = name_ref F, @impl.ddd.%F.decl.loc68_18.1 [concrete = constants.%F.424e9e.1]
|
||||
// CHECK:STDOUT: return
|
||||
@@ -1207,7 +1207,7 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.4(%self.param: %FExtraImplicitParam);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.5() {
|
||||
// CHECK:STDOUT: fn @F.5() [thunk @impl.698.%F.decl.loc84_23.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.e1abdd.1 = name_ref F, @impl.698.%F.decl.loc84_23.1 [concrete = constants.%F.6ff574.1]
|
||||
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.ref(<error>)
|
||||
@@ -1222,22 +1222,24 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.8(%self.param: bool) -> bool;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.9(%self.param: bool, %b.param: bool) -> bool {
|
||||
// CHECK:STDOUT: fn @F.9(%self.param: bool, %b.param: bool) -> bool [thunk @impl.5cf.%F.decl.loc116_31.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.69596c.1 = name_ref F, @impl.5cf.%F.decl.loc116_31.1 [concrete = constants.%F.738f31.1]
|
||||
// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param
|
||||
// CHECK:STDOUT: %return.ref: ref bool = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.10(%b.param: bool) -> bool;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.11(%self.param: bool, %b.param: bool) -> bool {
|
||||
// CHECK:STDOUT: fn @F.11(%self.param: bool, %b.param: bool) -> bool [thunk @impl.bac.%F.decl.loc129_26.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.d97cef.1 = name_ref F, @impl.bac.%F.decl.loc129_26.1 [concrete = constants.%F.01de92.1]
|
||||
// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param
|
||||
// CHECK:STDOUT: %return.ref: ref bool = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.call: init bool = call %F.ref(%b.ref)
|
||||
// CHECK:STDOUT: %.loc129_26.1: bool = value_of_initializer %F.call
|
||||
// CHECK:STDOUT: %.loc129_26.2: bool = converted %F.call, %.loc129_26.1
|
||||
@@ -1246,12 +1248,13 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.12(%self.param: bool, %b.param: bool);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.13(%self.param: bool, %b.param: bool) -> bool {
|
||||
// CHECK:STDOUT: fn @F.13(%self.param: bool, %b.param: bool) -> bool [thunk @impl.1a7.%F.decl.loc151_30.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.123d7a.1 = name_ref F, @impl.1a7.%F.decl.loc151_30.1 [concrete = constants.%F.c7d02d.1]
|
||||
// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param
|
||||
// CHECK:STDOUT: %return.ref: ref bool = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.bound(%self.ref, %b.ref)
|
||||
// CHECK:STDOUT: %.loc151: bool = converted %F.call, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: return <error>
|
||||
@@ -1259,12 +1262,13 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.14(%self.param: bool, %b.param: %FDifferentParamType) -> bool;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.15(%self.param: bool, %b.param: bool) -> bool {
|
||||
// CHECK:STDOUT: fn @F.15(%self.param: bool, %b.param: bool) -> bool [thunk @impl.f2b.%F.decl.loc170_38.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.6b537d.1 = name_ref F, @impl.f2b.%F.decl.loc170_38.1 [concrete = constants.%F.04313a.1]
|
||||
// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param
|
||||
// CHECK:STDOUT: %return.ref: ref bool = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %.loc102: %FDifferentParamType = converted %b.ref, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %F.call: init bool = call %F.bound(%self.ref, <error>)
|
||||
// CHECK:STDOUT: %.loc170_38.1: bool = value_of_initializer %F.call
|
||||
@@ -1274,12 +1278,13 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.16(%self.param: %FDifferentImplicitParamType, %b.param: bool) -> bool;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.17(%self.param: bool, %b.param: bool) -> bool {
|
||||
// CHECK:STDOUT: fn @F.17(%self.param: bool, %b.param: bool) -> bool [thunk @impl.db4.%F.decl.loc183_38.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.d6232a.1 = name_ref F, @impl.db4.%F.decl.loc183_38.1 [concrete = constants.%F.886f70.1]
|
||||
// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param
|
||||
// CHECK:STDOUT: %return.ref: ref bool = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %.loc102: %FDifferentImplicitParamType = converted %self.ref, <error> [concrete = <error>]
|
||||
// CHECK:STDOUT: %F.call: init bool = call %F.bound(<error>, %b.ref)
|
||||
// CHECK:STDOUT: %.loc183_38.1: bool = value_of_initializer %F.call
|
||||
@@ -1289,12 +1294,13 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.18(%self.param: bool, %b.param: bool) -> %return.param: %FDifferentReturnType;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.19(%self.param: bool, %b.param: bool) -> bool {
|
||||
// CHECK:STDOUT: fn @F.19(%self.param: bool, %b.param: bool) -> bool [thunk @impl.fcc.%F.decl.loc199_38.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.d3b58f.1 = name_ref F, @impl.fcc.%F.decl.loc199_38.1 [concrete = constants.%F.be86c9.1]
|
||||
// CHECK:STDOUT: %self.ref: bool = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %b.ref: bool = name_ref b, %b.param
|
||||
// CHECK:STDOUT: %return.ref: ref bool = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %.loc199_38.1: ref %FDifferentReturnType = temporary_storage
|
||||
// CHECK:STDOUT: %F.call: init %FDifferentReturnType = call %F.bound(%self.ref, %b.ref) to %.loc199_38.1
|
||||
// CHECK:STDOUT: %.loc199_38.2: bool = converted %F.call, <error> [concrete = <error>]
|
||||
@@ -1316,10 +1322,11 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.21(%x.param: %tuple.type.a7d) -> %return.param: %array_type.a41;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.22(%x.param: %tuple.type.9c9) -> %return.param: %array_type.a41 {
|
||||
// CHECK:STDOUT: fn @F.22(%x.param: %tuple.type.9c9) -> %return.param: %array_type.a41 [thunk @impl.6a5.%F.decl.loc222_87.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.f90165.1 = name_ref F, @impl.6a5.%F.decl.loc222_87.1 [concrete = constants.%F.fa8d04.1]
|
||||
// CHECK:STDOUT: %x.ref: %tuple.type.9c9 = name_ref x, %x.param
|
||||
// CHECK:STDOUT: %return.ref: ref %array_type.a41 = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %.loc210_41: ref %array_type.a41 = splice_block %return {}
|
||||
// CHECK:STDOUT: %tuple.elem0: %ptr.4cd = tuple_access %x.ref, element0
|
||||
// CHECK:STDOUT: %tuple.elem1: %struct_type.x.y.a89 = tuple_access %x.ref, element1
|
||||
@@ -1331,10 +1338,11 @@ class SelfNestedBadReturnType {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.23(%x.param: %tuple.type.eb9) -> %return.param: %array_type.a41;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.24(%x.param: %tuple.type.eb9) -> %return.param: %array_type.126 {
|
||||
// CHECK:STDOUT: fn @F.24(%x.param: %tuple.type.eb9) -> %return.param: %array_type.126 [thunk @impl.bfc.%F.decl.loc238_112.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.0e7d1d.1 = name_ref F, @impl.bfc.%F.decl.loc238_112.1 [concrete = constants.%F.0bc78a.1]
|
||||
// CHECK:STDOUT: %x.ref: %tuple.type.eb9 = name_ref x, %x.param
|
||||
// CHECK:STDOUT: %return.ref: ref %array_type.126 = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %.loc238_112.1: ref %array_type.a41 = temporary_storage
|
||||
// CHECK:STDOUT: %F.call: init %array_type.a41 = call %F.ref(%x.ref) to %.loc238_112.1
|
||||
// CHECK:STDOUT: %.loc238_112.2: %array_type.126 = converted %F.call, <error> [concrete = <error>]
|
||||
|
||||
@@ -240,7 +240,7 @@ impl i32 as I {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%c.param: %C.6fb);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.4(%c.param: %C.d88) {
|
||||
// CHECK:STDOUT: fn @F.4(%c.param: %C.d88) [thunk @impl.a9a.%F.decl.loc42_18.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.066a53.1 = name_ref F, @impl.a9a.%F.decl.loc42_18.1 [concrete = constants.%F.9ec58f.1]
|
||||
// CHECK:STDOUT: %c.ref: %C.d88 = name_ref c, %c.param
|
||||
|
||||
+10
-8
@@ -359,7 +359,7 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%y.param: %struct_type.b.a.40c) -> %return.param: %struct_type.d.c.b36;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%x.param: %struct_type.a.b.391) -> %return.param: %struct_type.c.d.15a {
|
||||
// CHECK:STDOUT: fn @F.3(%x.param: %struct_type.a.b.391) -> %return.param: %struct_type.c.d.15a [thunk @impl.%F.decl.loc10_48.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.39e918.1 = name_ref F, @impl.%F.decl.loc10_48.1 [concrete = constants.%F.c04b92.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -440,7 +440,7 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%self.param: %ptr.6db, %other.param: %ptr.6db) -> %ptr.019;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %ptr.e79, %other.param: %ptr.e79) -> %ptr.e79 {
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %ptr.e79, %other.param: %ptr.e79) -> %ptr.e79 [thunk @impl.%F.decl.loc14_39.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.f1b0b1.1 = name_ref F, @impl.%F.decl.loc14_39.1 [concrete = constants.%F.5161e9.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -497,7 +497,7 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%self.param: %A, %other.param: %A);
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %B, %other.param: %B) {
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %B, %other.param: %B) [thunk @impl.%F.decl.loc13_26.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.f1b0b1.1 = name_ref F, @impl.%F.decl.loc13_26.1 [concrete = constants.%F.5161e9.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -567,7 +567,7 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2(%self.param: %ptr.6db, %other.param: %ptr.6db) -> %ptr.019;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %ptr.e79, %other.param: %ptr.e79) -> %ptr.e79 {
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %ptr.e79, %other.param: %ptr.e79) -> %ptr.e79 [thunk @impl.%F.decl.loc14_39.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.f1b0b1.1 = name_ref F, @impl.%F.decl.loc14_39.1 [concrete = constants.%F.5161e9.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -618,9 +618,10 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2() -> %return.param: %B;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3() -> %return.param: %A {
|
||||
// CHECK:STDOUT: fn @F.3() -> %return.param: %A [thunk @impl.%F.decl.loc20_14.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.b24d6f.1 = name_ref F, @impl.%F.decl.loc20_14.1 [concrete = constants.%F.77e9d5.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %.loc20_14.1: ref %B = temporary_storage
|
||||
// CHECK:STDOUT: %F.call: init %B = call %F.ref() to %.loc20_14.1
|
||||
// CHECK:STDOUT: %.loc20_14.2: ref %B = temporary %.loc20_14.1, %F.call
|
||||
@@ -696,7 +697,7 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT: %F.specific_fn.loc10_29.2: <specific function> = specific_function constants.%F.c04b92.1, @F.2(%ptr) [symbolic = %F.specific_fn.loc10_29.2 (constants.%F.specific_fn)]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn(%x.param: @F.3.%ptr (%ptr.79f)) -> @F.3.%ptr (%ptr.79f) {
|
||||
// CHECK:STDOUT: fn(%x.param: @F.3.%ptr (%ptr.79f)) -> @F.3.%ptr (%ptr.79f) [thunk @impl.%F.decl.loc10_29.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.39e918.1 = name_ref F, @impl.%F.decl.loc10_29.1 [concrete = constants.%F.c04b92.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -799,7 +800,7 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !definition:
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn(%self.param: %empty_tuple.type, %x.param: @F.3.%ptr (%ptr.79f)) -> @F.3.%ptr (%ptr.79f) {
|
||||
// CHECK:STDOUT: fn(%self.param: %empty_tuple.type, %x.param: @F.3.%ptr (%ptr.79f)) -> @F.3.%ptr (%ptr.79f) [thunk @impl.%F.decl.loc19_39.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.39e918.1 = name_ref F, @impl.%F.decl.loc19_39.1 [concrete = constants.%F.c04b92.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
@@ -859,9 +860,10 @@ impl () as I({}) {
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.2() -> %return.param: %struct_type.b.a.1b0;
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3() -> %return.param: %struct_type.a.b.f95 {
|
||||
// CHECK:STDOUT: fn @F.3() -> %return.param: %struct_type.a.b.f95 [thunk @impl.%F.decl.loc10_29.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.29ab63.1 = name_ref F, @impl.%F.decl.loc10_29.1 [concrete = constants.%F.975709.1]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %.loc10_29.1: ref %struct_type.b.a.1b0 = temporary_storage
|
||||
// CHECK:STDOUT: %F.call: init %struct_type.b.a.1b0 = call %F.ref() to %.loc10_29.1
|
||||
// CHECK:STDOUT: %.loc10_29.2: ref %struct_type.b.a.1b0 = temporary %.loc10_29.1, %F.call
|
||||
|
||||
@@ -78,3 +78,84 @@ interface OpWith(U:! type) {
|
||||
impl forall [T:! type, U:! Core.ImplicitAs(Wrap(T))] Wrap(T) as OpWith(U) {
|
||||
fn Op[self: Self](other: Self) = "no_op";
|
||||
}
|
||||
|
||||
// --- thunk_literal_convert.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
fn IntLiteral() -> type = "int_literal.make_type";
|
||||
fn Int(size: IntLiteral()) -> type = "int.make_type_signed";
|
||||
|
||||
impl IntLiteral() as Core.ImplicitAs(Int(32)) {
|
||||
fn Convert[self: Self]() -> Int(32) = "int.convert_checked";
|
||||
}
|
||||
|
||||
interface Add(T:! type) {
|
||||
fn Op(a: Self, b: T) -> Self;
|
||||
}
|
||||
impl forall [T:! Core.ImplicitAs(Int(32))] Int(32) as Add(T) {
|
||||
fn Op(a: Self, b: Self) -> Self = "int.sadd";
|
||||
}
|
||||
|
||||
fn Call() -> Int(32) {
|
||||
let a: Int(32) = 1;
|
||||
// The conversion from 2 to IntLiteral here relies on having the
|
||||
// constant value available, so is only possible if the thunk is
|
||||
// inlined.
|
||||
return Int(32).(Add(IntLiteral()).Op)
|
||||
//@dump-sem-ir-begin
|
||||
(a, 2)
|
||||
//@dump-sem-ir-end
|
||||
;
|
||||
}
|
||||
|
||||
// CHECK:STDOUT: --- thunk_literal_convert.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
|
||||
// CHECK:STDOUT: %i32.builtin: type = int_type signed, %int_32 [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.type.61e: type = facet_type <@ImplicitAs, @ImplicitAs(%i32.builtin)> [concrete]
|
||||
// CHECK:STDOUT: %Convert.type.059: type = fn_type @Convert.1, @ImplicitAs(%i32.builtin) [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.impl_witness: <witness> = impl_witness file.%ImplicitAs.impl_witness_table [concrete]
|
||||
// CHECK:STDOUT: %Convert.type.1dd: type = fn_type @Convert.2 [concrete]
|
||||
// CHECK:STDOUT: %Convert.52c: %Convert.type.1dd = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ImplicitAs.facet.54f: %ImplicitAs.type.61e = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness) [concrete]
|
||||
// CHECK:STDOUT: %.f22: type = fn_type_with_self_type %Convert.type.059, %ImplicitAs.facet.54f [concrete]
|
||||
// CHECK:STDOUT: %Op.type.049d3a.1: type = fn_type @Op.2, @impl.797(%ImplicitAs.facet.54f) [concrete]
|
||||
// CHECK:STDOUT: %Op.1fb3b5.1: %Op.type.049d3a.1 = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]
|
||||
// CHECK:STDOUT: %Convert.bound.713: <bound method> = bound_method %int_2.ecc, %Convert.52c [concrete]
|
||||
// CHECK:STDOUT: %int_2.5a1: %i32.builtin = int_value 2 [concrete]
|
||||
// CHECK:STDOUT: %Op.specific_fn.01379b.2: <specific function> = specific_function %Op.1fb3b5.1, @Op.2(%ImplicitAs.facet.54f) [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @Call() -> %i32.builtin {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %a.ref: %i32.builtin = name_ref a, %a
|
||||
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
|
||||
// CHECK:STDOUT: %ImplicitAs.facet.loc25_14.1: %ImplicitAs.type.61e = facet_value Core.IntLiteral, (constants.%ImplicitAs.impl_witness) [concrete = constants.%ImplicitAs.facet.54f]
|
||||
// CHECK:STDOUT: %.loc25_14.1: %ImplicitAs.type.61e = converted Core.IntLiteral, %ImplicitAs.facet.loc25_14.1 [concrete = constants.%ImplicitAs.facet.54f]
|
||||
// CHECK:STDOUT: %ImplicitAs.facet.loc25_14.2: %ImplicitAs.type.61e = facet_value Core.IntLiteral, (constants.%ImplicitAs.impl_witness) [concrete = constants.%ImplicitAs.facet.54f]
|
||||
// CHECK:STDOUT: %.loc25_14.2: %ImplicitAs.type.61e = converted Core.IntLiteral, %ImplicitAs.facet.loc25_14.2 [concrete = constants.%ImplicitAs.facet.54f]
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: %.loc25_14.3: %Op.type.049d3a.1 = specific_constant @impl.797.%Op.decl.loc15_35.1, @impl.797(constants.%ImplicitAs.facet.54f) [concrete = constants.%Op.1fb3b5.1]
|
||||
// CHECK:STDOUT: %Op.ref.loc25: %Op.type.049d3a.1 = name_ref Op, %.loc25_14.3 [concrete = constants.%Op.1fb3b5.1]
|
||||
// CHECK:STDOUT: %impl.elem0.loc25_14: %.f22 = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%Convert.52c]
|
||||
// CHECK:STDOUT: %bound_method.loc25_14: <bound method> = bound_method %int_2, %impl.elem0.loc25_14 [concrete = constants.%Convert.bound.713]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc25_14: init %i32.builtin = call %bound_method.loc25_14(%int_2) [concrete = constants.%int_2.5a1]
|
||||
// CHECK:STDOUT: %.loc25_14.4: %i32.builtin = value_of_initializer %int.convert_checked.loc25_14 [concrete = constants.%int_2.5a1]
|
||||
// CHECK:STDOUT: %.loc25_14.5: %i32.builtin = converted %int_2, %.loc25_14.4 [concrete = constants.%int_2.5a1]
|
||||
// CHECK:STDOUT: %Op.specific_fn: <specific function> = specific_function %Op.ref.loc25, @Op.2(constants.%ImplicitAs.facet.54f) [concrete = constants.%Op.specific_fn.01379b.2]
|
||||
// CHECK:STDOUT: %impl.elem0.loc25_13: %.f22 = impl_witness_access constants.%ImplicitAs.impl_witness, element0 [concrete = constants.%Convert.52c]
|
||||
// CHECK:STDOUT: %bound_method.loc25_13: <bound method> = bound_method %int_2, %impl.elem0.loc25_13 [concrete = constants.%Convert.bound.713]
|
||||
// CHECK:STDOUT: %int.convert_checked.loc25_13: init %i32.builtin = call %bound_method.loc25_13(%int_2) [concrete = constants.%int_2.5a1]
|
||||
// CHECK:STDOUT: %.loc25_13.1: %i32.builtin = value_of_initializer %int.convert_checked.loc25_13 [concrete = constants.%int_2.5a1]
|
||||
// CHECK:STDOUT: %.loc25_13.2: %i32.builtin = converted %int_2, %.loc25_13.1 [concrete = constants.%int_2.5a1]
|
||||
// CHECK:STDOUT: %int.sadd: init %i32.builtin = call %Op.specific_fn(%a.ref, %.loc25_13.2)
|
||||
// CHECK:STDOUT: <elided>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
+16
-7
@@ -247,7 +247,7 @@ fn G() {
|
||||
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %C [symbolic = %require_complete (constants.%require_complete)]
|
||||
// CHECK:STDOUT: %C.val: @F.3.%C (%C.13320f.2) = struct_value () [symbolic = %C.val (constants.%C.val)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn(%x.param: %empty_struct_type) {
|
||||
// CHECK:STDOUT: fn(%x.param: %empty_struct_type) [thunk @impl.%F.decl.loc8_17.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %.loc8: @F.3.%F.type (%F.type.0daaa1.1) = specific_constant @impl.%F.decl.loc8_17.1, @impl(constants.%Y) [symbolic = %F (constants.%F.49c1ac.1)]
|
||||
// CHECK:STDOUT: %F.ref: @F.3.%F.type (%F.type.0daaa1.1) = name_ref F, %.loc8 [symbolic = %F (constants.%F.49c1ac.1)]
|
||||
@@ -352,7 +352,7 @@ fn G() {
|
||||
// CHECK:STDOUT: %Main.import_ref.572 = import_ref Main//b, inst29 [no loc], unloaded
|
||||
// CHECK:STDOUT: %Main.import_ref.e5d = import_ref Main//a, inst17 [no loc], unloaded
|
||||
// CHECK:STDOUT: %Main.import_ref.c44: %I.assoc_type = import_ref Main//a, loc5_14, loaded [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT: %Main.F = import_ref Main//a, F, unloaded
|
||||
// CHECK:STDOUT: %Main.F.8b9 = import_ref Main//a, F, unloaded
|
||||
// CHECK:STDOUT: %Main.import_ref.e03: %F.type.cf0 = import_ref Main//a, loc5_14, loaded [concrete = constants.%F.bc6]
|
||||
// CHECK:STDOUT: %Main.import_ref.5dd: %I.type = import_ref Main//a, inst17 [no loc], loaded [symbolic = constants.%Self]
|
||||
// CHECK:STDOUT: %Main.import_ref.f89: <witness> = import_ref Main//b, loc7_32, loaded [symbolic = @impl.%I.impl_witness (constants.%I.impl_witness.7d9)]
|
||||
@@ -363,6 +363,7 @@ fn G() {
|
||||
// CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.047), @impl [concrete]
|
||||
// CHECK:STDOUT: %Main.import_ref.eb1c17.3: %empty_tuple.type = import_ref Main//b, loc7_14, loaded [symbolic = @impl.%Y (constants.%Y)]
|
||||
// CHECK:STDOUT: %Main.import_ref.eb1c17.4: %empty_tuple.type = import_ref Main//b, loc7_14, loaded [symbolic = @impl.%Y (constants.%Y)]
|
||||
// CHECK:STDOUT: %Main.F.5a8: @impl.%F.type.1 (%F.type.0daaa1.1) = import_ref Main//b, F, loaded [symbolic = @impl.%F.1 (constants.%F.49c1ac.1)]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -379,7 +380,7 @@ fn G() {
|
||||
// CHECK:STDOUT: !members:
|
||||
// CHECK:STDOUT: .Self = imports.%Main.import_ref.e5d
|
||||
// CHECK:STDOUT: .F = imports.%Main.import_ref.c44
|
||||
// CHECK:STDOUT: witness = (imports.%Main.F)
|
||||
// CHECK:STDOUT: witness = (imports.%Main.F.8b9)
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: generic impl @impl(imports.%Main.import_ref.eb1c17.2: %empty_tuple.type) [from "b.carbon"] {
|
||||
@@ -420,17 +421,25 @@ fn G() {
|
||||
// CHECK:STDOUT: %.loc7_7: %empty_tuple.type = converted %.loc7_6, %empty_tuple [concrete = constants.%empty_tuple]
|
||||
// CHECK:STDOUT: %C: type = class_type @C, @C(constants.%empty_tuple) [concrete = constants.%C.607]
|
||||
// CHECK:STDOUT: %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type]
|
||||
// CHECK:STDOUT: %F.ref: %I.assoc_type = name_ref F, imports.%Main.import_ref.c44 [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT: %F.ref.loc7_11: %I.assoc_type = name_ref F, imports.%Main.import_ref.c44 [concrete = constants.%assoc0]
|
||||
// CHECK:STDOUT: %I.facet: %I.type = facet_value constants.%C.607, (constants.%I.impl_witness.02b) [concrete = constants.%I.facet]
|
||||
// CHECK:STDOUT: %.loc7_8: %I.type = converted %C, %I.facet [concrete = constants.%I.facet]
|
||||
// CHECK:STDOUT: %impl.elem0: %.885 = impl_witness_access constants.%I.impl_witness.02b, element0 [concrete = constants.%F.5fa954.2]
|
||||
// CHECK:STDOUT: %.loc7_16.1: %empty_struct_type = struct_literal ()
|
||||
// CHECK:STDOUT: %empty_struct.loc7_16.1: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %.loc7_17: %empty_struct_type = converted %.loc7_16.1, %empty_struct.loc7_16.1 [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %.loc7_17.1: %empty_struct_type = converted %.loc7_16.1, %empty_struct.loc7_16.1 [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %specific_fn: <specific function> = specific_function %impl.elem0, @F.3(constants.%empty_tuple) [concrete = constants.%F.specific_fn.4832e8.1]
|
||||
// CHECK:STDOUT: %empty_struct.loc7_16.2: %empty_struct_type = struct_value () [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %.loc7_16.2: %empty_struct_type = converted %.loc7_16.1, %empty_struct.loc7_16.2 [concrete = constants.%empty_struct]
|
||||
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %specific_fn(%.loc7_16.2)
|
||||
// CHECK:STDOUT: %.loc7_17.2: %F.type.af4856.1 = specific_constant imports.%Main.F.5a8, @impl(constants.%empty_tuple) [concrete = constants.%F.5fa954.1]
|
||||
// CHECK:STDOUT: %F.ref.loc7_17: %F.type.af4856.1 = name_ref F, %.loc7_17.2 [concrete = constants.%F.5fa954.1]
|
||||
// CHECK:STDOUT: %F.specific_fn: <specific function> = specific_function %F.ref.loc7_17, @F.2(constants.%empty_tuple) [concrete = constants.%F.specific_fn.4832e8.2]
|
||||
// CHECK:STDOUT: %.loc7_16.3: ref %C.607 = temporary_storage
|
||||
// CHECK:STDOUT: %.loc7_16.4: init %C.607 = class_init (), %.loc7_16.3 [concrete = constants.%C.val.12f]
|
||||
// CHECK:STDOUT: %.loc7_16.5: ref %C.607 = temporary %.loc7_16.3, %.loc7_16.4
|
||||
// CHECK:STDOUT: %.loc7_16.6: ref %C.607 = converted %.loc7_16.2, %.loc7_16.5
|
||||
// CHECK:STDOUT: %.loc7_16.7: %C.607 = bind_value %.loc7_16.6
|
||||
// CHECK:STDOUT: %F.call: init %empty_tuple.type = call %F.specific_fn(%.loc7_16.7)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -459,7 +468,7 @@ fn G() {
|
||||
// CHECK:STDOUT: %require_complete: <witness> = require_complete_type %C [symbolic = %require_complete (constants.%require_complete)]
|
||||
// CHECK:STDOUT: %C.val: @F.3.%C (%C.13320f.2) = struct_value () [symbolic = %C.val (constants.%C.val.56a)]
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn;
|
||||
// CHECK:STDOUT: fn [thunk imports.%Main.F.5a8];
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: specific @C(constants.%X) {
|
||||
|
||||
+9
-5
@@ -2420,10 +2420,11 @@ fn F() {
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%u.param: %i32) -> %i32 {
|
||||
// CHECK:STDOUT: fn @F.3(%u.param: %i32) -> %i32 [thunk @impl.%F.decl.loc24_21.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.b842fd.1 = name_ref F, @impl.%F.decl.loc24_21.1 [concrete = constants.%F.b07d12.1]
|
||||
// CHECK:STDOUT: %u.ref: %i32 = name_ref u, %u.param
|
||||
// CHECK:STDOUT: %return.ref: ref %i32 = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: %F.call: init <error> = call %F.ref(<error>)
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
@@ -2688,11 +2689,12 @@ fn F() {
|
||||
// CHECK:STDOUT: return %z.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %empty_tuple.type, %.param: <error>) -> <error> {
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %empty_tuple.type, %.param: <error>) -> <error> [thunk @impl.4e9.%F.decl.loc30_33.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.f405c5.1 = name_ref F, @impl.4e9.%F.decl.loc30_33.1 [concrete = constants.%F.214a71.1]
|
||||
// CHECK:STDOUT: %self.ref: %empty_tuple.type = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %.ref: <error> = name_ref <none>, %.param [concrete = <error>]
|
||||
// CHECK:STDOUT: %return.ref: ref <error> = name_ref <return slot>, %return.param [concrete = <error>]
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
@@ -2702,12 +2704,13 @@ fn F() {
|
||||
// CHECK:STDOUT: return %self.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.5(%self.param: %C2, %.param: <error>) -> <error> {
|
||||
// CHECK:STDOUT: fn @F.5(%self.param: %C2, %.param: <error>) -> <error> [thunk @impl.8b3.%F.decl.loc39_33.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.05d6a0.1 = name_ref F, @impl.8b3.%F.decl.loc39_33.1 [concrete = constants.%F.bfa759.1]
|
||||
// CHECK:STDOUT: %self.ref: %C2 = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %.ref: <error> = name_ref <none>, %.param [concrete = <error>]
|
||||
// CHECK:STDOUT: %return.ref: ref <error> = name_ref <return slot>, %return.param [concrete = <error>]
|
||||
// CHECK:STDOUT: %F.bound: <bound method> = bound_method %self.ref, %F.ref
|
||||
// CHECK:STDOUT: %F.call: init %C2 = call %F.bound(%self.ref, <error>)
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
@@ -2913,11 +2916,12 @@ fn F() {
|
||||
// CHECK:STDOUT: return %v.ref
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %empty_tuple.type, %v.param: %struct_type.a) -> %struct_type.a {
|
||||
// CHECK:STDOUT: fn @F.3(%self.param: %empty_tuple.type, %v.param: %struct_type.a) -> %struct_type.a [thunk @impl.%F.decl.loc16_45.1] {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %F.ref: %F.type.c5249c.1 = name_ref F, @impl.%F.decl.loc16_45.1 [concrete = constants.%F.5eb4dd.1]
|
||||
// CHECK:STDOUT: %self.ref: %empty_tuple.type = name_ref self, %self.param
|
||||
// CHECK:STDOUT: %v.ref: %struct_type.a = name_ref v, %v.param
|
||||
// CHECK:STDOUT: %return.ref: ref %struct_type.a = name_ref <return slot>, %return.param
|
||||
// CHECK:STDOUT: return <error>
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
Reference in New Issue
Block a user