Skip to content

Commit e4f7650

Browse files
committed
Implements LBOUND / UBOUND in Local arrays
1 parent a25fcd6 commit e4f7650

5 files changed

Lines changed: 135 additions & 15 deletions

File tree

arch/zx48k/backend/__init__.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -584,16 +584,29 @@ def _larrd(ins):
584584
- 1st param is offset of the local variable.
585585
- 2nd param is a list of bytes in hexadecimal corresponding to the index table
586586
- 3rd param is the size of elements in byte
587-
- 4rd param a list (might be empty) of byte to initialize the array with
587+
- 4th param is a list (might be empty) of byte to initialize the array with
588+
- 5th param is a list (might be empty or 2 elements) of [lbound, ubound] labels.
588589
"""
589590
output = []
590591

591592
label = tmp_label()
592593
offset = int(ins.quad[1])
593594
elements_size = ins.quad[3]
594595
AT_END.extend(_vard(Quad('vard', label, ins.quad[2])))
595-
must_initialize = ins.quad[4] != '[]'
596596

597+
bounds = eval(ins.quad[5])
598+
if not isinstance(bounds, list) or len(bounds) not in (0, 2):
599+
raise InvalidIC(ins.quad, 'Bounds list length must be 0 or 2, not %s' % ins.quad[5])
600+
601+
if bounds:
602+
output.extend([
603+
'ld hl, %s' % bounds[1],
604+
'push hl',
605+
'ld hl, %s' % bounds[0],
606+
'push hl',
607+
])
608+
609+
must_initialize = ins.quad[4] != '[]'
597610
if must_initialize:
598611
label2 = tmp_label()
599612
AT_END.extend(_vard(Quad('vard', label2, ins.quad[4])))
@@ -608,10 +621,11 @@ def _larrd(ins):
608621
'ld bc, %s' % elements_size,
609622
])
610623

624+
suffix = '_WITH_BOUNDS' if bounds else ''
611625
if must_initialize:
612-
output.append('call __ALLOC_INITIALIZED_LOCAL_ARRAY')
626+
output.append('call __ALLOC_INITIALIZED_LOCAL_ARRAY' + suffix)
613627
else:
614-
output.append('call __ALLOC_LOCAL_ARRAY')
628+
output.append('call __ALLOC_LOCAL_ARRAY' + suffix)
615629

616630
REQUIRES.add('arrayalloc.asm')
617631
return output
@@ -2137,7 +2151,7 @@ def __str__(self):
21372151
'vard': [2, _vard], # Like the above but with a list of items (chars, bytes or words, hex)
21382152
'lvarx': [3, _lvarx], # Initializes a local variable. lvard X, (list of bytes): Initializes variable at offset X
21392153
'lvard': [2, _lvard], # Initializes a local variable. lvard X, (list of bytes): Initializes variable at offset X
2140-
'larrd': [4, _larrd], # Initializes a local array
2154+
'larrd': [5, _larrd], # Initializes a local array
21412155
'memcopy': [3, _memcopy], # Copies a block of param 3 bytes of memory from param 2 addr to param 1 addr.
21422156

21432157
'bandu8': [3, _band8], # x = A & B

arch/zx48k/translator.py

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from api.errors import InvalidOperatorError
2222
from api.errors import InvalidBuiltinFunctionError
2323
from api.errors import InternalError
24+
from zxbpp import zxbpp
2425

2526
from . import backend
2627
from .backend.__float import _float
@@ -36,6 +37,7 @@
3637
'FunctionTranslator']
3738

3839
JumpTable = namedtuple('JumpTable', ('label', 'addresses'))
40+
LabelledData = namedtuple('LabelledData', ('label', 'data'))
3941

4042

4143
class Translator(TranslatorVisitor):
@@ -1305,7 +1307,9 @@ def visit_LBOUND(self, node):
13051307
elif entry.scope == SCOPE.parameter:
13061308
self.ic_fparam(entry.t, entry.offset)
13071309
elif entry.scope == SCOPE.local:
1308-
self.ic_fparam(entry.t, -entry.offset)
1310+
self.ic_paddr(-entry.offset, entry.t)
1311+
t1 = optemps.new_t()
1312+
self.ic_fparam(gl.PTR_TYPE, t1)
13091313
self.ic_call('__LBOUND', self.TYPE(gl.BOUND_TYPE).size)
13101314
backend.REQUIRES.add('bound.asm')
13111315

@@ -1318,7 +1322,9 @@ def visit_UBOUND(self, node):
13181322
elif entry.scope == SCOPE.parameter:
13191323
self.ic_fparam(entry.t, entry.offset)
13201324
elif entry.scope == SCOPE.local:
1321-
self.ic_fparam(entry.t, -entry.offset)
1325+
self.ic_paddr(-entry.offset, entry.t)
1326+
t1 = optemps.new_t()
1327+
self.ic_fparam(gl.PTR_TYPE, t1)
13221328
self.ic_call('__UBOUND', self.TYPE(gl.BOUND_TYPE).size)
13231329
backend.REQUIRES.add('bound.asm')
13241330

@@ -1364,6 +1370,8 @@ def start(self):
13641370
self.visit(f)
13651371

13661372
def visit_FUNCTION(self, node):
1373+
bound_tables = []
1374+
13671375
self.ic_label(node.mangled)
13681376
if node.convention == CONVENTION.fastcall:
13691377
self.ic_enter('__fastcall__')
@@ -1378,6 +1386,28 @@ def visit_FUNCTION(self, node):
13781386
# return
13791387

13801388
if local_var.class_ == CLASS.array and local_var.scope == SCOPE.local:
1389+
bound_ptrs = [] # Bound tables pointers (empty if not used)
1390+
lbound_label = local_var.mangled + '.__LBOUND__'
1391+
ubound_label = local_var.mangled + '.__UBOUND__'
1392+
1393+
if local_var.lbound_used or local_var.ubound_used:
1394+
bound_ptrs = ['0', '0'] # NULL by default
1395+
if local_var.lbound_used:
1396+
bound_ptrs[0] = lbound_label
1397+
if local_var.ubound_used:
1398+
bound_ptrs[1] = ubound_label
1399+
1400+
if bound_ptrs:
1401+
zxbpp.ID_TABLE.define('__ZXB_USE_LOCAL_ARRAY_WITH_BOUNDS__', lineno=0)
1402+
1403+
if local_var.lbound_used:
1404+
l = ['%04X' % bound.lower for bound in local_var.bounds]
1405+
bound_tables.append(LabelledData(lbound_label, l))
1406+
1407+
if local_var.ubound_used:
1408+
l = ['%04X' % bound.upper for bound in local_var.bounds]
1409+
bound_tables.append(LabelledData(ubound_label, l))
1410+
13811411
l = [len(local_var.bounds) - 1] + [x.count for x in local_var.bounds[1:]] # TODO Check this
13821412
q = []
13831413
for x in l:
@@ -1388,7 +1418,7 @@ def visit_FUNCTION(self, node):
13881418
r = []
13891419
if local_var.default_value is not None:
13901420
r.extend(self.array_default_value(local_var.type_, local_var.default_value))
1391-
self.ic_larrd(local_var.offset, q, local_var.size, r) # Initializes array bounds
1421+
self.ic_larrd(local_var.offset, q, local_var.size, r, bound_ptrs) # Initializes array bounds
13921422
elif local_var.class_ == CLASS.const:
13931423
continue
13941424
else: # Local vars always defaults to 0, so if 0 we do nothing
@@ -1451,6 +1481,9 @@ def visit_FUNCTION(self, node):
14511481
else:
14521482
self.ic_leave(node.params.size)
14531483

1484+
for bound_table in bound_tables:
1485+
self.ic_vard(bound_table.label, bound_table.data)
1486+
14541487
def visit_FUNCDECL(self, node):
14551488
""" Nested scope functions
14561489
"""

arch/zx48k/translatorinstvisitor.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ def ic_jzero(self, type_, t, label: str):
127127
def ic_label(self, label: str):
128128
return self.emit('label', label)
129129

130-
def ic_larrd(self, offset, arg1, size, arg2):
131-
return self.emit('larrd', offset, arg1, size, arg2)
130+
def ic_larrd(self, offset, arg1, size, arg2, bound_ptrs):
131+
return self.emit('larrd', offset, arg1, size, arg2, bound_ptrs)
132132

133133
def ic_le(self, type_, t, t1, t2):
134134
return self.emit('le' + self.TSUFFIX(type_), t, t1, t2)

library-asm/arrayalloc.asm

Lines changed: 77 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,19 +45,92 @@ __ALLOC_LOCAL_ARRAY:
4545
; HL = Offset to be added to IX => HL = IX + HL
4646
; BC = Length of the element area = n.elements * size(element)
4747
; DE = PTR to the index table
48-
; TOP of the stack = PTR to the element area
48+
; [SP + 2] = PTR to the element area
49+
;
4950
; Returns:
50-
; Nothing
51+
; HL = (IX + HL) + 4
5152
; ---------------------------------------------------------------------
5253

5354
__ALLOC_INITIALIZED_LOCAL_ARRAY:
5455
push bc
5556
call __ALLOC_LOCAL_ARRAY
5657
pop bc
57-
pop hl
58-
ex (sp), hl
58+
;; Swaps [SP], [SP + 2]
59+
exx
60+
pop hl ; HL <- RET address
61+
ex (sp), hl ; HL <- Data table, [SP] <- RET address
62+
push hl ; [SP] <- Data table
63+
exx
64+
ex (sp), hl ; HL = Data table, (SP) = (IX + HL + 4) - start of array address lbound
5965
; HL = data table
6066
; BC = length
6167
; DE = new data area
6268
ldir
69+
pop hl ; HL = addr of LBound area if used
70+
ret
71+
72+
73+
#ifdef __ZXB_USE_LOCAL_ARRAY_WITH_BOUNDS__
74+
75+
; ---------------------------------------------------------------------
76+
; __ALLOC_LOCAL_ARRAY_WITH_BOUNDS
77+
; Allocates an array element area in the heap, and clears it filling it
78+
; with 0 bytes. Then sets LBOUND and UBOUND ptrs
79+
;
80+
; Parameters
81+
; HL = Offset to be added to IX => HL = IX + HL
82+
; BC = Length of the element area = n.elements * size(element)
83+
; DE = PTR to the index table
84+
; [SP + 2] PTR to the lbound element area
85+
; [SP + 4] PTR to the ubound element area
86+
;
87+
; Returns:
88+
; HL = (IX + HL) + 8
89+
; ---------------------------------------------------------------------
90+
__ALLOC_LOCAL_ARRAY_WITH_BOUNDS:
91+
call __ALLOC_LOCAL_ARRAY
92+
93+
__ALLOC_LOCAL_ARRAY_WITH_BOUNDS2:
94+
pop bc ;; ret address
95+
pop de ;; lbound
96+
inc hl
97+
ld (hl), e
98+
inc hl
99+
ld (hl), d
100+
pop de
101+
inc hl
102+
ld (hl), e
103+
inc hl
104+
ld (hl), d
105+
push bc
63106
ret
107+
108+
109+
; ---------------------------------------------------------------------
110+
; __ALLOC_INITIALIZED_LOCAL_ARRAY_WITH_BOUNDS
111+
; Allocates an array element area in the heap, and clears it filling it
112+
; with 0 bytes
113+
;
114+
; Parameters
115+
; HL = Offset to be added to IX => HL = IX + HL
116+
; BC = Length of the element area = n.elements * size(element)
117+
; DE = PTR to the index table
118+
; TOP of the stack = PTR to the element area
119+
; [SP + 2] = PTR to the element area
120+
; [SP + 4] = PTR to the lbound element area
121+
; [SP + 6] = PTR to the ubound element area
122+
;
123+
; Returns:
124+
; HL = (IX + HL) + 8
125+
; ---------------------------------------------------------------------
126+
__ALLOC_INITIALIZED_LOCAL_ARRAY_WITH_BOUNDS:
127+
;; Swaps [SP] and [SP + 2]
128+
exx
129+
pop hl ;; Ret address
130+
ex (sp), hl ;; HL <- PTR to Element area, (sp) = Ret address
131+
push hl ;; [SP] = PTR to element area, [SP + 2] = Ret address
132+
exx
133+
call __ALLOC_INITIALIZED_LOCAL_ARRAY
134+
jp __ALLOC_LOCAL_ARRAY_WITH_BOUNDS2
135+
136+
#endif

symbols/vararray.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ def size(self):
5252
def memsize(self):
5353
""" Total array cell + indexes size
5454
"""
55-
return 2 * TYPE.size(gl.PTR_TYPE)
55+
return (2 + (2 if self.lbound_used or self.ubound_used else 0)) * TYPE.size(gl.PTR_TYPE)
5656

5757
@property
5858
def data_label(self):

0 commit comments

Comments
 (0)