in benchmarks/JetStream2/wasm/TSF/tsf_gpc_code_gen.c [1829:2887]
static tsf_bool_t generate_converter(gpc_proto_t *proto,
tsf_type_t *dest_type,
tsf_type_t *src_type,
gpc_cell_t dest_offset,
gpc_cell_t src_offset,
gpc_cell_t label) {
uint32_t i;
gpc_cell_t done_label,really_done_label;
gpc_cell_t loop_label;
gpc_cell_t label_offset;
gpc_cell_t *targets;
tsf_bool_t result;
if (dest_type->kind_code == TSF_TK_VOID) {
return tsf_true;
}
if (!tsf_type_instanceof(src_type, dest_type)) {
C(generate_set_default_copier(proto, dest_type, dest_offset));
}
/* reason why we don't memcpy primitives: if we see a primitive at
this point, then it is just one word - so a primitive copy
operation will be faster than memcpy.
interestingly, if we see a struct that contains exactly one
primitive, we will still use memcpy (unless it is a byte). this
is not optimal, but oh well. */
if (!tsf_type_kind_is_primitive(tsf_type_get_kind_code(src_type)) &&
tsf_native_type_can_blit(dest_type,src_type)) {
switch (tsf_native_type_get_size(src_type)) {
case 0:
break;
case 1:
C(append(proto,
GPC_I_COPY_C,
dest_offset,
src_offset));
break;
default:
C(append(proto,
GPC_I_MEMCPY,
dest_offset,
src_offset,
tsf_native_type_get_size(src_type)));
break;
}
return tsf_true;
}
switch (src_type->kind_code) {
case TSF_TK_BIT:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
tsf_abort("bit-to-bit copies should have been handled elsewhere");
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_BIT_TO_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_BIT_TO_L,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_BIT_TO_LL,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_BIT_TO_F,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_BIT_TO_D,
dest_offset,
src_offset));
break;
default:
tsf_abort("Bad src_type/dest_type combination; "
"should have been caught by "
"tsf_type_instanceof()");
break;
}
break;
case TSF_TK_INT8:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto,
GPC_I_COPY_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_C_TO_S_E,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_C_TO_L_E,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_C_TO_LL_E,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_C_TO_F_E,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_C_TO_D_E,
dest_offset,
src_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_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_C_TO_S_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_C_TO_L_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_C_TO_LL_Z,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_C_TO_F_Z,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_C_TO_D_Z,
dest_offset,
src_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_S_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_S_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_S_TO_L_E,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_S_TO_LL_E,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_S_TO_F_E,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_S_TO_D_E,
dest_offset,
src_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_S_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_S_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_S_TO_L_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_S_TO_LL_Z,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_S_TO_F_Z,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_S_TO_D_Z,
dest_offset,
src_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:
case TSF_TK_INTEGER:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto,
GPC_I_COPY_L_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_L_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_L_TO_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_L,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_L_TO_LL_E,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_L_TO_F_E,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_L_TO_D_E,
dest_offset,
src_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_L_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_L_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_L_TO_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_L,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_L_TO_LL_Z,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_L_TO_F_Z,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_L_TO_D_Z,
dest_offset,
src_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:
case TSF_TK_LONG:
switch (dest_type->kind_code) {
case TSF_TK_BIT:
C(append(proto,
GPC_I_COPY_LL_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_LL_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_LL_TO_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_LL_TO_L,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_LL,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_LL_TO_F_E,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_LL_TO_D_E,
dest_offset,
src_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_LL_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_LL_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_LL_TO_S,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_UINT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_LL_TO_L,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_UINT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_LL,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_LL_TO_F_Z,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_LL_TO_D_Z,
dest_offset,
src_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_F_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_F_TO_C_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
C(append(proto,
GPC_I_COPY_F_TO_C_E,
dest_offset,
src_offset));
break;
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_F_TO_S_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
C(append(proto,
GPC_I_COPY_F_TO_S_E,
dest_offset,
src_offset));
break;
case TSF_TK_UINT32:
C(append(proto,
GPC_I_COPY_F_TO_L_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_F_TO_L_E,
dest_offset,
src_offset));
break;
case TSF_TK_UINT64:
C(append(proto,
GPC_I_COPY_F_TO_LL_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_F_TO_LL_E,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_F,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_F_TO_D,
dest_offset,
src_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_D_TO_BIT,
dest_offset,
src_offset));
break;
case TSF_TK_UINT8:
C(append(proto,
GPC_I_COPY_D_TO_C_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT8:
C(append(proto,
GPC_I_COPY_D_TO_C_E,
dest_offset,
src_offset));
break;
case TSF_TK_UINT16:
C(append(proto,
GPC_I_COPY_D_TO_S_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT16:
C(append(proto,
GPC_I_COPY_D_TO_S_E,
dest_offset,
src_offset));
break;
case TSF_TK_UINT32:
C(append(proto,
GPC_I_COPY_D_TO_L_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_D_TO_L_E,
dest_offset,
src_offset));
break;
case TSF_TK_UINT64:
C(append(proto,
GPC_I_COPY_D_TO_LL_Z,
dest_offset,
src_offset));
break;
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_D_TO_LL_E,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_D_TO_F,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_D,
dest_offset,
src_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 ||
dest_type->u.s.pre_destructor != NULL) {
/* This could be optimized by adding I_CALL_2ND and I_ADD_CBACK_2ND. I don't think
it's worth it. */
C(append(proto, GPC_I_DUP_PTR_2ND));
if (dest_type->u.s.constructor != NULL) {
C(append(proto, GPC_I_CALL,
dest_offset,
dest_type->u.s.constructor));
}
if (dest_type->u.s.pre_destructor != NULL) {
C(append(proto, GPC_I_ADD_CBACK,
dest_offset,
dest_type->u.s.pre_destructor));
}
C(append(proto, GPC_I_POP));
}
for (i = 0; i < tsf_struct_type_get_num_elements(dest_type); ++i) {
tsf_named_type_t *n =
tsf_struct_type_get_element(dest_type, i);
tsf_named_type_t *n2 =
tsf_struct_type_find_node(src_type, n->name);
if (n2 == NULL) {
C(generate_set_default_copier(
proto, n->type, dest_offset + n->offset));
} else {
C(generate_converter(proto,
n->type,
n2->type,
dest_offset + n->offset,
src_offset + n2->offset,
label));
}
}
break;
case TSF_TK_ARRAY:
if (dest_type->u.a.element_type->kind_code == TSF_TK_VOID) {
C(append(proto,
GPC_I_COPY_L,
(gpc_cell_t)(dest_offset +
tsf_offsetof(tsf_native_void_array_t, len)),
(gpc_cell_t)(src_offset +
src_type->u.a.element_type->kind_code == TSF_TK_VOID
? tsf_offsetof(tsf_native_void_array_t, len)
: (src_type->u.a.element_type->kind_code == TSF_TK_BIT
? tsf_offsetof(tsf_native_bitvector_t, num_bits)
: tsf_offsetof(tsf_native_array_t, len)))));
} 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_COPY_BITVECTOR,
dest_offset,
src_offset));
break;
case TSF_TK_UINT8:
case TSF_TK_INT8:
C(append(proto,
GPC_I_COPY_BITVECTOR_FROM_C,
dest_offset,
src_offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto,
GPC_I_COPY_BITVECTOR_FROM_S,
dest_offset,
src_offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_BITVECTOR_FROM_L,
dest_offset,
src_offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_BITVECTOR_FROM_LL,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_BITVECTOR_FROM_F,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_BITVECTOR_FROM_D,
dest_offset,
src_offset));
break;
default:
tsf_abort("case missed");
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_COPY_BITVECTOR_TO_C,
dest_offset,
src_offset));
break;
case TSF_TK_UINT16:
case TSF_TK_INT16:
C(append(proto,
GPC_I_COPY_BITVECTOR_TO_S,
dest_offset,
src_offset));
break;
case TSF_TK_UINT32:
case TSF_TK_INT32:
case TSF_TK_INTEGER:
C(append(proto,
GPC_I_COPY_BITVECTOR_TO_L,
dest_offset,
src_offset));
break;
case TSF_TK_UINT64:
case TSF_TK_INT64:
case TSF_TK_LONG:
C(append(proto,
GPC_I_COPY_BITVECTOR_TO_LL,
dest_offset,
src_offset));
break;
case TSF_TK_FLOAT:
C(append(proto,
GPC_I_COPY_BITVECTOR_TO_F,
dest_offset,
src_offset));
break;
case TSF_TK_DOUBLE:
C(append(proto,
GPC_I_COPY_BITVECTOR_TO_D,
dest_offset,
src_offset));
break;
default:
tsf_abort("case missed");
}
} else if (tsf_native_type_can_blit(dest_type->u.a.element_type,
src_type->u.a.element_type) &&
tsf_native_type_get_size(dest_type->u.a.element_type) ==
tsf_native_type_get_size(src_type->u.a.element_type)) {
C(append(proto,
GPC_I_COPY_ARRAY,
dest_offset,
src_offset,
tsf_native_type_get_size(dest_type->u.a.element_type)));
} else {
loop_label = label++;
done_label = label++;
C(append(proto,
GPC_I_COPY_L,
dest_offset + tsf_offsetof(tsf_native_array_t, len),
src_offset + tsf_offsetof(tsf_native_array_t, len)));
C(append(proto,
GPC_I_ALLOC_ARRAY_2ND,
dest_offset,
tsf_native_type_get_size(dest_type->u.a.element_type)));
C(append(proto,
GPC_I_REPUSH_MULADD_PTR_2ND,
dest_offset + tsf_offsetof(tsf_native_array_t, len),
tsf_native_type_get_size(dest_type->u.a.element_type)));
C(append(proto,
GPC_I_PUSH_PTR_3RD,
src_offset + tsf_offsetof(tsf_native_array_t, data)));
C(append(proto,
GPC_I_COMPFAILJUMP_2ND,
done_label));
C(append(proto,GPC_I_LABEL, loop_label));
C(generate_converter(proto,
dest_type->u.a.element_type,
src_type->u.a.element_type,
0,
0,
label));
C(append(proto,
GPC_I_TWO_ADDCOMPJUMP,
tsf_native_type_get_size(dest_type->u.a.element_type),
tsf_native_type_get_size(src_type->u.a.element_type),
loop_label));
C(append(proto, GPC_I_LABEL, done_label));
C(append(proto, GPC_I_THREE_POP));
}
break;
case TSF_TK_CHOICE:
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;
}
if (tsf_choice_type_has_non_void(src_type)) {
label_offset = label;
label += tsf_choice_type_get_num_elements(src_type);
done_label = label++;
really_done_label = label++;
for (i = 0; i < tsf_choice_type_get_num_elements(src_type); ++i) {
targets[i] = label_offset + i;
}
result = append_tablejump_field(
proto,
src_offset + src_type->u.h.value_offset,
tsf_choice_type_get_num_elements(src_type),
targets);
free(targets);
if (!result) {
return tsf_false;
}
C(append(proto,
GPC_I_SET_2ND_L,
(gpc_cell_t)(dest_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_2ND_L,
(gpc_cell_t)(dest_offset + dest_type->u.h.value_offset),
(gpc_cell_t)UINT32_MAX));
C(append(proto, GPC_I_JUMP, really_done_label));
} else {
C(append(proto,
GPC_I_SET_2ND_L,
(gpc_cell_t)(dest_offset + dest_type->u.h.value_offset),
(gpc_cell_t)dn->index));
if (!tsf_native_choice_type_is_in_place(src_type) ||
!tsf_native_choice_type_is_in_place(dest_type)) {
uint32_t src_off = 0;
uint32_t dest_off = 0;
if (tsf_native_choice_type_is_in_place(dest_type)) {
C(append(proto, GPC_I_DUP_PTR_2ND));
dest_off = dest_offset +
dest_type->u.h.data_offset;
} else {
/* must alloc */
C(append(proto, GPC_I_ALLOC,
tsf_native_type_get_size(dn->type)));
C(append(proto, GPC_I_STORE_PTR_2ND,
dest_offset +
dest_type->u.h.data_offset));
}
if (tsf_native_choice_type_is_in_place(src_type)) {
C(append(proto, GPC_I_DUP_PTR_2ND));
src_off = src_offset +
src_type->u.h.data_offset;
} else {
/* just load */
C(append(proto, GPC_I_PUSH_PTR_2ND,
src_offset +
src_type->u.h.data_offset));
}
C(generate_converter(proto,
dn->type,
sn->type,
dest_off,
src_off,
label));
C(append(proto, GPC_I_JUMP, done_label));
} else {
C(generate_converter(proto,
dn->type,
sn->type,
dest_offset +
dest_type->u.h.data_offset,
src_offset +
src_type->u.h.data_offset,
label));
C(append(proto, GPC_I_JUMP, really_done_label));
}
}
}
C(append(proto, GPC_I_LABEL, done_label));
if (!tsf_native_choice_type_is_in_place(src_type) ||
!tsf_native_choice_type_is_in_place(dest_type)) {
C(append(proto, GPC_I_TWO_POP));
}
C(append(proto, GPC_I_LABEL, really_done_label));
} else {
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_field_to_field(
proto,
dest_offset + dest_type->u.h.value_offset,
src_offset + src_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_COPY,
dest_offset,
src_offset));
break;
case TSF_TK_ANY:
C(append(proto,
GPC_I_ANY_COPY,
dest_offset,
src_offset));
break;
default:
tsf_abort("Bad type.");
break;
}
return tsf_true;
}