From 2f5ea4629d415b2f327884e29c5eb35cce732b0c Mon Sep 17 00:00:00 2001 From: Alex Zenla Date: Sat, 15 Mar 2025 23:34:16 -0700 Subject: [PATCH] modify compiler to fix return values and add support for vm ffi --- .../pizza/pork/compiler/IrStubOpEmitter.kt | 3 - .../gay/pizza/pork/ffi/FfiNativeProvider.kt | 65 ++++++++++++------- stdlib/src/main/pork/ffi/printf.pork | 2 +- 3 files changed, 42 insertions(+), 28 deletions(-) diff --git a/compiler/src/main/kotlin/gay/pizza/pork/compiler/IrStubOpEmitter.kt b/compiler/src/main/kotlin/gay/pizza/pork/compiler/IrStubOpEmitter.kt index e7441b3..da2e91c 100644 --- a/compiler/src/main/kotlin/gay/pizza/pork/compiler/IrStubOpEmitter.kt +++ b/compiler/src/main/kotlin/gay/pizza/pork/compiler/IrStubOpEmitter.kt @@ -17,9 +17,6 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I } fun final() { - if (irDefinition.type == IrDefinitionType.CodeFunction) { - code.emit(Opcode.None) - } code.emit(Opcode.Return) code.emit(Opcode.End) } diff --git a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt index 4f23b67..352b2df 100644 --- a/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt +++ b/ffi/src/main/kotlin/gay/pizza/pork/ffi/FfiNativeProvider.kt @@ -3,6 +3,7 @@ package gay.pizza.pork.ffi import com.kenai.jffi.* import com.kenai.jffi.Function import gay.pizza.pork.ast.gen.ArgumentSpec +import gay.pizza.pork.ast.gen.Symbol import gay.pizza.pork.evaluator.* import gay.pizza.pork.execution.ArgumentList import gay.pizza.pork.execution.NativeFunction @@ -26,14 +27,14 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { rootTypeRegistry.registerPrimitiveTypes() } - override fun provideNativeFunction( + fun provideNativeFunctionGeneric( definitions: List, - arguments: List, - inside: SlabContext + arguments: List? = null, + inside: SlabContext? = null, ): CallableFunction { if (definitions[0] == "internal") { - val internal = internalFunctions[definitions[1]] ?: - throw RuntimeException("Unknown internal function: ${definitions[1]}") + val internal = + internalFunctions[definitions[1]] ?: throw RuntimeException("Unknown internal function: ${definitions[1]}") return CallableFunction { functionArguments, _ -> internal(functionArguments) } @@ -77,7 +78,13 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { } } - private fun addStructDefs(ffiTypeRegistry: FfiTypeRegistry, types: List, inside: SlabContext) { + override fun provideNativeFunction( + definitions: List, + arguments: List, + inside: SlabContext + ): CallableFunction = provideNativeFunctionGeneric(definitions, arguments, inside) + + private fun addStructDefs(ffiTypeRegistry: FfiTypeRegistry, types: List, inside: SlabContext?) { for (parameter in types) { if (!parameter.startsWith("struct ")) { continue @@ -87,7 +94,8 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { if (structureName.endsWith("*")) { structureName = structureName.substring(0, structureName.length - 1) } - val structureDefinitionValue = inside.internalScope.value(structureName) + val structureDefinitionValue = + inside?.internalScope?.value(structureName) ?: throw RuntimeException("Undefined structure: $structureName") if (structureDefinitionValue !is FfiStructDefinition) { throw RuntimeException("Structure '${structureName}' was not an FfiStructDefinition.") } @@ -101,16 +109,21 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { private fun buildArgumentList( context: CallContext, - functionArgumentSpecs: List, + functionArgumentSpecs: List?, functionArguments: List, ffiTypeRegistry: FfiTypeRegistry, functionDefinition: FfiFunctionDefinition, freeStringList: MutableList ): HeapInvocationBuffer { val buffer = HeapInvocationBuffer(context) - for ((index, spec) in functionArgumentSpecs.withIndex()) { - val ffiType = ffiTypeRegistry.lookup(functionDefinition.parameters[index]) ?: - throw RuntimeException("Unknown ffi type: ${functionDefinition.parameters[index]}") + + val useFunctionArguments = functionArgumentSpecs ?: functionArguments.map { + ArgumentSpec(symbol = Symbol(""), multiple = false) + } + + for ((index, spec) in useFunctionArguments.withIndex()) { + val ffiType = ffiTypeRegistry.lookup(functionDefinition.parameters[index]) + ?: throw RuntimeException("Unknown ffi type: ${functionDefinition.parameters[index]}") if (spec.multiple) { val variableArguments = functionArguments .subList(index, functionArguments.size) @@ -143,7 +156,8 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { if (functionAddress == 0L) { throw RuntimeException( "Failed to find symbol ${functionDefinition.function} in " + - "library $actualLibraryPath") + "library $actualLibraryPath" + ) } return functionAddress } @@ -156,16 +170,17 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { return FfiPlatforms.current.platform.findLibrary(name) ?: name } - private fun invoke(invoker: Invoker, function: Function, buffer: HeapInvocationBuffer, type: FfiType): Any = when (type) { - FfiPrimitiveType.Pointer -> invoker.invokeAddress(function, buffer) - FfiPrimitiveType.UnsignedInt, FfiPrimitiveType.Int -> invoker.invokeInt(function, buffer) - FfiPrimitiveType.Long -> invoker.invokeLong(function, buffer) - FfiPrimitiveType.Void -> invoker.invokeStruct(function, buffer) - FfiPrimitiveType.Double -> invoker.invokeDouble(function, buffer) - FfiPrimitiveType.Float -> invoker.invokeFloat(function, buffer) - FfiPrimitiveType.String -> invoker.invokeAddress(function, buffer) - else -> throw RuntimeException("Unsupported ffi return type: $type") - } ?: None + private fun invoke(invoker: Invoker, function: Function, buffer: HeapInvocationBuffer, type: FfiType): Any = + when (type) { + FfiPrimitiveType.Pointer -> invoker.invokeAddress(function, buffer) + FfiPrimitiveType.UnsignedInt, FfiPrimitiveType.Int -> invoker.invokeInt(function, buffer) + FfiPrimitiveType.Long -> invoker.invokeLong(function, buffer) + FfiPrimitiveType.Void -> invoker.invokeStruct(function, buffer) + FfiPrimitiveType.Double -> invoker.invokeDouble(function, buffer) + FfiPrimitiveType.Float -> invoker.invokeFloat(function, buffer) + FfiPrimitiveType.String -> invoker.invokeAddress(function, buffer) + else -> throw RuntimeException("Unsupported ffi return type: $type") + } ?: None private fun ffiStructDefine(arguments: ArgumentList): Any { val copy = arguments.toMutableList() @@ -211,9 +226,11 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider { } override fun provideNativeFunction(definitions: List): NativeFunction { - throw RuntimeException("Invalid Native Function Usage") + val callable = provideNativeFunctionGeneric(definitions, arguments = null, inside = null) + return NativeFunction { arguments -> + callable.call(arguments, CallStack()) + } } - companion object { fun typeConversion(type: FfiType): Type = when (type) { FfiPrimitiveType.UnsignedByte -> Type.UINT8 diff --git a/stdlib/src/main/pork/ffi/printf.pork b/stdlib/src/main/pork/ffi/printf.pork index 1e79a0a..1810b82 100644 --- a/stdlib/src/main/pork/ffi/printf.pork +++ b/stdlib/src/main/pork/ffi/printf.pork @@ -1,2 +1,2 @@ export func printf(format, arguments...) - native ffi "c:printf:int:char*,..." + native ffi "c" "int printf(int argc, ...)"