@@ -247,6 +247,10 @@ private static void EmitNoArgsMethodCallPopReturn(
247247 private  TypeBuilder  runnableBuilder ; 
248248 private  ConsumableTypeInfo  consumableInfo ; 
249249 private  ConsumeEmitter  consumeEmitter ; 
250+  private  ConsumableTypeInfo  globalSetupReturnInfo ; 
251+  private  ConsumableTypeInfo  globalCleanupReturnInfo ; 
252+  private  ConsumableTypeInfo  iterationSetupReturnInfo ; 
253+  private  ConsumableTypeInfo  iterationCleanupReturnInfo ; 
250254
251255 private  FieldBuilder  globalSetupActionField ; 
252256 private  FieldBuilder  globalCleanupActionField ; 
@@ -358,13 +362,22 @@ private void InitForEmitRunnable(BenchmarkBuildInfo newBenchmark)
358362
359363 consumableInfo  =  new  ConsumableTypeInfo ( benchmark . BenchmarkCase . Descriptor . WorkloadMethod . ReturnType ) ; 
360364 consumeEmitter  =  ConsumeEmitter . GetConsumeEmitter ( consumableInfo ) ; 
365+  globalSetupReturnInfo  =  GetConsumableTypeInfo ( benchmark . BenchmarkCase . Descriptor . GlobalSetupMethod ? . ReturnType ) ; 
366+  globalCleanupReturnInfo  =  GetConsumableTypeInfo ( benchmark . BenchmarkCase . Descriptor . GlobalCleanupMethod ? . ReturnType ) ; 
367+  iterationSetupReturnInfo  =  GetConsumableTypeInfo ( benchmark . BenchmarkCase . Descriptor . IterationSetupMethod ? . ReturnType ) ; 
368+  iterationCleanupReturnInfo  =  GetConsumableTypeInfo ( benchmark . BenchmarkCase . Descriptor . IterationCleanupMethod ? . ReturnType ) ; 
361369
362370 // Init types 
363371 runnableBuilder  =  DefineRunnableTypeBuilder ( benchmark ,  moduleBuilder ) ; 
364372 overheadDelegateType  =  EmitOverheadDelegateType ( ) ; 
365373 workloadDelegateType  =  EmitWorkloadDelegateType ( ) ; 
366374 } 
367375
376+  private  static ConsumableTypeInfo  GetConsumableTypeInfo ( Type  methodReturnType ) 
377+  { 
378+  return  methodReturnType  ==  null  ?  null  :  new  ConsumableTypeInfo ( methodReturnType ) ; 
379+  } 
380+ 
368381 private  Type  EmitOverheadDelegateType ( ) 
369382 { 
370383 // .class public auto ansi sealed BenchmarkDotNet.Autogenerated.Runnable_0OverheadDelegate 
@@ -890,34 +903,84 @@ private void EmitSetupCleanupMethods()
890903 { 
891904 // Emit Setup/Cleanup methods 
892905 // We emit empty method instead of EmptyAction = "() => { }" 
893-  globalSetupMethod  =  EmitWrapperMethod ( 
894-  GlobalSetupMethodName , 
895-  Descriptor . GlobalSetupMethod ) ; 
896-  globalCleanupMethod  =  EmitWrapperMethod ( 
897-  GlobalCleanupMethodName , 
898-  Descriptor . GlobalCleanupMethod ) ; 
899-  iterationSetupMethod  =  EmitWrapperMethod ( 
900-  IterationSetupMethodName , 
901-  Descriptor . IterationSetupMethod ) ; 
902-  iterationCleanupMethod  =  EmitWrapperMethod ( 
903-  IterationCleanupMethodName , 
904-  Descriptor . IterationCleanupMethod ) ; 
906+  globalSetupMethod  =  EmitWrapperMethod ( GlobalSetupMethodName ,  Descriptor . GlobalSetupMethod ,  globalSetupReturnInfo ) ; 
907+  globalCleanupMethod  =  EmitWrapperMethod ( GlobalCleanupMethodName ,  Descriptor . GlobalCleanupMethod ,  globalCleanupReturnInfo ) ; 
908+  iterationSetupMethod  =  EmitWrapperMethod ( IterationSetupMethodName ,  Descriptor . IterationSetupMethod ,  iterationSetupReturnInfo ) ; 
909+  iterationCleanupMethod  =  EmitWrapperMethod ( IterationCleanupMethodName ,  Descriptor . IterationCleanupMethod ,  iterationCleanupReturnInfo ) ; 
905910 } 
906911
907-  private  MethodBuilder  EmitWrapperMethod ( string  methodName ,  MethodInfo  optionalTargetMethod ) 
912+  private  MethodBuilder  EmitWrapperMethod ( string  methodName ,  MethodInfo  optionalTargetMethod ,   ConsumableTypeInfo   returnTypeInfo ) 
908913 { 
909914 var  methodBuilder  =  runnableBuilder . DefinePrivateVoidInstanceMethod ( methodName ) ; 
910915
911916 var  ilBuilder  =  methodBuilder . GetILGenerator ( ) ; 
912917
913918 if  ( optionalTargetMethod  !=  null ) 
914-  EmitNoArgsMethodCallPopReturn ( methodBuilder ,  optionalTargetMethod ,  ilBuilder ,  forceDirectCall :  true ) ; 
919+  { 
920+  if  ( returnTypeInfo ? . IsAwaitable  ==  true ) 
921+  { 
922+  EmitAwaitableSetupTeardown ( methodBuilder ,  optionalTargetMethod ,  ilBuilder ,  returnTypeInfo ) ; 
923+  } 
924+  else 
925+  { 
926+  EmitNoArgsMethodCallPopReturn ( methodBuilder ,  optionalTargetMethod ,  ilBuilder ,  forceDirectCall :  true ) ; 
927+  } 
928+  } 
915929
916930 ilBuilder . EmitVoidReturn ( methodBuilder ) ; 
917931
918932 return  methodBuilder ; 
919933 } 
920934
935+  private  void  EmitAwaitableSetupTeardown ( 
936+  MethodBuilder  methodBuilder , 
937+  MethodInfo  targetMethod , 
938+  ILGenerator  ilBuilder , 
939+  ConsumableTypeInfo  returnTypeInfo ) 
940+  { 
941+  if  ( targetMethod  ==  null ) 
942+  throw  new  ArgumentNullException ( nameof ( targetMethod ) ) ; 
943+ 
944+  if  ( returnTypeInfo . WorkloadMethodReturnType  ==  typeof ( void ) ) 
945+  { 
946+  ilBuilder . Emit ( OpCodes . Ldarg_0 ) ; 
947+  } 
948+  /* 
949+  // call for instance 
950+  // GlobalSetup(); 
951+  IL_0006: ldarg.0 
952+  IL_0007: call instance void [BenchmarkDotNet]BenchmarkDotNet.Samples.SampleBenchmark::GlobalSetup() 
953+  */ 
954+  /* 
955+  // call for static 
956+  // GlobalSetup(); 
957+  IL_0006: call string [BenchmarkDotNet]BenchmarkDotNet.Samples.SampleBenchmark::GlobalCleanup() 
958+  */ 
959+  if  ( targetMethod . IsStatic ) 
960+  { 
961+  ilBuilder . Emit ( OpCodes . Call ,  targetMethod ) ; 
962+ 
963+  } 
964+  else  if  ( methodBuilder . IsStatic ) 
965+  { 
966+  throw  new  InvalidOperationException ( 
967+  $ "[BUG] Static method { methodBuilder . Name }  tries to call instance member { targetMethod . Name } ") ; 
968+  } 
969+  else 
970+  { 
971+  ilBuilder . Emit ( OpCodes . Ldarg_0 ) ; 
972+  ilBuilder . Emit ( OpCodes . Call ,  targetMethod ) ; 
973+  } 
974+ 
975+  /* 
976+  // BenchmarkDotNet.Helpers.AwaitHelper.GetResult(...); 
977+  IL_000e: call !!0 BenchmarkDotNet.Helpers.AwaitHelper::GetResult<int32>(valuetype [System.Runtime]System.Threading.Tasks.ValueTask`1<!!0>) 
978+  */ 
979+ 
980+  ilBuilder . Emit ( OpCodes . Call ,  returnTypeInfo . GetResultMethod ) ; 
981+  ilBuilder . Emit ( OpCodes . Pop ) ; 
982+  } 
983+ 
921984 private  void  EmitCtorBody ( ) 
922985 { 
923986 var  ilBuilder  =  ctorMethod . GetILGenerator ( ) ; 
0 commit comments