modify compiler to fix return values and add support for vm ffi

This commit is contained in:
Alex Zenla 2025-03-15 23:34:16 -07:00
parent 4100752f1c
commit 2f5ea4629d
No known key found for this signature in database
GPG Key ID: 067B238899B51269
3 changed files with 42 additions and 28 deletions

View File

@ -17,9 +17,6 @@ class IrStubOpEmitter(val irDefinition: IrDefinition, val code: CodeBuilder) : I
} }
fun final() { fun final() {
if (irDefinition.type == IrDefinitionType.CodeFunction) {
code.emit(Opcode.None)
}
code.emit(Opcode.Return) code.emit(Opcode.Return)
code.emit(Opcode.End) code.emit(Opcode.End)
} }

View File

@ -3,6 +3,7 @@ package gay.pizza.pork.ffi
import com.kenai.jffi.* import com.kenai.jffi.*
import com.kenai.jffi.Function import com.kenai.jffi.Function
import gay.pizza.pork.ast.gen.ArgumentSpec import gay.pizza.pork.ast.gen.ArgumentSpec
import gay.pizza.pork.ast.gen.Symbol
import gay.pizza.pork.evaluator.* import gay.pizza.pork.evaluator.*
import gay.pizza.pork.execution.ArgumentList import gay.pizza.pork.execution.ArgumentList
import gay.pizza.pork.execution.NativeFunction import gay.pizza.pork.execution.NativeFunction
@ -26,14 +27,14 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
rootTypeRegistry.registerPrimitiveTypes() rootTypeRegistry.registerPrimitiveTypes()
} }
override fun provideNativeFunction( fun provideNativeFunctionGeneric(
definitions: List<String>, definitions: List<String>,
arguments: List<ArgumentSpec>, arguments: List<ArgumentSpec>? = null,
inside: SlabContext inside: SlabContext? = null,
): CallableFunction { ): CallableFunction {
if (definitions[0] == "internal") { if (definitions[0] == "internal") {
val internal = internalFunctions[definitions[1]] ?: val internal =
throw RuntimeException("Unknown internal function: ${definitions[1]}") internalFunctions[definitions[1]] ?: throw RuntimeException("Unknown internal function: ${definitions[1]}")
return CallableFunction { functionArguments, _ -> return CallableFunction { functionArguments, _ ->
internal(functionArguments) internal(functionArguments)
} }
@ -77,7 +78,13 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
} }
} }
private fun addStructDefs(ffiTypeRegistry: FfiTypeRegistry, types: List<String>, inside: SlabContext) { override fun provideNativeFunction(
definitions: List<String>,
arguments: List<ArgumentSpec>,
inside: SlabContext
): CallableFunction = provideNativeFunctionGeneric(definitions, arguments, inside)
private fun addStructDefs(ffiTypeRegistry: FfiTypeRegistry, types: List<String>, inside: SlabContext?) {
for (parameter in types) { for (parameter in types) {
if (!parameter.startsWith("struct ")) { if (!parameter.startsWith("struct ")) {
continue continue
@ -87,7 +94,8 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
if (structureName.endsWith("*")) { if (structureName.endsWith("*")) {
structureName = structureName.substring(0, structureName.length - 1) 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) { if (structureDefinitionValue !is FfiStructDefinition) {
throw RuntimeException("Structure '${structureName}' was not an FfiStructDefinition.") throw RuntimeException("Structure '${structureName}' was not an FfiStructDefinition.")
} }
@ -101,16 +109,21 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
private fun buildArgumentList( private fun buildArgumentList(
context: CallContext, context: CallContext,
functionArgumentSpecs: List<ArgumentSpec>, functionArgumentSpecs: List<ArgumentSpec>?,
functionArguments: List<Any>, functionArguments: List<Any>,
ffiTypeRegistry: FfiTypeRegistry, ffiTypeRegistry: FfiTypeRegistry,
functionDefinition: FfiFunctionDefinition, functionDefinition: FfiFunctionDefinition,
freeStringList: MutableList<FfiString> freeStringList: MutableList<FfiString>
): HeapInvocationBuffer { ): HeapInvocationBuffer {
val buffer = HeapInvocationBuffer(context) val buffer = HeapInvocationBuffer(context)
for ((index, spec) in functionArgumentSpecs.withIndex()) {
val ffiType = ffiTypeRegistry.lookup(functionDefinition.parameters[index]) ?: val useFunctionArguments = functionArgumentSpecs ?: functionArguments.map {
throw RuntimeException("Unknown ffi type: ${functionDefinition.parameters[index]}") 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) { if (spec.multiple) {
val variableArguments = functionArguments val variableArguments = functionArguments
.subList(index, functionArguments.size) .subList(index, functionArguments.size)
@ -143,7 +156,8 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
if (functionAddress == 0L) { if (functionAddress == 0L) {
throw RuntimeException( throw RuntimeException(
"Failed to find symbol ${functionDefinition.function} in " + "Failed to find symbol ${functionDefinition.function} in " +
"library $actualLibraryPath") "library $actualLibraryPath"
)
} }
return functionAddress return functionAddress
} }
@ -156,16 +170,17 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
return FfiPlatforms.current.platform.findLibrary(name) ?: name return FfiPlatforms.current.platform.findLibrary(name) ?: name
} }
private fun invoke(invoker: Invoker, function: Function, buffer: HeapInvocationBuffer, type: FfiType): Any = when (type) { private fun invoke(invoker: Invoker, function: Function, buffer: HeapInvocationBuffer, type: FfiType): Any =
FfiPrimitiveType.Pointer -> invoker.invokeAddress(function, buffer) when (type) {
FfiPrimitiveType.UnsignedInt, FfiPrimitiveType.Int -> invoker.invokeInt(function, buffer) FfiPrimitiveType.Pointer -> invoker.invokeAddress(function, buffer)
FfiPrimitiveType.Long -> invoker.invokeLong(function, buffer) FfiPrimitiveType.UnsignedInt, FfiPrimitiveType.Int -> invoker.invokeInt(function, buffer)
FfiPrimitiveType.Void -> invoker.invokeStruct(function, buffer) FfiPrimitiveType.Long -> invoker.invokeLong(function, buffer)
FfiPrimitiveType.Double -> invoker.invokeDouble(function, buffer) FfiPrimitiveType.Void -> invoker.invokeStruct(function, buffer)
FfiPrimitiveType.Float -> invoker.invokeFloat(function, buffer) FfiPrimitiveType.Double -> invoker.invokeDouble(function, buffer)
FfiPrimitiveType.String -> invoker.invokeAddress(function, buffer) FfiPrimitiveType.Float -> invoker.invokeFloat(function, buffer)
else -> throw RuntimeException("Unsupported ffi return type: $type") FfiPrimitiveType.String -> invoker.invokeAddress(function, buffer)
} ?: None else -> throw RuntimeException("Unsupported ffi return type: $type")
} ?: None
private fun ffiStructDefine(arguments: ArgumentList): Any { private fun ffiStructDefine(arguments: ArgumentList): Any {
val copy = arguments.toMutableList() val copy = arguments.toMutableList()
@ -211,9 +226,11 @@ class FfiNativeProvider : ExpandedNativeProvider, NativeProvider {
} }
override fun provideNativeFunction(definitions: List<String>): NativeFunction { override fun provideNativeFunction(definitions: List<String>): NativeFunction {
throw RuntimeException("Invalid Native Function Usage") val callable = provideNativeFunctionGeneric(definitions, arguments = null, inside = null)
return NativeFunction { arguments ->
callable.call(arguments, CallStack())
}
} }
companion object { companion object {
fun typeConversion(type: FfiType): Type = when (type) { fun typeConversion(type: FfiType): Type = when (type) {
FfiPrimitiveType.UnsignedByte -> Type.UINT8 FfiPrimitiveType.UnsignedByte -> Type.UINT8

View File

@ -1,2 +1,2 @@
export func printf(format, arguments...) export func printf(format, arguments...)
native ffi "c:printf:int:char*,..." native ffi "c" "int printf(int argc, ...)"