Пример #1
0
struct LLVMOpaqueValue *bllvm_compile_rirbop(const struct rir_expression *expr,
                                             struct llvm_traversal_ctx *ctx)
{
    LLVMValueRef ret;
    LLVMValueRef left = bllvm_value_from_rir_value_or_die(expr->binaryop.a, ctx);
    LLVMValueRef right = bllvm_value_from_rir_value_or_die(expr->binaryop.b, ctx);
    switch(expr->type) {
    case RIR_EXPRESSION_ADD:
        ret = LLVMBuildAdd(ctx->builder, left, right, "");
        break;
    case RIR_EXPRESSION_SUB:
        ret = LLVMBuildSub(ctx->builder, left, right, "");
        break;
    case RIR_EXPRESSION_MUL:
        ret = LLVMBuildMul(ctx->builder, left, right, "");
        break;
    case RIR_EXPRESSION_DIV:
        ret = LLVMBuildUDiv(ctx->builder, left, right, "");
        break;
    default:
        RF_CRITICAL_FAIL("Should never get anything other than binaryop here");
        break;
    }
    return ret;
}
Пример #2
0
const struct RFstring *ast_identifier_analyzed_str(const struct ast_node *n)
{
    RF_ASSERT(n->type == AST_IDENTIFIER || n->type == AST_XIDENTIFIER,
              "Unexpected ast node type");
    AST_NODE_ASSERT_STATE(n, AST_NODE_STATE_ANALYZER_PASS1);

    RF_CRITICAL_FAIL("function not implemented yet");
    return NULL;
#if 0 // this is not used anywhere atm. If that changes either pass the module
      // or each node should know which module it belongs to.
    if (n->type == AST_IDENTIFIER) {
        return string_table_get_str(a->identifiers_table, n->identifier.hash);
    }
    return string_table_get_str(a->identifiers_table,
                                n->xidentifier.id->identifier.hash);
#endif
}
Пример #3
0
// populate for generic non-top level type element
static bool analyzer_populate_symbol_table_typeelement(struct analyzer_traversal_ctx *ctx,
                                                       struct ast_node *n)
{
    switch (n->type) {
    case AST_TYPE_LEAF:
        return analyzer_populate_symbol_table_typeleaf(ctx, n);
    case AST_TYPE_OPERATOR:
        return analyzer_populate_symbol_table_typeelement(ctx, ast_typeop_left(n)) &&
            analyzer_populate_symbol_table_typeelement(ctx, ast_typeop_right(n));
    case AST_TYPE_DESCRIPTION:
        // don't go further into a recursive top level typedesc. Should be handled by the
        // main loop
    case AST_XIDENTIFIER: //fallthrough
        // don't do anything for right part of leaves that are simply identifiers
        return true;
    default:
        RF_CRITICAL_FAIL("Case should never happen");
        return false;
    }
}
Пример #4
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;
    }
}
Пример #5
0
LLVMValueRef bllvm_compile_comparison(const struct rir_expression *expr,
                                      struct llvm_traversal_ctx *ctx)
{
    LLVMValueRef left = bllvm_value_from_rir_value_or_die(expr->binaryop.a, ctx);
    LLVMValueRef right = bllvm_value_from_rir_value_or_die(expr->binaryop.b, ctx);
    struct rir_type *typea = expr->binaryop.a->type;
    struct rir_type *typeb = expr->binaryop.b->type;
    RF_ASSERT(rir_type_is_elementary(typea), "Backend comparisons should only happen with elementary types");
    RF_ASSERT(rir_type_is_elementary(typeb), "Backend comparisons should only happen with elementary types");
    RF_ASSERT(typea->etype == typeb->etype, "Comparison should only happen with same type");

    // TODO: Maybe take into account signedness?
    if (elementary_type_is_float(typea->etype)) {
        LLVMRealPredicate llvm_real_compare_type;
        switch(expr->type) {
        case RIR_EXPRESSION_CMP_EQ:
                llvm_real_compare_type = LLVMRealOEQ;
            break;
        case RIR_EXPRESSION_CMP_NE:
                llvm_real_compare_type = LLVMRealONE;
            break;
        case RIR_EXPRESSION_CMP_GE:
                llvm_real_compare_type = LLVMRealOGE;
            break;
        case RIR_EXPRESSION_CMP_GT:
                llvm_real_compare_type = LLVMRealOGT;
            break;
        case RIR_EXPRESSION_CMP_LE:
                llvm_real_compare_type = LLVMRealOLE;
            break;
        case RIR_EXPRESSION_CMP_LT:
                llvm_real_compare_type = LLVMRealOLT;
            break;
        default:
            RF_CRITICAL_FAIL("Illegal operand types at comparison code generation");
            return NULL;
            break;
        }
        return LLVMBuildFCmp(ctx->builder, llvm_real_compare_type, left, right, "");
    }
    LLVMIntPredicate llvm_int_compare_type;
    switch(expr->type) {
    case RIR_EXPRESSION_CMP_EQ:
        llvm_int_compare_type = LLVMIntEQ;
        break;
    case RIR_EXPRESSION_CMP_NE:
        llvm_int_compare_type = LLVMIntNE;
        break;
    case RIR_EXPRESSION_CMP_GE:
        llvm_int_compare_type = LLVMIntUGE;
        break;
    case RIR_EXPRESSION_CMP_GT:
        llvm_int_compare_type = LLVMIntUGT;
        break;
    case RIR_EXPRESSION_CMP_LE:
        llvm_int_compare_type = LLVMIntULE;
        break;
    case RIR_EXPRESSION_CMP_LT:
        llvm_int_compare_type = LLVMIntULT;
        break;
    default:
            RF_CRITICAL_FAIL("Illegal operand types at comparison code generation");
            return NULL;
        break;
    }
    return LLVMBuildICmp(ctx->builder, llvm_int_compare_type, left, right, "");
}