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(greater
), fx(ugreater
), in(greater
), re(greater
), bo(greater
), },
80 { fx(greater_equal
), fx(ugreater_equal
), in(greater_equal
), re(greater_equal
), bo(greater_equal
),},
81 { fx(bt
), fx(bt
), in(bt
), NO_OPCODE
, NO_OPCODE
, },
82 { fx(not), fx(not), in(not), NO_OPCODE
, bo(not), },
83 { fx(neg
), fx(neg
), in(neg
), re(neg
), NO_OPCODE
, },
84 { fx(bswap
), fx(bswap
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
85 { fx(brev
), fx(brev
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
86 { fx(bsf
), fx(bsf
), in(bsf
), NO_OPCODE
, NO_OPCODE
, },
87 { fx(bsr
), fx(bsr
), in(bsr
), NO_OPCODE
, NO_OPCODE
, },
88 { fx(popcnt
), fx(popcnt
), in(popcnt
), NO_OPCODE
, NO_OPCODE
, },
89 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sqrt
), NO_OPCODE
, },
90 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cbrt
), NO_OPCODE
, },
91 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sin
), NO_OPCODE
, },
92 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cos
), NO_OPCODE
, },
93 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(tan
), NO_OPCODE
, },
94 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(asin
), NO_OPCODE
, },
95 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(acos
), NO_OPCODE
, },
96 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atan
), NO_OPCODE
, },
97 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sinh
), NO_OPCODE
, },
98 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cosh
), NO_OPCODE
, },
99 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(tanh
), NO_OPCODE
, },
100 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(asinh
), NO_OPCODE
, },
101 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(acosh
), NO_OPCODE
, },
102 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atanh
), NO_OPCODE
, },
103 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp2
), NO_OPCODE
, },
104 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp
), NO_OPCODE
, },
105 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp10
), NO_OPCODE
, },
106 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log2
), NO_OPCODE
, },
107 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log
), NO_OPCODE
, },
108 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log10
), NO_OPCODE
, },
109 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(round
), NO_OPCODE
, },
110 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(floor
), NO_OPCODE
, },
111 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(ceil
), NO_OPCODE
, },
112 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(trunc
), NO_OPCODE
, },
113 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(fract
), NO_OPCODE
, },
114 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(mantissa
), NO_OPCODE
, },
115 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exponent
), NO_OPCODE
, },
116 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(next_number
), NO_OPCODE
, },
117 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(prev_number
), NO_OPCODE
, },
118 { fx(to_int
), fx(uto_int
), in(to_int
), re(to_int
), NO_OPCODE
, },
119 { fx(from_int
), fx(ufrom_int
), in(from_int
), re(from_int
), NO_OPCODE
, },
120 { OPCODE_IS_EXCEPTION
, NO_OPCODE
, NO_OPCODE
, re(is_exception
), NO_OPCODE
, },
121 { OPCODE_EXCEPTION_CLASS
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
122 { OPCODE_EXCEPTION_TYPE
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
123 { OPCODE_EXCEPTION_AUX
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
124 { OPCODE_SYSTEM_PROPERTY
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
125 { fx(move
), fx(move
), in(move
), re(move
), bo(move
), },
126 { fx(copy
), fx(copy
), in(copy
), re(copy
), bo(copy
), },
127 { fx(ldc
), fx(ldc
), in(ldc
), re(ldc
), NO_OPCODE
, },
137 static void instruction_class(const struct type
*t
, unsigned *cls
, code_t
*typeq
, pcode_t op
)
139 if ((op
== Un_IsException
&& !TYPE_TAG_IS_REAL(t
->tag
)) || op
== Un_ExceptionClass
|| op
== Un_ExceptionType
|| op
== Un_ExceptionAux
|| op
== Un_SystemProperty
) {
142 } else if (TYPE_TAG_IS_FIXED(t
->tag
)) {
143 *typeq
= (TYPE_TAG_IDX_FIXED(t
->tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
;
144 *cls
= TYPE_TAG_FIXED_IS_UNSIGNED(t
->tag
);
145 } else if (TYPE_TAG_IS_INT(t
->tag
)) {
146 *typeq
= TYPE_TAG_IDX_INT(t
->tag
) * OPCODE_INT_TYPE_MULT
;
148 } else if (TYPE_TAG_IS_REAL(t
->tag
)) {
149 *typeq
= TYPE_TAG_IDX_REAL(t
->tag
) * OPCODE_REAL_TYPE_MULT
;
151 } else if (t
->tag
== TYPE_TAG_flat_option
) {
155 internal(file_line
, "instruction_class: invalid type %u", t
->tag
);
159 static code_t
get_code(pcode_t op
, const struct type
*t
)
163 ajla_assert(op
>= 0 && op
< Op_NN
, (file_line
, "get_code: invalid operation %"PRIdMAX
"", (intmax_t)op
));
164 instruction_class(t
, &cls
, &typeq
, op
);
165 code
= pcode2code
[op
][cls
];
166 ajla_assert(code
!= NO_OPCODE
, (file_line
, "get_code: invalid instruction and type: %"PRIdMAX
", %u", (intmax_t)op
, t
->tag
));
168 return code_alt(code
);
171 #define INIT_ARG_MODE 0
172 #define INIT_ARG_MODE_1 1
173 typedef unsigned char arg_mode_t
;
175 static bool adjust_arg_mode(arg_mode_t
*am
, uintmax_t offs
, ajla_error_t
*mayfail
)
178 if (offs
+ uzero
<= 0xff) my_am
= 0;
179 else if (offs
+ uzero
<= 0xffffU
) my_am
= 1;
180 else if (offs
+ uzero
<= 0xffffffffUL
+ uzero
) my_am
= 2;
182 if (unlikely(my_am
>= ARG_MODE_N
)) {
184 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
187 internal(file_line
, "adjust_arg_mode: too big arg mode: offset %"PRIuMAX
", max mode %d", (uintmax_t)offs
, ARG_MODE_N
);
189 if (unlikely(my_am
> *am
))
194 #define get_arg_mode(am, val) \
196 if (unlikely(!adjust_arg_mode(&(am), (val), ctx->err))) \
201 const struct type
*type
;
206 const struct type
*type
;
207 struct local_arg
*argument
;
211 bool is_dereferenced_in_call_argument
;
227 struct tree_entry entry
;
232 struct build_function_context
{
233 const pcode_t
*pcode
;
234 const pcode_t
*pcode_limit
;
235 const pcode_t
*pcode_instr_end
;
240 pcode_t function_type
;
241 pcode_t n_local_types
;
243 frame_t n_local_variables
;
245 arg_t n_return_values
;
246 arg_t n_real_arguments
;
247 arg_t n_real_return_values
;
250 uint8_t *function_name
;
252 struct local_type
*local_types
;
253 struct pcode_type
*pcode_types
; /* indexed by pcode idx */
254 struct layout
*layout
;
255 struct local_variable
*local_variables
; /* indexed by slot */
256 struct local_variable_flags
*local_variables_flags
; /* indexed by slot */
258 struct color
*colors
;
262 struct label_ref
*label_ref
;
263 size_t label_ref_len
;
269 struct local_arg
*args
;
271 const struct type
**types
;
273 struct data
*ft_free
;
278 frame_t
*record_entries
;
279 size_t record_entries_len
;
281 struct record_definition
*record_definition
;
283 struct line_position
*lp
;
286 struct escape_data
*escape_data
;
288 unsigned checkpoint_num
;
293 pcode_t builtin_type_indices
[TYPE_TAG_N
];
296 static const pcode_t no_type_index
= -1;
297 static const pcode_t error_type_index
= -2;
298 static const size_t no_label
= (size_t)-1;
300 static void init_ctx(struct build_function_context
*ctx
)
303 ctx
->n_real_arguments
= 0;
304 ctx
->function_name
= NULL
;
305 ctx
->local_types
= NULL
;
306 ctx
->pcode_types
= NULL
;
308 ctx
->local_variables
= NULL
;
309 ctx
->local_variables_flags
= NULL
;
312 ctx
->label_ref
= NULL
;
314 tree_init(&ctx
->ld_tree
);
320 ctx
->record_entries
= NULL
;
321 ctx
->record_definition
= NULL
;
324 ctx
->escape_data
= NULL
;
325 ctx
->checkpoint_num
= 0;
327 for (i
= 0; i
< n_array_elements(ctx
->builtin_type_indices
); i
++)
328 ctx
->builtin_type_indices
[i
] = no_type_index
;
331 static void free_ld_tree(struct build_function_context
*ctx
)
333 while (!tree_is_empty(&ctx
->ld_tree
)) {
334 struct ld_ref
*ld_ref
= get_struct(tree_any(&ctx
->ld_tree
), struct ld_ref
, entry
);
335 tree_delete(&ld_ref
->entry
);
340 static void done_ctx(struct build_function_context
*ctx
)
342 if (ctx
->function_name
)
343 mem_free(ctx
->function_name
);
344 if (ctx
->local_types
)
345 mem_free(ctx
->local_types
);
346 if (ctx
->pcode_types
)
347 mem_free(ctx
->pcode_types
);
349 layout_free(ctx
->layout
);
350 if (ctx
->local_variables
)
351 mem_free(ctx
->local_variables
);
352 if (ctx
->local_variables_flags
)
353 mem_free(ctx
->local_variables_flags
);
355 mem_free(ctx
->colors
);
357 mem_free(ctx
->labels
);
359 mem_free(ctx
->label_ref
);
366 mem_free(ctx
->types
);
368 mem_free(ctx
->ft_free
);
371 if (ctx
->record_entries
)
372 mem_free(ctx
->record_entries
);
373 if (ctx
->record_definition
) {
374 mem_free(ctx
->record_definition
->idx_to_frame
);
375 mem_free(ctx
->record_definition
);
379 if (ctx
->escape_data
)
380 mem_free(ctx
->escape_data
);
383 static char *function_name(const struct build_function_context
*ctx
)
385 if (ctx
->function_name
)
386 return cast_ptr(char *, ctx
->function_name
);
390 static pcode_t
pcode_get_fn(struct build_function_context
*ctx argument_position
)
392 ajla_assert(ctx
->pcode
< ctx
->pcode_limit
, (caller_file_line
, "pcode_get_fn(%s): no pcode left", function_name(ctx
)));
393 return *ctx
->pcode
++;
395 #define pcode_get() pcode_get_fn(ctx pass_file_line)
397 static pcode_t
u_pcode_get_fn(struct build_function_context
*ctx argument_position
)
399 pcode_t p
= pcode_get_fn(ctx pass_position
);
400 ajla_assert(p
>= 0, (caller_file_line
, "u_pcode_get_fn(%s): negative pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)p
));
403 #define u_pcode_get() u_pcode_get_fn(ctx pass_file_line)
405 typedef const pcode_t
*pcode_position_save_t
;
407 static inline void pcode_position_save(struct build_function_context
*ctx
, pcode_position_save_t
*save
)
412 static inline void pcode_position_restore(struct build_function_context
*ctx
, const pcode_position_save_t
*save
)
417 typedef size_t code_position_save_t
;
419 static inline void code_position_save(struct build_function_context
*ctx
, code_position_save_t
*save
)
421 *save
= ctx
->code_len
;
424 static inline void code_position_restore(struct build_function_context
*ctx
, const code_position_save_t
*save
)
426 ajla_assert_lo(ctx
->code_len
>= *save
, (file_line
, "code_position_restore(%s): attempting to restore forward: %"PRIuMAX
" < %"PRIuMAX
"", function_name(ctx
), (uintmax_t)ctx
->code_len
, (uintmax_t)*save
));
427 ctx
->code_len
= *save
;
430 const struct type
*pcode_get_type(pcode_t q
)
432 const struct type
*t
;
435 t
= type_get_fixed(0, false);
438 t
= type_get_fixed(0, true);
441 t
= type_get_fixed(1, false);
444 t
= type_get_fixed(1, true);
447 t
= type_get_fixed(2, false);
450 t
= type_get_fixed(2, true);
453 t
= type_get_fixed(3, false);
456 t
= type_get_fixed(3, true);
459 t
= type_get_fixed(4, false);
462 t
= type_get_fixed(4, true);
466 t
= type_get_int(INT_DEFAULT_N
);
485 t
= type_get_real(0);
488 t
= type_get_real(1);
491 t
= type_get_real(2);
494 t
= type_get_real(3);
497 t
= type_get_real(4);
501 t
= type_get_flat_option();
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
, true, 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
, true, 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
, cnst
;
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
);
2464 case P_BinaryConstOp
:
2466 ajla_assert_lo(Op_IsBinary(op
), (file_line
, "P_BinaryConstOp(%s): invalid binary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2467 res
= u_pcode_get();
2468 flags1
= u_pcode_get();
2471 if (unlikely(var_elided(res
))) {
2472 if (flags1
& Flag_Free_Argument
)
2473 pcode_free(ctx
, a1
);
2476 tr
= get_var_type(ctx
, res
);
2477 t1
= get_var_type(ctx
, a1
);
2478 ajla_assert_lo(type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option() : t1
->type
)), (file_line
, "P_BinaryConstOp(%s): invalid types for binary operation %"PRIdMAX
": %u, %u", function_name(ctx
), (intmax_t)op
, t1
->type
->tag
, tr
->type
->tag
));
2480 if (flags1
& Flag_Fused_Bin_Jmp
)
2481 fflags
|= OPCODE_FLAG_FUSED
;
2483 get_arg_mode(am
, t1
->slot
);
2484 get_arg_mode(am
, (frame_t
)cnst
);
2485 get_arg_mode(am
, tr
->slot
);
2486 code
= get_code(op
, t1
->type
) + (TYPE_TAG_IS_FIXED(t1
->type
->tag
) ? OPCODE_FIXED_OP_C
: OPCODE_INT_OP_C
) + am
* OPCODE_MODE_MULT
;
2488 gen_am_two(am
, t1
->slot
, (frame_t
)cnst
);
2489 gen_am_two(am
, tr
->slot
, fflags
);
2490 if (flags1
& Flag_Free_Argument
) {
2491 if (t1
->slot
!= tr
->slot
)
2492 pcode_free(ctx
, a1
);
2497 ajla_assert_lo(op
>= Op_N
|| Op_IsUnary(op
), (file_line
, "P_UnaryOp(%s): invalid unary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2498 res
= u_pcode_get();
2499 flags1
= u_pcode_get();
2501 if (unlikely(var_elided(res
))) {
2502 if (flags1
& Flag_Free_Argument
)
2503 pcode_free(ctx
, a1
);
2506 tr
= get_var_type(ctx
, res
);
2507 t1
= get_var_type(ctx
, a1
);
2508 ajla_assert_lo(op
>= Op_N
|| op
== Un_ConvertFromInt
||
2509 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2510 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2511 : 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
));
2512 if (NEED_OP_EMULATION
&& (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
))) {
2513 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, false)))
2518 get_arg_mode(am
, t1
->slot
);
2519 get_arg_mode(am
, tr
->slot
);
2520 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
);
2522 gen_am_two(am
, t1
->slot
, tr
->slot
);
2523 gen_am(am
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2524 if (flags1
& Flag_Free_Argument
) {
2525 if (t1
->slot
!= tr
->slot
)
2526 pcode_free(ctx
, a1
);
2530 case P_Copy_Type_Cast
:
2531 res
= u_pcode_get();
2532 pcode_get_var_deref(&a1
, &a1_deref
);
2533 if (unlikely(var_elided(res
))) {
2535 if (unlikely(!pcode_free(ctx
, a1
)))
2540 if (unlikely(!pcode_copy(ctx
, instr
!= P_Copy
, res
, a1
, a1_deref
)))
2544 res
= u_pcode_get();
2545 if (unlikely(!pcode_free(ctx
, res
)))
2550 if (unlikely(var_elided(a1
)))
2552 t1
= get_var_type(ctx
, a1
);
2554 get_arg_mode(am
, t1
->slot
);
2556 code
+= am
* OPCODE_MODE_MULT
;
2558 gen_am(am
, t1
->slot
);
2564 res
= u_pcode_get();
2565 ajla_assert_lo(var_elided(res
), (file_line
, "P_Fn(%s): Fn result is not elided", function_name(ctx
)));
2568 for (p
= 0; p
< a1
; p
++)
2570 for (p
= 0; p
< a2
; p
++)
2573 case P_Load_Local_Type
:
2574 res
= u_pcode_get();
2575 ajla_assert_lo(var_elided(res
), (file_line
, "P_Load_Local_Type(%s): Load_Local_Type result is not elided", function_name(ctx
)));
2581 case P_Call_Indirect
:
2583 if (unlikely(!pcode_call(ctx
, instr
)))
2586 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
2587 pcode_t next
, next_params
;
2588 pcode_position_save_t s
;
2589 pcode_position_save(ctx
, &s
);
2591 pcode_get_instr(ctx
, &next
, &next_params
);
2592 if (next
== P_Line_Info
) {
2593 ctx
->pcode
= ctx
->pcode_instr_end
;
2596 pcode_position_restore(ctx
, &s
);
2597 //ajla_assert_lo(next == P_Checkpoint, (file_line, "%s: is followed by %"PRIdMAX"", instr == P_Call ? "P_Call" : "P_Call_Indirect", (intmax_t)next));
2599 ctx
->pcode_instr_end
= ctx
->pcode
;
2604 if (unlikely(!pcode_load_constant(ctx
)))
2607 case P_Structured_Write
:
2608 if (unlikely(!pcode_structured_write(ctx
)))
2613 for (p
= 0; p
< instr_params
; p
++)
2616 case P_Record_Create
:
2617 if (unlikely(!pcode_record_create(ctx
)))
2620 case P_Record_Load_Slot
:
2621 res
= u_pcode_get();
2624 tr
= get_var_type(ctx
, res
);
2625 t1
= get_var_type(ctx
, a1
);
2627 get_arg_mode(am
, tr
->slot
);
2628 get_arg_mode(am
, t1
->slot
);
2629 get_arg_mode(am
, op
);
2630 code
= OPCODE_RECORD_LOAD
;
2631 code
+= am
* OPCODE_MODE_MULT
;
2633 gen_am_two(am
, t1
->slot
, op
);
2634 gen_am_two(am
, tr
->slot
, OPCODE_OP_FLAG_STRICT
);
2637 res
= u_pcode_get();
2638 flags
= u_pcode_get();
2641 if (unlikely(var_elided(res
)))
2643 tr
= get_var_type(ctx
, res
);
2644 t1
= get_var_type(ctx
, a1
);
2645 if (TYPE_IS_FLAT(tr
->type
))
2646 flags
&= ~Flag_Borrow
;
2647 if (t1
->type
->tag
== TYPE_TAG_flat_record
) {
2648 def
= type_def(type_def(t1
->type
,flat_record
)->base
,record
);
2650 def
= type_def(t1
->type
,record
);
2652 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
));
2653 op
= record_definition_slot(def
, op
);
2655 get_arg_mode(am
, tr
->slot
);
2656 get_arg_mode(am
, t1
->slot
);
2657 get_arg_mode(am
, op
);
2658 code
= OPCODE_RECORD_LOAD
;
2659 code
+= am
* OPCODE_MODE_MULT
;
2661 gen_am_two(am
, t1
->slot
, op
);
2662 gen_am_two(am
, tr
->slot
,
2663 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2664 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2665 if (flags
& Flag_Borrow
)
2666 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2669 res
= u_pcode_get();
2670 flags
= u_pcode_get();
2673 if (unlikely(var_elided(res
)))
2675 tr
= get_var_type(ctx
, res
);
2676 t1
= get_var_type(ctx
, a1
);
2677 if (TYPE_IS_FLAT(tr
->type
))
2678 flags
&= ~Flag_Borrow
;
2680 get_arg_mode(am
, tr
->slot
);
2681 get_arg_mode(am
, t1
->slot
);
2682 get_arg_mode(am
, op
);
2683 code
= OPCODE_OPTION_LOAD
;
2684 code
+= am
* OPCODE_MODE_MULT
;
2686 gen_am_two(am
, t1
->slot
, op
);
2687 gen_am_two(am
, tr
->slot
,
2688 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2689 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2690 if (flags
& Flag_Borrow
)
2691 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2693 case P_Option_Create
:
2694 res
= u_pcode_get();
2696 pcode_get_var_deref(&a1
, &a1_deref
);
2697 if (unlikely(var_elided(res
))) {
2699 if (unlikely(!pcode_free(ctx
, a1
)))
2704 tr
= get_var_type(ctx
, res
);
2705 t1
= get_var_type(ctx
, a1
);
2706 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
));
2708 get_arg_mode(am
, tr
->slot
);
2709 get_arg_mode(am
, t1
->slot
);
2710 get_arg_mode(am
, op
);
2711 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2712 goto exception_overflow
;
2713 code
= OPCODE_OPTION_CREATE
;
2714 code
+= am
* OPCODE_MODE_MULT
;
2716 gen_am_two(am
, tr
->slot
, op
);
2717 gen_am_two(am
, t1
->slot
, a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
2720 res
= u_pcode_get();
2723 if (unlikely(var_elided(res
)))
2725 tr
= get_var_type(ctx
, res
);
2726 t1
= get_var_type(ctx
, a1
);
2727 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
));
2729 get_arg_mode(am
, tr
->slot
);
2730 get_arg_mode(am
, t1
->slot
);
2731 get_arg_mode(am
, op
);
2732 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2733 goto exception_overflow
;
2734 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2735 code
= OPCODE_OPTION_TEST_FLAT
;
2737 code
= OPCODE_OPTION_TEST
;
2738 code
+= am
* OPCODE_MODE_MULT
;
2740 gen_am_two(am
, t1
->slot
, op
);
2741 gen_am(am
, tr
->slot
);
2744 res
= u_pcode_get();
2746 if (unlikely(var_elided(res
)))
2748 tr
= get_var_type(ctx
, res
);
2749 t1
= get_var_type(ctx
, a1
);
2750 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
));
2752 get_arg_mode(am
, tr
->slot
);
2753 get_arg_mode(am
, t1
->slot
);
2754 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2755 code
= OPCODE_OPTION_ORD_FLAT
;
2757 code
= OPCODE_OPTION_ORD
;
2758 code
+= am
* OPCODE_MODE_MULT
;
2760 gen_am_two(am
, t1
->slot
, tr
->slot
);
2762 case P_Array_Flexible
:
2764 res
= u_pcode_get();
2765 ajla_assert_lo(var_elided(res
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible result is not elided", function_name(ctx
)));
2767 ajla_assert_lo(var_elided(a1
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible argument is not elided", function_name(ctx
)));
2768 if (instr
== P_Array_Fixed
)
2771 case P_Array_Create
:
2772 if (unlikely(!pcode_array_create(ctx
)))
2776 res
= u_pcode_get();
2777 pcode_get(); /* local type */
2779 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
));
2782 if (unlikely(var_elided(res
)))
2784 tr
= get_var_type(ctx
, res
);
2785 t1
= get_var_type(ctx
, a1
);
2786 t2
= get_var_type(ctx
, a2
);
2787 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
));
2789 get_arg_mode(am
, t1
->slot
);
2790 get_arg_mode(am
, t2
->slot
);
2791 get_arg_mode(am
, tr
->slot
);
2792 gen_code(OPCODE_ARRAY_FILL
+ am
* OPCODE_MODE_MULT
);
2793 gen_am_two(am
, t1
->slot
,
2794 ((op
& Flag_Free_Argument
) ? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2795 ((op
& Flag_Array_Fill_Sparse
) ? OPCODE_ARRAY_FILL_FLAG_SPARSE
: 0)
2797 gen_am_two(am
, t2
->slot
, tr
->slot
);
2799 case P_Array_String
:
2800 if (unlikely(!pcode_array_string(ctx
)))
2803 case P_Array_Unicode
:
2804 if (unlikely(!pcode_array_unicode(ctx
)))
2808 res
= u_pcode_get();
2809 flags
= u_pcode_get();
2812 if (unlikely(var_elided(res
)))
2814 tr
= get_var_type(ctx
, res
);
2815 t1
= get_var_type(ctx
, a1
);
2816 t2
= get_var_type(ctx
, a2
);
2817 if (TYPE_IS_FLAT(tr
->type
))
2818 flags
&= ~Flag_Borrow
;
2820 get_arg_mode(am
, tr
->slot
);
2821 get_arg_mode(am
, t1
->slot
);
2822 get_arg_mode(am
, t2
->slot
);
2823 code
= OPCODE_ARRAY_LOAD
;
2824 code
+= am
* OPCODE_MODE_MULT
;
2826 gen_am_two(am
, t1
->slot
, t2
->slot
);
2827 gen_am_two(am
, tr
->slot
,
2828 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2829 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0) |
2830 (flags
& Flag_Index_In_Range
? OPCODE_ARRAY_INDEX_IN_RANGE
: 0));
2831 if (flags
& Flag_Borrow
)
2832 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2835 res
= u_pcode_get();
2837 flags
= u_pcode_get();
2838 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2839 if (unlikely(var_elided(res
)))
2841 tr
= get_var_type(ctx
, res
);
2842 t1
= get_var_type(ctx
, a1
);
2843 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
));
2844 if (TYPE_IS_FLAT(t1
->type
)) {
2845 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
));
2846 if (unlikely(!pcode_generate_constant(ctx
, res
, (int_default_t
)type_def(t1
->type
,flat_array
)->n_elements
)))
2849 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
));
2851 get_arg_mode(am
, t1
->slot
);
2852 get_arg_mode(am
, tr
->slot
);
2853 gen_code(OPCODE_ARRAY_LEN
+ am
* OPCODE_MODE_MULT
);
2854 gen_am_two(am
, t1
->slot
, tr
->slot
);
2855 gen_am(am
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2858 case P_Array_Len_Greater_Than
:
2859 res
= u_pcode_get();
2862 flags
= u_pcode_get();
2863 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
));
2864 if (unlikely(var_elided(res
)))
2866 tr
= get_var_type(ctx
, res
);
2867 t1
= get_var_type(ctx
, a1
);
2868 t2
= get_var_type(ctx
, a2
);
2869 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
));
2870 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
));
2873 if (unlikely(flags
& Flag_Evaluate
) != 0)
2874 fflags
|= OPCODE_OP_FLAG_STRICT
;
2875 if (flags
& Flag_Fused_Bin_Jmp
)
2876 fflags
|= OPCODE_FLAG_FUSED
;
2878 get_arg_mode(am
, t1
->slot
);
2879 get_arg_mode(am
, t2
->slot
);
2880 get_arg_mode(am
, tr
->slot
);
2881 gen_code(OPCODE_ARRAY_LEN_GREATER_THAN
+ am
* OPCODE_MODE_MULT
);
2882 gen_am_two(am
, t1
->slot
, t2
->slot
);
2883 gen_am_two(am
, tr
->slot
, fflags
);
2886 res
= u_pcode_get();
2887 flags
= u_pcode_get();
2891 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Sub(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2892 if (unlikely(var_elided(res
)))
2894 tr
= get_var_type(ctx
, res
);
2895 ta
= get_var_type(ctx
, aa
);
2896 t1
= get_var_type(ctx
, a1
);
2897 t2
= get_var_type(ctx
, a2
);
2898 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
));
2899 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
));
2902 get_arg_mode(am
, ta
->slot
);
2903 get_arg_mode(am
, t1
->slot
);
2904 get_arg_mode(am
, t2
->slot
);
2905 get_arg_mode(am
, tr
->slot
);
2906 gen_code(OPCODE_ARRAY_SUB
+ am
* OPCODE_MODE_MULT
);
2907 gen_am_two(am
, ta
->slot
, t1
->slot
);
2908 gen_am_two(am
, t2
->slot
, tr
->slot
);
2910 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2911 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2915 res
= u_pcode_get();
2916 flags
= u_pcode_get();
2919 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Skip(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2920 if (unlikely(var_elided(res
)))
2922 tr
= get_var_type(ctx
, res
);
2923 ta
= get_var_type(ctx
, aa
);
2924 t1
= get_var_type(ctx
, a1
);
2925 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
));
2928 get_arg_mode(am
, ta
->slot
);
2929 get_arg_mode(am
, t1
->slot
);
2930 get_arg_mode(am
, tr
->slot
);
2931 gen_code(OPCODE_ARRAY_SKIP
+ am
* OPCODE_MODE_MULT
);
2932 gen_am_two(am
, ta
->slot
, t1
->slot
);
2933 gen_am_two(am
, tr
->slot
,
2934 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2935 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2938 case P_Array_Append
:
2939 case P_Array_Append_One
:
2940 res
= u_pcode_get();
2941 pcode_get_var_deref(&a1
, &a1_deref
);
2942 pcode_get_var_deref(&a2
, &a2_deref
);
2943 if (unlikely(var_elided(res
)))
2945 tr
= get_var_type(ctx
, res
);
2946 t1
= get_var_type(ctx
, a1
);
2947 t2
= get_var_type(ctx
, a2
);
2949 get_arg_mode(am
, tr
->slot
);
2950 get_arg_mode(am
, t1
->slot
);
2951 get_arg_mode(am
, t2
->slot
);
2952 if (instr
== P_Array_Append
) {
2953 gen_code(OPCODE_ARRAY_APPEND
+ am
* OPCODE_MODE_MULT
);
2955 if (TYPE_IS_FLAT(t2
->type
)) {
2956 gen_code(OPCODE_ARRAY_APPEND_ONE_FLAT
+ am
* OPCODE_MODE_MULT
);
2958 gen_code(OPCODE_ARRAY_APPEND_ONE
+ am
* OPCODE_MODE_MULT
);
2961 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0) | (a2_deref
? OPCODE_FLAG_FREE_ARGUMENT_2
: 0));
2962 gen_am_two(am
, t1
->slot
, t2
->slot
);
2964 case P_Array_Flatten
:
2965 res
= u_pcode_get();
2966 pcode_get_var_deref(&a1
, &a1_deref
);
2967 if (unlikely(var_elided(res
)))
2969 tr
= get_var_type(ctx
, res
);
2970 t1
= get_var_type(ctx
, a1
);
2972 get_arg_mode(am
, tr
->slot
);
2973 get_arg_mode(am
, t1
->slot
);
2974 gen_code(OPCODE_ARRAY_FLATTEN
+ am
* OPCODE_MODE_MULT
);
2975 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0));
2976 gen_am(am
, t1
->slot
);
2979 res
= u_pcode_get();
2980 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Jmp(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2982 if (ctx
->labels
[res
] != no_label
) {
2984 target
= (uint32_t)((ctx
->code_len
- ctx
->labels
[res
]) * sizeof(code_t
));
2985 if (likely(target
< 0x10000)) {
2986 gen_code(OPCODE_JMP_BACK_16
);
2987 gen_code((code_t
)target
);
2992 gen_code(OPCODE_JMP
);
2993 gen_relative_jump(res
, SIZEOF_IP_T
);
2997 tr
= get_var_type(ctx
, res
);
2998 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
));
3004 get_arg_mode(am
, tr
->slot
);
3005 code
= OPCODE_JMP_FALSE
+ am
* OPCODE_MODE_MULT
;
3007 gen_am(am
, tr
->slot
);
3008 gen_relative_jump(a1
, SIZEOF_IP_T
* 2);
3009 gen_relative_jump(a2
, SIZEOF_IP_T
);
3012 gen_code(OPCODE_LABEL
);
3013 res
= u_pcode_get();
3014 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Label(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
3015 ajla_assert_lo(ctx
->labels
[res
] == no_label
, (file_line
, "P_Label(%s): label %"PRIdMAX
" already defined", function_name(ctx
), (intmax_t)res
));
3016 ctx
->labels
[res
] = ctx
->code_len
;
3019 if (unlikely(!pcode_io(ctx
)))
3023 ctx
->pcode
= ctx
->pcode_instr_end
;
3026 for (p
= 0; p
< instr_params
; p
++)
3030 if (unlikely(!pcode_return(ctx
)))
3034 if (unlikely(!gen_checkpoint(ctx
, ctx
->pcode
, instr_params
, true)))
3036 for (p
= 0; p
< instr_params
; p
++)
3040 lp
.line
= u_pcode_get();
3041 lp
.ip
= ctx
->code_len
;
3042 if (unlikely(!array_add_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, lp
, NULL
, ctx
->err
)))
3046 internal(file_line
, "pcode_generate_instructions(%s): invalid pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
3049 if (unlikely(ctx
->pcode
!= ctx
->pcode_instr_end
)) {
3054 for (pp
= ctx
->pcode_instr_end
- instr_params
- 2; pp
< ctx
->pcode
; pp
++) {
3055 str_add_char(&s
, &l
, ' ');
3056 str_add_signed(&s
, &l
, *pp
, 10);
3059 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
);
3062 if (unlikely(ctx
->code_len
> sign_bit(ip_t
) / sizeof(code_t
) + uzero
))
3063 goto exception_overflow
;
3067 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3072 static bool pcode_generate_record(struct build_function_context
*ctx
)
3076 struct record_definition
*def
;
3077 if (unlikely(!array_init_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, ctx
->err
)))
3080 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, slot_size
, data_record_offset
, ctx
->err
);
3081 if (unlikely(!ctx
->layout
))
3084 for (; ctx
->pcode
!= ctx
->pcode_limit
; ctx
->pcode
= ctx
->pcode_instr_end
) {
3085 pcode_t instr
, instr_params
;
3086 pcode_get_instr(ctx
, &instr
, &instr_params
);
3088 if (instr
== P_Load_Local_Type
) {
3089 pcode_t var
, fn_var
;
3090 pcode_t attr_unused idx
;
3091 const struct pcode_type
*p
;
3092 const struct type
*t
;
3094 ajla_assert_lo(instr_params
== 3, (file_line
, "pcode_generate_record(%s): invalid number of parameters %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr_params
));
3096 var
= u_pcode_get();
3097 fn_var
= pcode_get();
3098 idx
= u_pcode_get();
3099 if (unlikely(fn_var
!= -1))
3101 if (unlikely(var
!= (pcode_t
)(frame_t
)var
))
3102 goto exception_overflow
;
3103 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
));
3105 if (unlikely(!array_add_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, var
, NULL
, ctx
->err
)))
3108 if (var_elided(var
))
3111 p
= get_var_type(ctx
, var
);
3114 if (unlikely(!layout_add(ctx
->layout
, maximum(t
->size
, 1), t
->align
, ctx
->err
)))
3119 array_finish(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
);
3121 if (unlikely(ctx
->record_entries_len
!= (size_t)(arg_t
)ctx
->record_entries_len
))
3122 goto exception_overflow
;
3124 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3128 def
= type_alloc_record_definition(layout_size(ctx
->layout
), ctx
->err
);
3131 def
->n_slots
= layout_size(ctx
->layout
);
3132 def
->alignment
= maximum(layout_alignment(ctx
->layout
), frame_align
);
3133 def
->n_entries
= (arg_t
)ctx
->record_entries_len
;
3136 for (ai
= 0; ai
< ctx
->record_entries_len
; ai
++) {
3138 const struct pcode_type
*te
;
3139 var
= ctx
->record_entries
[ai
];
3140 if (var_elided((pcode_t
)var
)) {
3141 ctx
->record_entries
[ai
] = NO_FRAME_T
;
3144 slot
= layout_get(ctx
->layout
, layout_idx
++);
3145 ctx
->record_entries
[ai
] = slot
;
3146 te
= get_var_type(ctx
, (pcode_t
)var
);
3147 def
->types
[slot
] = te
->type
;
3150 def
->idx_to_frame
= ctx
->record_entries
, ctx
->record_entries
= NULL
;
3151 ctx
->record_definition
= def
;
3153 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3158 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3164 * pointer_empty -> ret_ex
3165 * poitner_mark -> err
3166 * other -> thunk(error) or data(function)
3168 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
)
3171 pcode_t p
, q
, subfns
;
3175 struct data
*ft
, *fn
;
3176 struct function_descriptor
*sfd
;
3179 #if defined(HAVE_CODEGEN)
3180 union internal_arg ia
[1];
3183 struct build_function_context ctx_
;
3184 struct build_function_context
*ctx
= &ctx_
;
3189 ctx
->pcode_limit
= pcode
+ size
;
3192 q
= u_pcode_get() & Fn_Mask
;
3193 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
));
3194 ctx
->function_type
= q
;
3196 u_pcode_get(); /* call mode - used by the optimizer */
3198 subfns
= u_pcode_get();
3200 ctx
->n_local_types
= u_pcode_get();
3203 ctx
->n_local_variables
= (frame_t
)q
;
3204 if (unlikely(q
!= (pcode_t
)ctx
->n_local_variables
))
3205 goto exception_overflow
;
3208 ctx
->n_arguments
= (arg_t
)q
;
3209 ajla_assert_lo(q
== (pcode_t
)ctx
->n_arguments
, (file_line
, "pcode_build_function_core: overflow in n_arguments"));
3212 ctx
->n_return_values
= (arg_t
)q
;
3213 ajla_assert_lo(q
== (pcode_t
)ctx
->n_return_values
, (file_line
, "pcode_build_function_core: overflow in n_return_values"));
3215 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"));
3218 ctx
->n_real_return_values
= (arg_t
)q
;
3219 ajla_assert_lo(ctx
->n_real_return_values
<= ctx
->n_return_values
, (file_line
, "pcode_build_function_core: invalid n_real_return_values"));
3221 ctx
->n_labels
= u_pcode_get();
3223 if (unlikely(!pcode_load_blob(ctx
, &ctx
->function_name
, &is
)))
3225 if (unlikely(!array_add_mayfail(uint8_t, &ctx
->function_name
, &is
, 0, NULL
, ctx
->err
)))
3227 array_finish(uint8_t, &ctx
->function_name
, &is
);
3235 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
);
3236 if (unlikely(!ctx
->local_types
))
3239 for (p
= 0; p
< ctx
->n_local_types
; p
++) {
3241 struct data
*rec_fn
;
3242 const struct record_definition
*def
;
3243 pcode_t base_idx
, n_elements
;
3244 struct type_entry
*flat_rec
;
3246 const struct type
*tt
, *tp
;
3250 case Local_Type_Record
:
3251 ptr
= pcode_module_load_function(ctx
);
3254 pointer_follow(ptr
, false, rec_fn
, PF_WAIT
, fp
, ip
,
3256 ctx
->ret_val
= pointer_empty();
3258 thunk_reference(thunk_
);
3259 ctx
->ret_val
= pointer_thunk(thunk_
);
3262 ajla_assert_lo(da(rec_fn
,function
)->record_definition
!= NULL
, (file_line
, "pcode_build_function_core(%s): record has no definition", function_name(ctx
)));
3263 def
= type_def(da(rec_fn
,function
)->record_definition
,record
);
3266 case Local_Type_Flat_Record
:
3267 base_idx
= u_pcode_get();
3268 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
));
3269 n_elements
= u_pcode_get();
3270 def
= type_def(ctx
->local_types
[base_idx
].type
,record
);
3271 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
));
3272 flat_rec
= type_prepare_flat_record(&def
->type
, ctx
->err
);
3273 if (unlikely(!flat_rec
))
3274 goto record_not_flattened
;
3275 for (ai
= 0; ai
< def
->n_entries
; ai
++) {
3276 pcode_t typ
= pcode_get();
3277 tp
= pcode_to_type(ctx
, typ
, NULL
);
3278 if (unlikely(!TYPE_IS_FLAT(tp
))) {
3279 type_free_flat_record(flat_rec
);
3280 goto record_not_flattened
;
3282 type_set_flat_record_entry(flat_rec
, ai
, tp
);
3284 tt
= type_get_flat_record(flat_rec
, ctx
->err
);
3286 goto record_not_flattened
;
3288 record_not_flattened
:
3291 case Local_Type_Flat_Array
:
3292 base_idx
= pcode_get();
3293 n_elements
= pcode_get();
3294 tp
= pcode_to_type(ctx
, base_idx
, NULL
);
3295 if (unlikely(!TYPE_IS_FLAT(tp
)))
3296 goto array_not_flattened
;
3297 if (unlikely(n_elements
> signed_maximum(int_default_t
) + zero
))
3298 goto array_not_flattened
;
3299 tt
= type_get_flat_array(tp
, n_elements
, ctx
->err
);
3301 goto array_not_flattened
;
3303 array_not_flattened
:
3304 tt
= type_get_unknown();
3307 internal(file_line
, "pcode_build_function_core(%s): invalid local type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
3309 ctx
->local_types
[p
].type
= tt
;
3310 ctx
->local_types
[p
].type_index
= no_type_index
;
3313 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, frame_align
, frame_offset
, ctx
->err
);
3314 if (unlikely(!ctx
->layout
))
3317 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
);
3318 if (unlikely(!ctx
->pcode_types
))
3321 if (unlikely(!array_init_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, ctx
->err
)))
3324 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3325 struct pcode_type
*pt
;
3326 pcode_t typ
, color
, varflags
;
3330 color
= pcode_get();
3331 varflags
= u_pcode_get();
3332 pcode_load_blob(ctx
, NULL
, NULL
);
3333 pt
= &ctx
->pcode_types
[v
];
3334 pt
->argument
= NULL
;
3336 pt
->varflags
= varflags
;
3341 const struct type
*t
= pcode_to_type(ctx
, typ
, NULL
);
3342 struct color empty_color
= { 0, 0, false };
3347 if (typ
< 0 && !pcode_get_type(typ
))
3348 pt
->extra_type
= typ
;
3349 while ((size_t)color
>= ctx
->n_colors
)
3350 if (unlikely(!array_add_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, empty_color
, NULL
, ctx
->err
)))
3354 if (!ctx
->colors
[color
].align
) {
3355 ctx
->colors
[color
].size
= t
->size
;
3356 ctx
->colors
[color
].align
= t
->align
;
3358 ajla_assert_lo(ctx
->colors
[color
].size
== t
->size
&&
3359 ctx
->colors
[color
].align
== t
->align
,
3360 (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
));
3365 /*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);*/
3367 for (is
= 0; is
< ctx
->n_colors
; is
++) {
3368 const struct color
*c
= &ctx
->colors
[is
];
3370 if (unlikely(!layout_add(ctx
->layout
, maximum(c
->size
, 1), c
->align
, ctx
->err
)))
3373 if (unlikely(!layout_add(ctx
->layout
, 0, 1, ctx
->err
)))
3378 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3381 ctx
->n_slots
= layout_size(ctx
->layout
);
3383 ctx
->local_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct local_variable
*, 0, 0, ctx
->n_slots
, sizeof(struct local_variable
), ctx
->err
);
3384 if (unlikely(!ctx
->local_variables
))
3387 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
);
3388 if (unlikely(!ctx
->local_variables_flags
))
3391 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3392 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3394 pt
->slot
= NO_FRAME_T
;
3396 pt
->slot
= layout_get(ctx
->layout
, pt
->color
);
3397 ctx
->local_variables
[pt
->slot
].type
= pt
->type
;
3398 /*ctx->local_variables_flags[pt->slot].may_be_borrowed = false;*/
3399 /*if (pt->type->tag == TYPE_TAG_flat_option && !(pt->varflags & VarFlag_Must_Be_Flat))
3400 debug("non-flat variable in %s", function_name(ctx));*/
3401 ctx
->local_variables_flags
[pt
->slot
].must_be_flat
= !!(pt
->varflags
& VarFlag_Must_Be_Flat
);
3402 ctx
->local_variables_flags
[pt
->slot
].must_be_data
= !!(pt
->varflags
& VarFlag_Must_Be_Data
);
3406 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3410 unsigned n_elided
= 0;
3411 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3412 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3416 debug("function, elided %d/%d", n_elided
, ctx
->n_local_variables
);
3420 if (unlikely(!array_init_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ctx
->err
)))
3423 if (unlikely(!pcode_preload_ld(ctx
)))
3427 sfd
= save_find_function_descriptor(md
, fd
);
3434 ctx
->code
= sfd
->code
;
3435 ctx
->code_len
= sfd
->code_size
;
3441 ctx
->labels
= mem_alloc_array_mayfail(mem_alloc_mayfail
, size_t *, 0, 0, ctx
->n_labels
, sizeof(size_t), ctx
->err
);
3442 if (unlikely(!ctx
->labels
))
3444 for (p
= 0; p
< ctx
->n_labels
; p
++)
3445 ctx
->labels
[p
] = no_label
;
3447 if (unlikely(!array_init_mayfail(struct label_ref
, &ctx
->label_ref
, &ctx
->label_ref_len
, ctx
->err
)))
3450 if (unlikely(!array_init_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, ctx
->err
)))
3453 if (unlikely(!array_init_mayfail(code_t
, &ctx
->code
, &ctx
->code_len
, ctx
->err
)))
3456 if (unlikely(!array_init_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, ctx
->err
)))
3459 if (unlikely(ctx
->function_type
== Fn_Record
) || unlikely(ctx
->function_type
== Fn_Option
)) {
3460 if (ctx
->function_type
== Fn_Record
) {
3461 if (unlikely(!pcode_generate_record(ctx
)))
3464 gen_code(OPCODE_UNREACHABLE
);
3466 if (unlikely(!pcode_generate_instructions(ctx
)))
3470 array_finish(code_t
, &ctx
->code
, &ctx
->code_len
);
3471 array_finish(struct line_position
, &ctx
->lp
, &ctx
->lp_size
);
3473 for (is
= 0; is
< ctx
->label_ref_len
; is
++) {
3475 struct label_ref
*lr
= &ctx
->label_ref
[is
];
3476 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
));
3477 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
));
3478 diff
= ((uint32_t)ctx
->labels
[lr
->label
] - (uint32_t)lr
->code_pos
) * sizeof(code_t
);
3479 if (SIZEOF_IP_T
== 2) {
3480 ctx
->code
[lr
->code_pos
] += (code_t
)diff
;
3481 } else if (SIZEOF_IP_T
== 4 && !CODE_ENDIAN
) {
3482 uint32_t val
= ctx
->code
[lr
->code_pos
] | ((uint32_t)ctx
->code
[lr
->code_pos
+ 1] << 16);
3484 ctx
->code
[lr
->code_pos
] = val
& 0xffff;
3485 ctx
->code
[lr
->code_pos
+ 1] = val
>> 16;
3486 } else if (SIZEOF_IP_T
== 4 && CODE_ENDIAN
) {
3487 uint32_t val
= ((uint32_t)ctx
->code
[lr
->code_pos
] << 16) | ctx
->code
[lr
->code_pos
+ 1];
3489 ctx
->code
[lr
->code_pos
] = val
>> 16;
3490 ctx
->code
[lr
->code_pos
+ 1] = val
& 0xffff;
3496 mem_free(ctx
->labels
), ctx
->labels
= NULL
;
3497 mem_free(ctx
->label_ref
), ctx
->label_ref
= NULL
;
3499 ft
= data_alloc_flexible(function_types
, types
, ctx
->types_len
, ctx
->err
);
3502 da(ft
,function_types
)->n_types
= ctx
->types_len
;
3503 memcpy(da(ft
,function_types
)->types
, ctx
->types
, ctx
->types_len
* sizeof(const struct type
*));
3504 mem_free(ctx
->types
);
3510 mem_free(ctx
->colors
), ctx
->colors
= NULL
;
3511 mem_free(ctx
->pcode_types
), ctx
->pcode_types
= NULL
;
3512 mem_free(ctx
->local_types
), ctx
->local_types
= NULL
;
3514 array_finish(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
);
3516 if (profiling_escapes
) {
3517 ctx
->escape_data
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct escape_data
*, 0, 0, ctx
->code_len
, sizeof(struct escape_data
), ctx
->err
);
3518 if (unlikely(!ctx
->escape_data
))
3522 fn
= data_alloc_flexible(function
, local_directory
, ctx
->ld_len
, ctx
->err
);
3526 da(fn
,function
)->frame_slots
= frame_offset
/ slot_size
+ ctx
->n_slots
;
3527 da(fn
,function
)->n_bitmap_slots
= bitmap_slots(ctx
->n_slots
);
3528 da(fn
,function
)->n_arguments
= ctx
->n_real_arguments
;
3529 da(fn
,function
)->n_return_values
= ctx
->n_real_return_values
;
3530 da(fn
,function
)->code
= ctx
->code
;
3531 da(fn
,function
)->code_size
= ctx
->code_len
;
3532 da(fn
,function
)->local_variables
= ctx
->local_variables
;
3534 da(fn
,function
)->local_variables_flags
= ctx
->local_variables_flags
;
3536 mem_free(ctx
->local_variables_flags
);
3537 da(fn
,function
)->local_variables_flags
= sfd
->local_variables_flags
;
3539 da(fn
,function
)->args
= ctx
->args
;
3540 da(fn
,function
)->types_ptr
= pointer_data(ft
);
3541 da(fn
,function
)->record_definition
= ctx
->record_definition
? &ctx
->record_definition
->type
: NULL
;
3542 da(fn
,function
)->function_name
= cast_ptr(char *, ctx
->function_name
);
3543 da(fn
,function
)->module_designator
= md
;
3544 da(fn
,function
)->function_designator
= fd
;
3546 da(fn
,function
)->lp
= ctx
->lp
;
3547 da(fn
,function
)->lp_size
= ctx
->lp_size
;
3549 da(fn
,function
)->lp
= sfd
->lp
;
3550 da(fn
,function
)->lp_size
= sfd
->lp_size
;
3552 memcpy(da(fn
,function
)->local_directory
, ctx
->ld
, ctx
->ld_len
* sizeof(pointer_t
*));
3553 da(fn
,function
)->local_directory_size
= ctx
->ld_len
;
3557 da(fn
,function
)->codegen
= function_build_internal_thunk(codegen_fn
, 1, ia
);
3558 store_relaxed(&da(fn
,function
)->codegen_failed
, 0);
3560 function_init_common(fn
);
3563 /*if (memcmp(ctx->code, sfd->code, ctx->code_len * sizeof(code_t))) internal(file_line, "code mismatch");*/
3564 da(fn
,function
)->loaded_cache
= sfd
->data_saved_cache
;
3565 /*if (da(fn,function)->loaded_cache) debug("loaded cache: %s", function_name(ctx));*/
3568 da(fn
,function
)->escape_data
= ctx
->escape_data
;
3569 da(fn
,function
)->leaf
= ctx
->leaf
;
3570 da(fn
,function
)->is_saved
= is_saved
;
3572 ipret_prefetch_functions(fn
);
3574 return pointer_data(fn
);
3577 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3579 ctx
->ret_val
= pointer_mark();
3582 return ctx
->ret_val
;
3585 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
)
3590 ptr
= pcode_build_function_core(fp
, ip
, pcode
, size
, md
, fd
, &ex
, &err
);
3591 if (unlikely(pointer_is_empty(ptr
)))
3593 if (unlikely(pointer_is_mark(ptr
)))
3594 return function_return(fp
, pointer_error(err
, NULL
, NULL pass_file_line
));
3595 return function_return(fp
, ptr
);
3598 void *pcode_build_function_from_builtin(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3600 const pcode_t
*start
;
3602 struct module_designator
*md
= arguments
[0].ptr
;
3603 struct function_designator
*fd
= arguments
[1].ptr
;
3604 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3605 return pcode_build_function(fp
, ip
, start
, size
, md
, arguments
[1].ptr
);
3608 void *pcode_build_function_from_array(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3612 struct thunk
*thunk
;
3615 const struct function_designator
*fd
;
3616 const pcode_t
*start
;
3619 ptr
= arguments
[0].ptr
;
3620 ex
= pointer_deep_eval(ptr
, fp
, ip
, &thunk
);
3621 if (unlikely(ex
!= POINTER_FOLLOW_THUNK_GO
)) {
3622 if (ex
== POINTER_FOLLOW_THUNK_EXCEPTION
) {
3623 return function_return(fp
, pointer_thunk(thunk
));
3628 array_to_bytes(ptr
, &bytes
, &bytes_l
);
3631 if (unlikely(bytes_l
% sizeof(pcode_t
) != 0))
3632 internal(file_line
, "pcode_build_function_from_array: invalid length: %lu", (unsigned long)bytes_l
);
3634 start
= cast_ptr(const pcode_t
*, bytes
);
3635 size
= bytes_l
/ sizeof(pcode_t
);
3636 fd
= arguments
[2].ptr
;
3638 /*builtin_walk_nested(&start, &size, fd->n_entries, fd->entries);*/
3640 ex
= pcode_build_function(fp
, ip
, start
, size
, arguments
[1].ptr
, fd
);
3647 void *pcode_array_from_builtin(frame_s
*fp
, const code_t attr_unused
*ip
, union internal_arg arguments
[])
3649 const struct type
*t
;
3652 const pcode_t
*start
;
3654 struct module_designator
*md
= arguments
[0].ptr
;
3655 struct function_designator
*fd
= arguments
[1].ptr
;
3657 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3659 t
= type_get_fixed(log_2(sizeof(pcode_t
)), false);
3660 d
= data_alloc_array_flat_mayfail(t
, size
, size
, false, &err pass_file_line
);
3662 return function_return(fp
, pointer_thunk(thunk_alloc_exception_error(err
, NULL
, NULL
, NULL pass_file_line
)));
3665 memcpy(da_array_flat(d
), start
, size
* sizeof(pcode_t
));
3667 return function_return(fp
, pointer_data(d
));
3671 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
)
3675 unsigned n_local_variables
;
3676 unsigned n_arguments
;
3680 if (unlikely(!array_init_mayfail(pcode_t
, &pc
, &pc_l
, err
)))
3684 if (unlikely(!array_add_mayfail(pcode_t, &pc, &pc_l, x, NULL, err)))\
3687 #define addstr(x, l) \
3689 if (unlikely(!array_add_multiple_mayfail(pcode_t, &pc, &pc_l, x, l, NULL, err)))\
3693 n_local_variables
= Op_IsUnary(op
) ? 2 : 3;
3694 n_arguments
= n_local_variables
- 1;
3697 add(Call_Mode_Strict
);
3700 add(n_local_variables
);
3707 for (i
= 0; i
< n_local_variables
; i
++) {
3708 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3720 add(1 + blob_1_len
);
3722 addstr(blob_1
, blob_1_len
);
3723 if (n_arguments
== 2) {
3725 add(1 + blob_2_len
);
3727 addstr(blob_2
, blob_2_len
);
3730 add(Op_IsUnary(op
) ? P_UnaryOp
: P_BinaryOp
);
3731 add(Op_IsUnary(op
) ? 4 : 6);
3734 add(Flag_Free_Argument
| Flag_Op_Strict
);
3736 if (n_arguments
== 2) {
3737 add(Flag_Free_Argument
);
3743 add(Flag_Free_Argument
);
3749 ptr
= pcode_build_function_core(NULL
, NULL
, pc
, pc_l
, NULL
, NULL
, NULL
, err
);
3758 return pointer_empty();
3762 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
)
3764 struct data
*function
;
3767 #ifdef POINTER_FOLLOW_IS_LOCKLESS
3768 const addrlock_depth lock_depth
= DEPTH_THUNK
;
3770 const addrlock_depth lock_depth
= DEPTH_POINTER
;
3774 pointer_follow(ptr
, false, function
, PF_WAIT
, fp
, ip
,
3777 return POINTER_FOLLOW_THUNK_RETRY
);
3779 if (likely(function
!= NULL
)) {
3781 return POINTER_FOLLOW_THUNK_RETRY
;
3784 fn_thunk
= function_build_internal_thunk(build_fn
, n_arguments
, ia
);
3786 barrier_write_before_lock();
3787 address_lock(ptr
, lock_depth
);
3788 if (likely(pointer_is_empty(*pointer_volatile(ptr
)))) {
3789 *pointer_volatile(ptr
) = fn_thunk
;
3790 address_unlock(ptr
, lock_depth
);
3792 address_unlock(ptr
, lock_depth
);
3793 pointer_dereference(fn_thunk
);
3799 static void *pcode_build_op_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3801 pcode_t src_type
= (pcode_t
)a
[0].i
;
3802 pcode_t dest_type
= (pcode_t
)a
[1].i
;
3803 pcode_t op
= (pcode_t
)a
[2].i
;
3804 unsigned flags
= (unsigned)a
[3].i
;
3806 unsigned n_local_variables
;
3807 unsigned n_arguments
;
3809 pcode_t
*pc
= pcode
;
3811 n_local_variables
= flags
& PCODE_FIND_OP_UNARY
? 2 : 3;
3812 n_arguments
= n_local_variables
- 1;
3814 *pc
++ = Fn_Function
;
3815 *pc
++ = Call_Mode_Strict
;
3818 *pc
++ = (pcode_t
)n_local_variables
;
3819 *pc
++ = (pcode_t
)n_arguments
;
3825 for (i
= 0; i
< n_local_variables
; i
++) {
3826 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3835 *pc
++ = n_arguments
;
3836 for (i
= 0; i
< n_arguments
; i
++)
3839 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? P_UnaryOp
: P_BinaryOp
);
3840 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? 4 : 6);
3842 *pc
++ = (pcode_t
)n_arguments
;
3843 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3845 if (!(flags
& PCODE_FIND_OP_UNARY
)) {
3846 *pc
++ = Flag_Free_Argument
;
3852 *pc
++ = Flag_Free_Argument
;
3853 *pc
++ = n_arguments
;
3855 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
));
3857 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3860 static pointer_t fixed_op_thunk
[TYPE_FIXED_N
][OPCODE_FIXED_OP_N
];
3861 static pointer_t int_op_thunk
[TYPE_INT_N
][OPCODE_INT_OP_N
];
3862 static pointer_t real_op_thunk
[TYPE_REAL_N
][OPCODE_REAL_OP_N
];
3863 static pointer_t bool_op_thunk
[OPCODE_BOOL_TYPE_MULT
];
3865 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
)
3867 union internal_arg ia
[4];
3870 type_tag_t tag
= likely(!(flags
& PCODE_CONVERT_FROM_INT
)) ? type
->tag
: rtype
->tag
;
3872 if (TYPE_TAG_IS_FIXED(tag
)) {
3873 unsigned idx
= (code
- OPCODE_FIXED_OP
- (TYPE_TAG_IDX_FIXED(tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
) / OPCODE_FIXED_OP_MULT
;
3874 ajla_assert(idx
< OPCODE_FIXED_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3875 ptr
= &fixed_op_thunk
[TYPE_TAG_IDX_FIXED(tag
) >> 1][idx
];
3876 } else if (TYPE_TAG_IS_INT(tag
)) {
3877 unsigned idx
= (code
- OPCODE_INT_OP
- TYPE_TAG_IDX_INT(tag
) * OPCODE_INT_TYPE_MULT
) / OPCODE_INT_OP_MULT
;
3878 if (idx
>= OPCODE_INT_OP_C
&& idx
< OPCODE_INT_OP_UNARY
)
3879 idx
-= OPCODE_INT_OP_C
;
3880 ajla_assert(idx
< OPCODE_INT_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3881 ptr
= &int_op_thunk
[TYPE_TAG_IDX_INT(tag
)][idx
];
3882 ajla_assert(is_power_of_2(type
->size
), (file_line
, "pcode_find_op_function: invalid integer type size %"PRIuMAX
"", (uintmax_t)type
->size
));
3883 } else if (TYPE_TAG_IS_REAL(tag
)) {
3884 unsigned idx
= (code
- OPCODE_REAL_OP
- TYPE_TAG_IDX_REAL(tag
) * OPCODE_REAL_TYPE_MULT
) / OPCODE_REAL_OP_MULT
;
3885 ajla_assert(idx
< OPCODE_REAL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3886 ptr
= &real_op_thunk
[TYPE_TAG_IDX_REAL(tag
)][idx
];
3888 unsigned idx
= (code
- OPCODE_BOOL_OP
) / OPCODE_BOOL_OP_MULT
;
3889 ajla_assert(idx
< OPCODE_BOOL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3890 ptr
= &bool_op_thunk
[idx
];
3892 internal(file_line
, "pcode_find_op_function: invalid type %u", tag
);
3895 ia
[0].i
= type_to_pcode(type
);
3896 ia
[1].i
= type_to_pcode(rtype
);
3897 ia
[2].i
= code
+ Op_N
;
3900 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_op_function
, 4, ia
, result
);
3903 static void *pcode_build_is_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3906 pcode_t
*pc
= pcode
;
3908 *pc
++ = Fn_Function
;
3909 *pc
++ = Call_Mode_Strict
;
3919 *pc
++ = T_Undetermined
;
3920 *pc
++ = T_Undetermined
;
3925 *pc
++ = T_FlatOption
;
3926 *pc
++ = T_FlatOption
;
3937 *pc
++ = Un_IsException
;
3939 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3948 *pc
++ = Flag_Free_Argument
;
3951 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
)));
3953 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3956 static pointer_t is_exception_thunk
;
3958 void * attr_fastcall
pcode_find_is_exception(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3960 return pcode_alloc_op_function(&is_exception_thunk
, fp
, ip
, pcode_build_is_exception_function
, 0, NULL
, result
);
3963 static void *pcode_build_get_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3966 pcode_t
*pc
= pcode
;
3968 *pc
++ = Fn_Function
;
3969 *pc
++ = Call_Mode_Strict
;
3979 *pc
++ = T_Undetermined
;
3980 *pc
++ = T_Undetermined
;
3997 *pc
++ = Un_ExceptionClass
+ a
[0].i
;
3999 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
4008 *pc
++ = Flag_Free_Argument
;
4011 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
)));
4013 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4016 static pointer_t get_exception_thunk
[3];
4018 void * attr_fastcall
pcode_find_get_exception(unsigned mode
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4020 union internal_arg ia
[1];
4022 return pcode_alloc_op_function(&get_exception_thunk
[mode
], fp
, ip
, pcode_build_get_exception_function
, 1, ia
, result
);
4025 static void *pcode_build_array_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4028 pcode_t
*pc
= pcode
;
4030 *pc
++ = Fn_Function
;
4031 *pc
++ = Call_Mode_Strict
;
4041 *pc
++ = T_Undetermined
;
4042 *pc
++ = T_Undetermined
;
4053 *pc
++ = T_Undetermined
;
4054 *pc
++ = T_Undetermined
;
4064 *pc
++ = P_Array_Load
;
4067 *pc
++ = Flag_Evaluate
;
4081 *pc
++ = Flag_Free_Argument
;
4084 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
)));
4086 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4089 static pointer_t array_load_thunk
;
4091 void * attr_fastcall
pcode_find_array_load_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4093 return pcode_alloc_op_function(&array_load_thunk
, fp
, ip
, pcode_build_array_load_function
, 0, NULL
, result
);
4096 static void *pcode_build_array_len_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4099 pcode_t
*pc
= pcode
;
4101 *pc
++ = Fn_Function
;
4102 *pc
++ = Call_Mode_Strict
;
4112 *pc
++ = T_Undetermined
;
4113 *pc
++ = T_Undetermined
;
4128 *pc
++ = P_Array_Len
;
4132 *pc
++ = Flag_Evaluate
;
4140 *pc
++ = Flag_Free_Argument
;
4143 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
)));
4145 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4148 static pointer_t array_len_thunk
;
4150 void * attr_fastcall
pcode_find_array_len_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4152 return pcode_alloc_op_function(&array_len_thunk
, fp
, ip
, pcode_build_array_len_function
, 0, NULL
, result
);
4155 static void *pcode_build_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4158 pcode_t
*pc
= pcode
;
4160 *pc
++ = Fn_Function
;
4161 *pc
++ = Call_Mode_Strict
;
4171 *pc
++ = T_Undetermined
;
4172 *pc
++ = T_Undetermined
;
4183 *pc
++ = T_FlatOption
;
4184 *pc
++ = T_FlatOption
;
4194 *pc
++ = P_Array_Len_Greater_Than
;
4199 *pc
++ = Flag_Evaluate
;
4211 *pc
++ = Flag_Free_Argument
;
4214 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
)));
4216 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4219 static pointer_t array_len_greater_than_thunk
;
4221 void * attr_fastcall
pcode_find_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4223 return pcode_alloc_op_function(&array_len_greater_than_thunk
, fp
, ip
, pcode_build_array_len_greater_than_function
, 0, NULL
, result
);
4226 static void *pcode_build_array_sub_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4229 pcode_t
*pc
= pcode
;
4231 *pc
++ = Fn_Function
;
4232 *pc
++ = Call_Mode_Strict
;
4242 *pc
++ = T_Undetermined
;
4243 *pc
++ = T_Undetermined
;
4260 *pc
++ = T_Undetermined
;
4261 *pc
++ = T_Undetermined
;
4272 *pc
++ = P_Array_Sub
;
4275 *pc
++ = Flag_Evaluate
;
4294 *pc
++ = Flag_Free_Argument
;
4297 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
)));
4299 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4302 static pointer_t array_sub_thunk
;
4304 void * attr_fastcall
pcode_find_array_sub_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4306 return pcode_alloc_op_function(&array_sub_thunk
, fp
, ip
, pcode_build_array_sub_function
, 0, NULL
, result
);
4309 static void *pcode_build_array_skip_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4312 pcode_t
*pc
= pcode
;
4314 *pc
++ = Fn_Function
;
4315 *pc
++ = Call_Mode_Strict
;
4325 *pc
++ = T_Undetermined
;
4326 *pc
++ = T_Undetermined
;
4337 *pc
++ = T_Undetermined
;
4338 *pc
++ = T_Undetermined
;
4348 *pc
++ = P_Array_Skip
;
4351 *pc
++ = Flag_Evaluate
;
4365 *pc
++ = Flag_Free_Argument
;
4368 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
)));
4370 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4373 static pointer_t array_skip_thunk
;
4375 void * attr_fastcall
pcode_find_array_skip_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4377 return pcode_alloc_op_function(&array_skip_thunk
, fp
, ip
, pcode_build_array_skip_function
, 0, NULL
, result
);
4380 static void *pcode_build_array_append_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4383 pcode_t
*pc
= pcode
;
4385 *pc
++ = Fn_Function
;
4386 *pc
++ = Call_Mode_Strict
;
4396 *pc
++ = T_Undetermined
;
4397 *pc
++ = T_Undetermined
;
4402 *pc
++ = T_Undetermined
;
4403 *pc
++ = T_Undetermined
;
4408 *pc
++ = T_Undetermined
;
4409 *pc
++ = T_Undetermined
;
4429 *pc
++ = P_Array_Append
;
4432 *pc
++ = Flag_Free_Argument
;
4434 *pc
++ = Flag_Free_Argument
;
4439 *pc
++ = Flag_Free_Argument
;
4441 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
)));
4443 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4446 static pointer_t array_append_thunk
;
4448 void * attr_fastcall
pcode_find_array_append_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4450 return pcode_alloc_op_function(&array_append_thunk
, fp
, ip
, pcode_build_array_append_function
, 0, NULL
, result
);
4454 static void *pcode_build_option_ord_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4457 pcode_t
*pc
= pcode
;
4459 *pc
++ = Fn_Function
;
4460 *pc
++ = Call_Mode_Strict
;
4470 *pc
++ = T_Undetermined
;
4471 *pc
++ = T_Undetermined
;
4490 *pc
++ = P_Option_Ord
;
4501 *pc
++ = Flag_Free_Argument
;
4504 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
)));
4506 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4509 static pointer_t option_ord_thunk
;
4511 void * attr_fastcall
pcode_find_option_ord_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4513 return pcode_alloc_op_function(&option_ord_thunk
, fp
, ip
, pcode_build_option_ord_function
, 0, NULL
, result
);
4517 struct function_key
{
4522 static void *pcode_build_record_option_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
4525 pcode_t
*pc
= pcode
;
4526 pcode_t result_type
= a
[0].i
== PCODE_FUNCTION_OPTION_TEST
? T_FlatOption
: T_Undetermined
;
4528 *pc
++ = Fn_Function
;
4529 *pc
++ = Call_Mode_Strict
;
4539 *pc
++ = T_Undetermined
;
4540 *pc
++ = T_Undetermined
;
4545 *pc
++ = result_type
;
4546 *pc
++ = result_type
;
4556 case PCODE_FUNCTION_RECORD_LOAD
:
4557 /* P_Record_Load_Slot already sets Flag_Evaluate */
4558 *pc
++ = P_Record_Load_Slot
;
4562 *pc
++ = (pcode_t
)a
[1].i
;
4564 case PCODE_FUNCTION_OPTION_LOAD
:
4565 *pc
++ = P_Option_Load
;
4568 *pc
++ = Flag_Evaluate
;
4570 *pc
++ = (pcode_t
)a
[1].i
;
4572 case PCODE_FUNCTION_OPTION_TEST
:
4576 *pc
++ = P_Option_Test
;
4580 *pc
++ = (pcode_t
)a
[1].i
;
4583 internal(file_line
, "pcode_build_record_option_load_function: invalid operation %"PRIuMAX
"", (uintmax_t)a
[0].i
);
4592 *pc
++ = Flag_Free_Argument
;
4595 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
)));
4597 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4600 struct pcode_function
{
4601 struct tree_entry entry
;
4602 struct function_key key
;
4606 shared_var
struct tree pcode_functions
;
4607 rwlock_decl(pcode_functions_mutex
);
4609 static int record_option_load_compare(const struct tree_entry
*e1
, uintptr_t e2
)
4611 struct pcode_function
*rl
= get_struct(e1
, struct pcode_function
, entry
);
4612 struct function_key
*key
= cast_cpp(struct function_key
*, num_to_ptr(e2
));
4613 if (rl
->key
.tag
!= key
->tag
)
4614 return (int)rl
->key
.tag
- key
->tag
;
4615 if (rl
->key
.id
< key
->id
)
4617 if (rl
->key
.id
> key
->id
)
4622 static pointer_t
*pcode_find_function_for_key(struct function_key
*key
)
4624 struct tree_entry
*e
;
4626 rwlock_lock_read(&pcode_functions_mutex
);
4627 e
= tree_find(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
));
4628 rwlock_unlock_read(&pcode_functions_mutex
);
4630 struct tree_insert_position ins
;
4631 rwlock_lock_write(&pcode_functions_mutex
);
4632 e
= tree_find_for_insert(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
), &ins
);
4635 struct pcode_function
*rl
;
4636 rl
= mem_alloc_mayfail(struct pcode_function
*, sizeof(struct pcode_function
), &sink
);
4637 if (unlikely(!rl
)) {
4638 rwlock_unlock_write(&pcode_functions_mutex
);
4642 rl
->ptr
= pointer_empty();
4644 tree_insert_after_find(e
, &ins
);
4646 rwlock_unlock_write(&pcode_functions_mutex
);
4648 return &get_struct(e
, struct pcode_function
, entry
)->ptr
;
4651 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
)
4653 struct function_key key
;
4655 union internal_arg ia
[2];
4657 if (unlikely((uintmax_t)slot
> (uintmax_t)signed_maximum(pcode_t
) + zero
)) {
4658 *result
= out_of_memory_ptr
;
4659 return POINTER_FOLLOW_THUNK_RETRY
;
4665 ptr
= pcode_find_function_for_key(&key
);
4666 if (unlikely(!ptr
)) {
4667 *result
= out_of_memory_ptr
;
4668 return POINTER_FOLLOW_THUNK_RETRY
;
4673 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_record_option_load_function
, 2, ia
, result
);
4676 static void thunk_init_run(pointer_t
*ptr
, unsigned n
)
4679 *ptr
= pointer_empty();
4684 static void thunk_free_run(pointer_t
*ptr
, unsigned n
)
4687 if (!pointer_is_empty(*ptr
))
4688 pointer_dereference(*ptr
);
4693 void name(pcode_init
)(void)
4697 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_init_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4698 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_init_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4699 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_init_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4700 thunk_init_run(&is_exception_thunk
, 1);
4701 thunk_init_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4702 thunk_init_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4703 thunk_init_run(&array_load_thunk
, 1);
4704 thunk_init_run(&array_len_thunk
, 1);
4705 thunk_init_run(&array_len_greater_than_thunk
, 1);
4706 thunk_init_run(&array_sub_thunk
, 1);
4707 thunk_init_run(&array_skip_thunk
, 1);
4708 thunk_init_run(&array_append_thunk
, 1);
4709 thunk_init_run(&option_ord_thunk
, 1);
4710 tree_init(&pcode_functions
);
4711 rwlock_init(&pcode_functions_mutex
);
4714 void name(pcode_done
)(void)
4717 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_free_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4718 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_free_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4719 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_free_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4720 thunk_free_run(&is_exception_thunk
, 1);
4721 thunk_free_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4722 thunk_free_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4723 thunk_free_run(&array_load_thunk
, 1);
4724 thunk_free_run(&array_len_thunk
, 1);
4725 thunk_free_run(&array_len_greater_than_thunk
, 1);
4726 thunk_free_run(&array_sub_thunk
, 1);
4727 thunk_free_run(&array_skip_thunk
, 1);
4728 thunk_free_run(&array_append_thunk
, 1);
4729 thunk_free_run(&option_ord_thunk
, 1);
4730 while (!tree_is_empty(&pcode_functions
)) {
4731 struct pcode_function
*rl
= get_struct(tree_any(&pcode_functions
), struct pcode_function
, entry
);
4732 if (!pointer_is_empty(rl
->ptr
))
4733 pointer_dereference(rl
->ptr
);
4734 tree_delete(&rl
->entry
);
4737 rwlock_done(&pcode_functions_mutex
);