| // RUN: %target-sil-opt -test-constant-evaluator %s 2>&1 | %FileCheck %s |
| |
| /// Tests for the constant evaluator in stepwise evaluation mode (also referred |
| /// to as flow-sensitive mode) in which instructions are evaluated following |
| /// the control flow of the program. The evaluator will be run on every function |
| /// whose name starts with `interpret` prefix and outputs the constant value |
| /// returned by the function or diagnostics if the evaluation fails. |
| |
| sil_stage canonical |
| |
| import Builtin |
| import Swift |
| |
| // Test builtin literals and operations. |
| |
| // CHECK-LABEL: @interpretBuiltinIntLiteral |
| sil @interpretBuiltinIntLiteral : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 17 |
| return %0 : $(Builtin.Int64) |
| } // CHECK: Returns int: 17 |
| |
| // CHECK-LABEL: @interpretBuiltinAddition |
| sil @interpretBuiltinAddition : $@convention(thin) () -> Builtin.Int32 { |
| bb0: |
| %0 = integer_literal $Builtin.Int32, 1 |
| %1 = builtin "add_Int32"(%0 : $Builtin.Int32, %0 : $Builtin.Int32) : $(Builtin.Int32) |
| return %1 : $(Builtin.Int32) |
| } // CHECK: Returns int: 2 |
| |
| // CHECK-LABEL: @interpretBuiltinAddWrapAround |
| sil @interpretBuiltinAddWrapAround : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, 127 |
| %1 = integer_literal $Builtin.Int8, 1 |
| %2 = builtin "add_Int32"(%0 : $Builtin.Int8, %1 : $Builtin.Int8) : $(Builtin.Int8) |
| return %2 : $(Builtin.Int8) |
| } // CHECK: Returns int: -128 |
| |
| // CHECK-LABEL: @interpretBuiltinMultiplication |
| sil @interpretBuiltinMultiplication : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 10 |
| %1 = integer_literal $Builtin.Int64, 11 |
| %2 = builtin "mul_Int64"(%0 : $Builtin.Int64, %1 : $Builtin.Int64) : $(Builtin.Int64) |
| return %2 : $(Builtin.Int64) |
| } // CHECK: Returns int: 110 |
| |
| // CHECK-LABEL: @interpretBuiltinDivision |
| sil @interpretBuiltinDivision : $@convention(thin) () -> Builtin.Int16 { |
| bb0: |
| %0 = integer_literal $Builtin.Int16, 10 |
| %1 = integer_literal $Builtin.Int16, 11 |
| %2 = builtin "sdiv_Int16"(%1 : $Builtin.Int16, %0 : $Builtin.Int16) : $(Builtin.Int16) |
| return %2 : $(Builtin.Int16) |
| } // CHECK: Returns int: 1 |
| |
| // CHECK-LABEL: @interpretBuiltinModulo |
| sil @interpretBuiltinModulo : $@convention(thin) () -> Builtin.Int16 { |
| bb0: |
| %0 = integer_literal $Builtin.Int16, 23 |
| %1 = integer_literal $Builtin.Int16, 6 |
| %2 = builtin "srem_Int16"(%0 : $Builtin.Int16, %1 : $Builtin.Int16) : $(Builtin.Int16) |
| return %2 : $(Builtin.Int16) |
| } // CHECK: Returns int: 5 |
| |
| // CHECK-LABEL: @interpretBuiltinLeftShift |
| sil @interpretBuiltinLeftShift : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, 10 |
| %1 = integer_literal $Builtin.Int8, 2 |
| %2 = builtin "shl_Int8"(%0 : $Builtin.Int8, %1: $Builtin.Int8) : $(Builtin.Int8) |
| return %2 : $(Builtin.Int8) |
| } // CHECK: Returns int: 40 |
| |
| // CHECK-LABEL: @interpretBuiltinRightShift |
| sil @interpretBuiltinRightShift : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, 10 |
| %1 = integer_literal $Builtin.Int8, 2 |
| %2 = builtin "ashr_Int8"(%0 : $Builtin.Int8, %1: $Builtin.Int8) : $(Builtin.Int8) |
| return %2 : $(Builtin.Int8) |
| } // CHECK: Returns int: 2 |
| |
| // CHECK-LABEL: @interpretBuiltinBitWiseAnd |
| sil @interpretBuiltinBitWiseAnd : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, 10 |
| %1 = integer_literal $Builtin.Int8, 8 |
| %2 = builtin "and_Int8"(%0 : $Builtin.Int8, %1: $Builtin.Int8) : $(Builtin.Int8) |
| return %2 : $(Builtin.Int8) |
| } // CHECK: Returns int: 8 |
| |
| // CHECK-LABEL: @interpretBuiltinBitWiseOr |
| sil @interpretBuiltinBitWiseOr : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, 10 |
| %1 = integer_literal $Builtin.Int8, 8 |
| %2 = builtin "or_Int8"(%0 : $Builtin.Int8, %1: $Builtin.Int8) : $(Builtin.Int8) |
| return %2 : $(Builtin.Int8) |
| } // CHECK: Returns int: 10 |
| |
| // Test conditional branches and comparison operators. |
| |
| // CHECK-LABEL: @interpretFalseBranch |
| sil hidden @interpretFalseBranch : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = integer_literal $Builtin.Int64, 100 |
| %2 = integer_literal $Builtin.Int64, 0 |
| %3 = builtin "cmp_slt_Int64"(%1 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int1 |
| cond_br %3, bb1, bb2 |
| |
| bb1: |
| %8 = integer_literal $Builtin.Int64, 0 |
| br bb3(%8 : $Builtin.Int64) |
| |
| bb2: |
| br bb3(%1 : $Builtin.Int64) |
| |
| bb3(%12 : $Builtin.Int64): |
| return %12 : $Builtin.Int64 |
| } // CHECK: Returns int: 100 |
| |
| // CHECK-LABEL: @interpretTrueBranch |
| sil hidden @interpretTrueBranch : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = integer_literal $Builtin.Int64, 100 |
| %2 = integer_literal $Builtin.Int64, 0 |
| %3 = builtin "cmp_slt_Int64"(%1 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int1 |
| %4 = integer_literal $Builtin.Int1, -1 |
| %5 = builtin "xor_Int1"(%3 : $Builtin.Int1, %4 : $Builtin.Int1) : $Builtin.Int1 |
| cond_br %5, bb1, bb2 |
| |
| bb1: |
| %8 = integer_literal $Builtin.Int64, 0 |
| br bb3(%8 : $Builtin.Int64) |
| |
| bb2: |
| br bb3(%1 : $Builtin.Int64) |
| |
| bb3(%12 : $Builtin.Int64): |
| return %12 : $Builtin.Int64 |
| } // CHECK: Returns int: 0 |
| |
| // Test builtin truncation and extension. |
| |
| // CHECK-LABEL: @interpretSignedTruncation |
| sil @interpretSignedTruncation : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, -1 |
| %1 = builtin "s_to_s_checked_trunc_Int64_Int8"(%0 : $Builtin.Int64) : $(Builtin.Int8, Builtin.Int1) |
| %2 = tuple_extract %1 : $(Builtin.Int8, Builtin.Int1), 0 |
| return %2 : $(Builtin.Int8) |
| } // CHECK: Returns int: -1 |
| |
| // CHECK-LABEL: @interpretSignedTruncWithIntLiteral |
| sil @interpretSignedTruncWithIntLiteral : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.IntLiteral, 5 |
| %1 = builtin "s_to_s_checked_trunc_IntLiteral_Int64"(%0 : $Builtin.IntLiteral) : $(Builtin.Int64, Builtin.Int1) |
| %2 = tuple_extract %1 : $(Builtin.Int64, Builtin.Int1), 0 |
| return %2 : $(Builtin.Int64) |
| } // CHECK: Returns int: 5 |
| |
| // CHECK-LABEL: @interpretSignedExtend |
| sil @interpretSignedExtend : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, -1 |
| %1 = builtin "sext_Int8_Int64"(%0 : $Builtin.Int8) : $Builtin.Int64 |
| return %1 : $(Builtin.Int64) |
| } // CHECK: Returns int: -1 |
| |
| // CHECK-LABEL: @interpretZeroExtend |
| sil @interpretZeroExtend : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, -1 |
| %1 = builtin "zext_Int8_Int64"(%0 : $Builtin.Int8) : $Builtin.Int64 |
| return %1 : $(Builtin.Int64) |
| } // CHECK: Returns int: 255 |
| |
| // FIXME: assertion failure in conversion of s_to_s_checked_trunc_IntLiteral. |
| sil @xfailInterpretBuiltinIntLiteralTrunc : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.IntLiteral, 2 |
| %2 = builtin "s_to_s_checked_trunc_IntLiteral_Int8"(%0 : $Builtin.IntLiteral) : $(Builtin.Int8, Builtin.Int1) |
| %3 = tuple_extract %2 : $(Builtin.Int8, Builtin.Int1), 0 |
| return %3 : $(Builtin.Int8) |
| } |
| |
| // Test overflow diagnostics. |
| // FIXME: Imprecision: the following builtin operations return a tuple where |
| // the second element indicate whether an overflow happened or not. |
| // The interpreter currently makes the entire tuple unknown in the case of |
| // overflow. This should be replaced by the correct semantics of the builtin |
| // which produces a trucated value for the first element and returns true for |
| // the second element. |
| |
| // CHECK-LABEL: @interpretSignedTruncationError |
| sil @interpretSignedTruncationError : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, -1 |
| %1 = builtin "s_to_u_checked_trunc_Int64_Int8"(%0 : $Builtin.Int64) : $(Builtin.Int8, Builtin.Int1) |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: integer overflow detected |
| %2 = tuple_extract %1 : $(Builtin.Int8, Builtin.Int1), 0 |
| return %2 : $(Builtin.Int8) |
| } |
| |
| // CHECK-LABEL: @interpretBuiltinAddOverflow |
| sil @interpretBuiltinAddOverflow : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int8, 127 |
| %1 = integer_literal $Builtin.Int8, 1 |
| %2 = integer_literal $Builtin.Int1, -1 |
| %3 = builtin "sadd_with_overflow_Int8"(%0 : $Builtin.Int8, %1 : $Builtin.Int8, %2: $Builtin.Int1) : $(Builtin.Int8, Builtin.Int1) |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: integer overflow detected |
| %4 = tuple_extract %3 : $(Builtin.Int8, Builtin.Int1), 0 |
| return %4 : $(Builtin.Int8) |
| } |
| |
| // Test function calls |
| |
| sil hidden @identity : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { |
| bb0(%0 : $Builtin.Int64): |
| return %0 : $Builtin.Int64 |
| } |
| |
| // CHECK-LABEL: @interpretCallTest |
| sil hidden @interpretCallTest : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 10 |
| %2 = function_ref @identity : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| %3 = apply %2(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| return %3 : $Builtin.Int64 |
| } // CHECK: Returns int: 10 |
| |
| // A function that computes factorial of a Builtin.Int64 and traps on overflow. |
| sil hidden @factorial : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 { |
| bb0(%0 : $Builtin.Int64): |
| %2 = integer_literal $Builtin.Int64, 0 |
| %4 = builtin "cmp_eq_Int64"(%0 : $Builtin.Int64, %2 : $Builtin.Int64) : $Builtin.Int1 |
| cond_br %4, bb1, bb2 |
| |
| bb1: |
| %8 = integer_literal $Builtin.Int64, 1 |
| br bb3(%8 : $Builtin.Int64) |
| |
| bb2: |
| %11 = integer_literal $Builtin.Int64, 1 |
| %13 = integer_literal $Builtin.Int1, -1 |
| %14 = builtin "usub_with_overflow_Int64"(%0 : $Builtin.Int64, %11 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| %15 = tuple_extract %14 : $(Builtin.Int64, Builtin.Int1), 0 |
| %16 = tuple_extract %14 : $(Builtin.Int64, Builtin.Int1), 1 |
| cond_fail %16 : $Builtin.Int1 |
| %19 = function_ref @factorial : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| %20 = apply %19(%15) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| %23 = integer_literal $Builtin.Int1, -1 |
| %24 = builtin "umul_with_overflow_Int64"(%0 : $Builtin.Int64, %20 : $Builtin.Int64, %23 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| %25 = tuple_extract %24 : $(Builtin.Int64, Builtin.Int1), 0 |
| %26 = tuple_extract %24 : $(Builtin.Int64, Builtin.Int1), 1 |
| cond_fail %26 : $Builtin.Int1 |
| br bb3(%25 : $Builtin.Int64) |
| |
| bb3(%30 : $Builtin.Int64): |
| return %30 : $Builtin.Int64 |
| } |
| |
| // CHECK-LABEL: @interpretFactorialCall |
| sil hidden @interpretFactorialCall : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 5 |
| %2 = function_ref @factorial : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| %3 = apply %2(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| return %3 : $Builtin.Int64 |
| } // CHECK: Returns int: 120 |
| |
| // CHECK-LABEL: @interpretAndDiagnoseLongRecursion |
| sil hidden @interpretAndDiagnoseLongRecursion : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, -5 |
| %2 = function_ref @factorial : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| %3 = apply %2(%0) : $@convention(thin) (Builtin.Int64) -> Builtin.Int64 |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: exceeded instruction limit: {{.*}} when evaluating the expression at compile time |
| // CHECK: {{.*}}: note: limit exceeded here |
| return %3 : $Builtin.Int64 |
| } |
| |
| // Test meta types. |
| |
| // CHECK-LABEL: @interpretIntMetatype |
| sil @interpretIntMetatype : $@convention(thin) () -> @thin Int.Type { |
| bb0: |
| %0 = metatype $@thin Int.Type |
| return %0 : $@thin Int.Type |
| } // CHECK: Returns metatype: Int |
| |
| // CHECK-LABEL: @interpretStringMetatype |
| sil @interpretStringMetatype : $@convention(thin) () -> @thin String.Type { |
| bb0: |
| %0 = metatype $@thin String.Type |
| return %0 : $@thin String.Type |
| } // CHECK: Returns metatype: String |
| |
| // Test standard integers. |
| |
| // CHECK-LABEL: @interpretIntInit |
| sil @interpretIntInit : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 122 |
| %1 = struct $Int64 (%0 : $Builtin.Int64) |
| %2 = struct_extract %1 : $Int64, #Int64._value |
| return %2 : $Builtin.Int64 |
| } // CHECK: Returns int: 122 |
| |
| sil @mockInt8Init : $@convention(thin) (Builtin.Int64, @thin Int8.Type) -> Int8 { |
| bb0(%0 : $Builtin.Int64, %1 : $@thin Int8.Type): |
| %2 = builtin "s_to_s_checked_trunc_Int64_Int8"(%0 : $Builtin.Int64) : $(Builtin.Int8, Builtin.Int1) |
| %3 = tuple_extract %2 : $(Builtin.Int8, Builtin.Int1), 0 |
| %4 = struct $Int8 (%3 : $Builtin.Int8) |
| return %4 : $Int8 |
| } |
| |
| // CHECK-LABEL: @interpretInt8Init |
| sil @interpretInt8Init : $@convention(thin) () -> Builtin.Int8 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 122 |
| %1 = metatype $@thin Int8.Type |
| %2 = function_ref @mockInt8Init : $@convention(thin) (Builtin.Int64, @thin Int8.Type) -> Int8 |
| %3 = apply %2(%0, %1) : $@convention(thin) (Builtin.Int64, @thin Int8.Type) -> Int8 |
| %4 = struct_extract %3 : $Int8, #Int8._value |
| return %4 : $Builtin.Int8 |
| } // CHECK: Returns int: 122 |
| |
| sil @boolEquals : $@convention(method) (Bool, Bool, @thin Bool.Type) -> Bool { |
| bb0(%0 : $Bool, %1 : $Bool, %2 : $@thin Bool.Type): |
| %3 = struct_extract %0 : $Bool, #Bool._value |
| %4 = struct_extract %1 : $Bool, #Bool._value |
| %5 = builtin "cmp_eq_Int1"(%3 : $Builtin.Int1, %4 : $Builtin.Int1) : $Builtin.Int1 |
| %6 = struct $Bool (%5 : $Builtin.Int1) |
| return %6 : $Bool |
| } |
| |
| // CHECK-LABEL: @interpretBoolEquals |
| sil @interpretBoolEquals : $@convention(thin) () -> Builtin.Int1 { |
| bb0: |
| %0 = integer_literal $Builtin.Int1, 0 |
| %1 = struct $Bool (%0 : $Builtin.Int1) |
| %2 = integer_literal $Builtin.Int1, -1 |
| %3 = struct $Bool (%2 : $Builtin.Int1) |
| %4 = metatype $@thin Bool.Type |
| %5 = function_ref @boolEquals : $@convention(method) (Bool, Bool, @thin Bool.Type) -> Bool |
| %6 = apply %5(%1, %3, %4) : $@convention(method) (Bool, Bool, @thin Bool.Type) -> Bool |
| %7 = struct_extract %6 : $Bool, #Bool._value |
| return %7 : $Builtin.Int1 |
| } // CHECK: Returns int: 0 |
| |
| // Test custom structs. |
| |
| struct InnerStruct { |
| var z: Int64 |
| var w: Bool |
| } |
| |
| struct CustomStruct { |
| let x: (Int64, Int64) |
| let y: InnerStruct |
| } |
| |
| sil @innerStructInit : $@convention(method) (Int64, Bool, @thin InnerStruct.Type) -> InnerStruct { |
| bb0(%0 : $Int64, %1 : $Bool, %2 : $@thin InnerStruct.Type): |
| %3 = struct $InnerStruct (%0 : $Int64, %1 : $Bool) |
| return %3 : $InnerStruct |
| } |
| |
| sil @customStructInit : $@convention(method) (Int64, Int64, InnerStruct, @thin CustomStruct.Type) -> CustomStruct { |
| bb0(%0 : $Int64, %1 : $Int64, %2 : $InnerStruct, %3 : $@thin CustomStruct.Type): |
| %4 = tuple (%0 : $Int64, %1 : $Int64) |
| %5 = struct $CustomStruct (%4 : $(Int64, Int64), %2 : $InnerStruct) |
| return %5 : $CustomStruct |
| } |
| |
| sil @constructCustomStruct : $@convention(thin) () -> CustomStruct { |
| bb0: |
| %0 = metatype $@thin CustomStruct.Type |
| %1 = integer_literal $Builtin.Int64, 1 |
| %2 = struct $Int64 (%1 : $Builtin.Int64) |
| %3 = integer_literal $Builtin.Int64, 2 |
| %4 = struct $Int64 (%3 : $Builtin.Int64) |
| %5 = metatype $@thin InnerStruct.Type |
| %6 = integer_literal $Builtin.Int64, 3 |
| %7 = struct $Int64 (%6 : $Builtin.Int64) |
| %8 = integer_literal $Builtin.Int1, -1 |
| %9 = struct $Bool (%8 : $Builtin.Int1) |
| |
| %10 = function_ref @innerStructInit : $@convention(method) (Int64, Bool, @thin InnerStruct.Type) -> InnerStruct |
| %11 = apply %10(%7, %9, %5) : $@convention(method) (Int64, Bool, @thin InnerStruct.Type) -> InnerStruct |
| |
| %12 = function_ref @customStructInit : $@convention(method) (Int64, Int64, InnerStruct, @thin CustomStruct.Type) -> CustomStruct |
| %13 = apply %12(%2, %4, %11, %0) : $@convention(method) (Int64, Int64, InnerStruct, @thin CustomStruct.Type) -> CustomStruct |
| return %13 : $CustomStruct |
| } |
| |
| // CHECK-LABEL: @interpretCustomStruct |
| sil @interpretCustomStruct : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = function_ref @constructCustomStruct : $@convention(thin) () -> CustomStruct |
| %2 = apply %1() : $@convention(thin) () -> CustomStruct |
| %3 = struct_extract %2 : $CustomStruct, #CustomStruct.x |
| %4 = tuple_extract %3 : $(Int64, Int64), 0 |
| %5 = struct_extract %4 : $Int64, #Int64._value |
| return %5 : $Builtin.Int64 |
| } // CHECK: Returns int: 1 |
| |
| // CHECK-LABEL: @interpretCustomStruct2 |
| sil @interpretCustomStruct2 : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = function_ref @constructCustomStruct : $@convention(thin) () -> CustomStruct |
| %2 = apply %1() : $@convention(thin) () -> CustomStruct |
| %3 = struct_extract %2 : $CustomStruct, #CustomStruct.x |
| %4 = tuple_extract %3 : $(Int64, Int64), 1 |
| %5 = struct_extract %4 : $Int64, #Int64._value |
| return %5 : $Builtin.Int64 |
| } // CHECK: Returns int: 2 |
| |
| // CHECK-LABEL: @interpretCustomStruct3 |
| sil @interpretCustomStruct3 : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = function_ref @constructCustomStruct : $@convention(thin) () -> CustomStruct |
| %2 = apply %1() : $@convention(thin) () -> CustomStruct |
| %3 = struct_extract %2 : $CustomStruct, #CustomStruct.y |
| %4 = struct_extract %3 : $InnerStruct, #InnerStruct.z |
| %5 = struct_extract %4 : $Int64, #Int64._value |
| return %5 : $Builtin.Int64 |
| } // CHECK: Returns int: 3 |
| |
| // CHECK-LABEL: @interpretCustomStruct4 |
| sil @interpretCustomStruct4 : $@convention(thin) () -> Builtin.Int1 { |
| bb0: |
| %1 = function_ref @constructCustomStruct : $@convention(thin) () -> CustomStruct |
| %2 = apply %1() : $@convention(thin) () -> CustomStruct |
| %3 = struct_extract %2 : $CustomStruct, #CustomStruct.y |
| %4 = struct_extract %3 : $InnerStruct, #InnerStruct.w |
| %5 = struct_extract %4 : $Bool, #Bool._value |
| return %5 : $Builtin.Int1 |
| } // CHECK: Returns int: -1 |
| |
| // Test non-constant diagnostics. |
| |
| // CHECK-LABEL: @interpretAndDiagnoseNonConstantVars |
| sil hidden @interpretAndDiagnoseNonConstantVars : $@convention(thin) (Int) -> () { |
| bb0(%0 : $Int): |
| %4 = struct_extract %0 : $Int, #Int._value |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: cannot evaluate expression as constant here |
| %10 = tuple () |
| return %10 : $() |
| } |
| |
| sil @$ss8readLine16strippingNewlineSSSgSb_tF : $@convention(thin) (Bool) -> @owned Optional<String> |
| |
| // CHECK-LABEL: @interpretAndDiagnoseNonConstantCalls |
| sil @interpretAndDiagnoseNonConstantCalls : $@convention(thin) () -> () { |
| bb0: |
| %0 = integer_literal $Builtin.Int1, -1 |
| %1 = struct $Bool (%0 : $Builtin.Int1) |
| // function_ref readLine(strippingNewline:) |
| %2 = function_ref @$ss8readLine16strippingNewlineSSSgSb_tF : $@convention(thin) (Bool) -> @owned Optional<String> |
| %3 = apply %2(%1) : $@convention(thin) (Bool) -> @owned Optional<String> |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: encountered call to 'Swift.readLine(strippingNewline: Swift.Bool) -> Swift.Optional<Swift.String>' whose body is not available |
| release_value %3 : $Optional<String> |
| %5 = tuple () |
| return %5 : $() |
| } |
| |
| // Test loop diagnostics. |
| |
| // CHECK-LABEL: @interpretAndDiagnoseLoops |
| sil hidden @interpretAndDiagnoseLoops : $@convention(thin) () -> () { |
| bb0: |
| br bb1 |
| |
| bb1: |
| %3 = integer_literal $Builtin.Int64, 0 |
| %4 = integer_literal $Builtin.Int64, 100 |
| |
| %5 = builtin "cmp_slt_Int64"(%3 : $Builtin.Int64, %4 : $Builtin.Int64) : $Builtin.Int1 |
| cond_br %5, bb2, bb3 |
| |
| bb2: |
| br bb1 |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: control-flow loop found during evaluation |
| |
| bb3: |
| %10 = tuple () |
| return %10 : $() |
| } |
| |
| // Test stack allocation and memory access. |
| |
| // CHECK-LABEL: @interpretLoadStore |
| sil hidden @interpretLoadStore : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = alloc_stack $Builtin.Int64, var, name "i" |
| %1 = integer_literal $Builtin.Int64, 11 |
| store %1 to %0 : $*Builtin.Int64 |
| %3 = load %0 : $*Builtin.Int64 |
| dealloc_stack %0 : $*Builtin.Int64 |
| return %3 : $Builtin.Int64 |
| } // CHECK: Returns int: 11 |
| |
| // CHECK-LABEL: @interpretBeginEndAccess |
| sil hidden @interpretBeginEndAccess : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = alloc_stack $Builtin.Int64, var, name "i" |
| %1 = integer_literal $Builtin.Int64, 11 |
| %3 = begin_access [modify] [static] %0 : $*Builtin.Int64 |
| store %1 to %3 : $*Builtin.Int64 |
| end_access %3 : $*Builtin.Int64 |
| %5 = load %0 : $*Builtin.Int64 |
| dealloc_stack %0 : $*Builtin.Int64 |
| return %5 : $Builtin.Int64 |
| } // CHECK: Returns int: 11 |
| |
| // Test structs with mutating functions. |
| |
| sil hidden @increment : $@convention(thin) (@inout Int32) -> () { |
| bb0(%0 : $*Int32): |
| %2 = integer_literal $Builtin.Int32, 1 |
| %3 = begin_access [modify] [static] %0 : $*Int32 |
| %4 = struct_element_addr %3 : $*Int32, #Int32._value |
| %5 = load %4 : $*Builtin.Int32 |
| %6 = integer_literal $Builtin.Int1, -1 |
| %7 = builtin "sadd_with_overflow_Int32"(%5 : $Builtin.Int32, %2 : $Builtin.Int32, %6 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) |
| %8 = tuple_extract %7 : $(Builtin.Int32, Builtin.Int1), 0 |
| %9 = tuple_extract %7 : $(Builtin.Int32, Builtin.Int1), 1 |
| cond_fail %9 : $Builtin.Int1 |
| %11 = struct $Int32 (%8 : $Builtin.Int32) |
| store %11 to %3 : $*Int32 |
| %13 = tuple () |
| end_access %3 : $*Int32 |
| %15 = tuple () |
| return %15 : $() |
| } |
| |
| // CHECK-LABEL: @interpretIntInOut |
| sil hidden @interpretIntInOut : $@convention(thin) () -> Builtin.Int32 { |
| bb0: |
| %0 = alloc_stack $Int32, var, name "i" |
| %1 = integer_literal $Builtin.Int32, 13 |
| %2 = struct $Int32 (%1 : $Builtin.Int32) |
| store %2 to %0 : $*Int32 |
| %4 = begin_access [modify] [static] %0 : $*Int32 |
| %5 = function_ref @increment : $@convention(thin) (@inout Int32) -> () |
| %6 = apply %5(%4) : $@convention(thin) (@inout Int32) -> () |
| end_access %4 : $*Int32 |
| |
| %7 = load %0 : $*Int32 |
| %8 = struct_extract %7 : $Int32, #Int32._value |
| dealloc_stack %0 : $*Int32 |
| return %8 : $Builtin.Int32 |
| } // CHECK: Returns int: 14 |
| |
| // CHECK-LABEL: @interpretNoAliasingTest |
| sil hidden @interpretNoAliasingTest : $@convention(thin) () -> Builtin.Int32 { |
| bb0: |
| %0 = alloc_stack $Int32, var, name "x" |
| %1 = integer_literal $Builtin.Int32, 1 |
| %2 = struct $Int32 (%1 : $Builtin.Int32) |
| store %2 to %0 : $*Int32 |
| %4 = alloc_stack $Int32, var, name "y" |
| %5 = begin_access [read] [static] %0 : $*Int32 |
| store %2 to %4 : $*Int32 |
| end_access %5 : $*Int32 |
| %8 = begin_access [modify] [static] %0 : $*Int32 |
| %9 = function_ref @increment : $@convention(thin) (@inout Int32) -> () |
| %10 = apply %9(%8) : $@convention(thin) (@inout Int32) -> () |
| end_access %8 : $*Int32 |
| %12 = begin_access [read] [static] %0 : $*Int32 |
| %13 = load %12 : $*Int32 |
| end_access %12 : $*Int32 |
| %15 = begin_access [read] [static] %4 : $*Int32 |
| end_access %15 : $*Int32 |
| %17 = struct_extract %13 : $Int32, #Int32._value |
| %18 = integer_literal $Builtin.Int1, -1 |
| %19 = builtin "sadd_with_overflow_Int32"(%17 : $Builtin.Int32, %1 : $Builtin.Int32, %18 : $Builtin.Int1) : $(Builtin.Int32, Builtin.Int1) |
| %20 = tuple_extract %19 : $(Builtin.Int32, Builtin.Int1), 0 |
| %21 = tuple_extract %19 : $(Builtin.Int32, Builtin.Int1), 1 |
| cond_fail %21 : $Builtin.Int1 |
| dealloc_stack %4 : $*Int32 |
| dealloc_stack %0 : $*Int32 |
| return %20 : $Builtin.Int32 |
| } // CHECK: Returns int: 3 |
| |
| // Test strings. |
| |
| // CHECK-LABEL: @interpretStringLiteral |
| sil hidden @interpretStringLiteral : $@convention(thin) () -> Builtin.RawPointer { |
| bb0: |
| %0 = string_literal utf8 "plain string" |
| return %0 : $Builtin.RawPointer |
| } // CHECK: Returns string: "plain string" |
| |
| // CHECK-LABEL: @interpretStringLiteralUnicode |
| sil hidden @interpretStringLiteralUnicode : $@convention(thin) () -> Builtin.RawPointer { |
| bb0: |
| %0 = string_literal utf8 "\u{1F496}" |
| return %0 : $Builtin.RawPointer |
| } // CHECK: Returns string: "💖" |
| |
| // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) |
| // The semantics attribute is used by the interpreter. |
| sil [serialized] [always_inline] [readonly] [_semantics "string.makeUTF8"] @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| |
| // CHECK-LABEL: @interpretStringInitIntrinsic |
| sil hidden @interpretStringInitIntrinsic : $@convention(thin) () -> @owned String { |
| bb0: |
| %0 = string_literal utf8 "plain string" |
| %1 = integer_literal $Builtin.Word, 12 |
| %2 = integer_literal $Builtin.Int1, -1 |
| %3 = metatype $@thin String.Type |
| %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| return %5 : $String |
| } // CHECK: Returns string: "plain string" |
| |
| // TODO: Provide a more descriptive note that mentions the actual error. |
| // CHECK-LABEL: @interpretAndDiagnoseStringInitError |
| sil hidden @interpretAndDiagnoseStringInitError: $@convention(thin) () -> @owned String { |
| bb0: |
| %0 = string_literal utf8 "\u{1F496}" |
| %1 = integer_literal $Builtin.Word, 1 // The byte length of the literal is wrong. |
| %2 = integer_literal $Builtin.Int1, 0 |
| %3 = metatype $@thin String.Type |
| %4 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %5 = apply %4(%0, %1, %2, %3) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: operation with invalid operands encountered during evaluation |
| return %5 : $String |
| } |
| |
| // String.append(_:_:) |
| // The semantics attribute is used by the interpreter. |
| sil [serialized] [_semantics "string.append"] @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| |
| // CHECK-LABEL: @interpretStringAppend |
| sil @interpretStringAppend: $@convention(thin) () -> @owned String { |
| bb0: |
| %0 = alloc_stack $String, var, name "a" |
| %1 = string_literal utf8 "a" |
| %2 = integer_literal $Builtin.Word, 1 |
| %3 = integer_literal $Builtin.Int1, -1 |
| %4 = metatype $@thin String.Type |
| %5 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %6 = apply %5(%1, %2, %3, %4) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| store %6 to %0 : $*String |
| %8 = metatype $@thin String.Type |
| %9 = string_literal utf8 "b" |
| %10 = integer_literal $Builtin.Word, 1 |
| %11 = integer_literal $Builtin.Int1, -1 |
| %12 = metatype $@thin String.Type |
| %13 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %14 = apply %13(%9, %10, %11, %12) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %15 = begin_access [modify] [static] %0 : $*String |
| // function_ref static String.append (_:_:) |
| %16 = function_ref @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| %17 = apply %16(%14, %15) : $@convention(method) (@guaranteed String, @inout String) -> () |
| end_access %15 : $*String |
| release_value %14 : $String |
| %20 = begin_access [read] [static] %0 : $*String |
| %21 = load %20 : $*String |
| retain_value %21 : $String |
| end_access %20 : $*String |
| destroy_addr %0 : $*String |
| dealloc_stack %0 : $*String |
| return %21 : $String |
| } // CHECK: Returns string: "ab" |
| |
| // CHECK-LABEL: @interpretStringAppendUnicode |
| sil @interpretStringAppendUnicode: $@convention(thin) () -> @owned String { |
| bb0: |
| %0 = alloc_stack $String, var, name "a" |
| %1 = string_literal utf8 "\u{1F1FA}" |
| %2 = integer_literal $Builtin.Word, 4 |
| %3 = integer_literal $Builtin.Int1, 0 |
| %4 = metatype $@thin String.Type |
| %5 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %6 = apply %5(%1, %2, %3, %4) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| store %6 to %0 : $*String |
| %8 = metatype $@thin String.Type |
| %9 = string_literal utf8 "\u{1F1F8}" |
| %10 = integer_literal $Builtin.Word, 4 |
| %11 = integer_literal $Builtin.Int1, 0 |
| %12 = metatype $@thin String.Type |
| %13 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %14 = apply %13(%9, %10, %11, %12) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %15 = begin_access [modify] [static] %0 : $*String |
| // function_ref static String.+= infix(_:_:) |
| %16 = function_ref @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| %17 = apply %16(%14, %15) : $@convention(method) (@guaranteed String, @inout String) -> () |
| end_access %15 : $*String |
| release_value %14 : $String |
| %20 = begin_access [read] [static] %0 : $*String |
| %21 = load %20 : $*String |
| retain_value %21 : $String |
| end_access %20 : $*String |
| destroy_addr %0 : $*String |
| dealloc_stack %0 : $*String |
| return %21 : $String |
| } // CHECK: Returns string: "🇺🇸" |
| |
| // Test Enums. |
| |
| public enum Shape { |
| case square(Int64) |
| case rectangle(Int64, Int64) |
| } |
| |
| // CHECK-LABEL: @interpretShapeArea |
| sil @interpretShapeArea : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = integer_literal $Builtin.Int64, 10 |
| %2 = struct $Int64 (%1 : $Builtin.Int64) |
| %3 = enum $Shape, #Shape.square!enumelt.1, %2 : $Int64 |
| switch_enum %3 : $Shape, case #Shape.square!enumelt.1: bb1, case #Shape.rectangle!enumelt.1: bb2 |
| |
| bb1(%4 : $Int64): |
| debug_value %4 : $Int64, let, name "side" |
| %5 = struct_extract %4 : $Int64, #Int64._value |
| %6 = struct_extract %4 : $Int64, #Int64._value |
| %7 = integer_literal $Builtin.Int1, -1 |
| %8 = builtin "smul_with_overflow_Int64"(%5 : $Builtin.Int64, %6 : $Builtin.Int64, %7 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| %9 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 0 |
| %10 = tuple_extract %8 : $(Builtin.Int64, Builtin.Int1), 1 |
| cond_fail %10 : $Builtin.Int1 |
| br bb3(%9 : $Builtin.Int64) |
| |
| bb2(%15 : $(Int64, Int64)): |
| %16 = tuple_extract %15 : $(Int64, Int64), 0 |
| %17 = tuple_extract %15 : $(Int64, Int64), 1 |
| debug_value %16 : $Int64, let, name "length" |
| debug_value %17 : $Int64, let, name "width" |
| %20 = struct_extract %16 : $Int64, #Int64._value // user: %23 |
| %21 = struct_extract %17 : $Int64, #Int64._value // user: %23 |
| %22 = integer_literal $Builtin.Int1, -1 |
| %23 = builtin "smul_with_overflow_Int64"(%20 : $Builtin.Int64, %21 : $Builtin.Int64, %22 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| %24 = tuple_extract %23 : $(Builtin.Int64, Builtin.Int1), 0 |
| %25 = tuple_extract %23 : $(Builtin.Int64, Builtin.Int1), 1 |
| cond_fail %25 : $Builtin.Int1 |
| br bb3(%24 : $Builtin.Int64) |
| |
| bb3(%30 : $Builtin.Int64): |
| return %30 : $Builtin.Int64 |
| } // CHECK: Returns int: 100 |
| |
| // Test inject_enum_addr instruction. |
| |
| public enum Direction { |
| case north |
| case south |
| case east |
| case west |
| } |
| |
| sil @isNorth : $@convention(thin) (@in_guaranteed Direction) -> Builtin.Int32 { |
| bb0(%0 : $*Direction): |
| switch_enum_addr %0 : $*Direction, case #Direction.north!enumelt: bb1, default bb2 |
| |
| bb1: |
| %3 = integer_literal $Builtin.Int32, 1 |
| br bb3(%3 : $Builtin.Int32) |
| |
| bb2: |
| %6 = integer_literal $Builtin.Int32, 0 |
| br bb3(%6 : $Builtin.Int32) |
| |
| bb3(%9 : $Builtin.Int32): |
| return %9 : $Builtin.Int32 |
| } |
| |
| // CHECK: @interpretTestInjectEnumAddr |
| sil hidden @interpretTestInjectEnumAddr : $@convention(thin) () -> Builtin.Int32 { |
| bb0: |
| %1 = alloc_stack $Direction |
| inject_enum_addr %1 : $*Direction, #Direction.north!enumelt |
| %2 = function_ref @isNorth : $@convention(thin) (@in_guaranteed Direction) -> Builtin.Int32 |
| %3 = apply %2(%1) : $@convention(thin) (@in_guaranteed Direction) -> Builtin.Int32 |
| destroy_addr %1 : $*Direction |
| dealloc_stack %1 : $*Direction |
| return %3 : $Builtin.Int32 |
| } // CHECK: Returns int: 1 |
| |
| // Test select_enum and select_enum_addr instructions. |
| |
| // CHECK: @interpretTestSelectEnum |
| sil hidden @interpretTestSelectEnum : $@convention(thin) () -> Builtin.Int32 { |
| bb0: |
| %1 = enum $Direction, #Direction.north!enumelt |
| %2 = integer_literal $Builtin.Int32, 1 |
| %3 = integer_literal $Builtin.Int32, 0 |
| %4 = select_enum %1 : $Direction, case #Direction.north!enumelt: %2, default %3 : $Builtin.Int32 |
| return %4 : $Builtin.Int32 |
| } // CHECK: Returns int: 1 |
| |
| // CHECK: @interpretTestSelectEnumAddr |
| sil hidden @interpretTestSelectEnumAddr : $@convention(thin) () -> Builtin.Int32 { |
| bb0: |
| %1 = alloc_stack $Direction |
| inject_enum_addr %1 : $*Direction, #Direction.north!enumelt |
| %2 = integer_literal $Builtin.Int32, 1 |
| %3 = integer_literal $Builtin.Int32, 0 |
| %4 = select_enum_addr %1 : $*Direction, case #Direction.north!enumelt: %2, default %3 : $Builtin.Int32 |
| destroy_addr %1 : $*Direction |
| dealloc_stack %1 : $*Direction |
| return %4 : $Builtin.Int32 |
| } // CHECK: Returns int: 1 |
| |
| // Test calling conventions. |
| |
| // Test struct with a string property. The struct will be passed and returned |
| // @guaranteed when its methods are called. |
| |
| struct S { |
| var prop: String |
| } |
| |
| sil hidden @initS : $@convention(thin) () -> @owned S { |
| bb0: |
| %2 = string_literal utf8 "something" |
| %3 = integer_literal $Builtin.Word, 9 |
| %4 = integer_literal $Builtin.Int1, -1 |
| %5 = metatype $@thin String.Type |
| // String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:) |
| %6 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %7 = apply %6(%2, %3, %4, %5) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %12 = struct $S (%7 : $String) |
| retain_value %12 : $S |
| return %12 : $S |
| } |
| |
| sil @getProp : $@convention(method) (@guaranteed S) -> @owned String { |
| bb0(%0 : $S): |
| %2 = struct_extract %0 : $S, #S.prop |
| retain_value %2 : $String |
| return %2 : $String |
| } |
| |
| // CHECK: @interpretGuaranteedConvention |
| sil @interpretGuaranteedConvention : $@convention(thin) () -> @owned String { |
| bb0: |
| %1 = function_ref @initS : $@convention(thin) () -> @owned S |
| %2 = apply %1() : $@convention(thin) () -> @owned S |
| %4 = function_ref @getProp : $@convention(method) (@guaranteed S) -> @owned String |
| %5 = apply %4(%2) : $@convention(method) (@guaranteed S) -> @owned String |
| release_value %2 : $S |
| return %5 : $String |
| } // CHECK: Returns string: "something" |
| |
| |
| // TODO: add tests for generic functions, generic structs and generic enums. |
| |
| // A composite test that mimics the format specifier construction used by |
| // os log APIs. |
| |
| enum IntFormat { |
| case decimal |
| case hex |
| case octal |
| } |
| |
| // getIntegerFormatSpecifier(IntFormat:isPrivate:bitWidth:isSigned:) |
| sil @getIntegerFormatSpecifier : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String { |
| bb0(%0 : $IntFormat, %1 : $Bool, %2 : $Int64, %3 : $Bool): |
| %10 = alloc_stack $String, var, name "formatSpecifier" |
| %11 = struct_extract %1 : $Bool, #Bool._value |
| cond_br %11, bb1, bb2 |
| |
| bb1: |
| %13 = string_literal utf8 "%{private}" |
| %14 = integer_literal $Builtin.Word, 10 |
| %15 = integer_literal $Builtin.Int1, -1 |
| %16 = metatype $@thin String.Type |
| %17 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %18 = apply %17(%13, %14, %15, %16) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| br bb3(%18 : $String) |
| |
| bb2: |
| %20 = string_literal utf8 "%{public}" |
| %21 = integer_literal $Builtin.Word, 9 |
| %22 = integer_literal $Builtin.Int1, -1 |
| %23 = metatype $@thin String.Type |
| %24 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %25 = apply %24(%20, %21, %22, %23) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| br bb3(%25 : $String) |
| |
| bb3(%27 : $String): |
| store %27 to %10 : $*String |
| %29 = integer_literal $Builtin.Int64, 64 |
| %30 = struct_extract %2 : $Int64, #Int64._value |
| %31 = builtin "cmp_eq_Int64"(%30 : $Builtin.Int64, %29 : $Builtin.Int64) : $Builtin.Int1 |
| %32 = struct $Bool (%31 : $Builtin.Int1) |
| %33 = struct_extract %32 : $Bool, #Bool._value |
| cond_br %33, bb4, bb5 |
| |
| bb4: |
| %35 = metatype $@thin String.Type |
| %36 = string_literal utf8 "ll" |
| %37 = integer_literal $Builtin.Word, 2 |
| %38 = integer_literal $Builtin.Int1, -1 |
| %39 = metatype $@thin String.Type |
| %40 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %41 = apply %40(%36, %37, %38, %39) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %42 = begin_access [modify] [static] %10 : $*String |
| %43 = function_ref @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| %44 = apply %43(%41, %42) : $@convention(method) (@guaranteed String, @inout String) -> () |
| end_access %42 : $*String |
| release_value %41 : $String |
| br bb6 |
| |
| bb5: |
| br bb6 |
| |
| bb6: |
| switch_enum %0 : $IntFormat, case #IntFormat.hex!enumelt: bb7, case #IntFormat.octal!enumelt: bb8, default bb9 |
| |
| bb7: |
| %50 = metatype $@thin String.Type |
| %51 = string_literal utf8 "x" |
| %52 = integer_literal $Builtin.Word, 1 |
| %53 = integer_literal $Builtin.Int1, -1 |
| %54 = metatype $@thin String.Type |
| %55 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %56 = apply %55(%51, %52, %53, %54) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %57 = begin_access [modify] [static] %10 : $*String |
| %58 = function_ref @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| %59 = apply %58(%56, %57) : $@convention(method) (@guaranteed String, @inout String) -> () |
| end_access %57 : $*String |
| release_value %56 : $String |
| br bb13 |
| |
| bb8: |
| %63 = metatype $@thin String.Type |
| %64 = string_literal utf8 "o" |
| %65 = integer_literal $Builtin.Word, 1 |
| %66 = integer_literal $Builtin.Int1, -1 |
| %67 = metatype $@thin String.Type |
| %68 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %69 = apply %68(%64, %65, %66, %67) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %70 = begin_access [modify] [static] %10 : $*String |
| %71 = function_ref @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| %72 = apply %71(%69, %70) : $@convention(method) (@guaranteed String, @inout String) -> () |
| end_access %70 : $*String |
| release_value %69 : $String |
| br bb13 |
| |
| bb9: |
| %76 = metatype $@thin String.Type |
| %77 = struct_extract %3 : $Bool, #Bool._value |
| cond_br %77, bb10, bb11 |
| |
| bb10: |
| %79 = string_literal utf8 "d" |
| %80 = integer_literal $Builtin.Word, 1 |
| %81 = integer_literal $Builtin.Int1, -1 |
| %82 = metatype $@thin String.Type |
| %83 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %84 = apply %83(%79, %80, %81, %82) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| br bb12(%84 : $String) |
| |
| bb11: |
| %86 = string_literal utf8 "u" |
| %87 = integer_literal $Builtin.Word, 1 |
| %88 = integer_literal $Builtin.Int1, -1 |
| %89 = metatype $@thin String.Type |
| %90 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %91 = apply %90(%86, %87, %88, %89) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| br bb12(%91 : $String) |
| |
| bb12(%93 : $String): |
| %94 = begin_access [modify] [static] %10 : $*String |
| %95 = function_ref @$sSS6appendyySSF : $@convention(method) (@guaranteed String, @inout String) -> () |
| %96 = apply %95(%93, %94) : $@convention(method) (@guaranteed String, @inout String) -> () |
| end_access %94 : $*String |
| release_value %93 : $String |
| br bb13 |
| |
| bb13: |
| %100 = begin_access [read] [static] %10 : $*String |
| %101 = load %100 : $*String |
| retain_value %101 : $String |
| end_access %100 : $*String |
| destroy_addr %10 : $*String |
| dealloc_stack %10 : $*String |
| return %101 : $String |
| } |
| |
| // CHECK-LABEL: @interpretGetPrivateInt64FormatString |
| sil @interpretGetPrivateInt64FormatString : $@convention(thin) () -> @owned String { |
| bb0: |
| %2 = metatype $@thin IntFormat.Type |
| %3 = enum $IntFormat, #IntFormat.decimal!enumelt |
| %4 = integer_literal $Builtin.Int1, -1 |
| %5 = struct $Bool (%4 : $Builtin.Int1) |
| %6 = integer_literal $Builtin.Int64, 64 |
| %7 = struct $Int64 (%6 : $Builtin.Int64) |
| %8 = integer_literal $Builtin.Int1, -1 |
| %9 = struct $Bool (%8 : $Builtin.Int1) |
| %10 = function_ref @getIntegerFormatSpecifier : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| %11 = apply %10(%3, %5, %7, %9) : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| return %11 : $String |
| } // CHECK: Returns string: "%{private}lld" |
| |
| // CHECK-LABEL: @interpretGetPrivateHexInt64FormatString |
| sil @interpretGetPrivateHexInt64FormatString : $@convention(thin) () -> @owned String { |
| bb0: |
| %2 = metatype $@thin IntFormat.Type |
| %3 = enum $IntFormat, #IntFormat.hex!enumelt |
| %4 = integer_literal $Builtin.Int1, -1 |
| %5 = struct $Bool (%4 : $Builtin.Int1) |
| %6 = integer_literal $Builtin.Int64, 64 |
| %7 = struct $Int64 (%6 : $Builtin.Int64) |
| %8 = integer_literal $Builtin.Int1, -1 |
| %9 = struct $Bool (%8 : $Builtin.Int1) |
| %10 = function_ref @getIntegerFormatSpecifier : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| %11 = apply %10(%3, %5, %7, %9) : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| return %11 : $String |
| } // CHECK: Returns string: "%{private}llx" |
| |
| // CHECK-LABEL: @interpretGetPublicOctalInt32FormatString |
| sil @interpretGetPublicOctalInt32FormatString : $@convention(thin) () -> @owned String { |
| bb0: |
| %2 = metatype $@thin IntFormat.Type |
| %3 = enum $IntFormat, #IntFormat.octal!enumelt |
| %4 = integer_literal $Builtin.Int1, 0 |
| %5 = struct $Bool (%4 : $Builtin.Int1) |
| %6 = integer_literal $Builtin.Int64, 32 |
| %7 = struct $Int64 (%6 : $Builtin.Int64) |
| %8 = integer_literal $Builtin.Int1, -1 |
| %9 = struct $Bool (%8 : $Builtin.Int1) |
| %10 = function_ref @getIntegerFormatSpecifier : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| %11 = apply %10(%3, %5, %7, %9) : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| return %11 : $String |
| } // CHECK: Returns string: "%{public}o" |
| |
| // CHECK-LABEL: @interpretGetUInt64FormatString |
| sil @interpretGetUInt64FormatString : $@convention(thin) () -> @owned String { |
| bb0: |
| %2 = metatype $@thin IntFormat.Type |
| %3 = enum $IntFormat, #IntFormat.decimal!enumelt |
| %4 = integer_literal $Builtin.Int1, 0 |
| %5 = struct $Bool (%4 : $Builtin.Int1) |
| %6 = integer_literal $Builtin.Int64, 64 |
| %7 = struct $Int64 (%6 : $Builtin.Int64) |
| %8 = integer_literal $Builtin.Int1, 0 |
| %9 = struct $Bool (%8 : $Builtin.Int1) |
| %10 = function_ref @getIntegerFormatSpecifier : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| %11 = apply %10(%3, %5, %7, %9) : $@convention(thin) (IntFormat, Bool, Int64, Bool) -> @owned String |
| return %11 : $String |
| } // CHECK: Returns string: "%{public}llu" |
| |
| // String.percentEscapedString.getter |
| // The semantics attribute is used by the interpreter. |
| sil [serialized] [readonly] [_semantics "string.escapePercent.get"] @$sSS14OSLogPrototypeE20percentEscapedStringSSvg : $@convention(method) (@guaranteed String) -> @owned String |
| |
| // CHECK-LABEL: @interpretStringPercentEscape |
| sil @interpretStringPercentEscape : $@convention(thin) () -> @owned String { |
| bb0: |
| %1 = string_literal utf8 "a%" |
| %2 = integer_literal $Builtin.Word, 2 |
| %3 = integer_literal $Builtin.Int1, -1 |
| %4 = metatype $@thin String.Type |
| %5 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %6 = apply %5(%1, %2, %3, %4) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %8 = function_ref @$sSS14OSLogPrototypeE20percentEscapedStringSSvg : $@convention(method) (@guaranteed String) -> @owned String |
| %9 = apply %8(%6) : $@convention(method) (@guaranteed String) -> @owned String |
| return %9 : $String |
| } // CHECK: Returns string: "a%%" |
| |
| // CHECK-LABEL: @interpretEscapeMutiplePercent |
| sil @interpretEscapeMutiplePercent : $@convention(thin) () -> @owned String { |
| bb0: |
| %1 = string_literal utf8 "%%%a% %%b%" |
| %2 = integer_literal $Builtin.Word, 10 |
| %3 = integer_literal $Builtin.Int1, -1 |
| %4 = metatype $@thin String.Type |
| %5 = function_ref @$sSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %6 = apply %5(%1, %2, %3, %4) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String |
| %8 = function_ref @$sSS14OSLogPrototypeE20percentEscapedStringSSvg : $@convention(method) (@guaranteed String) -> @owned String |
| %9 = apply %8(%6) : $@convention(method) (@guaranteed String) -> @owned String |
| return %9 : $String |
| } // CHECK: Returns string: "%%%%%%a%% %%%%b%%" |
| |
| // Tests for Ownership SIL. |
| |
| // CHECK-LABEL: @interpretDestructureInt64 |
| sil [ossa] @interpretDestructureInt64 : $@convention(thin) () -> Builtin.Int64 { |
| %1 = integer_literal $Builtin.Int64, 12 |
| %2 = struct $Int64 (%1 : $Builtin.Int64) |
| %3 = destructure_struct %2 : $Int64 |
| return %3 : $Builtin.Int64 |
| } // CHECK: Returns int: 12 |
| |
| struct IntPair { |
| var first: Builtin.Int64 |
| var second: Builtin.Int64 |
| } |
| |
| // CHECK-LABEL: @interpretIntPairStruct |
| sil [ossa] @interpretIntPairStruct : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 17 |
| %1 = integer_literal $Builtin.Int64, 34 |
| %2 = struct $IntPair (%0: $Builtin.Int64, %1: $Builtin.Int64) |
| (%3, %4) = destructure_struct %2 : $IntPair |
| return %4 : $Builtin.Int64 |
| } // CHECK: Returns int: 34 |
| |
| sil [ossa] @constructCustomStructOSSA : $@convention(thin) () -> CustomStruct { |
| bb0: |
| %1 = integer_literal $Builtin.Int64, 11 |
| %2 = struct $Int64 (%1 : $Builtin.Int64) |
| %3 = integer_literal $Builtin.Int64, 12 |
| %4 = struct $Int64 (%3 : $Builtin.Int64) |
| %6 = integer_literal $Builtin.Int64, 13 |
| %7 = struct $Int64 (%6 : $Builtin.Int64) |
| %8 = integer_literal $Builtin.Int1, 0 |
| %9 = struct $Bool (%8 : $Builtin.Int1) |
| |
| %10 = struct $InnerStruct (%7 : $Int64, %9 : $Bool) |
| %11 = tuple (%2 : $Int64, %4 : $Int64) |
| %12 = struct $CustomStruct (%11 : $(Int64, Int64), %10 : $InnerStruct) |
| return %12 : $CustomStruct |
| } |
| |
| // CHECK-LABEL: @interpretCustomStructOSSA |
| sil [ossa] @interpretCustomStructOSSA : $@convention(thin) () -> Builtin.Int64 { |
| bb0: |
| %1 = function_ref @constructCustomStructOSSA : $@convention(thin) () -> CustomStruct |
| %2 = apply %1() : $@convention(thin) () -> CustomStruct |
| (%3, %4) = destructure_struct %2 : $CustomStruct |
| (%5, %6) = destructure_tuple %3 : $(Int64, Int64) |
| (%7, %8) = destructure_struct %4 : $InnerStruct |
| %9 = destructure_struct %5 : $Int64 |
| %10 = destructure_struct %6 : $Int64 |
| %11 = destructure_struct %7 : $Int64 |
| %12 = destructure_struct %8 : $Bool |
| cond_fail %12 : $Builtin.Int1 |
| |
| %13 = integer_literal $Builtin.Int1, -1 |
| %14 = builtin "sadd_with_overflow_Int64"(%9 : $Builtin.Int64, %10 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| (%15, %16) = destructure_tuple %14 : $(Builtin.Int64, Builtin.Int1) |
| cond_fail %16 : $Builtin.Int1 |
| |
| %17 = builtin "sadd_with_overflow_Int64"(%15 : $Builtin.Int64, %11 : $Builtin.Int64, %13 : $Builtin.Int1) : $(Builtin.Int64, Builtin.Int1) |
| (%18, %19) = destructure_tuple %17 : $(Builtin.Int64, Builtin.Int1) |
| cond_fail %19 : $Builtin.Int1 |
| return %18 : $Builtin.Int64 |
| } // CHECK: Returns int: 36 |
| |
| // Tests for builtin "ptrtoint_Word", which is supported only for string |
| // constants in order to handle 'StaticString' construction. |
| |
| // CHECK-LABEL: @interpretPtrToInt |
| sil @interpretPtrToInt : $@convention(thin) () -> Builtin.Word { |
| %0 = string_literal utf8 "Fatal error" |
| %1 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word |
| return %1 : $Builtin.Word |
| } // CHECK: Returns string: "Fatal error" |
| |
| // CHECK-LABEL: @interpretStaticStringInit |
| sil @interpretStaticStringInit : $@convention(thin) () -> Builtin.Word { |
| %0 = string_literal utf8 "static error message" |
| %1 = integer_literal $Builtin.Word, 11 |
| %2 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word |
| %3 = integer_literal $Builtin.Int8, 2 |
| %4 = struct $StaticString (%2 : $Builtin.Word, %1 : $Builtin.Word, %3 : $Builtin.Int8) |
| %5 = struct_extract %4 : $StaticString, #StaticString._startPtrOrData |
| return %5 : $Builtin.Word |
| } // CHECK: Returns string: "static error message" |
| |
| // Tests for builtin "assert_configuration". Constant evaluator evaluates this |
| // builtin to 0, meaning that the the configuration is "debug". |
| |
| // CHECK-LABEL: @interpretAssertConfiguration |
| sil @interpretAssertConfiguration : $@convention(thin) () -> Builtin.Int32 { |
| %0 = builtin "assert_configuration"() : $Builtin.Int32 |
| return %0 : $Builtin.Int32 |
| } // CHECK: Returns int: 0 |
| |
| // Tests for "assertionFailure" stdlib functions. Such functions have the |
| // @_semantics attribute: "programtermination_point" |
| |
| sil [noinline] [_semantics "programtermination_point"] [canonical] @$assertionFailure : $@convention(thin) (StaticString, StaticString, UInt64) -> Never |
| |
| // CHECK-LABEL: @interpretAssertionFailure |
| sil @interpretAssertionFailure : $@convention(thin) () -> Never { |
| // Construct error prefix. |
| %0 = string_literal utf8 "error-prefix" |
| %1 = integer_literal $Builtin.Word, 12 |
| %2 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word |
| %3 = integer_literal $Builtin.Int8, 2 |
| %4 = struct $StaticString (%2 : $Builtin.Word, %1 : $Builtin.Word, %3 : $Builtin.Int8) |
| |
| // Construct error message. |
| %10 = string_literal utf8 "message" |
| %11 = integer_literal $Builtin.Word, 7 |
| %12 = builtin "ptrtoint_Word"(%10 : $Builtin.RawPointer) : $Builtin.Word |
| %13 = integer_literal $Builtin.Int8, 2 |
| %14 = struct $StaticString (%12 : $Builtin.Word, %11 : $Builtin.Word, %13 : $Builtin.Int8) |
| |
| // Construct line number. |
| %20 = integer_literal $Builtin.Int64, 1208 |
| %21 = struct $UInt64 (%20 : $Builtin.Int64) |
| |
| %22 = function_ref @$assertionFailure : $@convention(thin) (StaticString, StaticString, UInt64) -> Never |
| %23 = apply %22(%4, %14, %21) : $@convention(thin) (StaticString, StaticString, UInt64) -> Never |
| // CHECK: {{.*}}:[[@LINE-1]]:{{.*}}: note: error-prefix: message |
| unreachable |
| } |
| |
| // Tests for arrays. |
| |
| // Array.init() |
| sil [serialized] [_semantics "array.init.empty"] @$sS2ayxGycfC : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| |
| // _allocateUninitializedArray<A>(_:) |
| sil [serialized] [always_inline] [_semantics "array.uninitialized_intrinsic"] @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) |
| |
| sil @interpretArrayInit : $@convention(thin) () -> @owned Array<Int> { |
| bb0: |
| %0 = metatype $@thin Array<Int>.Type |
| // function_ref Array.init() |
| %1 = function_ref @$sS2ayxGycfC : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| %2 = apply %1<Int>(%0) : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| return %2 : $Array<Int> |
| } // CHECK: Returns Array<Int> |
| // CHECK: size: 0 contents [] |
| |
| sil [ossa] @interpretEmptyArrayLiteral : $@convention(thin) () -> @owned Array<String> { |
| bb0: |
| %0 = integer_literal $Builtin.Word, 0 |
| // function_ref _allocateUninitializedArray<A>(_:) |
| %1 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) |
| %2 = apply %1<String>(%0) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) |
| (%3, %4) = destructure_tuple %2 : $(Array<String>, Builtin.RawPointer) |
| return %3 : $Array<String> |
| } // CHECK: Returns Array<String> |
| // CHECK: size: 0 contents [] |
| |
| sil [ossa] @initializeArrayWithLiterals : $@convention(thin) () -> @owned Array<Int64> { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 11 // element 1 |
| %1 = struct $Int64 (%0 : $Builtin.Int64) |
| %2 = integer_literal $Builtin.Int64, 12 // element 2 |
| %3 = struct $Int64 (%2 : $Builtin.Int64) |
| %4 = integer_literal $Builtin.Int64, 14 // element 3 |
| %5 = struct $Int64 (%4 : $Builtin.Int64) |
| |
| %6 = integer_literal $Builtin.Word, 3 // array literal size |
| // function_ref _allocateUninitializedArray<A>(_:) |
| %7 = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) |
| %8 = apply %7<Int64>(%6) : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer) |
| (%9, %10) = destructure_tuple %8 : $(Array<Int64>, Builtin.RawPointer) |
| %11 = pointer_to_address %10 : $Builtin.RawPointer to [strict] $*Int64 |
| store %1 to [trivial] %11 : $*Int64 |
| %13 = integer_literal $Builtin.Word, 1 // Index: 1 |
| %14 = index_addr %11 : $*Int64, %13 : $Builtin.Word |
| store %3 to [trivial] %14 : $*Int64 |
| %16 = integer_literal $Builtin.Word, 2 // Index: 2 |
| %17 = index_addr %11 : $*Int64, %16 : $Builtin.Word |
| store %5 to [trivial] %17 : $*Int64 |
| return %9 : $Array<Int64> |
| } |
| |
| sil [ossa] @interpretArrayLiteral : $@convention(thin) () -> @owned Array<Int64> { |
| bb0: |
| %7 = function_ref @initializeArrayWithLiterals : $@convention(thin) () -> @owned Array<Int64> |
| %8 = apply %7() : $@convention(thin) () -> @owned Array<Int64> |
| return %8 : $Array<Int64> |
| } // CHECK: Returns Array<Int64> |
| // CHECK: size: 3 |
| // CHECK: agg: 1 elt: int: 11 |
| // CHECK: agg: 1 elt: int: 12 |
| // CHECK: agg: 1 elt: int: 14 |
| |
| // Array.append(_:) |
| sil [serialized] [_semantics "array.append_element"] @$sSa6appendyyxnF : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| |
| sil [ossa] @interpretArrayAppend : $@convention(thin) () -> @owned Array<Int64> { |
| %0 = integer_literal $Builtin.Int64, 71 |
| %1 = struct $Int64 (%0 : $Builtin.Int64) |
| %2 = alloc_stack $Array<Int64>, var, name "a" |
| %3 = metatype $@thin Array<Int64>.Type |
| // function_ref Array.init() |
| %4 = function_ref @$sS2ayxGycfC : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| %5 = apply %4<Int64>(%3) : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| store %5 to [init] %2 : $*Array<Int64> |
| %10 = alloc_stack $Int64 |
| store %1 to [trivial] %10 : $*Int64 |
| // function_ref Array.append(_:) |
| %13 = function_ref @$sSa6appendyyxnF : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| %14 = apply %13<Int64>(%10, %2) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| dealloc_stack %10 : $*Int64 |
| %18 = load [copy] %2 : $*Array<Int64> |
| destroy_addr %2 : $*Array<Int64> |
| dealloc_stack %2 : $*Array<Int64> |
| return %18 : $Array<Int64> |
| } // CHECK: Returns Array<Int64> |
| // CHECK: size: 1 |
| // CHECK: agg: 1 elt: int: 71 |
| |
| sil [ossa] @interpretArrayAppendNonEmpty : $@convention(thin) () -> @owned Array<Int64> { |
| bb0: |
| %0 = integer_literal $Builtin.Int64, 100 |
| %1 = struct $Int64 (%0 : $Builtin.Int64) |
| %2 = alloc_stack $Array<Int64>, var, name "a" |
| %3 = metatype $@thin Array<Int64>.Type |
| %4 = function_ref @initializeArrayWithLiterals : $@convention(thin) () -> @owned Array<Int64> |
| %5 = apply %4() : $@convention(thin) () -> @owned Array<Int64> |
| store %5 to [init] %2 : $*Array<Int64> |
| %10 = alloc_stack $Int64 |
| store %1 to [trivial] %10 : $*Int64 |
| // function_ref Array.append(_:) |
| %13 = function_ref @$sSa6appendyyxnF : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| %14 = apply %13<Int64>(%10, %2) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| dealloc_stack %10 : $*Int64 |
| %18 = load [copy] %2 : $*Array<Int64> |
| destroy_addr %2 : $*Array<Int64> |
| dealloc_stack %2 : $*Array<Int64> |
| return %18 : $Array<Int64> |
| } // CHECK: Returns Array<Int64> |
| // CHECK: size: 4 |
| // CHECK: agg: 1 elt: int: 11 |
| // CHECK: agg: 1 elt: int: 12 |
| // CHECK: agg: 1 elt: int: 14 |
| // CHECK: agg: 1 elt: int: 100 |
| |
| /// Test appending of a static string to an array. The construction of a static |
| /// string is a bit complicated due to the use of instructions like "ptrtoint". |
| /// This tests that array append works with such complex constant values as well. |
| sil @interpretArrayAppendStaticString : $@convention(thin) () -> @owned Array<StaticString> { |
| %0 = string_literal utf8 "constant" // string to be appended. |
| |
| // Initialize an empty array |
| %2 = alloc_stack $Array<StaticString>, var, name "a" |
| %3 = metatype $@thin Array<StaticString>.Type |
| // function_ref Array.init() |
| %4 = function_ref @$sS2ayxGycfC : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| %5 = apply %4<StaticString>(%3) : $@convention(method) <τ_0_0> (@thin Array<τ_0_0>.Type) -> @owned Array<τ_0_0> |
| store %5 to %2 : $*Array<StaticString> |
| |
| // Initialize a static string. |
| %6 = integer_literal $Builtin.Word, 8 |
| %7 = builtin "ptrtoint_Word"(%0 : $Builtin.RawPointer) : $Builtin.Word |
| %8 = integer_literal $Builtin.Int8, 2 |
| %9 = struct $StaticString (%7 : $Builtin.Word, %6 : $Builtin.Word, %8 : $Builtin.Int8) |
| |
| %10 = alloc_stack $StaticString |
| store %9 to %10 : $*StaticString |
| // function_ref Array.append(_:) |
| %13 = function_ref @$sSa6appendyyxnF : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| %14 = apply %13<StaticString>(%10, %2) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> () |
| dealloc_stack %10 : $*StaticString |
| %18 = load %2 : $*Array<StaticString> |
| destroy_addr %2 : $*Array<StaticString> |
| dealloc_stack %2 : $*Array<StaticString> |
| return %18 : $Array<StaticString> |
| } // CHECK: Returns Array<StaticString> |
| // CHECK: size: 1 |
| // CHECK: string: "constant" |
| |