summaryrefslogtreecommitdiffstats
path: root/src/fluent-bit/lib/wasm-micro-runtime-WAMR-1.2.2/core/iwasm/compilation/aot_emit_exception.c
blob: d40ccc6a4cfe096032d6b1b5afe0b4bb13c82583 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
 * Copyright (C) 2019 Intel Corporation. All rights reserved.
 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 */

#include "aot_emit_exception.h"
#include "../interpreter/wasm_runtime.h"
#include "../aot/aot_runtime.h"

bool
aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                   int32 exception_id, bool is_cond_br, LLVMValueRef cond_br_if,
                   LLVMBasicBlockRef cond_br_else_block)
{
    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
    LLVMValueRef exce_id = I32_CONST((uint32)exception_id), func_const, func;
    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
    LLVMValueRef param_values[2];

    bh_assert(exception_id >= 0 && exception_id < EXCE_NUM);

    CHECK_LLVM_CONST(exce_id);

    /* Create got_exception block if needed */
    if (!func_ctx->got_exception_block) {
        if (!(func_ctx->got_exception_block = LLVMAppendBasicBlockInContext(
                  comp_ctx->context, func_ctx->func, "got_exception"))) {
            aot_set_last_error("add LLVM basic block failed.");
            return false;
        }

        LLVMPositionBuilderAtEnd(comp_ctx->builder,
                                 func_ctx->got_exception_block);

        /* Create exection id phi */
        if (!(func_ctx->exception_id_phi = LLVMBuildPhi(
                  comp_ctx->builder, I32_TYPE, "exception_id_phi"))) {
            aot_set_last_error("llvm build phi failed.");
            return false;
        }

        /* Call aot_set_exception_with_id() to throw exception */
        param_types[0] = INT8_PTR_TYPE;
        param_types[1] = I32_TYPE;
        ret_type = VOID_TYPE;

        /* Create function type */
        if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) {
            aot_set_last_error("create LLVM function type failed.");
            return false;
        }

        if (comp_ctx->is_jit_mode) {
            /* Create function type */
            if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
                aot_set_last_error("create LLVM function type failed.");
                return false;
            }
            /* Create LLVM function with const function pointer */
            if (!(func_const =
                      I64_CONST((uint64)(uintptr_t)jit_set_exception_with_id))
                || !(func = LLVMConstIntToPtr(func_const, func_ptr_type))) {
                aot_set_last_error("create LLVM value failed.");
                return false;
            }
        }
        else if (comp_ctx->is_indirect_mode) {
            int32 func_index;
            if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
                aot_set_last_error("create LLVM function type failed.");
                return false;
            }

            func_index = aot_get_native_symbol_index(
                comp_ctx, "aot_set_exception_with_id");
            if (func_index < 0) {
                return false;
            }
            if (!(func =
                      aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
                                              func_ptr_type, func_index))) {
                return false;
            }
        }
        else {
            /* Create LLVM function with external function pointer */
            if (!(func = LLVMGetNamedFunction(func_ctx->module,
                                              "aot_set_exception_with_id"))
                && !(func = LLVMAddFunction(func_ctx->module,
                                            "aot_set_exception_with_id",
                                            func_type))) {
                aot_set_last_error("add LLVM function failed.");
                return false;
            }
        }

        /* Call the aot_set_exception_with_id() function */
        param_values[0] = func_ctx->aot_inst;
        param_values[1] = func_ctx->exception_id_phi;
        if (!LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 2,
                            "")) {
            aot_set_last_error("llvm build call failed.");
            return false;
        }

        /* Create return IR */
        AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
        if (!aot_build_zero_function_ret(comp_ctx, func_ctx, aot_func_type)) {
            return false;
        }

        /* Resume the builder position */
        LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
    }

    /* Add phi incoming value to got_exception block */
    LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &block_curr, 1);

    if (!is_cond_br) {
        /* not condition br, create br IR */
        if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
            aot_set_last_error("llvm build br failed.");
            return false;
        }
    }
    else {
        /* Create condition br */
        if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if,
                             func_ctx->got_exception_block,
                             cond_br_else_block)) {
            aot_set_last_error("llvm build cond br failed.");
            return false;
        }
        /* Start to translate the else block */
        LLVMPositionBuilderAtEnd(comp_ctx->builder, cond_br_else_block);
    }

    return true;
fail:
    return false;
}