mirror of
https://github.com/irmen/prog8.git
synced 2024-11-22 15:33:02 +00:00
ir: write values as hex into p8ir file
This commit is contained in:
parent
e426fc0922
commit
e614e9787a
@ -4,7 +4,10 @@ import prog8.code.StRomSub
|
||||
import prog8.code.StStaticVariable
|
||||
import prog8.code.StSub
|
||||
import prog8.code.ast.*
|
||||
import prog8.code.core.*
|
||||
import prog8.code.core.AssemblyError
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.PassByValueDatatypes
|
||||
import prog8.code.core.SignedDatatypes
|
||||
import prog8.intermediate.*
|
||||
|
||||
|
||||
|
@ -1 +1 @@
|
||||
8.7
|
||||
8.8-dev
|
||||
|
@ -86,7 +86,7 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
|
||||
val existing = subroutine.lookup(listOf(subroutine.name))
|
||||
if (existing != null && existing !== subroutine) {
|
||||
if(existing.parent!==existing.parent)
|
||||
if(existing.parent!==existing.parent) // TODO fix this check
|
||||
nameShadowWarning(subroutine.name, existing.position, subroutine)
|
||||
else
|
||||
nameError(subroutine.name, existing.position, subroutine)
|
||||
@ -122,7 +122,6 @@ internal class AstIdentifiersChecker(private val errors: IErrorReporter,
|
||||
errors.err("can't use a cpu opcode name as a symbol: '${label.name}'", label.position)
|
||||
|
||||
if(label.name in BuiltinFunctions) {
|
||||
// the builtin functions can't be redefined
|
||||
errors.err("builtin function cannot be redefined", label.position)
|
||||
} else {
|
||||
val existing = (label.definingSubroutine ?: label.definingBlock).getAllLabels(label.name)
|
||||
|
@ -508,6 +508,7 @@ logical: ``not`` ``and`` ``or`` ``xor``
|
||||
Unlike most other programming languages, there is no short-circuit or McCarthy evaluation
|
||||
for the logical ``and`` and ``or`` operators. This means that prog8 currently always evaluates
|
||||
all operands from these logical expressions, even when one of them already determines the outcome!
|
||||
If you don't want this to happen, you have to split and nest the if-statements yourself.
|
||||
|
||||
range creation: ``to``
|
||||
Creates a range of values from the LHS value to the RHS value, inclusive.
|
||||
|
@ -3,8 +3,10 @@ TODO
|
||||
|
||||
For next release
|
||||
^^^^^^^^^^^^^^^^
|
||||
- ir: register allocation per data type a specific allocation, so we are certain when a reg is used it's just for one specific datatype
|
||||
- ir: write addresses as hex into p8ir file
|
||||
- AstIdentifiersChecker: fix the subroutine name shadow if-condition (see vardecl check)
|
||||
- 6502 codegen: make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
|
||||
then we can get rid of the instruction lists in the machinedefinitions as well. This is already no problem at all in the IR codegen.
|
||||
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
|
||||
|
||||
...
|
||||
|
||||
@ -20,7 +22,7 @@ Future Things and Ideas
|
||||
^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Compiler:
|
||||
|
||||
- create BSS section in output program and put StStaticVariables in there with bss=true. Don't forget to add init code to zero out everything that was put in bss. If array in bss->only zero ONCE! So requires self-modifying code
|
||||
- AstIdentifiersChecker: can a subroutine really not have the same name as its enclosing block?
|
||||
- ir: mechanism to determine for chunks which registers are getting input values from "outside"
|
||||
- ir: mechanism to determine for chunks which registers are passing values out? (i.e. are used again in another chunk)
|
||||
- ir: peephole opt: renumber registers in chunks to start with 1 again every time (but keep entry values in mind!)
|
||||
@ -33,20 +35,12 @@ Compiler:
|
||||
- createAssemblyAndAssemble(): make it possible to actually get rid of the VarDecl nodes by fixing the rest of the code mentioned there.
|
||||
but probably better to rewrite the 6502 codegen on top of the new Ast.
|
||||
- generate WASM to eventually run prog8 on a browser canvas?
|
||||
- make it possible to use cpu opcodes such as 'nop' as variable names by prefixing all asm vars with something such as ``p8v_``? Or not worth it (most 3 letter opcodes as variables are nonsensical anyway)
|
||||
then we can get rid of the instruction lists in the machinedefinitions as well?
|
||||
- [problematic due to using 64tass:] add a compiler option to not remove unused subroutines. this allows for building library programs. But this won't work with 64tass's .proc ...
|
||||
Perhaps replace all uses of .proc/.pend by .block/.bend will fix that with a compiler flag?
|
||||
But all library code written in asm uses .proc already..... (search/replace when writing the actual asm?)
|
||||
Once new codegen is written that is based on the IR, this point is moot anyway as that will have its own dead code removal.
|
||||
- Zig-like try-based error handling where the V flag could indicate error condition? and/or BRK to jump into monitor on failure? (has to set BRK vector for that)
|
||||
- add special (u)word array type (or modifier?) that puts the array into memory as 2 separate byte-arrays 1 for LSB 1 for MSB -> allows for word arrays of length 256 and faster indexing
|
||||
- ast: don't rewrite by-reference parameter type to uword, but keep the original type (str, array)
|
||||
BUT that makes the handling of these types different between the scope they are defined in, and the
|
||||
scope they get passed in by reference... unless we make str and array types by-reference ALWAYS?
|
||||
BUT that makes simple code accessing them in the declared scope very slow because that then has to always go through
|
||||
the pointer rather than directly referencing the variable symbol in the generated asm....
|
||||
Or maybe make codegen smart to check if it's a subroutine parameter or local declared variable?
|
||||
|
||||
|
||||
Libraries:
|
||||
|
||||
|
@ -1,27 +1,17 @@
|
||||
%import textio
|
||||
%import floats
|
||||
%zeropage basicsafe
|
||||
|
||||
main {
|
||||
ubyte @shared qqq=123
|
||||
|
||||
&uword mapped = $ea31
|
||||
|
||||
sub start() {
|
||||
float f1
|
||||
|
||||
floats.rndseedf(-1.2345)
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.nl()
|
||||
|
||||
floats.rndseedf(1.2345)
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.spc()
|
||||
floats.print_f(floats.rndf())
|
||||
txt.nl()
|
||||
ubyte bb = 99
|
||||
txt.print_ub(bb)
|
||||
txt.print("Hello, world!")
|
||||
uword ww = bb
|
||||
txt.print_uw(bb)
|
||||
txt.print_uw(ww)
|
||||
}
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ class IRFileReader {
|
||||
"zeropage" -> zeropage = ZeropageType.valueOf(value)
|
||||
"loadAddress" -> loadAddress = value.toUInt()
|
||||
"dontReinitGlobals" -> dontReinitGlobals = value.toBoolean()
|
||||
"evalStackBaseAddress" -> evalStackBaseAddress = if(value=="null") null else value.toUInt()
|
||||
"evalStackBaseAddress" -> evalStackBaseAddress = if(value=="null") null else parseIRValue(value).toUInt()
|
||||
"zpReserved" -> {
|
||||
val (start, end) = value.split(',')
|
||||
zpReserved.add(UIntRange(start.toUInt(), end.toUInt()))
|
||||
@ -161,7 +161,7 @@ class IRFileReader {
|
||||
} else {
|
||||
require(dontReinitGlobals)
|
||||
bss = false
|
||||
initNumeric = value.toDouble()
|
||||
initNumeric = parseIRValue(value).toDouble()
|
||||
}
|
||||
}
|
||||
in ArrayDatatypes -> {
|
||||
@ -174,7 +174,7 @@ class IRFileReader {
|
||||
if (it.startsWith('&'))
|
||||
StArrayElement(null, it.drop(1).split('.'))
|
||||
else
|
||||
StArrayElement(it.toDouble(), null)
|
||||
StArrayElement(parseIRValue(it).toDouble(), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -206,7 +206,7 @@ class IRFileReader {
|
||||
val (type, arrayspec, name, address) = match.destructured
|
||||
val arraysize = if(arrayspec.isNotBlank()) arrayspec.substring(1, arrayspec.length-1).toInt() else null
|
||||
val dt: DataType = parseDatatype(type, arraysize!=null)
|
||||
memvars.add(StMemVar(name, dt, address.toUInt(), arraysize, Position.DUMMY))
|
||||
memvars.add(StMemVar(name, dt, parseIRValue(address).toUInt(), arraysize, Position.DUMMY))
|
||||
}
|
||||
return memvars
|
||||
}
|
||||
@ -286,7 +286,7 @@ class IRFileReader {
|
||||
return blocks
|
||||
}
|
||||
|
||||
private val blockPattern = Regex("<BLOCK NAME=(.+) ADDRESS=(.+) ALIGN=(.+) POS=(.+)>")
|
||||
private val blockPattern = Regex("<BLOCK NAME=(.+) ADDRESS=(.*) ALIGN=(.+) POS=(.+)>")
|
||||
private val inlineAsmPattern = Regex("<INLINEASM LABEL=(.*) IR=(.+)>")
|
||||
private val bytesPattern = Regex("<BYTES LABEL=(.*)>")
|
||||
private val asmsubPattern = Regex("<ASMSUB NAME=(.+) ADDRESS=(.+) CLOBBERS=(.*) RETURNS=(.*) POS=(.+)>")
|
||||
@ -299,7 +299,7 @@ class IRFileReader {
|
||||
throw IRParseException("invalid BLOCK")
|
||||
val match = blockPattern.matchEntire(line) ?: throw IRParseException("invalid BLOCK")
|
||||
val (name, address, align, position) = match.destructured
|
||||
val addressNum = if(address=="null") null else address.toUInt()
|
||||
val addressNum = if(address=="null") null else parseIRValue(address).toUInt()
|
||||
val block = IRBlock(name, addressNum, IRBlock.BlockAlignment.valueOf(align), parsePosition(position))
|
||||
while(true) {
|
||||
line = lines.next()
|
||||
@ -367,7 +367,7 @@ class IRFileReader {
|
||||
}
|
||||
return IRAsmSubroutine(
|
||||
scopedname,
|
||||
if(address=="null") null else address.toUInt(),
|
||||
if(address=="null") null else parseIRValue(address).toUInt(),
|
||||
clobberRegs.toSet(),
|
||||
params,
|
||||
returns,
|
||||
|
@ -1,9 +1,6 @@
|
||||
package prog8.intermediate
|
||||
|
||||
import prog8.code.core.ArrayDatatypes
|
||||
import prog8.code.core.DataType
|
||||
import prog8.code.core.InternalCompilerException
|
||||
import prog8.code.core.NumericDatatypes
|
||||
import prog8.code.core.*
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.bufferedWriter
|
||||
import kotlin.io.path.div
|
||||
@ -47,7 +44,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
|
||||
private fun writeBlocks() {
|
||||
irProgram.blocks.forEach { block ->
|
||||
out.write("\n<BLOCK NAME=${block.name} ADDRESS=${block.address} ALIGN=${block.alignment} POS=${block.position}>\n")
|
||||
out.write("\n<BLOCK NAME=${block.name} ADDRESS=${block.address?.toHex()} ALIGN=${block.alignment} POS=${block.position}>\n")
|
||||
block.inlineAssembly.forEach {
|
||||
writeInlineAsm(it)
|
||||
}
|
||||
@ -73,7 +70,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
if(reg.registerOrPair!=null) "${reg.registerOrPair}:${dt.toString().lowercase()}"
|
||||
else "${reg.statusflag}:${dt.toString().lowercase()}"
|
||||
}.joinToString(",")
|
||||
out.write("<ASMSUB NAME=${it.name} ADDRESS=${it.address} CLOBBERS=$clobbers RETURNS=$returns POS=${it.position}>\n")
|
||||
out.write("<ASMSUB NAME=${it.name} ADDRESS=${it.address?.toHex()} CLOBBERS=$clobbers RETURNS=$returns POS=${it.position}>\n")
|
||||
out.write("<PARAMS>\n")
|
||||
it.parameters.forEach { (dt, regOrSf) ->
|
||||
val reg = if(regOrSf.registerOrPair!=null) regOrSf.registerOrPair.toString()
|
||||
@ -126,10 +123,10 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
for(range in irProgram.options.zpReserved) {
|
||||
out.write("zpReserved=${range.first},${range.last}\n")
|
||||
}
|
||||
out.write("loadAddress=${irProgram.options.loadAddress}\n")
|
||||
out.write("loadAddress=${irProgram.options.loadAddress.toHex()}\n")
|
||||
out.write("optimize=${irProgram.options.optimize}\n")
|
||||
out.write("dontReinitGlobals=${irProgram.options.dontReinitGlobals}\n")
|
||||
out.write("evalStackBaseAddress=${irProgram.options.evalStackBaseAddress}\n")
|
||||
out.write("evalStackBaseAddress=${irProgram.options.evalStackBaseAddress?.toHex()}\n")
|
||||
out.write("outputDir=${irProgram.options.outputDir.toAbsolutePath()}\n")
|
||||
// other options not yet useful here?
|
||||
out.write("</OPTIONS>\n")
|
||||
@ -142,7 +139,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
val typeStr = getTypeString(variable)
|
||||
val value: String = when(variable.dt) {
|
||||
DataType.FLOAT -> (variable.onetimeInitializationNumericValue ?: "").toString()
|
||||
in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt() ?: "").toString()
|
||||
in NumericDatatypes -> (variable.onetimeInitializationNumericValue?.toInt()?.toHex() ?: "").toString()
|
||||
DataType.STR -> {
|
||||
val encoded = irProgram.encoding.encodeString(variable.onetimeInitializationStringValue!!.first, variable.onetimeInitializationStringValue!!.second) + listOf(0u)
|
||||
encoded.joinToString(",") { it.toInt().toString() }
|
||||
@ -158,7 +155,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
if(variable.onetimeInitializationArrayValue!==null) {
|
||||
variable.onetimeInitializationArrayValue!!.joinToString(",") {
|
||||
if(it.number!=null)
|
||||
it.number!!.toInt().toString()
|
||||
it.number!!.toInt().toHex()
|
||||
else
|
||||
"&${it.addressOf!!.joinToString(".")}"
|
||||
}
|
||||
@ -175,7 +172,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
|
||||
out.write("\n<MEMORYMAPPEDVARIABLES>\n")
|
||||
for (variable in irProgram.st.allMemMappedVariables()) {
|
||||
val typeStr = getTypeString(variable)
|
||||
out.write("&$typeStr ${variable.name}=${variable.address}\n")
|
||||
out.write("&$typeStr ${variable.name}=${variable.address.toHex()}\n")
|
||||
}
|
||||
out.write("</MEMORYMAPPEDVARIABLES>\n")
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package prog8.intermediate
|
||||
|
||||
import prog8.code.core.toHex
|
||||
|
||||
/*
|
||||
|
||||
Intermediate Representation instructions for the IR Virtual machine.
|
||||
@ -807,7 +809,7 @@ data class IRInstruction(
|
||||
result.add(",")
|
||||
}
|
||||
value?.let {
|
||||
result.add(it.toString())
|
||||
result.add(it.toHex())
|
||||
result.add(",")
|
||||
}
|
||||
fpValue?.let {
|
||||
|
@ -30,7 +30,7 @@ class TestInstructions: FunSpec({
|
||||
ins.reg2 shouldBe null
|
||||
ins.value shouldBe 99
|
||||
ins.labelSymbol shouldBe null
|
||||
ins.toString() shouldBe "bz.b r42,99"
|
||||
ins.toString() shouldBe "bz.b r42,$63"
|
||||
}
|
||||
|
||||
test("with label") {
|
||||
|
Loading…
Reference in New Issue
Block a user