diff --git a/il65/codegen.py b/il65/codegen.py index 3937d9c7b..1699e4a5c 100644 --- a/il65/codegen.py +++ b/il65/codegen.py @@ -6,6 +6,7 @@ Written by Irmen de Jong (irmen@razorvine.net) License: GNU GPL 3.0, see LICENSE """ +import sys import io import math import datetime @@ -435,7 +436,9 @@ class CodeGenerator: raise NotImplementedError("decr by > 1") # XXX def generate_call(self, stmt: ParseResult.CallStmt) -> None: - # the argument assignments have already been generated via separate assignment statements. + def generate_param_assignments(): + for assign_stmt in stmt.desugared_call_arguments: + self.generate_assignment(assign_stmt) if stmt.target.name: symblock, targetdef = self.cur_block.lookup(stmt.target.name) else: @@ -451,9 +454,10 @@ class CodeGenerator: return clobbered = set() # type: Set[str] if targetdef.clobbered_registers: - if stmt.preserve_regs: # @todo make this work with the separate assignment statements for the parameters.. :( + if stmt.preserve_regs: clobbered = targetdef.clobbered_registers with self.preserving_registers(clobbered): + generate_param_assignments() self.p("\t\tjsr " + targetstr) return if isinstance(stmt.target, ParseResult.IndirectValue): @@ -471,6 +475,7 @@ class CodeGenerator: raise CodeError("missing name", stmt.target.value) if stmt.is_goto: # no need to preserve registers for a goto + generate_param_assignments() if targetstr in REGISTER_WORDS: self.p("\t\tst{:s} {:s}".format(targetstr[0].lower(), Parser.to_hex(Zeropage.SCRATCH_B1))) self.p("\t\tst{:s} {:s}".format(targetstr[1].lower(), Parser.to_hex(Zeropage.SCRATCH_B2))) @@ -480,6 +485,7 @@ class CodeGenerator: else: preserve_regs = {'A', 'X', 'Y'} if stmt.preserve_regs else set() with self.preserving_registers(preserve_regs): + generate_param_assignments() if targetstr in REGISTER_WORDS: if stmt.preserve_regs: # cannot use zp scratch. This is very inefficient code! @@ -515,10 +521,13 @@ class CodeGenerator: else: raise CodeError("missing name", stmt.target) if stmt.is_goto: + # no need to preserve registers for a goto + generate_param_assignments() self.p("\t\tjmp " + targetstr) else: preserve_regs = {'A', 'X', 'Y'} if stmt.preserve_regs else set() with self.preserving_registers(preserve_regs): + generate_param_assignments() self.p("\t\tjsr " + targetstr) def generate_assignment(self, stmt: ParseResult.AssignmentStmt) -> None: @@ -949,6 +958,9 @@ class Assembler64Tass: print("\ncreating C-64 .prg") elif self.format == ProgramFormat.RAW: print("\ncreating raw binary") - subprocess.check_call(args) + try: + subprocess.check_call(args) + except FileNotFoundError as x: + raise SystemExit("ERROR: cannot run assembler program: "+str(x)) except subprocess.CalledProcessError as x: print("assembler failed with returncode", x.returncode) diff --git a/il65/main.py b/il65/main.py index 387366453..81db760fc 100644 --- a/il65/main.py +++ b/il65/main.py @@ -8,6 +8,7 @@ Written by Irmen de Jong (irmen@razorvine.net) License: GNU GPL 3.0, see LICENSE """ +import time import os import argparse from .parse import Parser, Optimizer @@ -31,6 +32,7 @@ def main() -> None: print("\n" + description) + start = time.perf_counter() pp = PreprocessingParser(args.sourcefile) sourcelines, symbols = pp.preprocess() symbols.print_table(True) @@ -50,5 +52,7 @@ def main() -> None: cg.write_assembly(out) assembler = Assembler64Tass(parsed.format) assembler.assemble(assembly_filename, program_filename) + duration_total = time.perf_counter() - start + print("Compile duration: {:.2f} seconds".format(duration_total)) print("Output file: ", program_filename) print() diff --git a/il65/parse.py b/il65/parse.py index 45cf605bd..8c9930346 100644 --- a/il65/parse.py +++ b/il65/parse.py @@ -406,18 +406,16 @@ class ParseResult: self.arguments = arguments self.is_goto = is_goto self.preserve_regs = preserve_regs + self.desugared_call_arguments = [] # type: List[ParseResult.AssignmentStmt] - def desugar_call_arguments(self, parser: 'Parser') -> List['ParseResult._AstNode']: - if not self.arguments: - return [self] - statements = [] # type: List[ParseResult._AstNode] - for name, value in self.arguments: - assert name is not None, "all call arguments should have a name or be matched on a named parameter" - assignment = parser.parse_assignment("{:s}={:s}".format(name, value)) - assignment.lineno = self.lineno - statements.append(assignment) - statements.append(self) - return statements + def desugar_call_arguments(self, parser: 'Parser') -> None: + if self.arguments: + self.desugared_call_arguments.clear() + for name, value in self.arguments: + assert name is not None, "all call arguments should have a name or be matched on a named parameter" + assignment = parser.parse_assignment("{:s}={:s}".format(name, value)) + assignment.lineno = self.lineno + self.desugared_call_arguments.append(assignment) class InlineAsm(_AstNode): def __init__(self, lineno: int, asmlines: List[str]) -> None: @@ -571,11 +569,7 @@ class Parser: if isinstance(stmt, ParseResult.CallStmt): self.sourceref.line = stmt.lineno self.sourceref.column = 0 - statements = stmt.desugar_call_arguments(self) - if len(statements) == 1: - block.statements[index] = statements[0] - else: - block.statements[index] = statements # type: ignore + stmt.desugar_call_arguments(self) block.flatten_statement_list() # desugar immediate string value assignments for index, stmt in enumerate(list(block.statements)): @@ -1034,7 +1028,10 @@ class Parser: and not isinstance(target.value, (ParseResult.IntegerValue, ParseResult.RegisterValue, ParseResult.MemMappedValue)): raise self.PError("cannot call that type of indirect symbol") address = target.address if isinstance(target, ParseResult.MemMappedValue) else None - _, symbol = self.lookup(targetstr) + try: + _, symbol = self.lookup(targetstr) + except ParseError: + symbol = None # it's probably a number or a register then if isinstance(symbol, SubroutineDef): # verify subroutine arguments if len(arguments or []) != len(symbol.parameters): diff --git a/testsource/floats.ill b/testsource/floats.ill index 2db5298ee..ff4744392 100644 --- a/testsource/floats.ill +++ b/testsource/floats.ill @@ -135,5 +135,34 @@ start c64.MOVFM!(#c64.FL_FR4) c64.FPRINTLN!() +reg_to_float + c64.CHROUT!(13) + + A=34 + X=99 + Y=121 + + my_float = A + c64.MOVFM(#my_float) + c64.FPRINTLN() + + my_float = X + c64.MOVFM(#my_float) + c64.FPRINTLN() + + my_float = Y + c64.MOVFM(#my_float) + c64.FPRINTLN() + + XY = 56789 + ;my_float = XY ; @todo support + c64.MOVFM(#my_float) + c64.FPRINTLN() + + AX = 33221 + ;my_float = AX ; @todo support + c64.MOVFM(#my_float) + c64.FPRINTLN() + return }