mirror of
https://github.com/irmen/prog8.git
synced 2026-10-22 05:02:58 +00:00
fix code generation for "return <void function call>"
This commit is contained in:
1 parent
7f3b2e8aa6
commit
ba76fbfe85
4 files changed
+81
-1
No files matched your search
@@ -1982,6 +1982,16 @@ $repeatLabel""")
|
||||
return
|
||||
}
|
||||
|
||||
if(sub.signature.returns.isEmpty()) {
|
||||
// a void subroutine may return the result of a void function call (e.g. "return voidfunc(args)"):
|
||||
// perform the call for its side effects, then return
|
||||
val fcall = ret.children.single() as? PtFunctionCall
|
||||
?: throw AssemblyError("void subroutine can only return the result of a void function call ${ret.position}")
|
||||
functioncallAsmGen.translateFunctionCall(fcall)
|
||||
out(" rts")
|
||||
return
|
||||
}
|
||||
|
||||
val returnDt = sub.signature.returns.single()
|
||||
if (returnDt.isNumericOrBool || returnDt.isPointer) {
|
||||
assignExpressionToRegister(returnvalue, returnRegs.single().first.registerOrPair!!, returnDt.isSigned)
|
||||
|
||||
@@ -1895,7 +1895,14 @@ class IRCodeGen(
|
||||
}
|
||||
|
||||
val value = ret.children.singleOrNull()
|
||||
if(value==null) {
|
||||
if(ret.numReturnValues()==0) {
|
||||
// a void subroutine may return the result of a void function call (e.g. "return voidfunc(args)"):
|
||||
// translate the call for its side effects, then return void
|
||||
val callValue = value as? PtExpression
|
||||
if(callValue!=null)
|
||||
result += expressionEval.translateExpression(callValue).chunks
|
||||
addInstr(result, IRInstructions.returnVoid(), null)
|
||||
} else if(value==null) {
|
||||
addInstr(result, IRInstructions.returnVoid(), null)
|
||||
} else {
|
||||
value as PtExpression
|
||||
|
||||
@@ -13,6 +13,39 @@ class TestM68k : FunSpec({
|
||||
|
||||
val outputDir = tempdir().toPath()
|
||||
|
||||
test("void subroutine returning the result of a void function call compiles") {
|
||||
// Regression test: "return voidfunc(args)" inside a void subroutine is valid Prog8.
|
||||
// The optimizer only rewrites this to "voidfunc(args); return" when it can inline the
|
||||
// caller, so in general it reaches the IR codegen as a Return whose value expression is a
|
||||
// void function call. The m68k/IR backend must translate the call for its side effects and
|
||||
// then return void instead of dying with 'no IR datatype for undefined'.
|
||||
val src = """
|
||||
main {
|
||||
ubyte flag
|
||||
|
||||
sub start() {
|
||||
flag = 1
|
||||
benchmark(flag)
|
||||
}
|
||||
|
||||
sub benchmark(ubyte f) {
|
||||
when f {
|
||||
1 -> return helper(f)
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub helper(ubyte x) {
|
||||
}
|
||||
}
|
||||
"""
|
||||
compileText(Amiga500Target(), optimize = false, src, outputDir, writeAssembly = true, assemble = false) shouldNotBe null
|
||||
compileText(Amiga500Target(), optimize = true, src, outputDir, writeAssembly = true, assemble = false) shouldNotBe null
|
||||
compileText(Qemu68kTarget(), optimize = false, src, outputDir, writeAssembly = true, assemble = false) shouldNotBe null
|
||||
compileText(Qemu68kTarget(), optimize = true, src, outputDir, writeAssembly = true, assemble = false) shouldNotBe null
|
||||
}
|
||||
|
||||
test("module sub returning uword computed from a long expression assembles on qemu68k") {
|
||||
// Regression test for a m68k backend bug: a module-level sub whose return
|
||||
// type is uword, but whose return expression is a 'long' value cast to uword,
|
||||
|
||||
@@ -24,6 +24,36 @@ class TestVariousCodeGen: FunSpec({
|
||||
|
||||
val outputDir = tempdir().toPath()
|
||||
|
||||
test("void subroutine returning the result of a void function call compiles on 6502") {
|
||||
// Regression test: "return voidfunc(args)" inside a void subroutine is valid Prog8.
|
||||
// The optimizer only rewrites this to "voidfunc(args); return" when it can inline the
|
||||
// caller, so in general it reaches the 6502 codegen as a Return whose value expression is a
|
||||
// void function call. The 6502 backend must call it for its side effects and then return.
|
||||
val text = """
|
||||
main {
|
||||
ubyte flag
|
||||
|
||||
sub start() {
|
||||
flag = 1
|
||||
benchmark(flag)
|
||||
}
|
||||
|
||||
sub benchmark(ubyte f) {
|
||||
when f {
|
||||
1 -> return helper(f)
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub helper(ubyte x) {
|
||||
}
|
||||
}
|
||||
"""
|
||||
compileText(Cx16Target(), false, text, outputDir, writeAssembly = true) shouldNotBe null
|
||||
compileText(Cx16Target(), true, text, outputDir, writeAssembly = true) shouldNotBe null
|
||||
}
|
||||
|
||||
test("nested scoping") {
|
||||
val text="""
|
||||
main {
|
||||
|
||||
Reference in new issue
Block a user