Skip to content

Commit

Permalink
Add new instrs
Browse files Browse the repository at this point in the history
  • Loading branch information
john-h-k committed Dec 13, 2024
1 parent 9b1469f commit 33aa23e
Show file tree
Hide file tree
Showing 7 changed files with 222 additions and 34 deletions.
86 changes: 72 additions & 14 deletions aarch64/lower.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,6 @@ static void lower_comparison(struct ir_func *irb, struct ir_op *op) {
op->reg = NO_REG;
}

// actually more than this but we don't support that yet
#define MAX_REG_SIZE (8)

static void lower_store(struct ir_func *func, struct ir_op *op) {
struct ir_op *source = op->store.value;

Expand All @@ -132,21 +129,24 @@ static void lower_store(struct ir_func *func, struct ir_op *op) {
struct ir_op *source_addr = build_addr(func, source);
struct ir_op *dest_addr = build_addr(func, op);

struct ir_op *size = insert_after_ir_op(func, dest_addr, IR_OP_TY_CNST, IR_VAR_TY_NONE);
struct ir_op *size =
insert_after_ir_op(func, dest_addr, IR_OP_TY_CNST, IR_VAR_TY_NONE);
mk_pointer_constant(func->unit, size, info.size);

struct ir_glb *memmove =
add_well_known_global(func->unit, IR_WELL_KNOWN_GLB_MEMMOVE);

struct ir_var_ty ptr_int = var_ty_for_pointer_size(func->unit);
struct ir_op *memmove_addr = insert_after_ir_op(func, size, IR_OP_TY_ADDR, ptr_int);
struct ir_op *memmove_addr =
insert_after_ir_op(func, size, IR_OP_TY_ADDR, ptr_int);
memmove_addr->addr = (struct ir_op_addr){
.ty = IR_OP_ADDR_TY_GLB,
.glb = memmove,
.ty = IR_OP_ADDR_TY_GLB,
.glb = memmove,
};

size_t num_args = 3;
struct ir_op **args = arena_alloc(func->arena, sizeof(struct ir_op *) * num_args);
struct ir_op **args =
arena_alloc(func->arena, sizeof(struct ir_op *) * num_args);

args[0] = dest_addr;
args[1] = source_addr;
Expand All @@ -155,10 +155,10 @@ static void lower_store(struct ir_func *func, struct ir_op *op) {
op->ty = IR_OP_TY_CALL;
op->var_ty = *memmove->var_ty.func.ret_ty;
op->call = (struct ir_op_call){
.target = memmove_addr,
.num_args = num_args,
.args = args,
.func_ty = memmove->var_ty,
.target = memmove_addr,
.num_args = num_args,
.args = args,
.func_ty = memmove->var_ty,
};
}

Expand Down Expand Up @@ -288,6 +288,50 @@ static void lower_store(struct ir_func *func, struct ir_op *op) {
// }
// }

static void try_contain_load(struct ir_func *func, struct ir_op *op) {
switch (op->load.ty) {
case IR_OP_LOAD_TY_LCL:
case IR_OP_LOAD_TY_GLB:
return;
case IR_OP_LOAD_TY_ADDR:
break;
}

struct ir_op *addr = op->load.addr;

if (addr->ty == IR_OP_TY_ADDR && addr->addr.ty == IR_OP_ADDR_TY_LCL) {
struct ir_lcl *lcl = addr->addr.lcl;

op->load = (struct ir_op_load){
.ty = IR_OP_LOAD_TY_LCL,
.lcl = lcl
};
}
}

static void try_contain_store(struct ir_func *func, struct ir_op *op) {
switch (op->store.ty) {
case IR_OP_STORE_TY_LCL:
case IR_OP_STORE_TY_GLB:
return;
case IR_OP_STORE_TY_ADDR:
break;
}

struct ir_op *addr = op->store.addr;

if (addr->ty == IR_OP_TY_ADDR && addr->addr.ty == IR_OP_ADDR_TY_LCL) {
struct ir_lcl *lcl = addr->addr.lcl;
struct ir_op *value = op->store.value;

op->store = (struct ir_op_store){
.ty = IR_OP_STORE_TY_LCL,
.value = value,
.lcl = lcl
};
}
}

static void lower_fp_cnst(struct ir_func *func, struct ir_op *op) {
// transform into creating an integer, and then mov to float reg

Expand Down Expand Up @@ -368,7 +412,8 @@ static void lower_call(struct ir_func *func, struct ir_op *op) {
}

if (var_ty_is_aggregate(&op->var_ty)) {
if (op->succ && op->succ->ty == IR_OP_TY_STORE && op->succ->store.ty == IR_OP_STORE_TY_LCL &&
if (op->succ && op->succ->ty == IR_OP_TY_STORE &&
op->succ->store.ty == IR_OP_STORE_TY_LCL &&
op->succ->store.value == op) {
op->lcl = op->succ->store.lcl;
detach_ir_op(func, op->succ);
Expand Down Expand Up @@ -433,10 +478,15 @@ void aarch64_lower(struct ir_unit *unit) {

break;
}
case IR_OP_TY_LOAD: {
try_contain_load(func, op);

break;
}

case IR_OP_TY_STORE:
lower_store(func, op);
break;
case IR_OP_TY_LOAD:
case IR_OP_TY_STORE_BITFIELD:
case IR_OP_TY_LOAD_BITFIELD:
case IR_OP_TY_BITFIELD_EXTRACT:
Expand Down Expand Up @@ -479,6 +529,8 @@ void aarch64_lower(struct ir_unit *unit) {
break;
}
break;
default:
break;
}

op = op->succ;
Expand Down Expand Up @@ -508,19 +560,25 @@ void aarch64_lower(struct ir_unit *unit) {
case IR_OP_TY_PHI:
case IR_OP_TY_CNST:
case IR_OP_TY_STORE:
try_contain_store(func, op);
break;
case IR_OP_TY_LOAD:
try_contain_load(func, op);
break;
case IR_OP_TY_STORE_BITFIELD:
case IR_OP_TY_LOAD_BITFIELD:
case IR_OP_TY_BITFIELD_EXTRACT:
case IR_OP_TY_BITFIELD_INSERT:
case IR_OP_TY_ADDR:
case IR_OP_TY_ADDR_OFFSET:
case IR_OP_TY_BR:
case IR_OP_TY_BR_COND:
case IR_OP_TY_BR_SWITCH:
case IR_OP_TY_MOV:
case IR_OP_TY_RET:
case IR_OP_TY_CALL:
case IR_OP_TY_CAST_OP:
case IR_OP_TY_MEM_SET:
case IR_OP_TY_UNARY_OP:
break;
case IR_OP_TY_BINARY_OP:
Expand Down
41 changes: 41 additions & 0 deletions ir/ir.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,14 @@ bool op_has_side_effects(const struct ir_op *op) {
case IR_OP_TY_BITFIELD_EXTRACT:
case IR_OP_TY_BITFIELD_INSERT:
case IR_OP_TY_ADDR:
case IR_OP_TY_ADDR_OFFSET:
case IR_OP_TY_BINARY_OP:
case IR_OP_TY_UNARY_OP:
return false;
case IR_OP_TY_MOV:
case IR_OP_TY_CALL:
case IR_OP_TY_STORE:
case IR_OP_TY_MEM_SET:
case IR_OP_TY_STORE_BITFIELD:
case IR_OP_TY_BR_COND:
case IR_OP_TY_BR_SWITCH:
Expand Down Expand Up @@ -106,6 +108,7 @@ bool op_produces_value(const struct ir_op *op) {
case IR_OP_TY_BITFIELD_INSERT:
case IR_OP_TY_BITFIELD_EXTRACT:
case IR_OP_TY_ADDR:
case IR_OP_TY_ADDR_OFFSET:
return true;
case IR_OP_TY_CALL:
return op->call.func_ty.func.ret_ty->ty != IR_VAR_TY_TY_NONE;
Expand All @@ -115,6 +118,7 @@ bool op_produces_value(const struct ir_op *op) {
case IR_OP_TY_BR_SWITCH:
case IR_OP_TY_RET:
case IR_OP_TY_BR:
case IR_OP_TY_MEM_SET:
return false;
case IR_OP_TY_CUSTOM:
BUG("`op_produces_value` not well defined for IR_OP_TY_CUSTOM");
Expand All @@ -141,11 +145,13 @@ bool op_is_branch(enum ir_op_ty ty) {
case IR_OP_TY_CAST_OP:
case IR_OP_TY_STORE:
case IR_OP_TY_LOAD:
case IR_OP_TY_MEM_SET:
case IR_OP_TY_STORE_BITFIELD:
case IR_OP_TY_LOAD_BITFIELD:
case IR_OP_TY_BITFIELD_EXTRACT:
case IR_OP_TY_BITFIELD_INSERT:
case IR_OP_TY_ADDR:
case IR_OP_TY_ADDR_OFFSET:
return false;
case IR_OP_TY_CUSTOM:
BUG("`op_produces_value` not well defined for IR_OP_TY_CUSTOM");
Expand Down Expand Up @@ -345,6 +351,10 @@ void walk_op_uses(struct ir_op *op, walk_op_callback *cb, void *cb_metadata) {
break;
case IR_OP_TY_ADDR:
break;
case IR_OP_TY_ADDR_OFFSET:
cb(&op->addr_offset.base, cb_metadata);
cb(&op->addr_offset.offset, cb_metadata);
break;
case IR_OP_TY_BR:
break;
case IR_OP_TY_BR_SWITCH:
Expand All @@ -370,6 +380,9 @@ void walk_op_uses(struct ir_op *op, walk_op_callback *cb, void *cb_metadata) {
cb(&op->bitfield_insert.target, cb_metadata);
cb(&op->bitfield_insert.value, cb_metadata);
break;
case IR_OP_TY_MEM_SET:
cb(&op->mem_set.addr, cb_metadata);
break;
}
}

Expand Down Expand Up @@ -1425,6 +1438,34 @@ struct ir_glb *add_well_known_global(struct ir_unit *iru,
iru->well_known_glbs.memmove = memmove;
return memmove;
}
case IR_WELL_KNOWN_GLB_MEMSET: {
if (iru->well_known_glbs.memset) {
return iru->well_known_glbs.memset;
}

struct ir_var_ty *ptr = arena_alloc(iru->arena, sizeof(*ptr));
*ptr = IR_VAR_TY_POINTER;

size_t num_params = 3;
struct ir_var_ty *params =
arena_alloc(iru->arena, sizeof(*params) * num_params);

params[0] = IR_VAR_TY_POINTER;
params[1] = IR_VAR_TY_I32;
params[2] = var_ty_for_pointer_size(iru);

struct ir_var_ty var_ty = {.ty = IR_VAR_TY_TY_FUNC,
.func = {.ret_ty = ptr,
.num_params = num_params,
.params = params,
.flags = IR_VAR_FUNC_TY_FLAG_NONE}};

struct ir_glb *memset = add_global(iru, IR_GLB_TY_FUNC, &var_ty,
IR_GLB_DEF_TY_UNDEFINED, "memset");

iru->well_known_glbs.memset = memset;
return memset;
}
}
}

Expand Down
19 changes: 19 additions & 0 deletions ir/ir.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ enum ir_op_ty {
IR_OP_TY_BITFIELD_EXTRACT,
IR_OP_TY_BITFIELD_INSERT,

IR_OP_TY_MEM_SET,

IR_OP_TY_ADDR,
IR_OP_TY_ADDR_OFFSET,

IR_OP_TY_BR,
IR_OP_TY_BR_COND,
Expand Down Expand Up @@ -267,6 +270,12 @@ struct ir_op_call {
struct ir_var_ty *arg_var_tys;
};

struct ir_op_addr_offset {
struct ir_op *base;
struct ir_op *offset;
size_t scale;
};

struct ir_bitfield {
size_t offset;
size_t width;
Expand Down Expand Up @@ -368,6 +377,12 @@ struct ir_op_br_cond {
// targets on `ir_basicblock`
};

struct ir_op_mem_set {
struct ir_op *addr;
unsigned char value;
size_t length;
};

struct aarch64_op;
struct eep_op;

Expand Down Expand Up @@ -459,13 +474,15 @@ struct ir_op {
struct ir_op_unary_op unary_op;
struct ir_op_cast_op cast_op;
struct ir_op_ret ret;
struct ir_op_mem_set mem_set;
struct ir_op_store store;
struct ir_op_load load;
struct ir_op_store_bitfield store_bitfield;
struct ir_op_load_bitfield load_bitfield;
struct ir_op_bitfield_extract bitfield_extract;
struct ir_op_bitfield_insert bitfield_insert;
struct ir_op_addr addr;
struct ir_op_addr_offset addr_offset;
struct ir_op_br_cond br_cond;
struct ir_op_br_switch br_switch;
/* br has no entry, as its target is on `ir_basicblock` and it has no
Expand Down Expand Up @@ -725,11 +742,13 @@ struct ir_unit {

struct {
struct ir_glb *memmove;
struct ir_glb *memset;
} well_known_glbs;
};

enum ir_well_known_glb {
IR_WELL_KNOWN_GLB_MEMMOVE,
IR_WELL_KNOWN_GLB_MEMSET,
};

struct ir_glb *add_well_known_global(struct ir_unit *iru, enum ir_well_known_glb glb);
Expand Down
30 changes: 22 additions & 8 deletions ir/prettyprint.c
Original file line number Diff line number Diff line change
Expand Up @@ -439,20 +439,20 @@ static void debug_print_op(FILE *file, struct ir_func *irb, struct ir_op *ir,
switch (ir->load_bitfield.ty) {
case IR_OP_LOAD_TY_LCL:
if (ir->load_bitfield.glb) {
fprintf(file, "load.bitfield.lcl (#%zu, #%zu) LCL(%zu)", bitfield.offset,
bitfield.width, ir->load_bitfield.lcl->id);
fprintf(file, "load.bitfield.lcl (#%zu, #%zu) LCL(%zu)",
bitfield.offset, bitfield.width, ir->load_bitfield.lcl->id);
} else {
fprintf(file, "load.bitfield.lcl (#%zu, #%zu) LCL(UNASSIGNED)", bitfield.offset,
bitfield.width);
fprintf(file, "load.bitfield.lcl (#%zu, #%zu) LCL(UNASSIGNED)",
bitfield.offset, bitfield.width);
}
break;
case IR_OP_LOAD_TY_GLB:
if (ir->load_bitfield.glb) {
fprintf(file, "load.bitfield.glb (#%zu, #%zu) GLB(%zu)", bitfield.offset,
bitfield.width, ir->load_bitfield.glb->id);
fprintf(file, "load.bitfield.glb (#%zu, #%zu) GLB(%zu)",
bitfield.offset, bitfield.width, ir->load_bitfield.glb->id);
} else {
fprintf(file, "load.bitfield.glb (#%zu, #%zu) GLB(UNASSIGNED)", bitfield.offset,
bitfield.width);
fprintf(file, "load.bitfield.glb (#%zu, #%zu) GLB(UNASSIGNED)",
bitfield.offset, bitfield.width);
}
break;
case IR_OP_LOAD_TY_ADDR:
Expand All @@ -465,6 +465,15 @@ static void debug_print_op(FILE *file, struct ir_func *irb, struct ir_op *ir,

break;
}
case IR_OP_TY_ADDR_OFFSET:
fprintf(file, "addr.off ");
debug_print_op_use(file, irb, ir->addr_offset.base);
fprintf(file, " + ");
debug_print_op_use(file, irb, ir->addr_offset.offset);
if (ir->addr_offset.scale != 1) {
fprintf(file, " * %zu", ir->addr_offset.scale);
}
break;
case IR_OP_TY_ADDR:
switch (ir->addr.ty) {
case IR_OP_ADDR_TY_LCL:
Expand Down Expand Up @@ -546,6 +555,11 @@ static void debug_print_op(FILE *file, struct ir_func *irb, struct ir_op *ir,
fprintf(file, ", ");
debug_print_op_use(file, irb, ir->bitfield_insert.value);
break;
case IR_OP_TY_MEM_SET:
fprintf(file, "mem.set ");
debug_print_op_use(file, irb, ir->mem_set.addr);
fprintf(file, ", #%zu, #%d", ir->mem_set.length, ir->mem_set.value);
break;
}
}

Expand Down
Loading

0 comments on commit 33aa23e

Please sign in to comment.