diff --git a/backend/common/src/commonMain/kotlin/SeleneCompilerBackend.kt b/backend/common/src/commonMain/kotlin/SeleneCompilerBackend.kt index 41eae17..a5a399c 100644 --- a/backend/common/src/commonMain/kotlin/SeleneCompilerBackend.kt +++ b/backend/common/src/commonMain/kotlin/SeleneCompilerBackend.kt @@ -1,6 +1,10 @@ package me.gabriel.selene.backend.common -interface SeleneCompilerBackend { +import me.gabriel.selene.backend.common.intrinsic.IntrinsicFunctionRepository + +interface SeleneCompilerBackend { + val intrinsics: IntrinsicFunctionRepository + fun compile( module: SeleneCompilerModule ): String diff --git a/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunction.kt b/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunction.kt deleted file mode 100644 index 0d2cbec..0000000 --- a/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunction.kt +++ /dev/null @@ -1,5 +0,0 @@ -package me.gabriel.selene.backend.common.intrinsic - -abstract class IntrinsicFunction( - val name: String -) \ No newline at end of file diff --git a/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionExecutor.kt b/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionExecutor.kt index e8c564e..661970f 100644 --- a/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionExecutor.kt +++ b/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionExecutor.kt @@ -1,7 +1,5 @@ package me.gabriel.selene.backend.common.intrinsic -abstract class IntrinsicFunctionExecutor( - val function: T -) { - abstract fun execute(): String +abstract class IntrinsicFunctionExecutor { + abstract fun onCall(context: Context) } \ No newline at end of file diff --git a/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionRepository.kt b/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionRepository.kt new file mode 100644 index 0000000..8faed57 --- /dev/null +++ b/backend/common/src/commonMain/kotlin/intrinsic/IntrinsicFunctionRepository.kt @@ -0,0 +1,17 @@ +package me.gabriel.selene.backend.common.intrinsic + +abstract class IntrinsicFunctionRepository { + abstract val intrinsics: MutableMap> + + fun register(name: String, executor: IntrinsicFunctionExecutor) { + intrinsics[name] = executor + } + + fun find(name: String): IntrinsicFunctionExecutor? { + return intrinsics[name] + } + + fun unregister(name: String) { + intrinsics.remove(name) + } +} \ No newline at end of file diff --git a/backend/llvm/src/commonMain/kotlin/DragonCompilerBackend.kt b/backend/llvm/src/commonMain/kotlin/DragonCompilerBackend.kt index 1385aaa..04abea7 100644 --- a/backend/llvm/src/commonMain/kotlin/DragonCompilerBackend.kt +++ b/backend/llvm/src/commonMain/kotlin/DragonCompilerBackend.kt @@ -4,11 +4,15 @@ import me.gabriel.ryujin.transcript.DefaultDragonIrTranscriber import me.gabriel.ryujin.transcript.DragonIrTranscriber import me.gabriel.selene.backend.common.SeleneCompilerBackend import me.gabriel.selene.backend.common.SeleneCompilerModule +import me.gabriel.selene.backend.common.intrinsic.IntrinsicFunctionRepository +import me.gabriel.selene.backend.llvm.intrinsic.DragonIntrinsicFunctionRepository import me.gabriel.selene.backend.llvm.session.SeleneDragonCompilingSession -class DragonCompilerBackend: SeleneCompilerBackend { +class DragonCompilerBackend: SeleneCompilerBackend { var irTranscriber: DragonIrTranscriber = DefaultDragonIrTranscriber() + override val intrinsics: IntrinsicFunctionRepository = DragonIntrinsicFunctionRepository() + override fun compile(module: SeleneCompilerModule): String { // TODO: remove if (module.stdlib) return "" diff --git a/backend/llvm/src/commonMain/kotlin/DragonHookContext.kt b/backend/llvm/src/commonMain/kotlin/DragonHookContext.kt new file mode 100644 index 0000000..9ca9519 --- /dev/null +++ b/backend/llvm/src/commonMain/kotlin/DragonHookContext.kt @@ -0,0 +1,13 @@ +package me.gabriel.selene.backend.llvm + +import me.gabriel.ryujin.DragonModule +import me.gabriel.ryujin.dsl.FunctionScopeDsl +import me.gabriel.ryujin.dsl.ModuleScopeDsl +import me.gabriel.ryujin.function.DragonFunction + +class DragonHookContext( + val module: DragonModule, + val function: DragonFunction, + val moduleDsl: ModuleScopeDsl, + val functionDsl: FunctionScopeDsl +) \ No newline at end of file diff --git a/backend/llvm/src/commonMain/kotlin/intrinsic/DragonIntrinsicFunctionRepository.kt b/backend/llvm/src/commonMain/kotlin/intrinsic/DragonIntrinsicFunctionRepository.kt new file mode 100644 index 0000000..0f95eee --- /dev/null +++ b/backend/llvm/src/commonMain/kotlin/intrinsic/DragonIntrinsicFunctionRepository.kt @@ -0,0 +1,11 @@ +package me.gabriel.selene.backend.llvm.intrinsic + +import me.gabriel.selene.backend.common.intrinsic.IntrinsicFunctionExecutor +import me.gabriel.selene.backend.common.intrinsic.IntrinsicFunctionRepository +import me.gabriel.selene.backend.llvm.DragonHookContext + +class DragonIntrinsicFunctionRepository: IntrinsicFunctionRepository() { + override val intrinsics: MutableMap> = mutableMapOf( + + ) +} \ No newline at end of file diff --git a/backend/llvm/src/commonMain/kotlin/intrinsic/Print.kt b/backend/llvm/src/commonMain/kotlin/intrinsic/Print.kt new file mode 100644 index 0000000..b4050e1 --- /dev/null +++ b/backend/llvm/src/commonMain/kotlin/intrinsic/Print.kt @@ -0,0 +1,20 @@ +package me.gabriel.selene.backend.llvm.intrinsic + +import me.gabriel.ryujin.struct.Constant +import me.gabriel.ryujin.struct.DragonType +import me.gabriel.selene.backend.common.intrinsic.IntrinsicFunctionExecutor +import me.gabriel.selene.backend.llvm.DragonHookContext + +class PrintlnIntrinsicFunctionExecutor : IntrinsicFunctionExecutor() { + override fun onCall(context: DragonHookContext) { + context.functionDsl.run { + callExternal( + functionName = "printf", + returnType = DragonType.Pointer(DragonType.Int8), + arguments = listOf( + Constant.DeclaredConstantPtr("%s\\0A"), + ) + ) + } + } +} \ No newline at end of file diff --git a/compiler/src/commonMain/kotlin/SeleneCompiler.kt b/compiler/src/commonMain/kotlin/SeleneCompiler.kt index 9ac2ed0..38b6574 100644 --- a/compiler/src/commonMain/kotlin/SeleneCompiler.kt +++ b/compiler/src/commonMain/kotlin/SeleneCompiler.kt @@ -15,7 +15,7 @@ import me.gabriel.selene.tools.* class SeleneCompiler( private val platform: SeleneCompilerPlatform, - private val backend: SeleneCompilerBackend, + private val backend: SeleneCompilerBackend<*>, private val cli: CommandLine ) { private val errorFormatter = ErrorFormatter(platform.logger) diff --git a/ryujin/src/commonMain/kotlin/dsl/FunctionScopeDsl.kt b/ryujin/src/commonMain/kotlin/dsl/FunctionScopeDsl.kt index 319dde0..937cce6 100644 --- a/ryujin/src/commonMain/kotlin/dsl/FunctionScopeDsl.kt +++ b/ryujin/src/commonMain/kotlin/dsl/FunctionScopeDsl.kt @@ -2,6 +2,7 @@ package me.gabriel.ryujin.dsl import me.gabriel.ryujin.function.DragonFunction import me.gabriel.ryujin.statement.* +import me.gabriel.ryujin.struct.DragonType import me.gabriel.ryujin.struct.Memory import me.gabriel.ryujin.struct.Value @@ -28,6 +29,26 @@ class FunctionScopeDsl( fun add(left: Value, right: Value): AddStatement = AddStatement(left, right) + fun call( + functionName: String, + returnType: DragonType, + arguments: List + ): CallStatement = + CallStatement(functionName, returnType, arguments) + + fun callExternal( + functionName: String, + returnType: DragonType, + arguments: List + ): CallStatement { + module.dependOnFunction( + name = functionName, + returnType = returnType, + parameters = arguments.map { it.type } + ) + return call(functionName, returnType, arguments) + } + fun load(target: Memory): LoadStatement = LoadStatement(target) diff --git a/ryujin/src/commonMain/kotlin/dsl/ModuleScopeDsl.kt b/ryujin/src/commonMain/kotlin/dsl/ModuleScopeDsl.kt index 02e28da..c2884ed 100644 --- a/ryujin/src/commonMain/kotlin/dsl/ModuleScopeDsl.kt +++ b/ryujin/src/commonMain/kotlin/dsl/ModuleScopeDsl.kt @@ -36,6 +36,24 @@ class ModuleScopeDsl: DragonModule { dsl.block(parameterMemoryUnits) } + fun dependOnFunction( + name: String, + returnType: DragonType, + parameters: List, + thoroughlyCheckForDuplicates: Boolean = true + ) { + if (thoroughlyCheckForDuplicates) { + // The dependencies is already a set, but what if the hash codes differs due to same name but different parameters, etc? + val alreadyDependsOnFunction = dependencies.any { it is Dependency.Function && it.name == name } + if (alreadyDependsOnFunction) return + } + dependencies.add(Dependency.Function( + name = name, + returnType = returnType, + parameters = parameters + )) + } + fun virtualTable( name: String, values: Collection diff --git a/ryujin/src/commonMain/kotlin/statement/Functions.kt b/ryujin/src/commonMain/kotlin/statement/Functions.kt new file mode 100644 index 0000000..ec6c28a --- /dev/null +++ b/ryujin/src/commonMain/kotlin/statement/Functions.kt @@ -0,0 +1,16 @@ +package me.gabriel.ryujin.statement + +import me.gabriel.ryujin.struct.DragonType +import me.gabriel.ryujin.struct.Value + +class CallStatement( + val functionName: String, + override val type: DragonType, + val arguments: List +) : TypedDragonStatement { + override val memoryDependencies: Set = arguments.toSet() + + override fun llvm(): String { + return "call ${type.llvm} @${functionName}(${arguments.joinToString { "${it.type.llvm} ${it.llvm()}" }})" + } +} \ No newline at end of file diff --git a/ryujin/src/commonMain/kotlin/struct/Value.kt b/ryujin/src/commonMain/kotlin/struct/Value.kt index cfe05f0..cc539a8 100644 --- a/ryujin/src/commonMain/kotlin/struct/Value.kt +++ b/ryujin/src/commonMain/kotlin/struct/Value.kt @@ -22,7 +22,7 @@ abstract class Constant(override val type: DragonType): Value { override fun llvm(): kotlin.String = "$value" } - class FunctionPtr( + class DeclaredConstantPtr( val name: kotlin.String, ): Constant( type = DragonType.Ptr diff --git a/ryujin/src/commonTest/kotlin/General.kt b/ryujin/src/commonTest/kotlin/General.kt index bfab8b2..a08d772 100644 --- a/ryujin/src/commonTest/kotlin/General.kt +++ b/ryujin/src/commonTest/kotlin/General.kt @@ -51,8 +51,8 @@ class GeneralTest { val module = ryujinModule { virtualTable( "my_vtable", listOf( - Constant.FunctionPtr("test"), - Constant.FunctionPtr("test2") + Constant.DeclaredConstantPtr("test"), + Constant.DeclaredConstantPtr("test2") ) ) }