Skip to content
This repository has been archived by the owner on Feb 16, 2025. It is now read-only.

Commit

Permalink
refactor: modular compiler backend, new llvm backend
Browse files Browse the repository at this point in the history
  • Loading branch information
SrGaabriel committed Sep 7, 2024
1 parent 8d59af2 commit a886eaf
Show file tree
Hide file tree
Showing 34 changed files with 293 additions and 473 deletions.
File renamed without changes.
25 changes: 25 additions & 0 deletions backend/common/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
kotlin("multiplatform")
}

repositories {
mavenCentral()
}

kotlin {
jvm()
mingwX64()
linuxX64()
iosArm64()
macosX64()
js().browser()

sourceSets {
val commonMain by getting {
dependencies {
api(project(":analysis"))
api(project(":frontend"))
}
}
}
}
7 changes: 7 additions & 0 deletions backend/common/src/commonMain/kotlin/SeleneCompilerBackend.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package me.gabriel.selene.backend.common

interface SeleneCompilerBackend {
fun compile(
module: SeleneCompilerModule
): String
}
13 changes: 13 additions & 0 deletions backend/common/src/commonMain/kotlin/SeleneCompilerModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package me.gabriel.selene.backend.common

import me.gabriel.selene.analysis.SymbolRepository
import me.gabriel.selene.analysis.signature.Signatures
import me.gabriel.selene.frontend.parsing.SyntaxTree

data class SeleneCompilerModule(
val name: String,
val symbols: SymbolRepository,
val signatures: Signatures,
val astTree: SyntaxTree,
val stdlib: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package me.gabriel.selene.backend.common.intrinsic

abstract class IntrinsicFunction(
val name: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package me.gabriel.selene.backend.common.intrinsic

abstract class IntrinsicFunctionExecutor<T : IntrinsicFunction>(
val function: T
) {
abstract fun execute(): String
}
25 changes: 25 additions & 0 deletions backend/llvm/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
plugins {
kotlin("multiplatform")
}

repositories {
mavenCentral()
}

kotlin {
jvm()
mingwX64()
linuxX64()
iosArm64()
macosX64()
js().browser()

sourceSets {
val commonMain by getting {
dependencies {
implementation(project(":ryujin"))
implementation(project(":backend:common"))
}
}
}
}
20 changes: 20 additions & 0 deletions backend/llvm/src/commonMain/kotlin/DragonCompilerBackend.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package me.gabriel.selene.backend.llvm

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.llvm.session.SeleneDragonCompilingSession

class DragonCompilerBackend: SeleneCompilerBackend {
var irTranscriber: DragonIrTranscriber = DefaultDragonIrTranscriber()

override fun compile(module: SeleneCompilerModule): String {
// TODO: remove
if (module.stdlib) return ""

val session = SeleneDragonCompilingSession(module)
val dragonModule = session.compile()
return irTranscriber.transcribe(dragonModule)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package me.gabriel.selene.backend.llvm.session

import me.gabriel.ryujin.DragonModule
import me.gabriel.ryujin.dsl.FunctionScopeDsl
import me.gabriel.ryujin.dsl.ModuleScopeDsl
import me.gabriel.ryujin.dsl.ryujinModule
import me.gabriel.ryujin.struct.Constant
import me.gabriel.ryujin.struct.Value
import me.gabriel.ryujin.struct.Void
import me.gabriel.selene.backend.common.SeleneCompilerModule
import me.gabriel.selene.backend.llvm.util.addPointerToStructs
import me.gabriel.selene.backend.llvm.util.asDragonType
import me.gabriel.selene.frontend.parsing.FunctionNode
import me.gabriel.selene.frontend.parsing.NumberNode
import me.gabriel.selene.frontend.parsing.ReturnNode
import me.gabriel.selene.frontend.parsing.SyntaxTreeNode

class SeleneDragonCompilingSession(
val module: SeleneCompilerModule
) {
private val dsl = ryujinModule {}
private val root = module.astTree.root

// todo: remove
var developmentMode: Boolean = true

fun compile(): DragonModule {
return ryujinModule {
generateModuleLevelDeclarations()
}
}

private fun ModuleScopeDsl.generateModuleLevelDeclarations() {
for (child in root.getChildren()) {
when (child) {
is FunctionNode -> generateFunction(child)
else -> if (developmentMode) continue else error("Unsupported module-level node: $child")
}
}
}

private fun ModuleScopeDsl.generateFunction(node: FunctionNode) {
val returnType = addPointerToStructs(node.returnType.asDragonType())
val parameterTypes = node.parameters.map { addPointerToStructs(it.type.asDragonType()) }

function(
name = node.name,
returnType = returnType,
parameters = parameterTypes,
) {
for (instruction in node.body.getChildren()) {
generateInstruction(instruction)
}
}
}

private fun FunctionScopeDsl.generateInstruction(node: SyntaxTreeNode): Value? {
return when (node) {
is ReturnNode -> generateReturn(node)
is NumberNode -> generateNumber(node)
else -> error("Unsupported AST tree node instruction: ${node::class.simpleName}")
}
}

private fun FunctionScopeDsl.generateReturn(node: ReturnNode): Value? {
val value = generateInstruction(node.expression)
`return`(value ?: Void)
return null
}

private fun FunctionScopeDsl.generateNumber(node: NumberNode): Value {
return Constant.Number(
type = node.type.asDragonType(),
value = node.value
)
}
}
37 changes: 37 additions & 0 deletions backend/llvm/src/commonMain/kotlin/util/TypeConversion.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package me.gabriel.selene.backend.llvm.util

import me.gabriel.ryujin.struct.DragonType
import me.gabriel.selene.frontend.SeleneType

fun SeleneType.asDragonType(): DragonType = when (this) {
SeleneType.String -> DragonType.Pointer(DragonType.Int8)
SeleneType.Void -> DragonType.Void
SeleneType.Any -> DragonType.Int32
SeleneType.Int8 -> DragonType.Int8
SeleneType.Int16 -> DragonType.Int16
SeleneType.Int32 -> DragonType.Int32
SeleneType.Int64 -> DragonType.Int64
SeleneType.Float32 -> DragonType.Float32
SeleneType.Float64 -> DragonType.Float64
SeleneType.Boolean -> DragonType.Int1
is SeleneType.FixedArray -> DragonType.Array(
type = this.baseType.asDragonType(),
length = this.length
)
is SeleneType.DynamicArray -> DragonType.Pointer(this.baseType.asDragonType())
is SeleneType.Struct -> DragonType.Struct(
name = this.identifier,
types = this.fields.values.map { addPointerToStructs(it.asDragonType()) }
)
is SeleneType.Mutable -> this.baseType.asDragonType()
is SeleneType.Lambda -> DragonType.Ptr
else -> error("Unsupported LLVM type $this")
}


fun addPointerToStructs(returnType: DragonType): DragonType {
return when (returnType) {
is DragonType.Struct, is DragonType.Array -> DragonType.Pointer(returnType)
else -> returnType
}
}
Loading

0 comments on commit a886eaf

Please sign in to comment.