2 * Copyright (C) 2024, 2025 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
42 #define NO_OPCODE ((code_t)-1)
44 #define fx(n) (OPCODE_FIXED_OP + (OPCODE_FIXED_OP_##n) * OPCODE_FIXED_OP_MULT)
45 #define in(n) (OPCODE_INT_OP + (OPCODE_INT_OP_##n) * OPCODE_INT_OP_MULT)
46 #define re(n) (OPCODE_REAL_OP + (OPCODE_REAL_OP_##n) * OPCODE_REAL_OP_MULT)
47 #define bo(n) (OPCODE_BOOL_OP + (OPCODE_BOOL_OP_##n) * OPCODE_BOOL_OP_MULT)
49 #define Op_Mov (Op_N + 0)
50 #define Op_Copy (Op_N + 1)
51 #define Op_Ldc (Op_N + 2)
52 #define Op_NN (Op_N + 3)
54 shared_var
const code_t pcode2code
[Op_NN
][5]
55 #ifndef FILE_COMPRESSION
57 { fx(add
), fx(add
), in(add
), re(add
), NO_OPCODE
, },
58 { fx(subtract
), fx(subtract
), in(subtract
), re(subtract
), NO_OPCODE
, },
59 { fx(multiply
), fx(multiply
), in(multiply
), re(multiply
), NO_OPCODE
, },
60 { fx(divide
), fx(udivide
), in(divide
), NO_OPCODE
, NO_OPCODE
, },
61 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(divide
), NO_OPCODE
, },
62 { fx(modulo
), fx(umodulo
), in(modulo
), re(modulo
), NO_OPCODE
, },
63 { fx(power
), fx(power
), in(power
), re(power
), NO_OPCODE
, },
64 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atan2
), NO_OPCODE
, },
65 { fx(and), fx(and), in(and), NO_OPCODE
, bo(and), },
66 { fx(or), fx(or), in(or), NO_OPCODE
, bo(or), },
67 { fx(xor), fx(xor), in(xor), NO_OPCODE
, bo(not_equal
), },
68 { fx(shl
), fx(shl
), in(shl
), re(ldexp
), NO_OPCODE
, },
69 { fx(shr
), fx(ushr
), in(shr
), NO_OPCODE
, NO_OPCODE
, },
70 { fx(rol
), fx(rol
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
71 { fx(ror
), fx(ror
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
72 { fx(bts
), fx(bts
), in(bts
), NO_OPCODE
, NO_OPCODE
, },
73 { fx(btr
), fx(btr
), in(btr
), NO_OPCODE
, NO_OPCODE
, },
74 { fx(btc
), fx(btc
), in(btc
), NO_OPCODE
, NO_OPCODE
, },
75 { fx(equal
), fx(equal
), in(equal
), re(equal
), bo(equal
), },
76 { fx(not_equal
), fx(not_equal
), in(not_equal
), re(not_equal
), bo(not_equal
), },
77 { fx(less
), fx(uless
), in(less
), re(less
), bo(less
), },
78 { fx(less_equal
), fx(uless_equal
), in(less_equal
), re(less_equal
), bo(less_equal
), },
79 { fx(greater
), fx(ugreater
), in(greater
), re(greater
), bo(greater
), },
80 { fx(greater_equal
), fx(ugreater_equal
), in(greater_equal
), re(greater_equal
), bo(greater_equal
),},
81 { fx(bt
), fx(bt
), in(bt
), NO_OPCODE
, NO_OPCODE
, },
82 { fx(not), fx(not), in(not), NO_OPCODE
, bo(not), },
83 { fx(neg
), fx(neg
), in(neg
), re(neg
), NO_OPCODE
, },
84 { fx(bswap
), fx(bswap
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
85 { fx(brev
), fx(brev
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
86 { fx(bsf
), fx(bsf
), in(bsf
), NO_OPCODE
, NO_OPCODE
, },
87 { fx(bsr
), fx(bsr
), in(bsr
), NO_OPCODE
, NO_OPCODE
, },
88 { fx(popcnt
), fx(popcnt
), in(popcnt
), NO_OPCODE
, NO_OPCODE
, },
89 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sqrt
), NO_OPCODE
, },
90 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cbrt
), NO_OPCODE
, },
91 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sin
), NO_OPCODE
, },
92 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cos
), NO_OPCODE
, },
93 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(tan
), NO_OPCODE
, },
94 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(asin
), NO_OPCODE
, },
95 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(acos
), NO_OPCODE
, },
96 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atan
), NO_OPCODE
, },
97 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sinh
), NO_OPCODE
, },
98 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cosh
), NO_OPCODE
, },
99 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(tanh
), NO_OPCODE
, },
100 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(asinh
), NO_OPCODE
, },
101 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(acosh
), NO_OPCODE
, },
102 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atanh
), NO_OPCODE
, },
103 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp2
), NO_OPCODE
, },
104 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp
), NO_OPCODE
, },
105 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp10
), NO_OPCODE
, },
106 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log2
), NO_OPCODE
, },
107 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log
), NO_OPCODE
, },
108 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log10
), NO_OPCODE
, },
109 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(round
), NO_OPCODE
, },
110 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(floor
), NO_OPCODE
, },
111 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(ceil
), NO_OPCODE
, },
112 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(trunc
), NO_OPCODE
, },
113 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(fract
), NO_OPCODE
, },
114 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(mantissa
), NO_OPCODE
, },
115 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exponent
), NO_OPCODE
, },
116 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(next_number
), NO_OPCODE
, },
117 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(prev_number
), NO_OPCODE
, },
118 { fx(to_int
), fx(uto_int
), in(to_int
), re(to_int
), NO_OPCODE
, },
119 { fx(from_int
), fx(ufrom_int
), in(from_int
), re(from_int
), NO_OPCODE
, },
120 { OPCODE_IS_EXCEPTION
, NO_OPCODE
, NO_OPCODE
, re(is_exception
), NO_OPCODE
, },
121 { OPCODE_EXCEPTION_CLASS
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
122 { OPCODE_EXCEPTION_TYPE
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
123 { OPCODE_EXCEPTION_AUX
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
124 { OPCODE_SYSTEM_PROPERTY
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
125 { fx(move
), fx(move
), in(move
), re(move
), bo(move
), },
126 { fx(copy
), fx(copy
), in(copy
), re(copy
), bo(copy
), },
127 { fx(ldc
), fx(ldc
), in(ldc
), re(ldc
), NO_OPCODE
, },
137 static void instruction_class(const struct type
*t
, unsigned *cls
, code_t
*typeq
, pcode_t op
)
139 if ((op
== Un_IsException
&& !TYPE_TAG_IS_REAL(t
->tag
)) || op
== Un_ExceptionClass
|| op
== Un_ExceptionType
|| op
== Un_ExceptionAux
|| op
== Un_SystemProperty
) {
142 } else if (TYPE_TAG_IS_FIXED(t
->tag
)) {
143 *typeq
= (TYPE_TAG_IDX_FIXED(t
->tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
;
144 *cls
= TYPE_TAG_FIXED_IS_UNSIGNED(t
->tag
);
145 } else if (TYPE_TAG_IS_INT(t
->tag
)) {
146 *typeq
= TYPE_TAG_IDX_INT(t
->tag
) * OPCODE_INT_TYPE_MULT
;
148 } else if (TYPE_TAG_IS_REAL(t
->tag
)) {
149 *typeq
= TYPE_TAG_IDX_REAL(t
->tag
) * OPCODE_REAL_TYPE_MULT
;
151 } else if (t
->tag
== TYPE_TAG_flat_option
) {
155 internal(file_line
, "instruction_class: invalid type %u", t
->tag
);
159 static code_t
get_code(pcode_t op
, const struct type
*t
)
163 ajla_assert(op
>= 0 && op
< Op_NN
, (file_line
, "get_code: invalid operation %"PRIdMAX
"", (intmax_t)op
));
164 instruction_class(t
, &cls
, &typeq
, op
);
165 code
= pcode2code
[op
][cls
];
166 ajla_assert(code
!= NO_OPCODE
, (file_line
, "get_code: invalid instruction and type: %"PRIdMAX
", %u", (intmax_t)op
, t
->tag
));
168 return code_alt(code
);
171 #define INIT_ARG_MODE 0
172 #define INIT_ARG_MODE_1 1
173 typedef unsigned char arg_mode_t
;
175 static bool adjust_arg_mode(arg_mode_t
*am
, uintmax_t offs
, ajla_error_t
*mayfail
)
178 if (offs
+ uzero
<= 0xff) my_am
= 0;
179 else if (offs
+ uzero
<= 0xffffU
) my_am
= 1;
180 else if (offs
+ uzero
<= 0xffffffffUL
+ uzero
) my_am
= 2;
182 if (unlikely(my_am
>= ARG_MODE_N
)) {
184 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
187 internal(file_line
, "adjust_arg_mode: too big arg mode: offset %"PRIuMAX
", max mode %d", (uintmax_t)offs
, ARG_MODE_N
);
189 if (unlikely(my_am
> *am
))
194 #define get_arg_mode(am, val) \
196 if (unlikely(!adjust_arg_mode(&(am), (val), ctx->err))) \
201 const struct type
*type
;
206 const struct type
*type
;
207 struct local_arg
*argument
;
211 bool is_dereferenced_in_call_argument
;
227 struct tree_entry entry
;
232 struct build_function_context
{
233 const pcode_t
*pcode
;
234 const pcode_t
*pcode_limit
;
235 const pcode_t
*pcode_instr_end
;
240 pcode_t function_type
;
241 pcode_t n_local_types
;
243 frame_t n_local_variables
;
245 arg_t n_return_values
;
246 arg_t n_real_arguments
;
247 arg_t n_real_return_values
;
250 uint8_t *function_name
;
252 struct local_type
*local_types
;
253 struct pcode_type
*pcode_types
; /* indexed by pcode idx */
254 struct layout
*layout
;
255 struct local_variable
*local_variables
; /* indexed by slot */
256 struct local_variable_flags
*local_variables_flags
; /* indexed by slot */
258 struct color
*colors
;
262 struct label_ref
*label_ref
;
263 size_t label_ref_len
;
269 struct local_arg
*args
;
271 const struct type
**types
;
273 struct data
*ft_free
;
278 frame_t
*record_entries
;
279 size_t record_entries_len
;
281 struct record_definition
*record_definition
;
283 struct line_position
*lp
;
286 struct escape_data
*escape_data
;
288 unsigned checkpoint_num
;
293 pcode_t builtin_type_indices
[TYPE_TAG_N
];
296 static const pcode_t no_type_index
= -1;
297 static const pcode_t error_type_index
= -2;
298 static const size_t no_label
= (size_t)-1;
300 static void init_ctx(struct build_function_context
*ctx
)
303 ctx
->n_real_arguments
= 0;
304 ctx
->function_name
= NULL
;
305 ctx
->local_types
= NULL
;
306 ctx
->pcode_types
= NULL
;
308 ctx
->local_variables
= NULL
;
309 ctx
->local_variables_flags
= NULL
;
312 ctx
->label_ref
= NULL
;
314 tree_init(&ctx
->ld_tree
);
320 ctx
->record_entries
= NULL
;
321 ctx
->record_definition
= NULL
;
324 ctx
->escape_data
= NULL
;
325 ctx
->checkpoint_num
= 0;
327 for (i
= 0; i
< n_array_elements(ctx
->builtin_type_indices
); i
++)
328 ctx
->builtin_type_indices
[i
] = no_type_index
;
331 static void free_ld_tree(struct build_function_context
*ctx
)
333 while (!tree_is_empty(&ctx
->ld_tree
)) {
334 struct ld_ref
*ld_ref
= get_struct(tree_any(&ctx
->ld_tree
), struct ld_ref
, entry
);
335 tree_delete(&ld_ref
->entry
);
340 static void done_ctx(struct build_function_context
*ctx
)
342 if (ctx
->function_name
)
343 mem_free(ctx
->function_name
);
344 if (ctx
->local_types
)
345 mem_free(ctx
->local_types
);
346 if (ctx
->pcode_types
)
347 mem_free(ctx
->pcode_types
);
349 layout_free(ctx
->layout
);
350 if (ctx
->local_variables
)
351 mem_free(ctx
->local_variables
);
352 if (ctx
->local_variables_flags
)
353 mem_free(ctx
->local_variables_flags
);
355 mem_free(ctx
->colors
);
357 mem_free(ctx
->labels
);
359 mem_free(ctx
->label_ref
);
366 mem_free(ctx
->types
);
368 mem_free(ctx
->ft_free
);
371 if (ctx
->record_entries
)
372 mem_free(ctx
->record_entries
);
373 if (ctx
->record_definition
) {
374 mem_free(ctx
->record_definition
->idx_to_frame
);
375 mem_free(ctx
->record_definition
);
379 if (ctx
->escape_data
)
380 mem_free(ctx
->escape_data
);
383 static char *function_name(const struct build_function_context
*ctx
)
385 if (ctx
->function_name
)
386 return cast_ptr(char *, ctx
->function_name
);
390 static pcode_t
pcode_get_fn(struct build_function_context
*ctx argument_position
)
392 ajla_assert(ctx
->pcode
< ctx
->pcode_limit
, (caller_file_line
, "pcode_get_fn(%s): no pcode left", function_name(ctx
)));
393 return *ctx
->pcode
++;
395 #define pcode_get() pcode_get_fn(ctx pass_file_line)
397 static pcode_t
u_pcode_get_fn(struct build_function_context
*ctx argument_position
)
399 pcode_t p
= pcode_get_fn(ctx pass_position
);
400 ajla_assert(p
>= 0, (caller_file_line
, "u_pcode_get_fn(%s): negative pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)p
));
403 #define u_pcode_get() u_pcode_get_fn(ctx pass_file_line)
405 typedef const pcode_t
*pcode_position_save_t
;
407 static inline void pcode_position_save(struct build_function_context
*ctx
, pcode_position_save_t
*save
)
412 static inline void pcode_position_restore(struct build_function_context
*ctx
, const pcode_position_save_t
*save
)
417 typedef size_t code_position_save_t
;
419 static inline void code_position_save(struct build_function_context
*ctx
, code_position_save_t
*save
)
421 *save
= ctx
->code_len
;
424 static inline void code_position_restore(struct build_function_context
*ctx
, const code_position_save_t
*save
)
426 ajla_assert_lo(ctx
->code_len
>= *save
, (file_line
, "code_position_restore(%s): attempting to restore forward: %"PRIuMAX
" < %"PRIuMAX
"", function_name(ctx
), (uintmax_t)ctx
->code_len
, (uintmax_t)*save
));
427 ctx
->code_len
= *save
;
430 const struct type
*pcode_get_type(pcode_t q
)
432 const struct type
*t
;
435 t
= type_get_fixed(0, false);
438 t
= type_get_fixed(0, true);
441 t
= type_get_fixed(1, false);
444 t
= type_get_fixed(1, true);
447 t
= type_get_fixed(2, false);
450 t
= type_get_fixed(2, true);
453 t
= type_get_fixed(3, false);
456 t
= type_get_fixed(3, true);
459 t
= type_get_fixed(4, false);
462 t
= type_get_fixed(4, true);
466 t
= type_get_int(INT_DEFAULT_N
);
485 t
= type_get_real(0);
488 t
= type_get_real(1);
491 t
= type_get_real(2);
494 t
= type_get_real(3);
497 t
= type_get_real(4);
501 t
= type_get_flat_option();
504 case T_AlwaysFlatOption
:
505 t
= type_get_flat_option();
509 t
= type_get_unknown();
519 static const struct type
*pcode_to_type(const struct build_function_context
*ctx
, pcode_t q
, ajla_error_t
*mayfail
)
521 const struct type
*t
;
523 ajla_assert_lo(q
< ctx
->n_local_types
, (file_line
, "pcode_to_type(%s): invalid local type: %"PRIdMAX
" >= %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
, (intmax_t)ctx
->n_local_types
));
524 return ctx
->local_types
[q
].type
;
526 t
= pcode_get_type(q
);
528 if (q
== T_SInt64
|| q
== T_UInt64
|| q
== T_SInt128
|| q
== T_UInt128
)
529 return pcode_get_type(T_Integer128
);
530 if (q
== T_Real16
|| q
== T_Real32
|| q
== T_Real64
|| q
== T_Real80
|| q
== T_Real128
)
531 return pcode_get_type(T_Integer128
);
532 if (unlikely(!mayfail
))
533 internal(file_line
, "pcode_to_type(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
534 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_NOT_SUPPORTED
);
539 static pcode_t
type_to_pcode(const struct type
*type
)
541 if (TYPE_TAG_IS_FIXED(type
->tag
))
542 return (pcode_t
)(T_SInt8
- TYPE_TAG_IDX_FIXED(type
->tag
));
543 else if (TYPE_TAG_IS_INT(type
->tag
))
544 return (pcode_t
)(T_Integer8
- TYPE_TAG_IDX_INT(type
->tag
));
545 else if (TYPE_TAG_IS_REAL(type
->tag
))
546 return (pcode_t
)(T_Real16
- TYPE_TAG_IDX_REAL(type
->tag
));
547 else if (type
->tag
== TYPE_TAG_flat_option
)
548 return T_AlwaysFlatOption
;
550 internal(file_line
, "type_to_pcode: invalid type %u", type
->tag
);
554 static pcode_t
pcode_to_type_index(struct build_function_context
*ctx
, pcode_t q
, bool non_flat
)
557 const struct type
*type
= pcode_to_type(ctx
, q
, NULL
);
558 if (!TYPE_IS_FLAT(type
) && non_flat
)
559 return no_type_index
;
562 result
= &ctx
->local_types
[q
].type_index
;
564 unsigned tag
= type
->tag
;
565 ajla_assert_lo(tag
< n_array_elements(ctx
->builtin_type_indices
), (file_line
, "pcode_to_type_index(%s): invalid type tag %u", function_name(ctx
), tag
));
566 result
= &ctx
->builtin_type_indices
[tag
];
568 if (*result
!= no_type_index
)
570 if (unlikely((pcode_t
)ctx
->types_len
< 0)) {
571 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "type array overflow");
572 return error_type_index
;
574 if (unlikely(!array_add_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, type
, NULL
, ctx
->err
)))
575 return error_type_index
;
576 return *result
= (pcode_t
)(ctx
->types_len
- 1);
579 #define pcode_get_var_deref(var, deref) \
581 pcode_t r_ = u_pcode_get(); \
582 ajla_assert_lo(!(r_ & ~(pcode_t)Flag_Free_Argument), (file_line, "pcode_get_ref(%s): invalid reference flag %"PRIdMAX"", function_name(ctx), (intmax_t)r_));\
583 *(deref) = !!(r_ & Flag_Free_Argument); \
584 *(var) = pcode_get(); \
587 #define var_elided(idx) (((idx) < zero) || ctx->pcode_types[idx].type == NULL)
589 static struct pcode_type
*get_var_type(struct build_function_context
*ctx
, pcode_t v
)
591 ajla_assert_lo(!var_elided(v
), (file_line
, "get_var_type(%s): variable %"PRIdMAX
" is elided", function_name(ctx
), (intmax_t)v
));
592 ajla_assert_lo((frame_t
)v
< ctx
->n_local_variables
, (file_line
, "get_var_type(%s): invalid local variable %"PRIdMAX
", limit %"PRIuMAX
"", function_name(ctx
), (intmax_t)v
, (uintmax_t)ctx
->n_local_variables
));
593 return &ctx
->pcode_types
[v
];
596 static bool pcode_load_blob(struct build_function_context
*ctx
, uint8_t **blob
, size_t *l
)
601 if (unlikely(!array_init_mayfail(uint8_t, blob
, l
, ctx
->err
)))
605 q
= 0; /* avoid warning */
607 for (i
= 0; i
< n
; i
++) {
615 if (unlikely(!array_add_mayfail(uint8_t, blob
, l
, (uint8_t)val
, NULL
, ctx
->err
)))
623 static bool pcode_generate_blob(uint8_t *str
, size_t str_len
, pcode_t
**res_blob
, size_t *res_len
, ajla_error_t
*err
)
626 if (unlikely(str_len
> signed_maximum(pcode_t
))) {
627 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), err
, "pcode overflow");
630 if (unlikely(!array_init_mayfail(pcode_t
, res_blob
, res_len
, err
)))
632 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, 0, NULL
, err
)))
634 for (i
= 0; i
< str_len
; i
++) {
636 if (!(**res_blob
% sizeof(pcode_t
))) {
637 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, b
, NULL
, err
)))
640 (*res_blob
)[*res_len
- 1] |= (upcode_t
)((b
) & 0xff) << (**res_blob
% sizeof(pcode_t
) * 8);
647 static pointer_t
*pcode_module_load_function(struct build_function_context
*ctx
)
652 uint8_t *blob
= NULL
;
654 struct module_designator
*md
= NULL
;
655 struct function_designator
*fd
= NULL
;
659 path_idx
= (unsigned)q
;
660 if (unlikely(q
!= (pcode_t
)path_idx
))
661 goto exception_overflow
;
662 program
= path_idx
& 1;
664 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
667 md
= module_designator_alloc(path_idx
, blob
, l
, program
, ctx
->err
);
671 mem_free(blob
), blob
= NULL
;
673 fd
= function_designator_alloc(ctx
->pcode
, ctx
->err
);
676 ctx
->pcode
+= fd
->n_entries
+ 1;
678 ptr
= module_load_function(md
, fd
, true, false, ctx
->err
);
682 module_designator_free(md
), md
= NULL
;
683 function_designator_free(fd
), fd
= NULL
;
688 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "pcode overflow");
693 module_designator_free(md
);
695 function_designator_free(fd
);
699 #define no_function_idx ((size_t)-1)
701 static int ld_tree_compare(const struct tree_entry
*e
, uintptr_t ptr
)
703 struct ld_ref
*ld_ref
= get_struct(e
, struct ld_ref
, entry
);
704 uintptr_t ld_ptr
= ptr_to_num(ld_ref
->ptr
);
712 static size_t pcode_module_load_function_idx(struct build_function_context
*ctx
, pointer_t
*ptr
, bool must_exist
)
714 struct tree_entry
*e
;
715 struct ld_ref
*ld_ref
;
716 struct tree_insert_position ins
;
718 e
= tree_find_for_insert(&ctx
->ld_tree
, ld_tree_compare
, ptr_to_num(ptr
), &ins
);
720 ld_ref
= get_struct(e
, struct ld_ref
, entry
);
724 if (unlikely(must_exist
))
725 internal(file_line
, "pcode_module_load_function_idx: local directory preload didn't work");
727 ld_ref
= mem_alloc_mayfail(struct ld_ref
*, sizeof(struct ld_ref
), ctx
->err
);
728 if (unlikely(!ld_ref
))
729 return no_function_idx
;
731 ld_ref
->idx
= ctx
->ld_len
;
733 tree_insert_after_find(&ld_ref
->entry
, &ins
);
735 if (unlikely(!array_add_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ptr
, NULL
, ctx
->err
)))
736 return no_function_idx
;
737 return ctx
->ld_len
- 1;
740 #define gen_code(n) \
742 if (unlikely(!array_add_mayfail(code_t, &ctx->code, &ctx->code_len, n, NULL, ctx->err)))\
747 #define gen_uint32(n) \
749 gen_code((code_t)((n) & 0xffff)); \
750 gen_code((code_t)((n) >> 15 >> 1)); \
753 #define gen_uint32(n) \
755 gen_code((code_t)((n) >> 15 >> 1)); \
756 gen_code((code_t)((n) & 0xffff)); \
760 #define gen_am(am, m) \
763 gen_code((code_t)(m)); \
764 } else if (am == 2) { \
767 internal(file_line, "gen_am(%s): arg mode %d", function_name(ctx), am);\
771 #define gen_am_two(am, m, n) \
774 gen_code((code_t)((m) + ((n) << 8))); \
775 } else if (am == 1) { \
776 gen_code((code_t)(m)); \
777 gen_code((code_t)(n)); \
778 } else if (am == 2) { \
782 internal(file_line, "gen_am_two(%s): arg mode %d", function_name(ctx), am);\
786 #define gen_relative_jump(lbl, diff) \
789 ajla_assert_lo((lbl) < ctx->n_labels, (file_line, "gen_relative_jump(%s): invalid label %"PRIdMAX"", function_name(ctx), (intmax_t)(lbl)));\
790 target = -(((uint32_t)(diff) + 1) / (uint32_t)sizeof(code_t) * (uint32_t)sizeof(code_t));\
791 if (ctx->labels[lbl] == no_label) { \
792 struct label_ref lr; \
793 lr.code_pos = ctx->code_len; \
795 if (unlikely(!array_add_mayfail(struct label_ref, &ctx->label_ref, &ctx->label_ref_len, lr, NULL, ctx->err)))\
798 target += ((uint32_t)ctx->labels[lbl] - (uint32_t)ctx->code_len) * (uint32_t)sizeof(code_t);\
800 if (SIZEOF_IP_T == 2) \
801 gen_code((code_t)target); \
802 else if (SIZEOF_IP_T == 4) \
803 gen_uint32(target); \
804 else not_reached(); \
807 static bool gen_checkpoint(struct build_function_context
*ctx
, const pcode_t
*params
, pcode_t n_params
, bool check_arguments
)
812 pcode_t n_used_params
;
814 bool *processed_variables
= NULL
;
816 if (unlikely(ctx
->is_eval
))
819 processed_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, bool *, 0, 0, ctx
->n_slots
, sizeof(bool), ctx
->err
);
820 if (unlikely(!processed_variables
))
823 am
= INIT_ARG_MODE_1
;
824 get_arg_mode(am
, n_params
);
827 for (i
= 0; i
< n_params
; i
++) {
828 const struct pcode_type
*tv
;
829 pcode_t var
= params
[i
];
832 tv
= get_var_type(ctx
, var
);
833 get_arg_mode(am
, tv
->slot
);
834 if (!processed_variables
[tv
->slot
]) {
835 processed_variables
[tv
->slot
] = true;
840 if (check_arguments
) {
842 for (ia
= 0; ia
< ctx
->n_real_arguments
; ia
++) {
843 const struct local_arg
*la
= &ctx
->args
[ia
];
844 if (ctx
->local_variables_flags
[la
->slot
].must_be_flat
&& ia
< 4 && 0)
846 if (!la
->may_be_borrowed
)
849 get_arg_mode(am
, la
->slot
);
850 if (!processed_variables
[la
->slot
]) {
851 processed_variables
[la
->slot
] = true;
857 code
= OPCODE_CHECKPOINT
;
858 code
+= am
* OPCODE_MODE_MULT
;
860 gen_am(ARG_MODE_N
- 1, ctx
->checkpoint_num
);
862 gen_am(am
, n_used_params
);
864 for (v
= 0; v
< ctx
->n_slots
; v
++) {
865 if (unlikely(processed_variables
[v
])) {
870 mem_free(processed_variables
);
871 processed_variables
= NULL
;
873 ctx
->checkpoint_num
++;
874 if (unlikely(!ctx
->checkpoint_num
)) {
875 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "checkpoint number overflow");
882 if (processed_variables
)
883 mem_free(processed_variables
);
887 static bool pcode_free(struct build_function_context
*ctx
, pcode_t res
)
890 const struct pcode_type
*tr
;
892 const struct color
*c
;
894 if (unlikely(var_elided(res
)))
896 tr
= get_var_type(ctx
, res
);
898 get_arg_mode(am
, tr
->slot
);
899 c
= &ctx
->colors
[tr
->color
];
900 if (!TYPE_IS_FLAT(tr
->type
) && c
->is_argument
)
901 code
= OPCODE_DEREFERENCE_CLEAR
;
903 code
= OPCODE_DEREFERENCE
;
904 code
+= am
* OPCODE_MODE_MULT
;
906 gen_am(am
, tr
->slot
);
914 static bool pcode_copy(struct build_function_context
*ctx
, bool type_cast
, pcode_t res
, pcode_t a1
, bool a1_deref
)
916 const struct pcode_type
*tr
, *t1
;
920 tr
= get_var_type(ctx
, res
);
921 t1
= get_var_type(ctx
, a1
);
923 if (t1
->slot
== tr
->slot
) {
924 ajla_assert(a1_deref
, (file_line
, "pcode_copy(%s): dereference not set", function_name(ctx
)));
926 * If we copy a value to itself, we must clear may_be_borrowed,
927 * otherwise we get failure in start03.ajla and start04.ajla.
929 * (note that pcode_copy is called from pcode_structured_write)
931 * The reason for the crash is that may_be_borrowed is per-variable,
932 * not per-slot flag - if we copy to a different variable occupying
933 * the same slot, we won't see may_be_borrowed anymore.
936 if (t1
->type
->size
== 0) {
938 get_arg_mode(am
, t1
->slot
);
939 code
= OPCODE_TAKE_BORROWED
;
940 code
+= am
* OPCODE_MODE_MULT
;
942 gen_am(am
, t1
->slot
);
948 if ((t1
->type
->size
== 0 && tr
->type
->size
== 0) || type_cast
) {
949 const struct color
*c
= &ctx
->colors
[t1
->color
];
951 get_arg_mode(am
, t1
->slot
);
952 get_arg_mode(am
, tr
->slot
);
954 code
= a1_deref
? OPCODE_BOX_MOVE_CLEAR
: OPCODE_BOX_COPY
;
956 code
= a1_deref
? (c
->is_argument
? OPCODE_REF_MOVE_CLEAR
: OPCODE_REF_MOVE
) : OPCODE_REF_COPY
;
958 code
+= am
* OPCODE_MODE_MULT
;
960 gen_am_two(am
, t1
->slot
, tr
->slot
);
961 } else if (t1
->type
->tag
== TYPE_TAG_flat_record
|| t1
->type
->tag
== TYPE_TAG_flat_array
) {
962 ajla_assert_lo(tr
->type
== t1
->type
, (file_line
, "pcode_copy(%s): invalid types for flat copy instruction: %u, %u", function_name(ctx
), t1
->type
->tag
, tr
->type
->tag
));
964 get_arg_mode(am
, t1
->slot
);
965 get_arg_mode(am
, tr
->slot
);
966 code
= a1_deref
? OPCODE_FLAT_MOVE
: OPCODE_FLAT_COPY
;
967 code
+= am
* OPCODE_MODE_MULT
;
969 gen_am_two(am
, t1
->slot
, tr
->slot
);
971 ajla_assert_lo(tr
->type
== t1
->type
, (file_line
, "pcode_copy(%s): invalid types for copy instruction: %u, %u", function_name(ctx
), t1
->type
->tag
, tr
->type
->tag
));
973 get_arg_mode(am
, t1
->slot
);
974 get_arg_mode(am
, tr
->slot
);
975 code
= get_code(a1_deref
? Op_Mov
: Op_Copy
, t1
->type
);
976 code
+= am
* OPCODE_MODE_MULT
;
978 gen_am_two(am
, t1
->slot
, tr
->slot
);
986 static bool pcode_process_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
, pcode_t
*n_real_arguments
, arg_mode_t
*am
)
989 if (n_real_arguments
)
990 *n_real_arguments
= 0;
991 for (ai
= 0; ai
< n_arguments
; ai
++) {
993 struct pcode_type
*t1
;
995 pcode_get_var_deref(&a1
, &deref
);
996 if (unlikely(var_elided(a1
)))
998 t1
= get_var_type(ctx
, a1
);
999 if (n_real_arguments
) {
1000 get_arg_mode(*am
, t1
->slot
);
1001 (*n_real_arguments
)++;
1002 t1
->is_dereferenced_in_call_argument
= deref
;
1006 flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
1007 if (!TYPE_IS_FLAT(t1
->type
))
1008 flags
|= OPCODE_CALL_MAY_GIVE
;
1010 if (!t1
->is_dereferenced_in_call_argument
&& !TYPE_IS_FLAT(t1
->type
))
1011 flags
|= OPCODE_CALL_MAY_LEND
;
1013 gen_am_two(*am
, t1
->slot
, flags
);
1016 if (n_real_arguments
)
1017 get_arg_mode(*am
, *n_real_arguments
);
1024 static bool pcode_dereference_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
)
1027 for (ai
= 0; ai
< n_arguments
; ai
++) {
1030 pcode_get_var_deref(&a1
, &deref
);
1032 if (unlikely(!pcode_free(ctx
, a1
)))
1042 static bool pcode_finish_call(struct build_function_context
*ctx
, const struct pcode_type
**rets
, size_t rets_l
, bool test_flat
)
1045 frame_t
*vars
= NULL
;
1049 for (i
= 0; i
< rets_l
; i
++) {
1050 const struct pcode_type
*tv
= rets
[i
];
1051 if (ARG_MODE_N
>= 3) {
1052 gen_uint32(tv
->slot
);
1054 gen_code((code_t
)tv
->slot
);
1056 gen_code(TYPE_IS_FLAT(tv
->type
) ? OPCODE_MAY_RETURN_FLAT
: 0);
1059 if (unlikely(test_flat
)) {
1064 if (unlikely(!gen_checkpoint(ctx
, NULL
, 0, false)))
1067 vars
= mem_alloc_array_mayfail(mem_alloc_mayfail
, frame_t
*, 0, 0, ctx
->n_slots
, sizeof(frame_t
), ctx
->err
);
1068 if (unlikely(!vars
))
1071 am
= INIT_ARG_MODE_1
;
1073 for (slot
= MIN_USEABLE_SLOT
; slot
< ctx
->n_slots
; slot
++) {
1074 if (ctx
->local_variables_flags
[slot
].must_be_flat
|| ctx
->local_variables_flags
[slot
].must_be_data
) {
1075 vars
[n_vars
++] = slot
;
1076 get_arg_mode(am
, slot
);
1081 get_arg_mode(am
, n_vars
);
1082 code
= OPCODE_ESCAPE_NONFLAT
;
1083 code
+= am
* OPCODE_MODE_MULT
;
1086 for (i
= 0; i
< n_vars
; i
++)
1087 gen_am(am
, vars
[i
]);
1101 static bool pcode_call(struct build_function_context
*ctx
, pcode_t instr
)
1104 arg_mode_t am
= INIT_ARG_MODE
;
1107 const struct pcode_type
*tr
= NULL
; /* avoid warning */
1108 const struct pcode_type
*ts
= NULL
; /* avoid warning */
1109 pcode_t call_mode
= 0; /* avoid warning */
1110 pcode_t src_fn
= 0; /* avoid warning */
1111 bool src_deref
= false; /* avoid warning */
1114 pcode_t n_arguments
, n_real_arguments
;
1115 arg_t n_return_values
, n_real_return_values
;
1116 size_t fn_idx
= 0; /* avoid warning */
1117 pcode_position_save_t saved
;
1118 const struct pcode_type
**rets
= NULL
;
1121 if (instr
== P_Load_Fn
|| instr
== P_Curry
) {
1122 res
= u_pcode_get();
1123 if (unlikely(var_elided(res
))) {
1126 tr
= get_var_type(ctx
, res
);
1127 get_arg_mode(am
, tr
->slot
);
1129 n_return_values
= 0; /* avoid warning */
1130 } else if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1131 call_mode
= u_pcode_get();
1133 n_return_values
= (arg_t
)q
;
1134 if (unlikely(q
!= (pcode_t
)n_return_values
))
1135 goto exception_overflow
;
1137 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1141 n_arguments
= (arg_t
)q
;
1142 if (unlikely(q
!= (pcode_t
)n_arguments
))
1143 goto exception_overflow
;
1144 if (instr
== P_Load_Fn
|| instr
== P_Call
) {
1146 if (instr
== P_Load_Fn
)
1147 u_pcode_get(); /* call mode */
1148 ptr
= pcode_module_load_function(ctx
);
1151 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, true);
1152 if (unlikely(fn_idx
== no_function_idx
))
1154 get_arg_mode(am
, fn_idx
);
1155 src_deref
= false; /* avoid warning */
1156 src_fn
= ~sign_bit(pcode_t
); /* avoid warning */
1158 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1159 pcode_get_var_deref(&src_fn
, &src_deref
);
1162 pcode_position_save(ctx
, &saved
);
1164 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1167 n_real_return_values
= 0;
1168 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1169 for (ai
= 0; ai
< n_return_values
; ai
++) {
1171 if (unlikely(var_elided(q
)))
1173 n_real_return_values
++;
1175 if (!n_real_return_values
)
1177 get_arg_mode(am
, n_return_values
);
1179 pcode_position_restore(ctx
, &saved
);
1181 if (unlikely(elide
)) {
1182 /* TODO: remove the function from local directory if we just added it */
1184 if (unlikely(!pcode_free(ctx
, src_fn
)))
1187 pcode_dereference_arguments(ctx
, n_arguments
);
1192 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1193 ts
= get_var_type(ctx
, src_fn
);
1194 ajla_assert_lo(ts
->type
->tag
== TYPE_TAG_unknown
, (file_line
, "pcode_call(%s): expected function type, got %u", function_name(ctx
), ts
->type
->tag
));
1195 get_arg_mode(am
, ts
->slot
);
1196 fn_idx
= no_function_idx
; /* avoid warning */
1199 code
= 0; /* avoid warning */
1202 code
= OPCODE_LOAD_FN
;
1205 code
= OPCODE_CURRY
;
1208 switch (call_mode
) {
1209 case Call_Mode_Unspecified
:
1210 case Call_Mode_Normal
:
1213 case Call_Mode_Strict
:
1214 case Call_Mode_Inline
:
1215 case Call_Mode_Flat
:
1216 code
= OPCODE_CALL_STRICT
;
1218 case Call_Mode_Spark
:
1219 code
= OPCODE_CALL_SPARK
;
1221 case Call_Mode_Lazy
:
1222 code
= OPCODE_CALL_LAZY
;
1224 case Call_Mode_Cache
:
1225 code
= OPCODE_CALL_CACHE
;
1227 case Call_Mode_Save
:
1228 code
= OPCODE_CALL_SAVE
;
1231 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1234 case P_Call_Indirect
:
1235 switch (call_mode
) {
1236 case Call_Mode_Unspecified
:
1237 case Call_Mode_Normal
:
1238 code
= OPCODE_CALL_INDIRECT
;
1240 case Call_Mode_Strict
:
1241 case Call_Mode_Inline
:
1242 case Call_Mode_Flat
:
1243 code
= OPCODE_CALL_INDIRECT_STRICT
;
1245 case Call_Mode_Spark
:
1246 code
= OPCODE_CALL_INDIRECT_SPARK
;
1248 case Call_Mode_Lazy
:
1249 code
= OPCODE_CALL_INDIRECT_LAZY
;
1251 case Call_Mode_Cache
:
1252 code
= OPCODE_CALL_INDIRECT_CACHE
;
1254 case Call_Mode_Save
:
1255 code
= OPCODE_CALL_INDIRECT_SAVE
;
1258 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1262 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1265 code
+= am
* OPCODE_MODE_MULT
;
1267 if (instr
== P_Load_Fn
|| instr
== P_Curry
)
1268 gen_am_two(am
, n_real_arguments
, tr
->slot
);
1270 gen_am_two(am
, n_real_arguments
, n_real_return_values
);
1271 if (instr
== P_Load_Fn
|| instr
== P_Call
)
1274 gen_am_two(am
, ts
->slot
, src_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1276 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1279 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1280 if (unlikely(!array_init_mayfail(const struct pcode_type
*, &rets
, &rets_l
, ctx
->err
)))
1282 for (ai
= 0; ai
< n_return_values
; ai
++) {
1283 const struct pcode_type
*tv
;
1285 if (unlikely(var_elided(q
)))
1287 tv
= get_var_type(ctx
, q
);
1288 if (unlikely(!array_add_mayfail(const struct pcode_type
*, &rets
, &rets_l
, tv
, NULL
, ctx
->err
)))
1291 if (unlikely(!pcode_finish_call(ctx
, rets
, rets_l
, false)))
1300 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1307 ctx
->pcode
= ctx
->pcode_instr_end
;
1311 static bool pcode_op_to_call(struct build_function_context
*ctx
, pcode_t op
, const struct pcode_type
*tr
, const struct pcode_type
*t1
, pcode_t flags1
, const struct pcode_type
*t2
, pcode_t flags2
, bool preload
)
1314 struct module_designator
*md
= NULL
;
1315 struct function_designator
*fd
= NULL
;
1322 switch (t1
->extra_type
? t1
->extra_type
: tr
->extra_type
) {
1323 case T_SInt128
: module
= "private/long"; fn
= 0 * Op_N
; break;
1324 case T_UInt128
: module
= "private/long"; fn
= 1 * Op_N
; break;
1325 case T_Real16
: module
= "private/longreal"; fn
= 0 * Op_N
; break;
1326 case T_Real32
: module
= "private/longreal"; fn
= 1 * Op_N
; break;
1327 case T_Real64
: module
= "private/longreal"; fn
= 2 * Op_N
; break;
1328 case T_Real80
: module
= "private/longreal"; fn
= 3 * Op_N
; break;
1329 case T_Real128
: module
= "private/longreal"; fn
= 4 * Op_N
; break;
1331 internal(file_line
, "pcode_op_to_call: type %d, %d", t1
->extra_type
, tr
->extra_type
);
1335 md
= module_designator_alloc(0, cast_ptr(const uint8_t *, module
), strlen(module
), false, ctx
->err
);
1338 fd
= function_designator_alloc_single(fn
, ctx
->err
);
1341 ptr
= module_load_function(md
, fd
, true, false, ctx
->err
);
1344 module_designator_free(md
), md
= NULL
;
1345 function_designator_free(fd
), fd
= NULL
;
1346 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, !preload
);
1347 if (unlikely(fn_idx
== no_function_idx
))
1354 get_arg_mode(am
, fn_idx
);
1355 get_arg_mode(am
, t1
->slot
);
1357 get_arg_mode(am
, t2
->slot
);
1359 code
= OPCODE_CALL
+ am
* OPCODE_MODE_MULT
;
1361 gen_am_two(am
, t2
? 2 : 1, 1);
1363 gen_am_two(am
, t1
->slot
, flags1
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1365 gen_am_two(am
, t2
->slot
, flags2
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1367 if (unlikely(!pcode_finish_call(ctx
, &tr
, 1, true)))
1374 module_designator_free(md
);
1376 function_designator_free(fd
);
1382 while ((size_t)(pos) >= 8 * *blob_len) \
1383 if (unlikely(!array_add_mayfail(uint8_t, blob, blob_len, 0, NULL, err)))\
1390 (*blob)[(pos) >> 3] |= 1U << ((pos) & 7); \
1393 #define re(n, rtype, ntype, pack, unpack) \
1394 static bool cat(pcode_generate_,rtype)(ntype val, uint8_t **blob, size_t *blob_len, ajla_error_t *err)\
1396 int ex_bits, sig_bits; \
1397 int min_exp, max_exp, e; \
1401 case 0: ex_bits = 5; sig_bits = 11; break; \
1402 case 1: ex_bits = 8; sig_bits = 24; break; \
1403 case 2: ex_bits = 11; sig_bits = 53; break; \
1404 case 3: ex_bits = 15; sig_bits = 64; break; \
1405 case 4: ex_bits = 15; sig_bits = 113; break; \
1406 default: internal(file_line, "invalid real type %d", n);\
1408 min_exp = -(1 << (ex_bits - 1)) - sig_bits + 3; \
1409 max_exp = (1 << (ex_bits - 1)) - sig_bits + 2; \
1410 if (unlikely(cat(isnan_,ntype)(val))) { \
1411 fatal_mayfail(error_ajla(EC_SYNC, AJLA_ERROR_NAN), err, "NaN");\
1414 if (unlikely(val == 0)) { \
1415 if (unlikely(1. / val < 0)) \
1420 if (unlikely(val < 0)) { \
1424 if (unlikely(!cat(isfinite_,ntype)(val))) { \
1429 norm = cat(mathfunc_,ntype)(frexp)(val, &e); \
1431 pos = sig_bits - 1; \
1432 if (e < min_exp) { \
1433 pos -= min_exp - e; \
1436 while (pos >= 0) { \
1446 pos = sig_bits + 1; \
1447 while (e && e != -1) { \
1462 } while (pos & 7); \
1465 for_all_real(re
, for_all_empty
)
1470 bool pcode_generate_blob_from_value(pointer_t ptr
, pcode_t pcode_type
, pcode_t
**res_blob
, size_t *res_len
, ajla_error_t
*err
)
1476 const struct type
*type
;
1478 type
= pcode_to_type(NULL
, pcode_type
, err
);
1479 if (unlikely(!type
))
1482 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &blob_len
, err
)))
1484 #define emit_byte(b) \
1486 if (unlikely(!array_add_mayfail(uint8_t, &blob, &blob_len, b, NULL, err)))\
1490 d
= pointer_get_data(ptr
);
1491 if (likely(da_tag(d
) == DATA_TAG_flat
)) {
1495 switch (type
->tag
) {
1496 #define fx(n, type, utype, sz, bits) \
1497 case TYPE_TAG_integer + n: \
1498 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_signed:\
1499 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_unsigned:\
1500 negative = *cast_ptr(type *, da_flat(d)) < 0;\
1501 value = *cast_ptr(type *, da_flat(d)); \
1504 #define re(n, rtype, ntype, pack, unpack) \
1505 case TYPE_TAG_real + n: { \
1506 if (unlikely(!cat(pcode_generate_,rtype)(unpack(*cast_ptr(rtype *, da_flat(d))), &blob, &blob_len, err)))\
1508 goto process_real; \
1511 for_all_real(re
, for_all_empty
);
1513 internal(file_line
, "pcode_generate_blob_from_value: invalid type tag %u", type
->tag
);
1520 for (i
= 0; i
< size
; i
++) {
1524 sign
= blob_len
&& blob
[blob_len
- 1] & 0x80;
1525 if (unlikely(sign
!= negative
))
1526 emit_byte(negative
? 0xff : 0x00);
1528 while (blob_len
>= 2 && blob
[blob_len
- 1] == (negative
? 0xff : 0x00) && (blob
[blob_len
- 2] & 0x80) == (negative
? 0x80 : 0x00))
1531 if (blob_len
== 1 && !blob
[0])
1534 } else if (unlikely(da_tag(d
) == DATA_TAG_longint
)) {
1536 if (unlikely(!mpint_export_to_blob(&da(d
,longint
)->mp
, &blob
, &blob_len
, err
)))
1538 } else if (likely(da_tag(d
) == DATA_TAG_option
)) {
1540 ajla_assert_lo(pointer_is_empty(da(d
,option
)->pointer
), (file_line
, "pcode_generate_blob_from_value: non-empty option"));
1541 opt
= da(d
,option
)->option
;
1543 emit_byte(opt
& 0xff);
1544 while ((opt
>>= 8));
1546 internal(file_line
, "pcode_generate_blob_from_value: invalid data tag %u", da_tag(d
));
1552 if (unlikely(!pcode_generate_blob(blob
, blob_len
, res_blob
, res_len
, err
))) {
1564 #define test(bit) ((size_t)(bit) < 8 * dl ? (d[(bit) >> 3] >> ((bit) & 7)) & 1 : dl ? d[dl - 1] >> 7 : 0)
1566 #define re(n, rtype, ntype, pack, unpack) \
1567 static inline rtype cat(strto_,rtype)(const unsigned char *d, size_t dl)\
1569 int ex_bits, sig_bits; \
1575 case 0: ex_bits = 5; sig_bits = 11; break; \
1576 case 1: ex_bits = 8; sig_bits = 24; break; \
1577 case 2: ex_bits = 11; sig_bits = 53; break; \
1578 case 3: ex_bits = 15; sig_bits = 64; break; \
1579 case 4: ex_bits = 15; sig_bits = 113; break; \
1580 default: internal(file_line, "invalid real type %d", n);\
1584 for (i = 0; i < ex_bits + 1; i++) { \
1585 b = test(sig_bits + 1 + i); \
1586 ex |= (int)b << i; \
1591 for (i = 0; i < sig_bits; i++) { \
1593 val += cat(mathfunc_,ntype)(ldexp)(1, ex + i); \
1596 if (test(sig_bits)) \
1600 for_all_real(re
, for_all_empty
)
1603 static bool pcode_decode_real(struct build_function_context
*ctx
, const struct type
*type
, const char attr_unused
*blob
, size_t attr_unused blob_l
, code_t attr_unused
**result
, size_t attr_unused
*result_len
)
1605 switch (type
->tag
) {
1606 #define re(n, rtype, ntype, pack, unpack) \
1607 case TYPE_TAG_real + n: { \
1608 rtype val = cat(strto_,rtype)((const unsigned char *)blob, blob_l);\
1609 *result_len = round_up(sizeof(rtype), sizeof(code_t)) / sizeof(code_t);\
1610 if (unlikely(!(*result = mem_alloc_array_mayfail(mem_calloc_mayfail, code_t *, 0, 0, *result_len, sizeof(code_t), ctx->err))))\
1612 memcpy(*result, &val, sizeof(rtype)); \
1615 for_all_real(re
, for_all_empty
);
1617 internal(file_line
, "pcode_decode_real(%s): invalid type tag %u", function_name(ctx
), type
->tag
);
1627 static bool pcode_generate_constant_from_blob(struct build_function_context
*ctx
, pcode_t res
, uint8_t *blob
, size_t l
)
1629 const struct pcode_type
*pt
;
1630 bool is_emulated_fixed_8
, is_emulated_fixed_16
;
1631 const struct type
*type
;
1633 code_t
*raw_result
= NULL
;
1635 size_t requested_size
;
1642 pt
= get_var_type(ctx
, res
);
1644 is_emulated_fixed_8
= pt
->extra_type
== T_SInt64
|| pt
->extra_type
== T_UInt64
;
1645 is_emulated_fixed_16
= pt
->extra_type
== T_SInt128
|| pt
->extra_type
== T_UInt128
;
1649 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1650 if (TYPE_TAG_FIXED_IS_UNSIGNED(type
->tag
) && l
== (size_t)type
->size
+ 1 && blob
[l
- 1] == 0x00)
1652 ajla_assert_lo(l
<= type
->size
, (file_line
, "pcode_generate_constant_from_blob(%s): too long constant for type %u", function_name(ctx
), type
->tag
));
1653 if (l
<= sizeof(code_t
))
1654 requested_size
= sizeof(code_t
);
1656 requested_size
= round_up(type
->size
, sizeof(code_t
));
1657 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1658 if (is_emulated_fixed_8
&& l
&& blob
[l
- 1] & 0x80)
1660 else if (is_emulated_fixed_16
&& l
&& blob
[l
- 1] & 0x80)
1661 requested_size
= 16;
1662 else if (l
<= sizeof(code_t
))
1663 requested_size
= sizeof(code_t
);
1664 else if (l
<= type
->size
)
1665 requested_size
= round_up(type
->size
, sizeof(code_t
));
1667 requested_size
= round_up(l
, sizeof(code_t
));
1668 } else if (TYPE_TAG_IS_REAL(type
->tag
)) {
1669 if (!unlikely(pcode_decode_real(ctx
, type
, cast_ptr(const char *, blob
), l
, &raw_result
, &requested_size
)))
1672 internal(file_line
, "pcode_generate_constant_from_blob(%s): unknown type %u", function_name(ctx
), type
->tag
);
1675 if (likely(!raw_result
)) {
1676 while (l
< requested_size
) {
1677 uint8_t c
= !l
? 0 : !(blob
[l
- 1] & 0x80) ? 0 : 0xff;
1678 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, c
, NULL
, ctx
->err
)))
1683 code
= get_code(Op_Ldc
, type
);
1684 const_swap
= !!CODE_ENDIAN
;
1686 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1687 if (requested_size
< type
->size
)
1688 code
+= (OPCODE_FIXED_OP_ldc16
- OPCODE_FIXED_OP_ldc
) * OPCODE_FIXED_OP_MULT
;
1689 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1690 if ((is_emulated_fixed_8
|| is_emulated_fixed_16
) && l
&& blob
[l
- 1] & 0x80) {
1691 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, 0, NULL
, ctx
->err
)))
1693 code
= OPCODE_INT_LDC_LONG
;
1694 } else if (requested_size
< type
->size
) {
1695 code
+= (OPCODE_INT_OP_ldc16
- OPCODE_INT_OP_ldc
) * OPCODE_INT_OP_MULT
;
1696 } else if (requested_size
> type
->size
&& orig_l
> type
->size
) {
1697 code
= OPCODE_INT_LDC_LONG
;
1702 get_arg_mode(am
, pt
->slot
);
1704 gen_code(code
+ am
* OPCODE_MODE_MULT
);
1705 gen_am(am
, pt
->slot
);
1706 if (unlikely(code
== OPCODE_INT_LDC_LONG
)) {
1707 gen_uint32(l
/ sizeof(code_t
));
1708 /*debug("load long constant: %zu (%d)", l, type->tag);*/
1710 if (unlikely(raw_result
!= NULL
)) {
1712 for (idx
= 0; idx
< requested_size
; idx
++)
1713 gen_code(raw_result
[idx
]);
1714 } else for (is
= 0; is
< l
; is
+= sizeof(code_t
)) {
1715 size_t idx
= !const_swap
? is
: l
- sizeof(code_t
) - is
;
1716 gen_code(blob
[idx
] + (blob
[idx
+ 1] << 8));
1719 mem_free(blob
), blob
= NULL
;
1720 if (unlikely(raw_result
!= NULL
))
1721 mem_free(raw_result
);
1729 mem_free(raw_result
);
1733 static bool pcode_generate_constant(struct build_function_context
*ctx
, pcode_t res
, int_default_t val
)
1737 uint_default_t uval
= (uint_default_t
)val
;
1739 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &l
, ctx
->err
)))
1743 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, (uint8_t)uval
, NULL
, ctx
->err
)))
1748 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1751 static bool pcode_generate_option_from_blob(struct build_function_context
*ctx
, const struct pcode_type
*tr
, uint8_t *blob
, size_t l
)
1759 for (i
= 0; i
< l
; i
++) {
1760 ajla_option_t o
= (ajla_option_t
)blob
[i
];
1761 opt
|= o
<< (i
* 8);
1762 if (unlikely(opt
>> (i
* 8) != o
))
1763 goto exception_overflow
;
1767 get_arg_mode(am
, tr
->slot
);
1768 if (likely(opt
== (ajla_option_t
)(ajla_flat_option_t
)opt
) && tr
->type
->tag
== TYPE_TAG_flat_option
) {
1769 code
= OPCODE_OPTION_CREATE_EMPTY_FLAT
;
1771 code
= OPCODE_OPTION_CREATE_EMPTY
;
1773 code
+= am
* OPCODE_MODE_MULT
;
1775 gen_am_two(am
, tr
->slot
, opt
);
1781 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1787 static bool pcode_load_constant(struct build_function_context
*ctx
)
1792 const struct pcode_type
*tr
;
1794 res
= u_pcode_get();
1795 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
1798 if (var_elided(res
)) {
1803 tr
= get_var_type(ctx
, res
);
1805 if (tr
->type
->tag
== TYPE_TAG_flat_option
|| tr
->type
->tag
== TYPE_TAG_unknown
) {
1806 return pcode_generate_option_from_blob(ctx
, tr
, blob
, l
);
1808 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1812 static bool pcode_structured_loop(struct build_function_context
*ctx
, pcode_t n_steps
, code_t extra_flags
, arg_mode_t
*am
, bool gen
)
1817 if (i
== n_steps
- 1)
1818 extra_flags
|= OPCODE_STRUCTURED_FLAG_END
;
1822 case Structured_Record
: {
1824 pcode_t rec_local
, q
, type_idx
;
1825 const struct record_definition
*def
;
1828 rec_local
= u_pcode_get();
1832 if (unlikely(q
!= (pcode_t
)idx
))
1833 goto exception_overflow
;
1835 def
= type_def(pcode_to_type(ctx
, rec_local
, NULL
),record
);
1837 if (record_definition_is_elided(def
, idx
)) {
1838 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided record entry in the second pass", function_name(ctx
)));
1842 type_idx
= pcode_to_type_index(ctx
, rec_local
, false);
1843 if (unlikely(type_idx
== error_type_index
))
1846 slot
= record_definition_slot(def
, idx
);
1848 get_arg_mode(*am
, slot
);
1849 get_arg_mode(*am
, type_idx
);
1851 gen_am_two(*am
, OPCODE_STRUCTURED_RECORD
| extra_flags
, slot
);
1852 gen_am(*am
, type_idx
);
1856 case Structured_Option
: {
1861 opt
= (ajla_option_t
)q
;
1862 if (unlikely(q
!= (pcode_t
)opt
))
1863 goto exception_overflow
;
1866 get_arg_mode(*am
, opt
);
1868 gen_am_two(*am
, OPCODE_STRUCTURED_OPTION
| extra_flags
, opt
);
1873 case Structured_Array
: {
1874 pcode_t var
, local_type
, local_idx
;
1875 const struct pcode_type
*var_type
;
1877 var
= u_pcode_get();
1879 local_type
= pcode_get();
1881 if (var_elided(var
)) {
1882 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided array index in the second pass", function_name(ctx
)));
1886 var_type
= get_var_type(ctx
, var
);
1887 ajla_assert_lo(type_is_equal(var_type
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "pcode_structured_loop(%s): invalid index type %u", function_name(ctx
), var_type
->type
->tag
));
1889 local_idx
= pcode_to_type_index(ctx
, local_type
, false);
1890 if (unlikely(local_idx
== error_type_index
))
1894 get_arg_mode(*am
, var_type
->slot
);
1895 get_arg_mode(*am
, local_idx
);
1897 gen_am_two(*am
, OPCODE_STRUCTURED_ARRAY
| extra_flags
, var_type
->slot
);
1898 gen_am(*am
, local_idx
);
1903 internal(file_line
, "pcode_structured_loop(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (uintmax_t)type
);
1905 } while (++i
< n_steps
);
1910 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1915 static bool pcode_structured_write(struct build_function_context
*ctx
)
1917 pcode_t structured
, scalar
, n_steps
;
1919 pcode_t structured_source
= 0; /* avoid warning */
1920 bool structured_source_deref
= false; /* avoid warning */
1921 const struct pcode_type
*structured_type
, *scalar_type
;
1922 code_t extra_flags
= 0;
1923 arg_mode_t am
= INIT_ARG_MODE
;
1925 pcode_position_save_t saved
;
1927 n_steps
= u_pcode_get();
1928 ajla_assert_lo(n_steps
!= 0, (file_line
, "pcode_structured_write(%s): zero n_steps", function_name(ctx
)));
1929 structured
= u_pcode_get();
1930 pcode_get_var_deref(&structured_source
, &structured_source_deref
);
1931 pcode_get_var_deref(&scalar
, &scalar_deref
);
1933 extra_flags
|= OPCODE_STRUCTURED_FREE_VARIABLE
;
1935 pcode_position_save(ctx
, &saved
);
1937 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, false))
1940 if (unlikely(var_elided(structured
)) || unlikely(var_elided(scalar
)))
1943 pcode_position_restore(ctx
, &saved
);
1945 if (!pcode_copy(ctx
, false, structured
, structured_source
, structured_source_deref
))
1948 structured_type
= get_var_type(ctx
, structured
);
1949 scalar_type
= get_var_type(ctx
, scalar
);
1950 get_arg_mode(am
, structured_type
->slot
);
1951 get_arg_mode(am
, scalar_type
->slot
);
1953 gen_code(OPCODE_STRUCTURED
+ am
* OPCODE_MODE_MULT
);
1954 gen_am_two(am
, structured_type
->slot
, scalar_type
->slot
);
1956 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, true))
1965 static bool pcode_record_create(struct build_function_context
*ctx
)
1968 pcode_position_save_t saved
;
1969 pcode_t n_arguments
, n_real_arguments
;
1970 const struct pcode_type
*tr
;
1971 arg_mode_t am
= INIT_ARG_MODE
;
1973 result
= u_pcode_get();
1975 n_arguments
= (arg_t
)q
;
1976 if (unlikely(q
!= (pcode_t
)n_arguments
))
1977 goto exception_overflow
;
1979 pcode_position_save(ctx
, &saved
);
1981 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1984 pcode_position_restore(ctx
, &saved
);
1986 if (unlikely(var_elided(result
))) {
1987 pcode_dereference_arguments(ctx
, n_arguments
);
1991 tr
= get_var_type(ctx
, result
);
1992 get_arg_mode(am
, tr
->slot
);
1994 gen_code(OPCODE_RECORD_CREATE
+ am
* OPCODE_MODE_MULT
);
1995 gen_am_two(am
, tr
->slot
, n_real_arguments
);
1997 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
2003 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
2008 static bool pcode_array_create(struct build_function_context
*ctx
)
2010 pcode_t result
, local_type
, length
, n_real_arguments
;
2011 pcode_position_save_t saved
;
2012 const struct pcode_type
*tr
;
2013 arg_mode_t am
= INIT_ARG_MODE
;
2015 result
= u_pcode_get();
2016 local_type
= pcode_get();
2017 length
= u_pcode_get();
2020 pcode_position_save(ctx
, &saved
);
2022 if (unlikely(!pcode_process_arguments(ctx
, length
, &n_real_arguments
, &am
)))
2025 pcode_position_restore(ctx
, &saved
);
2027 if (unlikely(var_elided(result
))) {
2028 pcode_dereference_arguments(ctx
, length
);
2032 ajla_assert_lo(length
== n_real_arguments
, (file_line
, "pcode_array_create(%s): some elements are elided: %"PRIdMAX
" != %"PRIdMAX
"", function_name(ctx
), (intmax_t)length
, (intmax_t)n_real_arguments
));
2034 tr
= get_var_type(ctx
, result
);
2035 get_arg_mode(am
, tr
->slot
);
2038 pcode_t type_idx
= pcode_to_type_index(ctx
, local_type
, true);
2039 if (unlikely(type_idx
== error_type_index
))
2041 if (type_idx
== no_type_index
) {
2042 gen_code(OPCODE_ARRAY_CREATE_EMPTY
+ am
* OPCODE_MODE_MULT
);
2043 gen_am(am
, tr
->slot
);
2045 get_arg_mode(am
, type_idx
);
2046 gen_code(OPCODE_ARRAY_CREATE_EMPTY_FLAT
+ am
* OPCODE_MODE_MULT
);
2047 gen_am_two(am
, tr
->slot
, type_idx
);
2050 get_arg_mode(am
, length
);
2051 gen_code(OPCODE_ARRAY_CREATE
+ am
* OPCODE_MODE_MULT
);
2052 gen_am_two(am
, tr
->slot
, length
);
2053 if (unlikely(!pcode_process_arguments(ctx
, length
, NULL
, &am
)))
2063 static bool pcode_array_string(struct build_function_context
*ctx
)
2068 const struct pcode_type
*tr
;
2069 arg_mode_t am
= INIT_ARG_MODE
;
2071 result
= u_pcode_get();
2073 if (!pcode_load_blob(ctx
, &blob
, &blob_len
))
2075 if (likely(var_elided(result
))) {
2080 tr
= get_var_type(ctx
, result
);
2081 get_arg_mode(am
, tr
->slot
);
2082 get_arg_mode(am
, blob_len
);
2083 gen_code(OPCODE_ARRAY_STRING
+ am
* OPCODE_MODE_MULT
);
2084 gen_am_two(am
, tr
->slot
, blob_len
);
2085 for (i
= 0; i
< blob_len
; i
+= 2) {
2091 u
.b
[1] = i
+ 1 < blob_len
? blob
[i
+ 1] : 0;
2103 static bool pcode_array_unicode(struct build_function_context
*ctx
)
2107 const struct pcode_type
*tr
;
2108 arg_mode_t am
= INIT_ARG_MODE
;
2110 result
= u_pcode_get();
2112 len
= ctx
->pcode_instr_end
- ctx
->pcode
;
2114 tr
= get_var_type(ctx
, result
);
2115 get_arg_mode(am
, tr
->slot
);
2116 get_arg_mode(am
, len
);
2117 gen_code(OPCODE_ARRAY_UNICODE
+ am
* OPCODE_MODE_MULT
);
2118 gen_am_two(am
, tr
->slot
, len
);
2119 for (i
= 0; i
< len
; i
++) {
2135 static bool pcode_io(struct build_function_context
*ctx
)
2137 pcode_t io_type
, n_outputs
, n_inputs
, n_params
;
2139 bool elided
= false;
2140 code_position_save_t saved
;
2142 code_position_save(ctx
, &saved
);
2144 io_type
= u_pcode_get();
2145 n_outputs
= u_pcode_get();
2146 n_inputs
= u_pcode_get();
2147 n_params
= u_pcode_get();
2149 ajla_assert_lo(!((io_type
| n_outputs
| n_inputs
| n_params
) & ~0xff), (file_line
, "pcode_io(%s): data out of range %"PRIdMAX
" %"PRIdMAX
" %"PRIdMAX
" %"PRIdMAX
"", function_name(ctx
), (intmax_t)io_type
, (intmax_t)n_outputs
, (intmax_t)n_inputs
, (intmax_t)n_params
));
2151 gen_code(OPCODE_IO
);
2152 gen_code(io_type
| (n_outputs
<< 8));
2153 gen_code(n_inputs
| (n_params
<< 8));
2155 for (pass
= 0; pass
< 3; pass
++) {
2157 if (!pass
) val
= n_outputs
;
2158 else if (pass
== 1) val
= n_inputs
;
2159 else val
= n_params
;
2162 pcode_t var
= pcode_get();
2163 if (!pass
&& var_elided(var
))
2167 const struct pcode_type
*t1
;
2168 t1
= get_var_type(ctx
, var
);
2169 gen_uint32(t1
->slot
);
2178 code_position_restore(ctx
, &saved
);
2187 static bool pcode_args(struct build_function_context
*ctx
)
2189 const struct pcode_type
*tr
;
2192 ajla_assert_lo(!ctx
->args
, (file_line
, "pcode_args(%s): args already specified", function_name(ctx
)));
2194 ctx
->args
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct local_arg
*, 0, 0, ctx
->n_arguments
, sizeof(struct local_arg
), ctx
->err
);
2195 if (unlikely(!ctx
->args
))
2198 for (i
= 0, vv
= 0; i
< ctx
->n_arguments
; i
++) {
2199 pcode_t res
= pcode_get();
2200 if (unlikely(var_elided(res
)))
2202 tr
= get_var_type(ctx
, res
);
2203 ctx
->args
[vv
].slot
= tr
->slot
;
2204 ctx
->args
[vv
].may_be_borrowed
= !TYPE_IS_FLAT(tr
->type
);
2205 ctx
->args
[vv
].may_be_flat
= TYPE_IS_FLAT(tr
->type
);
2206 ctx
->pcode_types
[res
].argument
= &ctx
->args
[vv
];
2207 ctx
->colors
[tr
->color
].is_argument
= true;
2208 if (!TYPE_IS_FLAT(tr
->type
))
2209 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2212 ctx
->n_real_arguments
= vv
;
2218 struct pcode_return_struct
{
2223 static bool pcode_return(struct build_function_context
*ctx
)
2225 arg_mode_t am
= INIT_ARG_MODE
;
2227 struct pcode_return_struct
*prs
;
2229 prs
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct pcode_return_struct
*, 0, 0, ctx
->n_return_values
, sizeof(struct pcode_return_struct
), ctx
->err
);
2233 for (i
= 0, vv
= 0; i
< ctx
->n_return_values
; i
++) {
2234 const struct pcode_type
*tr
;
2235 pcode_t flags
= u_pcode_get();
2236 pcode_t res
= pcode_get();
2237 prs
[i
].flags
= flags
;
2239 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2241 tr
= get_var_type(ctx
, res
);
2242 get_arg_mode(am
, tr
->slot
);
2246 ajla_assert_lo(ctx
->n_real_return_values
== vv
, (file_line
, "pcode_return(%s): return arguments mismatch: %u != %u", function_name(ctx
), (unsigned)ctx
->n_real_return_values
, (unsigned)vv
));
2248 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2249 if (unlikely((prs
[i
].flags
& (Flag_Free_Argument
| Flag_Return_Elided
)) == (Flag_Free_Argument
| Flag_Return_Elided
))) {
2251 arg_t q
= (arg_t
)-1;
2252 for (j
= 0; j
< i
; j
++)
2253 if (prs
[j
].res
== prs
[i
].res
&& !(prs
[j
].flags
& Flag_Return_Elided
))
2255 if (q
!= (arg_t
)-1) {
2256 prs
[q
].flags
|= Flag_Free_Argument
;
2258 if (!pcode_free(ctx
, prs
[i
].res
))
2261 prs
[i
].flags
&= ~Flag_Free_Argument
;
2265 gen_code(OPCODE_RETURN
+ am
* OPCODE_MODE_MULT
);
2267 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2268 unsigned code_flags
;
2269 const struct pcode_type
*tr
;
2270 pcode_t flags
= prs
[i
].flags
;
2271 pcode_t res
= prs
[i
].res
;
2272 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2274 tr
= get_var_type(ctx
, res
);
2276 if (flags
& Flag_Free_Argument
)
2277 code_flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
2278 gen_am_two(am
, tr
->slot
, code_flags
);
2290 static void pcode_get_instr(struct build_function_context
*ctx
, pcode_t
*instr
, pcode_t
*instr_params
)
2292 *instr
= u_pcode_get();
2293 *instr_params
= u_pcode_get();
2294 ajla_assert(ctx
->pcode_limit
- ctx
->pcode
>= *instr_params
, (file_line
, "pcode_get_instr(%s): instruction %"PRIdMAX
" crosses pcode boundary: %"PRIdMAX
" > %"PRIdMAX
"", function_name(ctx
), (intmax_t)*instr
, (intmax_t)*instr_params
, (intmax_t)(ctx
->pcode_limit
- ctx
->pcode
)));
2295 ctx
->pcode_instr_end
= ctx
->pcode
+ *instr_params
;
2299 static bool pcode_preload_ld(struct build_function_context
*ctx
)
2301 pcode_position_save_t saved
;
2303 pcode_position_save(ctx
, &saved
);
2304 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2305 pcode_t instr
, instr_params
;
2306 pcode_get_instr(ctx
, &instr
, &instr_params
);
2309 if (unlikely(!pcode_args(ctx
)))
2312 #if NEED_OP_EMULATION
2315 const struct pcode_type
*tr
, *t1
;
2316 pcode_t op
= u_pcode_get();
2317 pcode_t res
= u_pcode_get();
2318 pcode_t flags1
= u_pcode_get();
2319 pcode_t a1
= pcode_get();
2320 if (unlikely(var_elided(res
)))
2322 tr
= get_var_type(ctx
, res
);
2323 t1
= get_var_type(ctx
, a1
);
2324 if (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
)) {
2325 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, true)))
2336 ptr
= pcode_module_load_function(ctx
);
2339 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, false);
2340 if (unlikely(fn_idx
== no_function_idx
))
2345 ctx
->pcode
= ctx
->pcode_instr_end
;
2347 pcode_position_restore(ctx
, &saved
);
2355 static bool pcode_check_args(struct build_function_context
*ctx
)
2358 frame_t
*vars
= NULL
;
2362 vars
= mem_alloc_array_mayfail(mem_alloc_mayfail
, frame_t
*, 0, 0, ctx
->n_real_arguments
, sizeof(frame_t
), ctx
->err
);
2363 if (unlikely(!vars
))
2367 am
= INIT_ARG_MODE_1
;
2369 for (i
= 0; i
< ctx
->n_real_arguments
; i
++) {
2370 frame_t slot
= ctx
->args
[i
].slot
;
2371 if (ctx
->local_variables_flags
[slot
].must_be_flat
|| ctx
->local_variables_flags
[slot
].must_be_data
) {
2372 vars
[n_vars
++] = slot
;
2373 get_arg_mode(am
, slot
);
2379 get_arg_mode(am
, n_vars
);
2380 code
= OPCODE_ESCAPE_NONFLAT
;
2381 code
+= am
* OPCODE_MODE_MULT
;
2384 for (i
= 0; i
< n_vars
; i
++)
2385 gen_am(am
, vars
[i
]);
2399 static bool pcode_generate_instructions(struct build_function_context
*ctx
)
2401 if (unlikely(!gen_checkpoint(ctx
, NULL
, 0, false)))
2404 if (unlikely(!pcode_check_args(ctx
)))
2407 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2408 pcode_t instr
, instr_params
;
2409 pcode_get_instr(ctx
, &instr
, &instr_params
);
2411 pcode_t p
, op
, res
, a1
, a2
, aa
, flags
, flags1
, flags2
, cnst
;
2412 const struct pcode_type
*tr
, *t1
, *t2
, *ta
;
2413 bool a1_deref
, a2_deref
;
2417 struct line_position lp
;
2418 struct record_definition
*def
;
2422 ajla_assert_lo(op
>= Op_N
|| Op_IsBinary(op
), (file_line
, "P_BinaryOp(%s): invalid binary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2423 res
= u_pcode_get();
2424 flags1
= u_pcode_get();
2426 flags2
= u_pcode_get();
2428 if (unlikely(var_elided(res
))) {
2429 if (flags1
& Flag_Free_Argument
)
2430 pcode_free(ctx
, a1
);
2431 if (flags2
& Flag_Free_Argument
)
2432 pcode_free(ctx
, a2
);
2435 tr
= get_var_type(ctx
, res
);
2436 t1
= get_var_type(ctx
, a1
);
2437 t2
= get_var_type(ctx
, a2
);
2438 ajla_assert_lo(op
>= Op_N
||
2439 (type_is_equal(t1
->type
, t2
->type
) &&
2440 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2441 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2442 : t1
->type
))), (file_line
, "P_BinaryOp(%s): invalid types for binary operation %"PRIdMAX
": %u, %u, %u", function_name(ctx
), (intmax_t)op
, t1
->type
->tag
, t2
->type
->tag
, tr
->type
->tag
));
2443 if (NEED_OP_EMULATION
&& unlikely(t1
->extra_type
)) {
2444 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, t2
, flags2
, false)))
2449 if (unlikely(flags1
& Flag_Op_Strict
) != 0)
2450 fflags
|= OPCODE_OP_FLAG_STRICT
;
2451 if (flags1
& Flag_Fused_Bin_Jmp
)
2452 fflags
|= OPCODE_FLAG_FUSED
;
2454 get_arg_mode(am
, t1
->slot
);
2455 get_arg_mode(am
, t2
->slot
);
2456 get_arg_mode(am
, tr
->slot
);
2457 code
= (code_t
)((likely(op
< Op_N
) ? get_code(op
, t1
->type
) : (code_t
)(op
- Op_N
)) + am
* OPCODE_MODE_MULT
);
2459 gen_am_two(am
, t1
->slot
, t2
->slot
);
2460 gen_am_two(am
, tr
->slot
, fflags
);
2461 if (flags1
& Flag_Free_Argument
) {
2462 if (t1
->slot
!= tr
->slot
)
2463 pcode_free(ctx
, a1
);
2465 if (flags2
& Flag_Free_Argument
) {
2466 if (t2
->slot
!= tr
->slot
)
2467 pcode_free(ctx
, a2
);
2470 case P_BinaryConstOp
:
2472 ajla_assert_lo(Op_IsBinary(op
), (file_line
, "P_BinaryConstOp(%s): invalid binary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2473 res
= u_pcode_get();
2474 flags1
= u_pcode_get();
2477 if (unlikely(var_elided(res
))) {
2478 if (flags1
& Flag_Free_Argument
)
2479 pcode_free(ctx
, a1
);
2482 tr
= get_var_type(ctx
, res
);
2483 t1
= get_var_type(ctx
, a1
);
2484 ajla_assert_lo(type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option() : t1
->type
)), (file_line
, "P_BinaryConstOp(%s): invalid types for binary operation %"PRIdMAX
": %u, %u", function_name(ctx
), (intmax_t)op
, t1
->type
->tag
, tr
->type
->tag
));
2486 if (flags1
& Flag_Fused_Bin_Jmp
)
2487 fflags
|= OPCODE_FLAG_FUSED
;
2489 get_arg_mode(am
, t1
->slot
);
2490 get_arg_mode(am
, (frame_t
)cnst
);
2491 get_arg_mode(am
, tr
->slot
);
2492 code
= get_code(op
, t1
->type
) + (TYPE_TAG_IS_FIXED(t1
->type
->tag
) ? OPCODE_FIXED_OP_C
: OPCODE_INT_OP_C
) + am
* OPCODE_MODE_MULT
;
2494 gen_am_two(am
, t1
->slot
, (frame_t
)cnst
);
2495 gen_am_two(am
, tr
->slot
, fflags
);
2496 if (flags1
& Flag_Free_Argument
) {
2497 if (t1
->slot
!= tr
->slot
)
2498 pcode_free(ctx
, a1
);
2503 ajla_assert_lo(op
>= Op_N
|| Op_IsUnary(op
), (file_line
, "P_UnaryOp(%s): invalid unary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2504 res
= u_pcode_get();
2505 flags1
= u_pcode_get();
2507 if (unlikely(var_elided(res
))) {
2508 if (flags1
& Flag_Free_Argument
)
2509 pcode_free(ctx
, a1
);
2512 tr
= get_var_type(ctx
, res
);
2513 t1
= get_var_type(ctx
, a1
);
2514 ajla_assert_lo(op
>= Op_N
|| op
== Un_ConvertFromInt
||
2515 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2516 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2517 : t1
->type
)), (file_line
, "P_UnaryOp(%s): invalid types for unary operation %"PRIdMAX
": %u, %u", function_name(ctx
), (intmax_t)op
, t1
->type
->tag
, tr
->type
->tag
));
2518 if (NEED_OP_EMULATION
&& (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
))) {
2519 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, false)))
2524 get_arg_mode(am
, t1
->slot
);
2525 get_arg_mode(am
, tr
->slot
);
2526 code
= (code_t
)((likely(op
< Op_N
) ? get_code(op
, op
!= Un_ConvertFromInt
? t1
->type
: tr
->type
) : (code_t
)(op
- Op_N
)) + am
* OPCODE_MODE_MULT
);
2528 gen_am_two(am
, t1
->slot
, tr
->slot
);
2529 gen_am(am
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2530 if (flags1
& Flag_Free_Argument
) {
2531 if (t1
->slot
!= tr
->slot
)
2532 pcode_free(ctx
, a1
);
2536 case P_Copy_Type_Cast
:
2537 res
= u_pcode_get();
2538 pcode_get_var_deref(&a1
, &a1_deref
);
2539 if (unlikely(var_elided(res
))) {
2541 if (unlikely(!pcode_free(ctx
, a1
)))
2546 if (unlikely(!pcode_copy(ctx
, instr
!= P_Copy
, res
, a1
, a1_deref
)))
2550 res
= u_pcode_get();
2551 if (unlikely(!pcode_free(ctx
, res
)))
2556 if (unlikely(var_elided(a1
)))
2558 t1
= get_var_type(ctx
, a1
);
2560 get_arg_mode(am
, t1
->slot
);
2562 code
+= am
* OPCODE_MODE_MULT
;
2564 gen_am(am
, t1
->slot
);
2570 res
= u_pcode_get();
2571 ajla_assert_lo(var_elided(res
), (file_line
, "P_Fn(%s): Fn result is not elided", function_name(ctx
)));
2574 for (p
= 0; p
< a1
; p
++)
2576 for (p
= 0; p
< a2
; p
++)
2579 case P_Load_Local_Type
:
2580 res
= u_pcode_get();
2581 ajla_assert_lo(var_elided(res
), (file_line
, "P_Load_Local_Type(%s): Load_Local_Type result is not elided", function_name(ctx
)));
2587 case P_Call_Indirect
:
2589 if (unlikely(!pcode_call(ctx
, instr
)))
2592 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
2593 pcode_t next
, next_params
;
2594 pcode_position_save_t s
;
2595 pcode_position_save(ctx
, &s
);
2597 pcode_get_instr(ctx
, &next
, &next_params
);
2598 if (next
== P_Line_Info
) {
2599 ctx
->pcode
= ctx
->pcode_instr_end
;
2602 pcode_position_restore(ctx
, &s
);
2603 //ajla_assert_lo(next == P_Checkpoint, (file_line, "%s: is followed by %"PRIdMAX"", instr == P_Call ? "P_Call" : "P_Call_Indirect", (intmax_t)next));
2605 ctx
->pcode_instr_end
= ctx
->pcode
;
2610 if (unlikely(!pcode_load_constant(ctx
)))
2613 case P_Structured_Write
:
2614 if (unlikely(!pcode_structured_write(ctx
)))
2619 for (p
= 0; p
< instr_params
; p
++)
2622 case P_Record_Create
:
2623 if (unlikely(!pcode_record_create(ctx
)))
2626 case P_Record_Load_Slot
:
2627 res
= u_pcode_get();
2630 tr
= get_var_type(ctx
, res
);
2631 t1
= get_var_type(ctx
, a1
);
2633 get_arg_mode(am
, tr
->slot
);
2634 get_arg_mode(am
, t1
->slot
);
2635 get_arg_mode(am
, op
);
2636 code
= OPCODE_RECORD_LOAD
;
2637 code
+= am
* OPCODE_MODE_MULT
;
2639 gen_am_two(am
, t1
->slot
, op
);
2640 gen_am_two(am
, tr
->slot
, OPCODE_OP_FLAG_STRICT
);
2643 res
= u_pcode_get();
2644 flags
= u_pcode_get();
2647 if (unlikely(var_elided(res
)))
2649 tr
= get_var_type(ctx
, res
);
2650 t1
= get_var_type(ctx
, a1
);
2651 if (TYPE_IS_FLAT(tr
->type
))
2652 flags
&= ~Flag_Borrow
;
2653 if (t1
->type
->tag
== TYPE_TAG_flat_record
) {
2654 def
= type_def(type_def(t1
->type
,flat_record
)->base
,record
);
2656 def
= type_def(t1
->type
,record
);
2658 ajla_assert_lo(!record_definition_is_elided(def
, op
), (file_line
, "P_RecordLoad(%s): record entry %"PRIuMAX
" is elided", function_name(ctx
), (uintmax_t)op
));
2659 op
= record_definition_slot(def
, op
);
2661 get_arg_mode(am
, tr
->slot
);
2662 get_arg_mode(am
, t1
->slot
);
2663 get_arg_mode(am
, op
);
2664 code
= OPCODE_RECORD_LOAD
;
2665 code
+= am
* OPCODE_MODE_MULT
;
2667 gen_am_two(am
, t1
->slot
, op
);
2668 gen_am_two(am
, tr
->slot
,
2669 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2670 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2671 if (flags
& Flag_Borrow
)
2672 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2675 res
= u_pcode_get();
2676 flags
= u_pcode_get();
2679 if (unlikely(var_elided(res
)))
2681 tr
= get_var_type(ctx
, res
);
2682 t1
= get_var_type(ctx
, a1
);
2683 if (TYPE_IS_FLAT(tr
->type
))
2684 flags
&= ~Flag_Borrow
;
2686 get_arg_mode(am
, tr
->slot
);
2687 get_arg_mode(am
, t1
->slot
);
2688 get_arg_mode(am
, op
);
2689 code
= OPCODE_OPTION_LOAD
;
2690 code
+= am
* OPCODE_MODE_MULT
;
2692 gen_am_two(am
, t1
->slot
, op
);
2693 gen_am_two(am
, tr
->slot
,
2694 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2695 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2696 if (flags
& Flag_Borrow
)
2697 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2699 case P_Option_Create
:
2700 res
= u_pcode_get();
2702 pcode_get_var_deref(&a1
, &a1_deref
);
2703 if (unlikely(var_elided(res
))) {
2705 if (unlikely(!pcode_free(ctx
, a1
)))
2710 tr
= get_var_type(ctx
, res
);
2711 t1
= get_var_type(ctx
, a1
);
2712 ajla_assert_lo(tr
->type
->tag
== TYPE_TAG_flat_option
|| tr
->type
->tag
== TYPE_TAG_unknown
, (file_line
, "P_Option_Create(%s): invalid type %u", function_name(ctx
), tr
->type
->tag
));
2714 get_arg_mode(am
, tr
->slot
);
2715 get_arg_mode(am
, t1
->slot
);
2716 get_arg_mode(am
, op
);
2717 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2718 goto exception_overflow
;
2719 code
= OPCODE_OPTION_CREATE
;
2720 code
+= am
* OPCODE_MODE_MULT
;
2722 gen_am_two(am
, tr
->slot
, op
);
2723 gen_am_two(am
, t1
->slot
, a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
2726 res
= u_pcode_get();
2729 if (unlikely(var_elided(res
)))
2731 tr
= get_var_type(ctx
, res
);
2732 t1
= get_var_type(ctx
, a1
);
2733 ajla_assert_lo((t1
->type
->tag
== TYPE_TAG_flat_option
|| t1
->type
->tag
== TYPE_TAG_unknown
) && tr
->type
->tag
== TYPE_TAG_flat_option
, (file_line
, "P_Option_Test(%s): invalid types for option test %u, %u", function_name(ctx
), t1
->type
->tag
, tr
->type
->tag
));
2735 get_arg_mode(am
, tr
->slot
);
2736 get_arg_mode(am
, t1
->slot
);
2737 get_arg_mode(am
, op
);
2738 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2739 goto exception_overflow
;
2740 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2741 code
= OPCODE_OPTION_TEST_FLAT
;
2743 code
= OPCODE_OPTION_TEST
;
2744 code
+= am
* OPCODE_MODE_MULT
;
2746 gen_am_two(am
, t1
->slot
, op
);
2747 gen_am(am
, tr
->slot
);
2750 res
= u_pcode_get();
2752 if (unlikely(var_elided(res
)))
2754 tr
= get_var_type(ctx
, res
);
2755 t1
= get_var_type(ctx
, a1
);
2756 ajla_assert_lo((t1
->type
->tag
== TYPE_TAG_flat_option
|| t1
->type
->tag
== TYPE_TAG_unknown
) && type_is_equal(tr
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Option_Ord(%s): invalid types for option test %u, %u", function_name(ctx
), t1
->type
->tag
, tr
->type
->tag
));
2758 get_arg_mode(am
, tr
->slot
);
2759 get_arg_mode(am
, t1
->slot
);
2760 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2761 code
= OPCODE_OPTION_ORD_FLAT
;
2763 code
= OPCODE_OPTION_ORD
;
2764 code
+= am
* OPCODE_MODE_MULT
;
2766 gen_am_two(am
, t1
->slot
, tr
->slot
);
2768 case P_Array_Flexible
:
2770 res
= u_pcode_get();
2771 ajla_assert_lo(var_elided(res
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible result is not elided", function_name(ctx
)));
2773 ajla_assert_lo(var_elided(a1
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible argument is not elided", function_name(ctx
)));
2774 if (instr
== P_Array_Fixed
)
2777 case P_Array_Create
:
2778 if (unlikely(!pcode_array_create(ctx
)))
2782 res
= u_pcode_get();
2783 pcode_get(); /* local type */
2785 ajla_assert_lo(!(op
& ~(pcode_t
)(Flag_Free_Argument
| Flag_Array_Fill_Sparse
)), (file_line
, "P_Array_Fill(%s): invalid flags %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2788 if (unlikely(var_elided(res
)))
2790 tr
= get_var_type(ctx
, res
);
2791 t1
= get_var_type(ctx
, a1
);
2792 t2
= get_var_type(ctx
, a2
);
2793 ajla_assert_lo(type_is_equal(t2
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Array_Fill(%s): invalid length type: %u", function_name(ctx
), t2
->type
->tag
));
2795 get_arg_mode(am
, t1
->slot
);
2796 get_arg_mode(am
, t2
->slot
);
2797 get_arg_mode(am
, tr
->slot
);
2798 gen_code(OPCODE_ARRAY_FILL
+ am
* OPCODE_MODE_MULT
);
2799 gen_am_two(am
, t1
->slot
,
2800 ((op
& Flag_Free_Argument
) ? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2801 ((op
& Flag_Array_Fill_Sparse
) ? OPCODE_ARRAY_FILL_FLAG_SPARSE
: 0)
2803 gen_am_two(am
, t2
->slot
, tr
->slot
);
2805 case P_Array_String
:
2806 if (unlikely(!pcode_array_string(ctx
)))
2809 case P_Array_Unicode
:
2810 if (unlikely(!pcode_array_unicode(ctx
)))
2814 res
= u_pcode_get();
2815 flags
= u_pcode_get();
2818 if (unlikely(var_elided(res
)))
2820 tr
= get_var_type(ctx
, res
);
2821 t1
= get_var_type(ctx
, a1
);
2822 t2
= get_var_type(ctx
, a2
);
2823 if (TYPE_IS_FLAT(tr
->type
))
2824 flags
&= ~Flag_Borrow
;
2826 get_arg_mode(am
, tr
->slot
);
2827 get_arg_mode(am
, t1
->slot
);
2828 get_arg_mode(am
, t2
->slot
);
2829 code
= OPCODE_ARRAY_LOAD
;
2830 code
+= am
* OPCODE_MODE_MULT
;
2832 gen_am_two(am
, t1
->slot
, t2
->slot
);
2833 gen_am_two(am
, tr
->slot
,
2834 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2835 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0) |
2836 (flags
& Flag_Index_In_Range
? OPCODE_ARRAY_INDEX_IN_RANGE
: 0));
2837 if (flags
& Flag_Borrow
)
2838 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2841 res
= u_pcode_get();
2843 flags
= u_pcode_get();
2844 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2845 if (unlikely(var_elided(res
)))
2847 tr
= get_var_type(ctx
, res
);
2848 t1
= get_var_type(ctx
, a1
);
2849 ajla_assert_lo(type_is_equal(tr
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Array_Len(%s): invalid result type: %u", function_name(ctx
), tr
->type
->tag
));
2850 if (TYPE_IS_FLAT(t1
->type
)) {
2851 ajla_assert_lo(t1
->type
->tag
== TYPE_TAG_flat_array
, (file_line
, "P_Array_Len(%s): invalid flat array type: %u", function_name(ctx
), t1
->type
->tag
));
2852 if (unlikely(!pcode_generate_constant(ctx
, res
, (int_default_t
)type_def(t1
->type
,flat_array
)->n_elements
)))
2855 ajla_assert_lo(t1
->type
->tag
== TYPE_TAG_unknown
, (file_line
, "P_Array_Len(%s): invalid array type: %u", function_name(ctx
), t1
->type
->tag
));
2857 get_arg_mode(am
, t1
->slot
);
2858 get_arg_mode(am
, tr
->slot
);
2859 gen_code(OPCODE_ARRAY_LEN
+ am
* OPCODE_MODE_MULT
);
2860 gen_am_two(am
, t1
->slot
, tr
->slot
);
2861 gen_am(am
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2864 case P_Array_Len_Greater_Than
:
2865 res
= u_pcode_get();
2868 flags
= u_pcode_get();
2869 ajla_assert_lo(!(flags
& ~(Flag_Evaluate
| Flag_Fused_Bin_Jmp
)), (file_line
, "P_Array_Len_Greater_Than(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2870 if (unlikely(var_elided(res
)))
2872 tr
= get_var_type(ctx
, res
);
2873 t1
= get_var_type(ctx
, a1
);
2874 t2
= get_var_type(ctx
, a2
);
2875 ajla_assert_lo(type_is_equal(tr
->type
, type_get_flat_option()), (file_line
, "P_Array_Len_Greater_Than(%s): invalid result type: %u", function_name(ctx
), tr
->type
->tag
));
2876 ajla_assert_lo(type_is_equal(t2
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Array_Len_Greater_Than(%s): invalid length type: %u", function_name(ctx
), t2
->type
->tag
));
2879 if (unlikely(flags
& Flag_Evaluate
) != 0)
2880 fflags
|= OPCODE_OP_FLAG_STRICT
;
2881 if (flags
& Flag_Fused_Bin_Jmp
)
2882 fflags
|= OPCODE_FLAG_FUSED
;
2884 get_arg_mode(am
, t1
->slot
);
2885 get_arg_mode(am
, t2
->slot
);
2886 get_arg_mode(am
, tr
->slot
);
2887 gen_code(OPCODE_ARRAY_LEN_GREATER_THAN
+ am
* OPCODE_MODE_MULT
);
2888 gen_am_two(am
, t1
->slot
, t2
->slot
);
2889 gen_am_two(am
, tr
->slot
, fflags
);
2892 res
= u_pcode_get();
2893 flags
= u_pcode_get();
2897 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Sub(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2898 if (unlikely(var_elided(res
)))
2900 tr
= get_var_type(ctx
, res
);
2901 ta
= get_var_type(ctx
, aa
);
2902 t1
= get_var_type(ctx
, a1
);
2903 t2
= get_var_type(ctx
, a2
);
2904 ajla_assert_lo(type_is_equal(t1
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Array_Sub(%s): invalid length type: %u", function_name(ctx
), t1
->type
->tag
));
2905 ajla_assert_lo(type_is_equal(t2
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Array_Sub(%s): invalid length type: %u", function_name(ctx
), t2
->type
->tag
));
2908 get_arg_mode(am
, ta
->slot
);
2909 get_arg_mode(am
, t1
->slot
);
2910 get_arg_mode(am
, t2
->slot
);
2911 get_arg_mode(am
, tr
->slot
);
2912 gen_code(OPCODE_ARRAY_SUB
+ am
* OPCODE_MODE_MULT
);
2913 gen_am_two(am
, ta
->slot
, t1
->slot
);
2914 gen_am_two(am
, t2
->slot
, tr
->slot
);
2916 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2917 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2921 res
= u_pcode_get();
2922 flags
= u_pcode_get();
2925 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Skip(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2926 if (unlikely(var_elided(res
)))
2928 tr
= get_var_type(ctx
, res
);
2929 ta
= get_var_type(ctx
, aa
);
2930 t1
= get_var_type(ctx
, a1
);
2931 ajla_assert_lo(type_is_equal(t1
->type
, type_get_int(INT_DEFAULT_N
)), (file_line
, "P_Array_Skip(%s): invalid length type: %u", function_name(ctx
), t1
->type
->tag
));
2934 get_arg_mode(am
, ta
->slot
);
2935 get_arg_mode(am
, t1
->slot
);
2936 get_arg_mode(am
, tr
->slot
);
2937 gen_code(OPCODE_ARRAY_SKIP
+ am
* OPCODE_MODE_MULT
);
2938 gen_am_two(am
, ta
->slot
, t1
->slot
);
2939 gen_am_two(am
, tr
->slot
,
2940 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2941 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2944 case P_Array_Append
:
2945 case P_Array_Append_One
:
2946 res
= u_pcode_get();
2947 pcode_get_var_deref(&a1
, &a1_deref
);
2948 pcode_get_var_deref(&a2
, &a2_deref
);
2949 if (unlikely(var_elided(res
)))
2951 tr
= get_var_type(ctx
, res
);
2952 t1
= get_var_type(ctx
, a1
);
2953 t2
= get_var_type(ctx
, a2
);
2955 get_arg_mode(am
, tr
->slot
);
2956 get_arg_mode(am
, t1
->slot
);
2957 get_arg_mode(am
, t2
->slot
);
2958 if (instr
== P_Array_Append
) {
2959 gen_code(OPCODE_ARRAY_APPEND
+ am
* OPCODE_MODE_MULT
);
2961 if (TYPE_IS_FLAT(t2
->type
)) {
2962 gen_code(OPCODE_ARRAY_APPEND_ONE_FLAT
+ am
* OPCODE_MODE_MULT
);
2964 gen_code(OPCODE_ARRAY_APPEND_ONE
+ am
* OPCODE_MODE_MULT
);
2967 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0) | (a2_deref
? OPCODE_FLAG_FREE_ARGUMENT_2
: 0));
2968 gen_am_two(am
, t1
->slot
, t2
->slot
);
2970 case P_Array_Flatten
:
2971 res
= u_pcode_get();
2972 pcode_get_var_deref(&a1
, &a1_deref
);
2973 if (unlikely(var_elided(res
)))
2975 tr
= get_var_type(ctx
, res
);
2976 t1
= get_var_type(ctx
, a1
);
2978 get_arg_mode(am
, tr
->slot
);
2979 get_arg_mode(am
, t1
->slot
);
2980 gen_code(OPCODE_ARRAY_FLATTEN
+ am
* OPCODE_MODE_MULT
);
2981 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0));
2982 gen_am(am
, t1
->slot
);
2985 res
= u_pcode_get();
2986 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Jmp(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2988 if (ctx
->labels
[res
] != no_label
) {
2990 target
= (uint32_t)((ctx
->code_len
- ctx
->labels
[res
]) * sizeof(code_t
));
2991 if (likely(target
< 0x10000)) {
2992 gen_code(OPCODE_JMP_BACK_16
);
2993 gen_code((code_t
)target
);
2998 gen_code(OPCODE_JMP
);
2999 gen_relative_jump(res
, SIZEOF_IP_T
);
3003 tr
= get_var_type(ctx
, res
);
3004 ajla_assert_lo(type_is_equal(tr
->type
, type_get_flat_option()), (file_line
, "P_Jmp_False(%s): invalid type for conditional jump: %u", function_name(ctx
), tr
->type
->tag
));
3010 get_arg_mode(am
, tr
->slot
);
3011 code
= OPCODE_JMP_FALSE
+ am
* OPCODE_MODE_MULT
;
3013 gen_am(am
, tr
->slot
);
3014 gen_relative_jump(a1
, SIZEOF_IP_T
* 2);
3015 gen_relative_jump(a2
, SIZEOF_IP_T
);
3018 gen_code(OPCODE_LABEL
);
3019 res
= u_pcode_get();
3020 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Label(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
3021 ajla_assert_lo(ctx
->labels
[res
] == no_label
, (file_line
, "P_Label(%s): label %"PRIdMAX
" already defined", function_name(ctx
), (intmax_t)res
));
3022 ctx
->labels
[res
] = ctx
->code_len
;
3025 if (unlikely(!pcode_io(ctx
)))
3029 ctx
->pcode
= ctx
->pcode_instr_end
;
3032 for (p
= 0; p
< instr_params
; p
++)
3036 if (unlikely(!pcode_return(ctx
)))
3044 if (unlikely(!gen_checkpoint(ctx
, ctx
->pcode
, instr_params
, true)))
3046 for (p
= 0; p
< instr_params
; p
++)
3050 lp
.line
= u_pcode_get();
3051 lp
.ip
= ctx
->code_len
;
3052 if (unlikely(!array_add_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, lp
, NULL
, ctx
->err
)))
3056 internal(file_line
, "pcode_generate_instructions(%s): invalid pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
3059 if (unlikely(ctx
->pcode
!= ctx
->pcode_instr_end
)) {
3064 for (pp
= ctx
->pcode_instr_end
- instr_params
- 2; pp
< ctx
->pcode
; pp
++) {
3065 str_add_char(&s
, &l
, ' ');
3066 str_add_signed(&s
, &l
, *pp
, 10);
3069 internal(file_line
, "pcode_generate_instructions(%s): mismatched instruction %"PRIdMAX
" length: %"PRIdMAX
" != %"PRIdMAX
":%s", function_name(ctx
), (intmax_t)instr
, (intmax_t)(ctx
->pcode
- (ctx
->pcode_instr_end
- instr_params
)), (intmax_t)instr_params
, s
);
3072 if (unlikely(ctx
->code_len
> sign_bit(ip_t
) / sizeof(code_t
) + uzero
))
3073 goto exception_overflow
;
3077 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3082 static bool pcode_generate_record(struct build_function_context
*ctx
)
3086 struct record_definition
*def
;
3087 if (unlikely(!array_init_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, ctx
->err
)))
3090 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, slot_size
, data_record_offset
, ctx
->err
);
3091 if (unlikely(!ctx
->layout
))
3094 for (; ctx
->pcode
!= ctx
->pcode_limit
; ctx
->pcode
= ctx
->pcode_instr_end
) {
3095 pcode_t instr
, instr_params
;
3096 pcode_get_instr(ctx
, &instr
, &instr_params
);
3098 if (instr
== P_Load_Local_Type
) {
3099 pcode_t var
, fn_var
;
3100 pcode_t attr_unused idx
;
3101 const struct pcode_type
*p
;
3102 const struct type
*t
;
3104 ajla_assert_lo(instr_params
== 3, (file_line
, "pcode_generate_record(%s): invalid number of parameters %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr_params
));
3106 var
= u_pcode_get();
3107 fn_var
= pcode_get();
3108 idx
= u_pcode_get();
3109 if (unlikely(fn_var
!= -1))
3111 if (unlikely(var
!= (pcode_t
)(frame_t
)var
))
3112 goto exception_overflow
;
3113 ajla_assert_lo((size_t)idx
== ctx
->record_entries_len
, (file_line
, "pcode_generate_record(%s): invalid index: %"PRIdMAX
" != %"PRIuMAX
"", function_name(ctx
), (intmax_t)idx
, (uintmax_t)ctx
->record_entries_len
));
3115 if (unlikely(!array_add_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, var
, NULL
, ctx
->err
)))
3118 if (var_elided(var
))
3121 p
= get_var_type(ctx
, var
);
3124 if (unlikely(!layout_add(ctx
->layout
, maximum(t
->size
, 1), t
->align
, ctx
->err
)))
3129 array_finish(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
);
3131 if (unlikely(ctx
->record_entries_len
!= (size_t)(arg_t
)ctx
->record_entries_len
))
3132 goto exception_overflow
;
3134 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3138 def
= type_alloc_record_definition(layout_size(ctx
->layout
), ctx
->err
);
3141 def
->n_slots
= layout_size(ctx
->layout
);
3142 def
->alignment
= maximum(layout_alignment(ctx
->layout
), frame_align
);
3143 def
->n_entries
= (arg_t
)ctx
->record_entries_len
;
3146 for (ai
= 0; ai
< ctx
->record_entries_len
; ai
++) {
3148 const struct pcode_type
*te
;
3149 var
= ctx
->record_entries
[ai
];
3150 if (var_elided((pcode_t
)var
)) {
3151 ctx
->record_entries
[ai
] = NO_FRAME_T
;
3154 slot
= layout_get(ctx
->layout
, layout_idx
++);
3155 ctx
->record_entries
[ai
] = slot
;
3156 te
= get_var_type(ctx
, (pcode_t
)var
);
3157 def
->types
[slot
] = te
->type
;
3160 def
->idx_to_frame
= ctx
->record_entries
, ctx
->record_entries
= NULL
;
3161 ctx
->record_definition
= def
;
3163 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3168 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3174 * pointer_empty -> ret_ex
3175 * poitner_mark -> err
3176 * other -> thunk(error) or data(function)
3178 static pointer_t
pcode_build_function_core(frame_s
*fp
, const code_t
*ip
, const pcode_t
*pcode
, size_t size
, const struct module_designator
*md
, const struct function_designator
*fd
, void **ret_ex
, ajla_error_t
*err
)
3181 pcode_t p
, q
, subfns
;
3185 struct data
*ft
, *fn
;
3186 struct function_descriptor
*sfd
;
3189 #if defined(HAVE_CODEGEN)
3190 union internal_arg ia
[1];
3193 struct build_function_context ctx_
;
3194 struct build_function_context
*ctx
= &ctx_
;
3199 ctx
->pcode_limit
= pcode
+ size
;
3202 q
= u_pcode_get() & Fn_Mask
;
3203 ajla_assert_lo(q
== Fn_Function
|| q
== Fn_Record
|| q
== Fn_Option
, (file_line
, "pcode_build_function_core: invalid function type %"PRIdMAX
"", (intmax_t)q
));
3204 ctx
->function_type
= q
;
3206 u_pcode_get(); /* call mode - used by the optimizer */
3208 subfns
= u_pcode_get();
3210 ctx
->n_local_types
= u_pcode_get();
3213 ctx
->n_local_variables
= (frame_t
)q
;
3214 if (unlikely(q
!= (pcode_t
)ctx
->n_local_variables
))
3215 goto exception_overflow
;
3218 ctx
->n_arguments
= (arg_t
)q
;
3219 ajla_assert_lo(q
== (pcode_t
)ctx
->n_arguments
, (file_line
, "pcode_build_function_core: overflow in n_arguments"));
3222 ctx
->n_return_values
= (arg_t
)q
;
3223 ajla_assert_lo(q
== (pcode_t
)ctx
->n_return_values
, (file_line
, "pcode_build_function_core: overflow in n_return_values"));
3225 ajla_assert_lo((arg_t
)ctx
->n_arguments
<= ctx
->n_local_variables
, (file_line
, "pcode_build_function_core: invalid ctx->n_arguments or ctx->n_local_variables"));
3228 ctx
->n_real_return_values
= (arg_t
)q
;
3229 ajla_assert_lo(ctx
->n_real_return_values
<= ctx
->n_return_values
, (file_line
, "pcode_build_function_core: invalid n_real_return_values"));
3231 ctx
->n_labels
= u_pcode_get();
3233 if (unlikely(!pcode_load_blob(ctx
, &ctx
->function_name
, &is
)))
3235 if (unlikely(!array_add_mayfail(uint8_t, &ctx
->function_name
, &is
, 0, NULL
, ctx
->err
)))
3237 array_finish(uint8_t, &ctx
->function_name
, &is
);
3245 ctx
->local_types
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct local_type
*, 0, 0, ctx
->n_local_types
, sizeof(struct local_type
), ctx
->err
);
3246 if (unlikely(!ctx
->local_types
))
3249 for (p
= 0; p
< ctx
->n_local_types
; p
++) {
3251 struct data
*rec_fn
;
3252 const struct record_definition
*def
;
3253 pcode_t base_idx
, n_elements
;
3254 struct type_entry
*flat_rec
;
3256 const struct type
*tt
, *tp
;
3260 case Local_Type_Record
:
3261 ptr
= pcode_module_load_function(ctx
);
3264 pointer_follow(ptr
, false, rec_fn
, PF_WAIT
, fp
, ip
,
3266 ctx
->ret_val
= pointer_empty();
3268 thunk_reference(thunk_
);
3269 ctx
->ret_val
= pointer_thunk(thunk_
);
3272 ajla_assert_lo(da(rec_fn
,function
)->record_definition
!= NULL
, (file_line
, "pcode_build_function_core(%s): record has no definition", function_name(ctx
)));
3273 def
= type_def(da(rec_fn
,function
)->record_definition
,record
);
3276 case Local_Type_Flat_Record
:
3277 base_idx
= u_pcode_get();
3278 ajla_assert_lo(base_idx
< p
, (file_line
, "pcode_build_function_core(%s): invalid base record index: %"PRIdMAX
" >= %"PRIdMAX
"", function_name(ctx
), (intmax_t)base_idx
, (intmax_t)p
));
3279 n_elements
= u_pcode_get();
3280 def
= type_def(ctx
->local_types
[base_idx
].type
,record
);
3281 ajla_assert_lo(n_elements
== (pcode_t
)def
->n_entries
, (file_line
, "pcode_build_function_core(%s): the number of entries doesn't match: %"PRIdMAX
" != %"PRIuMAX
"", function_name(ctx
), (intmax_t)n_elements
, (uintmax_t)def
->n_entries
));
3282 flat_rec
= type_prepare_flat_record(&def
->type
, ctx
->err
);
3283 if (unlikely(!flat_rec
))
3284 goto record_not_flattened
;
3285 for (ai
= 0; ai
< def
->n_entries
; ai
++) {
3286 pcode_t typ
= pcode_get();
3287 tp
= pcode_to_type(ctx
, typ
, NULL
);
3288 if (unlikely(!TYPE_IS_FLAT(tp
))) {
3289 type_free_flat_record(flat_rec
);
3290 goto record_not_flattened
;
3292 type_set_flat_record_entry(flat_rec
, ai
, tp
);
3294 tt
= type_get_flat_record(flat_rec
, ctx
->err
);
3296 goto record_not_flattened
;
3298 record_not_flattened
:
3301 case Local_Type_Flat_Array
:
3302 base_idx
= pcode_get();
3303 n_elements
= pcode_get();
3304 tp
= pcode_to_type(ctx
, base_idx
, NULL
);
3305 if (unlikely(!TYPE_IS_FLAT(tp
)))
3306 goto array_not_flattened
;
3307 if (unlikely(n_elements
> signed_maximum(int_default_t
) + zero
))
3308 goto array_not_flattened
;
3309 tt
= type_get_flat_array(tp
, n_elements
, ctx
->err
);
3311 goto array_not_flattened
;
3313 array_not_flattened
:
3314 tt
= type_get_unknown();
3317 internal(file_line
, "pcode_build_function_core(%s): invalid local type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
3319 ctx
->local_types
[p
].type
= tt
;
3320 ctx
->local_types
[p
].type_index
= no_type_index
;
3323 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, frame_align
, frame_offset
, ctx
->err
);
3324 if (unlikely(!ctx
->layout
))
3327 ctx
->pcode_types
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct pcode_type
*, 0, 0, ctx
->n_local_variables
, sizeof(struct pcode_type
), ctx
->err
);
3328 if (unlikely(!ctx
->pcode_types
))
3331 if (unlikely(!array_init_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, ctx
->err
)))
3334 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3335 struct pcode_type
*pt
;
3336 pcode_t typ
, color
, varflags
;
3340 color
= pcode_get();
3341 varflags
= u_pcode_get();
3342 pcode_load_blob(ctx
, NULL
, NULL
);
3343 pt
= &ctx
->pcode_types
[v
];
3344 pt
->argument
= NULL
;
3346 pt
->varflags
= varflags
;
3351 const struct type
*t
= pcode_to_type(ctx
, typ
, NULL
);
3352 struct color empty_color
= { 0, 0, false };
3357 if (typ
< 0 && !pcode_get_type(typ
))
3358 pt
->extra_type
= typ
;
3359 while ((size_t)color
>= ctx
->n_colors
)
3360 if (unlikely(!array_add_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, empty_color
, NULL
, ctx
->err
)))
3364 if (!ctx
->colors
[color
].align
) {
3365 ctx
->colors
[color
].size
= t
->size
;
3366 ctx
->colors
[color
].align
= t
->align
;
3368 ajla_assert_lo(ctx
->colors
[color
].size
== t
->size
&&
3369 ctx
->colors
[color
].align
== t
->align
,
3370 (file_line
, "pcode_build_function_core(%s): mismatching variables are put into the same slot: %u != %u || %u != %u", function_name(ctx
), ctx
->colors
[color
].size
, t
->size
, ctx
->colors
[color
].align
, t
->align
));
3375 /*debug("n_local_variables: %s: %u * %zu = %zu (valid %zu, colors %zu, pcode %zu / %zu)", function_name(ctx), ctx->n_local_variables, sizeof(struct pcode_type), ctx->n_local_variables * sizeof(struct pcode_type), is, ctx->n_colors, ctx->pcode - pcode, ctx->pcode_limit - ctx->pcode);*/
3377 for (is
= 0; is
< ctx
->n_colors
; is
++) {
3378 const struct color
*c
= &ctx
->colors
[is
];
3380 if (unlikely(!layout_add(ctx
->layout
, maximum(c
->size
, 1), c
->align
, ctx
->err
)))
3383 if (unlikely(!layout_add(ctx
->layout
, 0, 1, ctx
->err
)))
3388 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3391 ctx
->n_slots
= layout_size(ctx
->layout
);
3393 ctx
->local_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct local_variable
*, 0, 0, ctx
->n_slots
, sizeof(struct local_variable
), ctx
->err
);
3394 if (unlikely(!ctx
->local_variables
))
3397 ctx
->local_variables_flags
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct local_variable_flags
*, 0, 0, ctx
->n_slots
, sizeof(struct local_variable_flags
), ctx
->err
);
3398 if (unlikely(!ctx
->local_variables_flags
))
3401 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3402 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3404 pt
->slot
= NO_FRAME_T
;
3406 pt
->slot
= layout_get(ctx
->layout
, pt
->color
);
3407 ctx
->local_variables
[pt
->slot
].type
= pt
->type
;
3408 /*ctx->local_variables_flags[pt->slot].may_be_borrowed = false;*/
3409 /*if (pt->type->tag == TYPE_TAG_flat_option && !(pt->varflags & VarFlag_Must_Be_Flat))
3410 debug("non-flat variable in %s", function_name(ctx));*/
3411 ctx
->local_variables_flags
[pt
->slot
].must_be_flat
= !!(pt
->varflags
& VarFlag_Must_Be_Flat
);
3412 ctx
->local_variables_flags
[pt
->slot
].must_be_data
= !!(pt
->varflags
& VarFlag_Must_Be_Data
);
3416 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3420 unsigned n_elided
= 0;
3421 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3422 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3426 debug("function, elided %d/%d", n_elided
, ctx
->n_local_variables
);
3430 if (unlikely(!array_init_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ctx
->err
)))
3433 if (unlikely(!pcode_preload_ld(ctx
)))
3437 sfd
= save_find_function_descriptor(md
, fd
);
3444 ctx
->code
= sfd
->code
;
3445 ctx
->code_len
= sfd
->code_size
;
3451 ctx
->labels
= mem_alloc_array_mayfail(mem_alloc_mayfail
, size_t *, 0, 0, ctx
->n_labels
, sizeof(size_t), ctx
->err
);
3452 if (unlikely(!ctx
->labels
))
3454 for (p
= 0; p
< ctx
->n_labels
; p
++)
3455 ctx
->labels
[p
] = no_label
;
3457 if (unlikely(!array_init_mayfail(struct label_ref
, &ctx
->label_ref
, &ctx
->label_ref_len
, ctx
->err
)))
3460 if (unlikely(!array_init_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, ctx
->err
)))
3463 if (unlikely(!array_init_mayfail(code_t
, &ctx
->code
, &ctx
->code_len
, ctx
->err
)))
3466 if (unlikely(!array_init_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, ctx
->err
)))
3469 if (unlikely(ctx
->function_type
== Fn_Record
) || unlikely(ctx
->function_type
== Fn_Option
)) {
3470 if (ctx
->function_type
== Fn_Record
) {
3471 if (unlikely(!pcode_generate_record(ctx
)))
3474 gen_code(OPCODE_UNREACHABLE
);
3476 if (unlikely(!pcode_generate_instructions(ctx
)))
3480 array_finish(code_t
, &ctx
->code
, &ctx
->code_len
);
3481 array_finish(struct line_position
, &ctx
->lp
, &ctx
->lp_size
);
3483 for (is
= 0; is
< ctx
->label_ref_len
; is
++) {
3485 struct label_ref
*lr
= &ctx
->label_ref
[is
];
3486 ajla_assert_lo(lr
->label
< ctx
->n_labels
, (file_line
, "pcode_build_function_core(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)lr
->label
));
3487 ajla_assert_lo(ctx
->labels
[lr
->label
] != no_label
, (file_line
, "pcode_build_function_core(%s): label %"PRIdMAX
" was not defined", function_name(ctx
), (intmax_t)lr
->label
));
3488 diff
= ((uint32_t)ctx
->labels
[lr
->label
] - (uint32_t)lr
->code_pos
) * sizeof(code_t
);
3489 if (SIZEOF_IP_T
== 2) {
3490 ctx
->code
[lr
->code_pos
] += (code_t
)diff
;
3491 } else if (SIZEOF_IP_T
== 4 && !CODE_ENDIAN
) {
3492 uint32_t val
= ctx
->code
[lr
->code_pos
] | ((uint32_t)ctx
->code
[lr
->code_pos
+ 1] << 16);
3494 ctx
->code
[lr
->code_pos
] = val
& 0xffff;
3495 ctx
->code
[lr
->code_pos
+ 1] = val
>> 16;
3496 } else if (SIZEOF_IP_T
== 4 && CODE_ENDIAN
) {
3497 uint32_t val
= ((uint32_t)ctx
->code
[lr
->code_pos
] << 16) | ctx
->code
[lr
->code_pos
+ 1];
3499 ctx
->code
[lr
->code_pos
] = val
>> 16;
3500 ctx
->code
[lr
->code_pos
+ 1] = val
& 0xffff;
3506 mem_free(ctx
->labels
), ctx
->labels
= NULL
;
3507 mem_free(ctx
->label_ref
), ctx
->label_ref
= NULL
;
3509 ft
= data_alloc_flexible(function_types
, types
, ctx
->types_len
, ctx
->err
);
3512 da(ft
,function_types
)->n_types
= ctx
->types_len
;
3513 memcpy(da(ft
,function_types
)->types
, ctx
->types
, ctx
->types_len
* sizeof(const struct type
*));
3514 mem_free(ctx
->types
);
3520 mem_free(ctx
->colors
), ctx
->colors
= NULL
;
3521 mem_free(ctx
->pcode_types
), ctx
->pcode_types
= NULL
;
3522 mem_free(ctx
->local_types
), ctx
->local_types
= NULL
;
3524 array_finish(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
);
3526 if (profiling_escapes
) {
3527 ctx
->escape_data
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct escape_data
*, 0, 0, ctx
->code_len
, sizeof(struct escape_data
), ctx
->err
);
3528 if (unlikely(!ctx
->escape_data
))
3532 fn
= data_alloc_flexible(function
, local_directory
, ctx
->ld_len
, ctx
->err
);
3536 da(fn
,function
)->frame_slots
= frame_offset
/ slot_size
+ ctx
->n_slots
;
3537 da(fn
,function
)->n_bitmap_slots
= bitmap_slots(ctx
->n_slots
);
3538 da(fn
,function
)->n_arguments
= ctx
->n_real_arguments
;
3539 da(fn
,function
)->n_return_values
= ctx
->n_real_return_values
;
3540 da(fn
,function
)->code
= ctx
->code
;
3541 da(fn
,function
)->code_size
= ctx
->code_len
;
3542 da(fn
,function
)->local_variables
= ctx
->local_variables
;
3544 da(fn
,function
)->local_variables_flags
= ctx
->local_variables_flags
;
3546 mem_free(ctx
->local_variables_flags
);
3547 da(fn
,function
)->local_variables_flags
= sfd
->local_variables_flags
;
3549 da(fn
,function
)->args
= ctx
->args
;
3550 da(fn
,function
)->types_ptr
= pointer_data(ft
);
3551 da(fn
,function
)->record_definition
= ctx
->record_definition
? &ctx
->record_definition
->type
: NULL
;
3552 da(fn
,function
)->function_name
= cast_ptr(char *, ctx
->function_name
);
3553 da(fn
,function
)->module_designator
= md
;
3554 da(fn
,function
)->function_designator
= fd
;
3556 da(fn
,function
)->lp
= ctx
->lp
;
3557 da(fn
,function
)->lp_size
= ctx
->lp_size
;
3559 da(fn
,function
)->lp
= sfd
->lp
;
3560 da(fn
,function
)->lp_size
= sfd
->lp_size
;
3562 memcpy(da(fn
,function
)->local_directory
, ctx
->ld
, ctx
->ld_len
* sizeof(pointer_t
*));
3563 da(fn
,function
)->local_directory_size
= ctx
->ld_len
;
3567 da(fn
,function
)->codegen
= function_build_internal_thunk(codegen_fn
, 1, ia
);
3568 store_relaxed(&da(fn
,function
)->codegen_failed
, 0);
3570 function_init_common(fn
);
3573 /*if (memcmp(ctx->code, sfd->code, ctx->code_len * sizeof(code_t))) internal(file_line, "code mismatch");*/
3574 da(fn
,function
)->loaded_cache
= sfd
->data_saved_cache
;
3575 /*if (da(fn,function)->loaded_cache) debug("loaded cache: %s", function_name(ctx));*/
3578 da(fn
,function
)->escape_data
= ctx
->escape_data
;
3579 da(fn
,function
)->leaf
= ctx
->leaf
;
3580 da(fn
,function
)->is_saved
= is_saved
;
3582 ipret_prefetch_functions(fn
);
3584 return pointer_data(fn
);
3587 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3589 ctx
->ret_val
= pointer_mark();
3592 return ctx
->ret_val
;
3595 static void *pcode_build_function(frame_s
*fp
, const code_t
*ip
, const pcode_t
*pcode
, size_t size
, const struct module_designator
*md
, const struct function_designator
*fd
)
3600 ptr
= pcode_build_function_core(fp
, ip
, pcode
, size
, md
, fd
, &ex
, &err
);
3601 if (unlikely(pointer_is_empty(ptr
)))
3603 if (unlikely(pointer_is_mark(ptr
)))
3604 return function_return(fp
, pointer_error(err
, NULL
, NULL pass_file_line
));
3605 return function_return(fp
, ptr
);
3608 void *pcode_build_function_from_builtin(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3610 const pcode_t
*start
;
3612 struct module_designator
*md
= arguments
[0].ptr
;
3613 struct function_designator
*fd
= arguments
[1].ptr
;
3614 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3615 return pcode_build_function(fp
, ip
, start
, size
, md
, arguments
[1].ptr
);
3618 void *pcode_build_function_from_array(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3622 struct thunk
*thunk
;
3625 const struct function_designator
*fd
;
3626 const pcode_t
*start
;
3629 ptr
= arguments
[0].ptr
;
3630 ex
= pointer_deep_eval(ptr
, fp
, ip
, &thunk
);
3631 if (unlikely(ex
!= POINTER_FOLLOW_THUNK_GO
)) {
3632 if (ex
== POINTER_FOLLOW_THUNK_EXCEPTION
) {
3633 return function_return(fp
, pointer_thunk(thunk
));
3638 array_to_bytes(ptr
, &bytes
, &bytes_l
);
3641 if (unlikely(bytes_l
% sizeof(pcode_t
) != 0))
3642 internal(file_line
, "pcode_build_function_from_array: invalid length: %lu", (unsigned long)bytes_l
);
3644 start
= cast_ptr(const pcode_t
*, bytes
);
3645 size
= bytes_l
/ sizeof(pcode_t
);
3646 fd
= arguments
[2].ptr
;
3648 /*builtin_walk_nested(&start, &size, fd->n_entries, fd->entries);*/
3650 ex
= pcode_build_function(fp
, ip
, start
, size
, arguments
[1].ptr
, fd
);
3657 void *pcode_array_from_builtin(frame_s
*fp
, const code_t attr_unused
*ip
, union internal_arg arguments
[])
3659 const struct type
*t
;
3662 const pcode_t
*start
;
3664 struct module_designator
*md
= arguments
[0].ptr
;
3665 struct function_designator
*fd
= arguments
[1].ptr
;
3667 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3669 t
= type_get_fixed(log_2(sizeof(pcode_t
)), false);
3670 d
= data_alloc_array_flat_mayfail(t
, size
, size
, false, &err pass_file_line
);
3672 return function_return(fp
, pointer_thunk(thunk_alloc_exception_error(err
, NULL
, NULL
, NULL pass_file_line
)));
3675 memcpy(da_array_flat(d
), start
, size
* sizeof(pcode_t
));
3677 return function_return(fp
, pointer_data(d
));
3681 pointer_t
pcode_build_eval_function(pcode_t src_type
, pcode_t dest_type
, pcode_t op
, pcode_t
*blob_1
, size_t blob_1_len
, pcode_t
*blob_2
, size_t blob_2_len
, ajla_error_t
*err
)
3685 unsigned n_local_variables
;
3686 unsigned n_arguments
;
3690 if (unlikely(!array_init_mayfail(pcode_t
, &pc
, &pc_l
, err
)))
3694 if (unlikely(!array_add_mayfail(pcode_t, &pc, &pc_l, x, NULL, err)))\
3697 #define addstr(x, l) \
3699 if (unlikely(!array_add_multiple_mayfail(pcode_t, &pc, &pc_l, x, l, NULL, err)))\
3703 n_local_variables
= Op_IsUnary(op
) ? 2 : 3;
3704 n_arguments
= n_local_variables
- 1;
3707 add(Call_Mode_Strict
);
3710 add(n_local_variables
);
3717 for (i
= 0; i
< n_local_variables
; i
++) {
3718 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3730 add(1 + blob_1_len
);
3732 addstr(blob_1
, blob_1_len
);
3733 if (n_arguments
== 2) {
3735 add(1 + blob_2_len
);
3737 addstr(blob_2
, blob_2_len
);
3740 add(Op_IsUnary(op
) ? P_UnaryOp
: P_BinaryOp
);
3741 add(Op_IsUnary(op
) ? 4 : 6);
3744 add(Flag_Free_Argument
| Flag_Op_Strict
);
3746 if (n_arguments
== 2) {
3747 add(Flag_Free_Argument
);
3753 add(Flag_Free_Argument
);
3759 ptr
= pcode_build_function_core(NULL
, NULL
, pc
, pc_l
, NULL
, NULL
, NULL
, err
);
3768 return pointer_empty();
3772 static void *pcode_alloc_op_function(pointer_t
*ptr
, frame_s
*fp
, const code_t
*ip
, void *(*build_fn
)(frame_s
*fp
, const code_t
*ip
, union internal_arg ia
[]), unsigned n_arguments
, union internal_arg ia
[], pointer_t
**result
)
3774 struct data
*function
;
3777 #ifdef POINTER_FOLLOW_IS_LOCKLESS
3778 const addrlock_depth lock_depth
= DEPTH_THUNK
;
3780 const addrlock_depth lock_depth
= DEPTH_POINTER
;
3784 pointer_follow(ptr
, false, function
, PF_WAIT
, fp
, ip
,
3787 return POINTER_FOLLOW_THUNK_RETRY
);
3789 if (likely(function
!= NULL
)) {
3791 return POINTER_FOLLOW_THUNK_RETRY
;
3794 fn_thunk
= function_build_internal_thunk(build_fn
, n_arguments
, ia
);
3796 barrier_write_before_lock();
3797 address_lock(ptr
, lock_depth
);
3798 if (likely(pointer_is_empty(*pointer_volatile(ptr
)))) {
3799 *pointer_volatile(ptr
) = fn_thunk
;
3800 address_unlock(ptr
, lock_depth
);
3802 address_unlock(ptr
, lock_depth
);
3803 pointer_dereference(fn_thunk
);
3809 static void *pcode_build_op_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3811 pcode_t src_type
= (pcode_t
)a
[0].i
;
3812 pcode_t dest_type
= (pcode_t
)a
[1].i
;
3813 pcode_t op
= (pcode_t
)a
[2].i
;
3814 unsigned flags
= (unsigned)a
[3].i
;
3816 unsigned n_local_variables
;
3817 unsigned n_arguments
;
3819 pcode_t
*pc
= pcode
;
3821 n_local_variables
= flags
& PCODE_FIND_OP_UNARY
? 2 : 3;
3822 n_arguments
= n_local_variables
- 1;
3824 *pc
++ = Fn_Function
;
3825 *pc
++ = Call_Mode_Strict
;
3828 *pc
++ = (pcode_t
)n_local_variables
;
3829 *pc
++ = (pcode_t
)n_arguments
;
3835 for (i
= 0; i
< n_local_variables
; i
++) {
3836 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3845 *pc
++ = n_arguments
;
3846 for (i
= 0; i
< n_arguments
; i
++)
3849 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? P_UnaryOp
: P_BinaryOp
);
3850 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? 4 : 6);
3852 *pc
++ = (pcode_t
)n_arguments
;
3853 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3855 if (!(flags
& PCODE_FIND_OP_UNARY
)) {
3856 *pc
++ = Flag_Free_Argument
;
3862 *pc
++ = Flag_Free_Argument
;
3863 *pc
++ = n_arguments
;
3865 ajla_assert_lo((size_t)(pc
- pcode
) <= n_array_elements(pcode
), (file_line
, "pcode_build_op_function: array overflow: %"PRIdMAX
" > %"PRIdMAX
", src_type %"PRIdMAX
", dest_type %"PRIdMAX
", op %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
), (intmax_t)src_type
, (intmax_t)dest_type
, (intmax_t)op
));
3867 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3870 static pointer_t fixed_op_thunk
[TYPE_FIXED_N
][OPCODE_FIXED_OP_N
];
3871 static pointer_t int_op_thunk
[TYPE_INT_N
][OPCODE_INT_OP_N
];
3872 static pointer_t real_op_thunk
[TYPE_REAL_N
][OPCODE_REAL_OP_N
];
3873 static pointer_t bool_op_thunk
[OPCODE_BOOL_TYPE_MULT
];
3875 void * attr_fastcall
pcode_find_op_function(const struct type
*type
, const struct type
*rtype
, code_t code
, unsigned flags
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3877 union internal_arg ia
[4];
3880 type_tag_t tag
= likely(!(flags
& PCODE_CONVERT_FROM_INT
)) ? type
->tag
: rtype
->tag
;
3882 if (TYPE_TAG_IS_FIXED(tag
)) {
3883 unsigned idx
= (code
- OPCODE_FIXED_OP
- (TYPE_TAG_IDX_FIXED(tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
) / OPCODE_FIXED_OP_MULT
;
3884 ajla_assert(idx
< OPCODE_FIXED_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3885 ptr
= &fixed_op_thunk
[TYPE_TAG_IDX_FIXED(tag
) >> 1][idx
];
3886 } else if (TYPE_TAG_IS_INT(tag
)) {
3887 unsigned idx
= (code
- OPCODE_INT_OP
- TYPE_TAG_IDX_INT(tag
) * OPCODE_INT_TYPE_MULT
) / OPCODE_INT_OP_MULT
;
3888 if (idx
>= OPCODE_INT_OP_C
&& idx
< OPCODE_INT_OP_UNARY
)
3889 idx
-= OPCODE_INT_OP_C
;
3890 ajla_assert(idx
< OPCODE_INT_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3891 ptr
= &int_op_thunk
[TYPE_TAG_IDX_INT(tag
)][idx
];
3892 ajla_assert(is_power_of_2(type
->size
), (file_line
, "pcode_find_op_function: invalid integer type size %"PRIuMAX
"", (uintmax_t)type
->size
));
3893 } else if (TYPE_TAG_IS_REAL(tag
)) {
3894 unsigned idx
= (code
- OPCODE_REAL_OP
- TYPE_TAG_IDX_REAL(tag
) * OPCODE_REAL_TYPE_MULT
) / OPCODE_REAL_OP_MULT
;
3895 ajla_assert(idx
< OPCODE_REAL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3896 ptr
= &real_op_thunk
[TYPE_TAG_IDX_REAL(tag
)][idx
];
3898 unsigned idx
= (code
- OPCODE_BOOL_OP
) / OPCODE_BOOL_OP_MULT
;
3899 ajla_assert(idx
< OPCODE_BOOL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3900 ptr
= &bool_op_thunk
[idx
];
3902 internal(file_line
, "pcode_find_op_function: invalid type %u", tag
);
3905 ia
[0].i
= type_to_pcode(type
);
3906 ia
[1].i
= type_to_pcode(rtype
);
3907 ia
[2].i
= code
+ Op_N
;
3910 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_op_function
, 4, ia
, result
);
3913 static void *pcode_build_is_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3916 pcode_t
*pc
= pcode
;
3918 *pc
++ = Fn_Function
;
3919 *pc
++ = Call_Mode_Strict
;
3929 *pc
++ = T_Undetermined
;
3930 *pc
++ = T_Undetermined
;
3935 *pc
++ = T_AlwaysFlatOption
;
3936 *pc
++ = T_AlwaysFlatOption
;
3947 *pc
++ = Un_IsException
;
3949 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3958 *pc
++ = Flag_Free_Argument
;
3961 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_is_exception_function: array overflow: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
3963 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3966 static pointer_t is_exception_thunk
;
3968 void * attr_fastcall
pcode_find_is_exception(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3970 return pcode_alloc_op_function(&is_exception_thunk
, fp
, ip
, pcode_build_is_exception_function
, 0, NULL
, result
);
3973 static void *pcode_build_get_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3976 pcode_t
*pc
= pcode
;
3978 *pc
++ = Fn_Function
;
3979 *pc
++ = Call_Mode_Strict
;
3989 *pc
++ = T_Undetermined
;
3990 *pc
++ = T_Undetermined
;
4007 *pc
++ = Un_ExceptionClass
+ a
[0].i
;
4009 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
4018 *pc
++ = Flag_Free_Argument
;
4021 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_get_exception_function: array overflow: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4023 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4026 static pointer_t get_exception_thunk
[3];
4028 void * attr_fastcall
pcode_find_get_exception(unsigned mode
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4030 union internal_arg ia
[1];
4032 return pcode_alloc_op_function(&get_exception_thunk
[mode
], fp
, ip
, pcode_build_get_exception_function
, 1, ia
, result
);
4035 static void *pcode_build_array_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4038 pcode_t
*pc
= pcode
;
4040 *pc
++ = Fn_Function
;
4041 *pc
++ = Call_Mode_Strict
;
4051 *pc
++ = T_Undetermined
;
4052 *pc
++ = T_Undetermined
;
4063 *pc
++ = T_Undetermined
;
4064 *pc
++ = T_Undetermined
;
4074 *pc
++ = P_Array_Load
;
4077 *pc
++ = Flag_Evaluate
;
4091 *pc
++ = Flag_Free_Argument
;
4094 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_array_load_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4096 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4099 static pointer_t array_load_thunk
;
4101 void * attr_fastcall
pcode_find_array_load_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4103 return pcode_alloc_op_function(&array_load_thunk
, fp
, ip
, pcode_build_array_load_function
, 0, NULL
, result
);
4106 static void *pcode_build_array_len_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4109 pcode_t
*pc
= pcode
;
4111 *pc
++ = Fn_Function
;
4112 *pc
++ = Call_Mode_Strict
;
4122 *pc
++ = T_Undetermined
;
4123 *pc
++ = T_Undetermined
;
4138 *pc
++ = P_Array_Len
;
4142 *pc
++ = Flag_Evaluate
;
4150 *pc
++ = Flag_Free_Argument
;
4153 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_array_len_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4155 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4158 static pointer_t array_len_thunk
;
4160 void * attr_fastcall
pcode_find_array_len_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4162 return pcode_alloc_op_function(&array_len_thunk
, fp
, ip
, pcode_build_array_len_function
, 0, NULL
, result
);
4165 static void *pcode_build_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4168 pcode_t
*pc
= pcode
;
4170 *pc
++ = Fn_Function
;
4171 *pc
++ = Call_Mode_Strict
;
4181 *pc
++ = T_Undetermined
;
4182 *pc
++ = T_Undetermined
;
4193 *pc
++ = T_AlwaysFlatOption
;
4194 *pc
++ = T_AlwaysFlatOption
;
4204 *pc
++ = P_Array_Len_Greater_Than
;
4209 *pc
++ = Flag_Evaluate
;
4221 *pc
++ = Flag_Free_Argument
;
4224 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_array_len_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4226 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4229 static pointer_t array_len_greater_than_thunk
;
4231 void * attr_fastcall
pcode_find_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4233 return pcode_alloc_op_function(&array_len_greater_than_thunk
, fp
, ip
, pcode_build_array_len_greater_than_function
, 0, NULL
, result
);
4236 static void *pcode_build_array_sub_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4239 pcode_t
*pc
= pcode
;
4241 *pc
++ = Fn_Function
;
4242 *pc
++ = Call_Mode_Strict
;
4252 *pc
++ = T_Undetermined
;
4253 *pc
++ = T_Undetermined
;
4270 *pc
++ = T_Undetermined
;
4271 *pc
++ = T_Undetermined
;
4282 *pc
++ = P_Array_Sub
;
4285 *pc
++ = Flag_Evaluate
;
4304 *pc
++ = Flag_Free_Argument
;
4307 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_array_len_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4309 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4312 static pointer_t array_sub_thunk
;
4314 void * attr_fastcall
pcode_find_array_sub_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4316 return pcode_alloc_op_function(&array_sub_thunk
, fp
, ip
, pcode_build_array_sub_function
, 0, NULL
, result
);
4319 static void *pcode_build_array_skip_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4322 pcode_t
*pc
= pcode
;
4324 *pc
++ = Fn_Function
;
4325 *pc
++ = Call_Mode_Strict
;
4335 *pc
++ = T_Undetermined
;
4336 *pc
++ = T_Undetermined
;
4347 *pc
++ = T_Undetermined
;
4348 *pc
++ = T_Undetermined
;
4358 *pc
++ = P_Array_Skip
;
4361 *pc
++ = Flag_Evaluate
;
4375 *pc
++ = Flag_Free_Argument
;
4378 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_array_len_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4380 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4383 static pointer_t array_skip_thunk
;
4385 void * attr_fastcall
pcode_find_array_skip_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4387 return pcode_alloc_op_function(&array_skip_thunk
, fp
, ip
, pcode_build_array_skip_function
, 0, NULL
, result
);
4390 static void *pcode_build_array_append_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4393 pcode_t
*pc
= pcode
;
4395 *pc
++ = Fn_Function
;
4396 *pc
++ = Call_Mode_Strict
;
4406 *pc
++ = T_Undetermined
;
4407 *pc
++ = T_Undetermined
;
4412 *pc
++ = T_Undetermined
;
4413 *pc
++ = T_Undetermined
;
4418 *pc
++ = T_Undetermined
;
4419 *pc
++ = T_Undetermined
;
4439 *pc
++ = P_Array_Append
;
4442 *pc
++ = Flag_Free_Argument
;
4444 *pc
++ = Flag_Free_Argument
;
4449 *pc
++ = Flag_Free_Argument
;
4451 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_array_append_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4453 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4456 static pointer_t array_append_thunk
;
4458 void * attr_fastcall
pcode_find_array_append_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4460 return pcode_alloc_op_function(&array_append_thunk
, fp
, ip
, pcode_build_array_append_function
, 0, NULL
, result
);
4464 static void *pcode_build_option_ord_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4467 pcode_t
*pc
= pcode
;
4469 *pc
++ = Fn_Function
;
4470 *pc
++ = Call_Mode_Strict
;
4480 *pc
++ = T_Undetermined
;
4481 *pc
++ = T_Undetermined
;
4500 *pc
++ = P_Option_Ord
;
4511 *pc
++ = Flag_Free_Argument
;
4514 ajla_assert_lo((size_t)(pc
- pcode
) == n_array_elements(pcode
), (file_line
, "pcode_build_option_ord_function: array mismatch: %"PRIdMAX
" != %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4516 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4519 static pointer_t option_ord_thunk
;
4521 void * attr_fastcall
pcode_find_option_ord_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4523 return pcode_alloc_op_function(&option_ord_thunk
, fp
, ip
, pcode_build_option_ord_function
, 0, NULL
, result
);
4527 struct function_key
{
4532 static void *pcode_build_record_option_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
4535 pcode_t
*pc
= pcode
;
4536 pcode_t result_type
= a
[0].i
== PCODE_FUNCTION_OPTION_TEST
? T_FlatOption
: T_Undetermined
;
4538 *pc
++ = Fn_Function
;
4539 *pc
++ = Call_Mode_Strict
;
4549 *pc
++ = T_Undetermined
;
4550 *pc
++ = T_Undetermined
;
4555 *pc
++ = result_type
;
4556 *pc
++ = result_type
;
4566 case PCODE_FUNCTION_RECORD_LOAD
:
4567 /* P_Record_Load_Slot already sets Flag_Evaluate */
4568 *pc
++ = P_Record_Load_Slot
;
4572 *pc
++ = (pcode_t
)a
[1].i
;
4574 case PCODE_FUNCTION_OPTION_LOAD
:
4575 *pc
++ = P_Option_Load
;
4578 *pc
++ = Flag_Evaluate
;
4580 *pc
++ = (pcode_t
)a
[1].i
;
4582 case PCODE_FUNCTION_OPTION_TEST
:
4586 *pc
++ = P_Option_Test
;
4590 *pc
++ = (pcode_t
)a
[1].i
;
4593 internal(file_line
, "pcode_build_record_option_load_function: invalid operation %"PRIuMAX
"", (uintmax_t)a
[0].i
);
4602 *pc
++ = Flag_Free_Argument
;
4605 ajla_assert_lo((size_t)(pc
- pcode
) <= n_array_elements(pcode
), (file_line
, "pcode_build_record_option_load_function: array overflow: %"PRIdMAX
" > %"PRIdMAX
"", (intmax_t)(pc
- pcode
), (intmax_t)n_array_elements(pcode
)));
4607 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4610 struct pcode_function
{
4611 struct tree_entry entry
;
4612 struct function_key key
;
4616 shared_var
struct tree pcode_functions
;
4617 rwlock_decl(pcode_functions_mutex
);
4619 static int record_option_load_compare(const struct tree_entry
*e1
, uintptr_t e2
)
4621 struct pcode_function
*rl
= get_struct(e1
, struct pcode_function
, entry
);
4622 struct function_key
*key
= cast_cpp(struct function_key
*, num_to_ptr(e2
));
4623 if (rl
->key
.tag
!= key
->tag
)
4624 return (int)rl
->key
.tag
- key
->tag
;
4625 if (rl
->key
.id
< key
->id
)
4627 if (rl
->key
.id
> key
->id
)
4632 static pointer_t
*pcode_find_function_for_key(struct function_key
*key
)
4634 struct tree_entry
*e
;
4636 rwlock_lock_read(&pcode_functions_mutex
);
4637 e
= tree_find(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
));
4638 rwlock_unlock_read(&pcode_functions_mutex
);
4640 struct tree_insert_position ins
;
4641 rwlock_lock_write(&pcode_functions_mutex
);
4642 e
= tree_find_for_insert(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
), &ins
);
4645 struct pcode_function
*rl
;
4646 rl
= mem_alloc_mayfail(struct pcode_function
*, sizeof(struct pcode_function
), &sink
);
4647 if (unlikely(!rl
)) {
4648 rwlock_unlock_write(&pcode_functions_mutex
);
4652 rl
->ptr
= pointer_empty();
4654 tree_insert_after_find(e
, &ins
);
4656 rwlock_unlock_write(&pcode_functions_mutex
);
4658 return &get_struct(e
, struct pcode_function
, entry
)->ptr
;
4661 void * attr_fastcall
pcode_find_record_option_load_function(unsigned char tag
, frame_t slot
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4663 struct function_key key
;
4665 union internal_arg ia
[2];
4667 if (unlikely((uintmax_t)slot
> (uintmax_t)signed_maximum(pcode_t
) + zero
)) {
4668 *result
= out_of_memory_ptr
;
4669 return POINTER_FOLLOW_THUNK_RETRY
;
4675 ptr
= pcode_find_function_for_key(&key
);
4676 if (unlikely(!ptr
)) {
4677 *result
= out_of_memory_ptr
;
4678 return POINTER_FOLLOW_THUNK_RETRY
;
4683 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_record_option_load_function
, 2, ia
, result
);
4686 static void thunk_init_run(pointer_t
*ptr
, unsigned n
)
4689 *ptr
= pointer_empty();
4694 static void thunk_free_run(pointer_t
*ptr
, unsigned n
)
4697 if (!pointer_is_empty(*ptr
))
4698 pointer_dereference(*ptr
);
4703 void name(pcode_init
)(void)
4707 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_init_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4708 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_init_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4709 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_init_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4710 thunk_init_run(&is_exception_thunk
, 1);
4711 thunk_init_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4712 thunk_init_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4713 thunk_init_run(&array_load_thunk
, 1);
4714 thunk_init_run(&array_len_thunk
, 1);
4715 thunk_init_run(&array_len_greater_than_thunk
, 1);
4716 thunk_init_run(&array_sub_thunk
, 1);
4717 thunk_init_run(&array_skip_thunk
, 1);
4718 thunk_init_run(&array_append_thunk
, 1);
4719 thunk_init_run(&option_ord_thunk
, 1);
4720 tree_init(&pcode_functions
);
4721 rwlock_init(&pcode_functions_mutex
);
4724 void name(pcode_done
)(void)
4727 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_free_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4728 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_free_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4729 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_free_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4730 thunk_free_run(&is_exception_thunk
, 1);
4731 thunk_free_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4732 thunk_free_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4733 thunk_free_run(&array_load_thunk
, 1);
4734 thunk_free_run(&array_len_thunk
, 1);
4735 thunk_free_run(&array_len_greater_than_thunk
, 1);
4736 thunk_free_run(&array_sub_thunk
, 1);
4737 thunk_free_run(&array_skip_thunk
, 1);
4738 thunk_free_run(&array_append_thunk
, 1);
4739 thunk_free_run(&option_ord_thunk
, 1);
4740 while (!tree_is_empty(&pcode_functions
)) {
4741 struct pcode_function
*rl
= get_struct(tree_any(&pcode_functions
), struct pcode_function
, entry
);
4742 if (!pointer_is_empty(rl
->ptr
))
4743 pointer_dereference(rl
->ptr
);
4744 tree_delete(&rl
->entry
);
4747 rwlock_done(&pcode_functions_mutex
);