m68k: no longer print recursion warnings

This commit is contained in:
Irmen de Jong committed 2026-10-07 19:06:16 +02:00
1 parent a1a48405b0
commit 29254e892b
14 files changed
+64 -4

No files matched your search

+13 -1
View File
@@ -133,7 +133,19 @@ Steps when encountering a compiler crash:
- **NO EMOJI in user documentation**. Do not use emoji or decorative unicode symbols in documentation files. Functional unicode symbols are acceptable when they serve a clear purpose (e.g., → for arrows, ± for plus-minus, × for multiplication, ° for degrees). Avoid decorative emoji like ❌ ✅ ⚠️ 🎉 etc.
### Code Style Guidelines
**Minimal comments when making changes**: When modifying existing code, add only essential comments that explain *why* a change was made or document non-obvious behavior. **Do not add verbose comments** that restate what the code does; let the code speak for itself. Existing extensive comments should be preserved, but new changes should have minimal commentary.
**Code comments**: Comments are the exception, not the norm. A comment earns its place only by recording
something the code itself cannot say: the reason for a non-obvious choice, or a constraint that
a well-meaning future edit would otherwise violate.
- Inline comment inside a function body: 1 line, never more.
- KDoc on a declaration: 3 lines, unless a genuine non-obvious contract cannot be stated shorter.
- Never restate the identifier, the type, or what the following line does.
- Prefer a good name or a well-named function over a comment that explains it.
Before keeping any comment, delete it mentally and ask what the reader loses. If nothing, it goes.
Keep existing comments as they are; do not expand, reword, or reformat them while editing
nearby lines - unless that would cause inconsistency.
**Kotlin string `$` handling**: The `$` character is special in Kotlin string literals (string interpolation). If you need a literal `$` character, use Kotlin's `$$"..."` interpolation prefix instead of backslash escaping (`\$`) or `${'$'}`. The `$$"..."` syntax is a fairly recent Kotlin feature that avoids nasty escaping. For example:
```kotlin
@@ -87,6 +87,13 @@ interface ICompilationTarget: IStringEncoding, IMemSizer {
val defaultLauncherType: CbmPrgLauncherType
val supportsBankedCalls: Boolean
/**
* True when the code generator allocates subroutine locals and per-activation intermediate values
* in a stack frame instead of static memory, so a subroutine on a call-graph cycle can have more
* than one live activation. False means two live activations would share the same storage.
*/
val supportsStackFrames: Boolean
fun initializeMemoryAreas(compilerOptions: CompilationOptions)
fun getFloatAsmBytes(num: Number): String
@@ -12,6 +12,7 @@ class Amiga1200Target: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = true
override val supportsStackFrames = true
override val defaultEncoding = Encoding.ISO
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -12,6 +12,7 @@ class Amiga500Target: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = true
override val supportsStackFrames = true
override val defaultEncoding = Encoding.ISO
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -12,6 +12,7 @@ class C128Target: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = true
override val supportsStackFrames = false
override val defaultEncoding = Encoding.PETSCII
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -13,6 +13,7 @@ class C64Target: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = true
override val supportsStackFrames = false
override val defaultEncoding = Encoding.PETSCII
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -19,6 +19,7 @@ class ConfigFileTarget(
override val supportsBankedCalls: Boolean,
override val defaultEncoding: Encoding,
override val cpu: CpuType,
override val supportsStackFrames: Boolean,
override val PROGRAM_LOAD_ADDRESS: UInt,
override val PROGRAM_MEMTOP_ADDRESS: UInt,
override val BSSHIGHRAM_START: UInt,
@@ -144,6 +145,7 @@ class ConfigFileTarget(
props.getProperty("supports_banked_calls", "false").toBoolean(),
Encoding.entries.first { it.prefix==props.getString("encoding") },
cpuType,
props.getProperty("supports_stack_frames", cpuType.is68k.toString()).toBoolean(),
props.getInteger("load_address"),
props.getInteger("memtop"),
props.getInteger("bss_highram_start"),
@@ -12,6 +12,7 @@ class Cx16Target: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = true
override val supportsStackFrames = false
override val defaultEncoding = Encoding.PETSCII
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -12,6 +12,7 @@ class PETTarget: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = false
override val supportsStackFrames = false
override val defaultEncoding = Encoding.PETSCII
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -16,6 +16,7 @@ class Qemu68kTarget: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = false
override val supportsStackFrames = true
override val defaultEncoding = Encoding.ISO
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -12,6 +12,7 @@ class VMTarget: ICompilationTarget,
override val name = NAME
override val supportsBankedCalls = false
override val supportsStackFrames = false
override val defaultEncoding = Encoding.ISO
override val libraryPath = null
override val customLauncher = emptyList<String>()
@@ -29,8 +29,8 @@ class M68kCodeGenerator(val retainSSA: Boolean): ICodeGeneratorBackend {
}
irProgram.verifyRegisterTypes(virtualRegisterTypes)
// Vertical Slice Prototype: stack-frame locals for frameable leaf subroutines
StackFrameLayout(irProgram, errors).apply()
if (options.compTarget.supportsStackFrames)
StackFrameLayout(irProgram, errors).apply()
if (options.dumpVariables)
dumpVariables(irProgram)
+4 -1
View File
@@ -717,7 +717,10 @@ private fun postprocessAst(program: Program, errors: IErrorReporter, compilerOpt
errors.report()
program.variousCleanups(errors, compilerOptions)
val callGraph = CallGraph(program)
callGraph.checkRecursiveCalls(errors)
// on a stack-frame target a recursive subroutine either gets per-activation storage or is
// rejected by StackFrameLayout, so there is nothing left to warn about here
if(!compilerOptions.compTarget.supportsStackFrames)
callGraph.checkRecursiveCalls(errors)
if(compilerOptions.compTarget.cpu.is68k) {
checkDeferInReentrantSubroutines(program, callGraph, errors)
checkFrameAddressEscapes(program, errors)
+28
View File
@@ -530,6 +530,34 @@ main {
otherErrors.errors.size shouldBe 0
}
test("recursion warning is only emitted for targets without stack frames") {
val src = """
main {
sub rec(ubyte n) -> ubyte {
if n == 0 {
return 0
}
return rec(n-1) + 1
}
sub start() {
g = rec(3)
}
ubyte @shared g
}
"""
val m68kErrors = ErrorReporterForTests(keepMessagesAfterReporting = true)
compileText(Qemu68kTarget(), optimize = false, src, tempdir().toPath(),
writeAssembly = false, assemble = false, errors = m68kErrors) shouldNotBe null
m68kErrors.errors.size shouldBe 0
m68kErrors.warnings.any { it.contains("recursive subroutine") } shouldBe false
val otherErrors = ErrorReporterForTests(keepMessagesAfterReporting = true)
compileText(C64Target(), optimize = false, src, tempdir().toPath(),
writeAssembly = false, assemble = false, errors = otherErrors) shouldNotBe null
otherErrors.errors.size shouldBe 0
otherErrors.warnings.any { it.contains("recursive subroutine") } shouldBe true
}
test("slice 3: defer in a recursive subroutine is rejected on m68k only") {
val src = """
main {