mirror of
https://github.com/irmen/prog8.git
synced 2025-02-16 07:31:48 +00:00
incbin in IR
This commit is contained in:
parent
6886b61186
commit
aacea3e9db
@ -97,11 +97,12 @@ private fun BufferedWriter.writeLine(line: IRCodeLine) {
|
||||
write(line.ins.toString() + "\n")
|
||||
}
|
||||
is IRCodeInlineBinary -> {
|
||||
write("incbin \"${line.file}\"")
|
||||
if(line.offset!=null)
|
||||
write(",${line.offset}")
|
||||
if(line.length!=null)
|
||||
write(",${line.length}")
|
||||
write("!binary ")
|
||||
line.data.withIndex().forEach {(index, byte) ->
|
||||
write(byte.toString(16).padStart(2,'0'))
|
||||
if(index and 63 == 63 && index<line.data.size-1)
|
||||
write("\n!binary ")
|
||||
}
|
||||
write("\n")
|
||||
}
|
||||
is IRCodeLabel -> {
|
||||
|
@ -6,6 +6,7 @@ import prog8.code.SymbolTable
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.intermediate.*
|
||||
import kotlin.io.path.readBytes
|
||||
import kotlin.math.pow
|
||||
|
||||
|
||||
@ -204,7 +205,10 @@ class CodeGen(internal val program: PtProgram,
|
||||
is PtInlineAssembly -> IRInlineAsmChunk(node.assembly, node.position)
|
||||
is PtIncludeBinary -> {
|
||||
val chunk = IRCodeChunk(node.position)
|
||||
chunk += IRCodeInlineBinary(node.file, node.offset, node.length)
|
||||
val data = node.file.readBytes()
|
||||
.drop(node.offset?.toInt() ?: 0)
|
||||
.take(node.length?.toInt() ?: Int.MAX_VALUE)
|
||||
chunk += IRCodeInlineBinary(data.toByteArray())
|
||||
return chunk
|
||||
}
|
||||
is PtAddressOf,
|
||||
|
@ -136,4 +136,9 @@ internal class VmCodeInlineAsm(asm: String): VmCodeLine() {
|
||||
val assembly: String = asm.trimIndent()
|
||||
}
|
||||
|
||||
internal class VmCodeInlineBinary(val file: Path, val offset: UInt?, val length: UInt?): VmCodeLine()
|
||||
internal class VmCodeInlineBinary(val file: Path, val offset: UInt?, val length: UInt?): VmCodeLine() {
|
||||
init {
|
||||
require(file.isAbsolute)
|
||||
require(file.toFile().isFile)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import prog8.ast.walk.IAstModification
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.C64Target
|
||||
import prog8.code.target.Cx16Target
|
||||
import prog8.code.target.VMTarget
|
||||
|
||||
|
||||
class AstPreprocessor(val program: Program,
|
||||
@ -24,7 +25,7 @@ class AstPreprocessor(val program: Program,
|
||||
relocateCx16VirtualRegisters(program, 0x0004u)
|
||||
}
|
||||
}
|
||||
else if(options.compTarget.name!=Cx16Target.NAME) {
|
||||
else if(options.compTarget.name !in setOf(Cx16Target.NAME, VMTarget.NAME)) {
|
||||
relocateCx16VirtualRegisters(program, options.compTarget.machine.ESTACK_HI)
|
||||
}
|
||||
return noModifications
|
||||
|
@ -180,11 +180,19 @@ class IntermediateAstMaker(val program: Program) {
|
||||
return when(directive.directive) {
|
||||
"%breakpoint" -> PtBreakpoint(directive.position)
|
||||
"%asmbinary" -> {
|
||||
val filename = directive.args[0].str!!
|
||||
val offset: UInt? = if(directive.args.size>=2) directive.args[1].int!! else null
|
||||
val length: UInt? = if(directive.args.size>=3) directive.args[2].int!! else null
|
||||
val sourcePath = Path(directive.definingModule.source.origin)
|
||||
val includedPath = sourcePath.resolveSibling(directive.args[0].str!!)
|
||||
PtIncludeBinary(includedPath, offset, length, directive.position)
|
||||
val abspath = if(File(filename).isFile) {
|
||||
Path(filename).toAbsolutePath()
|
||||
} else {
|
||||
val sourcePath = Path(directive.definingModule.source.origin)
|
||||
sourcePath.resolveSibling(filename).toAbsolutePath()
|
||||
}
|
||||
if(abspath.toFile().isFile)
|
||||
PtIncludeBinary(abspath, offset, length, directive.position)
|
||||
else
|
||||
throw FatalAstException("included file doesn't exist")
|
||||
}
|
||||
"%asminclude" -> {
|
||||
val result = loadAsmIncludeFile(directive.args[0].str!!, directive.definingModule.source)
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
main {
|
||||
|
||||
uword global1 = 1234
|
||||
uword @shared global1 = 1234
|
||||
str @shared globalstring = "irmen"
|
||||
|
||||
%asm {{
|
||||
nop
|
||||
@ -27,6 +28,8 @@ main {
|
||||
}}
|
||||
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)
|
||||
|
@ -1,9 +1,6 @@
|
||||
package prog8.intermediate
|
||||
|
||||
import prog8.code.StMemVar
|
||||
import prog8.code.StMemorySlab
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.SymbolTable
|
||||
import prog8.code.*
|
||||
import prog8.code.ast.PtBlock
|
||||
import prog8.code.core.*
|
||||
import prog8.code.target.*
|
||||
@ -29,7 +26,7 @@ class IRFileReader(outputDir: Path, programName: String) {
|
||||
val match = programPattern.matchEntire(line) ?: throw IRParseException("invalid PROGRAM")
|
||||
val programName = match.groups[1]!!.value
|
||||
val options = parseOptions(lines)
|
||||
val variables = parseVariables(lines)
|
||||
val variables = parseVariables(lines, options.dontReinitGlobals)
|
||||
val memorymapped = parseMemMapped(lines)
|
||||
val slabs = parseSlabs(lines)
|
||||
val initGlobals = parseInitGlobals(lines)
|
||||
@ -104,7 +101,7 @@ class IRFileReader(outputDir: Path, programName: String) {
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseVariables(lines: Iterator<String>): List<StStaticVariable> {
|
||||
private fun parseVariables(lines: Iterator<String>, dontReinitGlobals: Boolean): List<StStaticVariable> {
|
||||
var line = lines.next()
|
||||
while(line.isBlank())
|
||||
line = lines.next()
|
||||
@ -121,11 +118,25 @@ class IRFileReader(outputDir: Path, programName: String) {
|
||||
// ubyte[6] main.start.namestring=105,114,109,101,110,0
|
||||
val match = varPattern.matchEntire(line) ?: throw IRParseException("invalid VARIABLE $line")
|
||||
val (type, arrayspec, name, value, _, zpwish) = match.destructured
|
||||
// TODO what to do with 'value' ??
|
||||
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
|
||||
val dt: DataType = parseDatatype(type, arraysize!=null)
|
||||
val zp = if(zpwish.isBlank()) ZeropageWish.DONTCARE else ZeropageWish.valueOf(zpwish)
|
||||
variables.add(StStaticVariable(name, dt, null, null, null, arraysize, zp, Position.DUMMY))
|
||||
var initNumeric: Double? = null
|
||||
var initArray: StArray? = null
|
||||
when(dt) {
|
||||
in NumericDatatypes -> {
|
||||
if(dontReinitGlobals) {
|
||||
// we need to specify a one time initialization value
|
||||
initNumeric = value.toDouble()
|
||||
}
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
initArray = value.split(',').map { StArrayElement(it.toDouble(), null) }
|
||||
}
|
||||
DataType.STR -> throw IRParseException("STR should have been converted to byte array")
|
||||
else -> throw IRParseException("weird dt")
|
||||
}
|
||||
variables.add(StStaticVariable(name, dt, initNumeric, null, initArray, arraysize, zp, Position.DUMMY))
|
||||
}
|
||||
return variables
|
||||
}
|
||||
@ -204,8 +215,12 @@ class IRFileReader(outputDir: Path, programName: String) {
|
||||
line = lines.next()
|
||||
if(line!="<INITGLOBALS>")
|
||||
throw IRParseException("invalid INITGLOBALS")
|
||||
val chunk = parseCodeChunk(lines.next(), lines)!!
|
||||
line = lines.next()
|
||||
var chunk = IRCodeChunk(Position.DUMMY)
|
||||
if(line=="<CODE>") {
|
||||
chunk = parseCodeChunk(line, lines)!!
|
||||
line = lines.next()
|
||||
}
|
||||
if(line!="</INITGLOBALS>")
|
||||
throw IRParseException("missing INITGLOBALS close tag")
|
||||
return chunk
|
||||
@ -322,12 +337,24 @@ class IRFileReader(outputDir: Path, programName: String) {
|
||||
}
|
||||
val chunk = IRCodeChunk(Position.DUMMY)
|
||||
while(true) {
|
||||
val line = lines.next()
|
||||
var line = lines.next()
|
||||
if (line == "</CODE>")
|
||||
return chunk
|
||||
if (line.isBlank() || line.startsWith(';'))
|
||||
continue
|
||||
chunk += parseCodeLine(line)
|
||||
if(line=="<BYTES>") {
|
||||
val bytes = mutableListOf<Byte>()
|
||||
line = lines.next()
|
||||
while(line!="</BYTES>") {
|
||||
line.trimEnd().windowed(size=2, step=2) {
|
||||
bytes.add(it.toString().toByte(16))
|
||||
}
|
||||
line = lines.next()
|
||||
}
|
||||
chunk += IRCodeInlineBinary(bytes.toByteArray())
|
||||
} else {
|
||||
chunk += parseCodeLine(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -341,9 +368,6 @@ class IRFileReader(outputDir: Path, programName: String) {
|
||||
|
||||
// it's an instruction.
|
||||
val (_, instr, typestr, rest) = match.groupValues
|
||||
if(instr=="incbin") {
|
||||
TODO("incbin")
|
||||
}
|
||||
val opcode = try {
|
||||
Opcode.valueOf(instr.uppercase())
|
||||
} catch (ax: IllegalArgumentException) {
|
||||
|
@ -8,9 +8,6 @@ import kotlin.io.path.bufferedWriter
|
||||
import kotlin.io.path.div
|
||||
|
||||
|
||||
// TODO incbins
|
||||
|
||||
|
||||
class IRFileWriter(private val irProgram: IRProgram) {
|
||||
private val outfile = irProgram.options.outputDir / ("${irProgram.name}.p8ir")
|
||||
private val out = outfile.bufferedWriter()
|
||||
@ -21,12 +18,14 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
||||
writeOptions()
|
||||
writeVariableAllocations()
|
||||
|
||||
out.write("\n<INITGLOBALS>\n")
|
||||
if(!irProgram.options.dontReinitGlobals) {
|
||||
out.write("<CODE>\n")
|
||||
// note: this a block of code that loads values and stores them into the global variables to reset their values.
|
||||
out.write("\n<INITGLOBALS>\n<CODE>\n")
|
||||
irProgram.globalInits.forEach { out.writeLine(it) }
|
||||
out.write("</CODE>\n</INITGLOBALS>\n")
|
||||
out.write("</CODE>\n")
|
||||
}
|
||||
out.write("</INITGLOBALS>\n")
|
||||
writeBlocks()
|
||||
out.write("</PROGRAM>\n")
|
||||
out.close()
|
||||
@ -91,9 +90,9 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
||||
out.write("\n<VARIABLES>\n")
|
||||
for (variable in irProgram.st.allVariables) {
|
||||
val typeStr = getTypeString(variable)
|
||||
val value = when(variable.dt) {
|
||||
val value: String = when(variable.dt) {
|
||||
DataType.FLOAT -> (variable.onetimeInitializationNumericValue ?: 0.0).toString()
|
||||
in NumericDatatypes -> (variable.onetimeInitializationNumericValue ?: 0)
|
||||
in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt()?.toString() ?: "0")
|
||||
DataType.STR -> {
|
||||
val encoded = irProgram.encoding.encodeString(variable.onetimeInitializationStringValue!!.first, variable.onetimeInitializationStringValue!!.second) + listOf(0u)
|
||||
encoded.joinToString(",") { it.toInt().toString() }
|
||||
@ -171,12 +170,13 @@ class IRFileWriter(private val irProgram: IRProgram) {
|
||||
}
|
||||
is IRCodeLabel -> write("_${line.name}:\n")
|
||||
is IRCodeInlineBinary -> {
|
||||
write("incbin \"${line.file}\"")
|
||||
if(line.offset!=null)
|
||||
write(",${line.offset}")
|
||||
if(line.length!=null)
|
||||
write(",${line.length}")
|
||||
write("\n")
|
||||
write("<BYTES>\n")
|
||||
line.data.withIndex().forEach {(index, byte) ->
|
||||
write(byte.toString(16).padStart(2,'0'))
|
||||
if(index and 63 == 63 && index < line.data.size-1)
|
||||
write("\n")
|
||||
}
|
||||
write("\n</BYTES>\n")
|
||||
}
|
||||
else -> throw AssemblyError("invalid vm code line")
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ import prog8.code.core.CompilationOptions
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.IStringEncoding
|
||||
import prog8.code.core.Position
|
||||
import java.nio.file.Path
|
||||
|
||||
/*
|
||||
|
||||
@ -158,7 +157,7 @@ class IRCodeLabel(val name: String): IRCodeLine()
|
||||
|
||||
class IRCodeComment(val comment: String): IRCodeLine()
|
||||
|
||||
class IRCodeInlineBinary(val file: Path, val offset: UInt?, val length: UInt?): IRCodeLine()
|
||||
class IRCodeInlineBinary(val data: ByteArray): IRCodeLine()
|
||||
|
||||
abstract class IRCodeChunkBase(val position: Position) {
|
||||
val lines = mutableListOf<IRCodeLine>()
|
||||
|
Loading…
x
Reference in New Issue
Block a user