static tsf_bool_t generate_size_calc()

in benchmarks/JetStream2/wasm/TSF/tsf_gpc_code_gen.c [44:221]


static tsf_bool_t generate_size_calc(gpc_proto_t *proto,
                                     tsf_type_t *type,
                                     gpc_cell_t offset,
                                     gpc_cell_t label) {
    uint32_t i;
    uint32_t num_bits = 0;
    gpc_cell_t label_offset;
    gpc_cell_t done_label, really_done_label;
    gpc_cell_t *targets;
    tsf_bool_t result;
    
    gpc_cell_t static_size = tsf_type_get_static_size(type);
    if (static_size != UINT32_MAX) {
        if (static_size != 0) {
            C(append(proto, GPC_I_INC_SIZE, static_size));
        }
        
        return tsf_true;
    }
    
    switch (type->kind_code) {
    case TSF_TK_INTEGER:
        C(append(proto, GPC_I_TSF_INTEGER_SIZE, offset));
        break;
    case TSF_TK_LONG:
        C(append(proto, GPC_I_TSF_LONG_SIZE, offset));
        break;
    case TSF_TK_STRUCT:
        for (i = 0; i < tsf_struct_type_get_num_elements(type); ++i) {
            tsf_named_type_t *n = tsf_struct_type_get_element(type, i);
            if (n->type->kind_code == TSF_TK_BIT) {
                ++num_bits;
                continue;
            }
            C(generate_size_calc(proto,
                                 n->type,
                                 offset + n->offset,
                                 label));
        }
        if (num_bits != 0) {
            C(append(proto,
                     GPC_I_INC_SIZE,
                     (gpc_cell_t)((num_bits + 7) >> 3)));
        }
        break;
    case TSF_TK_ARRAY:
        if (type->u.a.element_type->kind_code == TSF_TK_VOID) {
            C(append(proto,
                     GPC_I_INC_SIZE_ARRAY_LEN,
                     offset + tsf_offsetof(tsf_native_void_array_t, len)));
        } else if (type->u.a.element_type->kind_code == TSF_TK_BIT) {
            C(append(proto,
                     GPC_I_INC_SIZE_BITVECTOR,
                     offset));
        } else {
            static_size = tsf_type_get_static_size(type->u.a.element_type);
            if (static_size == UINT32_MAX) {
                gpc_cell_t loop_label = label++;
                done_label = label++;
                    
                C(append(proto,
                         GPC_I_INC_SIZE_ARRAY_LEN,
                         offset + tsf_offsetof(tsf_native_array_t,
                                               len)));
                C(append(proto,
                         GPC_I_PUSH_PTR,
                         offset + tsf_offsetof(tsf_native_array_t,
                                               data)));
                C(append(proto,
                         GPC_I_REPUSH_MULADD_PTR,
                         offset + tsf_offsetof(tsf_native_array_t,
                                               len),
                         tsf_native_type_get_size(
                             type->u.a.element_type)));
                C(append(proto, GPC_I_COMPFAILJUMP, done_label));
                C(append(proto, GPC_I_LABEL, loop_label));
                C(generate_size_calc(proto,
                                     type->u.a.element_type,
                                     0,
                                     label));
                C(append(proto,
                         GPC_I_ADDCOMPJUMP,
                         tsf_native_type_get_size(
                             type->u.a.element_type),
                         loop_label));
                C(append(proto, GPC_I_LABEL, done_label));
                C(append(proto, GPC_I_TWO_POP));
            } else {
                C(append(proto,
                         GPC_I_INC_SIZE_ARRAY,
                         offset,
                         (gpc_cell_t)static_size));
            }
        }
        break;
    case TSF_TK_CHOICE:
        tsf_assert(tsf_choice_type_has_non_void(type) ||
                   (tsf_choice_type_get_num_elements(type) >= 256 &&
                    !type->u.h.choice_as_full_word));
        if (tsf_choice_type_get_num_elements(type) >= 256) {
            if (type->u.h.choice_as_full_word) {
                C(append(proto, GPC_I_INC_SIZE, 4));
            } else {
                C(append(proto, GPC_I_TSF_UNSIGNED_PLUS1_SIZE,
                         offset + type->u.h.value_offset));
            }
        } else {
            C(append(proto, GPC_I_INC_SIZE, 1));
        }
        if (tsf_choice_type_has_non_void(type)) {
            label_offset = label;
            label += tsf_choice_type_get_num_elements(type);
            done_label = label++;
            really_done_label = label++;
            targets=malloc(sizeof(gpc_cell_t)*
                           tsf_choice_type_get_num_elements(type));
            if (targets == NULL) {
                tsf_set_errno("Could not malloc array of "
                              "gpc_cell_t");
                return tsf_false;
            }
            for (i = 0; i < tsf_choice_type_get_num_elements(type); ++i) {
                targets[i] = label_offset + i;
            }
            result=append_tablejump_field(
                proto,
                offset + type->u.h.value_offset,
                tsf_choice_type_get_num_elements(type),
                targets);
            free(targets);
            if (!result) {
                return tsf_false;
            }
            C(append(proto, GPC_I_JUMP, really_done_label)); /* for unknown values */
            for (i = 0; i < tsf_choice_type_get_num_elements(type); ++i) {
                tsf_named_type_t *n = tsf_choice_type_get_element(type, i);
                C(append(proto, GPC_I_LABEL, label_offset + i));
                if (tsf_native_choice_type_is_in_place(type)) {
                    C(generate_size_calc(proto,
                                         n->type,
                                         offset + type->u.h.data_offset,
                                         label));
                } else {
                    /* cannot move this push above the tablejump since the
                       tablejump uses the value at the top of the stack, and
                       I don't feel like adding a second tablejump just to
                       get around that. */
                    C(append(proto, GPC_I_PUSH_PTR,
                             offset + type->u.h.data_offset));
                    C(generate_size_calc(proto,
                                         n->type,
                                         0,
                                         label));
                }
                C(append(proto, GPC_I_JUMP, done_label));
            }
            /* if it is in place, you get two labels...  oh well. */
            C(append(proto, GPC_I_LABEL, done_label));
            if (!tsf_native_choice_type_is_in_place(type)) {
                C(append(proto, GPC_I_POP));
            }
            C(append(proto, GPC_I_LABEL, really_done_label));
        }
        break;
    case TSF_TK_STRING:
        C(append(proto, GPC_I_STRING_SIZE, offset));
        break;
    case TSF_TK_ANY:
        C(append(proto, GPC_I_ANY_SIZE, offset));
        break;
    default:
        tsf_abort("Types other than struct, array, and choice "
                  "should have static size!");
        break;
    }
    
    return tsf_true;
}