From f7555f8269d74941e83963a52e69949b417bb485 Mon Sep 17 00:00:00 2001 From: "alexander.nutz" Date: Tue, 19 Nov 2024 16:24:50 +0100 Subject: [PATCH] wip --- cg/x86_stupid/cg.c | 87 +++++++++++++++++++++------------------------- common/common.c | 46 ++++++++++++++++++++++++ ir/ir.c | 49 ++++++++++++++------------ ir/ir.h | 60 ++++++++++++++------------------ ir/opt/if_opts.c | 11 +++--- ir/verify.h | 6 ++-- ir/verify_common.c | 49 +++++++++++++------------- ir/verify_ssa.c | 4 +-- 8 files changed, 173 insertions(+), 139 deletions(-) diff --git a/cg/x86_stupid/cg.c b/cg/x86_stupid/cg.c index 33b6163..5a702de 100644 --- a/cg/x86_stupid/cg.c +++ b/cg/x86_stupid/cg.c @@ -183,7 +183,7 @@ static char widthToWidthWidth(char width) { } return 16; } - return widthToWidthWidthLut[width]; + return widthToWidthWidthLut[(int) width]; } static char widthToWidthIdx(char width) { @@ -211,7 +211,7 @@ static char widthToWidthIdx(char width) { return 4; } - return lut[width]; + return lut[(int) width]; } static const char * widthWidthToASM[] = { @@ -262,26 +262,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; } } @@ -691,16 +691,15 @@ static Location* as_loc(size_t width, vx_IrValue val) { } } -static void emit_call_arg_load(vx_IrOp* callOp, FILE* file) { +static void emit_call_arg_load(vx_CU* cu, vx_IrOp* callOp, FILE* file) { assert(callOp->args_len <= 6); 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 }; @@ -848,7 +847,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_CU* cu, vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) { switch (op->id) { case VX_IR_OP_RETURN: { @@ -883,9 +882,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(ty), val); Location* src = val_loc; if (val_loc->type != LOC_REG) { @@ -960,19 +958,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(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 +1054,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(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); @@ -1244,7 +1239,7 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) vx_IrValue addr = *vx_IrOp_param(op->next, VX_IR_NAME_ADDR); vx_IrValue v = *vx_IrOp_param(op->next, VX_IR_NAME_COND); if (v.type == VX_IR_VAL_VAR && v.var == ov) { - emit_call_arg_load(op->next, file); + emit_call_arg_load(cu, op->next, file); emiti_jump_cond(as_loc(PTRSIZE, addr), cc, file); emit_call_ret_store(op->next, file); return op->next->next; @@ -1272,7 +1267,7 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) vx_IrValue cond = *vx_IrOp_param(op, VX_IR_NAME_COND); Location* loc = as_loc(1, cond); emiti_cmp0(loc, file); - emit_call_arg_load(op, file); + emit_call_arg_load(cu, op, file); emiti_jump_cond(as_loc(PTRSIZE, addr), "nz", file); } break; @@ -1299,7 +1294,7 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) case VX_IR_OP_CALL: // "addr": int / fnref { vx_IrValue addr = *vx_IrOp_param(op, VX_IR_NAME_ADDR); - emit_call_arg_load(op, file); + emit_call_arg_load(cu, op, file); emiti_call(as_loc(PTRSIZE, addr), file); emit_call_ret_store(op, file); } break; @@ -1308,7 +1303,7 @@ static vx_IrOp* emiti(vx_IrBlock* block, vx_IrOp *prev, vx_IrOp* op, FILE* file) { assert(!needEpilog); vx_IrValue addr = *vx_IrOp_param(op, VX_IR_NAME_ADDR); - emit_call_arg_load(op, file); + emit_call_arg_load(cu, op, file); emiti_jump(as_loc(PTRSIZE, addr), file); } break; @@ -1385,11 +1380,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 +1402,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; @@ -1678,7 +1671,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(cu, block, prev, op, out); prev = op; op = new; } @@ -1721,8 +1714,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..1d05db7 100644 --- a/ir/ir.c +++ b/ir/ir.c @@ -138,28 +138,30 @@ void vx_IrType_free(vx_IrType *ty) { } } -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 +255,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) diff --git a/ir/ir.h b/ir/ir.h index 854cf08..64d18bd 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 { @@ -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,18 +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; } -// TODO: move builder functions into separate header - -typedef struct { +struct vx_IrValue { enum { // storable VX_IR_VAL_IMM_INT, @@ -295,7 +309,7 @@ typedef struct { vx_IrType *ty; size_t id; }; -} vx_IrValue; +}; bool vx_IrValue_eq(vx_IrValue a, vx_IrValue b); @@ -600,32 +614,10 @@ 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); 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/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_common.c b/ir/verify_common.c index 0d0604b..40c22a8 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: @@ -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 ++) {