mirror of
https://github.com/irmen/prog8.git
synced 2024-12-24 01:29:28 +00:00
fix call parameters to be inside reg preserve logic
This commit is contained in:
parent
4025d44b74
commit
d0f5a9789b
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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):
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user