summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkugwa <kugwa2000@gmail.com>2016-01-02 03:53:17 +0800
committerkugwa <kugwa2000@gmail.com>2016-01-02 03:54:31 +0800
commitd883f060e2f074c5be1d5685db7a7da4ac404ff9 (patch)
treeac438ccf15714ad2fe265e21018676405ec1c537
parent1ee3320a0b86e1d34c2b52fc8d4b4c760978c6f4 (diff)
downloadcompiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.tar
compiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.tar.gz
compiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.tar.bz2
compiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.tar.lz
compiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.tar.xz
compiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.tar.zst
compiler2015-d883f060e2f074c5be1d5685db7a7da4ac404ff9.zip
Can allocate many tmps
-rw-r--r--src/code-generation.c10
-rw-r--r--src/register.c126
-rw-r--r--src/register.h20
3 files changed, 118 insertions, 38 deletions
diff --git a/src/code-generation.c b/src/code-generation.c
index 59e47ad..7abf51b 100644
--- a/src/code-generation.c
+++ b/src/code-generation.c
@@ -156,13 +156,13 @@ static void generate_block(
offset_diff = current_offset - orig_offset;
if (offset_diff > 0) {
if (offset_diff > 4096) {
- CcmmcTmp *tmp = ccmmc_register_alloc(state->reg_pool);
+ CcmmcTmp *tmp = ccmmc_register_alloc(state->reg_pool, &current_offset);
const char *reg_name = ccmmc_register_lock(state->reg_pool, tmp);
fprintf(state->asm_output,
"\tldr\t%s, =%" PRIu64 "\n"
"\tsub\tsp, sp, %s\n", reg_name, offset_diff, reg_name);
ccmmc_register_unlock(state->reg_pool, tmp);
- ccmmc_register_free(state->reg_pool, tmp);
+ ccmmc_register_free(state->reg_pool, tmp, &current_offset);
} else {
fprintf(state->asm_output, "\tsub\tsp, sp, #%" PRIu64 "\n",
offset_diff);
@@ -176,13 +176,13 @@ static void generate_block(
}
if (offset_diff > 0) {
if (offset_diff > 4096) {
- CcmmcTmp *tmp = ccmmc_register_alloc(state->reg_pool);
+ CcmmcTmp *tmp = ccmmc_register_alloc(state->reg_pool, &current_offset);
const char *reg_name = ccmmc_register_lock(state->reg_pool, tmp);
fprintf(state->asm_output,
"\tldr\t%s, =%" PRIu64 "\n"
"\tadd\tsp, sp, %s\n", reg_name, offset_diff, reg_name);
ccmmc_register_unlock(state->reg_pool, tmp);
- ccmmc_register_free(state->reg_pool, tmp);
+ ccmmc_register_free(state->reg_pool, tmp, &current_offset);
} else {
fprintf(state->asm_output, "\tadd\tsp, sp, #%" PRIu64 "\n",
offset_diff);
@@ -227,7 +227,7 @@ void ccmmc_code_generation(CcmmcState *state)
state->table->this_scope = NULL;
state->table->current = NULL;
ccmmc_symbol_table_reopen_scope(state->table);
- state->reg_pool = ccmmc_register_init();
+ state->reg_pool = ccmmc_register_init(state->asm_output);
generate_program(state);
ccmmc_register_fini(state->reg_pool);
state->reg_pool = NULL;
diff --git a/src/register.c b/src/register.c
index 8f34255..99979b5 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1,21 +1,21 @@
#include "register.h"
#include <assert.h>
+#include <inttypes.h>
#include <stdbool.h>
+#include <stdio.h>
#include <stdlib.h>
#define REG_NUM 6
#define REG_RESERVED "x9"
#define REG_LOCK_MAX 3
+#define REG_SIZE 8
+#define SPILL_MAX 64
static const char *reg_name[REG_NUM] = {
"x10", "x11", "x12", "x13", "x14", "x15"};
-/* static void mov(CcmmcTmp *a, CcmmcTmp *b)
-{
-} */
-
-CcmmcRegPool *ccmmc_register_init(void)
+CcmmcRegPool *ccmmc_register_init(FILE *asm_output)
{
CcmmcRegPool *pool = malloc(sizeof(CcmmcRegPool));
pool->num = REG_NUM;
@@ -26,26 +26,43 @@ CcmmcRegPool *ccmmc_register_init(void)
pool->list[i]->lock = 0;
pool->list[i]->name = reg_name[i];
}
+ pool->spill = malloc(sizeof(CcmmcTmp*) * SPILL_MAX);
+ pool->top = 0;
pool->lock_max = REG_LOCK_MAX;
pool->lock_cnt = 0;
- pool->top = 0;
- pool->exceed = 0;
+ pool->asm_output = asm_output;
return pool;
}
-CcmmcTmp *ccmmc_register_alloc(CcmmcRegPool *pool)
+CcmmcTmp *ccmmc_register_alloc(CcmmcRegPool *pool, uint64_t *offset)
{
CcmmcTmp *tmp = malloc(sizeof(CcmmcTmp));
if (pool->top < pool->num) {
- tmp->reg = pool->list[pool->top];
+ // tmp
tmp->addr = 0;
+ tmp->reg = pool->list[pool->top];
+
+ // reg
tmp->reg->tmp = tmp;
+ tmp->reg->lock = 0;
+
+ // pool
pool->top++;
}
else {
+ // gen code to alloc space on the stack
+ fprintf(pool->asm_output, "\tsub\tsp, sp, #%d\n", REG_SIZE);
+
+ // tmp and offset
+ *offset += REG_SIZE;
+ tmp->addr = *offset;
tmp->reg = NULL;
- tmp->addr = (pool->exceed + 1) * (-8); // TODO: assign an offset for original tmp
- pool->exceed++;
+
+ // spill
+ pool->spill[pool->top - pool->num] = tmp;
+
+ // pool
+ pool->top++;
}
return tmp;
}
@@ -56,26 +73,49 @@ const char *ccmmc_register_lock(CcmmcRegPool *pool, CcmmcTmp *tmp)
if (pool->lock_cnt < pool->lock_max) {
if (tmp->reg !=NULL) {
if (tmp->reg->lock == 0) {
+ // reg
tmp->reg->lock = 1;
+
+ // pool
pool->lock_cnt++;
}
reg = tmp->reg->name;
}
- else { // find a unlocked reg
- int i;
+ else {
+ // find a unlocked reg
+ int i, j;
for (i = 0; i < pool->num && pool->list[i]->lock == 1; i++);
+ assert(i < pool->num); //must found
+
+ // gen code to swap the tmp in the register and the tmp on the stack
+ fprintf(pool->asm_output, "\tmov\t%s, %s\n", REG_RESERVED,
+ pool->list[i]->name);
+ fprintf(pool->asm_output, "\tldr\t%s, [fp - #%" PRIu64 "]\n",
+ pool->list[i]->name, tmp->addr);
+ fprintf(pool->asm_output, "\tstr\t%s, [fp - #%" PRIu64 "]\n",
+ REG_RESERVED, tmp->addr);
- // TODO: mov REG_RESERVED, pool->list[i]->name
- // TODO: ldr pool->list[i]->name, tmp->addr
- // TODO: str REG_RESERVED, tmp->addr
+ // find the index of tmp in pool->spill
+ for (j = 0; j < pool->top - pool->num && pool->spill[j] != tmp; j++);
+ // spill
+ pool->spill[j] = pool->list[i]->tmp;
+
+ // old tmp of the reg
pool->list[i]->tmp->reg = NULL;
pool->list[i]->tmp->addr = tmp->addr;
+
+ // tmp
tmp->reg = pool->list[i];
tmp->addr = 0;
+ // register
+ tmp->reg->tmp = tmp;
tmp->reg->lock = 1;
+
+ // pool
pool->lock_cnt++;
+
reg = tmp->reg->name;
}
}
@@ -85,26 +125,60 @@ const char *ccmmc_register_lock(CcmmcRegPool *pool, CcmmcTmp *tmp)
void ccmmc_register_unlock(CcmmcRegPool *pool, CcmmcTmp *tmp)
{
if (tmp->reg != NULL && tmp->reg->lock == 1) {
+ // reg
tmp->reg->lock = 0;
+
+ // pool
pool->lock_cnt--;
}
}
-void ccmmc_register_free(CcmmcRegPool *pool, CcmmcTmp *tmp)
+void ccmmc_register_free(CcmmcRegPool *pool, CcmmcTmp *tmp, uint64_t *offset)
{
- if (pool->exceed == 0) {
- int i;
- for (i = 0; i < pool->num && pool->list[i] != tmp->reg; i++);
- if (i < pool->top - 1) {
+ // find the index of register associated with tmp
+ int i;
+ for (i = 0; i < pool->num && pool->list[i] != tmp->reg; i++);
+
+ if (pool->top <= pool->num) {
+ // tmp
+ free(tmp);
+
+ // pool
+ pool->top--;
+ assert(i < pool->num); //must found
+ if (i < pool->top) {
CcmmcReg *swap = pool->list[i];
- pool->list[i] = pool->list[pool->top - 1];
- pool->list[pool->top - 1] = swap;
+ pool->list[i] = pool->list[pool->top];
+ pool->list[pool->top] = swap;
}
- pool->top--;
- free(tmp);
}
else {
- assert(false);
+ if (i < pool->num) {
+ // pool
+ pool->top--;
+
+ // gen code to move the last tmp to this register
+ fprintf(pool->asm_output, "\tldr\t%s, [fp - #%" PRIu64 "]\n",
+ tmp->reg->name, pool->spill[pool->top - pool->num]->addr);
+ fprintf(pool->asm_output, "\tadd\tsp, sp, #%d\n", REG_SIZE);
+
+ // offset
+ *offset -= REG_SIZE;
+
+ // reg
+ tmp->reg->tmp = pool->spill[pool->top - pool->num];
+
+ // the last tmp
+ tmp->reg->tmp->reg = tmp->reg;
+ tmp->reg->tmp->addr = 0;
+
+ // tmp
+ free(tmp);
+ }
+ else {
+ // tmp is on the stack, not handled
+ assert(false);
+ }
}
}
diff --git a/src/register.h b/src/register.h
index 52cab17..068f6d0 100644
--- a/src/register.h
+++ b/src/register.h
@@ -1,10 +1,13 @@
+#include <inttypes.h>
+#include <stdio.h>
+
#ifndef CCMMC_HEADER_REGISTER_H
#define CCMMC_HEADER_REGISTER_H
typedef struct CcmmcRegStruct CcmmcReg;
typedef struct CcmmcTmpStruct {
CcmmcReg *reg;
- int addr;
+ uint64_t addr;
} CcmmcTmp;
typedef struct CcmmcRegStruct {
@@ -16,20 +19,23 @@ typedef struct CcmmcRegStruct {
typedef struct CcmmcRegPoolStruct {
CcmmcReg **list;
int num;
- int lock_cnt;
- int lock_max;
int top;
- int exceed;
+ CcmmcTmp **spill;
+ int lock_max;
+ int lock_cnt;
+ FILE *asm_output;
} CcmmcRegPool;
-CcmmcRegPool *ccmmc_register_init (void);
-CcmmcTmp *ccmmc_register_alloc (CcmmcRegPool *pool);
+CcmmcRegPool *ccmmc_register_init (FILE *asm_output);
+CcmmcTmp *ccmmc_register_alloc (CcmmcRegPool *pool,
+ uint64_t *offset);
const char *ccmmc_register_lock (CcmmcRegPool *pool,
CcmmcTmp *tmp);
void ccmmc_register_unlock (CcmmcRegPool *pool,
CcmmcTmp *tmp);
void ccmmc_register_free (CcmmcRegPool *pool,
- CcmmcTmp *tmp);
+ CcmmcTmp *tmp,
+ uint64_t *offset);
void ccmmc_register_caller_save (CcmmcRegPool *pool);
void ccmmc_register_caller_load (CcmmcRegPool *pool);
void ccmmc_register_fini (CcmmcRegPool *pool);