From edfa65a98a6cd94b24003183e88e97671a982275 Mon Sep 17 00:00:00 2001 From: alex_s168 <63254202+alex-s168@users.noreply.github.com> Date: Tue, 19 Nov 2024 20:34:37 +0100 Subject: [PATCH] refactor some stuff --- cg/x86_stupid/cg.c | 99 +++++++++++++++--------------- common/common.c | 46 ++++++++++++++ ir/ir.c | 119 ++++++++++++++++++------------------- ir/ir.h | 66 ++++++++++---------- ir/opt/if_opts.c | 11 ++-- ir/passes.c | 2 +- ir/transform/share_slots.c | 4 +- ir/verify.h | 6 +- ir/verify_cir.c | 2 +- ir/verify_common.c | 51 ++++++++-------- ir/verify_ssa.c | 4 +- 11 files changed, 225 insertions(+), 185 deletions(-) diff --git a/cg/x86_stupid/cg.c b/cg/x86_stupid/cg.c index 33b6163..b650b6d 100644 --- a/cg/x86_stupid/cg.c +++ b/cg/x86_stupid/cg.c @@ -60,7 +60,7 @@ static RegType REG_XMM9 = MkVecRegTy(25, 9); #define IsIntReg(rid) (rid < IntRegCount) #define VecRegId(rid) (rid - IntRegCount) -static RegType* RegLut[RegCount] = { +RegType* RegLut[RegCount] = { ®_RAX, ®_RBX, ®_RCX, ®_RSP, ®_RBP, ®_RDX, ®_RSI, ®_RDI, ®_R8, ®_R9, ®_R10, ®_R11, ®_R12, ®_R13, ®_R14, ®_R15, @@ -68,6 +68,9 @@ static RegType* RegLut[RegCount] = { ®_XMM4, ®_XMM5, ®_XMM6, ®_XMM7, }; +static vx_CU* cu; +static vx_IrBlock* block; + typedef enum { LOC_REG = 0, LOC_EA, @@ -183,7 +186,7 @@ static char widthToWidthWidth(char width) { } return 16; } - return widthToWidthWidthLut[width]; + return widthToWidthWidthLut[(int) width]; } static char widthToWidthIdx(char width) { @@ -211,7 +214,7 @@ static char widthToWidthIdx(char width) { return 4; } - return lut[width]; + return lut[(int) width]; } static const char * widthWidthToASM[] = { @@ -262,26 +265,26 @@ static void emit(Location* loc, FILE* out) { fprintf(out, "%zu", loc->v.imm.bits); break; - case LOC_MEM: { - char ww = widthToWidthWidth(loc->bytesWidth); - const char * str = widthWidthToASM[ww]; - fputs(str, out); - fputs(" [", out); - emit(loc->v.mem.address, out); - fputs("]", out); - } break; + case LOC_MEM: { + char ww = widthToWidthWidth(loc->bytesWidth); + const char * str = widthWidthToASM[(int) ww]; + fputs(str, out); + fputs(" [", out); + emit(loc->v.mem.address, out); + fputs("]", out); + } break; case LOC_REG: - fputs(RegLut[loc->v.reg.id]->name[widthToWidthIdx(loc->bytesWidth)], out); - break; + fputs(RegLut[loc->v.reg.id]->name[(int) widthToWidthIdx(loc->bytesWidth)], out); + break; case LOC_LABEL: - fputs(loc->v.label.label, out); - break; + fputs(loc->v.label.label, out); + break; case LOC_INVALID: - assert(false); - break; + assert(false); + break; } } @@ -696,17 +699,16 @@ static void emit_call_arg_load(vx_IrOp* callOp, FILE* file) { vx_IrValue fn = *vx_IrOp_param(callOp, VX_IR_NAME_ADDR); - vx_IrTypeRef type = vx_IrValue_type(callOp->parent, fn); - assert(type.ptr); - assert(type.ptr->kind == VX_IR_TYPE_FUNC); - vx_IrTypeFunc fnType = type.ptr->func; - vx_IrTypeRef_drop(type); + vx_IrType* type = vx_IrValue_type(cu, callOp->parent, fn); + assert(type); + assert(type->kind == VX_IR_TYPE_FUNC); + vx_IrTypeFunc fnType = type->func; char regs[6] = { REG_RDI.id, REG_RSI.id, REG_RDX.id, REG_RCX.id, REG_R8.id, REG_R9.id }; for (size_t i = 0; i < callOp->args_len; i ++) { vx_IrType* type = fnType.args[i]; - size_t size = vx_IrType_size(type); + size_t size = vx_IrType_size(cu, block, type); Location* src = as_loc(size, callOp->args[i]); Location* dest = gen_reg_var(size, regs[i]); emiti_move(src, dest, false, file); @@ -848,7 +850,7 @@ static void emiti_ret(vx_IrBlock* block, vx_IrValue* values, FILE* out) { fputs("ret\n", out); } -static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) { +static vx_IrOp* emiti(vx_IrOp *prev, vx_IrOp* op, FILE* file) { switch (op->id) { case VX_IR_OP_RETURN: { @@ -883,9 +885,8 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) *dest = LocReg(dest->bytesWidth, XMM_SCRATCH_REG1); } - vx_IrTypeRef ty = vx_IrValue_type(block, val); - Location* val_loc = as_loc(vx_IrType_size(ty.ptr), val); - vx_IrTypeRef_drop(ty); + vx_IrType* ty = vx_IrValue_type(cu, block, val); + Location* val_loc = as_loc(vx_IrType_size(cu, block, ty), val); Location* src = val_loc; if (val_loc->type != LOC_REG) { @@ -960,19 +961,17 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) { vx_IrValue addrV = *vx_IrOp_param(op, VX_IR_NAME_ADDR); vx_IrValue valV = *vx_IrOp_param(op, VX_IR_NAME_VALUE); - vx_IrTypeRef type = vx_IrValue_type(block, valV); - assert(type.ptr); + vx_IrType* type = vx_IrValue_type(cu, block, valV); + assert(type); Location* addr = as_loc(PTRSIZE, addrV); Location* addr_real = start_as_primitive(addr, file); - Location* val = as_loc(vx_IrType_size(type.ptr), valV); + Location* val = as_loc(vx_IrType_size(cu, block, type), valV); Location* mem = gen_mem_var(val->bytesWidth, addr_real); emiti_move(val, mem, false, file); end_as_primitive(addr_real, addr, file); - - vx_IrTypeRef_drop(type); } break; case VX_IR_OP_PLACE: // "var" @@ -1058,10 +1057,9 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) } case VX_IR_OP_STORE_EA: { - vx_IrTypeRef valTy = vx_IrValue_type(block, *vx_IrOp_param(op, VX_IR_NAME_VALUE)); - size_t bytes = vx_IrType_size(valTy.ptr); + vx_IrType* valTy = vx_IrValue_type(cu, block, *vx_IrOp_param(op, VX_IR_NAME_VALUE)); + size_t bytes = vx_IrType_size(cu, block, valTy); Location* val = as_loc(bytes, *vx_IrOp_param(op, VX_IR_NAME_VALUE)); - vx_IrTypeRef_drop(valTy); Location* mem = fastalloc(sizeof(Location)); *mem = LocMem(bytes, ea); emiti_move(val, mem, false, file); @@ -1320,7 +1318,10 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) return op->next; } -void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { +void vx_cg_x86stupid_gen(vx_CU* _cu, vx_IrBlock* _block, FILE* out) { + cu = _cu; + block = _block; + fprintf(out, "%s:\n", block->name); assert(block->is_root); @@ -1333,7 +1334,7 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { if (use_rax) { use_rax_type = block->ll_out_types[0]; assert(use_rax_type); - if (vx_IrType_size(use_rax_type) > 8) { + if (vx_IrType_size(cu, block, use_rax_type) > 8) { use_rax = false; use_rax_type = NULL; } else { @@ -1385,11 +1386,11 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { for (vx_IrOp* op = block->first; op != NULL; op = op->next) { if (op->id == VX_IR_OP_CALL || op->id == VX_IR_OP_TAILCALL || op->id == VX_IR_OP_CONDTAILCALL) { vx_IrValue addr = *vx_IrOp_param(op, VX_IR_NAME_ADDR); - vx_IrTypeRef ty = vx_IrValue_type(block, addr); - assert(ty.ptr != NULL); - assert(ty.ptr->kind == VX_IR_TYPE_FUNC); + vx_IrType* ty = vx_IrValue_type(cu, block, addr); + assert(ty != NULL); + assert(ty->kind == VX_IR_TYPE_FUNC); - vx_IrTypeFunc fn = ty.ptr->func; + vx_IrTypeFunc fn = ty->func; size_t usedInt = 0; size_t usedXmm = 0; @@ -1407,8 +1408,6 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { anyCalledIntArgsCount = usedInt; if (usedXmm > anyCalledXmmArgsCount) anyCalledXmmArgsCount = usedXmm; - - vx_IrTypeRef_drop(ty); } } XMM_SCRATCH_REG1 = anyCalledXmmArgsCount; @@ -1522,7 +1521,7 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { vx_IrType* type = varData[var].type; if (type == NULL) continue; - size_t size = vx_IrType_size(type); + size_t size = vx_IrType_size(cu, block, type); if (size > 8) continue; if (block->as_root.vars[var].ever_placed) continue; @@ -1535,7 +1534,7 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { } if (optLastRetFirstArg.present) { - size_t size = vx_IrType_size(varData[optLastRetFirstArg.var].type); + size_t size = vx_IrType_size(cu, block, varData[optLastRetFirstArg.var].type); size = widthToWidthWidth(size); varData[optLastRetFirstArg.var].location = gen_reg_var(size, REG_RAX.id); } @@ -1553,7 +1552,7 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { for (size_t i = 0; i < block->ins_len; i ++) { vx_IrTypedVar var = block->ins[i]; assert(var.type->kind == VX_IR_TYPE_KIND_BASE); - size_t size = vx_IrType_size(var.type); + size_t size = vx_IrType_size(cu, block, var.type); assert(size != 0); assert(varData); @@ -1640,7 +1639,7 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { if (varData[var].location) continue; if (varData[var].type == NULL) continue; - size_t size = vx_IrType_size(varData[var].type); + size_t size = vx_IrType_size(cu, block, varData[var].type); varData[var].location = gen_stack_var(size, stackOff); stackOff += size; anyPlaced = true; @@ -1678,7 +1677,7 @@ void vx_cg_x86stupid_gen(vx_CU* cu, vx_IrBlock* block, FILE* out) { vx_IrOp* prev = NULL; while (op != NULL) { - vx_IrOp* new = emiti(block, prev, op, out); + vx_IrOp* new = emiti(prev, op, out); prev = op; op = new; } @@ -1721,8 +1720,8 @@ static void end_scratch_reg(Location* loc, FILE* out) { assert(loc->type == LOC_REG); char regId = loc->v.reg.id; - assert(RegLut[regId]->stored == loc); - RegLut[regId]->stored = NULL; + assert(RegLut[(int) regId]->stored == loc); + RegLut[(int) regId]->stored = NULL; loc->type = LOC_INVALID; } diff --git a/common/common.c b/common/common.c index d6e258b..49cc8ac 100644 --- a/common/common.c +++ b/common/common.c @@ -40,6 +40,44 @@ int vx_Target_parse(vx_Target* dest, const char * str) return 0; } +/** these functions are used by targets where a pointer is a integer */ +#define intlikeptr(name, tgty, ptrtotypecache, ptrwbytes, ptralignbytes) \ +static vx_IrType* name##_get_ptr_ty(vx_CU* cu, vx_IrBlock* root) { \ + if ( ( ((tgty) cu->info.tg) ptrtotypecache) != NULL) return ( ((tgty) cu->info.tg) ptrtotypecache); \ + vx_IrType* ptr = vx_IrType_heap(); \ + ( ((tgty) cu->info.tg) ptrtotypecache) = ptr; \ + ptr->debugName = "ptr"; \ + ptr->kind = VX_IR_TYPE_KIND_BASE; \ + ptr->base = (vx_IrTypeBase) { \ + .sizeless = false, .size = (ptrwbytes), .align = (ptralignbytes), \ + .isfloat = false, \ + }; \ + return ptr;\ +} \ +static vx_IrValue name##_get_null_ptr(vx_CU* cu, vx_IrBlock* dest) { \ + return VX_IR_VALUE_IMM_INT(0); \ +} \ +static void name##_lower_ptr_math(vx_CU* cu, vx_IrOp* op) { /* no-op */ } \ +static vx_IrValue name##_cast_ptr_to_human(vx_CU* cu, vx_IrBlock* block, vx_IrVar ptr) { \ + return VX_IR_VALUE_VAR(ptr); \ +} \ +static void name##_intlikeptr(vx_TargetInfo* dest) { \ + dest->get_ptr_ty = name##_get_ptr_ty; \ + dest->get_null_ptr = name##_get_null_ptr; \ + dest->lower_ptr_math = name##_lower_ptr_math; \ + dest->cast_ptr_to_human = name##_cast_ptr_to_human; \ +} + +typedef struct { + vx_IrType* ptrty_cache; +} x86; +intlikeptr(x86, x86*,->ptrty_cache, 8, 4); + +typedef struct { + vx_IrType* ptrty_cache; +} etca; +intlikeptr(etca, etca*,->ptrty_cache, 4, 2); + static bool x86_need_move_ret_to_arg(vx_CU* cu, vx_IrBlock* block, size_t ret_id) { // TODO @@ -54,22 +92,30 @@ static bool etca_need_move_ret_to_arg(vx_CU* cu, vx_IrBlock* block, size_t ret_i void vx_Target_info(vx_TargetInfo* dest, vx_Target const* target) { + #define set_tg(ty) \ + dest->tg = fastalloc(sizeof(ty)); \ + memset(dest->tg, 0, sizeof(ty)); + memset(dest, 0, sizeof(vx_TargetInfo)); switch (target->arch) { case vx_TargetArch_X86_64: { + set_tg(x86); dest->cmov_opt = true; // TODO: target->flags.x86[vx_Target_X86_CMOV]; dest->tailcall_opt = true; dest->ea_opt = true; dest->need_move_ret_to_arg = x86_need_move_ret_to_arg; + x86_intlikeptr(dest); } break; case vx_TargetArch_ETCA: { + set_tg(etca); dest->cmov_opt = target->flags.etca[vx_Target_ETCA_condExec]; dest->tailcall_opt = true; dest->need_move_ret_to_arg = etca_need_move_ret_to_arg; + etca_intlikeptr(dest); } break; // add target diff --git a/ir/ir.c b/ir/ir.c index 7790331..d733c41 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -4,7 +4,6 @@ #include #include - vx_IrName vx_IrName_parse(const char * src, uint32_t srcLen) { for (vx_IrName i = 0; i < VX_IR_NAME__LAST; i ++) @@ -92,7 +91,7 @@ vx_IrOp *vx_IrBlock_tail(vx_IrBlock *block) { // TODO: remove cir checks and make sure fn called after cir type expand -size_t vx_IrType_size(vx_IrType *ty) { +size_t vx_IrType_size(vx_CU* cu, vx_IrBlock* inCtx, vx_IrType *ty) { assert(ty != NULL); size_t total = 0; @@ -103,63 +102,46 @@ size_t vx_IrType_size(vx_IrType *ty) { case VX_IR_TYPE_KIND_CIR_STRUCT: for (size_t i = 0; i < ty->cir_struct.members_len; i ++) { - total += vx_IrType_size(ty->cir_struct.members[i]); + total += vx_IrType_size(cu, inCtx, ty->cir_struct.members[i]); } return total; case VX_IR_TYPE_FUNC: - return 8; // TODO - - default: - fprintf(stderr, "type %u doesn't have size\n", ty->kind); - fflush(stderr); - exit(1); - assert(false); - return 0; - } -} - -void vx_IrType_free(vx_IrType *ty) { - switch (ty->kind) { - case VX_IR_TYPE_KIND_BASE: - return; - - case VX_IR_TYPE_KIND_CIR_STRUCT: - free(ty->cir_struct.members); - return; - - case VX_IR_TYPE_FUNC: - free(ty->func.args); - return; + return vx_IrType_size(cu, inCtx, cu->info.get_ptr_ty(cu, inCtx)); default: - assert(false); - return; + fprintf(stderr, "type %u doesn't have size\n", ty->kind); + fflush(stderr); + exit(1); + assert(false); + return 0; } } -vx_IrTypeRef vx_IrValue_type(vx_IrBlock* root, vx_IrValue value) { - switch (value.type) { +vx_IrType* vx_IrValue_type(vx_CU* cu, vx_IrBlock* root, vx_IrValue value) { + switch (value.type) + { case VX_IR_VAL_IMM_INT: case VX_IR_VAL_IMM_FLT: case VX_IR_VAL_UNINIT: - return (vx_IrTypeRef) { .ptr = value.no_read_rt_type, .shouldFree = false }; + return value.no_read_rt_type; case VX_IR_VAL_ID: - return vx_ptrType(root); + return cu->info.get_ptr_ty(cu, root); - default: - assert(false); - case VX_IR_VAL_TYPE: + case VX_IR_VAL_TYPE: case VX_IR_VAL_BLOCK: - return (vx_IrTypeRef) { .ptr = NULL, .shouldFree = false }; + return NULL; case VX_IR_VAL_BLOCKREF: return vx_IrBlock_type(value.block); case VX_IR_VAL_VAR: - return (vx_IrTypeRef) { .ptr = vx_IrBlock_typeofVar(root, value.var), .shouldFree = false }; - } + return vx_IrBlock_typeofVar(root, value.var); + + default: + assert(false); + } } void vx_IrOp_warn(vx_IrOp *op, const char *optMsg0, const char *optMsg1) { @@ -253,25 +235,26 @@ void vx_IrBlock_appendLabelOpPredefined(vx_IrBlock *block, size_t label_id) { root->as_root.labels[label_id].decl = label_decl; } -vx_IrTypeRef vx_IrBlock_type(vx_IrBlock* block) { - // TODO: multiple rets - vx_IrType *ret = block->outs_len == 1 ? vx_IrBlock_typeofVar(block, block->outs[0]) - : NULL; +vx_IrType* vx_IrBlock_type(vx_IrBlock* block) { + vx_IrType *type = fastalloc(sizeof(vx_IrType)); + assert(type); + type->kind = VX_IR_TYPE_FUNC; - vx_IrType **args = malloc(sizeof(vx_IrType*) * block->ins_len); + vx_IrType **args = fastalloc(sizeof(vx_IrType*) * block->ins_len); assert(args); - for (size_t i = 0; i < block->ins_len; i ++) { + for (size_t i = 0; i < block->ins_len; i ++) args[i] = block->ins[i].type; - } - - vx_IrType *type = malloc(sizeof(vx_IrType)); - assert(type); - type->kind = VX_IR_TYPE_FUNC; - type->func.nullableReturnType = ret; type->func.args_len = block->ins_len; type->func.args = args; - return (vx_IrTypeRef) { .ptr = type, .shouldFree = true }; + vx_IrType **rets = fastalloc(sizeof(vx_IrType*) * block->outs_len); + assert(rets); + for (size_t i = 0; i < block->outs_len; i ++) + rets[i] = vx_IrBlock_typeofVar(block, block->outs[i]); + type->func.rets_len = block->outs_len; + type->func.rets = rets; + + return type; } void vx_IrOp_updateParent(vx_IrOp* op, vx_IrBlock* to) @@ -306,7 +289,7 @@ int vx_CU_compile(vx_CU * cu, vx_CIrBlock_mksa_final(cu, block); vx_CIrBlock_fix(cu, block); // TODO: why... - if (vx_ir_verify(block) != 0) + if (vx_ir_verify(cu, block) != 0) return 1; }); @@ -316,7 +299,7 @@ int vx_CU_compile(vx_CU * cu, if (optionalOptimizedSsaIr != NULL) vx_IrBlock_dump(block, optionalOptimizedSsaIr, 0); - if (vx_ir_verify(block) != 0) + if (vx_ir_verify(cu, block) != 0) return 1; }); @@ -342,9 +325,10 @@ int vx_CU_compile(vx_CU * cu, if (optionalAsm) { for (size_t i = 0; i < cu->blocks_len; i ++) { vx_CUBlock* cb = &cu->blocks[i]; - switch (cu->blocks[i].type) { + switch (cb->type) { case VX_CU_BLOCK_IR: { + fprintf(optionalAsm, "section .text\n"); if (cb->do_export) fprintf(optionalAsm, " global %s\n", cb->v.ir->name); switch (cu->target.arch) @@ -364,15 +348,30 @@ int vx_CU_compile(vx_CU * cu, case VX_CU_BLOCK_BLK_REF: { + fprintf(optionalAsm, "section .text\n"); fprintf(optionalAsm, " extern %s\n", cb->v.blk_ref->name); break; } - - default: - { - assert(false && "wip"); - break; - } + + case VX_CU_BLOCK_ASM: + { + fprintf(optionalAsm, "section .text\n"); + fprintf(optionalAsm, "; generated by frontend\n%s\n", cb->v.asmb); + } + + case VX_CU_BLOCK_DATA: + { + fprintf(optionalAsm, "section .data\n"); + if (cb->do_export) + fprintf(optionalAsm, " global %s\n", cb->v.data->name); + fprintf(optionalAsm, "%s: ; <%zu * %s>\n", cb->v.data->name, + cb->v.data->numel, + cb->v.data->elty->debugName); + fprintf(optionalAsm, " db "); + for (size_t i = 0; i < cb->v.data->comptime_elt_size * cb->v.data->numel; i ++) + fprintf(optionalAsm, "%i, ", ((char *) cb->v.data->data)[i]); + fprintf(optionalAsm, "\n\n"); + } } } } diff --git a/ir/ir.h b/ir/ir.h index c0de4b7..95b642a 100644 --- a/ir/ir.h +++ b/ir/ir.h @@ -15,7 +15,7 @@ // TODO: use kollektions // TODO: add allocator similar to this to kallok (allibs) and use allocators here -// TODO make sure that all analysis functions iterate params AND args +// TODO: make sure that all analysis functions iterate params AND args AND abstract away for future vector types typedef size_t vx_IrVar; @@ -48,7 +48,7 @@ static const char * vx_OptIrVar_debug(vx_OptIrVar var) { if (var.present) { static char c[8]; sprintf(c, "%zu", var.var); - return c; + return c; } return "none"; } @@ -75,7 +75,8 @@ typedef struct { vx_IrType **args; size_t args_len; - vx_IrType *nullableReturnType; + vx_IrType **rets; + size_t rets_len; } vx_IrTypeFunc; typedef enum { @@ -106,9 +107,6 @@ static vx_IrType* vx_IrType_heap(void) { return ptr; } -size_t vx_IrType_size(vx_IrType *ty); -void vx_IrType_free(vx_IrType *ty); - static bool vx_IrType_compatible(vx_IrType *a, vx_IrType *b) { return a == b; // TODO (not used right now) } @@ -168,9 +166,12 @@ typedef enum { VX_CU_BLOCK_BLK_REF, VX_CU_BLOCK_ASM, VX_CU_BLOCK_DATA, + // TODO: DATA_REF } vx_CUBlockType; typedef struct { + // TODO: in the future: use vector types for data + char const* name; size_t numel; @@ -209,12 +210,27 @@ typedef struct { } vx_OptConfig; typedef struct vx_CU vx_CU; +typedef struct vx_IrValue vx_IrValue; typedef struct { + void* tg; + bool cmov_opt; bool tailcall_opt; bool ea_opt; bool (*need_move_ret_to_arg)(vx_CU* cu, vx_IrBlock* block, size_t ret_id); + + /** gets a pointer type valid for the given root block; result should be cached! */ + vx_IrType* (*get_ptr_ty)(vx_CU*, vx_IrBlock* root); + + /** appends instructions to [dest] to generate a vx_IrValue that is of type [get_ptr_ty] and represents a invalid pointer */ + vx_IrValue (*get_null_ptr)(vx_CU* cu, vx_IrBlock* dest); + + /** expand pointer addition or subtraction at this op; called in ssair */ + void (*lower_ptr_math)(vx_CU* cu, vx_IrOp* op); + + /** append instructions to the end of the block to generate operations that convert a pointer to a integer which is only used in things like printf("%p") */ + vx_IrValue (*cast_ptr_to_human)(vx_CU* cu, vx_IrBlock* block, vx_IrVar ptr); } vx_TargetInfo; void vx_Target_info(vx_TargetInfo* dest, vx_Target const* target); @@ -258,16 +274,16 @@ vx_IrBlock *vx_IrBlock_root(vx_IrBlock *block); // TODO: do differently -vx_Errors vx_IrBlock_verify(vx_IrBlock *block); +vx_Errors vx_IrBlock_verify(vx_CU* cu, vx_IrBlock *block); -static int vx_ir_verify(vx_IrBlock *block) { - const vx_Errors errs = vx_IrBlock_verify(block); +static int vx_ir_verify(vx_CU* cu, vx_IrBlock *block) { + const vx_Errors errs = vx_IrBlock_verify(cu, block); vx_Errors_print(errs, stderr); vx_Errors_free(errs); return errs.len > 0; } -typedef struct { +struct vx_IrValue { enum { // storable VX_IR_VAL_IMM_INT, @@ -293,7 +309,7 @@ typedef struct { vx_IrType *ty; size_t id; }; -} vx_IrValue; +}; bool vx_IrValue_eq(vx_IrValue a, vx_IrValue b); @@ -598,33 +614,13 @@ struct IrStaticIncrement { }; struct IrStaticIncrement vx_IrOp_detectStaticIncrement(vx_IrOp *op); -typedef struct { - vx_IrType *ptr; - bool shouldFree; -} vx_IrTypeRef; - -static void vx_IrTypeRef_drop(vx_IrTypeRef ref) { - if (ref.shouldFree) { - vx_IrType_free(ref.ptr); - } -} - -vx_IrTypeRef vx_IrBlock_type(vx_IrBlock* block); +vx_IrType* vx_IrBlock_type(vx_IrBlock* block); // null if depends on context or has no type -vx_IrTypeRef vx_IrValue_type(vx_IrBlock* root, vx_IrValue value); - -static vx_IrTypeRef vx_ptrType(vx_IrBlock* root) { - vx_IrType* type = vx_IrType_heap(); - type->kind = VX_IR_TYPE_KIND_BASE; - type->debugName = "ptr"; - type->base.size = 8; // TODO - type->base.align = 0; // ^^^ - type->base.isfloat = false; - type->base.sizeless = false; - return (vx_IrTypeRef) { .ptr = type, .shouldFree = true }; -} +vx_IrType* vx_IrValue_type(vx_CU* cu, vx_IrBlock* root, vx_IrValue value); bool vx_IrBlock_llIsLeaf(vx_IrBlock* block); +size_t vx_IrType_size(vx_CU* cu, vx_IrBlock* inCtx, vx_IrType *ty); + #endif //IR_H diff --git a/ir/opt/if_opts.c b/ir/opt/if_opts.c index 5f09fb2..2d502e9 100644 --- a/ir/opt/if_opts.c +++ b/ir/opt/if_opts.c @@ -1,15 +1,14 @@ #include "../passes.h" // TODO: move to ir/transform.c -static vx_IrVar genIntoVar(vx_IrBlock* block, vx_IrValue val) +static vx_IrVar genIntoVar(vx_CU* cu, vx_IrBlock* block, vx_IrValue val) { vx_IrOp* op = vx_IrBlock_addOpBuilding(block); vx_IrOp_init(op, VX_IR_OP_IMM, block); vx_IrBlock* root = vx_IrBlock_root(block); vx_IrVar var = vx_IrBlock_newVar(root, op); - vx_IrTypeRef ty = vx_IrValue_type(root, val); - vx_IrOp_addOut(op, var, ty.ptr); - vx_IrTypeRef_drop(ty); + vx_IrType* ty = vx_IrValue_type(cu, root, val); + vx_IrOp_addOut(op, var, ty); vx_IrOp_addParam_s(op, VX_IR_NAME_VALUE, val); return var; } @@ -78,8 +77,8 @@ void vx_opt_if_opts(vx_CU* cu, vx_IrBlock* block) size_t numRets = root->outs_len; for (size_t i = 0; i < numRets; i ++) { - vx_IrBlock_addOut(bthen, genIntoVar(bthen, thenLast->args[i])); - vx_IrBlock_addOut(belse, genIntoVar(belse, elseLast->args[i])); + vx_IrBlock_addOut(bthen, genIntoVar(cu, bthen, thenLast->args[i])); + vx_IrBlock_addOut(belse, genIntoVar(cu, belse, elseLast->args[i])); vx_IrVar va = vx_IrBlock_newVar(root, op); vx_IrOp_addOut(op, va, vx_IrBlock_typeofVar(root, root->outs[i])); diff --git a/ir/passes.c b/ir/passes.c index 0f94e32..e5bf5b5 100644 --- a/ir/passes.c +++ b/ir/passes.c @@ -144,7 +144,7 @@ void vx_IrBlock_llir_fix_decl(vx_CU* cu, vx_IrBlock *root) { for (vx_IrOp *op = root->first; op; op = op->next) { for (size_t j = 0; j < op->outs_len; j ++) { vx_IrTypedVar out = op->outs[j]; - if (vx_IrType_size(out.type) == 0) { + if (vx_IrType_size(cu, root, out.type) == 0) { fprintf(stderr, "size of type %s in 0", out.type->debugName); exit(1); } diff --git a/ir/transform/share_slots.c b/ir/transform/share_slots.c index 8f5cd68..b938b2e 100644 --- a/ir/transform/share_slots.c +++ b/ir/transform/share_slots.c @@ -106,7 +106,7 @@ void vx_IrBlock_ll_share_slots(vx_CU* cu, vx_IrBlock *block) if (type1 == NULL) continue; - size_t typeSize1 = vx_IrType_size(type1); + size_t typeSize1 = vx_IrType_size(cu, block, type1); for (vx_IrVar var2 = 0; var2 < block->as_root.vars_len; var2 ++) { if (var == var2) @@ -124,7 +124,7 @@ void vx_IrBlock_ll_share_slots(vx_CU* cu, vx_IrBlock *block) if (type2 == NULL) continue; - size_t typeSize2 = vx_IrType_size(type2); + size_t typeSize2 = vx_IrType_size(cu, block, type2); if (typeSize1 != typeSize2) continue; diff --git a/ir/verify.h b/ir/verify.h index 493b515..d4c85a1 100644 --- a/ir/verify.h +++ b/ir/verify.h @@ -5,10 +5,10 @@ // TODO: rename this to verify_int.h -void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block); +void vx_IrBlock_verify_ssa_based(vx_CU* cu, vx_Errors *dest, vx_IrBlock *block); -void vx_error_param_type(vx_Errors *errors, const char *expected); -void vx_error_param_missing(vx_Errors *errors, const char *param); +void vx_error_param_type(vx_CU* cu, vx_Errors *errors, const char *expected); +void vx_error_param_missing(vx_CU* cu, vx_Errors *errors, const char *param); #endif diff --git a/ir/verify_cir.c b/ir/verify_cir.c index 5377c97..3da64c6 100644 --- a/ir/verify_cir.c +++ b/ir/verify_cir.c @@ -7,7 +7,7 @@ vx_Errors vx_CIrBlock_verify(vx_CU* cu, vx_IrBlock *block) errors.items = NULL; errors.len = 0; - vx_IrBlock_verify_ssa_based(&errors, block); + vx_IrBlock_verify_ssa_based(cu, &errors, block); return errors; } diff --git a/ir/verify_common.c b/ir/verify_common.c index 0d0604b..84b419d 100644 --- a/ir/verify_common.c +++ b/ir/verify_common.c @@ -4,52 +4,53 @@ #include "ir.h" #include "verify.h" -void vx_error_param_type(vx_Errors *errors, const char *expected) { - static char buf[256]; +void vx_error_param_type(vx_CU* cu, vx_Errors *errors, const char *expected) { + char buf[256]; sprintf(buf, "Expected parameter type %s", expected); const vx_Error error = { .error = "Incorrect type", - .additional = buf + .additional = faststrdup(buf) }; vx_Errors_add(errors, &error); } -void vx_error_param_missing(vx_Errors *errors, const char *param) { - static char buf[256]; +void vx_error_param_missing(vx_CU* cu, vx_Errors *errors, const char *param) { + char buf[256]; sprintf(buf, "Missing required parameter %s", param); const vx_Error error = { .error = "Missing parameter", - .additional = buf + .additional = faststrdup(buf) }; vx_Errors_add(errors, &error); } -static bool analyze_if(vx_Errors *dest, +static bool analyze_if(vx_CU* cu, + vx_Errors *dest, const vx_IrOp *op) { bool err = false; const vx_IrValue *vcond = vx_IrOp_param(op, VX_IR_NAME_COND); if (vcond == NULL) { - vx_error_param_missing(dest, "cond"); + vx_error_param_missing(cu, dest, "cond"); err = true; } const vx_IrValue *vthen = vx_IrOp_param(op, VX_IR_NAME_COND_THEN); if (vthen == NULL) { - vx_error_param_missing(dest, "then"); + vx_error_param_missing(cu, dest, "then"); err = true; } else if (vthen->type != VX_IR_VAL_BLOCK) { - vx_error_param_type(dest, "block"); + vx_error_param_type(cu, dest, "block"); err = true; } const vx_IrValue *velse = vx_IrOp_param(op, VX_IR_NAME_COND_ELSE); if (velse == NULL) { - vx_error_param_missing(dest, "else"); + vx_error_param_missing(cu, dest, "else"); err = true; } else if (velse->type != VX_IR_VAL_BLOCK) { - vx_error_param_type(dest, "block"); + vx_error_param_type(cu, dest, "block"); err = true; } @@ -69,7 +70,8 @@ static bool analyze_if(vx_Errors *dest, return err; } -static void analyze_loops(vx_Errors *dest, +static void analyze_loops(vx_CU* cu, + vx_Errors *dest, const vx_IrOp *op) { const size_t states_count = op->outs_len; @@ -91,7 +93,7 @@ static void analyze_loops(vx_Errors *dest, } else { if (doblock_v->type != VX_IR_VAL_BLOCK) { - vx_error_param_type(dest, "block"); + vx_error_param_type(cu, dest, "block"); } else { const vx_IrBlock *doblock = doblock_v->block; @@ -106,7 +108,7 @@ static void analyze_loops(vx_Errors *dest, } } -void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { +void vx_IrBlock_verify_ssa_based(vx_CU* cu, vx_Errors *dest, vx_IrBlock *block) { vx_IrBlock *root = vx_IrBlock_root(block); for (vx_IrOp *op = block->first; op; op = op->next) { @@ -115,7 +117,7 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { sprintf(buf, "OP (%s) has different parent", vx_IrOpType__entries[op->id].debug.a); const vx_Error error = { .error = "Invalid parent", - .additional = strdup(buf) + .additional = faststrdup(buf) }; vx_Errors_add(dest, &error); } @@ -139,11 +141,11 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { case VX_IR_OP_REPEAT: case VX_IR_OP_INFINITE: case VX_IR_OP_WHILE: - analyze_loops(dest, op); + analyze_loops(cu, dest, op); break; case VX_IR_OP_IF: - (void) analyze_if(dest, op); + (void) analyze_if(cu, dest, op); break; case VX_IR_OP_GOTO: @@ -154,7 +156,7 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { sprintf(buf, "Label %%%zu is never declared!", label); vx_Error error = { .error = "Undeclared label", - .additional = strdup(buf) + .additional = faststrdup(buf) }; vx_Errors_add(dest, &error); } @@ -163,10 +165,9 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { case VX_IR_OP_CALL: case VX_IR_OP_CONDTAILCALL: { vx_IrValue addr = *vx_IrOp_param(op, VX_IR_NAME_ADDR); - vx_IrTypeRef ty = vx_IrValue_type((vx_IrBlock*) root, addr); - assert(ty.ptr); - assert(ty.ptr->kind == VX_IR_TYPE_FUNC); - vx_IrTypeRef_drop(ty); + vx_IrType* ty = vx_IrValue_type(cu, (vx_IrBlock*) root, addr); + assert(ty); + assert(ty->kind == VX_IR_TYPE_FUNC); } break; default: @@ -182,7 +183,7 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { }; vx_Errors_add(dest, &error); } - vx_Errors errs = vx_IrBlock_verify(val.block); + vx_Errors errs = vx_IrBlock_verify(cu, val.block); vx_Errors_add_all_and_free(dest, &errs); } else if (val.type == VX_IR_VAL_VAR) { @@ -193,7 +194,7 @@ void vx_IrBlock_verify_ssa_based(vx_Errors *dest, vx_IrBlock *block) { sprintf(buf, "Variable %%%zu is never declared!", var); vx_Error error = { .error = "Undeclared variable", - .additional = strdup(buf) + .additional = faststrdup(buf) }; vx_Errors_add(dest, &error); } diff --git a/ir/verify_ssa.c b/ir/verify_ssa.c index a1c0cf3..900d25d 100644 --- a/ir/verify_ssa.c +++ b/ir/verify_ssa.c @@ -29,12 +29,12 @@ static bool verify_vardecls_deeptraverse(vx_IrOp *op, void *dataIn) { return false; } -vx_Errors vx_IrBlock_verify(vx_IrBlock *block) { +vx_Errors vx_IrBlock_verify(vx_CU* cu, vx_IrBlock *block) { vx_Errors errors; errors.len = 0; errors.items = NULL; - vx_IrBlock_verify_ssa_based(&errors, block); + vx_IrBlock_verify_ssa_based(cu, &errors, block); if (block->is_root) { for (size_t i = 0; i < block->as_root.vars_len; i ++) {