Преглед изворни кода

Add wamrc parameter to configure stack frame features (#3763)

Those parameters can be used to reduce the size of the AOT code.

There's going to be more changes related to AOT code size reduction,
this is just the initial step.

p.s. https://github.com/bytecodealliance/wasm-micro-runtime/issues/3758
Marcin Kolny пре 1 година
родитељ
комит
6f97822c18

+ 6 - 2
core/iwasm/compilation/aot_compiler.c

@@ -337,6 +337,10 @@ aot_gen_commit_values(AOTCompFrame *frame)
     LLVMValueRef value;
     LLVMValueRef value;
     uint32 n;
     uint32 n;
 
 
+    if (!frame->comp_ctx->call_stack_features.values) {
+        return true;
+    }
+
     /* First, commit reference flags
     /* First, commit reference flags
      * For LLVM JIT, iterate all local and stack ref flags
      * For LLVM JIT, iterate all local and stack ref flags
      * For AOT, ignore local(params + locals) ref flags */
      * For AOT, ignore local(params + locals) ref flags */
@@ -629,7 +633,7 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, bool commit_sp, bool commit_ip)
         offset_sp = offsetof(WASMInterpFrame, sp);
         offset_sp = offsetof(WASMInterpFrame, sp);
     }
     }
 
 
-    if (commit_ip) {
+    if (commit_ip && comp_ctx->call_stack_features.ip) {
         if (!comp_ctx->is_jit_mode) {
         if (!comp_ctx->is_jit_mode) {
             WASMModule *module = comp_ctx->comp_data->wasm_module;
             WASMModule *module = comp_ctx->comp_data->wasm_module;
             if (is_64bit)
             if (is_64bit)
@@ -654,7 +658,7 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, bool commit_sp, bool commit_ip)
         }
         }
     }
     }
 
 
-    if (commit_sp) {
+    if (commit_sp && comp_ctx->call_stack_features.values) {
         n = (uint32)(sp - frame->lp);
         n = (uint32)(sp - frame->lp);
         value = I32_CONST(offset_of_local(comp_ctx, n));
         value = I32_CONST(offset_of_local(comp_ctx, n));
         if (!value) {
         if (!value) {

+ 2 - 2
core/iwasm/compilation/aot_emit_exception.c

@@ -41,7 +41,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             return false;
             return false;
         }
         }
 
 
-        if (comp_ctx->aot_frame) {
+        if (comp_ctx->aot_frame && comp_ctx->call_stack_features.trap_ip) {
             /* Create exception ip phi */
             /* Create exception ip phi */
             if (!(func_ctx->exception_ip_phi = LLVMBuildPhi(
             if (!(func_ctx->exception_ip_phi = LLVMBuildPhi(
                       comp_ctx->builder, is_64bit ? I64_TYPE : I32_TYPE,
                       comp_ctx->builder, is_64bit ? I64_TYPE : I32_TYPE,
@@ -134,7 +134,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Add phi incoming value to got_exception block */
     /* Add phi incoming value to got_exception block */
     LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &block_curr, 1);
     LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &block_curr, 1);
 
 
-    if (comp_ctx->aot_frame) {
+    if (comp_ctx->aot_frame && comp_ctx->call_stack_features.trap_ip) {
         const uint8 *ip = comp_ctx->aot_frame->frame_ip;
         const uint8 *ip = comp_ctx->aot_frame->frame_ip;
         LLVMValueRef exce_ip = NULL;
         LLVMValueRef exce_ip = NULL;
 
 

+ 24 - 15
core/iwasm/compilation/aot_emit_function.c

@@ -682,24 +682,29 @@ alloc_frame_for_aot_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 
     new_frame = wasm_stack_top;
     new_frame = wasm_stack_top;
 
 
-    if (!(check_wasm_stack_succ = LLVMAppendBasicBlockInContext(
-              comp_ctx->context, func_ctx->func, "check_wasm_stack_succ"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        return false;
-    }
+    if (comp_ctx->call_stack_features.bounds_checks) {
+        if (!(check_wasm_stack_succ = LLVMAppendBasicBlockInContext(
+                  comp_ctx->context, func_ctx->func,
+                  "check_wasm_stack_succ"))) {
+            aot_set_last_error("llvm add basic block failed.");
+            return false;
+        }
 
 
-    LLVMMoveBasicBlockAfter(check_wasm_stack_succ,
-                            LLVMGetInsertBlock(comp_ctx->builder));
+        LLVMMoveBasicBlockAfter(check_wasm_stack_succ,
+                                LLVMGetInsertBlock(comp_ctx->builder));
 
 
-    if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT, wasm_stack_top_max,
-                              wasm_stack_top_bound, "cmp"))) {
-        aot_set_last_error("llvm build icmp failed");
-        return false;
-    }
+        if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT,
+                                  wasm_stack_top_max, wasm_stack_top_bound,
+                                  "cmp"))) {
+            aot_set_last_error("llvm build icmp failed");
+            return false;
+        }
 
 
-    if (!(aot_emit_exception(comp_ctx, func_ctx, EXCE_OPERAND_STACK_OVERFLOW,
-                             true, cmp, check_wasm_stack_succ))) {
-        return false;
+        if (!(aot_emit_exception(comp_ctx, func_ctx,
+                                 EXCE_OPERAND_STACK_OVERFLOW, true, cmp,
+                                 check_wasm_stack_succ))) {
+            return false;
+        }
     }
     }
 
 
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -1285,6 +1290,10 @@ commit_params_to_frame_of_import_func(AOTCompContext *comp_ctx,
 {
 {
     uint32 i, n;
     uint32 i, n;
 
 
+    if (!comp_ctx->call_stack_features.values) {
+        return true;
+    }
+
     for (i = 0, n = 0; i < func_type->param_count; i++, n++) {
     for (i = 0, n = 0; i < func_type->param_count; i++, n++) {
         switch (func_type->types[i]) {
         switch (func_type->types[i]) {
             case VALUE_TYPE_I32:
             case VALUE_TYPE_I32:

+ 2 - 0
core/iwasm/compilation/aot_llvm.c

@@ -2580,6 +2580,8 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
     if (option->enable_aux_stack_frame)
     if (option->enable_aux_stack_frame)
         comp_ctx->enable_aux_stack_frame = true;
         comp_ctx->enable_aux_stack_frame = true;
 
 
+    comp_ctx->call_stack_features = option->call_stack_features;
+
     if (option->enable_perf_profiling)
     if (option->enable_perf_profiling)
         comp_ctx->enable_perf_profiling = true;
         comp_ctx->enable_perf_profiling = true;
 
 

+ 3 - 0
core/iwasm/compilation/aot_llvm.h

@@ -412,6 +412,9 @@ typedef struct AOTCompContext {
     /* Generate auxiliary stack frame */
     /* Generate auxiliary stack frame */
     bool enable_aux_stack_frame;
     bool enable_aux_stack_frame;
 
 
+    /* Auxiliary call stack features */
+    AOTCallStackFeatures call_stack_features;
+
     /* Function performance profiling */
     /* Function performance profiling */
     bool enable_perf_profiling;
     bool enable_perf_profiling;
 
 

+ 18 - 0
core/iwasm/include/aot_comp_option.h

@@ -6,6 +6,23 @@
 #ifndef __AOT_COMP_OPTION_H__
 #ifndef __AOT_COMP_OPTION_H__
 #define __AOT_COMP_OPTION_H__
 #define __AOT_COMP_OPTION_H__
 
 
+typedef struct {
+    /* Enables or disables bounds checks for stack frames. When enabled, the AOT
+     * compiler generates code to check if the stack pointer is within the
+     * bounds of the current stack frame (and if not, traps). */
+    bool bounds_checks;
+
+    /*  Enables or disables instruction pointer (IP) tracking.*/
+    bool ip;
+
+    /* Enables or disables tracking instruction pointer of a trap. Only takes
+     * effect when `ip` is enabled.*/
+    bool trap_ip;
+
+    /* Enables or disables parameters, locals and stack operands. */
+    bool values;
+} AOTCallStackFeatures;
+
 typedef struct AOTCompOption {
 typedef struct AOTCompOption {
     bool is_jit_mode;
     bool is_jit_mode;
     bool is_indirect_mode;
     bool is_indirect_mode;
@@ -22,6 +39,7 @@ typedef struct AOTCompOption {
     bool enable_gc;
     bool enable_gc;
     bool enable_aux_stack_check;
     bool enable_aux_stack_check;
     bool enable_aux_stack_frame;
     bool enable_aux_stack_frame;
+    AOTCallStackFeatures call_stack_features;
     bool enable_perf_profiling;
     bool enable_perf_profiling;
     bool enable_memory_profiling;
     bool enable_memory_profiling;
     bool disable_llvm_intrinsics;
     bool disable_llvm_intrinsics;

+ 1 - 0
core/iwasm/interpreter/wasm_loader.c

@@ -5407,6 +5407,7 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 #if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
 #if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
     || WASM_ENABLE_AOT_STACK_FRAME != 0
     || WASM_ENABLE_AOT_STACK_FRAME != 0
     option.enable_aux_stack_frame = true;
     option.enable_aux_stack_frame = true;
+    memset(&option.call_stack_features, 1, sizeof(AOTCallStackFeatures));
 #endif
 #endif
 #if WASM_ENABLE_PERF_PROFILING != 0
 #if WASM_ENABLE_PERF_PROFILING != 0
     option.enable_perf_profiling = true;
     option.enable_perf_profiling = true;

+ 1 - 0
core/iwasm/interpreter/wasm_mini_loader.c

@@ -2149,6 +2149,7 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 #if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
 #if WASM_ENABLE_PERF_PROFILING != 0 || WASM_ENABLE_DUMP_CALL_STACK != 0 \
     || WASM_ENABLE_AOT_STACK_FRAME != 0
     || WASM_ENABLE_AOT_STACK_FRAME != 0
     option.enable_aux_stack_frame = true;
     option.enable_aux_stack_frame = true;
+    memset(&option.call_stack_features, 1, sizeof(AOTCallStackFeatures));
 #endif
 #endif
 #if WASM_ENABLE_PERF_PROFILING != 0
 #if WASM_ENABLE_PERF_PROFILING != 0
     option.enable_perf_profiling = true;
     option.enable_perf_profiling = true;

+ 70 - 0
wamr-compiler/main.c

@@ -162,6 +162,12 @@ print_help()
     printf("                              GC is enabled\n");
     printf("                              GC is enabled\n");
     printf("  --disable-aux-stack-check Disable auxiliary stack overflow/underflow check\n");
     printf("  --disable-aux-stack-check Disable auxiliary stack overflow/underflow check\n");
     printf("  --enable-dump-call-stack  Enable stack trace feature\n");
     printf("  --enable-dump-call-stack  Enable stack trace feature\n");
+    printf("  --call-stack-features=<features>\n");
+    printf("                            A comma-separated list of features when generating call stacks.\n");
+    printf("                            By default, all features are enabled. To disable all features,\n");
+    printf("                            provide an empty list (i.e. --call-stack-features=). This flag\n");
+    printf("                            only only takes effect when --enable-dump-call-stack is set.\n");
+    printf("                            Available features: bounds-checks, ip, trap-ip, values.\n");
     printf("  --enable-perf-profiling   Enable function performance profiling\n");
     printf("  --enable-perf-profiling   Enable function performance profiling\n");
     printf("  --enable-memory-profiling Enable memory usage profiling\n");
     printf("  --enable-memory-profiling Enable memory usage profiling\n");
     printf("  --xip                     A shorthand of --enable-indirect-mode --disable-llvm-intrinsics\n");
     printf("  --xip                     A shorthand of --enable-indirect-mode --disable-llvm-intrinsics\n");
@@ -259,6 +265,48 @@ split_string(char *str, int *count, const char *delimer)
     return res;
     return res;
 }
 }
 
 
+static bool
+parse_call_stack_features(char *features_str,
+                          AOTCallStackFeatures *out_features)
+{
+    int size = 0;
+    char **features;
+    bool ret = true;
+
+    bh_assert(features_str);
+    bh_assert(out_features);
+
+    /* non-empty feature list */
+    features = split_string(features_str, &size, ",");
+    if (!features) {
+        return false;
+    }
+
+    while (size--) {
+        if (!strcmp(features[size], "bounds-checks")) {
+            out_features->bounds_checks = true;
+        }
+        else if (!strcmp(features[size], "ip")) {
+            out_features->ip = true;
+        }
+        else if (!strcmp(features[size], "trap-ip")) {
+            out_features->trap_ip = true;
+        }
+        else if (!strcmp(features[size], "values")) {
+            out_features->values = true;
+        }
+        else {
+            ret = false;
+            printf("Unsupported feature %s\n", features[size]);
+            goto finish;
+        }
+    }
+
+finish:
+    free(features);
+    return ret;
+}
+
 static uint32
 static uint32
 resolve_segue_flags(char *str_flags)
 resolve_segue_flags(char *str_flags)
 {
 {
@@ -356,6 +404,9 @@ main(int argc, char *argv[])
     option.enable_ref_types = true;
     option.enable_ref_types = true;
     option.enable_gc = false;
     option.enable_gc = false;
 
 
+    /* Set all the features to true by default */
+    memset(&option.call_stack_features, 1, sizeof(AOTCallStackFeatures));
+
     /* Process options */
     /* Process options */
     for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
     for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) {
         if (!strcmp(argv[0], "-o")) {
         if (!strcmp(argv[0], "-o")) {
@@ -470,6 +521,19 @@ main(int argc, char *argv[])
         else if (!strcmp(argv[0], "--enable-dump-call-stack")) {
         else if (!strcmp(argv[0], "--enable-dump-call-stack")) {
             option.enable_aux_stack_frame = true;
             option.enable_aux_stack_frame = true;
         }
         }
+        else if (!strncmp(argv[0], "--call-stack-features=", 22)) {
+            /* Reset all the features, only enable the user-defined ones */
+            memset(&option.call_stack_features, 0,
+                   sizeof(AOTCallStackFeatures));
+
+            if (argv[0][22] != '\0') {
+                if (!parse_call_stack_features(argv[0] + 22,
+                                               &option.call_stack_features)) {
+                    printf("Failed to parse call-stack-features\n");
+                    PRINT_HELP_AND_EXIT();
+                }
+            }
+        }
         else if (!strcmp(argv[0], "--enable-perf-profiling")) {
         else if (!strcmp(argv[0], "--enable-perf-profiling")) {
             option.enable_aux_stack_frame = true;
             option.enable_aux_stack_frame = true;
             option.enable_perf_profiling = true;
             option.enable_perf_profiling = true;
@@ -608,6 +672,12 @@ main(int argc, char *argv[])
 #endif
 #endif
     }
     }
 
 
+    if (option.enable_gc && !option.call_stack_features.values) {
+        LOG_WARNING("Call stack feature 'values' must be enabled for GC. The "
+                    "feature will be enabled automatically.");
+        option.call_stack_features.values = true;
+    }
+
     if (sgx_mode) {
     if (sgx_mode) {
         option.size_level = 1;
         option.size_level = 1;
         option.is_sgx_platform = true;
         option.is_sgx_platform = true;