mirror of
https://github.com/irmen/prog8.git
synced 2024-11-29 17:50:35 +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
|
License: GNU GPL 3.0, see LICENSE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
import io
|
import io
|
||||||
import math
|
import math
|
||||||
import datetime
|
import datetime
|
||||||
@ -435,7 +436,9 @@ class CodeGenerator:
|
|||||||
raise NotImplementedError("decr by > 1") # XXX
|
raise NotImplementedError("decr by > 1") # XXX
|
||||||
|
|
||||||
def generate_call(self, stmt: ParseResult.CallStmt) -> None:
|
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:
|
if stmt.target.name:
|
||||||
symblock, targetdef = self.cur_block.lookup(stmt.target.name)
|
symblock, targetdef = self.cur_block.lookup(stmt.target.name)
|
||||||
else:
|
else:
|
||||||
@ -451,9 +454,10 @@ class CodeGenerator:
|
|||||||
return
|
return
|
||||||
clobbered = set() # type: Set[str]
|
clobbered = set() # type: Set[str]
|
||||||
if targetdef.clobbered_registers:
|
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
|
clobbered = targetdef.clobbered_registers
|
||||||
with self.preserving_registers(clobbered):
|
with self.preserving_registers(clobbered):
|
||||||
|
generate_param_assignments()
|
||||||
self.p("\t\tjsr " + targetstr)
|
self.p("\t\tjsr " + targetstr)
|
||||||
return
|
return
|
||||||
if isinstance(stmt.target, ParseResult.IndirectValue):
|
if isinstance(stmt.target, ParseResult.IndirectValue):
|
||||||
@ -471,6 +475,7 @@ class CodeGenerator:
|
|||||||
raise CodeError("missing name", stmt.target.value)
|
raise CodeError("missing name", stmt.target.value)
|
||||||
if stmt.is_goto:
|
if stmt.is_goto:
|
||||||
# no need to preserve registers for a goto
|
# no need to preserve registers for a goto
|
||||||
|
generate_param_assignments()
|
||||||
if targetstr in REGISTER_WORDS:
|
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[0].lower(), Parser.to_hex(Zeropage.SCRATCH_B1)))
|
||||||
self.p("\t\tst{:s} {:s}".format(targetstr[1].lower(), Parser.to_hex(Zeropage.SCRATCH_B2)))
|
self.p("\t\tst{:s} {:s}".format(targetstr[1].lower(), Parser.to_hex(Zeropage.SCRATCH_B2)))
|
||||||
@ -480,6 +485,7 @@ class CodeGenerator:
|
|||||||
else:
|
else:
|
||||||
preserve_regs = {'A', 'X', 'Y'} if stmt.preserve_regs else set()
|
preserve_regs = {'A', 'X', 'Y'} if stmt.preserve_regs else set()
|
||||||
with self.preserving_registers(preserve_regs):
|
with self.preserving_registers(preserve_regs):
|
||||||
|
generate_param_assignments()
|
||||||
if targetstr in REGISTER_WORDS:
|
if targetstr in REGISTER_WORDS:
|
||||||
if stmt.preserve_regs:
|
if stmt.preserve_regs:
|
||||||
# cannot use zp scratch. This is very inefficient code!
|
# cannot use zp scratch. This is very inefficient code!
|
||||||
@ -515,10 +521,13 @@ class CodeGenerator:
|
|||||||
else:
|
else:
|
||||||
raise CodeError("missing name", stmt.target)
|
raise CodeError("missing name", stmt.target)
|
||||||
if stmt.is_goto:
|
if stmt.is_goto:
|
||||||
|
# no need to preserve registers for a goto
|
||||||
|
generate_param_assignments()
|
||||||
self.p("\t\tjmp " + targetstr)
|
self.p("\t\tjmp " + targetstr)
|
||||||
else:
|
else:
|
||||||
preserve_regs = {'A', 'X', 'Y'} if stmt.preserve_regs else set()
|
preserve_regs = {'A', 'X', 'Y'} if stmt.preserve_regs else set()
|
||||||
with self.preserving_registers(preserve_regs):
|
with self.preserving_registers(preserve_regs):
|
||||||
|
generate_param_assignments()
|
||||||
self.p("\t\tjsr " + targetstr)
|
self.p("\t\tjsr " + targetstr)
|
||||||
|
|
||||||
def generate_assignment(self, stmt: ParseResult.AssignmentStmt) -> None:
|
def generate_assignment(self, stmt: ParseResult.AssignmentStmt) -> None:
|
||||||
@ -949,6 +958,9 @@ class Assembler64Tass:
|
|||||||
print("\ncreating C-64 .prg")
|
print("\ncreating C-64 .prg")
|
||||||
elif self.format == ProgramFormat.RAW:
|
elif self.format == ProgramFormat.RAW:
|
||||||
print("\ncreating raw binary")
|
print("\ncreating raw binary")
|
||||||
|
try:
|
||||||
subprocess.check_call(args)
|
subprocess.check_call(args)
|
||||||
|
except FileNotFoundError as x:
|
||||||
|
raise SystemExit("ERROR: cannot run assembler program: "+str(x))
|
||||||
except subprocess.CalledProcessError as x:
|
except subprocess.CalledProcessError as x:
|
||||||
print("assembler failed with returncode", x.returncode)
|
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
|
License: GNU GPL 3.0, see LICENSE
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import time
|
||||||
import os
|
import os
|
||||||
import argparse
|
import argparse
|
||||||
from .parse import Parser, Optimizer
|
from .parse import Parser, Optimizer
|
||||||
@ -31,6 +32,7 @@ def main() -> None:
|
|||||||
|
|
||||||
print("\n" + description)
|
print("\n" + description)
|
||||||
|
|
||||||
|
start = time.perf_counter()
|
||||||
pp = PreprocessingParser(args.sourcefile)
|
pp = PreprocessingParser(args.sourcefile)
|
||||||
sourcelines, symbols = pp.preprocess()
|
sourcelines, symbols = pp.preprocess()
|
||||||
symbols.print_table(True)
|
symbols.print_table(True)
|
||||||
@ -50,5 +52,7 @@ def main() -> None:
|
|||||||
cg.write_assembly(out)
|
cg.write_assembly(out)
|
||||||
assembler = Assembler64Tass(parsed.format)
|
assembler = Assembler64Tass(parsed.format)
|
||||||
assembler.assemble(assembly_filename, program_filename)
|
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("Output file: ", program_filename)
|
||||||
print()
|
print()
|
||||||
|
@ -406,18 +406,16 @@ class ParseResult:
|
|||||||
self.arguments = arguments
|
self.arguments = arguments
|
||||||
self.is_goto = is_goto
|
self.is_goto = is_goto
|
||||||
self.preserve_regs = preserve_regs
|
self.preserve_regs = preserve_regs
|
||||||
|
self.desugared_call_arguments = [] # type: List[ParseResult.AssignmentStmt]
|
||||||
|
|
||||||
def desugar_call_arguments(self, parser: 'Parser') -> List['ParseResult._AstNode']:
|
def desugar_call_arguments(self, parser: 'Parser') -> None:
|
||||||
if not self.arguments:
|
if self.arguments:
|
||||||
return [self]
|
self.desugared_call_arguments.clear()
|
||||||
statements = [] # type: List[ParseResult._AstNode]
|
|
||||||
for name, value in self.arguments:
|
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"
|
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 = parser.parse_assignment("{:s}={:s}".format(name, value))
|
||||||
assignment.lineno = self.lineno
|
assignment.lineno = self.lineno
|
||||||
statements.append(assignment)
|
self.desugared_call_arguments.append(assignment)
|
||||||
statements.append(self)
|
|
||||||
return statements
|
|
||||||
|
|
||||||
class InlineAsm(_AstNode):
|
class InlineAsm(_AstNode):
|
||||||
def __init__(self, lineno: int, asmlines: List[str]) -> None:
|
def __init__(self, lineno: int, asmlines: List[str]) -> None:
|
||||||
@ -571,11 +569,7 @@ class Parser:
|
|||||||
if isinstance(stmt, ParseResult.CallStmt):
|
if isinstance(stmt, ParseResult.CallStmt):
|
||||||
self.sourceref.line = stmt.lineno
|
self.sourceref.line = stmt.lineno
|
||||||
self.sourceref.column = 0
|
self.sourceref.column = 0
|
||||||
statements = stmt.desugar_call_arguments(self)
|
stmt.desugar_call_arguments(self)
|
||||||
if len(statements) == 1:
|
|
||||||
block.statements[index] = statements[0]
|
|
||||||
else:
|
|
||||||
block.statements[index] = statements # type: ignore
|
|
||||||
block.flatten_statement_list()
|
block.flatten_statement_list()
|
||||||
# desugar immediate string value assignments
|
# desugar immediate string value assignments
|
||||||
for index, stmt in enumerate(list(block.statements)):
|
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)):
|
and not isinstance(target.value, (ParseResult.IntegerValue, ParseResult.RegisterValue, ParseResult.MemMappedValue)):
|
||||||
raise self.PError("cannot call that type of indirect symbol")
|
raise self.PError("cannot call that type of indirect symbol")
|
||||||
address = target.address if isinstance(target, ParseResult.MemMappedValue) else None
|
address = target.address if isinstance(target, ParseResult.MemMappedValue) else None
|
||||||
|
try:
|
||||||
_, symbol = self.lookup(targetstr)
|
_, symbol = self.lookup(targetstr)
|
||||||
|
except ParseError:
|
||||||
|
symbol = None # it's probably a number or a register then
|
||||||
if isinstance(symbol, SubroutineDef):
|
if isinstance(symbol, SubroutineDef):
|
||||||
# verify subroutine arguments
|
# verify subroutine arguments
|
||||||
if len(arguments or []) != len(symbol.parameters):
|
if len(arguments or []) != len(symbol.parameters):
|
||||||
|
@ -135,5 +135,34 @@ start
|
|||||||
c64.MOVFM!(#c64.FL_FR4)
|
c64.MOVFM!(#c64.FL_FR4)
|
||||||
c64.FPRINTLN!()
|
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
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user