Skip to content

Commit 4ace5f0

Browse files
authored
Merge pull request #247 from boriel/bugfix/letsubstr_memleak
Fix error with LETSUBSTR
2 parents cc1708f + 12656fa commit 4ace5f0

26 files changed

Lines changed: 3300 additions & 1372 deletions

api/check.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,6 +411,12 @@ def is_block_accessed(block):
411411
return False
412412

413413

414+
def is_temporary_value(node) -> bool:
415+
""" Returns if the AST node value is a variable or a temporary copy in the heap.
416+
"""
417+
return node.token not in ('STRING', 'VAR') and node.t[0] not in ('_', '#')
418+
419+
414420
def common_type(a, b):
415421
""" Returns a type which is common for both a and b types.
416422
Returns None if no common types allowed.

arch/zx48k/translator.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,12 @@ def visit_LETARRAY(self, node):
314314

315315
def visit_LETSUBSTR(self, node):
316316
yield node.children[3]
317-
self.ic_param(TYPE.string, node.children[3].t)
318317

319-
if node.children[3].token != 'STRING' and (node.children[3].token != 'VAR' or
320-
node.children[3].mangled[0] != '_'):
321-
self.ic_param(TYPE.ubyte, 1) # If the argument is not a variable, it must be freed
318+
if check.is_temporary_value(node.children[3]):
319+
self.ic_param(TYPE.string, node.children[3].t)
320+
self.ic_param(TYPE.ubyte, 1)
322321
else:
322+
self.ic_param(gl.PTR_TYPE, node.children[3].t)
323323
self.ic_param(TYPE.ubyte, 0)
324324

325325
yield node.children[1]
@@ -338,6 +338,7 @@ def visit_LETARRAYSUBSTR(self, node):
338338
yield expr
339339
self.ic_param(TYPE.string, expr.t)
340340

341+
# TODO: this produces a memory leak
341342
if expr.token != 'STRING' and (expr.token != 'VAR' or expr.mangled[0] != '_'):
342343
self.ic_param(TYPE.ubyte, 1) # If the argument is not a variable, it must be freed
343344
else:

library-asm/letsubstr.asm

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ __LETSUBSTR:
1616
LOCAL __CONT1
1717
LOCAL __CONT2
1818
LOCAL __FREE_STR
19-
LOCAL __FREE_STR0
2019

2120
exx
2221
pop hl ; Return address
@@ -32,10 +31,11 @@ __LETSUBSTR:
3231
exx
3332
push hl ; push ret addr back
3433
exx
34+
push de ; B$ addr to be freed upon return (if A != 0)
3535

3636
ld a, h
3737
or l
38-
jp z, __FREE_STR0 ; Return if null
38+
jp z, __FREE_STR ; Return if null
3939
4040
ld c, (hl)
4141
inc hl
@@ -46,21 +46,21 @@ __LETSUBSTR:
4646
exx
4747
ex de, hl
4848
or a
49-
sbc hl, bc ; HL = Length of string requester by user
49+
sbc hl, bc ; HL = Length of string requested by user
5050
inc hl ; len (a$(p0 TO p1)) = p1 - p0 + 1
5151
ex de, hl ; Saves it in DE
5252

5353
pop hl ; HL = String length
5454
exx
55-
jp c, __FREE_STR0 ; Return if greather
56-
exx ; Return if p0 > p1
55+
jp c, __FREE_STR ; Return if p0 > p1
56+
exx
5757

5858
or a
5959
sbc hl, bc ; P0 >= String length?
6060
exx
6161

62-
jp z, __FREE_STR0 ; Return if equal
63-
jp c, __FREE_STR0 ; Return if greather
62+
jp z, __FREE_STR ; Return if equal
63+
jp c, __FREE_STR ; Return if greater
6464

6565
exx
6666
add hl, bc ; Add it back
@@ -72,7 +72,7 @@ __LETSUBSTR:
7272
ld d, h
7373
ld e, l ; Truncate length of substring to fit within the strlen
7474
75-
__CONT0: ; At this point DE = Length of subtring to copy
75+
__CONT0: ; At this point DE = Length of substring to copy
7676
; BC = start of char to copy
7777
push de
7878

@@ -143,15 +143,10 @@ __CONT1:
143143
pop de
144144
ldir ; Copy b$ into a$(x to y)
145145

146-
exx
147-
ex de, hl
148-
149-
__FREE_STR0:
150-
ex de, hl
151-
152146
__FREE_STR:
147+
pop hl
153148
ex af, af'
154-
or a ; If not 0, free
149+
or a ; If not 0, free
155150
jp nz, __MEM_FREE
156151
ret
157152

0 commit comments

Comments
 (0)