Skip to content

Commit 2650653

Browse files
committed
Translate array code using new scheme
* The new arrays are implemented as 2 pointers (4 bytes). * The 1st one points to the index table * The 2nd one points to the data elements area of the array (HEAP) This allows using array AT addr, and also makes the element table foldable! Also allows dynamic arrays (not implemented yet).
1 parent 2304e7f commit 2650653

1 file changed

Lines changed: 75 additions & 31 deletions

File tree

arch/zx48k/translator.py

Lines changed: 75 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#!/usr/bin/env python
22
# -*- coding: utf-8 -*-
33

4-
import functools
54
from collections import OrderedDict
65
from collections import namedtuple
76

@@ -281,15 +280,18 @@ def traverse_const(node):
281280
syntax_error_cant_convert_to_type(node.lineno, str(node.operand), node.type_)
282281
return
283282

284-
if node.token in ('VAR', 'VARARRAY', 'LABEL', 'FUNCTION'):
283+
if node.token == 'VARARRAY':
284+
return node.data_label
285+
286+
if node.token in ('VAR', 'LABEL', 'FUNCTION'):
285287
# TODO: Check what happens with local vars and params
286288
return node.t
287289

288290
if node.token == 'CONST':
289291
return Translator.traverse_const(node.expr)
290292

291293
if node.token == 'ARRAYACCESS':
292-
return '({} + {})'.format(node.entry.mangled, node.offset)
294+
return '({} + {})'.format(node.entry.data_label, node.offset)
293295

294296
raise InvalidCONSTexpr(node)
295297

@@ -516,36 +518,40 @@ def visit_ARRAYLOAD(self, node):
516518
else:
517519
offset = node.offset
518520
if scope == SCOPE.global_:
519-
self.emit('load' + self.TSUFFIX(node.type_), node.entry.t, '%s + %i' % (node.entry.mangled, offset))
521+
self.emit('load' + self.TSUFFIX(node.type_), node.entry.t, '%s + %i' % (node.entry.t, offset))
520522
elif scope == SCOPE.parameter:
521523
self.emit('pload' + self.TSUFFIX(node.type_), node.t, node.entry.offset - offset)
522524
elif scope == SCOPE.local:
523-
self.emit('pload' + self.TSUFFIX(node.type_), node.t, -(node.entry.offset - offset))
525+
t1 = optemps.new_t()
526+
t2 = optemps.new_t()
527+
t3 = optemps.new_t()
528+
self.emit('pload' + self.TSUFFIX(gl.PTR_TYPE), t1,
529+
-(node.entry.offset - self.TYPE(gl.PTR_TYPE).size))
530+
self.emit('add' + self.TSUFFIX(gl.PTR_TYPE), t2, t1, node.offset)
531+
self.emit('load' + self.TSUFFIX(node.type_), t3, '*$%s' % t2)
524532

525533
def visit_ARRAYCOPY(self, node):
526534
tr = node.children[0]
527535
scope = tr.scope
528-
offset = self.TYPE(gl.SIZE_TYPE).size + self.TYPE(gl.BOUND_TYPE).size * len(tr.bounds)
529536
if scope == SCOPE.global_:
530-
t1 = "#%s + %i" % (tr.mangled, offset)
537+
t1 = "#%s" % tr.data_label
531538
elif scope == SCOPE.parameter:
532-
self.emit('paddr', '%i' % (tr.offset - offset), tr.t)
533-
t1 = tr.t
539+
t1 = optemps.new_t()
540+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t1, '%i' % (tr.offset - self.TYPE(gl.PTR_TYPE).size))
534541
elif scope == SCOPE.local:
535-
self.emit('paddr', '%i' % -(tr.offset - offset), tr.t)
536-
t1 = tr.t
542+
t1 = optemps.new_t()
543+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t1, '%i' % -(tr.offset - self.TYPE(gl.PTR_TYPE).size))
537544

538545
tr = node.children[1]
539546
scope = tr.scope
540-
offset = self.TYPE(gl.SIZE_TYPE).size + self.TYPE(gl.BOUND_TYPE).size * len(tr.bounds)
541547
if scope == SCOPE.global_:
542-
t2 = "#%s + %i" % (tr.mangled, offset)
548+
t2 = "#%s" % tr.data_label
543549
elif scope == SCOPE.parameter:
544-
self.emit('paddr', '%i' % (tr.offset - offset), tr.t)
545-
t2 = tr.t
550+
t2 = optemps.new_t()
551+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t2, '%i' % (tr.offset - self.TYPE(gl.PTR_TYPE).size))
546552
elif scope == SCOPE.local:
547-
self.emit('paddr', '%i' % -(tr.offset - offset), tr.t)
548-
t2 = tr.t
553+
t2 = optemps.new_t()
554+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t2, '%i' % -(tr.offset - self.TYPE(gl.PTR_TYPE).size))
549555

550556
t = optemps.new_t()
551557
if tr.type_ != Type.string:
@@ -575,7 +581,7 @@ def visit_LETARRAY(self, node):
575581
elif scope == SCOPE.local:
576582
self.emit('pastore' + suf, -arr.entry.offset, node.children[1].t)
577583
else:
578-
name = arr.entry.mangled
584+
name = arr.entry.data_label
579585
if scope == SCOPE.global_:
580586
self.emit('store' + suf, '%s + %i' % (name, arr.offset), node.children[1].t)
581587
elif scope == SCOPE.parameter:
@@ -1352,28 +1358,44 @@ def visit_VARDECL(self, node):
13521358

13531359
def visit_ARRAYDECL(self, node):
13541360
entry = node.entry
1361+
assert entry.default_value is None or entry.addr is None, "Cannot use address and default_value at once"
1362+
13551363
if not entry.accessed:
13561364
api.errmsg.warning_not_used(entry.lineno, entry.name)
13571365
if self.O_LEVEL > 1:
13581366
return
13591367

1368+
data_label = entry.data_label
1369+
idx_table_label = backend.tmp_label()
13601370
l = ['%04X' % (len(node.bounds) - 1)] # Number of dimensions - 1
13611371

13621372
for bound in node.bounds[1:]:
13631373
l.append('%04X' % (bound.upper - bound.lower + 1))
13641374

13651375
l.append('%02X' % node.type_.size)
1376+
arr_data = []
13661377

1367-
if entry.default_value is not None:
1368-
l.extend(Translator.array_default_value(node.type_, entry.default_value))
1378+
if entry.addr:
1379+
self.emit('deflabel', data_label, "%s" % entry.addr)
13691380
else:
1370-
l.extend(['00'] * node.size)
1381+
if entry.default_value is not None:
1382+
arr_data = Translator.array_default_value(node.type_, entry.default_value)
1383+
else:
1384+
arr_data = ['00'] * node.size
13711385

13721386
for alias in entry.aliased_by:
13731387
offset = 1 + 2 * entry.count + alias.offset # TODO: Generalize for multi-arch
13741388
self.emit('deflabel', alias.mangled, '%s + %i' % (entry.mangled, offset))
13751389

1376-
self.emit('vard', node.mangled, l)
1390+
self.emit('varx', node.mangled, self.TSUFFIX(gl.PTR_TYPE), [idx_table_label])
1391+
1392+
if entry.addr:
1393+
self.emit('varx', entry.data_ptr_label, self.TSUFFIX(gl.PTR_TYPE), [self.traverse_const(entry.addr)])
1394+
else:
1395+
self.emit('varx', entry.data_ptr_label, self.TSUFFIX(gl.PTR_TYPE), [data_label])
1396+
self.emit('vard', data_label, arr_data)
1397+
1398+
self.emit('vard', idx_table_label, l)
13771399

13781400
if entry.lbound_used:
13791401
l = ['%04X' % len(node.bounds)] + \
@@ -1597,17 +1619,18 @@ def visit_FUNCTION(self, node):
15971619
# if self.O_LEVEL > 1:
15981620
# return
15991621

1600-
if local_var.class_ == CLASS.array:
1622+
if local_var.class_ == CLASS.array and local_var.scope != SCOPE.global_:
16011623
l = [len(local_var.bounds) - 1] + [x.count for x in local_var.bounds[1:]] # TODO Check this
16021624
q = []
16031625
for x in l:
16041626
q.append('%02X' % (x & 0xFF))
16051627
q.append('%02X' % (x >> 8))
16061628

16071629
q.append('%02X' % local_var.type_.size)
1630+
r = []
16081631
if local_var.default_value is not None:
1609-
q.extend(self.array_default_value(local_var.type_, local_var.default_value))
1610-
self.emit('lvard', local_var.offset, q) # Initializes array bounds
1632+
r.extend(self.array_default_value(local_var.type_, local_var.default_value))
1633+
self.emit('larrd', local_var.offset, q, local_var.size, r) # Initializes array bounds
16111634
elif local_var.class_ == CLASS.const:
16121635
continue
16131636
else: # Local vars always defaults to 0, so if 0 we do nothing
@@ -1628,8 +1651,8 @@ def visit_FUNCTION(self, node):
16281651
# Now free any local string from memory.
16291652
preserve_hl = False
16301653
for local_var in node.local_symbol_table.values():
1654+
scope = local_var.scope
16311655
if local_var.type_ == self.TYPE(TYPE.string): # Only if it's string we free it
1632-
scope = local_var.scope
16331656
if local_var.class_ != CLASS.array: # Ok just free it
16341657
if scope == SCOPE.local or (scope == SCOPE.parameter and not local_var.byref):
16351658
if not preserve_hl:
@@ -1648,14 +1671,35 @@ def visit_FUNCTION(self, node):
16481671
preserve_hl = True
16491672
self.emit('exchg')
16501673

1651-
offset = -local_var.offset if scope == SCOPE.local else local_var.offset
1652-
elems = functools.reduce(lambda x, y: x * y, [x.count for x in local_var.bounds])
1653-
self.emit('param' + self.TSUFFIX(gl.BOUND_TYPE), elems)
1654-
self.emit('paddr', offset, local_var.t)
1655-
self.emit('fparamu16', local_var.t)
1674+
self.emit('param' + self.TSUFFIX(gl.BOUND_TYPE), local_var.count)
1675+
t2 = optemps.new_t()
1676+
if scope == SCOPE.parameter:
1677+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t2,
1678+
'%i' % (local_var.offset - self.TYPE(gl.PTR_TYPE).size))
1679+
elif scope == SCOPE.local:
1680+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t2,
1681+
'%i' % -(local_var.offset - self.TYPE(gl.PTR_TYPE).size))
1682+
self.emit('fparam' + self.TSUFFIX(gl.PTR_TYPE), t2)
16561683
self.emit('call', '__ARRAY_FREE', 0)
16571684
self.REQUIRES.add('arrayfree.asm')
16581685

1686+
if local_var.class_ == CLASS.array and \
1687+
(scope == SCOPE.local or (scope == SCOPE.parameter and not local_var.byref)):
1688+
if not preserve_hl:
1689+
preserve_hl = True
1690+
self.emit('exchg')
1691+
1692+
t2 = optemps.new_t()
1693+
if scope == SCOPE.parameter:
1694+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t2, '%i'
1695+
% (local_var.offset - self.TYPE(gl.PTR_TYPE).size))
1696+
elif scope == SCOPE.local:
1697+
self.emit('pload%s' % self.TSUFFIX(gl.PTR_TYPE), t2, '%i'
1698+
% -(local_var.offset - self.TYPE(gl.PTR_TYPE).size))
1699+
1700+
self.emit('fparam' + self.TSUFFIX(gl.PTR_TYPE), t2)
1701+
self.emit('call', '__MEM_FREE', 0)
1702+
16591703
if preserve_hl:
16601704
self.emit('exchg')
16611705

0 commit comments

Comments
 (0)