IR no longer depends on VM syscalls but has its own syscall list for the few builtin functions that still require it

This commit is contained in:
Irmen de Jong 2022-09-23 14:12:36 +02:00
parent 46dac909ef
commit ca2fb6cef3
14 changed files with 109 additions and 133 deletions

View File

@ -32,7 +32,7 @@ class VirtualMachineDefinition: IMachineDefinition {
override fun launchEmulator(selectedEmulator: Int, programNameWithPath: Path) {
println("\nStarting Virtual Machine...")
// to not have external module dependencies we launch the virtual machine via reflection
// to not have external module dependencies in our own module, we launch the virtual machine via reflection
val vm = Class.forName("prog8.vm.VmRunner").getDeclaredConstructor().newInstance() as IVirtualMachineRunner
val filename = programNameWithPath.name
if(filename.endsWith(".p8virt")) {

View File

@ -26,7 +26,6 @@ compileTestKotlin {
dependencies {
implementation project(':codeCore')
implementation project(':intermediate')
implementation project(':virtualmachine')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.16"

View File

@ -12,7 +12,6 @@
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="module" module-name="codeCore" />
<orderEntry type="module" module-name="intermediate" />
<orderEntry type="module" module-name="virtualmachine" />
<orderEntry type="library" name="io.kotest.assertions.core.jvm" level="project" />
<orderEntry type="library" name="io.kotest.runner.junit5.jvm" level="project" />
</component>

View File

@ -6,7 +6,6 @@ import prog8.code.core.AssemblyError
import prog8.code.core.DataType
import prog8.code.core.Position
import prog8.intermediate.*
import prog8.vm.Syscall
internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGen: ExpressionGen) {
@ -67,10 +66,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val syscall =
when (array.dt) {
DataType.ARRAY_UB,
DataType.ARRAY_B -> Syscall.ANY_BYTE
DataType.ARRAY_B -> IMSyscall.ANY_BYTE
DataType.ARRAY_UW,
DataType.ARRAY_W -> Syscall.ANY_WORD
DataType.ARRAY_F -> Syscall.ANY_FLOAT
DataType.ARRAY_W -> IMSyscall.ANY_WORD
DataType.ARRAY_F -> IMSyscall.ANY_FLOAT
else -> throw IllegalArgumentException("weird type")
}
code += exprGen.translateExpression(call.args[0], 0, -1)
@ -87,10 +86,10 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
val syscall =
when(array.dt) {
DataType.ARRAY_UB,
DataType.ARRAY_B -> Syscall.ALL_BYTE
DataType.ARRAY_B -> IMSyscall.ALL_BYTE
DataType.ARRAY_UW,
DataType.ARRAY_W -> Syscall.ALL_WORD
DataType.ARRAY_F -> Syscall.ALL_FLOAT
DataType.ARRAY_W -> IMSyscall.ALL_WORD
DataType.ARRAY_F -> IMSyscall.ALL_FLOAT
else -> throw IllegalArgumentException("weird type")
}
val code = IRCodeChunk(call.position)
@ -187,37 +186,37 @@ internal class BuiltinFuncGen(private val codeGen: IRCodeGen, private val exprGe
private fun funcReverse(call: PtBuiltinFunctionCall): IRCodeChunk {
val arrayName = call.args[0] as PtIdentifier
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
val sortSyscall =
val syscall =
when(array.dt) {
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> Syscall.REVERSE_BYTES
DataType.ARRAY_UW, DataType.ARRAY_W -> Syscall.REVERSE_WORDS
DataType.ARRAY_F -> Syscall.REVERSE_FLOATS
DataType.ARRAY_UB, DataType.ARRAY_B, DataType.STR -> IMSyscall.REVERSE_BYTES
DataType.ARRAY_UW, DataType.ARRAY_W -> IMSyscall.REVERSE_WORDS
DataType.ARRAY_F -> IMSyscall.REVERSE_FLOATS
else -> throw IllegalArgumentException("weird type to reverse")
}
val code = IRCodeChunk(call.position)
code += exprGen.translateExpression(call.args[0], 0, -1)
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
code += IRCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
return code
}
private fun funcSort(call: PtBuiltinFunctionCall): IRCodeChunk {
val arrayName = call.args[0] as PtIdentifier
val array = codeGen.symbolTable.flat.getValue(arrayName.targetName) as StStaticVariable
val sortSyscall =
val syscall =
when(array.dt) {
DataType.ARRAY_UB -> Syscall.SORT_UBYTE
DataType.ARRAY_B -> Syscall.SORT_BYTE
DataType.ARRAY_UW -> Syscall.SORT_UWORD
DataType.ARRAY_W -> Syscall.SORT_WORD
DataType.STR -> Syscall.SORT_UBYTE
DataType.ARRAY_UB -> IMSyscall.SORT_UBYTE
DataType.ARRAY_B -> IMSyscall.SORT_BYTE
DataType.ARRAY_UW -> IMSyscall.SORT_UWORD
DataType.ARRAY_W -> IMSyscall.SORT_WORD
DataType.STR -> IMSyscall.SORT_UBYTE
DataType.ARRAY_F -> throw IllegalArgumentException("sorting a floating point array is not supported")
else -> throw IllegalArgumentException("weird type to sort")
}
val code = IRCodeChunk(call.position)
code += exprGen.translateExpression(call.args[0], 0, -1)
code += IRCodeInstruction(Opcode.LOAD, VmDataType.BYTE, reg1=1, value=array.length)
code += IRCodeInstruction(Opcode.SYSCALL, value=sortSyscall.ordinal)
code += IRCodeInstruction(Opcode.SYSCALL, value=syscall.ordinal)
return code
}

View File

@ -28,6 +28,7 @@ dependencies {
implementation project(':codeCore')
implementation project(':intermediate')
implementation project(':codeGenIntermediate')
implementation project(':virtualmachine')
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"
implementation "com.michael-bull.kotlin-result:kotlin-result-jvm:1.1.16"

View File

@ -16,5 +16,6 @@
<orderEntry type="module" module-name="codeCore" />
<orderEntry type="module" module-name="intermediate" />
<orderEntry type="module" module-name="codeGenIntermediate" />
<orderEntry type="module" module-name="virtualmachine" />
</component>
</module>

View File

@ -4,6 +4,7 @@ import prog8.code.core.AssemblyError
import prog8.code.core.CompilationOptions
import prog8.code.core.IAssemblyProgram
import prog8.intermediate.*
import prog8.vm.Syscall
import java.io.BufferedWriter
import kotlin.io.path.bufferedWriter
import kotlin.io.path.div
@ -84,7 +85,28 @@ private fun BufferedWriter.writeLine(line: IRCodeLine) {
write("; ${line.comment}\n")
}
is IRCodeInstruction -> {
write(line.ins.toString() + "\n")
if(line.ins.opcode==Opcode.SYSCALL) {
// convert IM Syscall to VM Syscall
val vmSyscall = when(line.ins.value!!) {
IMSyscall.SORT_UBYTE.ordinal -> Syscall.SORT_UBYTE
IMSyscall.SORT_BYTE.ordinal -> Syscall.SORT_BYTE
IMSyscall.SORT_UWORD.ordinal -> Syscall.SORT_UWORD
IMSyscall.SORT_WORD.ordinal -> Syscall.SORT_WORD
IMSyscall.ANY_BYTE.ordinal -> Syscall.ANY_BYTE
IMSyscall.ANY_WORD.ordinal -> Syscall.ANY_WORD
IMSyscall.ANY_FLOAT.ordinal -> Syscall.ANY_FLOAT
IMSyscall.ALL_BYTE.ordinal -> Syscall.ALL_BYTE
IMSyscall.ALL_WORD.ordinal -> Syscall.ALL_WORD
IMSyscall.ALL_FLOAT.ordinal -> Syscall.ALL_FLOAT
IMSyscall.REVERSE_BYTES.ordinal -> Syscall.REVERSE_BYTES
IMSyscall.REVERSE_WORDS.ordinal -> Syscall.REVERSE_WORDS
IMSyscall.REVERSE_FLOATS.ordinal -> Syscall.REVERSE_FLOATS
else -> throw IllegalArgumentException("invalid IM syscall number ${line.ins.value}")
}
val newIns = line.ins.copy(value = vmSyscall.ordinal)
write(newIns.toString() + "\n")
} else
write(line.ins.toString() + "\n")
}
is IRCodeInlineBinary -> {
write("!binary ")

View File

@ -33,6 +33,7 @@ dependencies {
implementation project(':codeGenCpu6502')
implementation project(':codeGenVirtual')
implementation project(':codeGenExperimental')
implementation project(':virtualmachine')
implementation 'org.antlr:antlr4-runtime:4.10.1'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
// implementation "org.jetbrains.kotlin:kotlin-reflect"

View File

@ -22,5 +22,6 @@
<orderEntry type="module" module-name="codeGenCpu6502" />
<orderEntry type="module" module-name="codeGenExperimental" />
<orderEntry type="module" module-name="codeGenVirtual" />
<orderEntry type="module" module-name="virtualmachine" />
</component>
</module>

View File

@ -0,0 +1,18 @@
package prog8tests
import io.kotest.core.spec.style.FunSpec
import prog8.code.target.VMTarget
import kotlin.io.path.deleteExisting
import kotlin.io.path.writeText
class TestLaunchEmu: FunSpec({
test("test launch virtualmachine via target") {
val target = VMTarget()
val tmpfile = kotlin.io.path.createTempFile(suffix=".p8virt")
tmpfile.writeText(";comment\n------PROGRAM------\n;comment\n")
target.machine.launchEmulator(0, tmpfile)
tmpfile.deleteExisting()
}
})

View File

@ -17,7 +17,6 @@ Future Things and Ideas
^^^^^^^^^^^^^^^^^^^^^^^
Compiler:
- vm/ir: all(), any(), reverse() and sort() still depend on a VM Syscall. Get rid of this. (maybe use a IR 'builtin' function?)
- 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.
@ -51,8 +50,8 @@ Libraries:
- fix the problems in atari target, and flesh out its libraries.
- c64: make the graphics.BITMAP_ADDRESS configurable (VIC banking)
- optimize several inner loops in gfx2 even further?
- add modes 3 and perhaps even 2 to gfx2 (16 color and 4 color)?
- add a flood fill routine to gfx2?
- add modes 3 and perhaps even 2 to gfx2 (lores 16 color and 4 color)?
- add a flood fill (span fill/scanline fill) routine to gfx2?
Expressions:

View File

@ -1,115 +1,32 @@
%import textio
%zeropage basicsafe
main {
sub start() {
%asm {{
loadcpu.b r1,_a
loadcpu.b r1,_x
loadcpu.b r1,_y
loadcpu.w r1,_ax
loadcpu.w r1,_ay
loadcpu.w r1,_xy
loadcpu.b r1,_pc
loadcpu.b r1,_pn
loadcpu.b r1,_pz
loadcpu.w r1,_r0
loadcpu.w r1,_r15
uword[] words = [1111,2222,0,4444,3333]
txt.print_ub(all(words))
txt.nl()
txt.print_ub(any(words))
txt.nl()
sort(words)
uword ww
for ww in words {
txt.print_uw(ww)
txt.spc()
}
txt.nl()
reverse(words)
for ww in words {
txt.print_uw(ww)
txt.spc()
}
txt.nl()
storezcpu.b _a
storezcpu.b _x
storezcpu.b _y
storezcpu.w _ax
storezcpu.w _ay
storezcpu.w _xy
storezcpu.b _pc
storezcpu.b _pn
storezcpu.b _pz
storezcpu.b _r0
storezcpu.w _r15
}}
}
}
; uword @shared global1 = 1234
; str @shared globalstring = "irmen"
;
; %asm {{
; nop
; nop
; return
; }}
;
; romsub $ee33 = myromsub(ubyte arg1 @A) clobbers() -> ubyte @Y
; romsub $ee44 = myromsubmulti(ubyte arg1 @A) clobbers() -> ubyte @Y, ubyte @X, ubyte @Pc
;
; asmsub testasmsub(ubyte arg1 @A) clobbers(Y) -> uword @AX {
; %asm {{
; nop
; return
; }}
; }
;
; sub start() {
; void myromsubmulti(44)
; global1 = myromsub(44)
; sys.wait(1)
;
; cx16.r0 = 11111
; cx16.r0L = 22
; cx16.r0H = 33
;
; %asm {{
; nop
; jump main.start.a_label
; }}
;a_label:
;
; %asmbinary "LICENSE", 200, 513
;
;; TODO add proper memory SLAB support to IR+VM
; uword @shared slab1 = memory("slab 1", 2000, 0)
; uword @shared slab2 = memory("slab 1", 2000, 0)
; uword @shared slab3 = memory("other # slab", 2000, 64)
;
; &uword mapped = $c000
; &ubyte[20] mappedarray = $c100
;
; uword @shared zz
; zz = slab1+slab2+slab3
;
; uword @shared @zp qq = zz
; uword @shared @zp qq2 = &zz
;
; str @shared namestring = "irmen"
; uword[] @shared wordarray1 = [1111,2222,3333,4444]
; uword[4] @shared wordarray2 = 12345
; uword[4] @shared wordzeroarray
;
; qq=4242 ; TODO should generate symbol not allocated address????
; mapped = 99 ; TODO wrong VMASM code generated... should generate mapped memory address?????
; mappedarray[1]=99 ; TODO check code????
;
; qq=global1
; qq=other.global2
; nested(11,22)
; main.start.nested.nested2()
;
; sub nested(ubyte a1, ubyte a2) {
; qq++
; txt.print("zzz")
; nested2()
;
; sub nested2() {
; txt.print("zzz2")
; qq++
; }
; }
; }
;}
;
;other {
;
; uword global2 = 9999
;
;}

View File

@ -0,0 +1,20 @@
package prog8.intermediate
// calls to builtin operations that are too complex to be implemented as an IR instruction
// these use the SYSCALL instruction instead.
enum class IMSyscall {
SORT_UBYTE,
SORT_BYTE,
SORT_UWORD,
SORT_WORD,
ANY_BYTE,
ANY_WORD,
ANY_FLOAT,
ALL_BYTE,
ALL_WORD,
ALL_FLOAT,
REVERSE_BYTES,
REVERSE_WORDS,
REVERSE_FLOATS
}

View File

@ -2,7 +2,6 @@ import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNotBe
import org.junit.jupiter.api.fail
import prog8.intermediate.*