Files
swift-mirror/test/SILOptimizer/constant_evaluator_test.sil
Nate Chandler e5d87f75a8 [SIL] Add source formal type to checked_cast_br.
It is necessary for opaque values where for casts that will newly start
out as checked_cast_brs and be lowered to checked_cast_addr_brs, since
the latter has the source formal type, IRGen relies on being able to
access it, and there's no way in general to obtain the source formal
type from the source lowered type.
2023-07-27 15:04:15 -07:00

1557 lines
65 KiB
Plaintext

// 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 truncated 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: encountered use of a variable not tracked by the evaluator
%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 'readLine(strippingNewline:)' 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, %2 : $Int64
switch_enum %3 : $Shape, case #Shape.square!enumelt: bb1, case #Shape.rectangle!enumelt: 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: @interpretEscapeMultiplePercent
sil @interpretEscapeMultiplePercent : $@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 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)
// CHECK-LABEL: @interpretArrayInit
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 []
// CHECK-LABEL: @interpretEmptyArrayLiteral
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>
}
// CHECK-LABEL: @interpretArrayLiteral
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>) -> ()
// CHECK-LABEL: @interpretArrayAppend
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
// CHECK-LABEL: @interpretArrayAppendNonEmpty
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
struct StructContainingArray {
var array: [Int64]
}
// CHECK-LABEL: @interpretArrayAppendViaStructElementAddr
sil [ossa] @interpretArrayAppendViaStructElementAddr : $@convention(thin) () -> @owned StructContainingArray {
bb0:
%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>
%6 = struct $StructContainingArray (%5 : $Array<Int64>)
%7 = alloc_stack $StructContainingArray, var, name "s"
store %6 to [init] %7 : $*StructContainingArray
%8 = struct_element_addr %7 : $*StructContainingArray, #StructContainingArray.array
%9 = integer_literal $Builtin.Int64, 105
%10 = struct $Int64 (%9 : $Builtin.Int64)
%11 = alloc_stack $Int64
store %10 to [trivial] %11 : $*Int64
// function_ref Array.append(_:)
%13 = function_ref @$sSa6appendyyxnF : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> ()
%14 = apply %13<Int64>(%11, %8) : $@convention(method) <τ_0_0> (@in τ_0_0, @inout Array<τ_0_0>) -> ()
dealloc_stack %11 : $*Int64
%18 = load [copy] %7 : $*StructContainingArray
destroy_addr %7 : $*StructContainingArray
dealloc_stack %7 : $*StructContainingArray
return %18 : $StructContainingArray
} // CHECK: agg: 1 elt: Array<Int64>:
// CHECK: size: 1
// CHECK: agg: 1 elt: int: 105
/// 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.
// CHECK-LABEL: @interpretArrayAppendStaticString
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"
// Test partial apply and closure creation.
sil private @closure1 : $@convention(thin) (Int32) -> Int32 {
bb0(%0 : $Int32):
return %0 : $Int32
}
// CHECK-LABEL: @interpretPartialApply
sil @interpretPartialApply: $@convention(thin) () -> @owned @callee_guaranteed () -> Int32 {
bb0:
%0 = integer_literal $Builtin.Int32, 81
%1 = struct $Int32 (%0 : $Builtin.Int32)
%2 = function_ref @closure1 : $@convention(thin) (Int32) -> Int32
%3 = partial_apply [callee_guaranteed] %2(%1) : $@convention(thin) (Int32) -> Int32
return %3 : $@callee_guaranteed () -> Int32
} // CHECK: Returns closure: target: closure1 captures
// CHECK: %1
// CHECK: values:
// CHECK: int: 81
sil private @closure2 : $@convention(thin) (Int32, Int32) -> Int32 {
bb0(%0 : $Int32, %1: $Int32):
return %0 : $Int32
}
sil private @closure3 : $@convention(thin) (@guaranteed @callee_guaranteed (Int32) -> Int32) -> Int32 {
bb0(%0 : $@callee_guaranteed (Int32) -> Int32):
%3 = integer_literal $Builtin.Int32, 19
%4 = struct $Int32 (%3 : $Builtin.Int32)
%5 = apply %0(%4) : $@callee_guaranteed (Int32) -> Int32
return %5 : $Int32
}
// CHECK-LABEL: @interpretPartialApplyChain
sil @interpretPartialApplyChain: $@convention(thin) () -> @owned @callee_guaranteed () -> Int32 {
bb0:
%0 = integer_literal $Builtin.Int32, 991
%1 = struct $Int32 (%0 : $Builtin.Int32)
%2 = function_ref @closure2 : $@convention(thin) (Int32, Int32) -> Int32
%3 = partial_apply [callee_guaranteed] %2(%1) : $@convention(thin) (Int32, Int32) -> Int32
%5 = function_ref @closure3 : $@convention(thin) (@guaranteed @callee_guaranteed (Int32) -> Int32) -> Int32
strong_retain %3 : $@callee_guaranteed (Int32) -> Int32
%7 = partial_apply [callee_guaranteed] %5(%3) : $@convention(thin) (@guaranteed @callee_guaranteed (Int32) -> Int32) -> Int32
strong_release %3 : $@callee_guaranteed (Int32) -> Int32
return %7 : $@callee_guaranteed () -> Int32
} // CHECK: Returns closure: target: closure3 captures
// CHECK: %3
// CHECK: values:
// CHECK: closure: target: closure2 captures
// CHECK: %1
// CHECK: values:
// CHECK: int: 991
sil private @closure4 : $@convention(thin) () -> Int64 {
bb0:
%0 = integer_literal $Builtin.Int64, 71
%1 = struct $Int64 (%0 : $Builtin.Int64)
return %1 : $Int64
}
// CHECK-LABEL: @interpretThinToThickFunction
sil @interpretThinToThickFunction: $@convention(thin) () -> @owned @callee_guaranteed () -> Int64 {
bb0:
%0 = function_ref @closure4 : $@convention(thin) () -> Int64
%3 = thin_to_thick_function %0 : $@convention(thin) () -> Int64 to $@callee_guaranteed () -> Int64
return %3 : $@callee_guaranteed () -> Int64
} // CHECK: Returns closure: target: closure4 captures
// CHECK-NEXT: values:
// Tests for checked cast instruction.
sil [ossa] @testMetatypeCast : $@convention(thin) <T> (@thick T.Type) -> Builtin.Int1 {
bb0(%0 : $@thick T.Type):
checked_cast_br T.Type in %0 : $@thick T.Type to Int64.Type, bb1, bb2
bb1(%3 : $@thick Int64.Type):
%4 = metatype $@thin Int64.Type
%5 = integer_literal $Builtin.Int1, -1
br bb3(%5 : $Builtin.Int1)
bb2(%7 : $@thick T.Type):
%8 = integer_literal $Builtin.Int1, 0
br bb3(%8 : $Builtin.Int1)
bb3(%10 : $Builtin.Int1):
return %10 : $Builtin.Int1
}
// CHECK-LABEL: @interpretMetatypeCast
sil [ossa] @interpretMetatypeCast : $@convention(thin) () -> Builtin.Int1 {
bb0:
%1 = metatype $@thick Int64.Type
%2 = function_ref @testMetatypeCast : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Builtin.Int1
%3 = apply %2<Int64>(%1) : $@convention(thin) <τ_0_0> (@thick τ_0_0.Type) -> Builtin.Int1
return %3 : $Builtin.Int1
} // CHECK: Returns int: -1
// CHECK-LABEL: @interpretBinaryIntegerDescription
sil [ossa] @interpretBinaryIntegerDescription : $@convention(thin) () -> @owned String {
bb0:
%0 = integer_literal $Builtin.Int64, -10
%1 = struct $Int64 (%0 : $Builtin.Int64)
%2 = alloc_stack $Int64
store %1 to [trivial] %2 : $*Int64
%4 = function_ref @binaryIntegerDescription : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String
%5 = apply %4<Int64>(%2) : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String
dealloc_stack %2 : $*Int64
return %5 : $String
} // CHECK: Returns string: "-10"
sil [_semantics "binaryInteger.description"] @binaryIntegerDescription : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String
// CHECK-LABEL: @interpretUnsignedBinaryIntegerDescription
sil [ossa] @interpretUnsignedBinaryIntegerDescription : $@convention(thin) () -> @owned String {
bb0:
%0 = integer_literal $Builtin.Int64, 0xffffffffffffffff
%1 = struct $UInt64 (%0 : $Builtin.Int64)
%2 = alloc_stack $UInt64
store %1 to [trivial] %2 : $*UInt64
%4 = function_ref @binaryIntegerDescription : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String
%5 = apply %4<UInt64>(%2) : $@convention(method) <τ_0_0 where τ_0_0 : BinaryInteger> (@in_guaranteed τ_0_0) -> @owned String
dealloc_stack %2 : $*UInt64
return %5 : $String
} // CHECK: Returns string: "18446744073709551615"
// CHECK-LABEL: @interpretTsanInstrumentationSkip
sil [ossa] @interpretTsanInstrumentationSkip : $@convention(thin) () -> Builtin.Int32 {
bb0:
%0 = integer_literal $Builtin.Int32, 23
%1 = alloc_stack $Builtin.Int32
store %0 to [trivial] %1 : $*Builtin.Int32
// This builtin should be skipped and should not affect the value of the argument
%2 = builtin "tsanInoutAccess"(%1 : $*Builtin.Int32) : $()
%3 = load [trivial] %1 : $*Builtin.Int32
dealloc_stack %1 : $*Builtin.Int32
return %3 : $Builtin.Int32
} // CHECK: Returns int: 23
// CHECK-LABEL: @interpretCoverageInstrumentationSkip
sil @interpretCoverageInstrumentationSkip : $@convention(thin) () -> Builtin.Int64 {
bb0:
%0 = integer_literal $Builtin.Int64, 25
// This builtin should be skipped
increment_profiler_counter 0, "$s2os6LoggerV3logyyAA12OSLogMessageVF", num_counters 1, hash 0
return %0 : $(Builtin.Int64)
} // CHECK: Returns int: 25