Exemple #1
0
struct rir_object *rirctx_alloc_write_add(
    struct rir_type *t,
    struct rir_value *value_to_write,
    struct rir_ctx *ctx)
{
    // allocate and initialize the object
    struct rir_object *obj = rir_alloca_create_obj(t, NULL, RIRPOS_AST, ctx);
    if (!obj) {
        return NULL;
    }
    rir_common_block_add(&ctx->common, &obj->expr);
    struct rir_expression *writeobj = rir_write_create(
        rir_object_value(obj),
        value_to_write,
        RIRPOS_AST,
        ctx
    );
    if (!writeobj) {
        return NULL;
    }
    rir_common_block_add(&ctx->common, writeobj);
    return obj;

}
Exemple #2
0
static struct rir_object *rir_convert_init(const struct rir_value *convval,
                                           const struct rir_type *totype,
                                           struct rir_ctx *ctx)
{
    struct rir_object *retobj = NULL;
    // at the moment only conversion to string requires special work
    if (!rir_type_is_specific_elementary(totype, ELEMENTARY_TYPE_STRING)) {
        if ((!(retobj = rir_object_create(RIR_OBJ_EXPRESSION, ctx->rir)))) {
            return NULL;
        }
        retobj->expr.convert.val = convval;
        retobj->expr.convert.type = totype;
        retobj->expr.type = RIR_EXPRESSION_PLACEHOLDER; // to signify we must continue
        return retobj;
    }

    // from here and down it's only about conversion to string
    if (convval->category == RIR_VALUE_CONSTANT) {
        // constant value to string conversion can be done easily here at compile time
        RFS_PUSH();
        const struct RFstring *temps = rir_constant_string(convval);
        if (!(retobj = rir_global_addorget_string(ctx, temps))) {
            RF_ERROR("Failed to add or get a global string literal to the RIR");
        }
        RFS_POP();
        return retobj;
    } else if (rir_type_is_specific_elementary(convval->type, ELEMENTARY_TYPE_BOOL)) {
        struct rir_object *obj;
        // boolean to string conversion requires some branching logic
        retobj = rir_alloca_create_obj(
            rir_type_elem_create(ELEMENTARY_TYPE_STRING, false),
            0,
            ctx
        );
        if (!retobj) {
            return NULL;
        }
        rirctx_block_add(ctx, &retobj->expr);
        struct rir_value *allocv = rir_object_value(retobj);
        // create the blocks
        struct rir_block *prev_block = ctx->current_block;
        struct rir_block *taken_block = rir_block_create(NULL, false, ctx);
        if (!taken_block) {
            return NULL;
        }
        struct rir_block *fallthrough_block = rir_block_create(NULL, false, ctx);
        if (!fallthrough_block) {
            return NULL;
        }
        struct rir_block *after_block = rir_block_create(NULL, false, ctx);
        if (!after_block) {
            return NULL;
        }

        // create the conditional branch to connect to if/else
        if (!rir_block_exit_init_condbranch(
                &prev_block->exit, convval, &taken_block->label, &fallthrough_block->label
            )) {
            return NULL;
        }

        // populate taken block
        ctx->current_block = taken_block;
        if (!(obj = rir_global_addorget_string(ctx, &g_str_true))) {
            RF_ERROR("Failed to add a global string literal to the RIR");
            return NULL;
        }
        struct rir_expression *e = rir_write_create(allocv, rir_object_value(obj), ctx);
        if (!e) {
            return NULL;
        }
        rirctx_block_add(ctx, e);
        if (!rir_block_exit_init_branch(&taken_block->exit, &after_block->label)) {
            return NULL;
        }
        rir_fndef_add_block(ctx->current_fn, taken_block);

        // populate fallthrough block
        ctx->current_block = fallthrough_block;
        if (!(obj = rir_global_addorget_string(ctx, &g_str_false))) {
            RF_ERROR("Failed to add a global string literal to the RIR");
            return NULL;
        }
        if (!(e = rir_write_create(allocv, rir_object_value(obj), ctx))) {
            return NULL;
        }
        rirctx_block_add(ctx, e);
        if (!rir_block_exit_init_branch(&fallthrough_block->exit, &after_block->label)) {
            return NULL;
        }
        rir_fndef_add_block(ctx->current_fn, fallthrough_block);

        // finally let's go to the after block and return the populated alloca which
        // should hold the value of the conversion
        rir_fndef_add_block(ctx->current_fn, after_block);
        ctx->current_block = after_block;
        return retobj;
    } else {
        RF_CRITICAL_FAIL("Unexpected conversion at RIR formation");
        return NULL;
    }
}