added '%ir' to write inline IR code, '%asm' is now only for real 6502 assembly.

(%ir is probably only used in the library modules for the virtual machine target)
This commit is contained in:
Irmen de Jong 2022-09-30 14:05:11 +02:00
parent 94f0f3e966
commit 0d4dd385b8
23 changed files with 137 additions and 80 deletions

View File

@ -96,7 +96,7 @@ class PtBlock(name: String,
}
class PtInlineAssembly(val assembly: String, position: Position) : PtNode(position) {
class PtInlineAssembly(val assembly: String, val isIR: Boolean, position: Position) : PtNode(position) {
override fun printProperties() {}
}

View File

@ -237,7 +237,7 @@ class IRCodeGen(
return chunk
}
is PtConditionalBranch -> translate(node)
is PtInlineAssembly -> IRInlineAsmChunk(node.assembly, node.position)
is PtInlineAssembly -> IRInlineAsmChunk(node.assembly, node.isIR, node.position)
is PtIncludeBinary -> {
val chunk = IRCodeChunk(node.position)
val data = node.file.readBytes()
@ -979,15 +979,18 @@ class IRCodeGen(
vmblock += vmsub
}
is PtAsmSub -> {
val assembly = if(child.children.isEmpty()) "" else (child.children.single() as PtInlineAssembly).assembly
vmblock += IRAsmSubroutine(child.name, child.position, child.address,
val assemblyChild = if(child.children.isEmpty()) null else (child.children.single() as PtInlineAssembly)
vmblock += IRAsmSubroutine(
child.name, child.position, child.address,
child.clobbers,
child.parameters.map { Pair(it.first.type, it.second) }, // note: the name of the asmsub param is not used anymore.
child.returnTypes.zip(child.retvalRegisters),
assembly)
assemblyChild?.isIR==true,
assemblyChild?.assembly ?: ""
)
}
is PtInlineAssembly -> {
vmblock += IRInlineAsmChunk(child.assembly, child.position)
vmblock += IRInlineAsmChunk(child.assembly, child.isIR, child.position)
}
else -> TODO("BLOCK HAS WEIRD CHILD NODE $child")
}

View File

@ -195,7 +195,7 @@ sub str2uword(str string) -> uword {
; -- returns the unsigned word value of the string number argument in AY
; the number may NOT be preceded by a + sign and may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed)
%asm {{
%ir {{
loadm.w r0,conv.str2uword.string
syscall 11
return
@ -206,7 +206,7 @@ sub str2word(str string) -> word {
; -- returns the signed word value of the string number argument in AY
; the number may be preceded by a + or - sign but may NOT contain spaces
; (any non-digit character will terminate the number string that is parsed)
%asm {{
%ir {{
loadm.w r0,conv.str2word.string
syscall 12
return

View File

@ -9,7 +9,7 @@ floats {
sub print_f(float value) {
; ---- prints the floating point value (without a newline).
%asm {{
%ir {{
loadm.f fr0,floats.print_f.value
syscall 25
return
@ -17,7 +17,7 @@ sub print_f(float value) {
}
sub pow(float value, float power) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.pow.value
loadm.f fr1,floats.pow.power
fpow.f fr0,fr1
@ -26,7 +26,7 @@ sub pow(float value, float power) -> float {
}
sub fabs(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.fabs.value
fabs.f fr0,fr0
return
@ -34,7 +34,7 @@ sub fabs(float value) -> float {
}
sub sin(float angle) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.sin.angle
fsin.f fr0,fr0
return
@ -42,7 +42,7 @@ sub sin(float angle) -> float {
}
sub cos(float angle) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.cos.angle
fcos.f fr0,fr0
return
@ -50,7 +50,7 @@ sub cos(float angle) -> float {
}
sub tan(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.tan.value
ftan.f fr0,fr0
return
@ -58,7 +58,7 @@ sub tan(float value) -> float {
}
sub atan(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.atan.value
fatan.f fr0,fr0
return
@ -66,7 +66,7 @@ sub atan(float value) -> float {
}
sub ln(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.ln.value
fln.f fr0,fr0
return
@ -74,7 +74,7 @@ sub ln(float value) -> float {
}
sub log2(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.log2.value
flog.f fr0,fr0
return
@ -82,7 +82,7 @@ sub log2(float value) -> float {
}
sub sqrt(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.sqrt.value
sqrt.f fr0,fr0
return
@ -100,7 +100,7 @@ sub deg(float angle) -> float {
}
sub round(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.round.value
fround.f fr0,fr0
return
@ -108,7 +108,7 @@ sub round(float value) -> float {
}
sub floor(float value) -> float {
%asm {{
%ir {{
loadm.f fr0,floats.floor.value
ffloor.f fr0,fr0
return
@ -117,7 +117,7 @@ sub floor(float value) -> float {
sub ceil(float value) -> float {
; -- ceil: tr = int(f); if tr==f -> return else return tr+1
%asm {{
%ir {{
loadm.f fr0,floats.ceil.value
fceil.f fr0,fr0
return
@ -125,7 +125,7 @@ sub ceil(float value) -> float {
}
sub rndf() -> float {
%asm {{
%ir {{
rnd.f fr0
return
}}

View File

@ -41,7 +41,7 @@ prog8_lib {
; Returns -1 (255), 0 or 1 depending on wether string1 sorts before, equal or after string2.
; Note that you can also directly compare strings and string values with eachother using
; comparison operators ==, < etcetera (it will use strcmp for you under water automatically).
%asm {{
%ir {{
loadm.w r0,prog8_lib.string_compare.st1
loadm.w r1,prog8_lib.string_compare.st2
syscall 29

View File

@ -7,14 +7,14 @@ sys {
sub reset_system() {
; Soft-reset the system back to initial power-on Basic prompt.
%asm {{
%ir {{
syscall 0
}}
}
sub wait(uword jiffies) {
; --- wait approximately the given number of jiffies (1/60th seconds)
%asm {{
%ir {{
loadm.w r0,sys.wait.jiffies
syscall 13
}}
@ -22,7 +22,7 @@ sys {
sub waitvsync() {
; --- busy wait till the next vsync has occurred (approximately), without depending on custom irq handling.
%asm {{
%ir {{
syscall 14
}}
}
@ -61,41 +61,41 @@ sys {
sub exit(ubyte returnvalue) {
; -- immediately exit the program with a return code in the A register
%asm {{
%ir {{
loadm.b r0,sys.exit.returnvalue
syscall 1
}}
}
sub set_carry() {
%asm {{
%ir {{
sec
}}
}
sub clear_carry() {
%asm {{
%ir {{
clc
}}
}
sub gfx_enable(ubyte mode) {
%asm {{
%ir {{
loadm.b r0,sys.gfx_enable.mode
syscall 8
}}
}
sub gfx_clear(ubyte color) {
%asm {{
%ir {{
loadm.b r0,sys.gfx_clear.color
syscall 9
}}
}
sub gfx_plot(uword xx, uword yy, ubyte color) {
%asm {{
%ir {{
loadm.w r0,sys.gfx_plot.xx
loadm.w r1,sys.gfx_plot.yy
loadm.b r2,sys.gfx_plot.color
@ -104,7 +104,7 @@ sys {
}
sub gfx_getpixel(uword xx, uword yy) -> ubyte {
%asm {{
%ir {{
loadm.w r0,sys.gfx_getpixel.xx
loadm.w r1,sys.gfx_getpixel.yy
syscall 30

View File

@ -6,7 +6,7 @@ txt {
sub clear_screen() {
str @shared sequence = "\x1b[2J\x1B[H"
%asm {{
%ir {{
load.w r0,txt.clear_screen.sequence
syscall 3
}}
@ -29,14 +29,14 @@ sub uppercase() {
}
sub chrout(ubyte char) {
%asm {{
%ir {{
loadm.b r0,txt.chrout.char
syscall 2
}}
}
sub print (str text) {
%asm {{
%ir {{
loadm.w r0,txt.print.text
syscall 3
}}
@ -113,7 +113,7 @@ sub print_w (word value) {
sub input_chars (uword buffer) -> ubyte {
; ---- Input a string (max. 80 chars) from the keyboard. Returns length of input. (string is terminated with a 0 byte as well)
; It assumes the keyboard is selected as I/O channel!
%asm {{
%ir {{
loadm.w r0,txt.input_chars.buffer
syscall 6
return

View File

@ -167,8 +167,10 @@ internal class BeforeAsmAstChanger(val program: Program,
if (subroutine.isAsmSubroutine && subroutine.asmAddress==null && !subroutine.hasRtsInAsm(options.compTarget)) {
// make sure the NOT INLINED asm subroutine actually has a rts at the end
// (non-asm routines get a Return statement as needed, above)
val instruction = if(options.compTarget.name==VMTarget.NAME) " return\n" else " rts\n"
mods += IAstModification.InsertLast(InlineAssembly(instruction, Position.DUMMY), subroutine)
mods += if(options.compTarget.name==VMTarget.NAME)
IAstModification.InsertLast(InlineAssembly(" return\n", true, Position.DUMMY), subroutine)
else
IAstModification.InsertLast(InlineAssembly(" rts\n", false, Position.DUMMY), subroutine)
}
}

View File

@ -197,7 +197,7 @@ class IntermediateAstMaker(val program: Program) {
"%asminclude" -> {
val result = loadAsmIncludeFile(directive.args[0].str!!, directive.definingModule.source)
val assembly = result.getOrElse { throw it }
PtInlineAssembly(assembly, directive.position)
PtInlineAssembly(assembly, false, directive.position)
}
else -> {
// other directives don't output any code (but could end up in option flags somewhere else)
@ -252,7 +252,7 @@ class IntermediateAstMaker(val program: Program) {
}
private fun transform(srcNode: InlineAssembly): PtInlineAssembly =
PtInlineAssembly(srcNode.assembly, srcNode.position)
PtInlineAssembly(srcNode.assembly, srcNode.isIR, srcNode.position)
private fun transform(srcJump: Jump): PtJump {
val identifier = if(srcJump.identifier!=null) transform(srcJump.identifier!!) else null
@ -306,13 +306,22 @@ class IntermediateAstMaker(val program: Program) {
sub.parameters.forEach { it.first.parent=sub }
if(srcSub.asmAddress==null) {
var combinedAsm = ""
for (asm in srcSub.statements)
combinedAsm += (asm as InlineAssembly).assembly + "\n"
if(combinedAsm.isNotEmpty())
sub.add(PtInlineAssembly(combinedAsm, srcSub.statements[0].position))
else
sub.add(PtInlineAssembly("", srcSub.position))
var combinedTrueAsm = ""
var combinedIrAsm = ""
for (asm in srcSub.statements) {
asm as InlineAssembly
if(asm.isIR)
combinedIrAsm += asm.assembly + "\n"
else
combinedTrueAsm += asm.assembly + "\n"
}
if(combinedTrueAsm.isNotEmpty())
sub.add(PtInlineAssembly(combinedTrueAsm, false, srcSub.statements[0].position))
if(combinedIrAsm.isNotEmpty())
sub.add(PtInlineAssembly(combinedIrAsm, true, srcSub.statements[0].position))
if(combinedIrAsm.isEmpty() && combinedTrueAsm.isEmpty())
sub.add(PtInlineAssembly("", true, srcSub.position))
}
return sub

View File

@ -17,7 +17,7 @@ class TestVarious: FunSpec({
test("symbol names in inline assembly blocks") {
val names1 = InlineAssembly("""
""", Position.DUMMY).names
""", false, Position.DUMMY).names
names1 shouldBe emptySet()
val names2 = InlineAssembly("""
@ -29,7 +29,7 @@ label2:
; also not these
;; ...or these
// valid words 123456
""", Position.DUMMY).names
""", false, Position.DUMMY).names
names2 shouldBe setOf("label", "lda", "sta", "ea", "value", "label2", "othervalue", "valid", "words")
}

View File

@ -125,6 +125,9 @@ private fun Prog8ANTLRParser.StatementContext.toAst() : Statement {
val asm = inlineasm()?.toAst()
if(asm!=null) return asm
val ir = inlineir()?.toAst()
if(ir!=null) return ir
val branchstmt = branch_stmt()?.toAst()
if(branchstmt!=null) return branchstmt
@ -252,7 +255,12 @@ private fun Prog8ANTLRParser.FunctioncallContext.toAst(): FunctionCallExpression
private fun Prog8ANTLRParser.InlineasmContext.toAst(): InlineAssembly {
val text = INLINEASMBLOCK().text
return InlineAssembly(text.substring(2, text.length-2), toPosition())
return InlineAssembly(text.substring(2, text.length-2), false, toPosition())
}
private fun Prog8ANTLRParser.InlineirContext.toAst(): InlineAssembly {
val text = INLINEASMBLOCK().text
return InlineAssembly(text.substring(2, text.length-2), true, toPosition())
}
private fun Prog8ANTLRParser.ReturnstmtContext.toAst() : Return {

View File

@ -616,14 +616,14 @@ class FunctionCallStatement(override var target: IdentifierReference,
override fun toString() = "FunctionCallStatement(target=$target, pos=$position)"
}
class InlineAssembly(val assembly: String, override val position: Position) : Statement() {
class InlineAssembly(val assembly: String, val isIR: Boolean, override val position: Position) : Statement() {
override lateinit var parent: Node
override fun linkParents(parent: Node) {
this.parent = parent
}
override fun copy() = InlineAssembly(assembly, position)
override fun copy() = InlineAssembly(assembly, isIR, position)
override fun replaceChildNode(node: Node, replacement: Node) = throw FatalAstException("can't replace here")
override fun accept(visitor: IAstVisitor) = visitor.visit(this)

View File

@ -2,6 +2,17 @@
main {
sub start() {
%asm {{
lda #99
rts
}}
%ir {{
nop
loadr r1,r2
return
}}
ubyte @shared @zp var1 = 42
uword @shared @zp var2 = 4242
str @shared name = "irmen"

View File

@ -265,7 +265,7 @@ class IRFileReader {
}
private val blockPattern = Regex("<BLOCK NAME=(.+) ADDRESS=(.+) ALIGN=(.+) POS=(.+)>")
private val inlineAsmPattern = Regex("<INLINEASM POS=(.+)>")
private val inlineAsmPattern = Regex("<INLINEASM IR=(.+) POS=(.+)>")
private val asmsubPattern = Regex("<ASMSUB NAME=(.+) ADDRESS=(.+) CLOBBERS=(.*) RETURNS=(.*) POS=(.+)>")
private val subPattern = Regex("<SUB NAME=(.+) RETURNTYPE=(.+) POS=(.+)>")
private val posPattern = Regex("\\[(.+): line (.+) col (.+)-(.+)\\]")
@ -299,16 +299,17 @@ class IRFileReader {
}
private fun parseInlineAssembly(startline: String, lines: Iterator<String>): IRInlineAsmChunk {
// <INLINEASM POS=[examples/test.p8: line 8 col 6-9]>
// <INLINEASM IR=true POS=[examples/test.p8: line 8 col 6-9]>
val match = inlineAsmPattern.matchEntire(startline) ?: throw IRParseException("invalid INLINEASM")
val pos = parsePosition(match.groupValues[1])
val isIr = match.groupValues[1].toBoolean()
val pos = parsePosition(match.groupValues[2])
val asmlines = mutableListOf<String>()
var line = lines.next()
while(line!="</INLINEASM>") {
asmlines.add(line)
line = lines.next()
}
return IRInlineAsmChunk(asmlines.joinToString("\n"), pos)
return IRInlineAsmChunk(asmlines.joinToString("\n"), isIr, pos)
}
private fun parseAsmSubroutine(startline: String, lines: Iterator<String>): IRAsmSubroutine {
@ -341,12 +342,15 @@ class IRFileReader {
val regsf = parseRegisterOrStatusflag(regstr)
returns.add(Pair(dt, regsf))
}
return IRAsmSubroutine(scopedname,
return IRAsmSubroutine(
scopedname,
parsePosition(pos), if(address=="null") null else address.toUInt(),
clobberRegs.toSet(),
params,
returns,
asm.assembly)
asm.isIR,
asm.assembly
)
}
private fun parseSubroutine(startline: String, lines: Iterator<String>, variables: List<StStaticVariable>): IRSubroutine {

View File

@ -78,7 +78,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
out.write("${dt.toString().lowercase()} $reg\n")
}
out.write("</PARAMS>\n")
out.write("<INLINEASM POS=${it.position}>\n")
out.write("<INLINEASM IR=${it.isIR} POS=${it.position}>\n")
out.write(it.assembly.trimStart('\r', '\n').trimEnd(' ', '\r', '\n'))
out.write("\n</INLINEASM>\n</ASMSUB>\n")
}
@ -87,7 +87,7 @@ class IRFileWriter(private val irProgram: IRProgram, outfileOverride: Path?) {
}
private fun writeInlineAsm(chunk: IRInlineAsmChunk) {
out.write("<INLINEASM POS=${chunk.position}>\n")
out.write("<INLINEASM IR=${chunk.isIR} POS=${chunk.position}>\n")
out.write(chunk.assembly.trimStart('\r', '\n').trimEnd(' ', '\r', '\n'))
out.write("\n</INLINEASM>\n")
}

View File

@ -104,13 +104,16 @@ class IRSubroutine(val name: String,
operator fun plusAssign(chunk: IRCodeChunkBase) { chunks+= chunk }
}
class IRAsmSubroutine(val name: String,
val position: Position,
val address: UInt?,
val clobbers: Set<CpuRegister>,
val parameters: List<Pair<DataType, RegisterOrStatusflag>>,
val returns: List<Pair<DataType, RegisterOrStatusflag>>,
val assembly: String) {
class IRAsmSubroutine(
val name: String,
val position: Position,
val address: UInt?,
val clobbers: Set<CpuRegister>,
val parameters: List<Pair<DataType, RegisterOrStatusflag>>,
val returns: List<Pair<DataType, RegisterOrStatusflag>>,
val isIR: Boolean,
val assembly: String
) {
init {
require('.' in name) { "subroutine name is not scoped: $name" }
require(!name.startsWith("main.main.")) { "subroutine name invalid main prefix: $name" }
@ -146,7 +149,7 @@ class IRCodeChunk(position: Position): IRCodeChunkBase(position) {
}
}
class IRInlineAsmChunk(val assembly: String, position: Position): IRCodeChunkBase(position) {
class IRInlineAsmChunk(val assembly: String, val isIR: Boolean, position: Position): IRCodeChunkBase(position) {
// note: no lines, asm is in the property
override fun isEmpty() = assembly.isBlank()
override fun isNotEmpty() = assembly.isNotBlank()

View File

@ -83,7 +83,7 @@ return
<PARAMS>
uword sys.wait.jiffies
</PARAMS>
<INLINEASM POS=[library:/prog8lib/virtual/syslib.p8: line 17 col 10-13]>
<INLINEASM IR=true POS=[library:/prog8lib/virtual/syslib.p8: line 17 col 10-13]>
loadm.w r0,sys.wait.jiffies
syscall 13
</INLINEASM>

View File

@ -72,6 +72,7 @@ block_statement:
| variabledeclaration
| subroutinedeclaration
| inlineasm
| inlineir
| labeldef
;
@ -88,6 +89,7 @@ statement :
| branch_stmt
| subroutinedeclaration
| inlineasm
| inlineir
| returnstmt
| forloop
| whileloop
@ -229,6 +231,8 @@ literalvalue :
inlineasm : '%asm' INLINEASMBLOCK;
inlineir: '%ir' INLINEASMBLOCK;
inline: 'inline';
subroutine :

View File

@ -12,7 +12,7 @@
<option name="HAS_STRING_ESCAPES" value="true" />
</options>
<keywords keywords="&amp;;-&gt;;@;\$;and;as;asmsub;break;clobbers;do;downto;else;false;for;goto;if;if_cc;if_cs;if_eq;if_mi;if_ne;if_neg;if_nz;if_pl;if_pos;if_vc;if_vs;if_z;in;inline;not;or;repeat;return;romsub;step;sub;to;true;until;when;while;xor;~" ignore_case="false" />
<keywords2 keywords="%address;%asm;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
<keywords2 keywords="%address;%asm;%ir;%asmbinary;%asminclude;%breakpoint;%import;%launcher;%option;%output;%zeropage;%zpreserved;iso:;petscii:;sc:" />
<keywords3 keywords="@requirezp;@shared;@zp;byte;const;float;str;ubyte;uword;bool;void;word" />
<keywords4 keywords="abs;all;any;avg;callfar;callrom;cmp;len;lsb;memory;mkword;msb;peek;peekw;poke;pokew;pop;popw;push;pushw;reverse;rnd;rndw;rol;rol2;ror;ror2;rrestore;rrestorex;rsave;rsavex;sgn;sizeof;sort;sqrt16;swap;|&gt;" />
</highlighting>

View File

@ -25,7 +25,7 @@
<Keywords name="Folders in comment, middle"></Keywords>
<Keywords name="Folders in comment, close"></Keywords>
<Keywords name="Keywords1">void const&#x000D;&#x000A;str&#x000D;&#x000A;byte ubyte bool&#x000D;&#x000A;word uword&#x000D;&#x000A;float&#x000D;&#x000A;zp shared requirezp</Keywords>
<Keywords name="Keywords2">%address&#x000D;&#x000A;%asm&#x000D;&#x000A;%asmbinary&#x000D;&#x000A;%asminclude&#x000D;&#x000A;%breakpoint&#x000D;&#x000A;%import&#x000D;&#x000A;%launcher&#x000D;&#x000A;%option&#x000D;&#x000A;%output&#x000D;&#x000A;%zeropage&#x000D;&#x000A;%zpreserved</Keywords>
<Keywords name="Keywords2">%address&#x000D;&#x000A;%asm&#x000D;&#x000A;%ir&#x000D;&#x000A;%asmbinary&#x000D;&#x000A;%asminclude&#x000D;&#x000A;%breakpoint&#x000D;&#x000A;%import&#x000D;&#x000A;%launcher&#x000D;&#x000A;%option&#x000D;&#x000A;%output&#x000D;&#x000A;%zeropage&#x000D;&#x000A;%zpreserved</Keywords>
<Keywords name="Keywords3">inline sub asmsub romsub&#x000D;&#x000A;clobbers&#x000D;&#x000A;asm&#x000D;&#x000A;if&#x000D;&#x000A;when else&#x000D;&#x000A;if_cc if_cs if_eq if_mi if_neg if_nz if_pl if_pos if_vc if_vs if_z&#x000D;&#x000A;for in step do while repeat&#x000D;&#x000A;break return goto</Keywords>
<Keywords name="Keywords4">abs all any avg callfar callrom cmp len lsb lsl lsr memory mkword msb peek peekw poke pokew push pushw pop popw rsave rsavex rrestore rrestorex reverse rnd rndw rol rol2 ror ror2 sgn sizeof sort sqrt16 swap</Keywords>
<Keywords name="Keywords5">true false&#x000D;&#x000A;not and or xor&#x000D;&#x000A;as to downto |&gt;</Keywords>

View File

@ -36,7 +36,7 @@ syn keyword prog8Operator and or to downto as void
syn match prog8Directive "\(^\|\s\)%\(output\|launcher\|zeropage\)\>"
syn match prog8Directive "\(^\|\s\)%\(zpreserved\|address\|import\|option\)\>"
syn match prog8Directive "\(^\|\s\)%\(asmbinary\|asminclude\|breakpoint\)\>"
syn match prog8Directive "\(^\|\s\)%asm\>"
syn match prog8Directive "\(^\|\s\)%\(asm\|ir\)\>"
syn match prog8Type "\<\%(u\?byte\|u\?word\|float\|str\|bool\)\>"
syn region prog8ArrayType matchgroup=prog8Type

View File

@ -229,12 +229,16 @@ class VmProgramLoader {
program: MutableList<IRInstruction>,
symbolAddresses: MutableMap<String, Int>,
) {
asmChunk.assembly.lineSequence().forEach {
val parsed = parseIRCodeLine(it.trim(), program.size, placeholders)
if(parsed is IRInstruction)
program += parsed
else if(parsed is IRCodeLabel)
symbolAddresses[parsed.name] = program.size
if(asmChunk.isIR) {
asmChunk.assembly.lineSequence().forEach {
val parsed = parseIRCodeLine(it.trim(), program.size, placeholders)
if (parsed is IRInstruction)
program += parsed
else if (parsed is IRCodeLabel)
symbolAddresses[parsed.name] = program.size
}
} else {
throw IRParseException("vm currently does not support real inlined assembly (only IR)': ${asmChunk.position}")
}
}
}

View File

@ -84,7 +84,16 @@ class TestVm: FunSpec( {
test("vm asmbinary not supported") {
val program = IRProgram("test", IRSymbolTable(null), getTestOptions(), VMTarget())
val block = IRBlock("main", null, IRBlock.BlockAlignment.NONE, Position.DUMMY)
val startSub = IRAsmSubroutine("main.asmstart", Position.DUMMY, 0x2000u, emptySet(), emptyList(), emptyList(), "inlined asm here")
val startSub = IRAsmSubroutine(
"main.asmstart",
Position.DUMMY,
0x2000u,
emptySet(),
emptyList(),
emptyList(),
true,
"inlined asm here"
)
block += startSub
program.addBlock(block)
shouldThrowWithMessage<IRParseException>("vm currently does not support asmsubs: main.asmstart") {