Skip to content

Stablize variable typing and support integer truncation and sign extension #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
28 changes: 24 additions & 4 deletions src/arm-codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,14 @@ void update_elf_offset(ph2_ir_t *ph2_ir)
case OP_return:
elf_offset += 24;
return;
case OP_trunc:
elf_offset += 4;
return;
case OP_sign_ext:
elf_offset += 4;
return;
default:
printf("Unknown opcode\n");
abort();
fatal("Unknown opcode");
}
}

Expand Down Expand Up @@ -421,9 +426,24 @@ void emit_ph2_ir(ph2_ir_t *ph2_ir)
emit(__mov_i(__NE, rd, 0));
emit(__mov_i(__EQ, rd, 1));
return;
case OP_trunc:
if (rm == 1)
rm = 0xFF;
else if (rm == 2)
rm = 0xFFFF;
else if (rm == 4)
rm = 0xFFFFFFFF;
else
fatal("Unsupported truncation operation with invalid target size");

emit(__and_i(__AL, rd, rn, rm));
return;
case OP_sign_ext:
/* TODO: Allow to sign extends to other types */
emit(__sxtb(__AL, rd, rn, 0));
return;
default:
printf("Unknown opcode\n");
abort();
fatal("Unknown opcode");
}
}

Expand Down
14 changes: 14 additions & 0 deletions src/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,11 @@ int __sub_r(arm_cond_t cond, arm_reg rd, arm_reg rs, arm_reg ro)
return __mov(cond, 0, arm_sub, 0, rs, rd, ro);
}

int __and_i(arm_cond_t cond, arm_reg rd, arm_reg rs, int imm)
{
return __mov(cond, 1, arm_and, 0, rs, rd, imm);
}

int __zero(int rd)
{
return __mov_i(__AL, rd, 0);
Expand Down Expand Up @@ -349,3 +354,12 @@ int __teq(arm_reg rd)
{
return __mov(__AL, 1, arm_teq, 1, rd, 0, 0);
}

int __sxtb(arm_cond_t cond, arm_reg rd, arm_reg rm, int rotation)
{
if (rotation != 0 && rotation != 8 && rotation != 16 && rotation != 24)
fatal("SXTB rotation must be 0, 8, 16, or 24");

return arm_encode(cond, 106, 0xF, rd,
rm | ((rotation >> 3) << 10) | (0x7 << 4));
}
29 changes: 15 additions & 14 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,10 @@ typedef enum {
OP_bit_not,
OP_negate,

/* data type conversion */
OP_trunc,
OP_sign_ext,

/* entry point of the state machine */
OP_start
} opcode_t;
Expand Down Expand Up @@ -276,8 +280,17 @@ typedef struct use_chain_node {
struct use_chain_node *prev;
} use_chain_t;

typedef struct var var_t;
typedef struct type type_t;

typedef struct var_list {
int capacity;
int size;
var_t **elements;
} var_list_t;

struct var {
char type_name[MAX_TYPE_LEN];
type_t *type;
char var_name[MAX_VAR_LEN];
int is_ptr;
bool is_func;
Expand All @@ -302,8 +315,6 @@ struct var {
bool is_const; /* whether a constant representaion or not */
};

typedef struct var var_t;

typedef struct {
char name[MAX_VAR_LEN];
bool is_variadic;
Expand All @@ -319,22 +330,14 @@ typedef struct func func_t;

/* block definition */
struct block {
var_t locals[MAX_LOCALS];
int next_local;
var_list_t locals;
struct block *parent;
func_t *func;
macro_t *macro;
int locals_size;
struct block *next;
};

typedef struct block block_t;

typedef struct {
block_t *head;
block_t *tail;
} block_list_t;

typedef struct basic_block basic_block_t;

/* Definition of a growable buffer for a mutable null-terminated string
Expand Down Expand Up @@ -374,8 +377,6 @@ struct type {
int num_fields;
};

typedef struct type type_t;

/* lvalue details */
typedef struct {
int size;
Expand Down
4 changes: 4 additions & 0 deletions src/elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@

/* ELF file manipulation */

#include "../config"
#include "defs.h"
#include "globals.c"

int elf_symbol_index;

void elf_write_str(strbuf_t *elf_array, char *vals)
Expand Down
92 changes: 54 additions & 38 deletions src/globals.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@ int macro_return_idx;

/* Global objects */

block_list_t BLOCKS;

macro_t *MACROS;
int macros_idx = 0;

Expand All @@ -41,11 +39,23 @@ hashmap_t *FUNC_MAP;
hashmap_t *ALIASES_MAP;
hashmap_t *CONSTANTS_MAP;

/* Types */

type_t *TYPES;
int types_idx = 0;

type_t *TY_void;
type_t *TY_char;
type_t *TY_bool;
type_t *TY_int;

/* Arenas */

arena_t *INSN_ARENA;

/* BLOCK_ARENA is responsible for block_t / var_t allocation */
arena_t *BLOCK_ARENA;

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

Expand All @@ -56,6 +66,7 @@ int ph2_ir_idx = 0;

func_list_t FUNC_LIST;
func_t *GLOBAL_FUNC;
block_t *GLOBAL_BLOCK;
basic_block_t *MAIN_BB;
int elf_offset = 0;

Expand Down Expand Up @@ -499,20 +510,14 @@ void set_var_liveout(var_t *var, int end)

block_t *add_block(block_t *parent, func_t *func, macro_t *macro)
{
block_t *blk = malloc(sizeof(block_t));

if (!BLOCKS.head) {
BLOCKS.head = blk;
BLOCKS.tail = BLOCKS.head;
} else {
BLOCKS.tail->next = blk;
BLOCKS.tail = blk;
}
block_t *blk = arena_alloc(BLOCK_ARENA, sizeof(block_t));

blk->parent = parent;
blk->func = func;
blk->macro = macro;
blk->next_local = 0;
blk->locals.capacity = 16;
blk->locals.elements =
arena_alloc(BLOCK_ARENA, blk->locals.capacity * sizeof(var_t *));
return blk;
}

Expand Down Expand Up @@ -645,9 +650,10 @@ var_t *find_local_var(char *token, block_t *block)
func_t *func = block->func;

for (; block; block = block->parent) {
for (int i = 0; i < block->next_local; i++) {
if (!strcmp(block->locals[i].var_name, token))
return &block->locals[i];
var_list_t *var_list = &block->locals;
for (int i = 0; i < var_list->size; i++) {
if (!strcmp(var_list->elements[i]->var_name, token))
return var_list->elements[i];
}
}

Expand All @@ -662,11 +668,11 @@ var_t *find_local_var(char *token, block_t *block)

var_t *find_global_var(char *token)
{
block_t *block = BLOCKS.head;
var_list_t *var_list = &GLOBAL_BLOCK->locals;

for (int i = 0; i < block->next_local; i++) {
if (!strcmp(block->locals[i].var_name, token))
return &block->locals[i];
for (int i = 0; i < var_list->size; i++) {
if (!strcmp(var_list->elements[i]->var_name, token))
return var_list->elements[i];
}
return NULL;
}
Expand All @@ -685,9 +691,7 @@ int size_var(var_t *var)
if (var->is_ptr > 0 || var->is_func) {
size = 4;
} else {
type_t *type = find_type(var->type_name, 0);
if (!type)
error("Incomplete type");
type_t *type = var->type;
if (type->size == 0)
size = type->base_struct->size;
else
Expand Down Expand Up @@ -970,16 +974,14 @@ void global_init()
{
elf_code_start = ELF_START + elf_header_len;

BLOCKS.head = NULL;
BLOCKS.tail = NULL;

MACROS = malloc(MAX_ALIASES * sizeof(macro_t));
FUNC_MAP = hashmap_create(DEFAULT_FUNCS_SIZE);
TYPES = malloc(MAX_TYPES * sizeof(type_t));
BLOCK_ARENA = arena_init(DEFAULT_ARENA_SIZE);
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 *));
SOURCE = strbuf_create(MAX_SOURCE);
FUNC_MAP = hashmap_create(DEFAULT_FUNCS_SIZE);
INCLUSION_MAP = hashmap_create(DEFAULT_INCLUSIONS_SIZE);
ALIASES_MAP = hashmap_create(MAX_ALIASES);
CONSTANTS_MAP = hashmap_create(MAX_CONSTANTS);
Expand All @@ -994,18 +996,14 @@ void global_init()

void global_release()
{
while (BLOCKS.head) {
block_t *next = BLOCKS.head->next;
free(BLOCKS.head);
BLOCKS.head = next;
}
free(MACROS);
hashmap_free(FUNC_MAP);
free(TYPES);
arena_free(BLOCK_ARENA);
arena_free(INSN_ARENA);
arena_free(BB_ARENA);
free(PH2_IR_FLATTEN);
strbuf_free(SOURCE);
hashmap_free(FUNC_MAP);
hashmap_free(INCLUSION_MAP);
hashmap_free(ALIASES_MAP);
hashmap_free(CONSTANTS_MAP);
Expand All @@ -1018,6 +1016,14 @@ void global_release()
strbuf_free(elf_section);
}

/* Reports an error without specifying a position */
void fatal(char *msg)
{
printf("[Error]: %s\n", msg);
abort();
}

/* Reports an error and specifying a position */
void error(char *msg)
{
/* Construct error source diagnostics, enabling precise identification of
Expand Down Expand Up @@ -1048,8 +1054,8 @@ void error(char *msg)
/* TODO: figure out the corresponding C source file path and report line
* number.
*/
printf("Error %s at source location %d\n%s\n", msg, SOURCE->size,
diagnostic);
printf("[Error]: %s\nOccurs at source location %d.\n%s\n", msg,
SOURCE->size, diagnostic);
abort();
}

Expand Down Expand Up @@ -1081,7 +1087,7 @@ void dump_bb_insn(func_t *func, basic_block_t *bb, bool *at_func_start)
continue;
case OP_allocat:
print_indent(1);
printf("allocat %s", rd->type_name);
printf("allocat %s", rd->type->type_name);

for (int i = 0; i < rd->is_ptr; i++)
printf("*");
Expand Down Expand Up @@ -1251,6 +1257,16 @@ void dump_bb_insn(func_t *func, basic_block_t *bb, bool *at_func_start)
printf("%%%s = lshift %%%s, %%%s", rd->var_name, rs1->var_name,
rs2->var_name);
break;
case OP_trunc:
print_indent(1);
printf("%%%s = trunc %%%s, %d", rd->var_name, rs1->var_name,
insn->sz);
break;
case OP_sign_ext:
print_indent(1);
printf("%%%s = sign_ext %%%s, %d", rd->var_name, rs1->var_name,
insn->sz);
break;
default:
printf("<Unsupported opcode: %d>", insn->opcode);
break;
Expand All @@ -1277,7 +1293,7 @@ void dump_insn()
for (func_t *func = FUNC_LIST.head; func; func = func->next) {
bool at_func_start = true;

printf("def %s", func->return_def.type_name);
printf("def %s", func->return_def.type->type_name);

for (int i = 0; i < func->return_def.is_ptr; i++)
printf("*");
Expand All @@ -1286,7 +1302,7 @@ void dump_insn()
for (int i = 0; i < func->num_params; i++) {
if (i != 0)
printf(", ");
printf("%s", func->param_defs[i].type_name);
printf("%s", func->param_defs[i].type->type_name);

for (int k = 0; k < func->param_defs[i].is_ptr; k++)
printf("*");
Expand All @@ -1302,7 +1318,7 @@ void dump_insn()
if (!bb)
continue;

if (strcmp(func->return_def.type_name, "void"))
if (func->return_def.type != TY_void)
continue;

if (bb->insn_list.tail)
Expand Down
Loading