mirror of
https://github.com/irmen/prog8.git
synced 2025-01-14 01:29:55 +00:00
cleanup of Pipe codegen
This commit is contained in:
parent
17694c1d01
commit
75d857027e
@ -959,6 +959,9 @@ class AsmGen(private val program: Program,
|
||||
internal fun translateBuiltinFunctionCallExpression(functionCallExpr: FunctionCallExpression, signature: FSignature, resultToStack: Boolean, resultRegister: RegisterOrPair?) =
|
||||
builtinFunctionsAsmGen.translateFunctioncallExpression(functionCallExpr, signature, resultToStack, resultRegister)
|
||||
|
||||
internal fun translateBuiltinFunctionCallStatement(functionCallStmt: FunctionCallStatement, signature: FSignature) =
|
||||
builtinFunctionsAsmGen.translateFunctioncallStatement(functionCallStmt, signature)
|
||||
|
||||
internal fun translateFunctionCall(functionCallExpr: FunctionCallExpression, isExpression: Boolean) =
|
||||
functioncallAsmGen.translateFunctionCall(functionCallExpr, isExpression)
|
||||
|
||||
@ -1634,40 +1637,31 @@ $label nop""")
|
||||
val subroutine = pipe.definingSubroutine
|
||||
assignExpressionToVariable(pipe.expressions.first(), valueVar.joinToString("."), valueDt, subroutine)
|
||||
pipe.expressions.drop(1).dropLast(1).forEach {
|
||||
val callName = it as IdentifierReference
|
||||
val args = mutableListOf<Expression>(IdentifierReference(valueVar, it.position))
|
||||
val call = FunctionCallExpression(callName, args,it.position)
|
||||
call.linkParents(pipe)
|
||||
valueDt = call.inferType(program).getOrElse { throw AssemblyError("invalid dt") }
|
||||
valueDt = functioncallAsmGen.translateFunctionCall(it as IdentifierReference, listOf(IdentifierReference(valueVar, it.position)), pipe)
|
||||
// assign result value from the functioncall back to the temp var:
|
||||
valueVar = getTempVarName(valueDt)
|
||||
assignExpressionToVariable(call, valueVar.joinToString("."), valueDt, subroutine)
|
||||
val valueVarTarget = AsmAssignTarget(TargetStorageKind.VARIABLE, program, this, valueDt, subroutine, variableAsmName = valueVar.joinToString("."))
|
||||
val returnRegister = returnRegisterOfFunction(it)!!
|
||||
assignRegister(returnRegister, valueVarTarget)
|
||||
}
|
||||
// the last term in the pipe:
|
||||
val callName = pipe.expressions.last() as IdentifierReference
|
||||
val callTarget = callName.targetStatement(program)!!
|
||||
when (callTarget) {
|
||||
// the last term in the pipe, don't care about return var:
|
||||
functioncallAsmGen.translateFunctionCallStatement(
|
||||
pipe.expressions.last() as IdentifierReference,
|
||||
listOf(IdentifierReference(valueVar, pipe.expressions.last().position)),
|
||||
pipe
|
||||
)
|
||||
}
|
||||
|
||||
private fun returnRegisterOfFunction(it: IdentifierReference): RegisterOrPair? {
|
||||
return when (val targetRoutine = it.targetStatement(program)!!) {
|
||||
is BuiltinFunctionPlaceholder -> {
|
||||
val args = mutableListOf<Expression>(IdentifierReference(valueVar, callName.position))
|
||||
val call = FunctionCallStatement(callName, args, true, callName.position)
|
||||
call.linkParents(pipe)
|
||||
translate(call)
|
||||
}
|
||||
is Subroutine -> {
|
||||
if(callTarget.isAsmSubroutine) {
|
||||
val args = mutableListOf<Expression>(IdentifierReference(valueVar, callName.position))
|
||||
val call = FunctionCallStatement(callName, args, true, callName.position)
|
||||
call.linkParents(pipe)
|
||||
translate(call)
|
||||
} else {
|
||||
// have to use GoSub and manual parameter assignment, because no codegen for FunctionCallStmt here
|
||||
val param = callTarget.parameters.single()
|
||||
val paramName = callTarget.scopedName.joinToString(".") + ".${param.name}"
|
||||
val tempvar = IdentifierReference(valueVar, callName.position)
|
||||
tempvar.linkParents(pipe)
|
||||
assignExpressionToVariable(tempvar, paramName, param.type, subroutine)
|
||||
out(" jsr ${asmSymbolName(callName)}")
|
||||
when (BuiltinFunctions.getValue(targetRoutine.name).known_returntype) {
|
||||
in ByteDatatypes -> RegisterOrPair.A
|
||||
in WordDatatypes -> RegisterOrPair.AY
|
||||
else -> return null
|
||||
}
|
||||
}
|
||||
is Subroutine -> targetRoutine.asmReturnvaluesRegisters.single().registerOrPair!!
|
||||
else -> throw AssemblyError("invalid call target")
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import prog8.codegen.target.cpu6502.codegen.assignment.AsmAssignSource
|
||||
import prog8.codegen.target.cpu6502.codegen.assignment.AsmAssignTarget
|
||||
import prog8.codegen.target.cpu6502.codegen.assignment.AsmAssignment
|
||||
import prog8.codegen.target.cpu6502.codegen.assignment.TargetStorageKind
|
||||
import prog8.compilerinterface.BuiltinFunctions
|
||||
import prog8.compilerinterface.CpuType
|
||||
|
||||
|
||||
@ -126,9 +127,53 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
// remember: dealing with the X register and/or dealing with return values is the responsibility of the caller
|
||||
}
|
||||
|
||||
internal fun translateFunctionCall(target: IdentifierReference, args: Iterable<Expression>, scope: Node): DataType {
|
||||
when(val targetStmt = target.targetStatement(program)!!) {
|
||||
is BuiltinFunctionPlaceholder -> {
|
||||
val call = FunctionCallExpression(target, args.toMutableList(), scope.position)
|
||||
call.linkParents(scope)
|
||||
val signature = BuiltinFunctions.getValue(targetStmt.name)
|
||||
asmgen.translateBuiltinFunctionCallExpression(call, signature, false, null)
|
||||
return signature.known_returntype!!
|
||||
}
|
||||
is Subroutine -> {
|
||||
val call = FunctionCallExpression(target, args.toMutableList(), scope.position)
|
||||
call.linkParents(scope)
|
||||
translateFunctionCall(call, true)
|
||||
return call.inferType(program).getOrElse { throw AssemblyError("invalid dt") }
|
||||
}
|
||||
else -> throw AssemblyError("invalid call target")
|
||||
}
|
||||
}
|
||||
|
||||
internal fun translateFunctionCallStatement(target: IdentifierReference, args: Iterable<Expression>, scope: Node) {
|
||||
when(val targetStmt = target.targetStatement(program)!!) {
|
||||
is BuiltinFunctionPlaceholder -> {
|
||||
val call = FunctionCallStatement(target, args.toMutableList(), true, scope.position)
|
||||
call.linkParents(scope)
|
||||
val signature = BuiltinFunctions.getValue(targetStmt.name)
|
||||
asmgen.translateBuiltinFunctionCallStatement(call, signature)
|
||||
}
|
||||
is Subroutine -> {
|
||||
if(targetStmt.isAsmSubroutine) {
|
||||
val call = FunctionCallStatement(target, args.toMutableList(), true, scope.position)
|
||||
call.linkParents(scope)
|
||||
translateFunctionCallStatement(call)
|
||||
} else {
|
||||
// have to use manual parameter assignment and jsr, because no codegen for FunctionCallStmt here
|
||||
val tempVar = args.single()
|
||||
tempVar.linkParents(scope)
|
||||
argumentViaVariable(targetStmt, targetStmt.parameters.single(), tempVar)
|
||||
asmgen.out(" jsr ${asmgen.asmSymbolName(target)}")
|
||||
}
|
||||
}
|
||||
else -> throw AssemblyError("invalid call target")
|
||||
}
|
||||
}
|
||||
|
||||
private fun argumentsViaVariables(sub: Subroutine, call: IFunctionCall) {
|
||||
for(arg in sub.parameters.withIndex().zip(call.args))
|
||||
argumentViaVariable(sub, arg.first, arg.second)
|
||||
argumentViaVariable(sub, arg.first.value, arg.second)
|
||||
}
|
||||
|
||||
private fun argumentsViaRegisters(sub: Subroutine, call: IFunctionCall) {
|
||||
@ -272,15 +317,15 @@ internal class FunctionCallAsmGen(private val program: Program, private val asmg
|
||||
asmgen.out(" plp") // set the carry flag back to correct value
|
||||
}
|
||||
|
||||
private fun argumentViaVariable(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression) {
|
||||
private fun argumentViaVariable(sub: Subroutine, parameter: SubroutineParameter, value: Expression) {
|
||||
// pass parameter via a regular variable (not via registers)
|
||||
val valueIDt = value.inferType(program)
|
||||
val valueDt = valueIDt.getOrElse { throw AssemblyError("unknown dt") }
|
||||
if(!isArgumentTypeCompatible(valueDt, parameter.value.type))
|
||||
if(!isArgumentTypeCompatible(valueDt, parameter.type))
|
||||
throw AssemblyError("argument type incompatible")
|
||||
|
||||
val varName = asmgen.asmVariableName(sub.scopedName + parameter.value.name)
|
||||
asmgen.assignExpressionToVariable(value, varName, parameter.value.type, sub)
|
||||
val varName = asmgen.asmVariableName(sub.scopedName + parameter.name)
|
||||
asmgen.assignExpressionToVariable(value, varName, parameter.type, sub)
|
||||
}
|
||||
|
||||
private fun argumentViaRegister(sub: Subroutine, parameter: IndexedValue<SubroutineParameter>, value: Expression, registerOverride: RegisterOrPair? = null) {
|
||||
|
@ -3,6 +3,7 @@ TODO
|
||||
|
||||
For next compiler release (7.7)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- make pipe statement an expression so that it DOES return a result value (possibly) so you can assign it ??
|
||||
- optimize codegen of pipe operator to avoid needless assigns to temp var
|
||||
- copying floats around: do it with a subroutine rather than 5 lda/sta pairs .
|
||||
is slower but floats are very slow already anyway and this should take a lot less program size.
|
||||
@ -24,6 +25,7 @@ Blocked by an official Commander-x16 r39 release
|
||||
Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- can we promise a left-to-right function call argument evaluation? without sacrificing performance
|
||||
- for the pipe operator: recognise a placeholder (? or % or _) in a non-unary function call to allow things as 4 |> mkword(?, $44) |> print_uw
|
||||
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``v_``
|
||||
then we can get rid of the instruction lists in the machinedefinitions as well?
|
||||
- fix the asm-labels problem (github issue #62)
|
||||
|
@ -1,16 +1,20 @@
|
||||
%import textio
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
sub start() {
|
||||
times_two(554 as ubyte)
|
||||
; txt.print_uw(times_two(add_one(9+3)))
|
||||
; txt.nl()
|
||||
; 9 + 3
|
||||
; |> add_one |> times_two
|
||||
; |> txt.print_uw
|
||||
1.234 |> addfloat |> addfloat |> floats.print_f
|
||||
txt.nl()
|
||||
9 * 3 |> assemblything
|
||||
|> sin8u
|
||||
|> add_one |> times_two
|
||||
|> txt.print_uw
|
||||
}
|
||||
|
||||
sub addfloat(float fl) -> float {
|
||||
return fl+1.11
|
||||
}
|
||||
sub add_one(ubyte input) -> ubyte {
|
||||
return input+1
|
||||
}
|
||||
@ -18,6 +22,13 @@ main {
|
||||
sub times_two(ubyte input) -> uword {
|
||||
return input*$0002
|
||||
}
|
||||
|
||||
asmsub assemblything(ubyte input @A) -> ubyte @A {
|
||||
%asm {{
|
||||
asl a
|
||||
rts
|
||||
}}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user