mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
1079 lines
44 KiB
Plaintext
1079 lines
44 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: @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: 512 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 a function 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%%"
|