@@ -1620,9 +1620,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
16201620
16211621 if (llvm_data_end_global && llvm_heap_base_global ) {
16221622 if ((data_end_global_index == heap_base_global_index + 1
1623- && data_end_global_index > 0 )
1623+ && ( int32 ) data_end_global_index > 1 )
16241624 || (heap_base_global_index == data_end_global_index + 1
1625- && heap_base_global_index > 0 )) {
1625+ && ( int32 ) heap_base_global_index > 1 )) {
16261626 global_index =
16271627 data_end_global_index < heap_base_global_index
16281628 ? data_end_global_index - 1 : heap_base_global_index - 1 ;
@@ -2716,6 +2716,128 @@ wasm_loader_check_br(WASMLoaderContext *ctx, uint32 depth,
27162716}
27172717
27182718#if WASM_ENABLE_FAST_INTERP != 0
2719+
2720+ #if WASM_ENABLE_ABS_LABEL_ADDR != 0
2721+
2722+ #define emit_label (opcode ) do { \
2723+ wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \
2724+ LOG_OP("\nemit_op [%02x]\t", opcode); \
2725+ } while (0)
2726+
2727+ #define skip_label () do { \
2728+ wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \
2729+ LOG_OP("\ndelete last op\n"); \
2730+ } while (0)
2731+
2732+ #else
2733+
2734+ #define emit_label (opcode ) do { \
2735+ int32 offset = (int32)(handle_table[opcode] - handle_table[0]); \
2736+ if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \
2737+ set_error_buf(error_buf, error_buf_size, \
2738+ "WASM module load failed: " \
2739+ "pre-compiled label offset out of range"); \
2740+ goto fail; \
2741+ } \
2742+ wasm_loader_emit_int16(loader_ctx, offset); \
2743+ LOG_OP("\nemit_op [%02x]\t", opcode); \
2744+ } while (0)
2745+
2746+ // drop local.get / const / block / loop / end
2747+ #define skip_label () do { \
2748+ wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \
2749+ LOG_OP("\ndelete last op\n"); \
2750+ } while (0)
2751+
2752+ #endif /* WASM_ENABLE_ABS_LABEL_ADDR */
2753+
2754+ #define emit_empty_label_addr_and_frame_ip (type ) do { \
2755+ if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \
2756+ loader_ctx->p_code_compiled, \
2757+ error_buf, error_buf_size)) \
2758+ goto fail; \
2759+ /* label address, to be patched */ \
2760+ wasm_loader_emit_ptr (loader_ctx , NULL ); \
2761+ } while (0 )
2762+
2763+ #define emit_br_info (frame_csp ) do { \
2764+ if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \
2765+ error_buf, error_buf_size)) \
2766+ goto fail; \
2767+ } while (0)
2768+
2769+ #define LAST_OP_OUTPUT_I32 () (last_op >= WASM_OP_I32_EQZ \
2770+ && last_op <= WASM_OP_I32_ROTR) \
2771+ || (last_op == WASM_OP_I32_LOAD \
2772+ || last_op == WASM_OP_F32_LOAD) \
2773+ || (last_op >= WASM_OP_I32_LOAD8_S \
2774+ && last_op <= WASM_OP_I32_LOAD16_U) \
2775+ || (last_op >= WASM_OP_F32_ABS \
2776+ && last_op <= WASM_OP_F32_COPYSIGN) \
2777+ || (last_op >= WASM_OP_I32_WRAP_I64 \
2778+ && last_op <= WASM_OP_I32_TRUNC_U_F64) \
2779+ || (last_op >= WASM_OP_F32_CONVERT_S_I32 \
2780+ && last_op <= WASM_OP_F32_DEMOTE_F64) \
2781+ || (last_op == WASM_OP_I32_REINTERPRET_F32) \
2782+ || (last_op == WASM_OP_F32_REINTERPRET_I32) \
2783+ || (last_op == EXT_OP_COPY_STACK_TOP)
2784+
2785+ #define LAST_OP_OUTPUT_I64 () (last_op >= WASM_OP_I64_CLZ \
2786+ && last_op <= WASM_OP_I64_ROTR) \
2787+ || (last_op >= WASM_OP_F64_ABS \
2788+ && last_op <= WASM_OP_F64_COPYSIGN) \
2789+ || (last_op == WASM_OP_I64_LOAD \
2790+ || last_op == WASM_OP_F64_LOAD) \
2791+ || (last_op >= WASM_OP_I64_LOAD8_S \
2792+ && last_op <= WASM_OP_I64_LOAD32_U) \
2793+ || (last_op >= WASM_OP_I64_EXTEND_S_I32 \
2794+ && last_op <= WASM_OP_I64_TRUNC_U_F64) \
2795+ || (last_op >= WASM_OP_F64_CONVERT_S_I32 \
2796+ && last_op <= WASM_OP_F64_PROMOTE_F32) \
2797+ || (last_op == WASM_OP_I64_REINTERPRET_F64) \
2798+ || (last_op == WASM_OP_F64_REINTERPRET_I64) \
2799+ || (last_op == EXT_OP_COPY_STACK_TOP_I64)
2800+
2801+ #define GET_CONST_OFFSET (type , val ) do { \
2802+ if (!(wasm_loader_get_const_offset(loader_ctx, type, \
2803+ val, 0, 0, &operand_offset, \
2804+ error_buf, error_buf_size))) \
2805+ goto fail; \
2806+ } while (0)
2807+
2808+ #define GET_CONST_F32_OFFSET (type , fval ) do { \
2809+ if (!(wasm_loader_get_const_offset(loader_ctx, type, \
2810+ 0, fval, 0, &operand_offset, \
2811+ error_buf, error_buf_size))) \
2812+ goto fail; \
2813+ } while (0)
2814+
2815+ #define GET_CONST_F64_OFFSET (type , fval ) do { \
2816+ if (!(wasm_loader_get_const_offset(loader_ctx, type, \
2817+ 0, 0, fval, &operand_offset, \
2818+ error_buf, error_buf_size))) \
2819+ goto fail; \
2820+ } while (0)
2821+
2822+ #define emit_operand (ctx , offset ) do { \
2823+ wasm_loader_emit_int16(ctx, offset); \
2824+ LOG_OP("%d\t", offset); \
2825+ } while (0)
2826+
2827+ #define emit_byte (ctx , byte ) do { \
2828+ wasm_loader_emit_uint8(ctx, byte); \
2829+ LOG_OP("%d\t", byte); \
2830+ } while (0)
2831+
2832+ #define emit_leb () do { \
2833+ wasm_loader_emit_leb(loader_ctx, p_org, p); \
2834+ } while (0)
2835+
2836+ #define emit_const (value ) do { \
2837+ GET_CONST_OFFSET(VALUE_TYPE_I32, value); \
2838+ emit_operand(loader_ctx, operand_offset); \
2839+ } while (0)
2840+
27192841static bool
27202842wasm_loader_ctx_reinit (WASMLoaderContext * ctx )
27212843{
@@ -2803,6 +2925,47 @@ wasm_loader_emit_leb(WASMLoaderContext *ctx, uint8* start, uint8* end)
28032925
28042926}
28052927
2928+ static bool
2929+ preserve_referenced_local (WASMLoaderContext * loader_ctx , uint8 opcode ,
2930+ uint32 local_index , uint32 local_type , bool * preserved ,
2931+ char * error_buf , uint32 error_buf_size )
2932+ {
2933+ int16 preserved_offset = (int16 )local_index ;
2934+ * preserved = false;
2935+ for (uint32 i = 0 ; i < loader_ctx -> stack_cell_num ; i ++ ) {
2936+ /* move previous local into dynamic space before a set/tee_local opcode */
2937+ if (loader_ctx -> frame_offset_bottom [i ] == (int16 )local_index ) {
2938+ if (preserved_offset == (int16 )local_index ) {
2939+ * preserved = true;
2940+ skip_label ();
2941+ if (local_type == VALUE_TYPE_I32
2942+ || local_type == VALUE_TYPE_F32 ) {
2943+ preserved_offset = loader_ctx -> dynamic_offset ++ ;
2944+ emit_label (EXT_OP_COPY_STACK_TOP );
2945+ }
2946+ else {
2947+ preserved_offset = loader_ctx -> dynamic_offset ;
2948+ loader_ctx -> dynamic_offset += 2 ;
2949+ emit_label (EXT_OP_COPY_STACK_TOP_I64 );
2950+ }
2951+ emit_operand (loader_ctx , local_index );
2952+ emit_operand (loader_ctx , preserved_offset );
2953+ emit_label (opcode );
2954+ if (loader_ctx -> dynamic_offset > loader_ctx -> max_dynamic_offset )
2955+ loader_ctx -> max_dynamic_offset = loader_ctx -> dynamic_offset ;
2956+ }
2957+ loader_ctx -> frame_offset_bottom [i ] = preserved_offset ;
2958+ }
2959+ }
2960+
2961+ return true;
2962+
2963+ #if WASM_ENABLE_ABS_LABEL_ADDR == 0
2964+ fail :
2965+ return false;
2966+ #endif
2967+ }
2968+
28062969static bool
28072970add_label_patch_to_list (BranchBlock * frame_csp ,
28082971 uint8 patch_type , uint8 * p_code_compiled ,
@@ -2858,25 +3021,6 @@ apply_label_patch(WASMLoaderContext *ctx, uint8 depth,
28583021 }
28593022}
28603023
2861- #define emit_operand (ctx , offset ) do { \
2862- wasm_loader_emit_int16(ctx, offset); \
2863- LOG_OP("%d\t", offset); \
2864- } while (0)
2865-
2866- #define emit_byte (ctx , byte ) do { \
2867- wasm_loader_emit_uint8(ctx, byte); \
2868- LOG_OP("%d\t", byte); \
2869- } while (0)
2870-
2871- #define emit_leb () do { \
2872- wasm_loader_emit_leb(loader_ctx, p_org, p); \
2873- } while (0)
2874-
2875- #define emit_const (value ) do { \
2876- GET_CONST_OFFSET(VALUE_TYPE_I32, value); \
2877- emit_operand(loader_ctx, operand_offset); \
2878- } while (0)
2879-
28803024static bool
28813025wasm_loader_emit_br_info (WASMLoaderContext * ctx , BranchBlock * frame_csp ,
28823026 char * error_buf , uint32 error_buf_size )
@@ -3270,107 +3414,7 @@ check_memory(WASMModule *module,
32703414 } while (0)
32713415
32723416#if WASM_ENABLE_FAST_INTERP != 0
3273- #if WASM_ENABLE_ABS_LABEL_ADDR != 0
3274-
3275- #define emit_label (opcode ) do { \
3276- wasm_loader_emit_ptr(loader_ctx, handle_table[opcode]); \
3277- LOG_OP("\nemit_op [%02x]\t", opcode); \
3278- } while (0)
3279-
3280- #define skip_label () do { \
3281- wasm_loader_emit_backspace(loader_ctx, sizeof(void *)); \
3282- LOG_OP("\ndelete last op\n"); \
3283- } while (0)
3284-
3285- #else
3286-
3287- #define emit_label (opcode ) do { \
3288- int32 offset = (int32)(handle_table[opcode] - handle_table[0]); \
3289- if (!(offset >= INT16_MIN && offset < INT16_MAX)) { \
3290- set_error_buf(error_buf, error_buf_size, \
3291- "WASM module load failed: " \
3292- "pre-compiled label offset out of range"); \
3293- goto fail; \
3294- } \
3295- wasm_loader_emit_int16(loader_ctx, offset); \
3296- LOG_OP("\nemit_op [%02x]\t", opcode); \
3297- } while (0)
3298-
3299- // drop local.get / const / block / loop / end
3300- #define skip_label () do { \
3301- wasm_loader_emit_backspace(loader_ctx, sizeof(int16)); \
3302- LOG_OP("\ndelete last op\n"); \
3303- } while (0)
3304-
3305- #endif /* WASM_ENABLE_ABS_LABEL_ADDR */
3306-
3307- #define emit_empty_label_addr_and_frame_ip (type ) do { \
3308- if (!add_label_patch_to_list(loader_ctx->frame_csp - 1, type, \
3309- loader_ctx->p_code_compiled, \
3310- error_buf, error_buf_size)) \
3311- goto fail; \
3312- /* label address, to be patched */ \
3313- wasm_loader_emit_ptr (loader_ctx , NULL ); \
3314- } while (0 )
33153417
3316- #define emit_br_info (frame_csp ) do { \
3317- if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, \
3318- error_buf, error_buf_size)) \
3319- goto fail; \
3320- } while (0)
3321-
3322- #define LAST_OP_OUTPUT_I32 () (last_op >= WASM_OP_I32_EQZ \
3323- && last_op <= WASM_OP_I32_ROTR) \
3324- || (last_op == WASM_OP_I32_LOAD \
3325- || last_op == WASM_OP_F32_LOAD) \
3326- || (last_op >= WASM_OP_I32_LOAD8_S \
3327- && last_op <= WASM_OP_I32_LOAD16_U) \
3328- || (last_op >= WASM_OP_F32_ABS \
3329- && last_op <= WASM_OP_F32_COPYSIGN) \
3330- || (last_op >= WASM_OP_I32_WRAP_I64 \
3331- && last_op <= WASM_OP_I32_TRUNC_U_F64) \
3332- || (last_op >= WASM_OP_F32_CONVERT_S_I32 \
3333- && last_op <= WASM_OP_F32_DEMOTE_F64) \
3334- || (last_op == WASM_OP_I32_REINTERPRET_F32) \
3335- || (last_op == WASM_OP_F32_REINTERPRET_I32) \
3336- || (last_op == EXT_OP_COPY_STACK_TOP)
3337-
3338- #define LAST_OP_OUTPUT_I64 () (last_op >= WASM_OP_I64_CLZ \
3339- && last_op <= WASM_OP_I64_ROTR) \
3340- || (last_op >= WASM_OP_F64_ABS \
3341- && last_op <= WASM_OP_F64_COPYSIGN) \
3342- || (last_op == WASM_OP_I64_LOAD \
3343- || last_op == WASM_OP_F64_LOAD) \
3344- || (last_op >= WASM_OP_I64_LOAD8_S \
3345- && last_op <= WASM_OP_I64_LOAD32_U) \
3346- || (last_op >= WASM_OP_I64_EXTEND_S_I32 \
3347- && last_op <= WASM_OP_I64_TRUNC_U_F64) \
3348- || (last_op >= WASM_OP_F64_CONVERT_S_I32 \
3349- && last_op <= WASM_OP_F64_PROMOTE_F32) \
3350- || (last_op == WASM_OP_I64_REINTERPRET_F64) \
3351- || (last_op == WASM_OP_F64_REINTERPRET_I64) \
3352- || (last_op == EXT_OP_COPY_STACK_TOP_I64)
3353-
3354- #define GET_CONST_OFFSET (type , val ) do { \
3355- if (!(wasm_loader_get_const_offset(loader_ctx, type, \
3356- val, 0, 0, &operand_offset, \
3357- error_buf, error_buf_size))) \
3358- goto fail; \
3359- } while (0)
3360-
3361- #define GET_CONST_F32_OFFSET (type , fval ) do { \
3362- if (!(wasm_loader_get_const_offset(loader_ctx, type, \
3363- 0, fval, 0, &operand_offset, \
3364- error_buf, error_buf_size))) \
3365- goto fail; \
3366- } while (0)
3367-
3368- #define GET_CONST_F64_OFFSET (type , fval ) do { \
3369- if (!(wasm_loader_get_const_offset(loader_ctx, type, \
3370- 0, 0, fval, &operand_offset, \
3371- error_buf, error_buf_size))) \
3372- goto fail; \
3373- } while (0)
33743418
33753419#endif /* WASM_ENABLE_FAST_INTERP */
33763420
@@ -3395,7 +3439,7 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
33953439 uint8 * func_const_end , * func_const ;
33963440 int16 operand_offset ;
33973441 uint8 last_op = 0 ;
3398- bool disable_emit ;
3442+ bool disable_emit , preserve_local = false ;
33993443 float32 f32 ;
34003444 float64 f64 ;
34013445
@@ -3997,15 +4041,20 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
39974041 POP_TYPE (local_type );
39984042
39994043#if WASM_ENABLE_FAST_INTERP != 0
4044+ if (!(preserve_referenced_local (loader_ctx , opcode , local_offset ,
4045+ local_type , & preserve_local ,
4046+ error_buf , error_buf_size )))
4047+ goto fail ;
4048+
40004049 if (local_offset < 256 ) {
40014050 skip_label ();
4002- if (LAST_OP_OUTPUT_I32 ()) {
4051+ if ((! preserve_local ) && ( LAST_OP_OUTPUT_I32 () )) {
40034052 if (loader_ctx -> p_code_compiled )
40044053 * (int16 * )(loader_ctx -> p_code_compiled - 2 ) = local_offset ;
40054054 loader_ctx -> frame_offset -- ;
40064055 loader_ctx -> dynamic_offset -- ;
40074056 }
4008- else if (LAST_OP_OUTPUT_I64 ()) {
4057+ else if ((! preserve_local ) && ( LAST_OP_OUTPUT_I64 () )) {
40094058 if (loader_ctx -> p_code_compiled )
40104059 * (int16 * )(loader_ctx -> p_code_compiled - 2 ) = local_offset ;
40114060 loader_ctx -> frame_offset -= 2 ;
@@ -4054,6 +4103,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
40544103 PUSH_TYPE (local_type );
40554104
40564105#if WASM_ENABLE_FAST_INTERP != 0
4106+ if (!(preserve_referenced_local (loader_ctx , opcode , local_offset ,
4107+ local_type , & preserve_local ,
4108+ error_buf , error_buf_size )))
4109+ goto fail ;
4110+
40574111 if (local_offset < 256 ) {
40584112 skip_label ();
40594113 if (local_type == VALUE_TYPE_I32
0 commit comments