in benchmarks/JetStream2/wasm/TSF/tsf_gpc_code_gen.c [634:1785]
static tsf_bool_t generate_parser(gpc_proto_t *proto,
tsf_type_t *dest_type,
tsf_type_t *src_type,
gpc_cell_t offset,
gpc_cell_t label,
tsf_bool_t do_bounds_check) {
uint32_t i, bit = 0, num_bits = 0;
gpc_cell_t loop_label, done_label, really_done_label, label_offset;
gpc_cell_t *targets;
uint32_t static_size;
tsf_bool_t result;
tsf_bool_t instanceof;
static_size = tsf_type_get_static_size(src_type);
if (do_bounds_check && static_size != UINT32_MAX) {
if (static_size > 0) {
C(append(proto, GPC_I_BC, static_size));
}
do_bounds_check = tsf_false;
}
instanceof = tsf_type_instanceof(src_type, dest_type);
if (!instanceof) {
C(generate_set_default(proto, dest_type, offset));
}
if (dest_type->kind_code == TSF_TK_VOID || !instanceof) {
/* this is the skip parser. */
tsf_type_t *type = src_type; /* makes things simpler since we
* won't refer to dest_type at this
* point. */
if (static_size != UINT32_MAX) {
if (static_size > 0) {
C(append(proto,
GPC_I_SKIP,
(gpc_cell_t)static_size));
}
return tsf_true;
}
/* interesting observation: from here on, do_bounds_check must be true.
* because if do_bounds_check was false, then that means that a bounds
* check was possible, which means in turn that our size is statically
* known. */
tsf_assert(do_bounds_check);
switch (type->kind_code) {
case TSF_TK_INTEGER:
C(append(proto, GPC_I_TSF_INTEGER_SKIP));
break;
case TSF_TK_LONG:
C(append(proto, GPC_I_TSF_LONG_SKIP));
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_parser(proto,
tsf_type_create(TSF_TK_VOID),
n->type,
0,
label,
tsf_true));
}
if (num_bits) {
C(append(proto,
GPC_I_SKIP,
(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_ARRAY_LEN_SKIP));
} else if (type->u.a.element_type->kind_code == TSF_TK_BIT) {
C(append(proto, GPC_I_BITVECTOR_SKIP));
} else {
static_size =
tsf_type_get_static_size(type->u.a.element_type);
if (static_size == UINT32_MAX) {
C(append(proto, GPC_I_ARRAY_LEN_READ_LOCAL));
loop_label = label++;
done_label = label++;
C(append(proto, GPC_I_ZEROJUMP, done_label));
C(append(proto, GPC_I_LABEL, loop_label));
C(generate_parser(proto,
tsf_type_create(TSF_TK_VOID),
type->u.a.element_type,
0,
label,
tsf_true));
C(append(proto, GPC_I_DECCOMPJUMP, loop_label));
C(append(proto, GPC_I_LABEL, done_label));
C(append(proto, GPC_I_POP));
} else {
C(append(proto,
GPC_I_ARRAY_SKIP,
(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_BC, 4));
C(append(proto, GPC_I_READL));
} else {
if (tsf_choice_type_has_non_void(type)) {
C(append(proto, GPC_I_TSF_UNSIGNED_READ_SUB1));
} else {
C(append(proto, GPC_I_TSF_UNSIGNED_SKIP));
}
}
} else {
C(append(proto, GPC_I_BC, 1));
C(append(proto, GPC_I_READC_TO_CHOICE));
}
if (tsf_choice_type_has_non_void(type)) {
label_offset = label;
label += tsf_choice_type_get_num_elements(type);
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_local(
proto,
tsf_choice_type_get_num_elements(type),
targets);
free(targets);
if (!result) {
return tsf_false;
}
/* for unknown (default) values */
C(append(proto, GPC_I_JUMP, 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));
C(generate_parser(proto,
tsf_type_create(TSF_TK_VOID),
n->type,
0,
label,
tsf_true));
C(append(proto, GPC_I_JUMP, done_label));
}
C(append(proto, GPC_I_LABEL, done_label));
}
break;
case TSF_TK_STRING:
C(append(proto, GPC_I_STRING_SKIP));
break;
case TSF_TK_ANY:
C(append(proto, GPC_I_ANY_SKIP));
break;
default:
tsf_abort("There appears to be a kind code that we don't "
"know about");
break;
}
return tsf_true;
}
switch (src_type->kind_code) {
case TSF_TK_VOID:
break;
case TSF_TK_INT8:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHC_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHC_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHC_TO_S_E_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHC_TO_L_E_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHC_TO_LL_E_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHC_TO_F_E_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHC_TO_D_E_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_UINT8:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHC_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHC_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHC_TO_S_Z_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHC_TO_L_Z_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHC_TO_LL_Z_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHC_TO_F_Z_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHC_TO_D_Z_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_INT16:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHS_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHS_TO_C_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHS_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHS_TO_L_E_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHS_TO_LL_E_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHS_TO_F_E_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHS_TO_D_E_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_UINT16:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHS_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHS_TO_C_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHS_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHS_TO_L_Z_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHS_TO_LL_Z_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHS_TO_F_Z_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHS_TO_D_Z_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_INT32:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHL_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHL_TO_C_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHL_TO_S_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHL_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHL_TO_LL_E_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHL_TO_F_E_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHL_TO_D_E_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_UINT32:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHL_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHL_TO_C_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHL_TO_S_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHL_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHL_TO_LL_Z_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHL_TO_F_Z_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHL_TO_D_Z_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_INT64:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHLL_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHLL_TO_C_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHLL_TO_S_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHLL_TO_L_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHLL_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHLL_TO_F_E_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHLL_TO_D_E_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_UINT64:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHLL_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHLL_TO_C_INCSRC, offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHLL_TO_S_INCSRC, offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHLL_TO_L_INCSRC, offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHLL_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHLL_TO_F_Z_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHLL_TO_D_Z_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_FLOAT:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHF_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
C(append(proto, GPC_I_COPY_NTOHF_TO_C_E_INCSRC, offset));
break;
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHF_TO_C_Z_INCSRC, offset));
break;
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHF_TO_S_E_INCSRC, offset));
break;
case TSF_TK_UINT16:
C(append(proto, GPC_I_COPY_NTOHF_TO_S_Z_INCSRC, offset));
break;
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHF_TO_L_E_INCSRC, offset));
break;
case TSF_TK_UINT32:
C(append(proto, GPC_I_COPY_NTOHF_TO_L_Z_INCSRC, offset));
break;
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHF_TO_LL_E_INCSRC, offset));
break;
case TSF_TK_UINT64:
C(append(proto, GPC_I_COPY_NTOHF_TO_LL_Z_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHF_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHF_TO_D_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_DOUBLE:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_COPY_NTOHD_TO_BIT_INCSRC, offset));
break;
case TSF_TK_INT8:
C(append(proto, GPC_I_COPY_NTOHD_TO_C_E_INCSRC, offset));
break;
case TSF_TK_UINT8:
C(append(proto, GPC_I_COPY_NTOHD_TO_C_Z_INCSRC, offset));
break;
case TSF_TK_INT16:
C(append(proto, GPC_I_COPY_NTOHD_TO_S_E_INCSRC, offset));
break;
case TSF_TK_UINT16:
C(append(proto, GPC_I_COPY_NTOHD_TO_S_Z_INCSRC, offset));
break;
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_COPY_NTOHD_TO_L_E_INCSRC, offset));
break;
case TSF_TK_UINT32:
C(append(proto, GPC_I_COPY_NTOHD_TO_L_Z_INCSRC, offset));
break;
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_COPY_NTOHD_TO_LL_E_INCSRC, offset));
break;
case TSF_TK_UINT64:
C(append(proto, GPC_I_COPY_NTOHD_TO_LL_Z_INCSRC, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_COPY_NTOHD_TO_F_INCSRC, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_COPY_NTOHD_INCSRC, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_INTEGER:
tsf_assert(do_bounds_check);
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_TSF_INTEGER_READ_TO_BIT, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_TSF_INTEGER_READ_TO_C, offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto, GPC_I_TSF_INTEGER_READ_TO_S, offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_TSF_INTEGER_READ, offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_TSF_INTEGER_READ_TO_LL, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_TSF_INTEGER_READ_TO_F, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_TSF_INTEGER_READ_TO_D, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_LONG:
tsf_assert(do_bounds_check);
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto, GPC_I_TSF_LONG_READ_TO_BIT, offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto, GPC_I_TSF_LONG_READ_TO_C, offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto, GPC_I_TSF_LONG_READ_TO_S, offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_TSF_LONG_READ_TO_L, offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_TSF_LONG_READ, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_TSF_LONG_READ_TO_F, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_TSF_LONG_READ_TO_D, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_BIT:
switch (dest_type->kind_code) {
case TSF_TK_INT8:
case TSF_TK_UINT8:
case TSF_TK_BIT:
C(append(proto, GPC_I_BIT_READ, offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto, GPC_I_BIT_READ_TO_S, offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto, GPC_I_BIT_READ_TO_L, offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto, GPC_I_BIT_READ_TO_LL, offset));
break;
case TSF_TK_FLOAT:
C(append(proto, GPC_I_BIT_READ_TO_F, offset));
break;
case TSF_TK_DOUBLE:
C(append(proto, GPC_I_BIT_READ_TO_D, offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_STRUCT:
if (dest_type->u.s.constructor != NULL) {
C(append(proto, GPC_I_CALL,
offset,
dest_type->u.s.constructor));
}
if (dest_type->u.s.pre_destructor != NULL) {
C(append(proto, GPC_I_ADD_CBACK,
offset,
dest_type->u.s.pre_destructor));
}
for (i = 0; i < tsf_struct_type_get_num_elements(dest_type); ++i) {
tsf_named_type_t *dn = tsf_struct_type_get_element(dest_type, i);
if (tsf_struct_type_find_node(src_type, dn->name) == NULL) {
C(generate_set_default(proto, dn->type, offset + dn->offset));
}
}
for (i = 0; i < tsf_struct_type_get_num_elements(src_type); ++i) {
tsf_named_type_t *sn = tsf_struct_type_get_element(src_type, i);
tsf_named_type_t *dn;
if (sn->type->kind_code == TSF_TK_BIT) {
num_bits++;
continue;
}
dn = tsf_struct_type_find_node(dest_type, sn->name);
if (dn == NULL) {
/* skip */
C(generate_parser(proto,
tsf_type_create(TSF_TK_VOID),
sn->type,
0,
label,
do_bounds_check));
} else {
/* read it */
C(generate_parser(proto,
dn->type,
sn->type,
offset + dn->offset,
label,
do_bounds_check));
}
}
if (num_bits) {
if (do_bounds_check) {
C(append(proto,
GPC_I_BC,
(gpc_cell_t)((num_bits + 7) >> 3)));
}
for (i = 0; i < tsf_struct_type_get_num_elements(src_type); ++i) {
tsf_named_type_t *sn =
tsf_struct_type_get_element(src_type, i);
tsf_named_type_t *dn;
if (sn->type->kind_code != TSF_TK_BIT) {
continue;
}
dn = tsf_struct_type_find_node(dest_type, sn->name);
if (dn != NULL) {
switch (dn->type->kind_code) {
case TSF_TK_VOID:
break;
case TSF_TK_BIT:
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_BIT_MASK_READ,
bit,
offset + dn->offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_BIT_MASK_READ_TO_S,
bit,
offset + dn->offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_BIT_MASK_READ_TO_L,
bit,
offset + dn->offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_BIT_MASK_READ_TO_LL,
bit,
offset + dn->offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_BIT_MASK_READ_TO_F,
bit,
offset + dn->offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_BIT_MASK_READ_TO_D,
bit,
offset + dn->offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
}
++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 (dest_type->u.a.element_type->kind_code == TSF_TK_VOID) {
C(append(proto,
GPC_I_ARRAY_LEN_READ_FIELD,
offset + tsf_offsetof(tsf_native_void_array_t,
len)));
if (src_type->u.a.element_type->kind_code == TSF_TK_BIT) {
C(append(proto,
GPC_I_BITVECTOR_BC_AND_SKIP_FIELD,
offset + tsf_offsetof(tsf_native_void_array_t,
len)));
} else if (src_type->u.a.element_type->kind_code
== TSF_TK_VOID) {
/* nothing to do */
} else {
static_size =
tsf_type_get_static_size(src_type->u.a.element_type);
if (static_size == UINT32_MAX) {
loop_label = label++;
done_label = label++;
C(append(proto,
GPC_I_PUSH_VAL,
offset + tsf_offsetof(tsf_native_void_array_t,
len)));
C(append(proto, GPC_I_ZEROJUMP, done_label));
C(append(proto, GPC_I_LABEL, loop_label));
C(generate_parser(proto,
tsf_type_create(TSF_TK_VOID),
src_type->u.a.element_type,
0,
label,
tsf_true));
C(append(proto, GPC_I_DECCOMPJUMP, loop_label));
C(append(proto, GPC_I_LABEL, done_label));
C(append(proto, GPC_I_POP));
} else {
C(append(proto,
GPC_I_ARRAY_BC_AND_SKIP_FIELD,
offset + tsf_offsetof(tsf_native_void_array_t,
len),
static_size));
}
}
} else if (dest_type->u.a.element_type->kind_code == TSF_TK_BIT) {
switch (src_type->u.a.element_type->kind_code) {
case TSF_TK_BIT:
C(append(proto,
GPC_I_BITVECTOR_READ,
offset));
break;
case TSF_TK_UINT8:
case TSF_TK_INT8:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_C,
offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_S,
offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_L,
offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_LL,
offset));
break;
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_TSF_INTEGER_ARRAY,
offset));
break;
case TSF_TK_LONG:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_TSF_LONG_ARRAY,
offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_F,
offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_BITVECTOR_READ_FROM_D,
offset));
break;
default:
tsf_abort("odd case");
break;
}
} else if (src_type->u.a.element_type->kind_code == TSF_TK_BIT) {
switch (dest_type->u.a.element_type->kind_code) {
case TSF_TK_UINT8:
case TSF_TK_INT8:
C(append(proto,
GPC_I_BITVECTOR_READ_TO_C,
offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto,
GPC_I_BITVECTOR_READ_TO_S,
offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_BITVECTOR_READ_TO_L,
offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_BITVECTOR_READ_TO_LL,
offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_BITVECTOR_READ_TO_F,
offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_BITVECTOR_READ_TO_D,
offset));
break;
default:
tsf_abort("odd case");
break;
}
} else if (src_type->u.a.element_type->kind_code
== dest_type->u.a.element_type->kind_code &&
(src_type->u.a.element_type->kind_code == TSF_TK_UINT8 ||
src_type->u.a.element_type->kind_code == TSF_TK_INT8
#ifndef NEED_INT_CONVERSION
|| (tsf_type_kind_is_int(src_type->u.a.element_type->kind_code)
&& src_type->u.a.element_type->kind_code != TSF_TK_INTEGER
&& src_type->u.a.element_type->kind_code != TSF_TK_LONG)
#endif
#ifndef NEED_FLOAT_CONVERSION
|| tsf_type_kind_is_float(src_type->u.a.element_type->kind_code)
#endif
)) {
C(append(proto,
GPC_I_BYTE_ARRAY_READ,
offset,
tsf_type_get_static_size(src_type->u.a.element_type)));
} else {
C(append(proto,
GPC_I_ARRAY_LEN_READ_FIELD,
offset + tsf_offsetof(tsf_native_array_t, len)));
static_size = tsf_type_get_static_size(src_type->u.a.element_type);
if (static_size != UINT32_MAX) {
C(append(proto,
GPC_I_ARRAY_BC_FIELD,
offset + tsf_offsetof(tsf_native_array_t, len),
static_size));
}
C(append(proto,
GPC_I_ALLOC_ARRAY,
offset,
tsf_native_type_get_size(dest_type->u.a.element_type)));
loop_label = label++;
done_label = label++;
C(append(proto,
GPC_I_REPUSH_MULADD_PTR,
offset + tsf_offsetof(tsf_native_array_t,len),
tsf_native_type_get_size(dest_type->u.a.element_type)));
C(append(proto,
GPC_I_COMPFAILJUMP,
done_label));
C(append(proto, GPC_I_LABEL, loop_label));
C(generate_parser(proto,
dest_type->u.a.element_type,
src_type->u.a.element_type,
0,
label,
static_size == UINT32_MAX));
C(append(proto,
GPC_I_ADDCOMPJUMP,
tsf_native_type_get_size(dest_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(src_type) >= 256) {
if (src_type->u.h.choice_as_full_word) {
if (do_bounds_check) {
C(append(proto, GPC_I_BC, 4));
}
C(append(proto, GPC_I_READL));
} else {
C(append(proto, GPC_I_TSF_UNSIGNED_READ_SUB1));
}
} else {
if (do_bounds_check) {
C(append(proto, GPC_I_BC, 1));
}
C(append(proto, GPC_I_READC_TO_CHOICE));
}
if (tsf_choice_type_has_non_void(src_type)) {
/* use tablejump */
label_offset = label;
label += tsf_choice_type_get_num_elements(src_type);
done_label = label++;
really_done_label = label++;
targets=malloc(sizeof(gpc_cell_t) *
tsf_choice_type_get_num_elements(src_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(src_type); ++i) {
targets[i] = label_offset + i;
}
result=append_tablejump_local(proto,
tsf_choice_type_get_num_elements(src_type),
targets);
free(targets);
if (!result) {
return tsf_false;
}
C(append(proto,
GPC_I_SET_L,
(gpc_cell_t)(offset + dest_type->u.h.value_offset),
(gpc_cell_t)UINT32_MAX));
C(append(proto, GPC_I_JUMP, really_done_label));
for (i = 0; i < tsf_choice_type_get_num_elements(src_type); ++i) {
tsf_named_type_t *sn =
tsf_choice_type_get_element(src_type, i);
tsf_named_type_t *dn =
tsf_choice_type_find_node(dest_type, sn->name);
C(append(proto, GPC_I_LABEL, label_offset + i));
if (dn == NULL) {
C(append(proto,
GPC_I_SET_L,
(gpc_cell_t)offset + dest_type->u.h.value_offset,
(gpc_cell_t)UINT32_MAX));
C(generate_parser(proto,
tsf_type_create(TSF_TK_VOID),
sn->type,
0,
label,
tsf_true));
C(append(proto, GPC_I_JUMP, really_done_label));
} else {
C(append(proto,
GPC_I_SET_L,
(gpc_cell_t)offset + dest_type->u.h.value_offset,
(gpc_cell_t)dn->index));
if (tsf_native_choice_type_is_in_place(dest_type)) {
C(generate_parser(proto,
dn->type,
sn->type,
offset + dest_type->u.h.data_offset,
label,
tsf_true));
} else {
C(append(proto,
GPC_I_ALLOC,
tsf_native_type_get_size(dn->type)));
C(append(proto,
GPC_I_STORE_PTR,
offset + dest_type->u.h.data_offset));
C(generate_parser(proto,
dn->type,
sn->type,
0,
label,
tsf_true));
}
C(append(proto, GPC_I_JUMP, done_label));
}
}
C(append(proto, GPC_I_LABEL, done_label));
if (!tsf_native_choice_type_is_in_place(dest_type)) {
C(append(proto, GPC_I_POP));
}
C(append(proto, GPC_I_LABEL, really_done_label));
} else if (tsf_choice_type_uses_same_indices(src_type,
dest_type)) {
/* use checkchoice and store */
C(append(proto,
GPC_I_CHECKCHOICE,
tsf_choice_type_get_num_elements(src_type)));
C(append(proto,
GPC_I_STORE_VAL,
offset + dest_type->u.h.value_offset));
C(append(proto, GPC_I_POP));
} else {
/* use tableset_local_to_field */
targets=malloc(sizeof(gpc_cell_t) *
tsf_choice_type_get_num_elements(src_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(src_type); ++i) {
tsf_named_type_t *sn =
tsf_choice_type_get_element(src_type, i);
tsf_named_type_t *dn =
tsf_choice_type_find_node(dest_type, sn->name);
if (dn == NULL) {
targets[i] = UINT32_MAX;
} else {
targets[i] = dn->index;
}
}
result = append_tableset_local_to_field(
proto,
offset + dest_type->u.h.value_offset,
tsf_choice_type_get_num_elements(src_type),
targets);
free(targets);
if (!result) {
return tsf_false;
}
}
break;
case TSF_TK_STRING:
C(append(proto, GPC_I_STRING_READ, offset));
break;
case TSF_TK_ANY:
C(append(proto, GPC_I_ANY_READ, offset));
break;
default:
tsf_abort("Unknown type");
break;
}
return tsf_true;
}