static tsf_bool_t generate_generator()

in benchmarks/JetStream2/wasm/TSF/tsf_gpc_code_gen.c [223:459]


static tsf_bool_t generate_generator(gpc_proto_t *proto,
                                     tsf_type_t *type,
                                     gpc_cell_t offset,
                                     gpc_cell_t label) {
    uint32_t i;
    uint32_t bit = 0;
    gpc_cell_t done_label, really_done_label;
    
    switch (type->kind_code) {
    case TSF_TK_VOID:
        break;
    case TSF_TK_INT8:
    case TSF_TK_UINT8:
        C(append(proto,
                 GPC_I_COPY_HTONC_INCDST,
                 offset));
        break;
    case TSF_TK_INT16:
    case TSF_TK_UINT16:
        C(append(proto,
                 GPC_I_COPY_HTONS_INCDST,
                 offset));
        break;
    case TSF_TK_INT32:
    case TSF_TK_UINT32:
        C(append(proto,
                 GPC_I_COPY_HTONL_INCDST,
                 offset));
        break;
    case TSF_TK_INT64:
    case TSF_TK_UINT64:
        C(append(proto,
                 GPC_I_COPY_HTONLL_INCDST,
                 offset));
        break;
    case TSF_TK_FLOAT:
        C(append(proto,
                 GPC_I_COPY_HTONF_INCDST,
                 offset));
        break;
    case TSF_TK_DOUBLE:
        C(append(proto,
                 GPC_I_COPY_HTOND_INCDST,
                 offset));
        break;
    case TSF_TK_BIT:
        C(append(proto,
                 GPC_I_BIT_WRITE,
                 offset));
        break;
    case TSF_TK_INTEGER:
        C(append(proto, GPC_I_TSF_INTEGER_WRITE, offset));
        break;
    case TSF_TK_LONG:
        C(append(proto, GPC_I_TSF_LONG_WRITE, 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) {
                continue;
            }
            C(generate_generator(proto,
                                 n->type,
                                 offset + n->offset,
                                 label));
        }
        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) {
                continue;
            }
            C(append(proto,
                     GPC_I_BIT_MASK_WRITE,
                     bit,
                     offset + n->offset));
            ++bit;
            if (bit == 8) {
                bit = 0;
                C(append(proto, GPC_I_SKIP, 1));
            }
        }
        if (bit) {
            C(append(proto, GPC_I_SKIP, 1));
        }
        break;
    case TSF_TK_ARRAY:
        if (type->u.a.element_type->kind_code == TSF_TK_VOID) {
            C(append(proto,
                     GPC_I_ARRAY_LEN_WRITE_FIELD,
                     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_BITVECTOR_WRITE,
                     offset));
        } else if (type->u.a.element_type->kind_code == TSF_TK_UINT8 ||
                   type->u.a.element_type->kind_code == TSF_TK_INT8
#ifndef NEED_INT_CONVERSION
                   || tsf_type_kind_is_int(
                       type->u.a.element_type->kind_code)
#endif
#ifndef NEED_FLOAT_CONVERSION
                   || tsf_type_kind_is_float(
                       type->u.a.element_type->kind_code)
#endif
            ) {
            C(append(proto,
                     GPC_I_BYTE_ARRAY_WRITE,
                     offset,
                     tsf_native_type_get_size(
                         type->u.a.element_type)));
        } else {
            gpc_cell_t loop_label = label++;
            done_label = label++;
                
            C(append(proto,
                     GPC_I_ARRAY_LEN_WRITE_FIELD,
                     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_generator(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));
        }
        break;
    case TSF_TK_CHOICE:
        if (tsf_choice_type_get_num_elements(type) >= 256) {
            if (type->u.h.choice_as_full_word) {
                C(append(proto,
                         GPC_I_COPY_HTONL_INCDST,
                         offset + type->u.h.value_offset));
            } else {
                C(append(proto,
                         GPC_I_TSF_UNSIGNED_PLUS1_WRITE,
                         offset + type->u.h.value_offset));
            }
        } else {
            C(append(proto,
                     GPC_I_COPY_HTONCHOICE_TO_UI8_INCDST,
                     offset + type->u.h.value_offset));
        }
        if (tsf_choice_type_has_non_void(type)) {
            gpc_cell_t *targets;
            gpc_cell_t label_offset;
            tsf_bool_t result;
                
            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;
            }
                
            /* for unknown values */
            C(append(proto, GPC_I_JUMP, really_done_label));
                
            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_generator(proto,
                                         n->type,
                                         offset + type->u.h.data_offset,
                                         label));
                } else {
                    C(append(proto, GPC_I_PUSH_PTR,
                             offset + type->u.h.data_offset));
                    C(generate_generator(proto,
                                         n->type,
                                         0,
                                         label));
                }
                C(append(proto, GPC_I_JUMP, done_label));
            }
            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_WRITE, offset));
        break;
    case TSF_TK_ANY:
        C(append(proto, GPC_I_ANY_WRITE, offset));
        break;
    default:
        tsf_abort("Bad kind code!");
        break;
    }
    
    return tsf_true;
}