diff options
| author | Andreas Schwab | 2021-08-30 18:26:46 +0200 |
|---|---|---|
| committer | Andreas Schwab | 2021-08-30 19:00:46 +0200 |
| commit | 6767e556590b10a168300a8746589cf401bc93eb (patch) | |
| tree | 24d9920e44d9b97fbe96ae9a8acbeaa6f9019f09 /src/comp.c | |
| parent | ebd7c52f1169fb61a5f9a4a02959e5eedba79d86 (diff) | |
| download | emacs-6767e556590b10a168300a8746589cf401bc93eb.tar.gz emacs-6767e556590b10a168300a8746589cf401bc93eb.zip | |
Implement proper type conversion in native compiler
* src/comp.c (enum cast_kind_of_type): Remove.
(comp_t): Add cast_ptr_to_int, cast_int_to_ptr, remove
cast_type_sizes, cast_type_kind, cast_type_names, cast_union_fields,
cast_union_field_biggest_type.
(emit_coerce): Remove check for type size.
(struct cast_type): Remove bytes_size.
(define_type_punning): New function.
(define_cast_from_to): Implement proper type conversion.
(define_cast_functions): Adjust. (bug#50230)
Diffstat (limited to 'src/comp.c')
| -rw-r--r-- | src/comp.c | 210 |
1 files changed, 102 insertions, 108 deletions
diff --git a/src/comp.c b/src/comp.c index 74a5337f8d7..3ea2836560f 100644 --- a/src/comp.c +++ b/src/comp.c | |||
| @@ -499,13 +499,6 @@ static f_reloc_t freloc; | |||
| 499 | 499 | ||
| 500 | #define NUM_CAST_TYPES 15 | 500 | #define NUM_CAST_TYPES 15 |
| 501 | 501 | ||
| 502 | enum cast_kind_of_type | ||
| 503 | { | ||
| 504 | kind_unsigned, | ||
| 505 | kind_signed, | ||
| 506 | kind_pointer | ||
| 507 | }; | ||
| 508 | |||
| 509 | typedef struct { | 502 | typedef struct { |
| 510 | EMACS_INT len; | 503 | EMACS_INT len; |
| 511 | gcc_jit_rvalue *r_val; | 504 | gcc_jit_rvalue *r_val; |
| @@ -571,14 +564,9 @@ typedef struct { | |||
| 571 | be used for the scope. */ | 564 | be used for the scope. */ |
| 572 | gcc_jit_type *cast_union_type; | 565 | gcc_jit_type *cast_union_type; |
| 573 | gcc_jit_function *cast_functions_from_to[NUM_CAST_TYPES][NUM_CAST_TYPES]; | 566 | gcc_jit_function *cast_functions_from_to[NUM_CAST_TYPES][NUM_CAST_TYPES]; |
| 574 | /* We add one to make space for the last member which is the "biggest_type" | 567 | gcc_jit_function *cast_ptr_to_int; |
| 575 | member. */ | 568 | gcc_jit_function *cast_int_to_ptr; |
| 576 | gcc_jit_type *cast_types[NUM_CAST_TYPES + 1]; | 569 | gcc_jit_type *cast_types[NUM_CAST_TYPES]; |
| 577 | size_t cast_type_sizes[NUM_CAST_TYPES + 1]; | ||
| 578 | enum cast_kind_of_type cast_type_kind[NUM_CAST_TYPES + 1]; | ||
| 579 | const char *cast_type_names[NUM_CAST_TYPES + 1]; | ||
| 580 | gcc_jit_field *cast_union_fields[NUM_CAST_TYPES + 1]; | ||
| 581 | size_t cast_union_field_biggest_type; | ||
| 582 | gcc_jit_function *func; /* Current function being compiled. */ | 570 | gcc_jit_function *func; /* Current function being compiled. */ |
| 583 | bool func_has_non_local; /* From comp-func has-non-local slot. */ | 571 | bool func_has_non_local; /* From comp-func has-non-local slot. */ |
| 584 | EMACS_INT func_speed; /* From comp-func speed slot. */ | 572 | EMACS_INT func_speed; /* From comp-func speed slot. */ |
| @@ -1113,13 +1101,6 @@ emit_coerce (gcc_jit_type *new_type, gcc_jit_rvalue *obj) | |||
| 1113 | int old_index = type_to_cast_index (old_type); | 1101 | int old_index = type_to_cast_index (old_type); |
| 1114 | int new_index = type_to_cast_index (new_type); | 1102 | int new_index = type_to_cast_index (new_type); |
| 1115 | 1103 | ||
| 1116 | if (comp.cast_type_sizes[old_index] < comp.cast_type_sizes[new_index] | ||
| 1117 | && comp.cast_type_kind[new_index] == kind_signed) | ||
| 1118 | xsignal3 (Qnative_ice, | ||
| 1119 | build_string ("FIXME: sign extension not implemented"), | ||
| 1120 | build_string (comp.cast_type_names[old_index]), | ||
| 1121 | build_string (comp.cast_type_names[new_index])); | ||
| 1122 | |||
| 1123 | /* Lookup the appropriate cast function in the cast matrix. */ | 1104 | /* Lookup the appropriate cast function in the cast matrix. */ |
| 1124 | return gcc_jit_context_new_call (comp.ctxt, | 1105 | return gcc_jit_context_new_call (comp.ctxt, |
| 1125 | NULL, | 1106 | NULL, |
| @@ -3111,30 +3092,17 @@ define_thread_state_struct (void) | |||
| 3111 | gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.thread_state_s)); | 3092 | gcc_jit_type_get_pointer (gcc_jit_struct_as_type (comp.thread_state_s)); |
| 3112 | } | 3093 | } |
| 3113 | 3094 | ||
| 3114 | struct cast_type | ||
| 3115 | { | ||
| 3116 | gcc_jit_type *type; | ||
| 3117 | const char *name; | ||
| 3118 | size_t bytes_size; | ||
| 3119 | enum cast_kind_of_type kind; | ||
| 3120 | }; | ||
| 3121 | |||
| 3122 | static gcc_jit_function * | 3095 | static gcc_jit_function * |
| 3123 | define_cast_from_to (struct cast_type from, int from_index, struct cast_type to, | 3096 | define_type_punning (const char *name, |
| 3124 | int to_index) | 3097 | gcc_jit_type *from, gcc_jit_field *from_field, |
| 3098 | gcc_jit_type *to, gcc_jit_field *to_field) | ||
| 3125 | { | 3099 | { |
| 3126 | /* FIXME: sign extension not implemented. */ | ||
| 3127 | if (comp.cast_type_sizes[from_index] < comp.cast_type_sizes[to_index] | ||
| 3128 | && comp.cast_type_kind[to_index] == kind_signed) | ||
| 3129 | return NULL; | ||
| 3130 | |||
| 3131 | char *name = format_string ("cast_from_%s_to_%s", from.name, to.name); | ||
| 3132 | gcc_jit_param *param = gcc_jit_context_new_param (comp.ctxt, NULL, | 3100 | gcc_jit_param *param = gcc_jit_context_new_param (comp.ctxt, NULL, |
| 3133 | from.type, "arg"); | 3101 | from, "arg"); |
| 3134 | gcc_jit_function *result = gcc_jit_context_new_function (comp.ctxt, | 3102 | gcc_jit_function *result = gcc_jit_context_new_function (comp.ctxt, |
| 3135 | NULL, | 3103 | NULL, |
| 3136 | GCC_JIT_FUNCTION_INTERNAL, | 3104 | GCC_JIT_FUNCTION_INTERNAL, |
| 3137 | to.type, | 3105 | to, |
| 3138 | name, | 3106 | name, |
| 3139 | 1, | 3107 | 1, |
| 3140 | ¶m, | 3108 | ¶m, |
| @@ -3148,26 +3116,63 @@ define_cast_from_to (struct cast_type from, int from_index, struct cast_type to, | |||
| 3148 | comp.cast_union_type, | 3116 | comp.cast_union_type, |
| 3149 | "union_cast"); | 3117 | "union_cast"); |
| 3150 | 3118 | ||
| 3151 | /* Zero the union first. */ | ||
| 3152 | gcc_jit_block_add_assignment (entry_block, NULL, | 3119 | gcc_jit_block_add_assignment (entry_block, NULL, |
| 3153 | gcc_jit_lvalue_access_field (tmp_union, NULL, | 3120 | gcc_jit_lvalue_access_field (tmp_union, NULL, |
| 3154 | comp.cast_union_fields[NUM_CAST_TYPES]), | 3121 | from_field), |
| 3155 | gcc_jit_context_new_rvalue_from_int ( | ||
| 3156 | comp.ctxt, | ||
| 3157 | comp.cast_types[NUM_CAST_TYPES], | ||
| 3158 | 0)); | ||
| 3159 | |||
| 3160 | gcc_jit_block_add_assignment (entry_block, NULL, | ||
| 3161 | gcc_jit_lvalue_access_field (tmp_union, NULL, | ||
| 3162 | comp.cast_union_fields[from_index]), | ||
| 3163 | gcc_jit_param_as_rvalue (param)); | 3122 | gcc_jit_param_as_rvalue (param)); |
| 3164 | 3123 | ||
| 3165 | gcc_jit_block_end_with_return (entry_block, | 3124 | gcc_jit_block_end_with_return (entry_block, |
| 3166 | NULL, | 3125 | NULL, |
| 3167 | gcc_jit_rvalue_access_field ( | 3126 | gcc_jit_rvalue_access_field ( |
| 3168 | gcc_jit_lvalue_as_rvalue (tmp_union), | 3127 | gcc_jit_lvalue_as_rvalue (tmp_union), |
| 3169 | NULL, | 3128 | NULL, to_field)); |
| 3170 | comp.cast_union_fields[to_index])); | 3129 | |
| 3130 | return result; | ||
| 3131 | } | ||
| 3132 | |||
| 3133 | struct cast_type | ||
| 3134 | { | ||
| 3135 | gcc_jit_type *type; | ||
| 3136 | const char *name; | ||
| 3137 | bool is_ptr; | ||
| 3138 | }; | ||
| 3139 | |||
| 3140 | static gcc_jit_function * | ||
| 3141 | define_cast_from_to (struct cast_type from, struct cast_type to) | ||
| 3142 | { | ||
| 3143 | char *name = format_string ("cast_from_%s_to_%s", from.name, to.name); | ||
| 3144 | gcc_jit_param *param = gcc_jit_context_new_param (comp.ctxt, NULL, | ||
| 3145 | from.type, "arg"); | ||
| 3146 | gcc_jit_function *result | ||
| 3147 | = gcc_jit_context_new_function (comp.ctxt, | ||
| 3148 | NULL, | ||
| 3149 | GCC_JIT_FUNCTION_INTERNAL, | ||
| 3150 | to.type, name, | ||
| 3151 | 1, ¶m, 0); | ||
| 3152 | DECL_BLOCK (entry_block, result); | ||
| 3153 | |||
| 3154 | gcc_jit_rvalue *tmp = gcc_jit_param_as_rvalue (param); | ||
| 3155 | if (from.is_ptr != to.is_ptr) | ||
| 3156 | { | ||
| 3157 | if (from.is_ptr) | ||
| 3158 | { | ||
| 3159 | tmp = gcc_jit_context_new_cast (comp.ctxt, NULL, | ||
| 3160 | tmp, comp.void_ptr_type); | ||
| 3161 | tmp = gcc_jit_context_new_call (comp.ctxt, NULL, | ||
| 3162 | comp.cast_ptr_to_int, 1, &tmp); | ||
| 3163 | } | ||
| 3164 | else | ||
| 3165 | { | ||
| 3166 | tmp = gcc_jit_context_new_cast (comp.ctxt, NULL, | ||
| 3167 | tmp, comp.uintptr_type); | ||
| 3168 | tmp = gcc_jit_context_new_call (comp.ctxt, NULL, | ||
| 3169 | comp.cast_int_to_ptr, 1, &tmp); | ||
| 3170 | } | ||
| 3171 | } | ||
| 3172 | |||
| 3173 | tmp = gcc_jit_context_new_cast (comp.ctxt, NULL, tmp, to.type); | ||
| 3174 | |||
| 3175 | gcc_jit_block_end_with_return (entry_block, NULL, tmp); | ||
| 3171 | 3176 | ||
| 3172 | return result; | 3177 | return result; |
| 3173 | } | 3178 | } |
| @@ -3176,69 +3181,58 @@ static void | |||
| 3176 | define_cast_functions (void) | 3181 | define_cast_functions (void) |
| 3177 | { | 3182 | { |
| 3178 | struct cast_type cast_types[NUM_CAST_TYPES] | 3183 | struct cast_type cast_types[NUM_CAST_TYPES] |
| 3179 | = { { comp.bool_type, "bool", sizeof (bool), kind_unsigned }, | 3184 | = { { comp.bool_type, "bool", false }, |
| 3180 | { comp.char_ptr_type, "char_ptr", sizeof (char *), kind_pointer }, | 3185 | { comp.char_ptr_type, "char_ptr", true }, |
| 3181 | { comp.int_type, "int", sizeof (int), kind_signed }, | 3186 | { comp.int_type, "int", false }, |
| 3182 | { comp.lisp_cons_ptr_type, "cons_ptr", sizeof (struct Lisp_Cons *), | 3187 | { comp.lisp_cons_ptr_type, "lisp_cons_ptr", true }, |
| 3183 | kind_pointer }, | 3188 | { comp.lisp_obj_ptr_type, "lisp_obj_ptr", true }, |
| 3184 | { comp.lisp_obj_ptr_type, "lisp_obj_ptr", sizeof (Lisp_Object *), | 3189 | { comp.lisp_word_tag_type, "lisp_word_tag", false }, |
| 3185 | kind_pointer }, | 3190 | { comp.lisp_word_type, "lisp_word", LISP_WORDS_ARE_POINTERS }, |
| 3186 | { comp.lisp_word_tag_type, "lisp_word_tag", sizeof (Lisp_Word_tag), | 3191 | { comp.long_long_type, "long_long", false }, |
| 3187 | kind_unsigned }, | 3192 | { comp.long_type, "long", false }, |
| 3188 | { comp.lisp_word_type, "lisp_word", sizeof (Lisp_Word), | 3193 | { comp.ptrdiff_type, "ptrdiff", false }, |
| 3189 | LISP_WORDS_ARE_POINTERS ? kind_pointer : kind_signed }, | 3194 | { comp.uintptr_type, "uintptr", false }, |
| 3190 | { comp.long_long_type, "long_long", sizeof (long long), kind_signed }, | 3195 | { comp.unsigned_long_long_type, "unsigned_long_long", false }, |
| 3191 | { comp.long_type, "long", sizeof (long), kind_signed }, | 3196 | { comp.unsigned_long_type, "unsigned_long", false }, |
| 3192 | { comp.ptrdiff_type, "ptrdiff", sizeof (ptrdiff_t), kind_signed }, | 3197 | { comp.unsigned_type, "unsigned", false }, |
| 3193 | { comp.uintptr_type, "uintptr", sizeof (uintptr_t), kind_unsigned }, | 3198 | { comp.void_ptr_type, "void_ptr", true } }; |
| 3194 | { comp.unsigned_long_long_type, "unsigned_long_long", | 3199 | gcc_jit_field *cast_union_fields[2]; |
| 3195 | sizeof (unsigned long long), kind_unsigned }, | 3200 | |
| 3196 | { comp.unsigned_long_type, "unsigned_long", sizeof (unsigned long), | 3201 | /* Define the union used for type punning. */ |
| 3197 | kind_unsigned }, | 3202 | cast_union_fields[0] = gcc_jit_context_new_field (comp.ctxt, |
| 3198 | { comp.unsigned_type, "unsigned", sizeof (unsigned), kind_unsigned }, | 3203 | NULL, |
| 3199 | { comp.void_ptr_type, "void_ptr", sizeof (void*), kind_pointer } }; | 3204 | comp.void_ptr_type, |
| 3200 | 3205 | "void_ptr"); | |
| 3201 | /* Find the biggest size. It should be unsigned long long, but to be | 3206 | cast_union_fields[1] = gcc_jit_context_new_field (comp.ctxt, |
| 3202 | sure we find it programmatically. */ | 3207 | NULL, |
| 3203 | size_t biggest_size = 0; | 3208 | comp.uintptr_type, |
| 3204 | for (int i = 0; i < NUM_CAST_TYPES; ++i) | 3209 | "uintptr"); |
| 3205 | biggest_size = max (biggest_size, cast_types[i].bytes_size); | ||
| 3206 | 3210 | ||
| 3207 | /* Define the union used for casting. */ | 3211 | comp.cast_union_type |
| 3208 | for (int i = 0; i < NUM_CAST_TYPES; ++i) | 3212 | = gcc_jit_context_new_union_type (comp.ctxt, |
| 3209 | { | 3213 | NULL, |
| 3210 | comp.cast_types[i] = cast_types[i].type; | 3214 | "cast_union", |
| 3211 | comp.cast_union_fields[i] = gcc_jit_context_new_field (comp.ctxt, | 3215 | 2, cast_union_fields); |
| 3212 | NULL, | 3216 | |
| 3213 | cast_types[i].type, | 3217 | comp.cast_ptr_to_int = define_type_punning ("cast_pointer_to_uintptr_t", |
| 3214 | cast_types[i].name); | 3218 | comp.void_ptr_type, |
| 3215 | comp.cast_type_names[i] = cast_types[i].name; | 3219 | cast_union_fields[0], |
| 3216 | comp.cast_type_sizes[i] = cast_types[i].bytes_size; | 3220 | comp.uintptr_type, |
| 3217 | comp.cast_type_kind[i] = cast_types[i].kind; | 3221 | cast_union_fields[1]); |
| 3218 | } | 3222 | comp.cast_int_to_ptr = define_type_punning ("cast_uintptr_t_to_pointer", |
| 3223 | comp.uintptr_type, | ||
| 3224 | cast_union_fields[1], | ||
| 3225 | comp.void_ptr_type, | ||
| 3226 | cast_union_fields[0]); | ||
| 3219 | 3227 | ||
| 3220 | gcc_jit_type *biggest_type = gcc_jit_context_get_int_type (comp.ctxt, | 3228 | for (int i = 0; i < NUM_CAST_TYPES; ++i) |
| 3221 | biggest_size, | 3229 | comp.cast_types[i] = cast_types[i].type; |
| 3222 | false); | ||
| 3223 | comp.cast_types[NUM_CAST_TYPES] = biggest_type; | ||
| 3224 | comp.cast_union_fields[NUM_CAST_TYPES] = | ||
| 3225 | gcc_jit_context_new_field (comp.ctxt, NULL, biggest_type, "biggest_type"); | ||
| 3226 | comp.cast_type_names[NUM_CAST_TYPES] = "biggest_type"; | ||
| 3227 | comp.cast_type_sizes[NUM_CAST_TYPES] = biggest_size; | ||
| 3228 | comp.cast_type_kind[NUM_CAST_TYPES] = kind_unsigned; | ||
| 3229 | |||
| 3230 | comp.cast_union_type = | ||
| 3231 | gcc_jit_context_new_union_type (comp.ctxt, | ||
| 3232 | NULL, | ||
| 3233 | "cast_union", | ||
| 3234 | NUM_CAST_TYPES + 1, | ||
| 3235 | comp.cast_union_fields); | ||
| 3236 | 3230 | ||
| 3237 | /* Define the cast functions using a matrix. */ | 3231 | /* Define the cast functions using a matrix. */ |
| 3238 | for (int i = 0; i < NUM_CAST_TYPES; ++i) | 3232 | for (int i = 0; i < NUM_CAST_TYPES; ++i) |
| 3239 | for (int j = 0; j < NUM_CAST_TYPES; ++j) | 3233 | for (int j = 0; j < NUM_CAST_TYPES; ++j) |
| 3240 | comp.cast_functions_from_to[i][j] = | 3234 | comp.cast_functions_from_to[i][j] = |
| 3241 | define_cast_from_to (cast_types[i], i, cast_types[j], j); | 3235 | define_cast_from_to (cast_types[i], cast_types[j]); |
| 3242 | } | 3236 | } |
| 3243 | 3237 | ||
| 3244 | static void | 3238 | static void |