mirror of
https://github.com/irmen/prog8.git
synced 2024-11-25 19:31:36 +00:00
vm: fix memory slabs (bsieve example)
This commit is contained in:
parent
9d219ae4b9
commit
06cf2e0bd7
@ -8,7 +8,6 @@ import prog8.ast.Program
|
||||
import prog8.ast.base.FatalAstException
|
||||
import prog8.ast.expressions.*
|
||||
import prog8.ast.statements.*
|
||||
import prog8.code.StMemorySlab
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.core.*
|
||||
import prog8.codegen.cpu6502.assignment.*
|
||||
@ -42,7 +41,7 @@ class AsmGen(internal val program: Program,
|
||||
private val expressionsAsmGen = ExpressionsAsmGen(program, this, allocator)
|
||||
private val programGen = ProgramAndVarsGen(program, options, errors, symbolTable, functioncallAsmGen, this, allocator, zeropage)
|
||||
private val assignmentAsmGen = AssignmentAsmGen(program, this, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen, allocator)
|
||||
private val builtinFunctionsAsmGen = BuiltinFunctionsAsmGen(program, this, assignmentAsmGen)
|
||||
|
||||
override fun compileToAssembly(): IAssemblyProgram? {
|
||||
|
||||
@ -2897,12 +2896,6 @@ $repeatLabel lda $counterVar
|
||||
else
|
||||
extra
|
||||
}
|
||||
|
||||
fun addMemorySlab(name: String, size: UInt, align: UInt, position: Position): String {
|
||||
val prefixedName = "prog8_memoryslab_$name"
|
||||
symbolTable.add(StMemorySlab(prefixedName, size, align, position))
|
||||
return prefixedName
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,8 +15,7 @@ import prog8.compiler.FSignature
|
||||
|
||||
internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
private val asmgen: AsmGen,
|
||||
private val assignAsmGen: AssignmentAsmGen,
|
||||
private val allocations: VariableAllocator) {
|
||||
private val assignAsmGen: AssignmentAsmGen) {
|
||||
|
||||
internal fun translateFunctioncallExpression(fcall: BuiltinFunctionCall, resultToStack: Boolean, resultRegister: RegisterOrPair?) {
|
||||
val func = BuiltinFunctions.getValue(fcall.target.nameInSource.single())
|
||||
@ -309,10 +308,7 @@ internal class BuiltinFunctionsAsmGen(private val program: Program,
|
||||
throw AssemblyError("should not discard result of memory allocation at $fcall")
|
||||
val name = (fcall.args[0] as StringLiteral).value
|
||||
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name"}
|
||||
val size = (fcall.args[1] as NumericLiteral).number.toUInt()
|
||||
val align = (fcall.args[2] as NumericLiteral).number.toUInt()
|
||||
val prefixedName = asmgen.addMemorySlab(name, size, align, fcall.position)
|
||||
val slabname = IdentifierReference(listOf("prog8_slabs", prefixedName), fcall.position)
|
||||
val slabname = IdentifierReference(listOf("prog8_slabs", "prog8_memoryslab_$name"), fcall.position)
|
||||
slabname.linkParents(fcall)
|
||||
val src = AsmAssignSource(SourceStorageKind.EXPRESSION, program, asmgen, DataType.UWORD, expression = AddressOf(slabname, fcall.position))
|
||||
val target =
|
||||
|
@ -323,11 +323,8 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
|
||||
|
||||
private fun funcMemory(call: PtBuiltinFunctionCall, resultRegister: Int): IRCodeChunk {
|
||||
val name = (call.args[0] as PtString).value
|
||||
val size = (call.args[1] as PtNumber).number.toUInt()
|
||||
val align = (call.args[2] as PtNumber).number.toUInt()
|
||||
val label = codeGen.addMemorySlab(name, size, align, call.position)
|
||||
val code = IRCodeChunk(call.position)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = label)
|
||||
code += IRInstruction(Opcode.LOAD, VmDataType.WORD, reg1=resultRegister, labelSymbol = "prog8_slabs.prog8_memoryslab_$name")
|
||||
return code
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package prog8.codegen.intermediate
|
||||
|
||||
import prog8.code.StMemVar
|
||||
import prog8.code.StMemorySlab
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
@ -1037,10 +1036,4 @@ class IRCodeGen(
|
||||
internal fun isZero(expression: PtExpression): Boolean = expression is PtNumber && expression.number==0.0
|
||||
|
||||
internal fun isOne(expression: PtExpression): Boolean = expression is PtNumber && expression.number==1.0
|
||||
|
||||
fun addMemorySlab(name: String, size: UInt, align: UInt, position: Position): String {
|
||||
val scopedName = "prog8_memoryslab_$name"
|
||||
symbolTable.add(StMemorySlab(scopedName, size, align, position))
|
||||
return scopedName
|
||||
}
|
||||
}
|
||||
|
@ -104,4 +104,16 @@ internal class SymbolTableMaker: IAstVisitor {
|
||||
scopestack.peek().add(node)
|
||||
// st.origAstLinks[label] = node
|
||||
}
|
||||
|
||||
override fun visit(fcall: BuiltinFunctionCall) {
|
||||
if(fcall.name=="memory") {
|
||||
// memory slab allocations are a builtin functioncall in the program, but end up named as well in the symboltable
|
||||
val name = (fcall.args[0] as StringLiteral).value
|
||||
require(name.all { it.isLetterOrDigit() || it=='_' }) {"memory name should be a valid symbol name"}
|
||||
val size = (fcall.args[1] as NumericLiteral).number.toUInt()
|
||||
val align = (fcall.args[2] as NumericLiteral).number.toUInt()
|
||||
st.add(StMemorySlab("prog8_memoryslab_$name", size, align, fcall.position))
|
||||
}
|
||||
super.visit(fcall)
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,10 @@
|
||||
package prog8tests.helpers
|
||||
|
||||
import prog8.ast.Program
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.c64.C64Zeropage
|
||||
import prog8.codegen.cpu6502.AsmGen
|
||||
import prog8.code.core.ICompilationTarget
|
||||
import prog8.code.core.IErrorReporter
|
||||
import prog8.compiler.CompilationResult
|
||||
import prog8.compiler.CompilerArguments
|
||||
import prog8.compiler.astprocessing.SymbolTableMaker
|
||||
import prog8.compiler.compileProgram
|
||||
import prog8.compiler.determineProgramLoadAddress
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.name
|
||||
|
||||
@ -67,23 +62,3 @@ internal fun compileText(
|
||||
return compileFile(platform, optimize, filePath.parent, filePath.name,
|
||||
errors=errors, writeAssembly=writeAssembly, optFloatExpr = optFloatExpr, keepIR=keepIR)
|
||||
}
|
||||
|
||||
|
||||
internal fun generateAssembly(
|
||||
program: Program,
|
||||
options: CompilationOptions? = null
|
||||
): IAssemblyProgram? {
|
||||
val coptions = options ?: CompilationOptions(OutputType.RAW, CbmPrgLauncherType.BASIC, ZeropageType.DONTUSE, emptyList(),
|
||||
floats = true,
|
||||
noSysInit = true,
|
||||
compTarget = C64Target(),
|
||||
loadAddress = 0u, outputDir = outputDir)
|
||||
coptions.compTarget.machine.zeropage = C64Zeropage(coptions)
|
||||
val st = SymbolTableMaker().makeFrom(program)
|
||||
val errors = ErrorReporterForTests()
|
||||
determineProgramLoadAddress(program, coptions, errors)
|
||||
errors.report()
|
||||
val asmgen = AsmGen(program, st, coptions, errors)
|
||||
errors.report()
|
||||
return asmgen.compileToAssembly()
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ package prog8tests.vm
|
||||
import io.kotest.core.spec.style.FunSpec
|
||||
import io.kotest.matchers.shouldBe
|
||||
import io.kotest.matchers.shouldNotBe
|
||||
import prog8.ast.expressions.BuiltinFunctionCall
|
||||
import prog8.ast.statements.Assignment
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.code.target.VMTarget
|
||||
import prog8.vm.VmRunner
|
||||
@ -135,4 +137,27 @@ skipLABEL:
|
||||
vm.memory.getUB(3) shouldBe 66u
|
||||
}
|
||||
}
|
||||
|
||||
test("memory slabs") {
|
||||
val src = """
|
||||
main {
|
||||
sub start() {
|
||||
uword slab1 = memory("slab1", 2000, 64)
|
||||
slab1[10]=42
|
||||
slab1[11]=43
|
||||
ubyte @shared value1 = slab1[10] ; var at 2
|
||||
ubyte @shared value2 = slab1[11] ; var at 3
|
||||
}
|
||||
}"""
|
||||
val target = VMTarget()
|
||||
val result = compileText(target, true, src, writeAssembly = true)!!
|
||||
val start = result.program.entrypoint
|
||||
start.statements.size shouldBe 9
|
||||
((start.statements[1] as Assignment).value as BuiltinFunctionCall).name shouldBe "memory"
|
||||
val virtfile = result.compilationOptions.outputDir.resolve(result.program.name + ".p8ir")
|
||||
VmRunner().runAndTestProgram(virtfile.readText()) { vm ->
|
||||
vm.memory.getUB(2) shouldBe 42u
|
||||
vm.memory.getUB(3) shouldBe 43u
|
||||
}
|
||||
}
|
||||
})
|
@ -4,8 +4,6 @@ TODO
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- vm: replace addAssemblyToProgram() by call to IRFileLoader's logic, instead of duplicating it.
|
||||
- vm: fix memory slabs (bsieve example)
|
||||
- replace throw IllegalArgumentException() by require()?
|
||||
|
||||
...
|
||||
|
||||
@ -21,6 +19,7 @@ Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Compiler:
|
||||
|
||||
- replace throw IllegalArgumentException() by require()?
|
||||
- vm/ir: put variables and arrays in BSS section (unless -noreinit is specified)
|
||||
- vm: Jumps go to a code block rather than a specific address(label) -> also helps future dead code elimination?
|
||||
- vm: the above means that every label introduces a new code block. This eliminates the use of actual labels altogether.
|
||||
|
@ -97,15 +97,10 @@ class IRSymbolTable(sourceSt: SymbolTable?) {
|
||||
}
|
||||
|
||||
fun add(variable: StMemorySlab) {
|
||||
val scopedName: String
|
||||
val varToadd: StMemorySlab
|
||||
if('.' in variable.name) {
|
||||
scopedName = variable.name
|
||||
varToadd = variable
|
||||
} else {
|
||||
scopedName = variable.scopedName.joinToString(".")
|
||||
varToadd = StMemorySlab(scopedName, variable.size, variable.align, variable.position)
|
||||
}
|
||||
table[scopedName] = varToadd
|
||||
val varToadd = if('.' in variable.name)
|
||||
variable
|
||||
else
|
||||
StMemorySlab("prog8_slabs.${variable.name}", variable.size, variable.align, variable.position)
|
||||
table[varToadd.name] = varToadd
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user