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;
}