2 * Copyright (C) 2024 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(bt
), fx(bt
), in(bt
), NO_OPCODE
, NO_OPCODE
, },
80 { fx(not), fx(not), in(not), NO_OPCODE
, bo(not), },
81 { fx(neg
), fx(neg
), in(neg
), re(neg
), NO_OPCODE
, },
82 { fx(inc
), fx(inc
), in(inc
), NO_OPCODE
, NO_OPCODE
, },
83 { fx(dec
), fx(dec
), in(dec
), NO_OPCODE
, 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();
505 t
= type_get_unknown();
515 static const struct type
*pcode_to_type(const struct build_function_context
*ctx
, pcode_t q
, ajla_error_t
*mayfail
)
517 const struct type
*t
;
519 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
));
520 return ctx
->local_types
[q
].type
;
522 t
= pcode_get_type(q
);
524 if (q
== T_SInt64
|| q
== T_UInt64
|| q
== T_SInt128
|| q
== T_UInt128
)
525 return pcode_get_type(T_Integer128
);
526 if (q
== T_Real16
|| q
== T_Real32
|| q
== T_Real64
|| q
== T_Real80
|| q
== T_Real128
)
527 return pcode_get_type(T_Integer128
);
528 if (unlikely(!mayfail
))
529 internal(file_line
, "pcode_to_type(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
530 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_NOT_SUPPORTED
);
535 static pcode_t
type_to_pcode(const struct type
*type
)
537 if (TYPE_TAG_IS_FIXED(type
->tag
))
538 return (pcode_t
)(T_SInt8
- TYPE_TAG_IDX_FIXED(type
->tag
));
539 else if (TYPE_TAG_IS_INT(type
->tag
))
540 return (pcode_t
)(T_Integer8
- TYPE_TAG_IDX_INT(type
->tag
));
541 else if (TYPE_TAG_IS_REAL(type
->tag
))
542 return (pcode_t
)(T_Real16
- TYPE_TAG_IDX_REAL(type
->tag
));
543 else if (type
->tag
== TYPE_TAG_flat_option
)
546 internal(file_line
, "type_to_pcode: invalid type %u", type
->tag
);
550 static pcode_t
pcode_to_type_index(struct build_function_context
*ctx
, pcode_t q
, bool non_flat
)
553 const struct type
*type
= pcode_to_type(ctx
, q
, NULL
);
554 if (!TYPE_IS_FLAT(type
) && non_flat
)
555 return no_type_index
;
558 result
= &ctx
->local_types
[q
].type_index
;
560 unsigned tag
= type
->tag
;
561 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
));
562 result
= &ctx
->builtin_type_indices
[tag
];
564 if (*result
!= no_type_index
)
566 if (unlikely((pcode_t
)ctx
->types_len
< 0)) {
567 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "type array overflow");
568 return error_type_index
;
570 if (unlikely(!array_add_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, type
, NULL
, ctx
->err
)))
571 return error_type_index
;
572 return *result
= (pcode_t
)(ctx
->types_len
- 1);
575 #define pcode_get_var_deref(var, deref) \
577 pcode_t r_ = u_pcode_get(); \
578 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_));\
579 *(deref) = !!(r_ & Flag_Free_Argument); \
580 *(var) = pcode_get(); \
583 #define var_elided(idx) (((idx) < zero) || ctx->pcode_types[idx].type == NULL)
585 static struct pcode_type
*get_var_type(struct build_function_context
*ctx
, pcode_t v
)
587 ajla_assert_lo(!var_elided(v
), (file_line
, "get_var_type(%s): variable %"PRIdMAX
" is elided", function_name(ctx
), (intmax_t)v
));
588 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
));
589 return &ctx
->pcode_types
[v
];
592 static bool pcode_load_blob(struct build_function_context
*ctx
, uint8_t **blob
, size_t *l
)
597 if (unlikely(!array_init_mayfail(uint8_t, blob
, l
, ctx
->err
)))
601 q
= 0; /* avoid warning */
603 for (i
= 0; i
< n
; i
++) {
611 if (unlikely(!array_add_mayfail(uint8_t, blob
, l
, (uint8_t)val
, NULL
, ctx
->err
)))
619 static bool pcode_generate_blob(uint8_t *str
, size_t str_len
, pcode_t
**res_blob
, size_t *res_len
, ajla_error_t
*err
)
622 if (unlikely(str_len
> signed_maximum(pcode_t
))) {
623 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), err
, "pcode overflow");
626 if (unlikely(!array_init_mayfail(pcode_t
, res_blob
, res_len
, err
)))
628 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, 0, NULL
, err
)))
630 for (i
= 0; i
< str_len
; i
++) {
632 if (!(**res_blob
% sizeof(pcode_t
))) {
633 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, b
, NULL
, err
)))
636 (*res_blob
)[*res_len
- 1] |= (upcode_t
)((b
) & 0xff) << (**res_blob
% sizeof(pcode_t
) * 8);
643 static pointer_t
*pcode_module_load_function(struct build_function_context
*ctx
)
648 uint8_t *blob
= NULL
;
650 struct module_designator
*md
= NULL
;
651 struct function_designator
*fd
= NULL
;
655 path_idx
= (unsigned)q
;
656 if (unlikely(q
!= (pcode_t
)path_idx
))
657 goto exception_overflow
;
658 program
= path_idx
& 1;
660 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
663 md
= module_designator_alloc(path_idx
, blob
, l
, program
, ctx
->err
);
667 mem_free(blob
), blob
= NULL
;
669 fd
= function_designator_alloc(ctx
->pcode
, ctx
->err
);
672 ctx
->pcode
+= fd
->n_entries
+ 1;
674 ptr
= module_load_function(md
, fd
, false, ctx
->err
);
678 module_designator_free(md
), md
= NULL
;
679 function_designator_free(fd
), fd
= NULL
;
684 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "pcode overflow");
689 module_designator_free(md
);
691 function_designator_free(fd
);
695 #define no_function_idx ((size_t)-1)
697 static int ld_tree_compare(const struct tree_entry
*e
, uintptr_t ptr
)
699 struct ld_ref
*ld_ref
= get_struct(e
, struct ld_ref
, entry
);
700 uintptr_t ld_ptr
= ptr_to_num(ld_ref
->ptr
);
708 static size_t pcode_module_load_function_idx(struct build_function_context
*ctx
, pointer_t
*ptr
, bool must_exist
)
710 struct tree_entry
*e
;
711 struct ld_ref
*ld_ref
;
712 struct tree_insert_position ins
;
714 e
= tree_find_for_insert(&ctx
->ld_tree
, ld_tree_compare
, ptr_to_num(ptr
), &ins
);
716 ld_ref
= get_struct(e
, struct ld_ref
, entry
);
720 if (unlikely(must_exist
))
721 internal(file_line
, "pcode_module_load_function_idx: local directory preload didn't work");
723 ld_ref
= mem_alloc_mayfail(struct ld_ref
*, sizeof(struct ld_ref
), ctx
->err
);
724 if (unlikely(!ld_ref
))
725 return no_function_idx
;
727 ld_ref
->idx
= ctx
->ld_len
;
729 tree_insert_after_find(&ld_ref
->entry
, &ins
);
731 if (unlikely(!array_add_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ptr
, NULL
, ctx
->err
)))
732 return no_function_idx
;
733 return ctx
->ld_len
- 1;
736 #define gen_code(n) \
738 if (unlikely(!array_add_mayfail(code_t, &ctx->code, &ctx->code_len, n, NULL, ctx->err)))\
743 #define gen_uint32(n) \
745 gen_code((code_t)((n) & 0xffff)); \
746 gen_code((code_t)((n) >> 15 >> 1)); \
749 #define gen_uint32(n) \
751 gen_code((code_t)((n) >> 15 >> 1)); \
752 gen_code((code_t)((n) & 0xffff)); \
756 #define gen_am(am, m) \
759 gen_code((code_t)(m)); \
760 } else if (am == 2) { \
763 internal(file_line, "gen_am(%s): arg mode %d", function_name(ctx), am);\
767 #define gen_am_two(am, m, n) \
770 gen_code((code_t)((m) + ((n) << 8))); \
771 } else if (am == 1) { \
772 gen_code((code_t)(m)); \
773 gen_code((code_t)(n)); \
774 } else if (am == 2) { \
778 internal(file_line, "gen_am_two(%s): arg mode %d", function_name(ctx), am);\
782 #define gen_relative_jump(lbl, diff) \
785 ajla_assert_lo((lbl) < ctx->n_labels, (file_line, "gen_relative_jump(%s): invalid label %"PRIdMAX"", function_name(ctx), (intmax_t)(lbl)));\
786 target = -(((uint32_t)(diff) + 1) / (uint32_t)sizeof(code_t) * (uint32_t)sizeof(code_t));\
787 if (ctx->labels[lbl] == no_label) { \
788 struct label_ref lr; \
789 lr.code_pos = ctx->code_len; \
791 if (unlikely(!array_add_mayfail(struct label_ref, &ctx->label_ref, &ctx->label_ref_len, lr, NULL, ctx->err)))\
794 target += ((uint32_t)ctx->labels[lbl] - (uint32_t)ctx->code_len) * (uint32_t)sizeof(code_t);\
796 if (SIZEOF_IP_T == 2) \
797 gen_code((code_t)target); \
798 else if (SIZEOF_IP_T == 4) \
799 gen_uint32(target); \
800 else not_reached(); \
803 static bool gen_checkpoint(struct build_function_context
*ctx
, const pcode_t
*params
, pcode_t n_params
, bool check_arguments
)
808 pcode_t n_used_params
;
810 bool *processed_variables
= NULL
;
812 if (unlikely(ctx
->is_eval
))
815 processed_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, bool *, 0, 0, ctx
->n_slots
, sizeof(bool), ctx
->err
);
816 if (unlikely(!processed_variables
))
819 am
= INIT_ARG_MODE_1
;
820 get_arg_mode(am
, n_params
);
823 for (i
= 0; i
< n_params
; i
++) {
824 const struct pcode_type
*tv
;
825 pcode_t var
= params
[i
];
828 tv
= get_var_type(ctx
, var
);
829 get_arg_mode(am
, tv
->slot
);
830 if (!processed_variables
[tv
->slot
]) {
831 processed_variables
[tv
->slot
] = true;
836 if (check_arguments
) {
838 for (ia
= 0; ia
< ctx
->n_real_arguments
; ia
++) {
839 const struct local_arg
*la
= &ctx
->args
[ia
];
840 if (ctx
->local_variables_flags
[la
->slot
].must_be_flat
&& ia
< 4 && 0)
842 if (!la
->may_be_borrowed
)
845 get_arg_mode(am
, la
->slot
);
846 if (!processed_variables
[la
->slot
]) {
847 processed_variables
[la
->slot
] = true;
853 code
= OPCODE_CHECKPOINT
;
854 code
+= am
* OPCODE_MODE_MULT
;
856 gen_am(ARG_MODE_N
- 1, ctx
->checkpoint_num
);
858 gen_am(am
, n_used_params
);
860 for (v
= 0; v
< ctx
->n_slots
; v
++) {
861 if (unlikely(processed_variables
[v
])) {
866 mem_free(processed_variables
);
867 processed_variables
= NULL
;
869 ctx
->checkpoint_num
++;
870 if (unlikely(!ctx
->checkpoint_num
)) {
871 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "checkpoint number overflow");
878 if (processed_variables
)
879 mem_free(processed_variables
);
883 static bool pcode_free(struct build_function_context
*ctx
, pcode_t res
)
886 const struct pcode_type
*tr
;
888 const struct color
*c
;
890 if (unlikely(var_elided(res
)))
892 tr
= get_var_type(ctx
, res
);
894 get_arg_mode(am
, tr
->slot
);
895 c
= &ctx
->colors
[tr
->color
];
896 if (!TYPE_IS_FLAT(tr
->type
) && c
->is_argument
)
897 code
= OPCODE_DEREFERENCE_CLEAR
;
899 code
= OPCODE_DEREFERENCE
;
900 code
+= am
* OPCODE_MODE_MULT
;
902 gen_am(am
, tr
->slot
);
910 static bool pcode_copy(struct build_function_context
*ctx
, bool type_cast
, pcode_t res
, pcode_t a1
, bool a1_deref
)
912 const struct pcode_type
*tr
, *t1
;
916 tr
= get_var_type(ctx
, res
);
917 t1
= get_var_type(ctx
, a1
);
919 if (t1
->slot
== tr
->slot
) {
920 ajla_assert(a1_deref
, (file_line
, "pcode_copy(%s): dereference not set", function_name(ctx
)));
922 * If we copy a value to itself, we must clear may_be_borrowed,
923 * otherwise we get failure in start03.ajla and start04.ajla.
925 * (note that pcode_copy is called from pcode_structured_write)
927 * The reason for the crash is that may_be_borrowed is per-variable,
928 * not per-slot flag - if we copy to a different variable occupying
929 * the same slot, we won't see may_be_borrowed anymore.
932 if (t1
->type
->size
== 0) {
934 get_arg_mode(am
, t1
->slot
);
935 code
= OPCODE_TAKE_BORROWED
;
936 code
+= am
* OPCODE_MODE_MULT
;
938 gen_am(am
, t1
->slot
);
944 if ((t1
->type
->size
== 0 && tr
->type
->size
== 0) || type_cast
) {
945 const struct color
*c
= &ctx
->colors
[t1
->color
];
947 get_arg_mode(am
, t1
->slot
);
948 get_arg_mode(am
, tr
->slot
);
950 code
= a1_deref
? OPCODE_BOX_MOVE_CLEAR
: OPCODE_BOX_COPY
;
952 code
= a1_deref
? (c
->is_argument
? OPCODE_REF_MOVE_CLEAR
: OPCODE_REF_MOVE
) : OPCODE_REF_COPY
;
954 code
+= am
* OPCODE_MODE_MULT
;
956 gen_am_two(am
, t1
->slot
, tr
->slot
);
957 } else if (t1
->type
->tag
== TYPE_TAG_flat_record
|| t1
->type
->tag
== TYPE_TAG_flat_array
) {
958 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
));
960 get_arg_mode(am
, t1
->slot
);
961 get_arg_mode(am
, tr
->slot
);
962 code
= a1_deref
? OPCODE_FLAT_MOVE
: OPCODE_FLAT_COPY
;
963 code
+= am
* OPCODE_MODE_MULT
;
965 gen_am_two(am
, t1
->slot
, tr
->slot
);
967 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
));
969 get_arg_mode(am
, t1
->slot
);
970 get_arg_mode(am
, tr
->slot
);
971 code
= get_code(a1_deref
? Op_Mov
: Op_Copy
, t1
->type
);
972 code
+= am
* OPCODE_MODE_MULT
;
974 gen_am_two(am
, t1
->slot
, tr
->slot
);
982 static bool pcode_process_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
, pcode_t
*n_real_arguments
, arg_mode_t
*am
)
985 if (n_real_arguments
)
986 *n_real_arguments
= 0;
987 for (ai
= 0; ai
< n_arguments
; ai
++) {
989 struct pcode_type
*t1
;
991 pcode_get_var_deref(&a1
, &deref
);
992 if (unlikely(var_elided(a1
)))
994 t1
= get_var_type(ctx
, a1
);
995 if (n_real_arguments
) {
996 get_arg_mode(*am
, t1
->slot
);
997 (*n_real_arguments
)++;
998 t1
->is_dereferenced_in_call_argument
= deref
;
1002 flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
1003 if (!TYPE_IS_FLAT(t1
->type
))
1004 flags
|= OPCODE_CALL_MAY_GIVE
;
1006 if (!t1
->is_dereferenced_in_call_argument
&& !TYPE_IS_FLAT(t1
->type
))
1007 flags
|= OPCODE_CALL_MAY_LEND
;
1009 gen_am_two(*am
, t1
->slot
, flags
);
1012 if (n_real_arguments
)
1013 get_arg_mode(*am
, *n_real_arguments
);
1020 static bool pcode_dereference_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
)
1023 for (ai
= 0; ai
< n_arguments
; ai
++) {
1026 pcode_get_var_deref(&a1
, &deref
);
1028 if (unlikely(!pcode_free(ctx
, a1
)))
1038 static bool pcode_finish_call(struct build_function_context
*ctx
, const struct pcode_type
**rets
, size_t rets_l
, bool test_flat
)
1041 frame_t
*vars
= NULL
;
1045 for (i
= 0; i
< rets_l
; i
++) {
1046 const struct pcode_type
*tv
= rets
[i
];
1047 if (ARG_MODE_N
>= 3) {
1048 gen_uint32(tv
->slot
);
1050 gen_code((code_t
)tv
->slot
);
1052 gen_code(TYPE_IS_FLAT(tv
->type
) ? OPCODE_MAY_RETURN_FLAT
: 0);
1055 if (unlikely(test_flat
)) {
1060 if (unlikely(!gen_checkpoint(ctx
, NULL
, 0, false)))
1063 vars
= mem_alloc_array_mayfail(mem_alloc_mayfail
, frame_t
*, 0, 0, ctx
->n_slots
, sizeof(frame_t
), ctx
->err
);
1064 if (unlikely(!vars
))
1067 am
= INIT_ARG_MODE_1
;
1069 for (slot
= MIN_USEABLE_SLOT
; slot
< ctx
->n_slots
; slot
++) {
1070 if (ctx
->local_variables_flags
[slot
].must_be_flat
|| ctx
->local_variables_flags
[slot
].must_be_data
) {
1071 vars
[n_vars
++] = slot
;
1072 get_arg_mode(am
, slot
);
1077 get_arg_mode(am
, n_vars
);
1078 code
= OPCODE_ESCAPE_NONFLAT
;
1079 code
+= am
* OPCODE_MODE_MULT
;
1082 for (i
= 0; i
< n_vars
; i
++)
1083 gen_am(am
, vars
[i
]);
1097 static bool pcode_call(struct build_function_context
*ctx
, pcode_t instr
)
1100 arg_mode_t am
= INIT_ARG_MODE
;
1103 const struct pcode_type
*tr
= NULL
; /* avoid warning */
1104 const struct pcode_type
*ts
= NULL
; /* avoid warning */
1105 pcode_t call_mode
= 0; /* avoid warning */
1106 pcode_t src_fn
= 0; /* avoid warning */
1107 bool src_deref
= false; /* avoid warning */
1110 pcode_t n_arguments
, n_real_arguments
;
1111 arg_t n_return_values
, n_real_return_values
;
1112 size_t fn_idx
= 0; /* avoid warning */
1113 pcode_position_save_t saved
;
1114 const struct pcode_type
**rets
= NULL
;
1117 if (instr
== P_Load_Fn
|| instr
== P_Curry
) {
1118 res
= u_pcode_get();
1119 if (unlikely(var_elided(res
))) {
1122 tr
= get_var_type(ctx
, res
);
1123 get_arg_mode(am
, tr
->slot
);
1125 n_return_values
= 0; /* avoid warning */
1126 } else if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1127 call_mode
= u_pcode_get();
1129 n_return_values
= (arg_t
)q
;
1130 if (unlikely(q
!= (pcode_t
)n_return_values
))
1131 goto exception_overflow
;
1133 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1137 n_arguments
= (arg_t
)q
;
1138 if (unlikely(q
!= (pcode_t
)n_arguments
))
1139 goto exception_overflow
;
1140 if (instr
== P_Load_Fn
|| instr
== P_Call
) {
1142 if (instr
== P_Load_Fn
)
1143 u_pcode_get(); /* call mode */
1144 ptr
= pcode_module_load_function(ctx
);
1147 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, true);
1148 if (unlikely(fn_idx
== no_function_idx
))
1150 get_arg_mode(am
, fn_idx
);
1151 src_deref
= false; /* avoid warning */
1152 src_fn
= ~sign_bit(pcode_t
); /* avoid warning */
1154 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1155 pcode_get_var_deref(&src_fn
, &src_deref
);
1158 pcode_position_save(ctx
, &saved
);
1160 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1163 n_real_return_values
= 0;
1164 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1165 for (ai
= 0; ai
< n_return_values
; ai
++) {
1167 if (unlikely(var_elided(q
)))
1169 n_real_return_values
++;
1171 if (!n_real_return_values
)
1173 get_arg_mode(am
, n_return_values
);
1175 pcode_position_restore(ctx
, &saved
);
1177 if (unlikely(elide
)) {
1178 /* TODO: remove the function from local directory if we just added it */
1180 if (unlikely(!pcode_free(ctx
, src_fn
)))
1183 pcode_dereference_arguments(ctx
, n_arguments
);
1188 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1189 ts
= get_var_type(ctx
, src_fn
);
1190 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
));
1191 get_arg_mode(am
, ts
->slot
);
1192 fn_idx
= no_function_idx
; /* avoid warning */
1195 code
= 0; /* avoid warning */
1198 code
= OPCODE_LOAD_FN
;
1201 code
= OPCODE_CURRY
;
1204 switch (call_mode
) {
1205 case Call_Mode_Unspecified
:
1206 case Call_Mode_Normal
:
1209 case Call_Mode_Strict
:
1210 case Call_Mode_Inline
:
1211 code
= OPCODE_CALL_STRICT
;
1213 case Call_Mode_Spark
:
1214 code
= OPCODE_CALL_SPARK
;
1216 case Call_Mode_Lazy
:
1217 code
= OPCODE_CALL_LAZY
;
1219 case Call_Mode_Cache
:
1220 code
= OPCODE_CALL_CACHE
;
1222 case Call_Mode_Save
:
1223 code
= OPCODE_CALL_SAVE
;
1226 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1229 case P_Call_Indirect
:
1230 switch (call_mode
) {
1231 case Call_Mode_Unspecified
:
1232 case Call_Mode_Normal
:
1233 code
= OPCODE_CALL_INDIRECT
;
1235 case Call_Mode_Strict
:
1236 case Call_Mode_Inline
:
1237 code
= OPCODE_CALL_INDIRECT_STRICT
;
1239 case Call_Mode_Spark
:
1240 code
= OPCODE_CALL_INDIRECT_SPARK
;
1242 case Call_Mode_Lazy
:
1243 code
= OPCODE_CALL_INDIRECT_LAZY
;
1245 case Call_Mode_Cache
:
1246 code
= OPCODE_CALL_INDIRECT_CACHE
;
1248 case Call_Mode_Save
:
1249 code
= OPCODE_CALL_INDIRECT_SAVE
;
1252 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1256 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1259 code
+= am
* OPCODE_MODE_MULT
;
1261 if (instr
== P_Load_Fn
|| instr
== P_Curry
)
1262 gen_am_two(am
, n_real_arguments
, tr
->slot
);
1264 gen_am_two(am
, n_real_arguments
, n_real_return_values
);
1265 if (instr
== P_Load_Fn
|| instr
== P_Call
)
1268 gen_am_two(am
, ts
->slot
, src_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1270 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1273 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1274 if (unlikely(!array_init_mayfail(const struct pcode_type
*, &rets
, &rets_l
, ctx
->err
)))
1276 for (ai
= 0; ai
< n_return_values
; ai
++) {
1277 const struct pcode_type
*tv
;
1279 if (unlikely(var_elided(q
)))
1281 tv
= get_var_type(ctx
, q
);
1282 if (unlikely(!array_add_mayfail(const struct pcode_type
*, &rets
, &rets_l
, tv
, NULL
, ctx
->err
)))
1285 if (unlikely(!pcode_finish_call(ctx
, rets
, rets_l
, false)))
1294 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1301 ctx
->pcode
= ctx
->pcode_instr_end
;
1305 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
)
1308 struct module_designator
*md
= NULL
;
1309 struct function_designator
*fd
= NULL
;
1316 switch (t1
->extra_type
? t1
->extra_type
: tr
->extra_type
) {
1317 case T_SInt128
: module
= "private/long"; fn
= 0 * Op_N
; break;
1318 case T_UInt128
: module
= "private/long"; fn
= 1 * Op_N
; break;
1319 case T_Real16
: module
= "private/longreal"; fn
= 0 * Op_N
; break;
1320 case T_Real32
: module
= "private/longreal"; fn
= 1 * Op_N
; break;
1321 case T_Real64
: module
= "private/longreal"; fn
= 2 * Op_N
; break;
1322 case T_Real80
: module
= "private/longreal"; fn
= 3 * Op_N
; break;
1323 case T_Real128
: module
= "private/longreal"; fn
= 4 * Op_N
; break;
1325 internal(file_line
, "pcode_op_to_call: type %d, %d", t1
->extra_type
, tr
->extra_type
);
1329 md
= module_designator_alloc(0, cast_ptr(const uint8_t *, module
), strlen(module
), false, ctx
->err
);
1332 fd
= function_designator_alloc_single(fn
, ctx
->err
);
1335 ptr
= module_load_function(md
, fd
, false, ctx
->err
);
1338 module_designator_free(md
), md
= NULL
;
1339 function_designator_free(fd
), fd
= NULL
;
1340 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, !preload
);
1341 if (unlikely(fn_idx
== no_function_idx
))
1348 get_arg_mode(am
, fn_idx
);
1349 get_arg_mode(am
, t1
->slot
);
1351 get_arg_mode(am
, t2
->slot
);
1353 code
= OPCODE_CALL
+ am
* OPCODE_MODE_MULT
;
1355 gen_am_two(am
, t2
? 2 : 1, 1);
1357 gen_am_two(am
, t1
->slot
, flags1
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1359 gen_am_two(am
, t2
->slot
, flags2
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1361 if (unlikely(!pcode_finish_call(ctx
, &tr
, 1, true)))
1368 module_designator_free(md
);
1370 function_designator_free(fd
);
1376 while ((size_t)(pos) >= 8 * *blob_len) \
1377 if (unlikely(!array_add_mayfail(uint8_t, blob, blob_len, 0, NULL, err)))\
1384 (*blob)[(pos) >> 3] |= 1U << ((pos) & 7); \
1387 #define re(n, rtype, ntype, pack, unpack) \
1388 static bool cat(pcode_generate_,rtype)(ntype val, uint8_t **blob, size_t *blob_len, ajla_error_t *err)\
1390 int ex_bits, sig_bits; \
1391 int min_exp, max_exp, e; \
1395 case 0: ex_bits = 5; sig_bits = 11; break; \
1396 case 1: ex_bits = 8; sig_bits = 24; break; \
1397 case 2: ex_bits = 11; sig_bits = 53; break; \
1398 case 3: ex_bits = 15; sig_bits = 64; break; \
1399 case 4: ex_bits = 15; sig_bits = 113; break; \
1400 default: internal(file_line, "invalid real type %d", n);\
1402 min_exp = -(1 << (ex_bits - 1)) - sig_bits + 3; \
1403 max_exp = (1 << (ex_bits - 1)) - sig_bits + 2; \
1404 if (unlikely(cat(isnan_,ntype)(val))) { \
1405 fatal_mayfail(error_ajla(EC_SYNC, AJLA_ERROR_NAN), err, "NaN");\
1408 if (unlikely(val == 0)) { \
1409 if (unlikely(1. / val < 0)) \
1414 if (unlikely(val < 0)) { \
1418 if (unlikely(!cat(isfinite_,ntype)(val))) { \
1423 norm = cat(mathfunc_,ntype)(frexp)(val, &e); \
1425 pos = sig_bits - 1; \
1426 if (e < min_exp) { \
1427 pos -= min_exp - e; \
1430 while (pos >= 0) { \
1440 pos = sig_bits + 1; \
1441 while (e && e != -1) { \
1456 } while (pos & 7); \
1459 for_all_real(re
, for_all_empty
)
1464 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
)
1470 const struct type
*type
;
1472 type
= pcode_to_type(NULL
, pcode_type
, err
);
1473 if (unlikely(!type
))
1476 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &blob_len
, err
)))
1478 #define emit_byte(b) \
1480 if (unlikely(!array_add_mayfail(uint8_t, &blob, &blob_len, b, NULL, err)))\
1484 d
= pointer_get_data(ptr
);
1485 if (likely(da_tag(d
) == DATA_TAG_flat
)) {
1489 switch (type
->tag
) {
1490 #define fx(n, type, utype, sz, bits) \
1491 case TYPE_TAG_integer + n: \
1492 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_signed:\
1493 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_unsigned:\
1494 negative = *cast_ptr(type *, da_flat(d)) < 0;\
1495 value = *cast_ptr(type *, da_flat(d)); \
1498 #define re(n, rtype, ntype, pack, unpack) \
1499 case TYPE_TAG_real + n: { \
1500 if (unlikely(!cat(pcode_generate_,rtype)(unpack(*cast_ptr(rtype *, da_flat(d))), &blob, &blob_len, err)))\
1502 goto process_real; \
1505 for_all_real(re
, for_all_empty
);
1507 internal(file_line
, "pcode_generate_blob_from_value: invalid type tag %u", type
->tag
);
1514 for (i
= 0; i
< size
; i
++) {
1518 sign
= blob_len
&& blob
[blob_len
- 1] & 0x80;
1519 if (unlikely(sign
!= negative
))
1520 emit_byte(negative
? 0xff : 0x00);
1522 while (blob_len
>= 2 && blob
[blob_len
- 1] == (negative
? 0xff : 0x00) && (blob
[blob_len
- 2] & 0x80) == (negative
? 0x80 : 0x00))
1525 if (blob_len
== 1 && !blob
[0])
1528 } else if (unlikely(da_tag(d
) == DATA_TAG_longint
)) {
1530 if (unlikely(!mpint_export_to_blob(&da(d
,longint
)->mp
, &blob
, &blob_len
, err
)))
1532 } else if (likely(da_tag(d
) == DATA_TAG_option
)) {
1534 ajla_assert_lo(pointer_is_empty(da(d
,option
)->pointer
), (file_line
, "pcode_generate_blob_from_value: non-empty option"));
1535 opt
= da(d
,option
)->option
;
1537 emit_byte(opt
& 0xff);
1538 while ((opt
>>= 8));
1540 internal(file_line
, "pcode_generate_blob_from_value: invalid data tag %u", da_tag(d
));
1546 if (unlikely(!pcode_generate_blob(blob
, blob_len
, res_blob
, res_len
, err
))) {
1558 #define test(bit) ((size_t)(bit) < 8 * dl ? (d[(bit) >> 3] >> ((bit) & 7)) & 1 : dl ? d[dl - 1] >> 7 : 0)
1560 #define re(n, rtype, ntype, pack, unpack) \
1561 static inline rtype cat(strto_,rtype)(const unsigned char *d, size_t dl)\
1563 int ex_bits, sig_bits; \
1569 case 0: ex_bits = 5; sig_bits = 11; break; \
1570 case 1: ex_bits = 8; sig_bits = 24; break; \
1571 case 2: ex_bits = 11; sig_bits = 53; break; \
1572 case 3: ex_bits = 15; sig_bits = 64; break; \
1573 case 4: ex_bits = 15; sig_bits = 113; break; \
1574 default: internal(file_line, "invalid real type %d", n);\
1578 for (i = 0; i < ex_bits + 1; i++) { \
1579 b = test(sig_bits + 1 + i); \
1580 ex |= (int)b << i; \
1585 for (i = 0; i < sig_bits; i++) { \
1587 val += cat(mathfunc_,ntype)(ldexp)(1, ex + i); \
1590 if (test(sig_bits)) \
1594 for_all_real(re
, for_all_empty
)
1597 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
)
1599 switch (type
->tag
) {
1600 #define re(n, rtype, ntype, pack, unpack) \
1601 case TYPE_TAG_real + n: { \
1602 rtype val = cat(strto_,rtype)((const unsigned char *)blob, blob_l);\
1603 *result_len = round_up(sizeof(rtype), sizeof(code_t)) / sizeof(code_t);\
1604 if (unlikely(!(*result = mem_alloc_array_mayfail(mem_calloc_mayfail, code_t *, 0, 0, *result_len, sizeof(code_t), ctx->err))))\
1606 memcpy(*result, &val, sizeof(rtype)); \
1609 for_all_real(re
, for_all_empty
);
1611 internal(file_line
, "pcode_decode_real(%s): invalid type tag %u", function_name(ctx
), type
->tag
);
1621 static bool pcode_generate_constant_from_blob(struct build_function_context
*ctx
, pcode_t res
, uint8_t *blob
, size_t l
)
1623 const struct pcode_type
*pt
;
1624 bool is_emulated_fixed_8
, is_emulated_fixed_16
;
1625 const struct type
*type
;
1627 code_t
*raw_result
= NULL
;
1629 size_t requested_size
;
1636 pt
= get_var_type(ctx
, res
);
1638 is_emulated_fixed_8
= pt
->extra_type
== T_SInt64
|| pt
->extra_type
== T_UInt64
;
1639 is_emulated_fixed_16
= pt
->extra_type
== T_SInt128
|| pt
->extra_type
== T_UInt128
;
1643 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1644 if (TYPE_TAG_FIXED_IS_UNSIGNED(type
->tag
) && l
== (size_t)type
->size
+ 1 && blob
[l
- 1] == 0x00)
1646 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
));
1647 if (l
<= sizeof(code_t
))
1648 requested_size
= sizeof(code_t
);
1650 requested_size
= round_up(type
->size
, sizeof(code_t
));
1651 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1652 if (is_emulated_fixed_8
&& l
&& blob
[l
- 1] & 0x80)
1654 else if (is_emulated_fixed_16
&& l
&& blob
[l
- 1] & 0x80)
1655 requested_size
= 16;
1656 else if (l
<= sizeof(code_t
))
1657 requested_size
= sizeof(code_t
);
1658 else if (l
<= type
->size
)
1659 requested_size
= round_up(type
->size
, sizeof(code_t
));
1661 requested_size
= round_up(l
, sizeof(code_t
));
1662 } else if (TYPE_TAG_IS_REAL(type
->tag
)) {
1663 if (!unlikely(pcode_decode_real(ctx
, type
, cast_ptr(const char *, blob
), l
, &raw_result
, &requested_size
)))
1666 internal(file_line
, "pcode_generate_constant_from_blob(%s): unknown type %u", function_name(ctx
), type
->tag
);
1669 if (likely(!raw_result
)) {
1670 while (l
< requested_size
) {
1671 uint8_t c
= !l
? 0 : !(blob
[l
- 1] & 0x80) ? 0 : 0xff;
1672 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, c
, NULL
, ctx
->err
)))
1677 code
= get_code(Op_Ldc
, type
);
1678 const_swap
= !!CODE_ENDIAN
;
1680 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1681 if (requested_size
< type
->size
)
1682 code
+= (OPCODE_FIXED_OP_ldc16
- OPCODE_FIXED_OP_ldc
) * OPCODE_FIXED_OP_MULT
;
1683 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1684 if ((is_emulated_fixed_8
|| is_emulated_fixed_16
) && l
&& blob
[l
- 1] & 0x80) {
1685 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, 0, NULL
, ctx
->err
)))
1687 code
= OPCODE_INT_LDC_LONG
;
1688 } else if (requested_size
< type
->size
) {
1689 code
+= (OPCODE_INT_OP_ldc16
- OPCODE_INT_OP_ldc
) * OPCODE_INT_OP_MULT
;
1690 } else if (requested_size
> type
->size
&& orig_l
> type
->size
) {
1691 code
= OPCODE_INT_LDC_LONG
;
1696 get_arg_mode(am
, pt
->slot
);
1698 gen_code(code
+ am
* OPCODE_MODE_MULT
);
1699 gen_am(am
, pt
->slot
);
1700 if (unlikely(code
== OPCODE_INT_LDC_LONG
)) {
1701 gen_uint32(l
/ sizeof(code_t
));
1702 /*debug("load long constant: %zu (%d)", l, type->tag);*/
1704 if (unlikely(raw_result
!= NULL
)) {
1706 for (idx
= 0; idx
< requested_size
; idx
++)
1707 gen_code(raw_result
[idx
]);
1708 } else for (is
= 0; is
< l
; is
+= sizeof(code_t
)) {
1709 size_t idx
= !const_swap
? is
: l
- sizeof(code_t
) - is
;
1710 gen_code(blob
[idx
] + (blob
[idx
+ 1] << 8));
1713 mem_free(blob
), blob
= NULL
;
1714 if (unlikely(raw_result
!= NULL
))
1715 mem_free(raw_result
);
1723 mem_free(raw_result
);
1727 static bool pcode_generate_constant(struct build_function_context
*ctx
, pcode_t res
, int_default_t val
)
1731 uint_default_t uval
= (uint_default_t
)val
;
1733 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &l
, ctx
->err
)))
1737 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, (uint8_t)uval
, NULL
, ctx
->err
)))
1742 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1745 static bool pcode_generate_option_from_blob(struct build_function_context
*ctx
, const struct pcode_type
*tr
, uint8_t *blob
, size_t l
)
1753 for (i
= 0; i
< l
; i
++) {
1754 ajla_option_t o
= (ajla_option_t
)blob
[i
];
1755 opt
|= o
<< (i
* 8);
1756 if (unlikely(opt
>> (i
* 8) != o
))
1757 goto exception_overflow
;
1761 get_arg_mode(am
, tr
->slot
);
1762 if (likely(opt
== (ajla_option_t
)(ajla_flat_option_t
)opt
) && tr
->type
->tag
== TYPE_TAG_flat_option
) {
1763 code
= OPCODE_OPTION_CREATE_EMPTY_FLAT
;
1765 code
= OPCODE_OPTION_CREATE_EMPTY
;
1767 code
+= am
* OPCODE_MODE_MULT
;
1769 gen_am_two(am
, tr
->slot
, opt
);
1775 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1781 static bool pcode_load_constant(struct build_function_context
*ctx
)
1786 const struct pcode_type
*tr
;
1788 res
= u_pcode_get();
1789 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
1792 if (var_elided(res
)) {
1797 tr
= get_var_type(ctx
, res
);
1799 if (tr
->type
->tag
== TYPE_TAG_flat_option
|| tr
->type
->tag
== TYPE_TAG_unknown
) {
1800 return pcode_generate_option_from_blob(ctx
, tr
, blob
, l
);
1802 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1806 static bool pcode_structured_loop(struct build_function_context
*ctx
, pcode_t n_steps
, code_t extra_flags
, arg_mode_t
*am
, bool gen
)
1811 if (i
== n_steps
- 1)
1812 extra_flags
|= OPCODE_STRUCTURED_FLAG_END
;
1816 case Structured_Record
: {
1818 pcode_t rec_local
, q
, type_idx
;
1819 const struct record_definition
*def
;
1822 rec_local
= u_pcode_get();
1826 if (unlikely(q
!= (pcode_t
)idx
))
1827 goto exception_overflow
;
1829 def
= type_def(pcode_to_type(ctx
, rec_local
, NULL
),record
);
1831 if (record_definition_is_elided(def
, idx
)) {
1832 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided record entry in the second pass", function_name(ctx
)));
1836 type_idx
= pcode_to_type_index(ctx
, rec_local
, false);
1837 if (unlikely(type_idx
== error_type_index
))
1840 slot
= record_definition_slot(def
, idx
);
1842 get_arg_mode(*am
, slot
);
1843 get_arg_mode(*am
, type_idx
);
1845 gen_am_two(*am
, OPCODE_STRUCTURED_RECORD
| extra_flags
, slot
);
1846 gen_am(*am
, type_idx
);
1850 case Structured_Option
: {
1855 opt
= (ajla_option_t
)q
;
1856 if (unlikely(q
!= (pcode_t
)opt
))
1857 goto exception_overflow
;
1860 get_arg_mode(*am
, opt
);
1862 gen_am_two(*am
, OPCODE_STRUCTURED_OPTION
| extra_flags
, opt
);
1867 case Structured_Array
: {
1868 pcode_t var
, local_type
, local_idx
;
1869 const struct pcode_type
*var_type
;
1871 var
= u_pcode_get();
1873 local_type
= pcode_get();
1875 if (var_elided(var
)) {
1876 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided array index in the second pass", function_name(ctx
)));
1880 var_type
= get_var_type(ctx
, var
);
1881 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
));
1883 local_idx
= pcode_to_type_index(ctx
, local_type
, false);
1884 if (unlikely(local_idx
== error_type_index
))
1888 get_arg_mode(*am
, var_type
->slot
);
1889 get_arg_mode(*am
, local_idx
);
1891 gen_am_two(*am
, OPCODE_STRUCTURED_ARRAY
| extra_flags
, var_type
->slot
);
1892 gen_am(*am
, local_idx
);
1897 internal(file_line
, "pcode_structured_loop(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (uintmax_t)type
);
1899 } while (++i
< n_steps
);
1904 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1909 static bool pcode_structured_write(struct build_function_context
*ctx
)
1911 pcode_t structured
, scalar
, n_steps
;
1913 pcode_t structured_source
= 0; /* avoid warning */
1914 bool structured_source_deref
= false; /* avoid warning */
1915 const struct pcode_type
*structured_type
, *scalar_type
;
1916 code_t extra_flags
= 0;
1917 arg_mode_t am
= INIT_ARG_MODE
;
1919 pcode_position_save_t saved
;
1921 n_steps
= u_pcode_get();
1922 ajla_assert_lo(n_steps
!= 0, (file_line
, "pcode_structured_write(%s): zero n_steps", function_name(ctx
)));
1923 structured
= u_pcode_get();
1924 pcode_get_var_deref(&structured_source
, &structured_source_deref
);
1925 pcode_get_var_deref(&scalar
, &scalar_deref
);
1927 extra_flags
|= OPCODE_STRUCTURED_FREE_VARIABLE
;
1929 pcode_position_save(ctx
, &saved
);
1931 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, false))
1934 if (unlikely(var_elided(structured
)) || unlikely(var_elided(scalar
)))
1937 pcode_position_restore(ctx
, &saved
);
1939 if (!pcode_copy(ctx
, false, structured
, structured_source
, structured_source_deref
))
1942 structured_type
= get_var_type(ctx
, structured
);
1943 scalar_type
= get_var_type(ctx
, scalar
);
1944 get_arg_mode(am
, structured_type
->slot
);
1945 get_arg_mode(am
, scalar_type
->slot
);
1947 gen_code(OPCODE_STRUCTURED
+ am
* OPCODE_MODE_MULT
);
1948 gen_am_two(am
, structured_type
->slot
, scalar_type
->slot
);
1950 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, true))
1959 static bool pcode_record_create(struct build_function_context
*ctx
)
1962 pcode_position_save_t saved
;
1963 pcode_t n_arguments
, n_real_arguments
;
1964 const struct pcode_type
*tr
;
1965 arg_mode_t am
= INIT_ARG_MODE
;
1967 result
= u_pcode_get();
1969 n_arguments
= (arg_t
)q
;
1970 if (unlikely(q
!= (pcode_t
)n_arguments
))
1971 goto exception_overflow
;
1973 pcode_position_save(ctx
, &saved
);
1975 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1978 pcode_position_restore(ctx
, &saved
);
1980 if (unlikely(var_elided(result
))) {
1981 pcode_dereference_arguments(ctx
, n_arguments
);
1985 tr
= get_var_type(ctx
, result
);
1986 get_arg_mode(am
, tr
->slot
);
1988 gen_code(OPCODE_RECORD_CREATE
+ am
* OPCODE_MODE_MULT
);
1989 gen_am_two(am
, tr
->slot
, n_real_arguments
);
1991 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1997 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
2002 static bool pcode_array_create(struct build_function_context
*ctx
)
2004 pcode_t result
, local_type
, length
, n_real_arguments
;
2005 pcode_position_save_t saved
;
2006 const struct pcode_type
*tr
;
2007 arg_mode_t am
= INIT_ARG_MODE
;
2009 result
= u_pcode_get();
2010 local_type
= pcode_get();
2011 length
= u_pcode_get();
2014 pcode_position_save(ctx
, &saved
);
2016 if (unlikely(!pcode_process_arguments(ctx
, length
, &n_real_arguments
, &am
)))
2019 pcode_position_restore(ctx
, &saved
);
2021 if (unlikely(var_elided(result
))) {
2022 pcode_dereference_arguments(ctx
, length
);
2026 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
));
2028 tr
= get_var_type(ctx
, result
);
2029 get_arg_mode(am
, tr
->slot
);
2032 pcode_t type_idx
= pcode_to_type_index(ctx
, local_type
, true);
2033 if (unlikely(type_idx
== error_type_index
))
2035 if (type_idx
== no_type_index
) {
2036 gen_code(OPCODE_ARRAY_CREATE_EMPTY
+ am
* OPCODE_MODE_MULT
);
2037 gen_am(am
, tr
->slot
);
2039 get_arg_mode(am
, type_idx
);
2040 gen_code(OPCODE_ARRAY_CREATE_EMPTY_FLAT
+ am
* OPCODE_MODE_MULT
);
2041 gen_am_two(am
, tr
->slot
, type_idx
);
2044 get_arg_mode(am
, length
);
2045 gen_code(OPCODE_ARRAY_CREATE
+ am
* OPCODE_MODE_MULT
);
2046 gen_am_two(am
, tr
->slot
, length
);
2047 if (unlikely(!pcode_process_arguments(ctx
, length
, NULL
, &am
)))
2057 static bool pcode_array_string(struct build_function_context
*ctx
)
2062 const struct pcode_type
*tr
;
2063 arg_mode_t am
= INIT_ARG_MODE
;
2065 result
= u_pcode_get();
2067 if (!pcode_load_blob(ctx
, &blob
, &blob_len
))
2069 if (likely(var_elided(result
))) {
2074 tr
= get_var_type(ctx
, result
);
2075 get_arg_mode(am
, tr
->slot
);
2076 get_arg_mode(am
, blob_len
);
2077 gen_code(OPCODE_ARRAY_STRING
+ am
* OPCODE_MODE_MULT
);
2078 gen_am_two(am
, tr
->slot
, blob_len
);
2079 for (i
= 0; i
< blob_len
; i
+= 2) {
2085 u
.b
[1] = i
+ 1 < blob_len
? blob
[i
+ 1] : 0;
2097 static bool pcode_array_unicode(struct build_function_context
*ctx
)
2101 const struct pcode_type
*tr
;
2102 arg_mode_t am
= INIT_ARG_MODE
;
2104 result
= u_pcode_get();
2106 len
= ctx
->pcode_instr_end
- ctx
->pcode
;
2108 tr
= get_var_type(ctx
, result
);
2109 get_arg_mode(am
, tr
->slot
);
2110 get_arg_mode(am
, len
);
2111 gen_code(OPCODE_ARRAY_UNICODE
+ am
* OPCODE_MODE_MULT
);
2112 gen_am_two(am
, tr
->slot
, len
);
2113 for (i
= 0; i
< len
; i
++) {
2129 static bool pcode_io(struct build_function_context
*ctx
)
2131 pcode_t io_type
, n_outputs
, n_inputs
, n_params
;
2133 bool elided
= false;
2134 code_position_save_t saved
;
2136 code_position_save(ctx
, &saved
);
2138 io_type
= u_pcode_get();
2139 n_outputs
= u_pcode_get();
2140 n_inputs
= u_pcode_get();
2141 n_params
= u_pcode_get();
2143 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
));
2145 gen_code(OPCODE_IO
);
2146 gen_code(io_type
| (n_outputs
<< 8));
2147 gen_code(n_inputs
| (n_params
<< 8));
2149 for (pass
= 0; pass
< 3; pass
++) {
2151 if (!pass
) val
= n_outputs
;
2152 else if (pass
== 1) val
= n_inputs
;
2153 else val
= n_params
;
2156 pcode_t var
= pcode_get();
2157 if (!pass
&& var_elided(var
))
2161 const struct pcode_type
*t1
;
2162 t1
= get_var_type(ctx
, var
);
2163 gen_uint32(t1
->slot
);
2172 code_position_restore(ctx
, &saved
);
2181 static bool pcode_args(struct build_function_context
*ctx
)
2183 const struct pcode_type
*tr
;
2186 ajla_assert_lo(!ctx
->args
, (file_line
, "pcode_args(%s): args already specified", function_name(ctx
)));
2188 ctx
->args
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct local_arg
*, 0, 0, ctx
->n_arguments
, sizeof(struct local_arg
), ctx
->err
);
2189 if (unlikely(!ctx
->args
))
2192 for (i
= 0, vv
= 0; i
< ctx
->n_arguments
; i
++) {
2193 pcode_t res
= pcode_get();
2194 if (unlikely(var_elided(res
)))
2196 tr
= get_var_type(ctx
, res
);
2197 ctx
->args
[vv
].slot
= tr
->slot
;
2198 ctx
->args
[vv
].may_be_borrowed
= !TYPE_IS_FLAT(tr
->type
);
2199 ctx
->args
[vv
].may_be_flat
= TYPE_IS_FLAT(tr
->type
);
2200 ctx
->pcode_types
[res
].argument
= &ctx
->args
[vv
];
2201 ctx
->colors
[tr
->color
].is_argument
= true;
2202 if (!TYPE_IS_FLAT(tr
->type
))
2203 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2206 ctx
->n_real_arguments
= vv
;
2212 struct pcode_return_struct
{
2217 static bool pcode_return(struct build_function_context
*ctx
)
2219 arg_mode_t am
= INIT_ARG_MODE
;
2221 struct pcode_return_struct
*prs
;
2223 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
);
2227 for (i
= 0, vv
= 0; i
< ctx
->n_return_values
; i
++) {
2228 const struct pcode_type
*tr
;
2229 pcode_t flags
= u_pcode_get();
2230 pcode_t res
= pcode_get();
2231 prs
[i
].flags
= flags
;
2233 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2235 tr
= get_var_type(ctx
, res
);
2236 get_arg_mode(am
, tr
->slot
);
2240 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
));
2242 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2243 if (unlikely((prs
[i
].flags
& (Flag_Free_Argument
| Flag_Return_Elided
)) == (Flag_Free_Argument
| Flag_Return_Elided
))) {
2245 arg_t q
= (arg_t
)-1;
2246 for (j
= 0; j
< i
; j
++)
2247 if (prs
[j
].res
== prs
[i
].res
&& !(prs
[j
].flags
& Flag_Return_Elided
))
2249 if (q
!= (arg_t
)-1) {
2250 prs
[q
].flags
|= Flag_Free_Argument
;
2252 if (!pcode_free(ctx
, prs
[i
].res
))
2255 prs
[i
].flags
&= ~Flag_Free_Argument
;
2259 gen_code(OPCODE_RETURN
+ am
* OPCODE_MODE_MULT
);
2261 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2262 unsigned code_flags
;
2263 const struct pcode_type
*tr
;
2264 pcode_t flags
= prs
[i
].flags
;
2265 pcode_t res
= prs
[i
].res
;
2266 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2268 tr
= get_var_type(ctx
, res
);
2270 if (flags
& Flag_Free_Argument
)
2271 code_flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
2272 gen_am_two(am
, tr
->slot
, code_flags
);
2284 static void pcode_get_instr(struct build_function_context
*ctx
, pcode_t
*instr
, pcode_t
*instr_params
)
2286 *instr
= u_pcode_get();
2287 *instr_params
= u_pcode_get();
2288 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
)));
2289 ctx
->pcode_instr_end
= ctx
->pcode
+ *instr_params
;
2293 static bool pcode_preload_ld(struct build_function_context
*ctx
)
2295 pcode_position_save_t saved
;
2297 pcode_position_save(ctx
, &saved
);
2298 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2299 pcode_t instr
, instr_params
;
2300 pcode_get_instr(ctx
, &instr
, &instr_params
);
2303 if (unlikely(!pcode_args(ctx
)))
2306 #if NEED_OP_EMULATION
2309 const struct pcode_type
*tr
, *t1
;
2310 pcode_t op
= u_pcode_get();
2311 pcode_t res
= u_pcode_get();
2312 pcode_t flags1
= u_pcode_get();
2313 pcode_t a1
= pcode_get();
2314 if (unlikely(var_elided(res
)))
2316 tr
= get_var_type(ctx
, res
);
2317 t1
= get_var_type(ctx
, a1
);
2318 if (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
)) {
2319 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, true)))
2330 ptr
= pcode_module_load_function(ctx
);
2333 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, false);
2334 if (unlikely(fn_idx
== no_function_idx
))
2339 ctx
->pcode
= ctx
->pcode_instr_end
;
2341 pcode_position_restore(ctx
, &saved
);
2349 static bool pcode_check_args(struct build_function_context
*ctx
)
2352 frame_t
*vars
= NULL
;
2356 vars
= mem_alloc_array_mayfail(mem_alloc_mayfail
, frame_t
*, 0, 0, ctx
->n_real_arguments
, sizeof(frame_t
), ctx
->err
);
2357 if (unlikely(!vars
))
2361 am
= INIT_ARG_MODE_1
;
2363 for (i
= 0; i
< ctx
->n_real_arguments
; i
++) {
2364 frame_t slot
= ctx
->args
[i
].slot
;
2365 if (ctx
->local_variables_flags
[slot
].must_be_flat
|| ctx
->local_variables_flags
[slot
].must_be_data
) {
2366 vars
[n_vars
++] = slot
;
2367 get_arg_mode(am
, slot
);
2373 get_arg_mode(am
, n_vars
);
2374 code
= OPCODE_ESCAPE_NONFLAT
;
2375 code
+= am
* OPCODE_MODE_MULT
;
2378 for (i
= 0; i
< n_vars
; i
++)
2379 gen_am(am
, vars
[i
]);
2393 static bool pcode_generate_instructions(struct build_function_context
*ctx
)
2395 if (unlikely(!gen_checkpoint(ctx
, NULL
, 0, false)))
2398 if (unlikely(!pcode_check_args(ctx
)))
2401 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2402 pcode_t instr
, instr_params
;
2403 pcode_get_instr(ctx
, &instr
, &instr_params
);
2405 pcode_t p
, op
, res
, a1
, a2
, aa
, flags
, flags1
, flags2
;
2406 const struct pcode_type
*tr
, *t1
, *t2
, *ta
;
2407 bool a1_deref
, a2_deref
;
2411 struct line_position lp
;
2412 struct record_definition
*def
;
2416 ajla_assert_lo(op
>= Op_N
|| Op_IsBinary(op
), (file_line
, "P_BinaryOp(%s): invalid binary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2417 res
= u_pcode_get();
2418 flags1
= u_pcode_get();
2420 flags2
= u_pcode_get();
2422 if (unlikely(var_elided(res
))) {
2423 if (flags1
& Flag_Free_Argument
)
2424 pcode_free(ctx
, a1
);
2425 if (flags2
& Flag_Free_Argument
)
2426 pcode_free(ctx
, a2
);
2429 tr
= get_var_type(ctx
, res
);
2430 t1
= get_var_type(ctx
, a1
);
2431 t2
= get_var_type(ctx
, a2
);
2432 ajla_assert_lo(op
>= Op_N
||
2433 (type_is_equal(t1
->type
, t2
->type
) &&
2434 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2435 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2436 : 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
));
2437 if (NEED_OP_EMULATION
&& unlikely(t1
->extra_type
)) {
2438 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, t2
, flags2
, false)))
2443 if (unlikely(flags1
& Flag_Op_Strict
) != 0)
2444 fflags
|= OPCODE_OP_FLAG_STRICT
;
2445 if (flags1
& Flag_Fused_Bin_Jmp
)
2446 fflags
|= OPCODE_FLAG_FUSED
;
2448 get_arg_mode(am
, t1
->slot
);
2449 get_arg_mode(am
, t2
->slot
);
2450 get_arg_mode(am
, tr
->slot
);
2451 code
= (code_t
)((likely(op
< Op_N
) ? get_code(op
, t1
->type
) : (code_t
)(op
- Op_N
)) + am
* OPCODE_MODE_MULT
);
2453 gen_am_two(am
, t1
->slot
, t2
->slot
);
2454 gen_am_two(am
, tr
->slot
, fflags
);
2455 if (flags1
& Flag_Free_Argument
) {
2456 if (t1
->slot
!= tr
->slot
)
2457 pcode_free(ctx
, a1
);
2459 if (flags2
& Flag_Free_Argument
) {
2460 if (t2
->slot
!= tr
->slot
)
2461 pcode_free(ctx
, a2
);
2466 ajla_assert_lo(op
>= Op_N
|| Op_IsUnary(op
), (file_line
, "P_UnaryOp(%s): invalid unary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2467 res
= u_pcode_get();
2468 flags1
= u_pcode_get();
2470 if (unlikely(var_elided(res
))) {
2471 if (flags1
& Flag_Free_Argument
)
2472 pcode_free(ctx
, a1
);
2475 tr
= get_var_type(ctx
, res
);
2476 t1
= get_var_type(ctx
, a1
);
2477 ajla_assert_lo(op
>= Op_N
|| op
== Un_ConvertFromInt
||
2478 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2479 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2480 : 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
));
2481 if (NEED_OP_EMULATION
&& (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
))) {
2482 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, false)))
2487 get_arg_mode(am
, t1
->slot
);
2488 get_arg_mode(am
, tr
->slot
);
2489 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
);
2491 gen_am_two(am
, t1
->slot
, tr
->slot
);
2492 gen_am(am
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2493 if (flags1
& Flag_Free_Argument
) {
2494 if (t1
->slot
!= tr
->slot
)
2495 pcode_free(ctx
, a1
);
2499 case P_Copy_Type_Cast
:
2500 res
= u_pcode_get();
2501 pcode_get_var_deref(&a1
, &a1_deref
);
2502 if (unlikely(var_elided(res
))) {
2504 if (unlikely(!pcode_free(ctx
, a1
)))
2509 if (unlikely(!pcode_copy(ctx
, instr
!= P_Copy
, res
, a1
, a1_deref
)))
2513 res
= u_pcode_get();
2514 if (unlikely(!pcode_free(ctx
, res
)))
2519 if (unlikely(var_elided(a1
)))
2521 t1
= get_var_type(ctx
, a1
);
2523 get_arg_mode(am
, t1
->slot
);
2525 code
+= am
* OPCODE_MODE_MULT
;
2527 gen_am(am
, t1
->slot
);
2533 res
= u_pcode_get();
2534 ajla_assert_lo(var_elided(res
), (file_line
, "P_Fn(%s): Fn result is not elided", function_name(ctx
)));
2537 for (p
= 0; p
< a1
; p
++)
2539 for (p
= 0; p
< a2
; p
++)
2542 case P_Load_Local_Type
:
2543 res
= u_pcode_get();
2544 ajla_assert_lo(var_elided(res
), (file_line
, "P_Load_Local_Type(%s): Load_Local_Type result is not elided", function_name(ctx
)));
2550 case P_Call_Indirect
:
2552 if (unlikely(!pcode_call(ctx
, instr
)))
2555 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
2556 pcode_t next
, next_params
;
2557 pcode_position_save_t s
;
2558 pcode_position_save(ctx
, &s
);
2560 pcode_get_instr(ctx
, &next
, &next_params
);
2561 if (next
== P_Line_Info
) {
2562 ctx
->pcode
= ctx
->pcode_instr_end
;
2565 pcode_position_restore(ctx
, &s
);
2566 //ajla_assert_lo(next == P_Checkpoint, (file_line, "%s: is followed by %"PRIdMAX"", instr == P_Call ? "P_Call" : "P_Call_Indirect", (intmax_t)next));
2568 ctx
->pcode_instr_end
= ctx
->pcode
;
2573 if (unlikely(!pcode_load_constant(ctx
)))
2576 case P_Structured_Write
:
2577 if (unlikely(!pcode_structured_write(ctx
)))
2582 for (p
= 0; p
< instr_params
; p
++)
2585 case P_Record_Create
:
2586 if (unlikely(!pcode_record_create(ctx
)))
2589 case P_Record_Load_Slot
:
2590 res
= u_pcode_get();
2593 tr
= get_var_type(ctx
, res
);
2594 t1
= get_var_type(ctx
, a1
);
2596 get_arg_mode(am
, tr
->slot
);
2597 get_arg_mode(am
, t1
->slot
);
2598 get_arg_mode(am
, op
);
2599 code
= OPCODE_RECORD_LOAD
;
2600 code
+= am
* OPCODE_MODE_MULT
;
2602 gen_am_two(am
, t1
->slot
, op
);
2603 gen_am_two(am
, tr
->slot
, OPCODE_OP_FLAG_STRICT
);
2606 res
= u_pcode_get();
2607 flags
= u_pcode_get();
2610 if (unlikely(var_elided(res
)))
2612 tr
= get_var_type(ctx
, res
);
2613 t1
= get_var_type(ctx
, a1
);
2614 if (TYPE_IS_FLAT(tr
->type
))
2615 flags
&= ~Flag_Borrow
;
2616 if (t1
->type
->tag
== TYPE_TAG_flat_record
) {
2617 def
= type_def(type_def(t1
->type
,flat_record
)->base
,record
);
2619 def
= type_def(t1
->type
,record
);
2621 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
));
2622 op
= record_definition_slot(def
, op
);
2624 get_arg_mode(am
, tr
->slot
);
2625 get_arg_mode(am
, t1
->slot
);
2626 get_arg_mode(am
, op
);
2627 code
= OPCODE_RECORD_LOAD
;
2628 code
+= am
* OPCODE_MODE_MULT
;
2630 gen_am_two(am
, t1
->slot
, op
);
2631 gen_am_two(am
, tr
->slot
,
2632 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2633 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2634 if (flags
& Flag_Borrow
)
2635 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2638 res
= u_pcode_get();
2639 flags
= u_pcode_get();
2642 if (unlikely(var_elided(res
)))
2644 tr
= get_var_type(ctx
, res
);
2645 t1
= get_var_type(ctx
, a1
);
2646 if (TYPE_IS_FLAT(tr
->type
))
2647 flags
&= ~Flag_Borrow
;
2649 get_arg_mode(am
, tr
->slot
);
2650 get_arg_mode(am
, t1
->slot
);
2651 get_arg_mode(am
, op
);
2652 code
= OPCODE_OPTION_LOAD
;
2653 code
+= am
* OPCODE_MODE_MULT
;
2655 gen_am_two(am
, t1
->slot
, op
);
2656 gen_am_two(am
, tr
->slot
,
2657 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2658 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2659 if (flags
& Flag_Borrow
)
2660 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2662 case P_Option_Create
:
2663 res
= u_pcode_get();
2665 pcode_get_var_deref(&a1
, &a1_deref
);
2666 if (unlikely(var_elided(res
))) {
2668 if (unlikely(!pcode_free(ctx
, a1
)))
2673 tr
= get_var_type(ctx
, res
);
2674 t1
= get_var_type(ctx
, a1
);
2675 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
));
2677 get_arg_mode(am
, tr
->slot
);
2678 get_arg_mode(am
, t1
->slot
);
2679 get_arg_mode(am
, op
);
2680 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2681 goto exception_overflow
;
2682 code
= OPCODE_OPTION_CREATE
;
2683 code
+= am
* OPCODE_MODE_MULT
;
2685 gen_am_two(am
, tr
->slot
, op
);
2686 gen_am_two(am
, t1
->slot
, a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
2689 res
= u_pcode_get();
2692 if (unlikely(var_elided(res
)))
2694 tr
= get_var_type(ctx
, res
);
2695 t1
= get_var_type(ctx
, a1
);
2696 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
));
2698 get_arg_mode(am
, tr
->slot
);
2699 get_arg_mode(am
, t1
->slot
);
2700 get_arg_mode(am
, op
);
2701 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2702 goto exception_overflow
;
2703 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2704 code
= OPCODE_OPTION_TEST_FLAT
;
2706 code
= OPCODE_OPTION_TEST
;
2707 code
+= am
* OPCODE_MODE_MULT
;
2709 gen_am_two(am
, t1
->slot
, op
);
2710 gen_am(am
, tr
->slot
);
2713 res
= u_pcode_get();
2715 if (unlikely(var_elided(res
)))
2717 tr
= get_var_type(ctx
, res
);
2718 t1
= get_var_type(ctx
, a1
);
2719 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
));
2721 get_arg_mode(am
, tr
->slot
);
2722 get_arg_mode(am
, t1
->slot
);
2723 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2724 code
= OPCODE_OPTION_ORD_FLAT
;
2726 code
= OPCODE_OPTION_ORD
;
2727 code
+= am
* OPCODE_MODE_MULT
;
2729 gen_am_two(am
, t1
->slot
, tr
->slot
);
2731 case P_Array_Flexible
:
2733 res
= u_pcode_get();
2734 ajla_assert_lo(var_elided(res
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible result is not elided", function_name(ctx
)));
2736 ajla_assert_lo(var_elided(a1
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible argument is not elided", function_name(ctx
)));
2737 if (instr
== P_Array_Fixed
)
2740 case P_Array_Create
:
2741 if (unlikely(!pcode_array_create(ctx
)))
2745 res
= u_pcode_get();
2746 pcode_get(); /* local type */
2748 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
));
2751 if (unlikely(var_elided(res
)))
2753 tr
= get_var_type(ctx
, res
);
2754 t1
= get_var_type(ctx
, a1
);
2755 t2
= get_var_type(ctx
, a2
);
2756 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
));
2758 get_arg_mode(am
, t1
->slot
);
2759 get_arg_mode(am
, t2
->slot
);
2760 get_arg_mode(am
, tr
->slot
);
2761 gen_code(OPCODE_ARRAY_FILL
+ am
* OPCODE_MODE_MULT
);
2762 gen_am_two(am
, t1
->slot
,
2763 ((op
& Flag_Free_Argument
) ? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2764 ((op
& Flag_Array_Fill_Sparse
) ? OPCODE_ARRAY_FILL_FLAG_SPARSE
: 0)
2766 gen_am_two(am
, t2
->slot
, tr
->slot
);
2768 case P_Array_String
:
2769 if (unlikely(!pcode_array_string(ctx
)))
2772 case P_Array_Unicode
:
2773 if (unlikely(!pcode_array_unicode(ctx
)))
2777 res
= u_pcode_get();
2778 flags
= u_pcode_get();
2781 if (unlikely(var_elided(res
)))
2783 tr
= get_var_type(ctx
, res
);
2784 t1
= get_var_type(ctx
, a1
);
2785 t2
= get_var_type(ctx
, a2
);
2786 if (TYPE_IS_FLAT(tr
->type
))
2787 flags
&= ~Flag_Borrow
;
2789 get_arg_mode(am
, tr
->slot
);
2790 get_arg_mode(am
, t1
->slot
);
2791 get_arg_mode(am
, t2
->slot
);
2792 code
= OPCODE_ARRAY_LOAD
;
2793 code
+= am
* OPCODE_MODE_MULT
;
2795 gen_am_two(am
, t1
->slot
, t2
->slot
);
2796 gen_am_two(am
, tr
->slot
,
2797 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2798 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0) |
2799 (flags
& Flag_Index_In_Range
? OPCODE_ARRAY_INDEX_IN_RANGE
: 0));
2800 if (flags
& Flag_Borrow
)
2801 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2804 res
= u_pcode_get();
2806 flags
= u_pcode_get();
2807 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2808 if (unlikely(var_elided(res
)))
2810 tr
= get_var_type(ctx
, res
);
2811 t1
= get_var_type(ctx
, a1
);
2812 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
));
2813 if (TYPE_IS_FLAT(t1
->type
)) {
2814 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
));
2815 if (unlikely(!pcode_generate_constant(ctx
, res
, (int_default_t
)type_def(t1
->type
,flat_array
)->n_elements
)))
2818 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
));
2820 get_arg_mode(am
, t1
->slot
);
2821 get_arg_mode(am
, tr
->slot
);
2822 gen_code(OPCODE_ARRAY_LEN
+ am
* OPCODE_MODE_MULT
);
2823 gen_am_two(am
, t1
->slot
, tr
->slot
);
2824 gen_am(am
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2827 case P_Array_Len_Greater_Than
:
2828 res
= u_pcode_get();
2831 flags
= u_pcode_get();
2832 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
));
2833 if (unlikely(var_elided(res
)))
2835 tr
= get_var_type(ctx
, res
);
2836 t1
= get_var_type(ctx
, a1
);
2837 t2
= get_var_type(ctx
, a2
);
2838 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
));
2839 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
));
2842 if (unlikely(flags
& Flag_Evaluate
) != 0)
2843 fflags
|= OPCODE_OP_FLAG_STRICT
;
2844 if (flags
& Flag_Fused_Bin_Jmp
)
2845 fflags
|= OPCODE_FLAG_FUSED
;
2847 get_arg_mode(am
, t1
->slot
);
2848 get_arg_mode(am
, t2
->slot
);
2849 get_arg_mode(am
, tr
->slot
);
2850 gen_code(OPCODE_ARRAY_LEN_GREATER_THAN
+ am
* OPCODE_MODE_MULT
);
2851 gen_am_two(am
, t1
->slot
, t2
->slot
);
2852 gen_am_two(am
, tr
->slot
, fflags
);
2855 res
= u_pcode_get();
2856 flags
= u_pcode_get();
2860 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Sub(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2861 if (unlikely(var_elided(res
)))
2863 tr
= get_var_type(ctx
, res
);
2864 ta
= get_var_type(ctx
, aa
);
2865 t1
= get_var_type(ctx
, a1
);
2866 t2
= get_var_type(ctx
, a2
);
2867 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
));
2868 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
));
2871 get_arg_mode(am
, ta
->slot
);
2872 get_arg_mode(am
, t1
->slot
);
2873 get_arg_mode(am
, t2
->slot
);
2874 get_arg_mode(am
, tr
->slot
);
2875 gen_code(OPCODE_ARRAY_SUB
+ am
* OPCODE_MODE_MULT
);
2876 gen_am_two(am
, ta
->slot
, t1
->slot
);
2877 gen_am_two(am
, t2
->slot
, tr
->slot
);
2879 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2880 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2884 res
= u_pcode_get();
2885 flags
= u_pcode_get();
2888 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Skip(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2889 if (unlikely(var_elided(res
)))
2891 tr
= get_var_type(ctx
, res
);
2892 ta
= get_var_type(ctx
, aa
);
2893 t1
= get_var_type(ctx
, a1
);
2894 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
));
2897 get_arg_mode(am
, ta
->slot
);
2898 get_arg_mode(am
, t1
->slot
);
2899 get_arg_mode(am
, tr
->slot
);
2900 gen_code(OPCODE_ARRAY_SKIP
+ am
* OPCODE_MODE_MULT
);
2901 gen_am_two(am
, ta
->slot
, t1
->slot
);
2902 gen_am_two(am
, tr
->slot
,
2903 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2904 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2907 case P_Array_Append
:
2908 case P_Array_Append_One
:
2909 res
= u_pcode_get();
2910 pcode_get_var_deref(&a1
, &a1_deref
);
2911 pcode_get_var_deref(&a2
, &a2_deref
);
2912 if (unlikely(var_elided(res
)))
2914 tr
= get_var_type(ctx
, res
);
2915 t1
= get_var_type(ctx
, a1
);
2916 t2
= get_var_type(ctx
, a2
);
2918 get_arg_mode(am
, tr
->slot
);
2919 get_arg_mode(am
, t1
->slot
);
2920 get_arg_mode(am
, t2
->slot
);
2921 if (instr
== P_Array_Append
) {
2922 gen_code(OPCODE_ARRAY_APPEND
+ am
* OPCODE_MODE_MULT
);
2924 if (TYPE_IS_FLAT(t2
->type
)) {
2925 gen_code(OPCODE_ARRAY_APPEND_ONE_FLAT
+ am
* OPCODE_MODE_MULT
);
2927 gen_code(OPCODE_ARRAY_APPEND_ONE
+ am
* OPCODE_MODE_MULT
);
2930 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0) | (a2_deref
? OPCODE_FLAG_FREE_ARGUMENT_2
: 0));
2931 gen_am_two(am
, t1
->slot
, t2
->slot
);
2933 case P_Array_Flatten
:
2934 res
= u_pcode_get();
2935 pcode_get_var_deref(&a1
, &a1_deref
);
2936 if (unlikely(var_elided(res
)))
2938 tr
= get_var_type(ctx
, res
);
2939 t1
= get_var_type(ctx
, a1
);
2941 get_arg_mode(am
, tr
->slot
);
2942 get_arg_mode(am
, t1
->slot
);
2943 gen_code(OPCODE_ARRAY_FLATTEN
+ am
* OPCODE_MODE_MULT
);
2944 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0));
2945 gen_am(am
, t1
->slot
);
2948 res
= u_pcode_get();
2949 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Jmp(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2951 if (ctx
->labels
[res
] != no_label
) {
2953 target
= (uint32_t)((ctx
->code_len
- ctx
->labels
[res
]) * sizeof(code_t
));
2954 if (likely(target
< 0x10000)) {
2955 gen_code(OPCODE_JMP_BACK_16
);
2956 gen_code((code_t
)target
);
2961 gen_code(OPCODE_JMP
);
2962 gen_relative_jump(res
, SIZEOF_IP_T
);
2966 tr
= get_var_type(ctx
, res
);
2967 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
));
2973 get_arg_mode(am
, tr
->slot
);
2974 code
= OPCODE_JMP_FALSE
+ am
* OPCODE_MODE_MULT
;
2976 gen_am(am
, tr
->slot
);
2977 gen_relative_jump(a1
, SIZEOF_IP_T
* 2);
2978 gen_relative_jump(a2
, SIZEOF_IP_T
);
2981 gen_code(OPCODE_LABEL
);
2982 res
= u_pcode_get();
2983 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Label(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2984 ajla_assert_lo(ctx
->labels
[res
] == no_label
, (file_line
, "P_Label(%s): label %"PRIdMAX
" already defined", function_name(ctx
), (intmax_t)res
));
2985 ctx
->labels
[res
] = ctx
->code_len
;
2988 if (unlikely(!pcode_io(ctx
)))
2992 ctx
->pcode
= ctx
->pcode_instr_end
;
2995 for (p
= 0; p
< instr_params
; p
++)
2999 if (unlikely(!pcode_return(ctx
)))
3003 if (unlikely(!gen_checkpoint(ctx
, ctx
->pcode
, instr_params
, true)))
3005 for (p
= 0; p
< instr_params
; p
++)
3009 lp
.line
= u_pcode_get();
3010 lp
.ip
= ctx
->code_len
;
3011 if (unlikely(!array_add_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, lp
, NULL
, ctx
->err
)))
3015 internal(file_line
, "pcode_generate_instructions(%s): invalid pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
3018 if (unlikely(ctx
->pcode
!= ctx
->pcode_instr_end
)) {
3023 for (pp
= ctx
->pcode_instr_end
- instr_params
- 2; pp
< ctx
->pcode
; pp
++) {
3024 str_add_char(&s
, &l
, ' ');
3025 str_add_signed(&s
, &l
, *pp
, 10);
3028 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
);
3031 if (unlikely(ctx
->code_len
> sign_bit(ip_t
) / sizeof(code_t
) + uzero
))
3032 goto exception_overflow
;
3036 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3041 static bool pcode_generate_record(struct build_function_context
*ctx
)
3045 struct record_definition
*def
;
3046 if (unlikely(!array_init_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, ctx
->err
)))
3049 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, slot_size
, data_record_offset
, ctx
->err
);
3050 if (unlikely(!ctx
->layout
))
3053 for (; ctx
->pcode
!= ctx
->pcode_limit
; ctx
->pcode
= ctx
->pcode_instr_end
) {
3054 pcode_t instr
, instr_params
;
3055 pcode_get_instr(ctx
, &instr
, &instr_params
);
3057 if (instr
== P_Load_Local_Type
) {
3058 pcode_t var
, fn_var
;
3059 pcode_t attr_unused idx
;
3060 const struct pcode_type
*p
;
3061 const struct type
*t
;
3063 ajla_assert_lo(instr_params
== 3, (file_line
, "pcode_generate_record(%s): invalid number of parameters %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr_params
));
3065 var
= u_pcode_get();
3066 fn_var
= pcode_get();
3067 idx
= u_pcode_get();
3068 if (unlikely(fn_var
!= -1))
3070 if (unlikely(var
!= (pcode_t
)(frame_t
)var
))
3071 goto exception_overflow
;
3072 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
));
3074 if (unlikely(!array_add_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, var
, NULL
, ctx
->err
)))
3077 if (var_elided(var
))
3080 p
= get_var_type(ctx
, var
);
3083 if (unlikely(!layout_add(ctx
->layout
, maximum(t
->size
, 1), t
->align
, ctx
->err
)))
3088 array_finish(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
);
3090 if (unlikely(ctx
->record_entries_len
!= (size_t)(arg_t
)ctx
->record_entries_len
))
3091 goto exception_overflow
;
3093 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3097 def
= type_alloc_record_definition(layout_size(ctx
->layout
), ctx
->err
);
3100 def
->n_slots
= layout_size(ctx
->layout
);
3101 def
->alignment
= maximum(layout_alignment(ctx
->layout
), frame_align
);
3102 def
->n_entries
= (arg_t
)ctx
->record_entries_len
;
3105 for (ai
= 0; ai
< ctx
->record_entries_len
; ai
++) {
3107 const struct pcode_type
*te
;
3108 var
= ctx
->record_entries
[ai
];
3109 if (var_elided((pcode_t
)var
)) {
3110 ctx
->record_entries
[ai
] = NO_FRAME_T
;
3113 slot
= layout_get(ctx
->layout
, layout_idx
++);
3114 ctx
->record_entries
[ai
] = slot
;
3115 te
= get_var_type(ctx
, (pcode_t
)var
);
3116 def
->types
[slot
] = te
->type
;
3119 def
->idx_to_frame
= ctx
->record_entries
, ctx
->record_entries
= NULL
;
3120 ctx
->record_definition
= def
;
3122 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3127 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3133 * pointer_empty -> ret_ex
3134 * poitner_mark -> err
3135 * other -> thunk(error) or data(function)
3137 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
)
3140 pcode_t p
, q
, subfns
;
3144 struct data
*ft
, *fn
;
3145 struct function_descriptor
*sfd
;
3148 #if defined(HAVE_CODEGEN)
3149 union internal_arg ia
[1];
3152 struct build_function_context ctx_
;
3153 struct build_function_context
*ctx
= &ctx_
;
3158 ctx
->pcode_limit
= pcode
+ size
;
3161 q
= u_pcode_get() & Fn_Mask
;
3162 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
));
3163 ctx
->function_type
= q
;
3165 u_pcode_get(); /* call mode - used by the optimizer */
3167 subfns
= u_pcode_get();
3169 ctx
->n_local_types
= u_pcode_get();
3172 ctx
->n_local_variables
= (frame_t
)q
;
3173 if (unlikely(q
!= (pcode_t
)ctx
->n_local_variables
))
3174 goto exception_overflow
;
3177 ctx
->n_arguments
= (arg_t
)q
;
3178 ajla_assert_lo(q
== (pcode_t
)ctx
->n_arguments
, (file_line
, "pcode_build_function_core: overflow in n_arguments"));
3181 ctx
->n_return_values
= (arg_t
)q
;
3182 ajla_assert_lo(q
== (pcode_t
)ctx
->n_return_values
, (file_line
, "pcode_build_function_core: overflow in n_return_values"));
3184 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"));
3187 ctx
->n_real_return_values
= (arg_t
)q
;
3188 ajla_assert_lo(ctx
->n_real_return_values
<= ctx
->n_return_values
, (file_line
, "pcode_build_function_core: invalid n_real_return_values"));
3190 ctx
->n_labels
= u_pcode_get();
3192 if (unlikely(!pcode_load_blob(ctx
, &ctx
->function_name
, &is
)))
3194 if (unlikely(!array_add_mayfail(uint8_t, &ctx
->function_name
, &is
, 0, NULL
, ctx
->err
)))
3196 array_finish(uint8_t, &ctx
->function_name
, &is
);
3204 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
);
3205 if (unlikely(!ctx
->local_types
))
3208 for (p
= 0; p
< ctx
->n_local_types
; p
++) {
3210 struct data
*rec_fn
;
3211 const struct record_definition
*def
;
3212 pcode_t base_idx
, n_elements
;
3213 struct type_entry
*flat_rec
;
3215 const struct type
*tt
, *tp
;
3219 case Local_Type_Record
:
3220 ptr
= pcode_module_load_function(ctx
);
3223 pointer_follow(ptr
, false, rec_fn
, PF_WAIT
, fp
, ip
,
3225 ctx
->ret_val
= pointer_empty();
3227 thunk_reference(thunk_
);
3228 ctx
->ret_val
= pointer_thunk(thunk_
);
3231 ajla_assert_lo(da(rec_fn
,function
)->record_definition
!= NULL
, (file_line
, "pcode_build_function_core(%s): record has no definition", function_name(ctx
)));
3232 def
= type_def(da(rec_fn
,function
)->record_definition
,record
);
3235 case Local_Type_Flat_Record
:
3236 base_idx
= u_pcode_get();
3237 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
));
3238 n_elements
= u_pcode_get();
3239 def
= type_def(ctx
->local_types
[base_idx
].type
,record
);
3240 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
));
3241 flat_rec
= type_prepare_flat_record(&def
->type
, ctx
->err
);
3242 if (unlikely(!flat_rec
))
3243 goto record_not_flattened
;
3244 for (ai
= 0; ai
< def
->n_entries
; ai
++) {
3245 pcode_t typ
= pcode_get();
3246 tp
= pcode_to_type(ctx
, typ
, NULL
);
3247 if (unlikely(!TYPE_IS_FLAT(tp
))) {
3248 type_free_flat_record(flat_rec
);
3249 goto record_not_flattened
;
3251 type_set_flat_record_entry(flat_rec
, ai
, tp
);
3253 tt
= type_get_flat_record(flat_rec
, ctx
->err
);
3255 goto record_not_flattened
;
3257 record_not_flattened
:
3260 case Local_Type_Flat_Array
:
3261 base_idx
= pcode_get();
3262 n_elements
= pcode_get();
3263 tp
= pcode_to_type(ctx
, base_idx
, NULL
);
3264 if (unlikely(!TYPE_IS_FLAT(tp
)))
3265 goto array_not_flattened
;
3266 if (unlikely(n_elements
> signed_maximum(int_default_t
) + zero
))
3267 goto array_not_flattened
;
3268 tt
= type_get_flat_array(tp
, n_elements
, ctx
->err
);
3270 goto array_not_flattened
;
3272 array_not_flattened
:
3273 tt
= type_get_unknown();
3276 internal(file_line
, "pcode_build_function_core(%s): invalid local type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
3278 ctx
->local_types
[p
].type
= tt
;
3279 ctx
->local_types
[p
].type_index
= no_type_index
;
3282 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, frame_align
, frame_offset
, ctx
->err
);
3283 if (unlikely(!ctx
->layout
))
3286 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
);
3287 if (unlikely(!ctx
->pcode_types
))
3290 if (unlikely(!array_init_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, ctx
->err
)))
3293 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3294 struct pcode_type
*pt
;
3295 pcode_t typ
, color
, varflags
;
3299 color
= pcode_get();
3300 varflags
= u_pcode_get();
3301 pcode_load_blob(ctx
, NULL
, NULL
);
3302 pt
= &ctx
->pcode_types
[v
];
3303 pt
->argument
= NULL
;
3305 pt
->varflags
= varflags
;
3310 const struct type
*t
= pcode_to_type(ctx
, typ
, NULL
);
3311 struct color empty_color
= { 0, 0, false };
3316 if (typ
< 0 && !pcode_get_type(typ
))
3317 pt
->extra_type
= typ
;
3318 while ((size_t)color
>= ctx
->n_colors
)
3319 if (unlikely(!array_add_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, empty_color
, NULL
, ctx
->err
)))
3323 if (!ctx
->colors
[color
].align
) {
3324 ctx
->colors
[color
].size
= t
->size
;
3325 ctx
->colors
[color
].align
= t
->align
;
3327 ajla_assert_lo(ctx
->colors
[color
].size
== t
->size
&&
3328 ctx
->colors
[color
].align
== t
->align
,
3329 (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
));
3334 /*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);*/
3336 for (is
= 0; is
< ctx
->n_colors
; is
++) {
3337 const struct color
*c
= &ctx
->colors
[is
];
3339 if (unlikely(!layout_add(ctx
->layout
, maximum(c
->size
, 1), c
->align
, ctx
->err
)))
3342 if (unlikely(!layout_add(ctx
->layout
, 0, 1, ctx
->err
)))
3347 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3350 ctx
->n_slots
= layout_size(ctx
->layout
);
3352 ctx
->local_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct local_variable
*, 0, 0, ctx
->n_slots
, sizeof(struct local_variable
), ctx
->err
);
3353 if (unlikely(!ctx
->local_variables
))
3356 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
);
3357 if (unlikely(!ctx
->local_variables_flags
))
3360 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3361 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3363 pt
->slot
= NO_FRAME_T
;
3365 pt
->slot
= layout_get(ctx
->layout
, pt
->color
);
3366 ctx
->local_variables
[pt
->slot
].type
= pt
->type
;
3367 /*ctx->local_variables_flags[pt->slot].may_be_borrowed = false;*/
3368 /*if (pt->type->tag == TYPE_TAG_flat_option && !(pt->varflags & VarFlag_Must_Be_Flat))
3369 debug("non-flat variable in %s", function_name(ctx));*/
3370 ctx
->local_variables_flags
[pt
->slot
].must_be_flat
= !!(pt
->varflags
& VarFlag_Must_Be_Flat
);
3371 ctx
->local_variables_flags
[pt
->slot
].must_be_data
= !!(pt
->varflags
& VarFlag_Must_Be_Data
);
3375 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3379 unsigned n_elided
= 0;
3380 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3381 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3385 debug("function, elided %d/%d", n_elided
, ctx
->n_local_variables
);
3389 if (unlikely(!array_init_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ctx
->err
)))
3392 if (unlikely(!pcode_preload_ld(ctx
)))
3396 sfd
= save_find_function_descriptor(md
, fd
);
3403 ctx
->code
= sfd
->code
;
3404 ctx
->code_len
= sfd
->code_size
;
3410 ctx
->labels
= mem_alloc_array_mayfail(mem_alloc_mayfail
, size_t *, 0, 0, ctx
->n_labels
, sizeof(size_t), ctx
->err
);
3411 if (unlikely(!ctx
->labels
))
3413 for (p
= 0; p
< ctx
->n_labels
; p
++)
3414 ctx
->labels
[p
] = no_label
;
3416 if (unlikely(!array_init_mayfail(struct label_ref
, &ctx
->label_ref
, &ctx
->label_ref_len
, ctx
->err
)))
3419 if (unlikely(!array_init_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, ctx
->err
)))
3422 if (unlikely(!array_init_mayfail(code_t
, &ctx
->code
, &ctx
->code_len
, ctx
->err
)))
3425 if (unlikely(!array_init_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, ctx
->err
)))
3428 if (unlikely(ctx
->function_type
== Fn_Record
) || unlikely(ctx
->function_type
== Fn_Option
)) {
3429 if (ctx
->function_type
== Fn_Record
) {
3430 if (unlikely(!pcode_generate_record(ctx
)))
3433 gen_code(OPCODE_UNREACHABLE
);
3435 if (unlikely(!pcode_generate_instructions(ctx
)))
3439 array_finish(code_t
, &ctx
->code
, &ctx
->code_len
);
3440 array_finish(struct line_position
, &ctx
->lp
, &ctx
->lp_size
);
3442 for (is
= 0; is
< ctx
->label_ref_len
; is
++) {
3444 struct label_ref
*lr
= &ctx
->label_ref
[is
];
3445 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
));
3446 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
));
3447 diff
= ((uint32_t)ctx
->labels
[lr
->label
] - (uint32_t)lr
->code_pos
) * sizeof(code_t
);
3448 if (SIZEOF_IP_T
== 2) {
3449 ctx
->code
[lr
->code_pos
] += (code_t
)diff
;
3450 } else if (SIZEOF_IP_T
== 4 && !CODE_ENDIAN
) {
3451 uint32_t val
= ctx
->code
[lr
->code_pos
] | ((uint32_t)ctx
->code
[lr
->code_pos
+ 1] << 16);
3453 ctx
->code
[lr
->code_pos
] = val
& 0xffff;
3454 ctx
->code
[lr
->code_pos
+ 1] = val
>> 16;
3455 } else if (SIZEOF_IP_T
== 4 && CODE_ENDIAN
) {
3456 uint32_t val
= ((uint32_t)ctx
->code
[lr
->code_pos
] << 16) | ctx
->code
[lr
->code_pos
+ 1];
3458 ctx
->code
[lr
->code_pos
] = val
>> 16;
3459 ctx
->code
[lr
->code_pos
+ 1] = val
& 0xffff;
3465 mem_free(ctx
->labels
), ctx
->labels
= NULL
;
3466 mem_free(ctx
->label_ref
), ctx
->label_ref
= NULL
;
3468 ft
= data_alloc_flexible(function_types
, types
, ctx
->types_len
, ctx
->err
);
3471 da(ft
,function_types
)->n_types
= ctx
->types_len
;
3472 memcpy(da(ft
,function_types
)->types
, ctx
->types
, ctx
->types_len
* sizeof(const struct type
*));
3473 mem_free(ctx
->types
);
3479 mem_free(ctx
->colors
), ctx
->colors
= NULL
;
3480 mem_free(ctx
->pcode_types
), ctx
->pcode_types
= NULL
;
3481 mem_free(ctx
->local_types
), ctx
->local_types
= NULL
;
3483 array_finish(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
);
3485 if (profiling_escapes
) {
3486 ctx
->escape_data
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct escape_data
*, 0, 0, ctx
->code_len
, sizeof(struct escape_data
), ctx
->err
);
3487 if (unlikely(!ctx
->escape_data
))
3491 fn
= data_alloc_flexible(function
, local_directory
, ctx
->ld_len
, ctx
->err
);
3495 da(fn
,function
)->frame_slots
= frame_offset
/ slot_size
+ ctx
->n_slots
;
3496 da(fn
,function
)->n_bitmap_slots
= bitmap_slots(ctx
->n_slots
);
3497 da(fn
,function
)->n_arguments
= ctx
->n_real_arguments
;
3498 da(fn
,function
)->n_return_values
= ctx
->n_real_return_values
;
3499 da(fn
,function
)->code
= ctx
->code
;
3500 da(fn
,function
)->code_size
= ctx
->code_len
;
3501 da(fn
,function
)->local_variables
= ctx
->local_variables
;
3503 da(fn
,function
)->local_variables_flags
= ctx
->local_variables_flags
;
3505 mem_free(ctx
->local_variables_flags
);
3506 da(fn
,function
)->local_variables_flags
= sfd
->local_variables_flags
;
3508 da(fn
,function
)->args
= ctx
->args
;
3509 da(fn
,function
)->types_ptr
= pointer_data(ft
);
3510 da(fn
,function
)->record_definition
= ctx
->record_definition
? &ctx
->record_definition
->type
: NULL
;
3511 da(fn
,function
)->function_name
= cast_ptr(char *, ctx
->function_name
);
3512 da(fn
,function
)->module_designator
= md
;
3513 da(fn
,function
)->function_designator
= fd
;
3515 da(fn
,function
)->lp
= ctx
->lp
;
3516 da(fn
,function
)->lp_size
= ctx
->lp_size
;
3518 da(fn
,function
)->lp
= sfd
->lp
;
3519 da(fn
,function
)->lp_size
= sfd
->lp_size
;
3521 memcpy(da(fn
,function
)->local_directory
, ctx
->ld
, ctx
->ld_len
* sizeof(pointer_t
*));
3522 da(fn
,function
)->local_directory_size
= ctx
->ld_len
;
3526 da(fn
,function
)->codegen
= function_build_internal_thunk(codegen_fn
, 1, ia
);
3527 store_relaxed(&da(fn
,function
)->codegen_failed
, 0);
3529 function_init_common(fn
);
3532 /*if (memcmp(ctx->code, sfd->code, ctx->code_len * sizeof(code_t))) internal(file_line, "code mismatch");*/
3533 da(fn
,function
)->loaded_cache
= sfd
->data_saved_cache
;
3534 /*if (da(fn,function)->loaded_cache) debug("loaded cache: %s", function_name(ctx));*/
3537 da(fn
,function
)->escape_data
= ctx
->escape_data
;
3538 da(fn
,function
)->leaf
= ctx
->leaf
;
3539 da(fn
,function
)->is_saved
= is_saved
;
3541 ipret_prefetch_functions(fn
);
3543 return pointer_data(fn
);
3546 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3548 ctx
->ret_val
= pointer_mark();
3551 return ctx
->ret_val
;
3554 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
)
3559 ptr
= pcode_build_function_core(fp
, ip
, pcode
, size
, md
, fd
, &ex
, &err
);
3560 if (unlikely(pointer_is_empty(ptr
)))
3562 if (unlikely(pointer_is_mark(ptr
)))
3563 return function_return(fp
, pointer_error(err
, NULL
, NULL pass_file_line
));
3564 return function_return(fp
, ptr
);
3567 void *pcode_build_function_from_builtin(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3569 const pcode_t
*start
;
3571 struct module_designator
*md
= arguments
[0].ptr
;
3572 struct function_designator
*fd
= arguments
[1].ptr
;
3573 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3574 return pcode_build_function(fp
, ip
, start
, size
, md
, arguments
[1].ptr
);
3577 void *pcode_build_function_from_array(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3581 struct thunk
*thunk
;
3584 const struct function_designator
*fd
;
3585 const pcode_t
*start
;
3588 ptr
= arguments
[0].ptr
;
3589 ex
= pointer_deep_eval(ptr
, fp
, ip
, &thunk
);
3590 if (unlikely(ex
!= POINTER_FOLLOW_THUNK_GO
)) {
3591 if (ex
== POINTER_FOLLOW_THUNK_EXCEPTION
) {
3592 return function_return(fp
, pointer_thunk(thunk
));
3597 array_to_bytes(ptr
, &bytes
, &bytes_l
);
3600 if (unlikely(bytes_l
% sizeof(pcode_t
) != 0))
3601 internal(file_line
, "pcode_build_function_from_array: invalid length: %lu", (unsigned long)bytes_l
);
3603 start
= cast_ptr(const pcode_t
*, bytes
);
3604 size
= bytes_l
/ sizeof(pcode_t
);
3605 fd
= arguments
[2].ptr
;
3607 /*builtin_walk_nested(&start, &size, fd->n_entries, fd->entries);*/
3609 ex
= pcode_build_function(fp
, ip
, start
, size
, arguments
[1].ptr
, fd
);
3616 void *pcode_array_from_builtin(frame_s
*fp
, const code_t attr_unused
*ip
, union internal_arg arguments
[])
3618 const struct type
*t
;
3621 const pcode_t
*start
;
3623 struct module_designator
*md
= arguments
[0].ptr
;
3624 struct function_designator
*fd
= arguments
[1].ptr
;
3626 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3628 t
= type_get_fixed(log_2(sizeof(pcode_t
)), false);
3629 d
= data_alloc_array_flat_mayfail(t
, size
, size
, false, &err pass_file_line
);
3631 return function_return(fp
, pointer_thunk(thunk_alloc_exception_error(err
, NULL
, NULL
, NULL pass_file_line
)));
3634 memcpy(da_array_flat(d
), start
, size
* sizeof(pcode_t
));
3636 return function_return(fp
, pointer_data(d
));
3640 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
)
3644 unsigned n_local_variables
;
3645 unsigned n_arguments
;
3649 if (unlikely(!array_init_mayfail(pcode_t
, &pc
, &pc_l
, err
)))
3653 if (unlikely(!array_add_mayfail(pcode_t, &pc, &pc_l, x, NULL, err)))\
3656 #define addstr(x, l) \
3658 if (unlikely(!array_add_multiple_mayfail(pcode_t, &pc, &pc_l, x, l, NULL, err)))\
3662 n_local_variables
= Op_IsUnary(op
) ? 2 : 3;
3663 n_arguments
= n_local_variables
- 1;
3666 add(Call_Mode_Strict
);
3669 add(n_local_variables
);
3676 for (i
= 0; i
< n_local_variables
; i
++) {
3677 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3689 add(1 + blob_1_len
);
3691 addstr(blob_1
, blob_1_len
);
3692 if (n_arguments
== 2) {
3694 add(1 + blob_2_len
);
3696 addstr(blob_2
, blob_2_len
);
3699 add(Op_IsUnary(op
) ? P_UnaryOp
: P_BinaryOp
);
3700 add(Op_IsUnary(op
) ? 4 : 6);
3703 add(Flag_Free_Argument
| Flag_Op_Strict
);
3705 if (n_arguments
== 2) {
3706 add(Flag_Free_Argument
);
3712 add(Flag_Free_Argument
);
3718 ptr
= pcode_build_function_core(NULL
, NULL
, pc
, pc_l
, NULL
, NULL
, NULL
, err
);
3727 return pointer_empty();
3731 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
)
3733 struct data
*function
;
3736 #ifdef POINTER_FOLLOW_IS_LOCKLESS
3737 const addrlock_depth lock_depth
= DEPTH_THUNK
;
3739 const addrlock_depth lock_depth
= DEPTH_POINTER
;
3743 pointer_follow(ptr
, false, function
, PF_WAIT
, fp
, ip
,
3746 return POINTER_FOLLOW_THUNK_RETRY
);
3748 if (likely(function
!= NULL
)) {
3750 return POINTER_FOLLOW_THUNK_RETRY
;
3753 fn_thunk
= function_build_internal_thunk(build_fn
, n_arguments
, ia
);
3755 barrier_write_before_lock();
3756 address_lock(ptr
, lock_depth
);
3757 if (likely(pointer_is_empty(*pointer_volatile(ptr
)))) {
3758 *pointer_volatile(ptr
) = fn_thunk
;
3759 address_unlock(ptr
, lock_depth
);
3761 address_unlock(ptr
, lock_depth
);
3762 pointer_dereference(fn_thunk
);
3768 static void *pcode_build_op_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3770 pcode_t src_type
= (pcode_t
)a
[0].i
;
3771 pcode_t dest_type
= (pcode_t
)a
[1].i
;
3772 pcode_t op
= (pcode_t
)a
[2].i
;
3773 unsigned flags
= (unsigned)a
[3].i
;
3775 unsigned n_local_variables
;
3776 unsigned n_arguments
;
3778 pcode_t
*pc
= pcode
;
3780 n_local_variables
= flags
& PCODE_FIND_OP_UNARY
? 2 : 3;
3781 n_arguments
= n_local_variables
- 1;
3783 *pc
++ = Fn_Function
;
3784 *pc
++ = Call_Mode_Strict
;
3787 *pc
++ = (pcode_t
)n_local_variables
;
3788 *pc
++ = (pcode_t
)n_arguments
;
3794 for (i
= 0; i
< n_local_variables
; i
++) {
3795 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3804 *pc
++ = n_arguments
;
3805 for (i
= 0; i
< n_arguments
; i
++)
3808 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? P_UnaryOp
: P_BinaryOp
);
3809 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? 4 : 6);
3811 *pc
++ = (pcode_t
)n_arguments
;
3812 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3814 if (!(flags
& PCODE_FIND_OP_UNARY
)) {
3815 *pc
++ = Flag_Free_Argument
;
3821 *pc
++ = Flag_Free_Argument
;
3822 *pc
++ = n_arguments
;
3824 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
));
3826 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3829 static pointer_t fixed_op_thunk
[TYPE_FIXED_N
][OPCODE_FIXED_OP_N
];
3830 static pointer_t int_op_thunk
[TYPE_INT_N
][OPCODE_INT_OP_N
];
3831 static pointer_t real_op_thunk
[TYPE_REAL_N
][OPCODE_REAL_OP_N
];
3832 static pointer_t bool_op_thunk
[OPCODE_BOOL_TYPE_MULT
];
3834 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
)
3836 union internal_arg ia
[4];
3839 type_tag_t tag
= likely(!(flags
& PCODE_CONVERT_FROM_INT
)) ? type
->tag
: rtype
->tag
;
3841 if (TYPE_TAG_IS_FIXED(tag
)) {
3842 unsigned idx
= (code
- OPCODE_FIXED_OP
- (TYPE_TAG_IDX_FIXED(tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
) / OPCODE_FIXED_OP_MULT
;
3843 ajla_assert(idx
< OPCODE_FIXED_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3844 ptr
= &fixed_op_thunk
[TYPE_TAG_IDX_FIXED(tag
) >> 1][idx
];
3845 } else if (TYPE_TAG_IS_INT(tag
)) {
3846 unsigned idx
= (code
- OPCODE_INT_OP
- TYPE_TAG_IDX_INT(tag
) * OPCODE_INT_TYPE_MULT
) / OPCODE_INT_OP_MULT
;
3847 ajla_assert(idx
< OPCODE_INT_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3848 ptr
= &int_op_thunk
[TYPE_TAG_IDX_INT(tag
)][idx
];
3849 ajla_assert(is_power_of_2(type
->size
), (file_line
, "pcode_find_op_function: invalid integer type size %"PRIuMAX
"", (uintmax_t)type
->size
));
3850 } else if (TYPE_TAG_IS_REAL(tag
)) {
3851 unsigned idx
= (code
- OPCODE_REAL_OP
- TYPE_TAG_IDX_REAL(tag
) * OPCODE_REAL_TYPE_MULT
) / OPCODE_REAL_OP_MULT
;
3852 ajla_assert(idx
< OPCODE_REAL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3853 ptr
= &real_op_thunk
[TYPE_TAG_IDX_REAL(tag
)][idx
];
3855 unsigned idx
= (code
- OPCODE_BOOL_OP
) / OPCODE_BOOL_OP_MULT
;
3856 ajla_assert(idx
< OPCODE_BOOL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3857 ptr
= &bool_op_thunk
[idx
];
3859 internal(file_line
, "pcode_find_op_function: invalid type %u", tag
);
3862 ia
[0].i
= type_to_pcode(type
);
3863 ia
[1].i
= type_to_pcode(rtype
);
3864 ia
[2].i
= code
+ Op_N
;
3867 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_op_function
, 4, ia
, result
);
3870 static void *pcode_build_is_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3873 pcode_t
*pc
= pcode
;
3875 *pc
++ = Fn_Function
;
3876 *pc
++ = Call_Mode_Strict
;
3886 *pc
++ = T_Undetermined
;
3887 *pc
++ = T_Undetermined
;
3892 *pc
++ = T_FlatOption
;
3893 *pc
++ = T_FlatOption
;
3904 *pc
++ = Un_IsException
;
3906 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3915 *pc
++ = Flag_Free_Argument
;
3918 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
)));
3920 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3923 static pointer_t is_exception_thunk
;
3925 void * attr_fastcall
pcode_find_is_exception(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3927 return pcode_alloc_op_function(&is_exception_thunk
, fp
, ip
, pcode_build_is_exception_function
, 0, NULL
, result
);
3930 static void *pcode_build_get_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3933 pcode_t
*pc
= pcode
;
3935 *pc
++ = Fn_Function
;
3936 *pc
++ = Call_Mode_Strict
;
3946 *pc
++ = T_Undetermined
;
3947 *pc
++ = T_Undetermined
;
3964 *pc
++ = Un_ExceptionClass
+ a
[0].i
;
3966 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3975 *pc
++ = Flag_Free_Argument
;
3978 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
)));
3980 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3983 static pointer_t get_exception_thunk
[3];
3985 void * attr_fastcall
pcode_find_get_exception(unsigned mode
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3987 union internal_arg ia
[1];
3989 return pcode_alloc_op_function(&get_exception_thunk
[mode
], fp
, ip
, pcode_build_get_exception_function
, 1, ia
, result
);
3992 static void *pcode_build_array_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3995 pcode_t
*pc
= pcode
;
3997 *pc
++ = Fn_Function
;
3998 *pc
++ = Call_Mode_Strict
;
4008 *pc
++ = T_Undetermined
;
4009 *pc
++ = T_Undetermined
;
4020 *pc
++ = T_Undetermined
;
4021 *pc
++ = T_Undetermined
;
4031 *pc
++ = P_Array_Load
;
4034 *pc
++ = Flag_Evaluate
;
4048 *pc
++ = Flag_Free_Argument
;
4051 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
)));
4053 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4056 static pointer_t array_load_thunk
;
4058 void * attr_fastcall
pcode_find_array_load_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4060 return pcode_alloc_op_function(&array_load_thunk
, fp
, ip
, pcode_build_array_load_function
, 0, NULL
, result
);
4063 static void *pcode_build_array_len_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4066 pcode_t
*pc
= pcode
;
4068 *pc
++ = Fn_Function
;
4069 *pc
++ = Call_Mode_Strict
;
4079 *pc
++ = T_Undetermined
;
4080 *pc
++ = T_Undetermined
;
4095 *pc
++ = P_Array_Len
;
4099 *pc
++ = Flag_Evaluate
;
4107 *pc
++ = Flag_Free_Argument
;
4110 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
)));
4112 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4115 static pointer_t array_len_thunk
;
4117 void * attr_fastcall
pcode_find_array_len_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4119 return pcode_alloc_op_function(&array_len_thunk
, fp
, ip
, pcode_build_array_len_function
, 0, NULL
, result
);
4122 static void *pcode_build_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4125 pcode_t
*pc
= pcode
;
4127 *pc
++ = Fn_Function
;
4128 *pc
++ = Call_Mode_Strict
;
4138 *pc
++ = T_Undetermined
;
4139 *pc
++ = T_Undetermined
;
4150 *pc
++ = T_FlatOption
;
4151 *pc
++ = T_FlatOption
;
4161 *pc
++ = P_Array_Len_Greater_Than
;
4166 *pc
++ = Flag_Evaluate
;
4178 *pc
++ = Flag_Free_Argument
;
4181 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
)));
4183 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4186 static pointer_t array_len_greater_than_thunk
;
4188 void * attr_fastcall
pcode_find_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4190 return pcode_alloc_op_function(&array_len_greater_than_thunk
, fp
, ip
, pcode_build_array_len_greater_than_function
, 0, NULL
, result
);
4193 static void *pcode_build_array_sub_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4196 pcode_t
*pc
= pcode
;
4198 *pc
++ = Fn_Function
;
4199 *pc
++ = Call_Mode_Strict
;
4209 *pc
++ = T_Undetermined
;
4210 *pc
++ = T_Undetermined
;
4227 *pc
++ = T_Undetermined
;
4228 *pc
++ = T_Undetermined
;
4239 *pc
++ = P_Array_Sub
;
4242 *pc
++ = Flag_Evaluate
;
4261 *pc
++ = Flag_Free_Argument
;
4264 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
)));
4266 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4269 static pointer_t array_sub_thunk
;
4271 void * attr_fastcall
pcode_find_array_sub_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4273 return pcode_alloc_op_function(&array_sub_thunk
, fp
, ip
, pcode_build_array_sub_function
, 0, NULL
, result
);
4276 static void *pcode_build_array_skip_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4279 pcode_t
*pc
= pcode
;
4281 *pc
++ = Fn_Function
;
4282 *pc
++ = Call_Mode_Strict
;
4292 *pc
++ = T_Undetermined
;
4293 *pc
++ = T_Undetermined
;
4304 *pc
++ = T_Undetermined
;
4305 *pc
++ = T_Undetermined
;
4315 *pc
++ = P_Array_Skip
;
4318 *pc
++ = Flag_Evaluate
;
4332 *pc
++ = Flag_Free_Argument
;
4335 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
)));
4337 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4340 static pointer_t array_skip_thunk
;
4342 void * attr_fastcall
pcode_find_array_skip_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4344 return pcode_alloc_op_function(&array_skip_thunk
, fp
, ip
, pcode_build_array_skip_function
, 0, NULL
, result
);
4347 static void *pcode_build_array_append_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4350 pcode_t
*pc
= pcode
;
4352 *pc
++ = Fn_Function
;
4353 *pc
++ = Call_Mode_Strict
;
4363 *pc
++ = T_Undetermined
;
4364 *pc
++ = T_Undetermined
;
4369 *pc
++ = T_Undetermined
;
4370 *pc
++ = T_Undetermined
;
4375 *pc
++ = T_Undetermined
;
4376 *pc
++ = T_Undetermined
;
4396 *pc
++ = P_Array_Append
;
4399 *pc
++ = Flag_Free_Argument
;
4401 *pc
++ = Flag_Free_Argument
;
4406 *pc
++ = Flag_Free_Argument
;
4408 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
)));
4410 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4413 static pointer_t array_append_thunk
;
4415 void * attr_fastcall
pcode_find_array_append_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4417 return pcode_alloc_op_function(&array_append_thunk
, fp
, ip
, pcode_build_array_append_function
, 0, NULL
, result
);
4421 static void *pcode_build_option_ord_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4424 pcode_t
*pc
= pcode
;
4426 *pc
++ = Fn_Function
;
4427 *pc
++ = Call_Mode_Strict
;
4437 *pc
++ = T_Undetermined
;
4438 *pc
++ = T_Undetermined
;
4457 *pc
++ = P_Option_Ord
;
4468 *pc
++ = Flag_Free_Argument
;
4471 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
)));
4473 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4476 static pointer_t option_ord_thunk
;
4478 void * attr_fastcall
pcode_find_option_ord_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4480 return pcode_alloc_op_function(&option_ord_thunk
, fp
, ip
, pcode_build_option_ord_function
, 0, NULL
, result
);
4484 struct function_key
{
4489 static void *pcode_build_record_option_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
4492 pcode_t
*pc
= pcode
;
4493 pcode_t result_type
= a
[0].i
== PCODE_FUNCTION_OPTION_TEST
? T_FlatOption
: T_Undetermined
;
4495 *pc
++ = Fn_Function
;
4496 *pc
++ = Call_Mode_Strict
;
4506 *pc
++ = T_Undetermined
;
4507 *pc
++ = T_Undetermined
;
4512 *pc
++ = result_type
;
4513 *pc
++ = result_type
;
4523 case PCODE_FUNCTION_RECORD_LOAD
:
4524 /* P_Record_Load_Slot already sets Flag_Evaluate */
4525 *pc
++ = P_Record_Load_Slot
;
4529 *pc
++ = (pcode_t
)a
[1].i
;
4531 case PCODE_FUNCTION_OPTION_LOAD
:
4532 *pc
++ = P_Option_Load
;
4535 *pc
++ = Flag_Evaluate
;
4537 *pc
++ = (pcode_t
)a
[1].i
;
4539 case PCODE_FUNCTION_OPTION_TEST
:
4543 *pc
++ = P_Option_Test
;
4547 *pc
++ = (pcode_t
)a
[1].i
;
4550 internal(file_line
, "pcode_build_record_option_load_function: invalid operation %"PRIuMAX
"", (uintmax_t)a
[0].i
);
4559 *pc
++ = Flag_Free_Argument
;
4562 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
)));
4564 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4567 struct pcode_function
{
4568 struct tree_entry entry
;
4569 struct function_key key
;
4573 shared_var
struct tree pcode_functions
;
4574 rwlock_decl(pcode_functions_mutex
);
4576 static int record_option_load_compare(const struct tree_entry
*e1
, uintptr_t e2
)
4578 struct pcode_function
*rl
= get_struct(e1
, struct pcode_function
, entry
);
4579 struct function_key
*key
= cast_cpp(struct function_key
*, num_to_ptr(e2
));
4580 if (rl
->key
.tag
!= key
->tag
)
4581 return (int)rl
->key
.tag
- key
->tag
;
4582 if (rl
->key
.id
< key
->id
)
4584 if (rl
->key
.id
> key
->id
)
4589 static pointer_t
*pcode_find_function_for_key(struct function_key
*key
)
4591 struct tree_entry
*e
;
4593 rwlock_lock_read(&pcode_functions_mutex
);
4594 e
= tree_find(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
));
4595 rwlock_unlock_read(&pcode_functions_mutex
);
4597 struct tree_insert_position ins
;
4598 rwlock_lock_write(&pcode_functions_mutex
);
4599 e
= tree_find_for_insert(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
), &ins
);
4602 struct pcode_function
*rl
;
4603 rl
= mem_alloc_mayfail(struct pcode_function
*, sizeof(struct pcode_function
), &sink
);
4604 if (unlikely(!rl
)) {
4605 rwlock_unlock_write(&pcode_functions_mutex
);
4609 rl
->ptr
= pointer_empty();
4611 tree_insert_after_find(e
, &ins
);
4613 rwlock_unlock_write(&pcode_functions_mutex
);
4615 return &get_struct(e
, struct pcode_function
, entry
)->ptr
;
4618 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
)
4620 struct function_key key
;
4622 union internal_arg ia
[2];
4624 if (unlikely((uintmax_t)slot
> (uintmax_t)signed_maximum(pcode_t
) + zero
)) {
4625 *result
= out_of_memory_ptr
;
4626 return POINTER_FOLLOW_THUNK_RETRY
;
4632 ptr
= pcode_find_function_for_key(&key
);
4633 if (unlikely(!ptr
)) {
4634 *result
= out_of_memory_ptr
;
4635 return POINTER_FOLLOW_THUNK_RETRY
;
4640 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_record_option_load_function
, 2, ia
, result
);
4643 static void thunk_init_run(pointer_t
*ptr
, unsigned n
)
4646 *ptr
= pointer_empty();
4651 static void thunk_free_run(pointer_t
*ptr
, unsigned n
)
4654 if (!pointer_is_empty(*ptr
))
4655 pointer_dereference(*ptr
);
4660 void name(pcode_init
)(void)
4664 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_init_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4665 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_init_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4666 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_init_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4667 thunk_init_run(&is_exception_thunk
, 1);
4668 thunk_init_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4669 thunk_init_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4670 thunk_init_run(&array_load_thunk
, 1);
4671 thunk_init_run(&array_len_thunk
, 1);
4672 thunk_init_run(&array_len_greater_than_thunk
, 1);
4673 thunk_init_run(&array_sub_thunk
, 1);
4674 thunk_init_run(&array_skip_thunk
, 1);
4675 thunk_init_run(&array_append_thunk
, 1);
4676 thunk_init_run(&option_ord_thunk
, 1);
4677 tree_init(&pcode_functions
);
4678 rwlock_init(&pcode_functions_mutex
);
4681 void name(pcode_done
)(void)
4684 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_free_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4685 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_free_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4686 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_free_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4687 thunk_free_run(&is_exception_thunk
, 1);
4688 thunk_free_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4689 thunk_free_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4690 thunk_free_run(&array_load_thunk
, 1);
4691 thunk_free_run(&array_len_thunk
, 1);
4692 thunk_free_run(&array_len_greater_than_thunk
, 1);
4693 thunk_free_run(&array_sub_thunk
, 1);
4694 thunk_free_run(&array_skip_thunk
, 1);
4695 thunk_free_run(&array_append_thunk
, 1);
4696 thunk_free_run(&option_ord_thunk
, 1);
4697 while (!tree_is_empty(&pcode_functions
)) {
4698 struct pcode_function
*rl
= get_struct(tree_any(&pcode_functions
), struct pcode_function
, entry
);
4699 if (!pointer_is_empty(rl
->ptr
))
4700 pointer_dereference(rl
->ptr
);
4701 tree_delete(&rl
->entry
);
4704 rwlock_done(&pcode_functions_mutex
);