mirror of
https://github.com/irmen/prog8.git
synced 2026-10-24 18:02:40 +00:00
105 lines
4.0 KiB
Kotlin
105 lines
4.0 KiB
Kotlin
package prog8tests.codegen.new6502
|
|
|
|
import io.kotest.core.spec.style.FunSpec
|
|
import io.kotest.engine.spec.tempdir
|
|
import io.kotest.matchers.shouldBe
|
|
import prog8.code.core.*
|
|
import prog8.code.target.Cx16Target
|
|
import prog8.codegen.new6502.AsmGen
|
|
import prog8.intermediate.*
|
|
import prog8tests.helpers.ErrorReporterForTests
|
|
import java.nio.file.Path
|
|
import kotlin.io.path.exists
|
|
import kotlin.io.path.readText
|
|
|
|
class TestInlineAsmSub : FunSpec({
|
|
|
|
val tempRoot = tempdir().toPath()
|
|
|
|
fun buildTestProgramWithInlineAsmSub(
|
|
inline: Boolean,
|
|
asmBody: String = "lda #42"
|
|
): Pair<IRProgram, ICompilationTarget> {
|
|
val target = Cx16Target()
|
|
val options = CompilationOptions.builder(target)
|
|
.output(OutputType.RAW)
|
|
.zeropage(ZeropageType.FLOATSAFE)
|
|
.floats(false)
|
|
.compilerVersion("test")
|
|
.memtopAddress(0xffffu)
|
|
.build()
|
|
|
|
val st = IRSymbolTable()
|
|
|
|
val program = IRProgram("test", st, options, DummyStringEncoder)
|
|
|
|
// Create the inline/regular asmsub
|
|
val asmChunk = IRInlineAsmChunk("main.test", asmBody, isIR = false, next = null)
|
|
val asmSub = IRAsmSubroutine(
|
|
label = "main.test",
|
|
address = null,
|
|
clobbers = emptySet(),
|
|
parameters = emptyList(),
|
|
returns = emptyList(),
|
|
asmChunk = asmChunk,
|
|
position = Position.DUMMY,
|
|
isInline = inline
|
|
)
|
|
|
|
// Create the main subroutine that calls the asmsub
|
|
val callChunk = IRCodeChunk(null, null)
|
|
callChunk.instructions.add(IRInstructions.call(CallSite(CallTarget.Direct(codeLabel("main.test")))))
|
|
val mainSub = IRSubroutine("main.start", emptyList(), emptyList(), Position.DUMMY)
|
|
mainSub.chunks.add(callChunk)
|
|
|
|
val block = IRBlock("main", false, IRBlock.Options(), Position.DUMMY)
|
|
block.children.add(mainSub)
|
|
block.children.add(asmSub)
|
|
program.blocks.add(block)
|
|
|
|
return Pair(program, target)
|
|
}
|
|
|
|
fun generateAsm(outputDir: Path, program: IRProgram, target: ICompilationTarget): String {
|
|
val codegen = AsmGen(program, target, ErrorReporterForTests())
|
|
codegen.generate()
|
|
val asmFile = outputDir.resolve("${program.name}.asm")
|
|
check(asmFile.exists()) { "Assembly file not written: $asmFile" }
|
|
return asmFile.readText()
|
|
}
|
|
|
|
test("inline asmsub is inlined at call site, no jsr") {
|
|
val (program, target) = buildTestProgramWithInlineAsmSub(inline = true)
|
|
val outputDir = tempRoot.resolve("test-inline-asmsub-new")
|
|
outputDir.toFile().deleteRecursively()
|
|
outputDir.toFile().mkdirs()
|
|
program.options.outputDir = outputDir
|
|
|
|
val asm = generateAsm(outputDir, program, target)
|
|
val lines = asm.lines().map { it.trim() }
|
|
|
|
// The assembly body should appear in the caller
|
|
lines.any { it == "lda #42" } shouldBe true
|
|
// Should NOT have a jsr to the inline asmsub
|
|
lines.count { it.startsWith("jsr") && it.contains("main.test") } shouldBe 0
|
|
// Should NOT have a separate .proc block for the inline asmsub
|
|
lines.count { it.contains("main.test") && it.contains(".proc") } shouldBe 0
|
|
}
|
|
|
|
test("regular asmsub is called via jsr, not inlined") {
|
|
val (program, target) = buildTestProgramWithInlineAsmSub(inline = false, asmBody = "lda #99\nrts")
|
|
val outputDir = tempRoot.resolve("test-regular-asmsub-new")
|
|
outputDir.toFile().deleteRecursively()
|
|
outputDir.toFile().mkdirs()
|
|
program.options.outputDir = outputDir
|
|
|
|
val asm = generateAsm(outputDir, program, target)
|
|
val lines = asm.lines().map { it.trim() }
|
|
|
|
// Should have a jsr to the regular asmsub
|
|
lines.any { it.startsWith("jsr") && it.contains("main.test") } shouldBe true
|
|
// The body should be in a separate .proc block
|
|
lines.any { it.contains("main.test") && it.contains(".proc") } shouldBe true
|
|
}
|
|
})
|