mirror of
https://github.com/irmen/prog8.git
synced 2024-12-23 09:32:43 +00:00
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:
parent
46dac909ef
commit
ca2fb6cef3
@ -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")) {
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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>
|
@ -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,6 +85,27 @@ private fun BufferedWriter.writeLine(line: IRCodeLine) {
|
||||
write("; ${line.comment}\n")
|
||||
}
|
||||
is IRCodeInstruction -> {
|
||||
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 -> {
|
||||
|
@ -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"
|
||||
|
@ -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>
|
18
compiler/test/TestLaunchEmu.kt
Normal file
18
compiler/test/TestLaunchEmu.kt
Normal 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()
|
||||
}
|
||||
})
|
@ -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:
|
||||
|
129
examples/test.p8
129
examples/test.p8
@ -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
|
||||
;
|
||||
;}
|
||||
|
20
intermediate/src/prog8/intermediate/IMSyscall.kt
Normal file
20
intermediate/src/prog8/intermediate/IMSyscall.kt
Normal 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
|
||||
}
|
@ -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.*
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user