Deduplicate and canonicalize all constants. (#3611)

Rather than producing multiple constants with the same value, fold all
instances of a given constant to the same constant instruction.

A future PR will use this to replace the current type canonicalization
system.
This commit is contained in:
Richard Smith
2024-01-18 21:42:19 +00:00
committed by GitHub
parent 62db3e9ad0
commit 29c294880d
142 changed files with 1603 additions and 1185 deletions
+21 -22
View File
@@ -19,16 +19,15 @@ fn F() {
// CHECK:STDOUT: --- address_of_lvalue.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = ptr_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: %.2: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.3: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.4: type = tuple_type (type, type) [template]
// CHECK:STDOUT: %.5: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.6: type = ptr_type (i32, i32) [template]
// CHECK:STDOUT: %.7: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.8: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.1: type = struct_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: %.2: type = ptr_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: %.3: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.4: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.5: type = ptr_type i32 [template]
// CHECK:STDOUT: %.6: type = tuple_type (type, type) [template]
// CHECK:STDOUT: %.7: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.8: type = ptr_type (i32, i32) [template]
// CHECK:STDOUT: %.9: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.10: i32 = int_literal 1 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -38,11 +37,11 @@ fn F() {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc8_27: type = struct_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: %.loc8_27: type = struct_type {.a: i32, .b: i32} [template = constants.%.1]
// CHECK:STDOUT: %s.var: ref {.a: i32, .b: i32} = var s
// CHECK:STDOUT: %s: ref {.a: i32, .b: i32} = bind_name s, %s.var
// CHECK:STDOUT: %.loc8_37: i32 = int_literal 1 [template = constants.%.2]
// CHECK:STDOUT: %.loc8_45: i32 = int_literal 2 [template = constants.%.3]
// CHECK:STDOUT: %.loc8_37: i32 = int_literal 1 [template = constants.%.3]
// CHECK:STDOUT: %.loc8_45: i32 = int_literal 2 [template = constants.%.4]
// CHECK:STDOUT: %.loc8_46.1: {.a: i32, .b: i32} = struct_literal (%.loc8_37, %.loc8_45)
// CHECK:STDOUT: %.loc8_46.2: ref i32 = struct_access %s.var, element0
// CHECK:STDOUT: %.loc8_46.3: init i32 = initialize_from %.loc8_37 to %.loc8_46.2
@@ -51,21 +50,21 @@ fn F() {
// CHECK:STDOUT: %.loc8_46.6: init {.a: i32, .b: i32} = struct_init (%.loc8_46.3, %.loc8_46.5) to %s.var
// CHECK:STDOUT: %.loc8_46.7: init {.a: i32, .b: i32} = converted %.loc8_46.1, %.loc8_46.6
// CHECK:STDOUT: assign %s.var, %.loc8_46.7
// CHECK:STDOUT: %.loc10_27: type = struct_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: %.loc10_28: type = ptr_type {.a: i32, .b: i32} [template]
// CHECK:STDOUT: %.loc10_27: type = struct_type {.a: i32, .b: i32} [template = constants.%.1]
// CHECK:STDOUT: %.loc10_28: type = ptr_type {.a: i32, .b: i32} [template = constants.%.2]
// CHECK:STDOUT: %p.var: ref {.a: i32, .b: i32}* = var p
// CHECK:STDOUT: %p: ref {.a: i32, .b: i32}* = bind_name p, %p.var
// CHECK:STDOUT: %s.ref.loc10: ref {.a: i32, .b: i32} = name_ref s, %s
// CHECK:STDOUT: %.loc10_32: {.a: i32, .b: i32}* = addr_of %s.ref.loc10
// CHECK:STDOUT: assign %p.var, %.loc10_32
// CHECK:STDOUT: %.loc11_13: type = ptr_type i32 [template]
// CHECK:STDOUT: %.loc11_13: type = ptr_type i32 [template = constants.%.5]
// CHECK:STDOUT: %q.var: ref i32* = var q
// CHECK:STDOUT: %q: ref i32* = bind_name q, %q.var
// CHECK:STDOUT: %s.ref.loc11: ref {.a: i32, .b: i32} = name_ref s, %s
// CHECK:STDOUT: %.loc11_19: ref i32 = struct_access %s.ref.loc11, element0
// CHECK:STDOUT: %.loc11_17: i32* = addr_of %.loc11_19
// CHECK:STDOUT: assign %q.var, %.loc11_17
// CHECK:STDOUT: %.loc12_13: type = ptr_type i32 [template]
// CHECK:STDOUT: %.loc12_13: type = ptr_type i32 [template = constants.%.5]
// CHECK:STDOUT: %r.var: ref i32* = var r
// CHECK:STDOUT: %r: ref i32* = bind_name r, %r.var
// CHECK:STDOUT: %s.ref.loc12: ref {.a: i32, .b: i32} = name_ref s, %s
@@ -73,11 +72,11 @@ fn F() {
// CHECK:STDOUT: %.loc12_17: i32* = addr_of %.loc12_19
// CHECK:STDOUT: assign %r.var, %.loc12_17
// CHECK:STDOUT: %.loc14_19.1: (type, type) = tuple_literal (i32, i32)
// CHECK:STDOUT: %.loc14_19.2: type = converted %.loc14_19.1, constants.%.5 [template = constants.%.5]
// CHECK:STDOUT: %.loc14_19.2: type = converted %.loc14_19.1, constants.%.7 [template = constants.%.7]
// CHECK:STDOUT: %t.var: ref (i32, i32) = var t
// CHECK:STDOUT: %t: ref (i32, i32) = bind_name t, %t.var
// CHECK:STDOUT: %.loc14_24: i32 = int_literal 1 [template = constants.%.7]
// CHECK:STDOUT: %.loc14_27: i32 = int_literal 2 [template = constants.%.8]
// CHECK:STDOUT: %.loc14_24: i32 = int_literal 1 [template = constants.%.3]
// CHECK:STDOUT: %.loc14_27: i32 = int_literal 2 [template = constants.%.4]
// CHECK:STDOUT: %.loc14_28.1: (i32, i32) = tuple_literal (%.loc14_24, %.loc14_27)
// CHECK:STDOUT: %.loc14_28.2: ref i32 = tuple_access %t.var, element0
// CHECK:STDOUT: %.loc14_28.3: init i32 = initialize_from %.loc14_24 to %.loc14_28.2
@@ -86,7 +85,7 @@ fn F() {
// CHECK:STDOUT: %.loc14_28.6: init (i32, i32) = tuple_init (%.loc14_28.3, %.loc14_28.5) to %t.var
// CHECK:STDOUT: %.loc14_28.7: init (i32, i32) = converted %.loc14_28.1, %.loc14_28.6
// CHECK:STDOUT: assign %t.var, %.loc14_28.7
// CHECK:STDOUT: %.loc15_14: type = ptr_type i32 [template]
// CHECK:STDOUT: %.loc15_14: type = ptr_type i32 [template = constants.%.5]
// CHECK:STDOUT: %t0.var: ref i32* = var t0
// CHECK:STDOUT: %t0: ref i32* = bind_name t0, %t0.var
// CHECK:STDOUT: %t.ref.loc15: ref (i32, i32) = name_ref t, %t
@@ -94,11 +93,11 @@ fn F() {
// CHECK:STDOUT: %.loc15_22: ref i32 = tuple_index %t.ref.loc15, %.loc15_21
// CHECK:STDOUT: %.loc15_18: i32* = addr_of %.loc15_22
// CHECK:STDOUT: assign %t0.var, %.loc15_18
// CHECK:STDOUT: %.loc16_14: type = ptr_type i32 [template]
// CHECK:STDOUT: %.loc16_14: type = ptr_type i32 [template = constants.%.5]
// CHECK:STDOUT: %t1.var: ref i32* = var t1
// CHECK:STDOUT: %t1: ref i32* = bind_name t1, %t1.var
// CHECK:STDOUT: %t.ref.loc16: ref (i32, i32) = name_ref t, %t
// CHECK:STDOUT: %.loc16_21: i32 = int_literal 1 [template = constants.%.10]
// CHECK:STDOUT: %.loc16_21: i32 = int_literal 1 [template = constants.%.3]
// CHECK:STDOUT: %.loc16_22: ref i32 = tuple_index %t.ref.loc16, %.loc16_21
// CHECK:STDOUT: %.loc16_18: i32* = addr_of %.loc16_22
// CHECK:STDOUT: assign %t1.var, %.loc16_18
+2 -1
View File
@@ -15,6 +15,7 @@ fn F() -> i32 {
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.2: type = ptr_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -28,7 +29,7 @@ fn F() -> i32 {
// CHECK:STDOUT: %n: ref i32 = bind_name n, %n.var
// CHECK:STDOUT: %.loc8: i32 = int_literal 0 [template = constants.%.1]
// CHECK:STDOUT: assign %n.var, %.loc8
// CHECK:STDOUT: %.loc9_13: type = ptr_type i32 [template]
// CHECK:STDOUT: %.loc9_13: type = ptr_type i32 [template = constants.%.2]
// CHECK:STDOUT: %p.var: ref i32* = var p
// CHECK:STDOUT: %p: ref i32* = bind_name p, %p.var
// CHECK:STDOUT: %n.ref: ref i32 = name_ref n, %n
+50 -54
View File
@@ -85,36 +85,32 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT: --- fail_address_of_value.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.2: type = ptr_type i32 [template]
// CHECK:STDOUT: %.3: i32* = addr_of %.1 [template]
// CHECK:STDOUT: %.4: bool = bool_literal true [template]
// CHECK:STDOUT: %.5: type = ptr_type bool [template]
// CHECK:STDOUT: %.6: bool* = addr_of %.4 [template]
// CHECK:STDOUT: %.7: f64 = real_literal 10e-1 [template]
// CHECK:STDOUT: %.8: type = ptr_type f64 [template]
// CHECK:STDOUT: %.9: f64* = addr_of %.7 [template]
// CHECK:STDOUT: %.10: type = ptr_type String [template]
// CHECK:STDOUT: %.11: String = string_literal "Hello" [template]
// CHECK:STDOUT: %.12: String* = addr_of %.11 [template]
// CHECK:STDOUT: %.13: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.14: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.15: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.16: type = ptr_type (i32, i32) [template]
// CHECK:STDOUT: %.17: i32 = int_literal 5 [template]
// CHECK:STDOUT: %.18: type = ptr_type {.a: i32} [template]
// CHECK:STDOUT: %.19: bool = bool_literal true [template]
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: type = ptr_type i32 [template]
// CHECK:STDOUT: %.4: i32* = addr_of %.2 [template]
// CHECK:STDOUT: %.5: bool = bool_literal true [template]
// CHECK:STDOUT: %.6: type = ptr_type bool [template]
// CHECK:STDOUT: %.7: bool* = addr_of %.5 [template]
// CHECK:STDOUT: %.8: f64 = real_literal 10e-1 [template]
// CHECK:STDOUT: %.9: type = ptr_type f64 [template]
// CHECK:STDOUT: %.10: f64* = addr_of %.8 [template]
// CHECK:STDOUT: %.11: type = ptr_type String [template]
// CHECK:STDOUT: %.12: String = string_literal "Hello" [template]
// CHECK:STDOUT: %.13: String* = addr_of %.12 [template]
// CHECK:STDOUT: %.14: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.15: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.16: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.17: type = ptr_type (i32, i32) [template]
// CHECK:STDOUT: %.18: i32 = int_literal 5 [template]
// CHECK:STDOUT: %.19: type = ptr_type {.a: i32} [template]
// CHECK:STDOUT: %.20: bool = bool_literal false [template]
// CHECK:STDOUT: %.21: bool = bool_literal false [template]
// CHECK:STDOUT: %.22: bool = bool_literal true [template]
// CHECK:STDOUT: %.23: bool = bool_literal false [template]
// CHECK:STDOUT: %.24: bool* = addr_of %.23 [template]
// CHECK:STDOUT: %.25: type = ptr_type type [template]
// CHECK:STDOUT: %.26: type* = addr_of @AddressOfType.%.loc68_14 [template]
// CHECK:STDOUT: %.27: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.28: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.29: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.30: (i32, i32) = tuple_value (%.27, %.28) [template]
// CHECK:STDOUT: %.21: bool* = addr_of %.20 [template]
// CHECK:STDOUT: %.22: type = ptr_type type [template]
// CHECK:STDOUT: %.23: type = const_type i32 [template]
// CHECK:STDOUT: %.24: type = ptr_type const i32 [template]
// CHECK:STDOUT: %.25: type* = addr_of %.24 [template]
// CHECK:STDOUT: %.26: (i32, i32) = tuple_value (%.14, %.15) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
@@ -135,19 +131,19 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @AddressOfLiteral() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc15_4: i32 = int_literal 0 [template = constants.%.1]
// CHECK:STDOUT: %.loc15_3: i32* = addr_of %.loc15_4 [template = constants.%.3]
// CHECK:STDOUT: %.loc19_4: bool = bool_literal true [template = constants.%.4]
// CHECK:STDOUT: %.loc19_3: bool* = addr_of %.loc19_4 [template = constants.%.6]
// CHECK:STDOUT: %.loc23_4: f64 = real_literal 10e-1 [template = constants.%.7]
// CHECK:STDOUT: %.loc23_3: f64* = addr_of %.loc23_4 [template = constants.%.9]
// CHECK:STDOUT: %.loc27_4: String = string_literal "Hello" [template = constants.%.11]
// CHECK:STDOUT: %.loc27_3: String* = addr_of %.loc27_4 [template = constants.%.12]
// CHECK:STDOUT: %.loc31_5: i32 = int_literal 1 [template = constants.%.13]
// CHECK:STDOUT: %.loc31_8: i32 = int_literal 2 [template = constants.%.14]
// CHECK:STDOUT: %.loc15_4: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc15_3: i32* = addr_of %.loc15_4 [template = constants.%.4]
// CHECK:STDOUT: %.loc19_4: bool = bool_literal true [template = constants.%.5]
// CHECK:STDOUT: %.loc19_3: bool* = addr_of %.loc19_4 [template = constants.%.7]
// CHECK:STDOUT: %.loc23_4: f64 = real_literal 10e-1 [template = constants.%.8]
// CHECK:STDOUT: %.loc23_3: f64* = addr_of %.loc23_4 [template = constants.%.10]
// CHECK:STDOUT: %.loc27_4: String = string_literal "Hello" [template = constants.%.12]
// CHECK:STDOUT: %.loc27_3: String* = addr_of %.loc27_4 [template = constants.%.13]
// CHECK:STDOUT: %.loc31_5: i32 = int_literal 1 [template = constants.%.14]
// CHECK:STDOUT: %.loc31_8: i32 = int_literal 2 [template = constants.%.15]
// CHECK:STDOUT: %.loc31_9: (i32, i32) = tuple_literal (%.loc31_5, %.loc31_8)
// CHECK:STDOUT: %.loc31_3: (i32, i32)* = addr_of %.loc31_9
// CHECK:STDOUT: %.loc35_10: i32 = int_literal 5 [template = constants.%.17]
// CHECK:STDOUT: %.loc35_10: i32 = int_literal 5 [template = constants.%.18]
// CHECK:STDOUT: %.loc35_11: {.a: i32} = struct_literal (%.loc35_10)
// CHECK:STDOUT: %.loc35_3: {.a: i32}* = addr_of %.loc35_11
// CHECK:STDOUT: return
@@ -155,12 +151,12 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @AddressOfOperator() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc42_5: bool = bool_literal true [template = constants.%.19]
// CHECK:STDOUT: %.loc42_5: bool = bool_literal true [template = constants.%.5]
// CHECK:STDOUT: %.loc42_10.1: bool = bool_literal false [template = constants.%.20]
// CHECK:STDOUT: if %.loc42_5 br !and.rhs else br !and.result(%.loc42_10.1)
// CHECK:STDOUT:
// CHECK:STDOUT: !and.rhs:
// CHECK:STDOUT: %.loc42_14: bool = bool_literal false [template = constants.%.21]
// CHECK:STDOUT: %.loc42_14: bool = bool_literal false [template = constants.%.20]
// CHECK:STDOUT: br !and.result(%.loc42_14)
// CHECK:STDOUT:
// CHECK:STDOUT: !and.result:
@@ -172,9 +168,9 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT: %.loc46_5.3: ref {.a: i32} = temporary %.loc46_5.2, %.loc46_5.1
// CHECK:STDOUT: %.loc46_7: ref i32 = struct_access %.loc46_5.3, element0
// CHECK:STDOUT: %.loc46_3: i32* = addr_of %.loc46_7
// CHECK:STDOUT: %.loc50_9: bool = bool_literal true [template = constants.%.22]
// CHECK:STDOUT: %.loc50_5: bool = not %.loc50_9 [template = constants.%.23]
// CHECK:STDOUT: %.loc50_3: bool* = addr_of %.loc50_5 [template = constants.%.24]
// CHECK:STDOUT: %.loc50_9: bool = bool_literal true [template = constants.%.5]
// CHECK:STDOUT: %.loc50_5: bool = not %.loc50_9 [template = constants.%.20]
// CHECK:STDOUT: %.loc50_3: bool* = addr_of %.loc50_5 [template = constants.%.21]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -189,20 +185,20 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT: fn @AddressOfType() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc64: type* = addr_of i32
// CHECK:STDOUT: %.loc68_5: type = const_type i32 [template]
// CHECK:STDOUT: %.loc68_14: type = ptr_type const i32 [template]
// CHECK:STDOUT: %.loc68_3: type* = addr_of %.loc68_14 [template = constants.%.26]
// CHECK:STDOUT: %.loc68_5: type = const_type i32 [template = constants.%.23]
// CHECK:STDOUT: %.loc68_14: type = ptr_type const i32 [template = constants.%.24]
// CHECK:STDOUT: %.loc68_3: type* = addr_of %.loc68_14 [template = constants.%.25]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @AddressOfTupleElementValue() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc75_6: i32 = int_literal 1 [template = constants.%.27]
// CHECK:STDOUT: %.loc75_9: i32 = int_literal 2 [template = constants.%.28]
// CHECK:STDOUT: %.loc75_6: i32 = int_literal 1 [template = constants.%.14]
// CHECK:STDOUT: %.loc75_9: i32 = int_literal 2 [template = constants.%.15]
// CHECK:STDOUT: %.loc75_10.1: (i32, i32) = tuple_literal (%.loc75_6, %.loc75_9)
// CHECK:STDOUT: %.loc75_12: i32 = int_literal 0 [template = constants.%.29]
// CHECK:STDOUT: %.loc75_10.2: (i32, i32) = tuple_value (%.loc75_6, %.loc75_9) [template = constants.%.30]
// CHECK:STDOUT: %.loc75_10.3: (i32, i32) = converted %.loc75_10.1, %.loc75_10.2 [template = constants.%.30]
// CHECK:STDOUT: %.loc75_12: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc75_10.2: (i32, i32) = tuple_value (%.loc75_6, %.loc75_9) [template = constants.%.26]
// CHECK:STDOUT: %.loc75_10.3: (i32, i32) = converted %.loc75_10.1, %.loc75_10.2 [template = constants.%.26]
// CHECK:STDOUT: %.loc75_13: i32 = tuple_index %.loc75_10.3, %.loc75_12
// CHECK:STDOUT: %.loc75_3: i32* = addr_of %.loc75_13
// CHECK:STDOUT: return
@@ -210,7 +206,7 @@ fn AddressOfParam(param: i32) {
// CHECK:STDOUT:
// CHECK:STDOUT: fn @AddressOfParam(%param: i32) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc82_22: type = ptr_type i32 [template]
// CHECK:STDOUT: %.loc82_22: type = ptr_type i32 [template = constants.%.3]
// CHECK:STDOUT: %param_addr.var: ref i32* = var param_addr
// CHECK:STDOUT: %param_addr: ref i32* = bind_name param_addr, %param_addr.var
// CHECK:STDOUT: %param.ref: i32 = name_ref param, %param
@@ -15,6 +15,10 @@ fn ConstMismatch(p: const {}*) -> const ({}*) {
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %.2: type = const_type {} [template]
// CHECK:STDOUT: %.3: type = ptr_type const {} [template]
// CHECK:STDOUT: %.4: type = ptr_type {} [template]
// CHECK:STDOUT: %.5: type = const_type {}* [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
+8
View File
@@ -11,6 +11,14 @@ fn F(p: const (const (const i32*)*)) -> const i32 {
// CHECK:STDOUT: --- nested_const.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: %.2: type = ptr_type const i32 [template]
// CHECK:STDOUT: %.3: type = const_type const i32* [template]
// CHECK:STDOUT: %.4: type = ptr_type const (const i32*) [template]
// CHECK:STDOUT: %.5: type = const_type const (const i32*)* [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace package, {.F = %F} [template]
// CHECK:STDOUT: %F: <function> = fn_decl @F [template]
+6
View File
@@ -14,6 +14,12 @@ fn ConstPtr(p: const i32*) -> (const i32)* {
// CHECK:STDOUT: --- types.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = ptr_type i32 [template]
// CHECK:STDOUT: %.2: type = const_type i32 [template]
// CHECK:STDOUT: %.3: type = ptr_type const i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace package, {.Ptr = %Ptr, .ConstPtr = %ConstPtr} [template]
// CHECK:STDOUT: %Ptr: <function> = fn_decl @Ptr [template]