| // RUN: %target-sil-opt -enable-sil-verify-all %s -global-opt | %FileCheck %s |
| sil_stage canonical |
| |
| import Builtin |
| import Swift |
| import SwiftShims |
| |
| public struct TStruct { |
| let x: Int32 |
| init(x: Int32) |
| } |
| |
| let trivialglobal: TStruct |
| |
| public class TClass { |
| final let x: Int32 |
| init(x: Int32) |
| deinit |
| } |
| |
| let nontrivialglobal: TClass |
| |
| // CHECK-LABEL: sil_global hidden [let] @$trivialglobal : $TStruct = { |
| // CHECK: [[CONST:%.*]] = integer_literal $Builtin.Int32, 10 |
| // CHECK: [[INT:%.*]] = struct $Int32 ([[CONST]] : $Builtin.Int32) |
| // CHECK: %initval = struct $TStruct ([[INT]] : $Int32) |
| sil_global private @globalinit_trivialglobal_token : $Builtin.Word |
| |
| sil_global hidden [let] @$trivialglobal : $TStruct |
| |
| sil_global private @globalinit_nontrivialglobal_token : $Builtin.Word |
| |
| sil_global hidden [let] @$nontrivialglobal : $TClass |
| |
| sil private [global_init_once_fn] [ossa] @globalinit_trivialglobal_func : $@convention(c) () -> () { |
| bb0: |
| alloc_global @$trivialglobal |
| %1 = global_addr @$trivialglobal : $*TStruct |
| %2 = integer_literal $Builtin.Int32, 10 |
| %3 = struct $Int32 (%2 : $Builtin.Int32) |
| %4 = struct $TStruct (%3 : $Int32) |
| store %4 to [trivial] %1 : $*TStruct |
| %6 = tuple () |
| return %6 : $() |
| } |
| |
| // CHECK-LABEL: sil hidden [global_init] [ossa] @$trivialglobal_unsafemutableaddressor : |
| // CHECK: [[GLOBL:%.*]] = global_addr @$trivialglobal : $*TStruct |
| // CHECK: [[GLOBL_ADDR:%.*]] = address_to_pointer [[GLOBL]] : $*TStruct to $Builtin.RawPointer |
| // CHECK: return [[GLOBL_ADDR]] : $Builtin.RawPointer |
| // CHECK: } // end sil function '$trivialglobal_unsafemutableaddressor' |
| sil hidden [global_init] [ossa] @$trivialglobal_unsafemutableaddressor : $@convention(thin) () -> Builtin.RawPointer { |
| bb0: |
| %0 = global_addr @globalinit_trivialglobal_token : $*Builtin.Word |
| %1 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer |
| %2 = function_ref @globalinit_trivialglobal_func : $@convention(c) () -> () |
| %3 = builtin "once"(%1 : $Builtin.RawPointer, %2 : $@convention(c) () -> ()) : $() |
| %4 = global_addr @$trivialglobal : $*TStruct |
| %5 = address_to_pointer %4 : $*TStruct to $Builtin.RawPointer |
| return %5 : $Builtin.RawPointer |
| } |
| |
| // CHECK-LABEL: sil hidden [noinline] [ossa] @$bartrivial : |
| // CHECK: [[CONST:%.*]] = integer_literal $Builtin.Int32, 10 |
| // CHECK: [[INT:%.*]] = struct $Int32 ([[CONST]] : $Builtin.Int32) |
| // CHECK: return [[INT]] : $Int32 |
| // CHECK-LABEL: } // end sil function '$bartrivial' |
| sil hidden [noinline] [ossa] @$bartrivial : $@convention(thin) () -> Int32 { |
| bb0: |
| %0 = function_ref @$trivialglobal_unsafemutableaddressor : $@convention(thin) () -> Builtin.RawPointer |
| %1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer |
| %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*TStruct |
| %3 = struct_element_addr %2 : $*TStruct, #TStruct.x |
| %4 = load [trivial] %3 : $*Int32 |
| return %4 : $Int32 |
| } |
| |
| // CHECK-LABEL: sil private [global_init_once_fn] [ossa] @globalinit_nontrivialglobal_func : |
| // CHECK: alloc_global @$nontrivialglobal |
| // CHECK: [[GLOBL_ADDR:%.*]] = global_addr @$nontrivialglobal : $*TClass |
| // CHECK: [[REF:%.*]] = alloc_ref $TClass |
| // CHECK: store [[REF]] to [init] [[GLOBL_ADDR]] : $*TClass |
| // CHECK: } // end sil function 'globalinit_nontrivialglobal_func' |
| sil private [global_init_once_fn] [ossa] @globalinit_nontrivialglobal_func : $@convention(c) () -> () { |
| bb0: |
| alloc_global @$nontrivialglobal |
| %1 = global_addr @$nontrivialglobal : $*TClass |
| %2 = integer_literal $Builtin.Int32, 10 |
| %3 = struct $Int32 (%2 : $Builtin.Int32) |
| %4 = alloc_ref $TClass |
| %5 = begin_borrow %4 : $TClass |
| %6 = ref_element_addr %5 : $TClass, #TClass.x |
| store %3 to [trivial] %6 : $*Int32 |
| end_borrow %5 : $TClass |
| store %4 to [init] %1 : $*TClass |
| %10 = tuple () |
| return %10 : $() |
| } |
| |
| sil hidden [global_init] [ossa] @$nontrivialglobal_unsafemutableaccessor : $@convention(thin) () -> Builtin.RawPointer { |
| bb0: |
| %0 = global_addr @globalinit_nontrivialglobal_token : $*Builtin.Word |
| %1 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer |
| %2 = function_ref @globalinit_nontrivialglobal_func : $@convention(c) () -> () |
| %3 = builtin "once"(%1 : $Builtin.RawPointer, %2 : $@convention(c) () -> ()) : $() |
| %4 = global_addr @$nontrivialglobal : $*TClass |
| %5 = address_to_pointer %4 : $*TClass to $Builtin.RawPointer |
| return %5 : $Builtin.RawPointer |
| } |
| |
| // CHECK-LABEL: sil hidden [noinline] [ossa] @$barnontrivial : |
| // CHECK: [[FUNC_REF:%.*]] = function_ref @$nontrivialglobal_unsafemutableaccessor : |
| // CHECK: [[APPLY:%.*]] = apply [[FUNC_REF]]() : |
| // CHECK-LABEL: } // end sil function '$barnontrivial' |
| sil hidden [noinline] [ossa] @$barnontrivial : $@convention(thin) () -> Int32 { |
| bb0: |
| %0 = function_ref @$nontrivialglobal_unsafemutableaccessor : $@convention(thin) () -> Builtin.RawPointer |
| %1 = apply %0() : $@convention(thin) () -> Builtin.RawPointer |
| %2 = pointer_to_address %1 : $Builtin.RawPointer to [strict] $*TClass |
| %3 = load [copy] %2 : $*TClass |
| %3b = begin_borrow %3 : $TClass |
| %4 = ref_element_addr %3b : $TClass, #TClass.x |
| %5 = load [trivial] %4 : $*Int32 |
| end_borrow %3b : $TClass |
| destroy_value %3 : $TClass |
| return %5 : $Int32 |
| } |
| |