blob: db8221f14ad176d757442d269e5de2a3ac41d97c [file] [log] [blame]
// RUN: %target-sil-opt -address-lowering -enable-sil-opaque-values -emit-sorted-sil -new-mangling-for-tests -assume-parsing-unqualified-ownership-sil %s | %FileCheck %s
import Builtin
sil_stage canonical
// CHECK: sil_stage lowered
// CHECK-LABEL: sil hidden @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
// CHECK: bb0(%0 : $*T, %1 : $*T):
// CHECK: copy_addr [take] %1 to [initialization] %0 : $*T
// CHECK: return %{{.*}} : $()
// CHECK-LABEL: } // end sil function 'f010_addrlower_identity'
sil hidden @f010_addrlower_identity : $@convention(thin) <T> (@in T) -> @out T {
bb0(%0 : $T):
return %0 : $T
}
sil hidden [noinline] @f020_multiResult : $@convention(thin) <T> (@in T) -> (@out T, @out T, @out T) {
bb0(%0 : $T):
%2 = copy_value %0 : $T
%3 = copy_value %0 : $T
%4 = copy_value %0 : $T
destroy_value %0 : $T
%6 = tuple (%2 : $T, %3 : $T, %4 : $T)
return %6 : $(T, T, T)
}
// Test returning an opaque tuple of tuples as a concrete tuple.
// The multiResult call is specialized, but the SIL result convention does not change.
// ---
// CHECK-LABEL: sil @f021_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
// CHECK: bb0(%0 : $Builtin.Int64):
// CHECK: %[[FN:.*]] = function_ref @f020_multiResult : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
// CHECK: %[[IN:.*]] = alloc_stack $Builtin.Int64
// CHECK: store %0 to %[[IN]] : $*Builtin.Int64
// CHECK: %[[OUT1:.*]] = alloc_stack $Builtin.Int64
// CHECK: %[[OUT2:.*]] = alloc_stack $Builtin.Int64
// CHECK: %[[OUT3:.*]] = alloc_stack $Builtin.Int64
// CHECK: %{{.*}} = apply %[[FN]]<Builtin.Int64>(%[[OUT1]], %[[OUT2]], %[[OUT3]], %[[IN]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
// CHECK: %[[R3:.*]] = load %[[OUT3]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[OUT3]] : $*Builtin.Int64
// CHECK: %[[R2:.*]] = load %[[OUT2]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[OUT2]] : $*Builtin.Int64
// CHECK: %[[R1:.*]] = load %[[OUT1]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[OUT1]] : $*Builtin.Int64
// CHECK: dealloc_stack %[[IN]] : $*Builtin.Int64
// CHECK: %[[R:.*]] = tuple (%[[R1]] : $Builtin.Int64, %[[R2]] : $Builtin.Int64, %[[R3]] : $Builtin.Int64)
// CHECK: return %[[R]] : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
// CHECK-LABEL: } // end sil function 'f021_callMultiResult'
sil @f021_callMultiResult : $@convention(thin) (Builtin.Int64) -> (Builtin.Int64, Builtin.Int64, Builtin.Int64) {
bb0(%0 : $Builtin.Int64):
%1 = function_ref @f020_multiResult : $@convention(thin) _0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
%2 = apply %1<Builtin.Int64>(%0) : $@convention(thin) _0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0, @out τ_0_0)
%3 = tuple_extract %2 : $(Builtin.Int64, Builtin.Int64, Builtin.Int64), 0
%4 = tuple_extract %2 : $(Builtin.Int64, Builtin.Int64, Builtin.Int64), 1
%5 = tuple_extract %2 : $(Builtin.Int64, Builtin.Int64, Builtin.Int64), 2
%6 = tuple (%3 : $Builtin.Int64, %4 : $Builtin.Int64, %5 : $Builtin.Int64)
return %6 : $(Builtin.Int64, Builtin.Int64, Builtin.Int64)
}
// CHECK-LABEL: sil @f030_returnPair : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
// CHECK: %[[LOCAL:.*]] = alloc_stack $T
// CHECK: copy_addr %2 to [initialization] %[[LOCAL]] : $*T
// CHECK: copy_addr [take] %[[LOCAL]] to [initialization] %0 : $*T
// CHECK: copy_addr [take] %2 to [initialization] %1 : $*T
// CHECK: %[[R:.*]] = tuple ()
// CHECK: dealloc_stack %[[LOCAL]] : $*T
// CHECK: return %[[R]] : $()
// CHECK-LABEL: } // end sil function 'f030_returnPair'
sil @f030_returnPair : $@convention(thin) <T> (@in T) -> (@out T, @out T) {
bb0(%0 : $T):
%2 = copy_value %0 : $T
%3 = tuple (%2 : $T, %0 : $T)
return %3 : $(T, T)
}
// CHECK-LABEL: sil @f031_unusedIndirect : $@convention(thin) <T> (@in T) -> @out T {
// CHECK: bb0(%0 : $*T, %1 : $*T):
// CHECK: %[[LOC2:.*]] = alloc_stack $T
// CHECK: %[[OUT2:.*]] = alloc_stack $T
// CHECK: %[[LOC1:.*]] = alloc_stack $T
// CHECK: %[[OUT1:.*]] = alloc_stack $T
// CHECK: %[[LOC0:.*]] = alloc_stack $T
// CHECK: // function_ref f030_returnPair
// CHECK: %7 = function_ref @f030_returnPair : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
// CHECK: copy_addr %1 to [initialization] %[[LOC0]] : $*T
// CHECK: %[[IN:.*]] = alloc_stack $T
// CHECK: copy_addr [take] %[[LOC0]] to [initialization] %[[IN]] : $*T
// CHECK: %11 = apply %7<T>(%[[OUT1]], %[[OUT2]], %[[IN]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
// CHECK: dealloc_stack %[[IN]] : $*T
// CHECK: copy_addr %[[OUT1]] to [initialization] %[[LOC1]] : $*T
// CHECK: copy_addr %[[OUT2]] to [initialization] %[[LOC2]] : $*T
// CHECK: destroy_addr %[[OUT1]] : $*T
// CHECK: destroy_addr %[[OUT2]] : $*T
// CHECK: destroy_addr %[[LOC1]] : $*T
// CHECK: destroy_addr %1 : $*T
// CHECK: copy_addr [take] %[[LOC2]] to [initialization] %0 : $*T
// CHECK: %[[R:.*]] = tuple ()
// CHECK: dealloc_stack %[[LOC0]] : $*T
// CHECK: dealloc_stack %[[OUT1]] : $*T
// CHECK: dealloc_stack %[[LOC1]] : $*T
// CHECK: dealloc_stack %[[OUT2]] : $*T
// CHECK: dealloc_stack %[[LOC2]] : $*T
// CHECK: return %[[R]] : $()
// CHECK-LABEL: } // end sil function 'f031_unusedIndirect'
sil @f031_unusedIndirect : $@convention(thin) <T> (@in T) -> @out T {
bb0(%0 : $T):
%2 = function_ref @f030_returnPair : $@convention(thin) _0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
%3 = copy_value %0 : $T
%4 = apply %2<T>(%3) : $@convention(thin) _0_0> (@in τ_0_0) -> (@out τ_0_0, @out τ_0_0)
%5 = tuple_extract %4 : $(T, T), 0
%6 = copy_value %5 : $T
%7 = tuple_extract %4 : $(T, T), 1
%8 = copy_value %7 : $T
destroy_value %4 : $(T, T)
destroy_value %6 : $T
destroy_value %0 : $T
return %8 : $T
}
sil hidden @f040_consumeArg : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $T):
destroy_value %0 : $T
%3 = tuple ()
return %3 : $()
}
// CHECK-LABEL: sil @f041_opaqueArg : $@convention(thin) <T> (@in T) -> () {
// CHECK: bb0(%0 : $*T):
// CHECK: %[[LOC:.*]] = alloc_stack $T
// CHECK: %[[FN:.*]] = function_ref @f040_consumeArg : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
// CHECK: copy_addr %0 to [initialization] %[[LOC]] : $*T
// CHECK: %[[ARG:.*]] = alloc_stack $T
// CHECK: copy_addr [take] %[[LOC]] to [initialization] %[[ARG]] : $*T
// CHECK: %{{.*}} = apply %[[FN]]<T>(%[[ARG]]) : $@convention(thin) <τ_0_0> (@in τ_0_0) -> ()
// CHECK: dealloc_stack %[[ARG]] : $*T
// CHECK: destroy_addr %0 : $*T
// CHECK: %[[R:.*]] = tuple ()
// CHECK: dealloc_stack %[[LOC]] : $*T
// CHECK: return %[[R]] : $()
// CHECK-LABEL: } // end sil function 'f041_opaqueArg'
sil @f041_opaqueArg : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $T):
%2 = function_ref @f040_consumeArg : $@convention(thin) _0_0> (@in τ_0_0) -> ()
%3 = copy_value %0 : $T
%4 = apply %2<T>(%3) : $@convention(thin) _0_0> (@in τ_0_0) -> ()
destroy_value %0 : $T
%6 = tuple ()
return %6 : $()
}
// CHECK-LABEL: sil @f050_storeinout : $@convention(thin) <T> (@inout T, @inout T, @in T) -> () {
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T):
// CHECK: %[[PREV2:.*]] = alloc_stack $T
// CHECK: %[[ARG2:.*]] = alloc_stack $T
// CHECK: %[[PREV1:.*]] = alloc_stack $T
// CHECK: %[[ARG1:.*]] = alloc_stack $T
// CHECK: debug_value_addr %0 : $*T, var, name "t", argno 1
// CHECK: debug_value_addr %1 : $*T, var, name "u", argno 2
// CHECK: debug_value_addr %2 : $*T
// CHECK: copy_addr %2 to [initialization] %[[ARG1]] : $*T
// CHECK: copy_addr [take] %0 to [initialization] %[[PREV1]] : $*T
// CHECK: copy_addr [take] %[[ARG1]] to [initialization] %0 : $*T
// CHECK: destroy_addr %[[PREV1]] : $*T
// CHECK: copy_addr %2 to [initialization] %[[ARG2]] : $*T
// CHECK: copy_addr [take] %1 to [initialization] %[[PREV2]] : $*T
// CHECK: copy_addr [take] %[[ARG2]] to [initialization] %1 : $*T
// CHECK: destroy_addr %[[PREV2]] : $*T
// CHECK: destroy_addr %2 : $*T
// CHECK: %19 = tuple ()
// CHECK: dealloc_stack %[[ARG1]] : $*T
// CHECK: dealloc_stack %[[PREV1]] : $*T
// CHECK: dealloc_stack %[[ARG2]] : $*T
// CHECK: dealloc_stack %[[PREV2]] : $*T
// CHECK: return %19 : $()
// CHECK-LABEL: } // end sil function 'f050_storeinout'
sil @f050_storeinout : $@convention(thin) <T> (@inout T, @inout T, @in T) -> () {
bb0(%0 : $*T, %1 : $*T, %2 : $T):
debug_value_addr %0 : $*T, var, name "t", argno 1
debug_value_addr %1 : $*T, var, name "u", argno 2
debug_value %2 : $T, let, name "x", argno 3
%6 = copy_value %2 : $T
%7 = load %0 : $*T
store %6 to %0 : $*T
destroy_value %7 : $T
%10 = copy_value %2 : $T
%11 = load %1 : $*T
store %10 to %1 : $*T
destroy_value %11 : $T
destroy_value %2 : $T
%15 = tuple ()
return %15 : $()
}
sil hidden @f060_mutate : $@convention(thin) <T> (@inout T, @in T) -> () {
bb0(%0 : $*T, %1 : $T):
%4 = copy_value %1 : $T
%5 = load %0 : $*T
store %4 to %0 : $*T
destroy_value %5 : $T
destroy_value %1 : $T
%9 = tuple ()
return %9 : $()
}
// CHECK-LABEL: sil @f061_callinout : $@convention(thin) <T> (@in T) -> () {
// CHECK: bb0(%0 : $*T):
// CHECK: %[[LOC2:.*]] = alloc_stack $T
// CHECK: %[[LOC1:.*]] = alloc_stack $T
// CHECK: %[[INOUT:.*]] = alloc_stack $T, var, name "u"
// CHECK: copy_addr %0 to [initialization] %[[LOC1]] : $*T
// CHECK: copy_addr [take] %[[LOC1]] to [initialization] %[[INOUT]] : $*T
// CHECK: %[[FN:.*]] = function_ref @f060_mutate : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
// CHECK: copy_addr %0 to [initialization] %[[LOC2]] : $*T
// CHECK: %[[IN:.*]] = alloc_stack $T
// CHECK: copy_addr [take] %[[LOC2]] to [initialization] %[[IN]] : $*T
// CHECK: %{{.*}} = apply %[[FN]]<T>(%[[INOUT]], %[[IN]]) : $@convention(thin) <τ_0_0> (@inout τ_0_0, @in τ_0_0) -> ()
// CHECK: dealloc_stack %[[IN]] : $*T
// CHECK: destroy_addr %[[INOUT]] : $*T
// CHECK: destroy_addr %0 : $*T
// CHECK: %[[R:.*]] = tuple ()
// CHECK: dealloc_stack %[[INOUT]] : $*T
// CHECK: dealloc_stack %[[LOC1]] : $*T
// CHECK: dealloc_stack %[[LOC2]] : $*T
// CHECK: return %[[R]] : $()
// CHECK-LABEL: } // end sil function 'f061_callinout'
sil @f061_callinout : $@convention(thin) <T> (@in T) -> () {
bb0(%0 : $T):
%1 = alloc_stack $T, var, name "u"
%3 = copy_value %0 : $T
store %3 to %1 : $*T
%5 = function_ref @f060_mutate : $@convention(thin) _0_0> (@inout τ_0_0, @in τ_0_0) -> ()
%6 = copy_value %0 : $T
%7 = apply %5<T>(%1, %6) : $@convention(thin) _0_0> (@inout τ_0_0, @in τ_0_0) -> ()
destroy_addr %1 : $*T
destroy_value %0 : $T
%10 = tuple ()
dealloc_stack %1 : $*T
return %10 : $()
}
public protocol C : class {}
// CHECK-LABEL: sil @f070_mixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $C):
// CHECK: copy_addr [take] %1 to [initialization] %0 : $*T
// CHECK: return %2 : $C
// CHECK-LABEL: } // end sil function 'f070_mixedResult1'
sil @f070_mixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
bb0(%0 : $T, %1 : $C):
%4 = tuple (%0 : $T, %1 : $C)
return %4 : $(T, C)
}
// CHECK-LABEL: sil @f071_mixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : $C):
// CHECK: %[[L:.*]] = alloc_stack $T
// CHECK: copy_addr %2 to [initialization] %[[L]] : $*T
// CHECK: strong_retain %3 : $C
// CHECK: copy_addr [take] %[[L]] to [initialization] %0 : $*T
// CHECK: copy_addr [take] %2 to [initialization] %1 : $*T
// CHECK: %[[T:.*]] = tuple (%3 : $C, %3 : $C)
// CHECK: dealloc_stack %[[L]] : $*T
// CHECK: return %[[T]] : $(C, C)
// CHECK-LABEL: } // end sil function 'f071_mixedResult2'
sil @f071_mixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
bb0(%0 : $T, %1 : $C):
%4 = copy_value %0 : $T
strong_retain %1 : $C
%6 = tuple (%4 : $T, %0 : $T, %1 : $C, %1 : $C)
return %6 : $(T, T, C, C)
}
// CHECK-LABEL: sil @f072_callMixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $C):
// CHECK: %[[LOUT:.*]] = alloc_stack $T
// CHECK: %[[OUT:.*]] = alloc_stack $T
// CHECK: %[[LIN:.*]] = alloc_stack $T
// CHECK: // function_ref f070_mixedResult1
// CHECK: %[[F:.*]] = function_ref @f070_mixedResult1 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
// CHECK: copy_addr %1 to [initialization] %[[LIN]] : $*T
// CHECK: strong_retain %2 : $C
// CHECK: %[[IN:.*]] = alloc_stack $T
// CHECK: copy_addr [take] %[[LIN]] to [initialization] %[[IN]] : $*T
// CHECK: %11 = apply %[[F]]<T>(%[[OUT]], %[[IN]], %2) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
// CHECK: dealloc_stack %[[IN]] : $*T
// CHECK: copy_addr %[[OUT]] to [initialization] %[[LOUT]] : $*T
// CHECK: strong_retain %11 : $C
// CHECK: destroy_addr %[[OUT]] : $*T
// CHECK: strong_release %11 : $C
// CHECK: strong_release %2 : $C
// CHECK: destroy_addr %1 : $*T
// CHECK: copy_addr [take] %[[LOUT]] to [initialization] %0 : $*T
// CHECK: dealloc_stack %[[LIN]] : $*T
// CHECK: dealloc_stack %[[OUT]] : $*T
// CHECK: dealloc_stack %[[LOUT]] : $*T
// CHECK: return %11 : $C
// CHECK-LABEL: } // end sil function 'f072_callMixedResult1'
sil @f072_callMixedResult1 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @owned C) {
bb0(%0 : $T, %1 : $C):
%4 = function_ref @f070_mixedResult1 : $@convention(thin) _0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
%5 = copy_value %0 : $T
strong_retain %1 : $C
%7 = apply %4<T>(%5, %1) : $@convention(thin) _0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @owned C)
%8 = tuple_extract %7 : $(T, C), 0
%9 = copy_value %8 : $T
%10 = tuple_extract %7 : $(T, C), 1
strong_retain %10 : $C
destroy_value %7 : $(T, C)
strong_release %1 : $C
destroy_value %0 : $T
%15 = tuple (%9 : $T, %10 : $C)
return %15 : $(T, C)
}
// CHECK-LABEL: sil @f073_callMixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
// CHECK: bb0(%0 : $*T, %1 : $*T, %2 : $*T, %3 : $C):
// CHECK: %[[LOC2:.*]] = alloc_stack $T
// CHECK: %[[OUT2:.*]] = alloc_stack $T
// CHECK: %[[LOC1:.*]] = alloc_stack $T
// CHECK: %[[OUT1:.*]] = alloc_stack $T
// CHECK: %[[LOC0:.*]] = alloc_stack $T
// CHECK: %[[F:.*]] = function_ref @f071_mixedResult2 : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
// CHECK: copy_addr %2 to [initialization] %[[LOC0]] : $*T
// CHECK: strong_retain %3 : $C
// CHECK: %[[IN:.*]] = alloc_stack $T
// CHECK: copy_addr [take] %[[LOC0]] to [initialization] %[[IN]] : $*T
// CHECK: %[[R:.*]] = apply %[[F]]<T>(%[[OUT1]], %[[OUT2]], %[[IN]], %3) : $@convention(thin) <τ_0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
// CHECK: %[[T2:.*]] = tuple_extract %[[R]] : $(C, C), 1
// CHECK: %[[T1:.*]] = tuple_extract %[[R]] : $(C, C), 0
// CHECK: dealloc_stack %[[IN]] : $*T
// CHECK: copy_addr %[[OUT1]] to [initialization] %[[LOC1]] : $*T
// CHECK: copy_addr %[[OUT2]] to [initialization] %[[LOC2]] : $*T
// CHECK: strong_retain %[[T1]] : $C
// CHECK: strong_retain %[[T2]] : $C
// CHECK: destroy_addr %[[OUT1]] : $*T
// CHECK: destroy_addr %[[OUT2]] : $*T
// CHECK: strong_release %[[T1]] : $C
// CHECK: strong_release %[[T2]] : $C
// CHECK: strong_release %3 : $C
// CHECK: destroy_addr %2 : $*T
// CHECK: copy_addr [take] %[[LOC1]] to [initialization] %0 : $*T
// CHECK: copy_addr [take] %[[LOC2]] to [initialization] %1 : $*T
// CHECK: %[[T:.*]] = tuple (%[[T1]] : $C, %[[T2]] : $C)
// CHECK: dealloc_stack %[[LOC0]] : $*T
// CHECK: dealloc_stack %[[OUT1]] : $*T
// CHECK: dealloc_stack %[[LOC1]] : $*T
// CHECK: dealloc_stack %[[OUT2]] : $*T
// CHECK: dealloc_stack %[[LOC2]] : $*T
// CHECK: return %[[T]] : $(C, C)
// CHECK-LABEL: } // end sil function 'f073_callMixedResult2'
sil @f073_callMixedResult2 : $@convention(thin) <T> (@in T, @owned C) -> (@out T, @out T, @owned C, @owned C) {
bb0(%0 : $T, %1 : $C):
%4 = function_ref @f071_mixedResult2 : $@convention(thin) _0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
%5 = copy_value %0 : $T
strong_retain %1 : $C
%7 = apply %4<T>(%5, %1) : $@convention(thin) _0_0> (@in τ_0_0, @owned C) -> (@out τ_0_0, @out τ_0_0, @owned C, @owned C)
%8 = tuple_extract %7 : $(T, T, C, C), 0
%9 = copy_value %8 : $T
%10 = tuple_extract %7 : $(T, T, C, C), 1
%11 = copy_value %10 : $T
%12 = tuple_extract %7 : $(T, T, C, C), 2
strong_retain %12 : $C
%14 = tuple_extract %7 : $(T, T, C, C), 3
strong_retain %14 : $C
destroy_value %7 : $(T, T, C, C)
strong_release %1 : $C
destroy_value %0 : $T
%19 = tuple (%9 : $T, %11 : $T, %12 : $C, %14 : $C)
return %19 : $(T, T, C, C)
}
sil_default_witness_table C {}