static inline bool rir_binaryop_init(struct rir_binaryop *op, const struct rir_value *a, const struct rir_value *b, struct rir_ctx *ctx) { struct rir_expression *e; // for operations on pointers, first create a read from memory if (a->type->is_pointer) { if (!(e = rir_read_create(a, ctx))) { return false; } rirctx_block_add(ctx, e); a = &e->val; } if (b->type->is_pointer) { if (!(e = rir_read_create(b, ctx))) { return false; } rirctx_block_add(ctx, e); b = &e->val; } // in addition if any of the two operands are not the same make a conversion // of the largest type, to the smallest type. if (!rir_type_equal(a->type, b->type)) { struct rir_object *obj; if (rir_type_bytesize(a->type) >= rir_type_bytesize(b->type)) { if (!(obj = rir_convert_create_obj_maybeadd(a, b->type, ctx))) { return false; } a = rir_object_value(obj); } else { if (!(obj = rir_convert_create_obj_maybeadd(b, a->type, ctx))) { return false; } b = rir_object_value(obj); } } op->a = a; op->b = b; return true; }
struct rir_value *rirctx_getread_val(struct rir_value *v, struct rir_ctx *ctx) { // if a pointer and not a string, also perform a read if (!v->type->is_pointer || rir_type_no_read_required(v->type)) { return v; } struct rir_expression *read; read = rir_read_create(v, RIRPOS_AST, ctx); if (!read) { RF_ERROR("Failed to create a read RIR instruction"); return NULL; } rir_common_block_add(&ctx->common, read); return &read->val; }
struct rir_expression *rirctx_getread_expr(struct rir_expression *e, struct rir_ctx *ctx) { struct rir_expression *ret = NULL; // gotta read the memory value from an alloca // unless it's a string, which is passed by pointer at least at the moment if (e->type == RIR_EXPRESSION_ALLOCA && !rir_type_no_read_required(e->alloca.type)) { struct rir_expression *read; read = rir_read_create(&e->val, RIRPOS_AST, ctx); if (!read) { RF_ERROR("Failed to create a read RIR instruction"); return NULL; } rir_common_block_add(&ctx->common, read); ret = read; } else { ret = e; } return ret; }