mirror of
https://github.com/irmen/prog8.git
synced 2024-12-27 05:29:38 +00:00
asmsub stack arg
This commit is contained in:
parent
d499e40a4b
commit
fe5b225732
@ -317,14 +317,11 @@ internal class AstChecker(private val program: Program,
|
||||
err("carry parameter has to come last")
|
||||
|
||||
} else {
|
||||
// TODO: non-asm subroutines can only take numeric arguments for now. (not strings and arrays) Maybe this can be improved now that we have '&' ?
|
||||
// the way string params are treated is almost okay (their address is passed) but the receiving subroutine treats it as an integer rather than referring back to the original string.
|
||||
// the way array params are treated is buggy; it thinks the subroutine needs a byte parameter in place of a byte[] ...
|
||||
// This is not easy to fix because strings and arrays are treated a bit simplistic (a "virtual" pointer to the value on the heap)
|
||||
// while passing them as subroutine parameters would require a "real" pointer OR copying the VALUE to the subroutine's parameter variable (which is very inefficient).
|
||||
// For now, don't pass strings and arrays as parameters and instead create the workaround as suggested in the error message below.
|
||||
if(!subroutine.parameters.all{it.type in NumericDatatypes }) {
|
||||
err("Non-asm subroutine can only take numerical parameters (no str/array types) for now. Workaround (for nested subroutine): access the variable from the outer scope directly.")
|
||||
// Pass-by-reference datatypes can not occur as parameters to a subroutine directly
|
||||
// Instead, their reference (address) should be passed (as an UWORD).
|
||||
// The language has no typed pointers at this time.
|
||||
if(subroutine.parameters.any{it.type in PassByReferenceDatatypes }) {
|
||||
err("Pass-by-reference types (str, array) cannot occur as a parameter type directly. Instead, use an uword for their address, or access the variable from the outer scope directly.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -319,7 +319,7 @@ internal class StatementReorderer(private val program: Program): IAstModifyingVi
|
||||
}
|
||||
}
|
||||
null -> {}
|
||||
else -> TODO("call to something weird $sub ${call.target}")
|
||||
else -> throw FatalAstException("call to something weird $sub ${call.target}")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -662,35 +662,35 @@ internal class AsmGen2(val program: Program,
|
||||
out(" ldx c64.SCRATCH_ZPREGX") // restore X again
|
||||
}
|
||||
|
||||
fun translateSubroutineArgument(arg: IndexedValue<SubroutineParameter>, value: Expression, sub: Subroutine) {
|
||||
fun translateSubroutineArgument(parameter: IndexedValue<SubroutineParameter>, value: Expression, sub: Subroutine) {
|
||||
val sourceDt = value.inferType(program)!!
|
||||
if(!argumentTypeCompatible(sourceDt, arg.value.type))
|
||||
if(!argumentTypeCompatible(sourceDt, parameter.value.type))
|
||||
throw AssemblyError("argument type incompatible")
|
||||
if(sub.asmParameterRegisters.isEmpty()) {
|
||||
// pass arg via a variable
|
||||
val paramVar = arg.value
|
||||
// pass parameter via a variable
|
||||
val paramVar = parameter.value
|
||||
val scopedParamVar = (sub.scopedname+"."+paramVar.name).split(".")
|
||||
val target = AssignTarget(null, IdentifierReference(scopedParamVar, sub.position), null, null, sub.position)
|
||||
target.linkParents(value.parent)
|
||||
when (value) {
|
||||
is NumericLiteralValue -> {
|
||||
// optimize when the argument is a constant literal
|
||||
when(arg.value.type) {
|
||||
when(parameter.value.type) {
|
||||
in ByteDatatypes -> assignFromByteConstant(target, value.number.toShort())
|
||||
in WordDatatypes -> assignFromWordConstant(target, value.number.toInt())
|
||||
DataType.FLOAT -> assignFromFloatConstant(target, value.number.toDouble())
|
||||
in PassByReferenceDatatypes -> throw AssemblyError("can't pass string/array as arguments?")
|
||||
else -> throw AssemblyError("weird arg datatype")
|
||||
else -> throw AssemblyError("weird parameter datatype")
|
||||
}
|
||||
}
|
||||
is IdentifierReference -> {
|
||||
// optimize when the argument is a variable
|
||||
when (arg.value.type) {
|
||||
when (parameter.value.type) {
|
||||
in ByteDatatypes -> assignFromByteVariable(target, value)
|
||||
in WordDatatypes -> assignFromWordVariable(target, value)
|
||||
DataType.FLOAT -> assignFromFloatVariable(target, value)
|
||||
in PassByReferenceDatatypes -> throw AssemblyError("can't pass string/array as arguments?")
|
||||
else -> throw AssemblyError("weird arg datatype")
|
||||
else -> throw AssemblyError("weird parameter datatype")
|
||||
}
|
||||
}
|
||||
is RegisterExpr -> {
|
||||
@ -718,13 +718,17 @@ internal class AsmGen2(val program: Program,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// pass arg via a register parameter
|
||||
val paramRegister = sub.asmParameterRegisters[arg.index]
|
||||
// pass parameter via a register parameter
|
||||
val paramRegister = sub.asmParameterRegisters[parameter.index]
|
||||
val statusflag = paramRegister.statusflag
|
||||
val register = paramRegister.registerOrPair
|
||||
val stack = paramRegister.stack
|
||||
when {
|
||||
stack==true -> TODO("param on stack")
|
||||
stack -> {
|
||||
// push arg onto the stack
|
||||
// note: argument order is reversed (first argument will be deepest on the stack)
|
||||
translateExpression(value)
|
||||
}
|
||||
statusflag!=null -> {
|
||||
if (statusflag == Statusflag.Pc) {
|
||||
// this param needs to be set last, right before the jsr
|
||||
|
@ -54,7 +54,7 @@ fun optimizeAssembly(lines: MutableList<String>): Int {
|
||||
numberOfOptimizations++
|
||||
}
|
||||
|
||||
// TODO more assembly optimizations?
|
||||
// TODO more assembly optimizations
|
||||
|
||||
return numberOfOptimizations
|
||||
}
|
||||
@ -101,7 +101,7 @@ fun optimizeSameAssignments(linesByFourteen: List<List<IndexedValue<String>>>):
|
||||
|
||||
// optimize sequential assignments of the isSameAs value to various targets (bytes, words, floats)
|
||||
// the float one is the one that requires 2*7=14 lines of code to check...
|
||||
// @todo a better place to do this is in the Compiler instead and work on opcodes, and never even create the inefficient asm...
|
||||
// @todo a better place to do this is in the Compiler instead and transform the Ast, and never even create the inefficient asm in the first place...
|
||||
|
||||
val removeLines = mutableListOf<Int>()
|
||||
for (pair in linesByFourteen) {
|
||||
|
@ -107,13 +107,6 @@ internal class StatementOptimizer(private val program: Program) : IAstModifyingV
|
||||
if(subroutine.canBeAsmSubroutine) {
|
||||
optimizationsDone++
|
||||
return subroutine.intoAsmSubroutine() // TODO this doesn't work yet due to parameter vardecl issue
|
||||
|
||||
// TODO fix parameter passing so this also works:
|
||||
// asmsub aa(byte arg @ Y) -> clobbers() -> () {
|
||||
// byte local = arg ; @todo fix 'undefined symbol arg' by some sort of alias name for the parameter
|
||||
// A=44
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
if(subroutine !in callgraph.usedSymbols && !forceOutput) {
|
||||
|
@ -19,6 +19,15 @@ these should call optimized pieces of assembly code, so they run as fast as poss
|
||||
|
||||
For now, we have the ``memcopy``, ``memset`` and ``strlen`` builtin functions.
|
||||
|
||||
Fixes
|
||||
^^^^^
|
||||
|
||||
fix asmsub parameters so this works::
|
||||
|
||||
asmsub aa(byte arg @ Y) -> clobbers() -> () {
|
||||
byte local = arg ; @todo fix 'undefined symbol arg' that occurs here
|
||||
A=44
|
||||
}
|
||||
|
||||
|
||||
More optimizations
|
||||
|
@ -4,25 +4,14 @@
|
||||
main {
|
||||
|
||||
sub start() {
|
||||
derp.dop()
|
||||
|
||||
A=derp.dop.zzz
|
||||
|
||||
derp.dop.zzz=3
|
||||
|
||||
|
||||
uword addr = &derp.dop.name ; @todo strange error "pointer-of operand must be the name of a heap variable"
|
||||
c64scr.print(&derp.dop.name)
|
||||
A = testsub(33)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
derp {
|
||||
|
||||
sub dop() {
|
||||
ubyte zzz=33
|
||||
str name="irmen"
|
||||
|
||||
A=54
|
||||
asmsub testsub(ubyte foo @stack) -> ubyte @stack {
|
||||
%asm {{
|
||||
Y=44
|
||||
rts
|
||||
}}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user