From 783c82501a887a8a7d986c922dd452d7bd393f71 Mon Sep 17 00:00:00 2001 From: Mark Hammons Date: Thu, 23 Mar 2023 18:53:26 +0100 Subject: [PATCH 1/2] Make C library bindings support allocating returns. Fixes #106 --- .../slinc/BindingsBenchmarkShape.scala | 12 + .../slinc/CFunctionBindingGenerator.scala | 237 ++++++++---------- core/test/src/fr/hammons/slinc/LibSpec.scala | 12 + .../hammons/slinc/modules/LibModule17.scala | 48 ++-- .../hammons/slinc/modules/LibModule19.scala | 39 ++- 5 files changed, 183 insertions(+), 165 deletions(-) diff --git a/core/benchmarks/test/src/fr/hammons/slinc/BindingsBenchmarkShape.scala b/core/benchmarks/test/src/fr/hammons/slinc/BindingsBenchmarkShape.scala index 90ed4985..abb0019e 100644 --- a/core/benchmarks/test/src/fr/hammons/slinc/BindingsBenchmarkShape.scala +++ b/core/benchmarks/test/src/fr/hammons/slinc/BindingsBenchmarkShape.scala @@ -5,6 +5,7 @@ import java.util.concurrent.TimeUnit import scala.util.Random import scala.annotation.nowarn import fr.hammons.slinc.modules.LibModule +import org.openjdk.jmh.infra.Blackhole case class div_t(quot: Int, rem: Int) @@ -61,6 +62,17 @@ trait BindingsBenchmarkShape(val s: Slinc): ) } + val path = Random.nextBoolean() + + @Benchmark + def ifmark(blackhole: Blackhole) = + if path then blackhole.consume(1 + 2) + else blackhole.consume(2 + 3) + + @Benchmark + def noifmark(blackhole: Blackhole) = + blackhole.consume(1 + 2) + @Benchmark def abs = Cstd.abs(6) diff --git a/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala b/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala index 4512d848..d621080b 100644 --- a/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala +++ b/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala @@ -3,51 +3,59 @@ package fr.hammons.slinc import java.lang.invoke.MethodHandle import scala.quoted.* import scala.annotation.nowarn +import fr.hammons.slinc.modules.TransitionModule type InputTransition = (Allocator, Any) => Any type OutputTransition = (Object | Null) => AnyRef -type VariadicInputTransition = (TypeDescriptor, Allocator, Any) => Any trait CFunctionBindingGenerator: def generate( methodHandler: MethodHandler, inputTransitions: IArray[InputTransition], + variadicTransition: TransitionModule, outputTransition: OutputTransition, - scope: Scope - ): AnyRef - - def generateVariadic( - methodHandler: MethodHandler, - inputTransitions: IArray[InputTransition], - variadicTransition: VariadicInputTransition, - outputTransition: OutputTransition, - scope: Scope + scope: Scope, + allocatingReturn: Boolean, + variadic: Boolean ): AnyRef object CFunctionBindingGenerator: + private case class LambdaInputs( + normalArgs: List[Expr[Any]], + varArgs: Option[Expr[Seq[Variadic]]] + ) + private def getVariadicExprs( s: Seq[Variadic], - variadicTransition: VariadicInputTransition, + variadicTransition: TransitionModule, allocator: Allocator ): Seq[Any] = s.map: vararg => vararg.use[DescriptorOf](dc ?=> - d => variadicTransition(dc.descriptor, allocator, d) + d => variadicTransition.methodArgument(dc.descriptor, d, allocator) ) - @nowarn("msg=unused implicit parameter") - private def invokeVariadicArguments( - mhGen: Expr[Seq[Variadic] => MethodHandle], - inputs: Expr[Seq[Any]], - varArgs: Expr[Seq[Variadic]], - variadicTransition: Expr[VariadicInputTransition], - alloc: Expr[Allocator] + private def invokation( + vTransition: Expr[TransitionModule], + mh: Expr[MethodHandler] )(using Quotes) = - '{ - MethodHandleFacade.callVariadic( - $mhGen($varArgs), - $inputs ++ getVariadicExprs($varArgs, $variadicTransition, $alloc)* - ) - } + (alloc: Expr[Allocator], args: LambdaInputs) => + args.varArgs match + case None => + MethodHandleTools.invokeArguments( + '{ $mh.nonVariadic }, + args.normalArgs + ) + case Some(varArgs) => + '{ + MethodHandleFacade.callVariadic( + $mh.variadic($varArgs), + ${ Expr.ofList(args.normalArgs) } ++ getVariadicExprs( + $varArgs, + $vTransition, + $alloc + )* + ) + } inline def apply[L]( name: String @@ -55,6 +63,57 @@ object CFunctionBindingGenerator: applyImpl[L]('name) } + private def lambda2( + argNumbers: Int, + scope: Expr[Scope], + inputTransitions: Expr[IArray[InputTransition]], + outputTransition: Expr[OutputTransition], + allocatingReturn: Boolean, + varArg: Boolean + )( + invocationExpr: Quotes ?=> ( + Expr[Allocator], + LambdaInputs + ) => Expr[Object | Null] + )(using Quotes) = + import quotes.reflect.* + + val names = List.fill(argNumbers)("a") + val argTypes = + if varArg then + List.fill(argNumbers - 1)(TypeRepr.of[Object]) :+ TypeRepr + .of[Seq[Variadic]] + else List.fill(argNumbers)(TypeRepr.of[Object]) + + val methodType = + MethodType(names)(_ => argTypes, _ => TypeRepr.of[Object]) + + Lambda( + Symbol.spliceOwner, + methodType, + (sym, inputs) => + def inputExprs(alloc: Expr[Allocator])(using q: Quotes) = + val prefix = if allocatingReturn then List(alloc.asTerm) else Nil + val toTransform = if varArg then inputs.init else inputs + LambdaInputs( + prefix + .concat(toTransform) + .map(_.asExpr) + .zipWithIndex + .map: (exp, i) => + '{ $inputTransitions(${ Expr(i) })($alloc, $exp) }, + Option.unless(!varArg)(inputs.last.asExprOf[Seq[Variadic]]) + ) + + '{ + $scope { alloc ?=> + $outputTransition( + ${ invocationExpr('alloc, inputExprs('alloc)) } + ) + } + }.asTerm.changeOwner(sym) + ).asExprOf[AnyRef] + @nowarn("msg=unused implicit parameter") private def applyImpl[L](name: Expr[String])(using Quotes, @@ -69,124 +128,32 @@ object CFunctionBindingGenerator: .declaredMethod(name.valueOrAbort) .head - val argNumbers = methodSymbol.paramSymss.map(_.size).sum - val names = List.fill(argNumbers)("a") - - def lambda( - methodHandle: Expr[MethodHandle], - inputTransitions: Expr[IArray[InputTransition]], - outputTransition: Expr[OutputTransition], - scope: Expr[Scope] - )(using Quotes): Expr[AnyRef] = - import quotes.reflect.* - - val argsTypes = List.fill(argNumbers)(TypeRepr.of[Object]) - - val methodType = - MethodType(names)(_ => argsTypes, _ => TypeRepr.of[Object]) - Lambda( - Symbol.spliceOwner, - methodType, - (sym, inputs) => - def inputExprs(using q: Quotes) = (alloc: Expr[Allocator]) => - inputs - .map(i => i.asExpr) - .zipWithIndex - .map((exp, i) => - '{ $inputTransitions(${ Expr(i) })($alloc, $exp) } - ) - '{ - $scope { alloc ?=> - $outputTransition( - ${ - MethodHandleTools.invokeArguments( - methodHandle, - inputExprs('alloc) - ) - } - ) - } - }.asTerm.changeOwner(sym) - ).asExprOf[AnyRef] - - def lambdaVariadic( - methodHandleGen: Expr[Seq[Variadic] => MethodHandle], - inputTransitions: Expr[IArray[InputTransition]], - outputTransition: Expr[OutputTransition], - variadicTransition: Expr[ - VariadicInputTransition - ], - scope: Expr[Scope] - )(using Quotes): Expr[AnyRef] = - import quotes.reflect.* - - val argTypes = List.fill(argNumbers - 1)(TypeRepr.of[Object]) :+ TypeRepr - .of[Seq[Variadic]] - - val methodType = - MethodType(names)(_ => argTypes, _ => TypeRepr.of[Object]) - - Lambda( - Symbol.spliceOwner, - methodType, - (sym, inputs) => - def inputExprs(using q: Quotes) = (alloc: Expr[Allocator]) => - Expr.ofList( - inputs.init - .map(i => i.asExpr) - .zipWithIndex - .map((exp, i) => - '{ $inputTransitions(${ Expr(i) })($alloc, $exp) } - ) - ) - - '{ - $scope { alloc ?=> - $outputTransition( - ${ - invokeVariadicArguments( - methodHandleGen, - inputExprs('alloc), - inputs.last.asExprOf[Seq[Variadic]], - variadicTransition, - '{ alloc } - ) - } - ) - } - }.asTerm.changeOwner(sym) - ).asExprOf[AnyRef] - '{ new CFunctionBindingGenerator: def generate( methodHandler: MethodHandler, inputTransitions: IArray[InputTransition], + variadicTransition: TransitionModule, outputTransition: OutputTransition, - scope: Scope - ): AnyRef = - ${ - lambda( - '{ methodHandler.nonVariadic }, + scope: Scope, + allocatingReturn: Boolean, + variadic: Boolean + ): AnyRef = ${ + val lamdaGen = (allocatingReturn: Boolean, variadic: Boolean) => + lambda2( + methodSymbol.paramSymss.map(_.size).sum, + 'scope, 'inputTransitions, 'outputTransition, - 'scope - ) - } + allocatingReturn, + variadic + )(invokation('variadicTransition, 'methodHandler)) - def generateVariadic( - methodHandler: MethodHandler, - inputTransitions: IArray[InputTransition], - variadicTransitions: VariadicInputTransition, - outputTransition: OutputTransition, - scope: Scope - ): AnyRef = ${ - lambdaVariadic( - '{ methodHandler.variadic }, - 'inputTransitions, - 'outputTransition, - 'variadicTransitions, - 'scope - ) + '{ + if allocatingReturn && variadic then ${ lamdaGen(true, true) } + else if allocatingReturn then ${ lamdaGen(true, false) } + else if variadic then ${ lamdaGen(false, true) } + else ${ lamdaGen(false, false) } + } } } diff --git a/core/test/src/fr/hammons/slinc/LibSpec.scala b/core/test/src/fr/hammons/slinc/LibSpec.scala index 62a2c011..3f15de25 100644 --- a/core/test/src/fr/hammons/slinc/LibSpec.scala +++ b/core/test/src/fr/hammons/slinc/LibSpec.scala @@ -68,6 +68,18 @@ trait LibSpec(val slinc: Slinc) extends ScalaCheckSuite { } } + test("allocating returns") { + import slinc.given + case class div_t(quot: Int, rem: Int) derives Struct + + trait AllocatingLib derives Lib: + def div(i: Int, r: Int): div_t + + val allocatingLib = Lib.instance[AllocatingLib] + + assertEquals(allocatingLib.div(5, 2), div_t(2, 1)) + } + test("platform dependent types") { val maybeError = compileErrors(""" trait PlatformLib derives Lib: diff --git a/j17/src/fr/hammons/slinc/modules/LibModule17.scala b/j17/src/fr/hammons/slinc/modules/LibModule17.scala index e3367b65..c8f5d5f5 100644 --- a/j17/src/fr/hammons/slinc/modules/LibModule17.scala +++ b/j17/src/fr/hammons/slinc/modules/LibModule17.scala @@ -8,6 +8,8 @@ import fr.hammons.slinc.OutputTransition import fr.hammons.slinc.CFunctionDescriptor import fr.hammons.slinc.MethodHandler import fr.hammons.slinc.Variadic +import fr.hammons.slinc.AliasDescriptor +import fr.hammons.slinc.StructDescriptor given libraryModule17: LibModule with val runtimeVersion = 17 @@ -25,14 +27,28 @@ given libraryModule17: LibModule with val mh: MethodHandler = MethodHandler((v: Seq[Variadic]) => getDowncall(cfd, v).bindTo(addr).nn ) - // getDowncall(cfd).bindTo(addr).nn - val transitions = IArray.from( + + val allocatingReturn = cfd.returnDescriptor + .map: + case ad: AliasDescriptor[?] => ad.real + case a => a + .exists: + case _: StructDescriptor => true + case _ => false + + val prefixTransition = + if allocatingReturn then + List((a: Allocator, _: Any) => + transitionModule17.methodArgument(a) + ) + else Nil + + val regularTransitions = cfd.inputDescriptors - .map(td => + .map: td => (a: Allocator) ?=> transitionModule17.methodArgument(td, _, a) - ) - .map(fn => (a: Allocator, b: Any) => fn(using a)(b)) - ) + .map: fn => + (a: Allocator, b: Any) => fn(using a)(b) val retTransition: OutputTransition = cfd.returnDescriptor .map: td => @@ -42,17 +58,15 @@ given libraryModule17: LibModule with ().asInstanceOf[Object] val fn = - if !cfd.isVariadic then - generator.generate(mh, transitions, retTransition, tempScope()) - else - generator.generateVariadic( - mh, - transitions, - (td, alloc, a) => - transitionModule17.methodArgument(td, a, alloc), - retTransition, - tempScope() - ) + generator.generate( + mh, + IArray.from(prefixTransition ++ regularTransitions), + transitionModule17, + retTransition, + tempScope(), + allocatingReturn, + cfd.isVariadic + ) AtomicReference(fn) diff --git a/j19/src/fr/hammons/slinc/modules/LibModule19.scala b/j19/src/fr/hammons/slinc/modules/LibModule19.scala index 4106792a..f98bd522 100644 --- a/j19/src/fr/hammons/slinc/modules/LibModule19.scala +++ b/j19/src/fr/hammons/slinc/modules/LibModule19.scala @@ -21,13 +21,28 @@ given libModule19: LibModule with val mh: MethodHandler = MethodHandler((v: Seq[Variadic]) => getDowncall(cfd, v).bindTo(addr).nn ) - val transitions = IArray.from( + + val allocatingReturn = cfd.returnDescriptor + .map: + case ad: AliasDescriptor[?] => ad.real + case a => a + .exists: + case _: StructDescriptor => true + case _ => false + + val prefixTransition = + if allocatingReturn then + List((a: Allocator, _: Any) => + transitionModule19.methodArgument(a) + ) + else Nil + + val regularTransitions = cfd.inputDescriptors .map: td => (a: Allocator) ?=> transitionModule19.methodArgument(td, _, a) .map: fn => (a: Allocator, b: Any) => fn(using a)(b) - ) val retTransition: OutputTransition = cfd.returnDescriptor .map: td => @@ -37,17 +52,15 @@ given libModule19: LibModule with ().asInstanceOf[Object] val fn = - if !cfd.isVariadic then - generator.generate(mh, transitions, retTransition, tempScope()) - else - generator.generateVariadic( - mh, - transitions, - (descriptor, alloc, value) => - transitionModule19.methodArgument(descriptor, value, alloc), - retTransition, - tempScope() - ) + generator.generate( + mh, + IArray.from(prefixTransition.concat(regularTransitions)), + transitionModule19, + retTransition, + tempScope(), + allocatingReturn, + cfd.isVariadic + ) AtomicReference(fn) LibBacking(IArray.from(fns)).asInstanceOf[LibBacking[?]] From ee172df9426fbec44dd376aa1feb4cb290011649 Mon Sep 17 00:00:00 2001 From: Mark Hammons Date: Fri, 24 Mar 2023 11:01:24 +0100 Subject: [PATCH 2/2] Refactor LibModules and CFunctionBindingGenerator to be simpler --- .../slinc/CFunctionBindingGenerator.scala | 119 +++++++++--------- .../hammons/slinc/CFunctionInformation.scala | 56 +++++++++ .../hammons/slinc/modules/LibModule17.scala | 52 ++------ .../hammons/slinc/modules/LibModule19.scala | 46 ++----- 4 files changed, 137 insertions(+), 136 deletions(-) create mode 100644 core/src/fr/hammons/slinc/CFunctionInformation.scala diff --git a/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala b/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala index d621080b..0b85f0a1 100644 --- a/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala +++ b/core/src/fr/hammons/slinc/CFunctionBindingGenerator.scala @@ -1,59 +1,52 @@ package fr.hammons.slinc -import java.lang.invoke.MethodHandle import scala.quoted.* import scala.annotation.nowarn -import fr.hammons.slinc.modules.TransitionModule +import fr.hammons.slinc.CFunctionRuntimeInformation.{ + InputTransition, + ReturnTransition +} +import fr.hammons.slinc.CFunctionBindingGenerator.VariadicTransition -type InputTransition = (Allocator, Any) => Any -type OutputTransition = (Object | Null) => AnyRef trait CFunctionBindingGenerator: def generate( methodHandler: MethodHandler, - inputTransitions: IArray[InputTransition], - variadicTransition: TransitionModule, - outputTransition: OutputTransition, - scope: Scope, - allocatingReturn: Boolean, - variadic: Boolean + transitionSet: CFunctionRuntimeInformation, + variadicTransition: VariadicTransition, + scope: Scope ): AnyRef object CFunctionBindingGenerator: - private case class LambdaInputs( - normalArgs: List[Expr[Any]], - varArgs: Option[Expr[Seq[Variadic]]] - ) - - private def getVariadicExprs( - s: Seq[Variadic], - variadicTransition: TransitionModule, - allocator: Allocator - ): Seq[Any] = - s.map: vararg => - vararg.use[DescriptorOf](dc ?=> - d => variadicTransition.methodArgument(dc.descriptor, d, allocator) - ) + type VariadicTransition = (Allocator, Seq[Variadic]) => Seq[Any] + + private enum LambdaInputs: + case Standard(args: List[Expr[Any]]) + case VariadicInputs(args: List[Expr[Any]], varArgs: Expr[Seq[Variadic]]) + private object LambdaInputs: + def choose(args: List[Expr[Any]], isVariadic: Boolean)( + variadicInput: => Expr[Seq[Variadic]] + ) = if isVariadic then + LambdaInputs.VariadicInputs(args, varArgs = variadicInput) + else LambdaInputs.Standard(args) + + @nowarn("msg=unused implicit parameter") private def invokation( - vTransition: Expr[TransitionModule], + variadicTransition: Expr[VariadicTransition], mh: Expr[MethodHandler] )(using Quotes) = - (alloc: Expr[Allocator], args: LambdaInputs) => - args.varArgs match - case None => + (alloc: Expr[Allocator], inputs: LambdaInputs) => + inputs match + case LambdaInputs.Standard(args) => MethodHandleTools.invokeArguments( '{ $mh.nonVariadic }, - args.normalArgs + args ) - case Some(varArgs) => + case LambdaInputs.VariadicInputs(args, varArgs) => '{ MethodHandleFacade.callVariadic( $mh.variadic($varArgs), - ${ Expr.ofList(args.normalArgs) } ++ getVariadicExprs( - $varArgs, - $vTransition, - $alloc - )* + ${ Expr.ofList(args) } ++ $variadicTransition($alloc, $varArgs)* ) } @@ -63,11 +56,12 @@ object CFunctionBindingGenerator: applyImpl[L]('name) } - private def lambda2( + @nowarn("msg=unused implicit parameter") + private def lambda( argNumbers: Int, scope: Expr[Scope], inputTransitions: Expr[IArray[InputTransition]], - outputTransition: Expr[OutputTransition], + outputTransition: Expr[ReturnTransition], allocatingReturn: Boolean, varArg: Boolean )( @@ -95,15 +89,15 @@ object CFunctionBindingGenerator: def inputExprs(alloc: Expr[Allocator])(using q: Quotes) = val prefix = if allocatingReturn then List(alloc.asTerm) else Nil val toTransform = if varArg then inputs.init else inputs - LambdaInputs( + LambdaInputs.choose( prefix .concat(toTransform) .map(_.asExpr) .zipWithIndex .map: (exp, i) => '{ $inputTransitions(${ Expr(i) })($alloc, $exp) }, - Option.unless(!varArg)(inputs.last.asExprOf[Seq[Variadic]]) - ) + varArg + )(inputs.last.asExprOf[Seq[Variadic]]) '{ $scope { alloc ?=> @@ -132,28 +126,29 @@ object CFunctionBindingGenerator: new CFunctionBindingGenerator: def generate( methodHandler: MethodHandler, - inputTransitions: IArray[InputTransition], - variadicTransition: TransitionModule, - outputTransition: OutputTransition, - scope: Scope, - allocatingReturn: Boolean, - variadic: Boolean - ): AnyRef = ${ - val lamdaGen = (allocatingReturn: Boolean, variadic: Boolean) => - lambda2( - methodSymbol.paramSymss.map(_.size).sum, - 'scope, - 'inputTransitions, - 'outputTransition, - allocatingReturn, - variadic - )(invokation('variadicTransition, 'methodHandler)) + functionInformation: CFunctionRuntimeInformation, + variadicTransition: VariadicTransition, + scope: Scope + ): AnyRef = + ${ + def lambdaGen(allocatingReturn: Boolean, variadic: Boolean) = + lambda( + methodSymbol.paramSymss.map(_.size).sum, + 'scope, + '{ functionInformation.inputTransitions }, + '{ functionInformation.returnTransition }, + allocatingReturn, + variadic + )(invokation('variadicTransition, 'methodHandler)) - '{ - if allocatingReturn && variadic then ${ lamdaGen(true, true) } - else if allocatingReturn then ${ lamdaGen(true, false) } - else if variadic then ${ lamdaGen(false, true) } - else ${ lamdaGen(false, false) } + '{ + if functionInformation.isVariadic && functionInformation.returnAllocates + then ${ lambdaGen(allocatingReturn = true, variadic = true) } + else if functionInformation.isVariadic then + ${ lambdaGen(allocatingReturn = false, variadic = true) } + else if functionInformation.returnAllocates then + ${ lambdaGen(allocatingReturn = true, variadic = false) } + else ${ lambdaGen(allocatingReturn = false, variadic = false) } + } } - } } diff --git a/core/src/fr/hammons/slinc/CFunctionInformation.scala b/core/src/fr/hammons/slinc/CFunctionInformation.scala new file mode 100644 index 00000000..14b7d2cc --- /dev/null +++ b/core/src/fr/hammons/slinc/CFunctionInformation.scala @@ -0,0 +1,56 @@ +package fr.hammons.slinc + +import fr.hammons.slinc.modules.TransitionModule +import fr.hammons.slinc.CFunctionRuntimeInformation.InputTransition +import fr.hammons.slinc.CFunctionRuntimeInformation.ReturnTransition + +final case class CFunctionRuntimeInformation( + name: String, + inputDescriptors: Seq[TypeDescriptor], + inputTransitions: IArray[InputTransition], + returnDescriptor: Option[TypeDescriptor], + returnTransition: ReturnTransition, + isVariadic: Boolean, + returnAllocates: Boolean +) + +object CFunctionRuntimeInformation: + def apply(functionDescriptor: CFunctionDescriptor)(using + transitionModule: TransitionModule + ) = + val allocatingReturn = functionDescriptor.returnDescriptor + .map: + case ad: AliasDescriptor[?] => ad.real + case a => a + .exists: + case _: StructDescriptor => true + case _ => false + + val allocationTransition: Seq[InputTransition] = + if allocatingReturn then + Seq((allocator, _) => transitionModule.methodArgument(allocator)) + else Seq.empty + + val inputTransitions: Seq[InputTransition] = + functionDescriptor.inputDescriptors.map: typeDescriptor => + (allocator, input) => + transitionModule.methodArgument(typeDescriptor, input, allocator) + val outputTransition: ReturnTransition = + functionDescriptor.returnDescriptor match + case None => _ => ().asInstanceOf[Object] + case Some(descriptor) => + returnValue => + transitionModule.methodReturn[Object](descriptor, returnValue.nn) + + new CFunctionRuntimeInformation( + functionDescriptor.name, + functionDescriptor.inputDescriptors, + IArray.from(allocationTransition ++ inputTransitions), + functionDescriptor.returnDescriptor, + outputTransition, + functionDescriptor.isVariadic, + allocatingReturn + ) + + type InputTransition = (Allocator, Any) => Any + type ReturnTransition = (Object | Null) => AnyRef diff --git a/j17/src/fr/hammons/slinc/modules/LibModule17.scala b/j17/src/fr/hammons/slinc/modules/LibModule17.scala index c8f5d5f5..aa92de61 100644 --- a/j17/src/fr/hammons/slinc/modules/LibModule17.scala +++ b/j17/src/fr/hammons/slinc/modules/LibModule17.scala @@ -1,15 +1,13 @@ package fr.hammons.slinc.modules import fr.hammons.slinc.LibBacking -import fr.hammons.slinc.Allocator import java.util.concurrent.atomic.AtomicReference import fr.hammons.slinc.CFunctionBindingGenerator -import fr.hammons.slinc.OutputTransition import fr.hammons.slinc.CFunctionDescriptor import fr.hammons.slinc.MethodHandler import fr.hammons.slinc.Variadic -import fr.hammons.slinc.AliasDescriptor -import fr.hammons.slinc.StructDescriptor +import fr.hammons.slinc.CFunctionRuntimeInformation +import fr.hammons.slinc.DescriptorOf given libraryModule17: LibModule with val runtimeVersion = 17 @@ -28,44 +26,20 @@ given libraryModule17: LibModule with getDowncall(cfd, v).bindTo(addr).nn ) - val allocatingReturn = cfd.returnDescriptor - .map: - case ad: AliasDescriptor[?] => ad.real - case a => a - .exists: - case _: StructDescriptor => true - case _ => false - - val prefixTransition = - if allocatingReturn then - List((a: Allocator, _: Any) => - transitionModule17.methodArgument(a) - ) - else Nil - - val regularTransitions = - cfd.inputDescriptors - .map: td => - (a: Allocator) ?=> transitionModule17.methodArgument(td, _, a) - .map: fn => - (a: Allocator, b: Any) => fn(using a)(b) - - val retTransition: OutputTransition = cfd.returnDescriptor - .map: td => - (o: Object | Null) => - transitionModule17.methodReturn[AnyRef](td, o.nn) - .getOrElse: (_: Object | Null) => - ().asInstanceOf[Object] - val fn = generator.generate( mh, - IArray.from(prefixTransition ++ regularTransitions), - transitionModule17, - retTransition, - tempScope(), - allocatingReturn, - cfd.isVariadic + CFunctionRuntimeInformation(cfd), + (allocator, varArgs) => + varArgs.map: varArg => + varArg.use[DescriptorOf]: descriptorOf ?=> + data => + transitionModule17.methodArgument( + descriptorOf.descriptor, + data, + allocator + ), + tempScope() ) AtomicReference(fn) diff --git a/j19/src/fr/hammons/slinc/modules/LibModule19.scala b/j19/src/fr/hammons/slinc/modules/LibModule19.scala index f98bd522..da258154 100644 --- a/j19/src/fr/hammons/slinc/modules/LibModule19.scala +++ b/j19/src/fr/hammons/slinc/modules/LibModule19.scala @@ -22,44 +22,20 @@ given libModule19: LibModule with getDowncall(cfd, v).bindTo(addr).nn ) - val allocatingReturn = cfd.returnDescriptor - .map: - case ad: AliasDescriptor[?] => ad.real - case a => a - .exists: - case _: StructDescriptor => true - case _ => false - - val prefixTransition = - if allocatingReturn then - List((a: Allocator, _: Any) => - transitionModule19.methodArgument(a) - ) - else Nil - - val regularTransitions = - cfd.inputDescriptors - .map: td => - (a: Allocator) ?=> transitionModule19.methodArgument(td, _, a) - .map: fn => - (a: Allocator, b: Any) => fn(using a)(b) - - val retTransition: OutputTransition = cfd.returnDescriptor - .map: td => - (o: Object | Null) => - transitionModule19.methodReturn[Object](td, o.nn) - .getOrElse: (_: Object | Null) => - ().asInstanceOf[Object] - val fn = generator.generate( mh, - IArray.from(prefixTransition.concat(regularTransitions)), - transitionModule19, - retTransition, - tempScope(), - allocatingReturn, - cfd.isVariadic + CFunctionRuntimeInformation(cfd), + (allocator, varArgs) => + varArgs.map: varArg => + varArg.use[DescriptorOf]: descriptorOf ?=> + data => + transitionModule19.methodArgument( + descriptorOf.descriptor, + data, + allocator + ), + tempScope() ) AtomicReference(fn)