But did that by switching away from using Lisp calling convention, because that broke horribly. This is bad news and must be sorted out.
115 lines
3.3 KiB
C
115 lines
3.3 KiB
C
/**
|
|
* payloads/stack.h
|
|
*
|
|
* a Lisp stack frame.
|
|
*
|
|
* Sits in a pso4.
|
|
*
|
|
* (c) 2026 Simon Brooke <simon@journeyman.cc>
|
|
* Licensed under GPL version 2.0, or, at your option, any later version.
|
|
*/
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include "debug.h"
|
|
|
|
#include "memory/node.h"
|
|
#include "memory/pointer.h"
|
|
#include "memory/pso.h"
|
|
#include "memory/pso2.h"
|
|
#include "memory/pso4.h"
|
|
#include "memory/tags.h"
|
|
|
|
#include "payloads/cons.h"
|
|
|
|
#include "ops/reverse.h"
|
|
|
|
/**
|
|
* @brief Construct a stack frame with this `previous` pointer, and arguments
|
|
* taken from the remaining arguments to this function, which should all be
|
|
* struct pso_pointer.
|
|
*
|
|
* @return a pso_pointer to the stack frame.
|
|
*/
|
|
struct pso_pointer make_frame( int arg_count, struct pso_pointer previous,
|
|
... ) {
|
|
va_list args;
|
|
va_start( args, previous );
|
|
|
|
struct pso_pointer frame_pointer = allocate( STACKTAG, 4 );
|
|
struct pso4 *frame = ( struct pso4 * ) pointer_to_object( frame_pointer );
|
|
|
|
#ifdef DEBUG
|
|
debug_printf( DEBUG_ALLOC, 0,
|
|
L"\nAllocating stack frame with %d arguments at page %d, "
|
|
L"offset %d...\n",
|
|
arg_count, frame_pointer.page, frame_pointer.offset );
|
|
#endif
|
|
|
|
frame->payload.stack_frame.previous = previous;
|
|
|
|
if ( stackp( previous ) ) {
|
|
struct pso4 *op = pointer_to_pso4( previous );
|
|
frame->payload.stack_frame.depth = op->payload.stack_frame.depth + 1;
|
|
} else {
|
|
frame->payload.stack_frame.depth = 0;
|
|
}
|
|
|
|
debug_printf( DEBUG_ALLOC, 1, L"depth is %d...\n",
|
|
frame->payload.stack_frame.depth );
|
|
|
|
int cursor = 0;
|
|
frame->payload.stack_frame.args = arg_count;
|
|
|
|
for ( ; cursor < arg_count && cursor < args_in_frame; cursor++ ) {
|
|
struct pso_pointer argument = va_arg( args, struct pso_pointer );
|
|
|
|
frame->payload.stack_frame.arg[cursor] = inc_ref( argument );
|
|
}
|
|
if ( cursor < arg_count ) {
|
|
struct pso_pointer more_args = nil;
|
|
|
|
for ( ; cursor < arg_count; cursor++ ) {
|
|
more_args =
|
|
c_cons( va_arg( args, struct pso_pointer ), more_args );
|
|
}
|
|
|
|
frame->payload.stack_frame.more = c_reverse( more_args );
|
|
} else {
|
|
for ( ; cursor < args_in_frame; cursor++ ) {
|
|
frame->payload.stack_frame.arg[cursor] = nil;
|
|
}
|
|
}
|
|
|
|
debug_printf( DEBUG_ALLOC, 1,
|
|
L"Allocation of frame at page %d, offset %d completed.\n",
|
|
frame_pointer.page, frame_pointer.offset );
|
|
|
|
return frame_pointer;
|
|
}
|
|
|
|
/**
|
|
* @brief When a stack frame is freed, all its pointers must be decremented.
|
|
*
|
|
* Lisp calling conventions; one expected arg, the pointer to the object to
|
|
* be destroyed.
|
|
*/
|
|
struct pso_pointer destroy_stack_frame( struct pso_pointer fp,
|
|
struct pso_pointer env ) {
|
|
if ( stackp( fp ) ) {
|
|
struct pso4 *frame = pointer_to_pso4( fp );
|
|
|
|
dec_ref( frame->payload.stack_frame.previous );
|
|
dec_ref( frame->payload.stack_frame.function );
|
|
dec_ref( frame->payload.stack_frame.more );
|
|
|
|
for ( int i = 0; i < args_in_frame; i++ ) {
|
|
dec_ref( frame->payload.stack_frame.arg[i] );
|
|
}
|
|
|
|
frame->payload.stack_frame.args = 0;
|
|
frame->payload.stack_frame.depth = 0;
|
|
}
|
|
|
|
return nil;
|
|
}
|