Fixed up memlib.c65 and added errors to POKEW and PEEKW if using the same variable for pointer and value.
This commit is contained in:
parent
4971da9978
commit
23a721217d
3 changed files with 121 additions and 248 deletions
|
|
@ -197,6 +197,11 @@ func (c *PeekWCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
|||
}
|
||||
c.destVarName = destSym.FullName()
|
||||
|
||||
// Check for self-referential PEEKW (reading through a pointer into itself)
|
||||
if c.isZPPointer && c.addrVarName == c.destVarName {
|
||||
return fmt.Errorf("PEEKW: cannot read through pointer %q into itself (would corrupt pointer during read)", c.destVarName)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ func (c *PokeWCommand) Interpret(line preproc.Line, ctx *compiler.CompilerContex
|
|||
c.isValueVar = false
|
||||
}
|
||||
|
||||
// Check for self-referential POKEW (writing pointer through itself)
|
||||
if c.isZPPointer && c.isValueVar && c.addrVarName == c.valueVarName {
|
||||
return fmt.Errorf("POKEW: writing pointer %q through itself - pointer is both address and value", c.valueVarName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
358
lib/memlib.c65
358
lib/memlib.c65
|
|
@ -4,48 +4,34 @@
|
|||
//
|
||||
//
|
||||
// Author: Mattias Hansson
|
||||
// Copyright (c) : 2000-2005 Mattias Hansson
|
||||
// Copyright (c) : 2000-2025 Mattias Hansson
|
||||
// License: GNU LGPL 2
|
||||
// Language: 65CM v0.4+
|
||||
// Dependencies:
|
||||
// Target: generic 6502
|
||||
//
|
||||
// Purpose: Provide some functions the help to create, update and access
|
||||
// a linked list of strings.
|
||||
// Purpose: Dynamic memory allocation using free list
|
||||
//
|
||||
// Modernized with:
|
||||
// - Free list algorithm
|
||||
// - ZP pointer for array-style access
|
||||
//-----------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Internals:
|
||||
//
|
||||
// Makes heap-handling in a defined part of the memory.
|
||||
// Free list memory allocator.
|
||||
//
|
||||
// Requested memory is placed "from bottom upwards".
|
||||
// Allocation entries are written from the top downwards.
|
||||
// Block structure:
|
||||
// - Free blocks: [size:WORD][next:WORD][...free space...]
|
||||
// - Allocated blocks: [size:WORD][...user data...]
|
||||
//
|
||||
// layout:
|
||||
// User receives pointer to data area (block + 2).
|
||||
// Size field includes 2-byte header.
|
||||
//
|
||||
// Bottom ( e.g. $2000-$2fff )
|
||||
// --------------
|
||||
// $2000
|
||||
// .
|
||||
// . area 1 allocated by application
|
||||
// .
|
||||
// $2020
|
||||
// $2021
|
||||
// .
|
||||
// . area 2 allocated by application
|
||||
// .
|
||||
// $2025
|
||||
//
|
||||
// .
|
||||
// .
|
||||
// .
|
||||
//
|
||||
// $2ff8 + $2ff9 = $2025 end of area 2
|
||||
// $2ffa + $2ffb = $2021 start of area 2
|
||||
// $2ffc + $2ffd = $2020 end of area 1
|
||||
// $2ffe + $2fff = $2000 start of area 1
|
||||
// ZP usage (can be overridden):
|
||||
// - $fa-$fb: current block pointer
|
||||
//-----------------------------------------------------------
|
||||
|
||||
#IFNDEF __LIB_MEM
|
||||
#DEFINE __LIB_MEM = 1
|
||||
|
|
@ -60,245 +46,123 @@
|
|||
#DEFINE __LIB_MEM_END = $$9fff
|
||||
#IFEND
|
||||
|
||||
#IFNDEF __LIB_MEM_ZP_CURRENT
|
||||
#DEFINE __LIB_MEM_ZP_CURRENT = $$fa
|
||||
#IFEND
|
||||
|
||||
#IFNDEF NULL
|
||||
#DEFINE NULL = 0
|
||||
#IFEND
|
||||
|
||||
GOTO lib_memlib_skip
|
||||
|
||||
WORD CONST lib_memstart = __LIB_MEM_START
|
||||
WORD CONST lib_memend = __LIB_MEM_END
|
||||
|
||||
WORD lib_alloctable_end
|
||||
WORD lib_memlib_current
|
||||
WORD lib_memlib_free_head
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Init: sets upp things for the lib in mem before start
|
||||
// Init: Initialize heap with one large free block
|
||||
//-----------------------------------------------------------
|
||||
FUNC lib_mem_init
|
||||
WORD current @ __LIB_MEM_ZP_CURRENT
|
||||
WORD CONST memstart = __LIB_MEM_START
|
||||
WORD CONST memend = __LIB_MEM_END
|
||||
|
||||
//set allocation table end start value
|
||||
LET lib_alloctable_end GET lib_memend
|
||||
INC lib_alloctable_end
|
||||
lib_memlib_free_head = memstart
|
||||
lib_memlib_current = memstart
|
||||
current = lib_memlib_current
|
||||
|
||||
WORD CONST total_size = memend-memstart+1
|
||||
|
||||
POKEW current[0] , total_size
|
||||
POKEW current[2] , NULL
|
||||
FEND
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Malloc: Allocate memory block
|
||||
// Returns pointer to user data area or NULL if no space
|
||||
//-----------------------------------------------------------
|
||||
FUNC lib_mem_malloc({WORD size_t} out:{WORD result})
|
||||
WORD current @ __LIB_MEM_ZP_CURRENT
|
||||
WORD prev
|
||||
WORD block_size
|
||||
WORD needed_size
|
||||
WORD remaining
|
||||
WORD next_free
|
||||
WORD split_addr
|
||||
WORD alloc_addr
|
||||
|
||||
result = NULL
|
||||
|
||||
IF size_t = 0
|
||||
EXIT
|
||||
ENDIF
|
||||
|
||||
needed_size = size_t + 2
|
||||
|
||||
current = lib_memlib_free_head
|
||||
prev = NULL
|
||||
|
||||
WHILE current != NULL
|
||||
block_size = PEEKW current[0]
|
||||
|
||||
IF block_size >= needed_size
|
||||
next_free = PEEKW current[2]
|
||||
alloc_addr = current
|
||||
|
||||
remaining = block_size - needed_size
|
||||
|
||||
IF remaining >= 6
|
||||
POKEW current[0] , needed_size
|
||||
|
||||
split_addr = current + needed_size
|
||||
current = split_addr
|
||||
POKEW current[0] , remaining
|
||||
POKEW current[2] , next_free
|
||||
|
||||
IF prev = NULL
|
||||
lib_memlib_free_head = split_addr
|
||||
ELSE
|
||||
current = prev
|
||||
POKEW current[2] , split_addr
|
||||
ENDIF
|
||||
ELSE
|
||||
IF prev = NULL
|
||||
lib_memlib_free_head = next_free
|
||||
ELSE
|
||||
current = prev
|
||||
POKEW current[2] , next_free
|
||||
ENDIF
|
||||
ENDIF
|
||||
|
||||
result = alloc_addr + 2
|
||||
EXIT
|
||||
ENDIF
|
||||
|
||||
prev = current
|
||||
WORD temp
|
||||
temp = PEEKW current[2]
|
||||
current = temp
|
||||
WEND
|
||||
|
||||
FEND
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Malloc: alloc memory of size size_t
|
||||
// Address to allocated space is returned in result
|
||||
// Free: Release allocated memory block
|
||||
//-----------------------------------------------------------
|
||||
FUNC lib_mem_free({WORD m_ptr})
|
||||
WORD current @ __LIB_MEM_ZP_CURRENT
|
||||
WORD block_start
|
||||
|
||||
FUNC lib_mem_malloc ( {WORD size_t} out:{WORD result} )
|
||||
WORD maxsize //max possible size now in heap
|
||||
WORD newspaceb
|
||||
WORD newspacee
|
||||
WORD newtableend
|
||||
|
||||
DEC size_t // 1 = e.g. $2001-$2001 ( $2001 - $2001 = 0 )
|
||||
|
||||
LET newtableend GET lib_alloctable_end
|
||||
SUBT newtableend - 4 -> newtableend
|
||||
|
||||
IF lib_alloctable_end > lib_memend THEN // only when first item!
|
||||
|
||||
SUBT newtableend - lib_memstart -> maxsize
|
||||
IF maxsize < size_t THEN
|
||||
//error handling: return NULL pointer!
|
||||
LET result GET NULL
|
||||
GOTO lib_malloc_exit
|
||||
IF m_ptr = NULL
|
||||
EXIT
|
||||
ENDIF
|
||||
|
||||
LET newspaceb GET lib_memstart
|
||||
ADD newspaceb + size_t -> newspacee
|
||||
block_start = m_ptr - 2
|
||||
|
||||
//insert first record and recalc lib_alloctable_end
|
||||
DEC lib_alloctable_end
|
||||
DEC lib_alloctable_end
|
||||
POKEW lib_alloctable_end , newspaceb
|
||||
DEC lib_alloctable_end
|
||||
DEC lib_alloctable_end
|
||||
POKEW lib_alloctable_end , newspacee
|
||||
|
||||
LET result GET newspaceb
|
||||
|
||||
GOTO lib_malloc_exit;
|
||||
|
||||
ENDIF
|
||||
//else if this is not the first item then:
|
||||
|
||||
WORD lib_malloc_ptr
|
||||
WORD lib_malloc_spaceend
|
||||
WORD lib_malloc_spacestart
|
||||
|
||||
//LET lib_malloc_ptr GET lib_memend
|
||||
//SUBT lib_malloc_ptr - 3 -> lib_malloc_ptr
|
||||
LET lib_malloc_ptr GET lib_alloctable_end
|
||||
|
||||
lib_malloc_spaceend = PEEKW lib_malloc_ptr
|
||||
|
||||
LET newspaceb GET NULL //if not found afterwards
|
||||
|
||||
WHILE 1
|
||||
|
||||
//if we reached the last record in the alloc-table
|
||||
IF lib_malloc_ptr = lib_alloctable_end THEN
|
||||
//is there sufficient space left @ top of heap?
|
||||
INC lib_malloc_spaceend
|
||||
SUBT newtableend - lib_malloc_spaceend -> maxsize
|
||||
|
||||
IF maxsize > size_t THEN
|
||||
LET newspaceb GET lib_malloc_spaceend
|
||||
ADD size_t + newspaceb -> newspacee
|
||||
ENDIF
|
||||
|
||||
BREAK
|
||||
ENDIF
|
||||
|
||||
DEC lib_malloc_ptr
|
||||
DEC lib_malloc_ptr
|
||||
lib_malloc_spacestart = PEEKW lib_malloc_ptr
|
||||
SUBT lib_malloc_spacestart - lib_malloc_spaceend -> maxsize
|
||||
DEC maxsize
|
||||
//if we found a space big enough for the allocation
|
||||
IF maxsize > size_t THEN
|
||||
//Save the pointer to the new space end the pointer in the alloctable
|
||||
LET newspaceb GET lib_malloc_spaceend
|
||||
INC newspaceb // must start @ the next byte
|
||||
ADD size_t + newspaceb -> newspacee
|
||||
|
||||
INC lib_malloc_ptr // set it to start of record! ( for move )
|
||||
// INC lib_malloc_ptr
|
||||
|
||||
BREAK
|
||||
ENDIF
|
||||
|
||||
DEC lib_malloc_ptr
|
||||
DEC lib_malloc_ptr
|
||||
lib_malloc_spaceend = PEEKW lib_malloc_ptr
|
||||
|
||||
WEND
|
||||
|
||||
IF newspaceb <> NULL THEN // allocate @ found space
|
||||
IF lib_malloc_ptr = lib_alloctable_end THEN //allocate @ end of table
|
||||
|
||||
//insert record and recalc lib_alloctable_end
|
||||
DEC lib_alloctable_end
|
||||
DEC lib_alloctable_end
|
||||
POKEW lib_alloctable_end , newspaceb
|
||||
DEC lib_alloctable_end
|
||||
DEC lib_alloctable_end
|
||||
POKEW lib_alloctable_end , newspacee
|
||||
|
||||
//return new pointer
|
||||
LET result GET newspaceb
|
||||
|
||||
GOTO lib_malloc_exit
|
||||
ENDIF
|
||||
//else = insert into alloctable
|
||||
WORD lib_malloc_from
|
||||
WORD lib_malloc_to
|
||||
BYTE lib_malloc_byte
|
||||
|
||||
// move the rest of the stack
|
||||
LET lib_malloc_from GET lib_alloctable_end
|
||||
LET lib_malloc_to GET newtableend
|
||||
|
||||
WHILE 1
|
||||
PEEK lib_malloc_from -> lib_malloc_byte
|
||||
POKE lib_malloc_to WITH lib_malloc_byte
|
||||
IF lib_malloc_from = lib_malloc_ptr THEN
|
||||
BREAK
|
||||
ENDIF
|
||||
INC lib_malloc_from
|
||||
INC lib_malloc_to
|
||||
WEND
|
||||
|
||||
//insert record and recalc lib_alloctable_end
|
||||
DEC lib_malloc_ptr
|
||||
POKEW lib_malloc_ptr , newspaceb
|
||||
DEC lib_malloc_ptr
|
||||
DEC lib_malloc_ptr
|
||||
POKEW lib_malloc_ptr , newspacee
|
||||
LET lib_alloctable_end GET newtableend
|
||||
|
||||
//return new pointer
|
||||
LET result GET newspaceb
|
||||
|
||||
ENDIF
|
||||
|
||||
IF newspaceb = NULL THEN // return null pointer
|
||||
LET result GET NULL
|
||||
GOTO lib_malloc_exit
|
||||
ENDIF
|
||||
|
||||
LABEL lib_malloc_exit
|
||||
|
||||
INC size_t
|
||||
|
||||
FEND
|
||||
|
||||
//-----------------------------------------------------------
|
||||
// Free: free alloced memory at m_ptr
|
||||
//-----------------------------------------------------------
|
||||
|
||||
FUNC lib_mem_free ( {WORD m_ptr} )
|
||||
WORD ptr
|
||||
WORD startaddr
|
||||
WORD lastrecfirst
|
||||
WORD from
|
||||
WORD to
|
||||
BYTE tempb
|
||||
|
||||
IF lib_alloctable_end > lib_memend THEN // no entries
|
||||
GOTO lib_free_exit
|
||||
ENDIF
|
||||
|
||||
LET ptr GET lib_memend
|
||||
DEC ptr
|
||||
|
||||
ADD 2 + lib_alloctable_end -> lastrecfirst
|
||||
|
||||
WHILE 1
|
||||
startaddr = PEEKW ptr
|
||||
|
||||
IF startaddr = m_ptr THEN //found allocation!
|
||||
//remove it!
|
||||
IF ptr = lastrecfirst THEN
|
||||
ADD 4 + lib_alloctable_end -> lib_alloctable_end
|
||||
BREAK
|
||||
ENDIF
|
||||
|
||||
LET to GET ptr
|
||||
INC to
|
||||
SUBT to - 4 -> from
|
||||
|
||||
WHILE 1
|
||||
PEEK from -> tempb
|
||||
POKE to WITH tempb
|
||||
IF from = lib_alloctable_end THEN
|
||||
BREAK
|
||||
ENDIF
|
||||
DEC from
|
||||
DEC to
|
||||
WEND
|
||||
|
||||
ADD 4 + lib_alloctable_end -> lib_alloctable_end
|
||||
|
||||
BREAK
|
||||
ENDIF
|
||||
|
||||
DEC ptr
|
||||
DEC ptr
|
||||
|
||||
IF ptr = lib_alloctable_end THEN
|
||||
BREAK
|
||||
ENDIF
|
||||
|
||||
DEC ptr
|
||||
DEC ptr
|
||||
|
||||
WEND
|
||||
|
||||
LABEL lib_free_exit
|
||||
current = block_start
|
||||
POKEW current[2] , lib_memlib_free_head
|
||||
lib_memlib_free_head = block_start
|
||||
|
||||
FEND
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue