Added missing codegen allocator files

This commit is contained in:
SarahW 2019-01-17 18:05:27 +00:00
commit 13087d0031
2 changed files with 155 additions and 0 deletions

117
src/codegen_allocator.c Normal file
View file

@ -0,0 +1,117 @@
#if defined(__linux__) || defined(__APPLE__)
#include <sys/mman.h>
#include <unistd.h>
#endif
#if defined WIN32 || defined _WIN32 || defined _WIN32
#include <windows.h>
#endif
#include "ibm.h"
#include "codegen.h"
#include "codegen_allocator.h"
typedef struct mem_block_t
{
uint32_t offset; /*Offset into mem_block_alloc*/
uint32_t next;
} mem_block_t;
static mem_block_t mem_blocks[MEM_BLOCK_NR];
static uint32_t mem_block_free_list;
static uint8_t *mem_block_alloc = NULL;
int codegen_allocator_usage = 0;
void codegen_allocator_init()
{
int c;
#if defined WIN32 || defined _WIN32 || defined _WIN32
mem_block_alloc = VirtualAlloc(NULL, MEM_BLOCK_NR * MEM_BLOCK_SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
mem_block_alloc = mmap(0, MEM_BLOCK_NR * MEM_BLOCK_SIZE, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_ANON|MAP_PRIVATE, 0, 0);
#endif
for (c = 0; c < MEM_BLOCK_NR; c++)
{
mem_blocks[c].offset = c * MEM_BLOCK_SIZE;
if (c < MEM_BLOCK_NR-1)
mem_blocks[c].next = c+2;
else
mem_blocks[c].next = 0;
}
mem_block_free_list = 1;
}
mem_block_t *codegen_allocator_allocate(mem_block_t *parent)
{
mem_block_t *block;
uint32_t block_nr;
while (!mem_block_free_list)
{
codegen_delete_random_block();
}
// fatal("codegen_allocator_allocate: free list empty!\n");
/*Remove from free list*/
block_nr = mem_block_free_list;
block = &mem_blocks[block_nr-1];
mem_block_free_list = block->next;
if (parent)
{
/*Add to parent list*/
block->next = parent->next;
parent->next = block_nr;
}
else
block->next = 0;
codegen_allocator_usage++;
/* if (parent)
pclog("codegen_allocator_allocate with parent: %p %i %i %p\n", block, block_nr, codegen_allocator_usage, parent);
else
pclog("codegen_allocator_allocate: %p %i %i\n", block, block_nr, codegen_allocator_usage);*/
return block;
}
void codegen_allocator_free(mem_block_t *block)
{
int block_nr = (((uintptr_t)block - (uintptr_t)mem_blocks) / sizeof(mem_block_t)) + 1;
// pclog("codegen_allocator_free: %p %i %i %i\n", block, block_nr, codegen_allocator_usage, block->next);
while (1)
{
int next_block_nr = block->next;
// pclog(" free next=%i\n", next_block_nr);
codegen_allocator_usage--;
block->next = mem_block_free_list;
mem_block_free_list = block_nr;
block_nr = next_block_nr;
if (block_nr)
block = &mem_blocks[block_nr - 1];
else
break;
}
}
uint8_t *codeblock_allocator_get_ptr(mem_block_t *block)
{
return &mem_block_alloc[block->offset];
}
void codegen_allocator_clean_blocks(struct mem_block_t *block)
{
#if defined __ARM_EABI__ || defined __aarch64__
while (1)
{
__clear_cache(&mem_block_alloc[block->offset], &mem_block_alloc[block->offset + MEM_BLOCK_SIZE]);
if (block->next)
block = &mem_blocks[block->next - 1];
else
break;
}
#endif
}

38
src/codegen_allocator.h Normal file
View file

@ -0,0 +1,38 @@
#ifndef _CODEGEN_ALLOCATOR_H_
#define _CODEGEN_ALLOCATOR_H_
/*The allocator handles all allocation of executable memory. Since the two-pass
recompiler design makes applying hard limits to codeblock size difficult, the
allocator allows memory to be provided as and when required.
The allocator provides a block size of a little under 1 kB (slightly lower to
limit cache aliasing). Each generated codeblock is allocated one block by default,
and will allocate additional block(s) once the existing memory is sorted. Blocks
are chained together by jump instructions.
Due to the chaining, the total memory size is limited by the range of a jump
instruction. ARMv7 is restricted to +/- 32 MB, ARMv8 to +/- 128 MB, x86 to
+/- 2GB. As a result, total memory size is limited to 32 MB on ARMv7*/
#ifdef __ARM_EABI__
#define MEM_BLOCK_NR 32768
#else
#define MEM_BLOCK_NR 65536
#endif
#define MEM_BLOCK_SIZE 0x3c0
void codegen_allocator_init();
/*Allocate a mem_block_t, and the associated backing memory.
If parent is non-NULL, then the new block will be added to the list in
parent->next*/
struct mem_block_t *codegen_allocator_allocate(struct mem_block_t *parent);
/*Free a mem_block_t, and any subsequent blocks in the list at block->next*/
void codegen_allocator_free(struct mem_block_t *block);
/*Get a pointer to the backing memory associated with block*/
uint8_t *codeblock_allocator_get_ptr(struct mem_block_t *block);
/*Cache clean memory block list*/
void codegen_allocator_clean_blocks(struct mem_block_t *block);
extern int codegen_allocator_usage;
#endif