Browse Source

Metaprogramming should work now

master
zelaven 4 years ago
parent
commit
b871225835
8 changed files with 169 additions and 88 deletions
  1. +14
    -17
      acs_interface/ZMEMORY.acs
  2. +16
    -0
      acs_interface/ZMEMORY_g.acs
  3. +16
    -0
      acs_interface/ZMEMORY_w.acs
  4. +21
    -0
      build2.sh
  5. +1
    -1
      meta_src/scanner.l
  6. +2
    -0
      meta_src/test.acs
  7. +99
    -66
      src/acs_source/ZMEMORY.acs
  8. +0
    -4
      src/acs_source/compile.sh

+ 14
- 17
acs_interface/ZMEMORY.acs View File

@ -1,18 +1,15 @@
#library "ZMEMORY"
#include "zcommon.acs"
//Simple linked list implementation of malloc
//Memory space
global int 63:memory[];
//NULL "pointer"
#libdefine nullptr 0
//Allocated size bytes in the memory space
function int malloc (int size) {return 0;}
//Frees an allocated block in the memory space.
//There are no safeguards in this function to guess whether or not the free is
// valid, so be careful.
function int free (int p_ptr) {return 0;}
#include "zcommon.acs"
#include "ZMEMORY_g.acs"
#include "ZMEMORY_w.acs"
global int 63:gmemory[];
world int 255:wmemory[];
#libdefine nullptr 0
//#define nullptr 0
#define malloc_allocated 0
#define malloc_size 1
#define malloc_next_header 2
#define malloc_prev_header 3
#define malloc_num_header_properties 4
#define p_malloc_init_flag_location 0
#define p_malloc_first_header_location 1

+ 16
- 0
acs_interface/ZMEMORY_g.acs View File

@ -0,0 +1,16 @@
global int 63:gmemory[];
//[Z] The reason I do it like this is because whoever made the acc is insane.
#define gnullptr 0
#define gmalloc_allocated 0
#define gmalloc_size 1
#define gmalloc_next_header 2
#define gmalloc_prev_header 3
#define gmalloc_num_header_properties 4
#define gp_malloc_init_flag_location 0
#define gp_malloc_first_header_location 1
function int gmalloc (int size) {return 0;}
function int gfree (int p_ptr) {return 0;}

+ 16
- 0
acs_interface/ZMEMORY_w.acs View File

@ -0,0 +1,16 @@
world int 255:wmemory[];
//[Z] The reason I do it like this is because whoever made the acc is insane.
#define wnullptr 0
#define wmalloc_allocated 0
#define wmalloc_size 1
#define wmalloc_next_header 2
#define wmalloc_prev_header 3
#define wmalloc_num_header_properties 4
#define wp_malloc_init_flag_location 0
#define wp_malloc_first_header_location 1
function int wmalloc (int size) {return 0;}
function int wfree (int p_ptr) {return 0;}

+ 21
- 0
build2.sh View File

@ -0,0 +1,21 @@
#!/bin/bash
# Construct the ACS source from the original file.
cd build_files
cat ../src/acs_source/ZMEMORY.acs | ../meta_src/metatool.out ZMEMORY.acs ZMEMORY_g.acs ZMEMORY_w.acs ../acs_interface/ZMEMORY.acs ../acs_interface/ZMEMORY_g.acs ../acs_interface/ZMEMORY_w.acs
# compile the ACS source
acc -i $ACC_ZCOMMON_PATH ZMEMORY.acs ../src/acs/ZMEMORY.o
cd ../src
# Bundle everything that isn't:
# .sh : a shell script.
thin_arg=$1
version=$(cat ../version.txt)
if [[ $thin_arg == "thin" ]]; then
7za a -tzip ../ZMemory_v$version\_thin.pk3 -r -x\!*.sh -x\!acs/.gitignore -xr\!acs_source
else
7za a -tzip ../ZMemory_v$version.pk3 -r -x\!*.sh -x\!acs/.gitignore
fi

+ 1
- 1
meta_src/scanner.l View File

@ -41,7 +41,7 @@ FILE* interface_g = NULL;
<LEX_STATE_EXPORT_SPLIT>"$$" BEGIN(INITIAL);
<LEX_STATE_EXPORT_SPLIT>(.|\n) p(code_g); p(code_w); p(interface_g); p(interface_w);
<LEX_STATE_EXPORT_SPLIT_FUNCTION>"{" p(code_g); p(code_w); ps(interface_g, "{return 0;}"); ps(interface_w, "{return 0;}"); BEGIN(LEX_STATE_EXPORT_SPLIT_FUNCTION_BODY);
<LEX_STATE_EXPORT_SPLIT_FUNCTION>"{" p(code_g); p(code_w); ps(interface_g, "{return 0;}\n"); ps(interface_w, "{return 0;}\n"); BEGIN(LEX_STATE_EXPORT_SPLIT_FUNCTION_BODY);
<LEX_STATE_EXPORT_SPLIT_FUNCTION>"@" ps(code_g,"g"); ps(code_w,"w"); ps(interface_g,"g"); ps(interface_w,"w");
<LEX_STATE_EXPORT_SPLIT_FUNCTION>(.|\n) p(code_g); p(code_w); p(interface_g); p(interface_w);
<LEX_STATE_EXPORT_SPLIT_FUNCTION_BODY>"@" ps(code_g,"g"); ps(code_w,"w");

+ 2
- 0
meta_src/test.acs View File

@ -0,0 +1,2 @@
$$export_split
cookies $$

+ 99
- 66
src/acs_source/ZMEMORY.acs View File

@ -1,136 +1,167 @@
#library "ZMEMORY"
#include "zcommon.acs"
$export_common #library "ZMEMORY"
$export_common #include "zcommon.acs"
#define muffins 42
$export_common #include "ZMEMORY_g.acs"
$export_common #include "ZMEMORY_w.acs"
//Simple linked list implementation of malloc
global int 63:memory[];
//$export_common global int 63:gmemory[];
//$export_common world int 255:wmemory[];
$export_option
global int 63:gmemory[];
$
world int 255:wmemory[];
$
$export_common #libdefine nullptr 0
$export_common //#define nullptr 0
#libdefine nullptr 0
$export_common #define malloc_allocated 0
$export_common #define malloc_size 1
$export_common #define malloc_next_header 2
$export_common #define malloc_prev_header 3
$export_common #define malloc_num_header_properties 4
#define malloc_allocated 0
#define malloc_size 1
#define malloc_next_header 2
#define malloc_prev_header 3
#define malloc_num_header_properties 4
$export_common #define p_malloc_init_flag_location 0
$export_common #define p_malloc_first_header_location 1
#define p_malloc_init_flag_location 0
#define p_malloc_first_header_location 1
$$export_split
//[Z] The reason I do it like this is because whoever made the acc is insane.
#define @nullptr 0
function int malloc (int size) {
log(s:"Invoked malloc");
#define @malloc_allocated 0
#define @malloc_size 1
#define @malloc_next_header 2
#define @malloc_prev_header 3
#define @malloc_num_header_properties 4
#define @p_malloc_init_flag_location 0
#define @p_malloc_first_header_location 1
$$
$$export_split function int @malloc (int size) {
//Do the setup on the first run of this function.
if(memory[p_malloc_init_flag_location] == FALSE) { //Default values for global values is 0, so this is true.
memory[p_malloc_init_flag_location] = TRUE;
memory[p_malloc_first_header_location+malloc_allocated] = FALSE;
memory[p_malloc_first_header_location+malloc_size] = -1; //"infinite"
memory[p_malloc_first_header_location+malloc_next_header] = nullptr; //nullptr
memory[p_malloc_first_header_location+malloc_prev_header] = nullptr; //nullptr
if(@memory[@p_malloc_init_flag_location] == FALSE) { //Default values for global values is 0, so this is true.
@memory[@p_malloc_init_flag_location] = TRUE;
@memory[@p_malloc_first_header_location+@malloc_allocated] = FALSE;
@memory[@p_malloc_first_header_location+@malloc_size] = -1; //"infinite"
@memory[@p_malloc_first_header_location+@malloc_next_header] = @nullptr; //nullptr
@memory[@p_malloc_first_header_location+@malloc_prev_header] = @nullptr; //nullptr
}
int p_previous_header = nullptr;
int p_current_header = p_malloc_first_header_location;
int p_retval = nullptr;
int p_previous_header = @nullptr;
int p_current_header = @p_malloc_first_header_location;
int p_retval = @nullptr;
while(p_retval == nullptr) {
int memalloced = memory[p_current_header+malloc_allocated];
int memsize = memory[p_current_header+malloc_size];
while(p_retval == @nullptr) {
int memalloced = @memory[p_current_header+@malloc_allocated];
int memsize = @memory[p_current_header+@malloc_size];
if(memsize == -1) { //The end of the list.
memory[p_current_header+malloc_allocated] = TRUE;
memory[p_current_header+malloc_size] = size;
memory[p_current_header+malloc_next_header] = p_current_header+malloc_num_header_properties+size; //New EOL
memory[p_current_header+malloc_prev_header] = p_previous_header;
@memory[p_current_header+@malloc_allocated] = TRUE;
@memory[p_current_header+@malloc_size] = size;
@memory[p_current_header+@malloc_next_header] = p_current_header+@malloc_num_header_properties+size; //New EOL
@memory[p_current_header+@malloc_prev_header] = p_previous_header;
//Retrieve the return value while we are at the allocated space.
p_retval = p_current_header+malloc_num_header_properties;
p_retval = p_current_header+@malloc_num_header_properties;
//Remember to initialize the new end list node.
p_previous_header = p_current_header; //This is the header previous to the EOL.
p_current_header = memory[p_current_header+malloc_next_header];
p_current_header = @memory[p_current_header+@malloc_next_header];
//Set the tail node constants.
memory[p_current_header+malloc_allocated] = FALSE;
memory[p_current_header+malloc_size] = -1;
memory[p_current_header+malloc_next_header] = nullptr;
memory[p_current_header+malloc_prev_header] = p_previous_header;
@memory[p_current_header+@malloc_allocated] = FALSE;
@memory[p_current_header+@malloc_size] = -1;
@memory[p_current_header+@malloc_next_header] = @nullptr;
@memory[p_current_header+@malloc_prev_header] = p_previous_header;
} else if(memsize >= size && memalloced == FALSE) { //There is room here AND it isn't in use,
memory[p_current_header+malloc_allocated] = TRUE;
@memory[p_current_header+@malloc_allocated] = TRUE;
//The size isn't modified because we are re-using an existing space.
// It would be a good idea to check just how large this space is and act accordingly rather
// than using a 500 indexes large space for a 4 indexes large object.
// Objects allocated in a doom mod probably won't be outside the 1-16 indexes range so it
// should still be fine for most applications.
//The next header isn't changed either for the same reason.
if(memsize >= (size+malloc_num_header_properties+5)) { //Assume that 5 is the smallest useful allocation size.
int p_split_newheader = p_current_header+malloc_num_header_properties+size; //Just to the end of the allocation.
memory[p_split_newheader+malloc_allocated] = FALSE;
memory[p_split_newheader+malloc_size] = memory[p_current_header+malloc_size]-malloc_num_header_properties-size;
memory[p_split_newheader+malloc_next_header] = memory[p_current_header+malloc_next_header];
memory[p_split_newheader+malloc_prev_header] = p_current_header;
memory[p_current_header+malloc_next_header] = p_split_newheader; //The header whose block was split should have its next pointer set to its other half.
memory[p_current_header+malloc_size] = size; //Set the size of the allocation to reflect the split.
if(memsize >= (size+@malloc_num_header_properties+5)) { //Assume that 5 is the smallest useful allocation size.
int p_split_newheader = p_current_header+@malloc_num_header_properties+size; //Just to the end of the allocation.
@memory[p_split_newheader+@malloc_allocated] = FALSE;
@memory[p_split_newheader+@malloc_size] = @memory[p_current_header+@malloc_size]-@malloc_num_header_properties-size;
@memory[p_split_newheader+@malloc_next_header] = @memory[p_current_header+@malloc_next_header];
@memory[p_split_newheader+@malloc_prev_header] = p_current_header;
@memory[p_current_header+@malloc_next_header] = p_split_newheader; //The header whose block was split should have its next pointer set to its other half.
@memory[p_current_header+@malloc_size] = size; //Set the size of the allocation to reflect the split.
}
//Retrieve the return value while we are at the allocated space.
p_retval = p_current_header+malloc_num_header_properties;
p_retval = p_current_header+@malloc_num_header_properties;
} else {
//The observed node isn't useful for allocating the request. Go to the next node.
p_previous_header = p_current_header;
p_current_header = memory[p_current_header+malloc_next_header];
p_current_header = @memory[p_current_header+@malloc_next_header];
}
}
log(s:"Malloc allocated ", d:size, s:" indexes at location ", d:p_retval, s:" with header location ", d:p_current_header);
//log(s:"Malloc allocated ", d:size, s:" indexes at location ", d:p_retval, s:" with header location ", d:p_current_header);
return p_retval;
}
$$
function int free (int p_ptr) {
$$export_split function int @free (int p_ptr) {
log(s:"Invoked free");
int p_header = p_ptr - malloc_num_header_properties;
int p_header = p_ptr - @malloc_num_header_properties;
memory[p_header+malloc_allocated] = FALSE;
@memory[p_header+@malloc_allocated] = FALSE;
int p_next = memory[p_header+malloc_next_header];
int p_prev = memory[p_header+malloc_prev_header];
int p_next = @memory[p_header+@malloc_next_header];
int p_prev = @memory[p_header+@malloc_prev_header];
//Below is the merging of free blocks.
//It merges to the left (lower indexes) first becaue the right (larger
// indexes) has a special case. (the end of the list)
//the previous block is unused. Merge.
if(p_prev != nullptr //This doesn't make sense if the previous block doesn't exist.
&& memory[p_prev+malloc_allocated] == FALSE) {
if(p_prev != @nullptr //This doesn't make sense if the previous block doesn't exist.
&& @memory[p_prev+@malloc_allocated] == FALSE) {
log(s:"Free attempting merge of header ", d:p_header, s: " to the left with header ", d:p_prev);
memory[p_prev+malloc_size] += memory[p_header+malloc_size] + malloc_num_header_properties;
memory[p_prev+malloc_next_header] = p_next; //The prev header needs to know the new next.
memory[p_next+malloc_prev_header] = p_prev; //The next header needs to know the new prev.
@memory[p_prev+@malloc_size] += @memory[p_header+@malloc_size] + @malloc_num_header_properties;
@memory[p_prev+@malloc_next_header] = p_next; //The prev header needs to know the new next.
@memory[p_next+@malloc_prev_header] = p_prev; //The next header needs to know the new prev.
//Now the two blocks are the same block. requires new initializations of the
// variables for the other check to function correctly.
//The header is the result of the merge, and the prev is the one before it.
p_header = p_prev;
p_prev = memory[p_header+malloc_prev_header];
p_prev = @memory[p_header+@malloc_prev_header];
}
//The next block is unused. Merge.
//Note that p_next will never be a nullptr with correct usage.
if(memory[p_next+malloc_allocated] == FALSE) {
if(memory[p_next+malloc_size] == -1) { //EOL
memory[p_header+malloc_size] = -1;
memory[p_header+malloc_next_header] = nullptr;
if(@memory[p_next+@malloc_allocated] == FALSE) {
if(@memory[p_next+@malloc_size] == -1) { //EOL
@memory[p_header+@malloc_size] = -1;
@memory[p_header+@malloc_next_header] = @nullptr;
} else {
int p_next_next = memory[p_next+malloc_next_header];
memory[p_header+malloc_size] += memory[p_next+malloc_size] + malloc_num_header_properties;
memory[p_header+malloc_next_header] = p_next_next; //The header on the other side of the next header needs to know its new prev.
memory[p_next_next+malloc_prev_header] = p_header; //This header needs to know its new next.
int p_next_next = @memory[p_next+@malloc_next_header];
@memory[p_header+@malloc_size] += @memory[p_next+@malloc_size] + @malloc_num_header_properties;
@memory[p_header+@malloc_next_header] = p_next_next; //The header on the other side of the next header needs to know its new prev.
@memory[p_next_next+@malloc_prev_header] = p_header; //This header needs to know its new next.
}
}
return -1;
}
$$
//These are for debugging
/*
script "memory_write" (int index, int value) {
memory[index] = value;
}
@ -154,3 +185,5 @@ script "memory_print_allocation_list" (void) {
p_current_header = memory[p_current_header+malloc_next_header];
}
}
*/

+ 0
- 4
src/acs_source/compile.sh View File

@ -1,4 +0,0 @@
#!/bin/bash
acc -i $ACC_ZCOMMON_PATH ZMEMORY.acs ../acs/ZMEMORY.o

Loading…
Cancel
Save