mirror of
https://github.com/irmen/prog8.git
synced 2025-01-11 13:29:45 +00:00
more codegen fixes
This commit is contained in:
parent
2f5bed36b3
commit
0f5cd22bb7
@ -3,6 +3,7 @@ package prog8.code.ast
|
||||
import prog8.code.core.IMemSizer
|
||||
import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.Position
|
||||
import prog8.code.core.SourceCode
|
||||
import java.nio.file.Path
|
||||
|
||||
// New simplified AST for the code generator.
|
||||
@ -87,6 +88,7 @@ class PtBlock(name: String,
|
||||
val library: Boolean,
|
||||
val forceOutput: Boolean,
|
||||
val alignment: BlockAlignment,
|
||||
val source: SourceCode, // taken from the module the block is defined in.
|
||||
position: Position
|
||||
) : PtNamedNode(name, position) {
|
||||
override fun printProperties() {
|
||||
|
@ -6,6 +6,7 @@ import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.assignment.*
|
||||
import java.util.*
|
||||
import kotlin.io.path.Path
|
||||
import kotlin.io.path.writeLines
|
||||
|
||||
|
||||
@ -315,8 +316,8 @@ class AsmGen(
|
||||
is PtForLoop -> forloopsAsmGen.translate(stmt)
|
||||
is PtRepeatLoop -> translate(stmt)
|
||||
is PtWhen -> translate(stmt)
|
||||
is PtIncludeBinary -> TODO()
|
||||
is PtBreakpoint -> TODO()
|
||||
is PtIncludeBinary -> translate(stmt)
|
||||
is PtBreakpoint -> translate(stmt)
|
||||
is PtVariable, is PtConstant, is PtMemMapped -> { /* do nothing; variables are handled elsewhere */ }
|
||||
is PtBlock -> throw AssemblyError("block should have been handled elsewhere")
|
||||
is PtNodeGroup -> stmt.children.forEach { translate(it) }
|
||||
@ -856,6 +857,27 @@ $repeatLabel lda $counterVar
|
||||
assemblyLines.add(asm.assembly.trimEnd().trimStart('\r', '\n'))
|
||||
}
|
||||
|
||||
private fun translate(incbin: PtIncludeBinary) {
|
||||
val offset = if(incbin.offset!=null) ", ${incbin.offset}" else ""
|
||||
val length = if(incbin.length!=null) ", ${incbin.length}" else ""
|
||||
if(incbin.definingBlock()!!.source is SourceCode.Generated)
|
||||
throw AssemblyError("%asmbinary inside non-library/non-filesystem module not yet supported")
|
||||
val sourcePath = Path(incbin.definingBlock()!!.source.origin)
|
||||
val includedPath = sourcePath.resolveSibling(incbin.file)
|
||||
val pathForAssembler = options.outputDir // #54: 64tass needs the path *relative to the .asm file*
|
||||
.toAbsolutePath()
|
||||
.relativize(includedPath.toAbsolutePath())
|
||||
.normalize() // avoid assembler warnings (-Wportable; only some, not all)
|
||||
.toString().replace('\\', '/')
|
||||
out(" .binary \"$pathForAssembler\" $offset $length")
|
||||
}
|
||||
|
||||
private fun translate(brk: PtBreakpoint) {
|
||||
val label = "_prog8_breakpoint_${breakpointLabels.size+1}"
|
||||
breakpointLabels.add(label)
|
||||
out(label)
|
||||
}
|
||||
|
||||
internal fun signExtendAYlsb(valueDt: DataType) {
|
||||
// sign extend signed byte in A to full word in AY
|
||||
when(valueDt) {
|
||||
@ -2853,14 +2875,13 @@ $repeatLabel lda $counterVar
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO remove?:
|
||||
internal fun popCpuStack(dt: DataType, target: PtVariable, scope: IPtSubroutine?) {
|
||||
// note: because A is pushed first so popped last, saving A is often not required here.
|
||||
val parameter: PtSubroutineParameter = TODO("search subroutine parameter that it may refer to") // target.subroutineParameter
|
||||
val parameter = target.definingSub()?.parameters?.singleOrNull { it.name===target.name }
|
||||
if(parameter!=null) {
|
||||
val sub = parameter.definingAsmSub()!! // TODO or also regular PtSub?
|
||||
val shouldKeepA = sub.asmParameterRegisters.any { it.registerOrPair==RegisterOrPair.AX || it.registerOrPair==RegisterOrPair.AY }
|
||||
val reg: RegisterOrStatusflag = sub.asmParameterRegisters[sub.parameters.indexOf(parameter)]
|
||||
val sub = parameter.definingAsmSub() ?: throw AssemblyError("push/pop arg passing only supported on asmsubs ${target.position}")
|
||||
val shouldKeepA = sub.parameters.any { it.second.registerOrPair==RegisterOrPair.AX || it.second.registerOrPair==RegisterOrPair.AY}
|
||||
val reg = sub.parameters.single { it.first === parameter }.second
|
||||
if(reg.statusflag!=null) {
|
||||
if(shouldKeepA)
|
||||
out(" sta P8ZP_SCRATCH_REG")
|
||||
@ -2951,7 +2972,6 @@ $repeatLabel lda $counterVar
|
||||
else -> throw AssemblyError("can't pop $dt")
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
internal fun pushCpuStack(dt: DataType, value: PtExpression) {
|
||||
val signed = value.type.oneOf(DataType.BYTE, DataType.WORD)
|
||||
|
@ -52,15 +52,25 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
require(fcall.args[0] is PtIdentifier) {
|
||||
"attempt to pop a value into a differently typed variable, or in something else that isn't supported ${fcall.position}"
|
||||
}
|
||||
TODO("pop cpu stack byte into ${fcall.args[0]}")
|
||||
// asmgen.popCpuStack(DataType.UBYTE, (fcall.args[0] as PtIdentifier).targetVarDecl(program)!!, fcall.definingISub())
|
||||
val target = (fcall.args[0] as PtIdentifier).targetVarDecl(program)
|
||||
val target2 = (fcall.args[0] as PtIdentifier).targetStatement(program)
|
||||
if(target2==null)
|
||||
TODO("huh1")
|
||||
if(target==null)
|
||||
TODO("huh2")
|
||||
asmgen.popCpuStack(DataType.UBYTE, target!!, fcall.definingISub())
|
||||
}
|
||||
"popw" -> {
|
||||
require(fcall.args[0] is PtIdentifier) {
|
||||
"attempt to pop a value into a differently typed variable, or in something else that isn't supported ${fcall.position}"
|
||||
}
|
||||
TODO("pop cpu stack word into ${fcall.args[0]}")
|
||||
// asmgen.popCpuStack(DataType.UWORD, (fcall.args[0] as PtIdentifier).targetVarDecl(program)!!, fcall.definingISub())
|
||||
val target = (fcall.args[0] as PtIdentifier).targetVarDecl(program)
|
||||
val target2 = (fcall.args[0] as PtIdentifier).targetStatement(program)
|
||||
if(target2==null)
|
||||
TODO("huh1")
|
||||
if(target==null)
|
||||
TODO("huh2")
|
||||
asmgen.popCpuStack(DataType.UWORD, target!!, fcall.definingISub())
|
||||
}
|
||||
"rsave" -> funcRsave()
|
||||
"rsavex" -> funcRsaveX()
|
||||
@ -319,7 +329,7 @@ internal class BuiltinFunctionsAsmGen(private val program: PtProgram,
|
||||
}
|
||||
|
||||
private fun funcMemory(fcall: PtBuiltinFunctionCall, discardResult: Boolean, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
||||
if(discardResult || fcall !is PtBuiltinFunctionCall) // TODO huh, is always this class??
|
||||
if(discardResult)
|
||||
throw AssemblyError("should not discard result of memory allocation at $fcall")
|
||||
val name = (fcall.args[0] as PtString).value
|
||||
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name ${fcall.position}"}
|
||||
|
@ -56,7 +56,6 @@ internal class AsmAssignTarget(val kind: TargetStorageKind,
|
||||
identifier != null -> {
|
||||
val paramName = identifier!!.targetVarDecl(program)?.name
|
||||
val parameter = identifier!!.targetStatement(program).definingSub()?.parameters?.singleOrNull { it.name===paramName }
|
||||
println("assign to ${identifier!!.name} param=$parameter") // TODO WEG
|
||||
if (parameter!=null) {
|
||||
val sub = parameter.definingAsmSub()
|
||||
if (sub!=null) {
|
||||
@ -137,7 +136,6 @@ internal class AsmAssignSource(val kind: SourceStorageKind,
|
||||
is PtIdentifier -> {
|
||||
val paramName = value.targetVarDecl(program)?.name
|
||||
val parameter = value.targetStatement(program).definingSub()?.parameters?.singleOrNull { it.name===paramName }
|
||||
println("assign to ${value.name} param=$parameter") // TODO WEG
|
||||
if(parameter?.definingAsmSub() != null)
|
||||
throw AssemblyError("can't assign from a asmsub register parameter $value ${value.position}")
|
||||
val varName=asmgen.asmVariableName(value)
|
||||
|
@ -130,7 +130,8 @@ class IntermediateAstMaker(private val program: Program, private val symbolTable
|
||||
}
|
||||
}
|
||||
val (vardecls, statements) = srcBlock.statements.partition { it is VarDecl }
|
||||
val block = PtBlock(srcBlock.name, srcBlock.address, srcBlock.isInLibrary, forceOutput, alignment, srcBlock.position)
|
||||
val src = srcBlock.definingModule.source
|
||||
val block = PtBlock(srcBlock.name, srcBlock.address, srcBlock.isInLibrary, forceOutput, alignment, src, srcBlock.position)
|
||||
makeScopeVarsDecls(vardecls).forEach { block.add(it) }
|
||||
for (stmt in statements)
|
||||
block.add(transformStatement(stmt))
|
||||
|
@ -63,9 +63,7 @@ class TestIntermediateAst: FunSpec({
|
||||
arraydecl.name shouldBe "array"
|
||||
arraydecl.type shouldBe DataType.ARRAY_UB
|
||||
|
||||
val containmentCast = (entry.children[3] as PtAssignment).value as PtTypeCast
|
||||
containmentCast.type shouldBe DataType.UBYTE
|
||||
val containment = containmentCast.value as PtContainmentCheck
|
||||
val containment = (entry.children[3] as PtAssignment).value as PtContainmentCheck
|
||||
(containment.element as PtNumber).number shouldBe 11.0
|
||||
val fcall = (entry.children[4] as PtAssignment).value as PtFunctionCall
|
||||
fcall.void shouldBe false
|
||||
|
@ -98,15 +98,15 @@ class TestAsmGenSymbols: StringSpec({
|
||||
val sub = asmgen.program.entrypoint()!!
|
||||
|
||||
val localvarIdent = sub.children.asSequence().filterIsInstance<PtAssignment>().first { it.value is PtIdentifier }.value as PtIdentifier
|
||||
asmgen.asmSymbolName(localvarIdent) shouldBe "localvar"
|
||||
asmgen.asmVariableName(localvarIdent) shouldBe "localvar"
|
||||
asmgen.asmSymbolName(localvarIdent) shouldBe "main.start.localvar"
|
||||
asmgen.asmVariableName(localvarIdent) shouldBe "main.start.localvar"
|
||||
val localvarIdentScoped = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.start.localvar" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(localvarIdentScoped) shouldBe "main.start.localvar"
|
||||
asmgen.asmVariableName(localvarIdentScoped) shouldBe "main.start.localvar"
|
||||
|
||||
val scopedVarIdent = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="var_outside" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(scopedVarIdent) shouldBe "var_outside"
|
||||
asmgen.asmVariableName(scopedVarIdent) shouldBe "var_outside"
|
||||
val scopedVarIdent = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.var_outside" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(scopedVarIdent) shouldBe "main.var_outside"
|
||||
asmgen.asmVariableName(scopedVarIdent) shouldBe "main.var_outside"
|
||||
val scopedVarIdentScoped = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.var_outside" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(scopedVarIdentScoped) shouldBe "main.var_outside"
|
||||
asmgen.asmVariableName(scopedVarIdentScoped) shouldBe "main.var_outside"
|
||||
@ -117,16 +117,16 @@ class TestAsmGenSymbols: StringSpec({
|
||||
val asmgen = createTestAsmGen(program)
|
||||
val sub = asmgen.program.entrypoint()!!
|
||||
|
||||
val localLabelIdent = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="locallabel" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(localLabelIdent) shouldBe "locallabel"
|
||||
asmgen.asmVariableName(localLabelIdent) shouldBe "locallabel"
|
||||
val localLabelIdent = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.start.locallabel" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(localLabelIdent) shouldBe "main.start.locallabel"
|
||||
asmgen.asmVariableName(localLabelIdent) shouldBe "main.start.locallabel"
|
||||
val localLabelIdentScoped = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.start.locallabel" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(localLabelIdentScoped) shouldBe "main.start.locallabel"
|
||||
asmgen.asmVariableName(localLabelIdentScoped) shouldBe "main.start.locallabel"
|
||||
|
||||
val scopedLabelIdent = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="label_outside" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(scopedLabelIdent) shouldBe "label_outside"
|
||||
asmgen.asmVariableName(scopedLabelIdent) shouldBe "label_outside"
|
||||
val scopedLabelIdent = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.label_outside" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(scopedLabelIdent) shouldBe "main.label_outside"
|
||||
asmgen.asmVariableName(scopedLabelIdent) shouldBe "main.label_outside"
|
||||
val scopedLabelIdentScoped = (sub.children.asSequence().filterIsInstance<PtAssignment>().first { (it.value as? PtAddressOf)?.identifier?.name=="main.label_outside" }.value as PtAddressOf).identifier
|
||||
asmgen.asmSymbolName(scopedLabelIdentScoped) shouldBe "main.label_outside"
|
||||
asmgen.asmVariableName(scopedLabelIdentScoped) shouldBe "main.label_outside"
|
||||
|
Loading…
x
Reference in New Issue
Block a user