Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 18 additions & 3 deletions lib/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -629,12 +629,27 @@ void *malloc(int size)

void *calloc(int n, int size)
{
char *p = malloc(n * size);
int total = n * size;
char *p = malloc(total);

if (!p)
return NULL;
for (int i = 0; i < n * size; i++)
p[i] = 0;

/* TODO: Replace the byte buffer clearing algorithm with memset once
* implemented.
*/

/* Currently malloc uses mmap(2) to request allocation, which guarantees
* memory to be page-aligned
*/
int *pi = p, num_words = total >> 2, offset = num_words << 2;

for (int i = 0; i < num_words; i++)
pi[i] = 0;

while (offset < total)
p[offset++] = 0;

return p;
}

Expand Down
5 changes: 2 additions & 3 deletions src/arm-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,7 @@ void cfg_flatten()

for (ph2_ir_t *insn = bb->ph2_ir_list.head; insn;
insn = insn->next) {
flatten_ir = add_ph2_ir(OP_generic);
memcpy(flatten_ir, insn, sizeof(ph2_ir_t));
flatten_ir = add_existed_ph2_ir(insn);

if (insn->op == OP_return) {
/* restore sp */
Expand Down Expand Up @@ -470,7 +469,7 @@ void code_generate()
emit(__b(__AL, MAIN_BB->elf_offset - elf_code_idx));

for (int i = 0; i < ph2_ir_idx; i++) {
ph2_ir = &PH2_IR[i];
ph2_ir = PH2_IR_FLATTEN[i];
emit_ph2_ir(ph2_ir);
}
}
16 changes: 16 additions & 0 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@
#define MAX_OPERAND_STACK_SIZE 32
#define MAX_ANALYSIS_STACK_SIZE 750

/* Default capacities for common data structures */
/* Default arena size is initialized with 256 KiB */
#define DEFAULT_ARENA_SIZE 262144

#define ELF_START 0x10000
#define PTR_SIZE 4

Expand All @@ -62,6 +66,18 @@
#define HOST_PTR_SIZE __SIZEOF_POINTER__
#endif

/* Common data structures */
typedef struct arena_block {
char *memory;
int capacity;
int offset;
struct arena_block *next;
} arena_block_t;

typedef struct {
arena_block_t *head;
} arena_t;

/* builtin types */
typedef enum {
TYPE_void = 0,
Expand Down
144 changes: 137 additions & 7 deletions src/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ int global_ir_idx = 0;
ph1_ir_t *PH1_IR;
int ph1_ir_idx = 0;

ph2_ir_t *PH2_IR;
arena_t *INSN_ARENA;

/* BB_ARENA is responsible for basic_block_t / ph2_ir_t allocation */
arena_t *BB_ARENA;

ph2_ir_t **PH2_IR_FLATTEN;
int ph2_ir_idx = 0;

label_lut_t *LABEL_LUT;
Expand Down Expand Up @@ -69,6 +74,121 @@ char *elf_symtab;
char *elf_strtab;
char *elf_section;

/**
* arena_block_create() - creates a new arena block with given capacity.
* The created arena block is guaranteed to be zero-initialized.
* @capacity: The capacity of the arena block. Must be positive.
*
* Return: The pointer of created arena block. NULL if failed to allocate.
*/
arena_block_t *arena_block_create(int capacity)
{
arena_block_t *block = malloc(sizeof(arena_block_t));

if (!block) {
printf("Failed to allocate memory for arena block\n");
exit(1);
}

block->memory = calloc(capacity, sizeof(char));

if (!block->memory) {
printf("Failed to allocate memory for arena block\n");
free(block);
exit(1);
}

block->capacity = capacity;
block->offset = 0;
block->next = NULL;
return block;
}

/**
* arena_init() - initializes the given arena with initial capacity.
* @initial_capacity: The initial capacity of the arena. Must be positive.
*
* Return: The pointer of initialized arena.
*/
arena_t *arena_init(int initial_capacity)
{
arena_t *arena = malloc(sizeof(arena_t));
arena->head = arena_block_create(initial_capacity);
return arena;
}

/**
* arena_alloc() - allocates memory from the given arena with given size.
* The arena may create a new arena block if no space is available.
* @arena: The arena to allocate memory from. Must not be NULL.
* @size: The size of memory to allocate. Must be positive.
*
* Return: The pointer of allocated memory. NULL if new arena block is failed to
* allocate.
*/
void *arena_alloc(arena_t *arena, int size)
{
char *ptr;
arena_block_t *block = arena->head;

while (block) {
if (block->offset + size <= block->capacity) {
ptr = block->memory + block->offset;
block->offset += size;
return ptr;
}
if (!block->next)
break;
block = block->next;
}

/* If no space is available, create a new block
* Allocate at least 256 KiB or the requested size
*/
int new_capacity = size > DEFAULT_ARENA_SIZE ? size : DEFAULT_ARENA_SIZE;
arena_block_t *new_block = arena_block_create(new_capacity);

if (!new_block)
return NULL;

block->next = new_block;
ptr = new_block->memory + new_block->offset;
new_block->offset += size;
return ptr;
}

/**
* arena_reset() - resets the given arena by resetting all blocks' offset to 0.
* @arena: The arena to reset. Must not be NULL.
*/
void arena_reset(arena_t *arena)
{
arena_block_t *block = arena->head;

while (block) {
block->offset = 0;
block = block->next;
}
}

/**
* arena_free() - frees the given arena and all its blocks.
* @arena: The arena to free. Must not be NULL.
*/
void arena_free(arena_t *arena)
{
arena_block_t *block = arena->head, *next;

while (block) {
next = block->next;
free(block->memory);
free(block);
block = next;
}

free(arena);
}

/**
* hashmap_hash_index() - hashses a string with FNV-1a hash function
* and converts into usable hashmap index. The range of returned
Expand Down Expand Up @@ -312,11 +432,17 @@ ph1_ir_t *add_ph1_ir(opcode_t op)
return ph1_ir;
}

ph2_ir_t *add_existed_ph2_ir(ph2_ir_t *ph2_ir)
{
PH2_IR_FLATTEN[ph2_ir_idx++] = ph2_ir;
return ph2_ir;
}

ph2_ir_t *add_ph2_ir(opcode_t op)
{
ph2_ir_t *ph2_ir = &PH2_IR[ph2_ir_idx++];
ph2_ir_t *ph2_ir = arena_alloc(BB_ARENA, sizeof(ph2_ir_t));
ph2_ir->op = op;
return ph2_ir;
return add_existed_ph2_ir(ph2_ir);
}

void set_var_liveout(var_t *var, int end)
Expand Down Expand Up @@ -579,7 +705,7 @@ fn_t *add_fn()
/* Create a basic block and set the scope of variables to 'parent' block */
basic_block_t *bb_create(block_t *parent)
{
basic_block_t *bb = calloc(1, sizeof(basic_block_t));
basic_block_t *bb = arena_alloc(BB_ARENA, sizeof(basic_block_t));

for (int i = 0; i < MAX_BB_PRED; i++) {
bb->prev[i].bb = NULL;
Expand Down Expand Up @@ -691,7 +817,7 @@ void add_insn(block_t *block,

bb->scope = block;

insn_t *n = calloc(1, sizeof(insn_t));
insn_t *n = arena_alloc(INSN_ARENA, sizeof(insn_t));
n->opcode = op;
n->rd = rd;
n->rs1 = rs1;
Expand Down Expand Up @@ -725,7 +851,9 @@ void global_init()
TYPES = malloc(MAX_TYPES * sizeof(type_t));
GLOBAL_IR = malloc(MAX_GLOBAL_IR * sizeof(ph1_ir_t));
PH1_IR = malloc(MAX_IR_INSTR * sizeof(ph1_ir_t));
PH2_IR = malloc(MAX_IR_INSTR * sizeof(ph2_ir_t));
INSN_ARENA = arena_init(DEFAULT_ARENA_SIZE);
BB_ARENA = arena_init(DEFAULT_ARENA_SIZE);
PH2_IR_FLATTEN = malloc(MAX_IR_INSTR * sizeof(ph2_ir_t *));
LABEL_LUT = malloc(MAX_LABEL * sizeof(label_lut_t));
SOURCE = malloc(MAX_SOURCE);
ALIASES = malloc(MAX_ALIASES * sizeof(alias_t));
Expand Down Expand Up @@ -755,7 +883,9 @@ void global_release()
free(TYPES);
free(GLOBAL_IR);
free(PH1_IR);
free(PH2_IR);
arena_free(INSN_ARENA);
arena_free(BB_ARENA);
free(PH2_IR_FLATTEN);
free(LABEL_LUT);
free(SOURCE);
free(ALIASES);
Expand Down
1 change: 0 additions & 1 deletion src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ int main(int argc, char *argv[])
elf_generate(out);

/* release allocated objects */
ssa_release();
global_release();

exit(0);
Expand Down
4 changes: 2 additions & 2 deletions src/reg-alloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ void refresh(basic_block_t *bb, insn_t *insn)

ph2_ir_t *bb_add_ph2_ir(basic_block_t *bb, opcode_t op)
{
ph2_ir_t *n = calloc(1, sizeof(ph2_ir_t));
ph2_ir_t *n = arena_alloc(BB_ARENA, sizeof(ph2_ir_t));
n->op = op;

if (!bb->ph2_ir_list.head)
Expand Down Expand Up @@ -640,7 +640,7 @@ void reg_alloc()
void dump_ph2_ir()
{
for (int i = 0; i < ph2_ir_idx; i++) {
ph2_ir_t *ph2_ir = &PH2_IR[i];
ph2_ir_t *ph2_ir = PH2_IR_FLATTEN[i];

int rd = ph2_ir->dest + 48;
int rs1 = ph2_ir->src0 + 48;
Expand Down
5 changes: 2 additions & 3 deletions src/riscv-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,7 @@ void cfg_flatten()

for (ph2_ir_t *insn = bb->ph2_ir_list.head; insn;
insn = insn->next) {
flatten_ir = add_ph2_ir(OP_generic);
memcpy(flatten_ir, insn, sizeof(ph2_ir_t));
flatten_ir = add_existed_ph2_ir(insn);

if (insn->op == OP_return) {
/* restore sp */
Expand Down Expand Up @@ -446,7 +445,7 @@ void code_generate()
emit(__jal(__zero, MAIN_BB->elf_offset - elf_code_idx));

for (int i = 0; i < ph2_ir_idx; i++) {
ph2_ir = &PH2_IR[i];
ph2_ir = PH2_IR_FLATTEN[i];
emit_ph2_ir(ph2_ir);
}
}
53 changes: 2 additions & 51 deletions src/ssa.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ bool insert_phi_insn(basic_block_t *bb, var_t *var)
return false;

insn_t *head = bb->insn_list.head;
insn_t *n = calloc(1, sizeof(insn_t));
insn_t *n = arena_alloc(INSN_ARENA, sizeof(insn_t));
n->opcode = OP_phi;
n->rd = var;
n->rs1 = var;
Expand Down Expand Up @@ -810,7 +810,7 @@ void solve_phi_params()

void append_unwound_phi_insn(basic_block_t *bb, var_t *dest, var_t *rs)
{
insn_t *n = calloc(1, sizeof(insn_t));
insn_t *n = arena_alloc(INSN_ARENA, sizeof(insn_t));
n->opcode = OP_unwound_phi;
n->rd = dest;
n->rs1 = rs;
Expand Down Expand Up @@ -1770,52 +1770,3 @@ void liveness_analysis()
} while (changed);
}
}

void bb_release(fn_t *fn, basic_block_t *bb)
{
UNUSED(fn);

insn_t *insn = bb->insn_list.head;
insn_t *next_insn;
while (insn) {
next_insn = insn->next;
free(insn);
insn = next_insn;
}

/* disconnect all predecessors */
for (int i = 0; i < MAX_BB_PRED; i++) {
if (!bb->prev[i].bb)
continue;
switch (bb->prev[i].type) {
case NEXT:
bb->prev[i].bb->next = NULL;
break;
case THEN:
bb->prev[i].bb->then_ = NULL;
break;
case ELSE:
bb->prev[i].bb->else_ = NULL;
break;
default:
abort();
}

bb->prev[i].bb = NULL;
}
free(bb);
}

void ssa_release()
{
bb_traversal_args_t *args = calloc(1, sizeof(bb_traversal_args_t));
for (fn_t *fn = FUNC_LIST.head; fn; fn = fn->next) {
args->fn = fn;
args->bb = fn->bbs;

fn->visited++;
args->postorder_cb = bb_release;
bb_forward_traversal(args);
}
free(args);
}
2 changes: 1 addition & 1 deletion tests/snapshots/fib-arm.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/fib-riscv.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello-arm.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion tests/snapshots/hello-riscv.json

Large diffs are not rendered by default.