2 * Copyright (C) 2024 Mikulas Patocka
4 * This file is part of Ajla.
6 * Ajla is free software: you can redistribute it and/or modify it under the
7 * terms of the GNU General Public License as published by the Free Software
8 * Foundation, either version 3 of the License, or (at your option) any later
11 * Ajla is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13 * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along with
16 * Ajla. If not, see <https://www.gnu.org/licenses/>.
42 #define NO_OPCODE ((code_t)-1)
44 #define fx(n) (OPCODE_FIXED_OP + (OPCODE_FIXED_OP_##n) * OPCODE_FIXED_OP_MULT)
45 #define in(n) (OPCODE_INT_OP + (OPCODE_INT_OP_##n) * OPCODE_INT_OP_MULT)
46 #define re(n) (OPCODE_REAL_OP + (OPCODE_REAL_OP_##n) * OPCODE_REAL_OP_MULT)
47 #define bo(n) (OPCODE_BOOL_OP + (OPCODE_BOOL_OP_##n) * OPCODE_BOOL_OP_MULT)
49 #define Op_Mov (Op_N + 0)
50 #define Op_Copy (Op_N + 1)
51 #define Op_Ldc (Op_N + 2)
52 #define Op_NN (Op_N + 3)
54 shared_var
const code_t pcode2code
[Op_NN
][5]
55 #ifndef FILE_COMPRESSION
57 { fx(add
), fx(add
), in(add
), re(add
), NO_OPCODE
, },
58 { fx(subtract
), fx(subtract
), in(subtract
), re(subtract
), NO_OPCODE
, },
59 { fx(multiply
), fx(multiply
), in(multiply
), re(multiply
), NO_OPCODE
, },
60 { fx(divide
), fx(udivide
), in(divide
), NO_OPCODE
, NO_OPCODE
, },
61 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(divide
), NO_OPCODE
, },
62 { fx(modulo
), fx(umodulo
), in(modulo
), re(modulo
), NO_OPCODE
, },
63 { fx(power
), fx(power
), in(power
), re(power
), NO_OPCODE
, },
64 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atan2
), NO_OPCODE
, },
65 { fx(and), fx(and), in(and), NO_OPCODE
, bo(and), },
66 { fx(or), fx(or), in(or), NO_OPCODE
, bo(or), },
67 { fx(xor), fx(xor), in(xor), NO_OPCODE
, bo(not_equal
), },
68 { fx(shl
), fx(shl
), in(shl
), re(ldexp
), NO_OPCODE
, },
69 { fx(shr
), fx(ushr
), in(shr
), NO_OPCODE
, NO_OPCODE
, },
70 { fx(rol
), fx(rol
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
71 { fx(ror
), fx(ror
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
72 { fx(bts
), fx(bts
), in(bts
), NO_OPCODE
, NO_OPCODE
, },
73 { fx(btr
), fx(btr
), in(btr
), NO_OPCODE
, NO_OPCODE
, },
74 { fx(btc
), fx(btc
), in(btc
), NO_OPCODE
, NO_OPCODE
, },
75 { fx(equal
), fx(equal
), in(equal
), re(equal
), bo(equal
), },
76 { fx(not_equal
), fx(not_equal
), in(not_equal
), re(not_equal
), bo(not_equal
), },
77 { fx(less
), fx(uless
), in(less
), re(less
), bo(less
), },
78 { fx(less_equal
), fx(uless_equal
), in(less_equal
), re(less_equal
), bo(less_equal
), },
79 { fx(bt
), fx(bt
), in(bt
), NO_OPCODE
, NO_OPCODE
, },
80 { fx(not), fx(not), in(not), NO_OPCODE
, bo(not), },
81 { fx(neg
), fx(neg
), in(neg
), re(neg
), NO_OPCODE
, },
82 { fx(inc
), fx(inc
), in(inc
), NO_OPCODE
, NO_OPCODE
, },
83 { fx(dec
), fx(dec
), in(dec
), NO_OPCODE
, NO_OPCODE
, },
84 { fx(bswap
), fx(bswap
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
85 { fx(brev
), fx(brev
), NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
86 { fx(bsf
), fx(bsf
), in(bsf
), NO_OPCODE
, NO_OPCODE
, },
87 { fx(bsr
), fx(bsr
), in(bsr
), NO_OPCODE
, NO_OPCODE
, },
88 { fx(popcnt
), fx(popcnt
), in(popcnt
), NO_OPCODE
, NO_OPCODE
, },
89 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sqrt
), NO_OPCODE
, },
90 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cbrt
), NO_OPCODE
, },
91 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sin
), NO_OPCODE
, },
92 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cos
), NO_OPCODE
, },
93 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(tan
), NO_OPCODE
, },
94 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(asin
), NO_OPCODE
, },
95 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(acos
), NO_OPCODE
, },
96 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atan
), NO_OPCODE
, },
97 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(sinh
), NO_OPCODE
, },
98 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(cosh
), NO_OPCODE
, },
99 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(tanh
), NO_OPCODE
, },
100 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(asinh
), NO_OPCODE
, },
101 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(acosh
), NO_OPCODE
, },
102 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(atanh
), NO_OPCODE
, },
103 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp2
), NO_OPCODE
, },
104 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp
), NO_OPCODE
, },
105 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exp10
), NO_OPCODE
, },
106 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log2
), NO_OPCODE
, },
107 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log
), NO_OPCODE
, },
108 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(log10
), NO_OPCODE
, },
109 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(round
), NO_OPCODE
, },
110 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(floor
), NO_OPCODE
, },
111 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(ceil
), NO_OPCODE
, },
112 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(trunc
), NO_OPCODE
, },
113 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(fract
), NO_OPCODE
, },
114 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(mantissa
), NO_OPCODE
, },
115 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(exponent
), NO_OPCODE
, },
116 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(next_number
), NO_OPCODE
, },
117 { NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, re(prev_number
), NO_OPCODE
, },
118 { fx(to_int
), fx(uto_int
), in(to_int
), re(to_int
), NO_OPCODE
, },
119 { fx(from_int
), fx(ufrom_int
), in(from_int
), re(from_int
), NO_OPCODE
, },
120 { OPCODE_IS_EXCEPTION
, NO_OPCODE
, NO_OPCODE
, re(is_exception
), NO_OPCODE
, },
121 { OPCODE_EXCEPTION_CLASS
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
122 { OPCODE_EXCEPTION_TYPE
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
123 { OPCODE_EXCEPTION_AUX
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
124 { OPCODE_SYSTEM_PROPERTY
,NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, NO_OPCODE
, },
125 { fx(move
), fx(move
), in(move
), re(move
), bo(move
), },
126 { fx(copy
), fx(copy
), in(copy
), re(copy
), bo(copy
), },
127 { fx(ldc
), fx(ldc
), in(ldc
), re(ldc
), NO_OPCODE
, },
137 static void instruction_class(const struct type
*t
, unsigned *cls
, code_t
*typeq
, pcode_t op
)
139 if ((op
== Un_IsException
&& !TYPE_TAG_IS_REAL(t
->tag
)) || op
== Un_ExceptionClass
|| op
== Un_ExceptionType
|| op
== Un_ExceptionAux
|| op
== Un_SystemProperty
) {
142 } else if (TYPE_TAG_IS_FIXED(t
->tag
)) {
143 *typeq
= (TYPE_TAG_IDX_FIXED(t
->tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
;
144 *cls
= TYPE_TAG_FIXED_IS_UNSIGNED(t
->tag
);
145 } else if (TYPE_TAG_IS_INT(t
->tag
)) {
146 *typeq
= TYPE_TAG_IDX_INT(t
->tag
) * OPCODE_INT_TYPE_MULT
;
148 } else if (TYPE_TAG_IS_REAL(t
->tag
)) {
149 *typeq
= TYPE_TAG_IDX_REAL(t
->tag
) * OPCODE_REAL_TYPE_MULT
;
151 } else if (t
->tag
== TYPE_TAG_flat_option
) {
155 internal(file_line
, "instruction_class: invalid type %u", t
->tag
);
159 static code_t
get_code(pcode_t op
, const struct type
*t
)
163 ajla_assert(op
>= 0 && op
< Op_NN
, (file_line
, "get_code: invalid operation %"PRIdMAX
"", (intmax_t)op
));
164 instruction_class(t
, &cls
, &typeq
, op
);
165 code
= pcode2code
[op
][cls
];
166 ajla_assert(code
!= NO_OPCODE
, (file_line
, "get_code: invalid instruction and type: %"PRIdMAX
", %u", (intmax_t)op
, t
->tag
));
168 return code_alt(code
);
171 #define INIT_ARG_MODE 0
172 #define INIT_ARG_MODE_1 1
173 typedef unsigned char arg_mode_t
;
175 static bool adjust_arg_mode(arg_mode_t
*am
, uintmax_t offs
, ajla_error_t
*mayfail
)
178 if (offs
+ uzero
<= 0xff) my_am
= 0;
179 else if (offs
+ uzero
<= 0xffffU
) my_am
= 1;
180 else if (offs
+ uzero
<= 0xffffffffUL
+ uzero
) my_am
= 2;
182 if (unlikely(my_am
>= ARG_MODE_N
)) {
184 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
187 internal(file_line
, "adjust_arg_mode: too big arg mode: offset %"PRIuMAX
", max mode %d", (uintmax_t)offs
, ARG_MODE_N
);
189 if (unlikely(my_am
> *am
))
194 #define get_arg_mode(am, val) \
196 if (unlikely(!adjust_arg_mode(&(am), (val), ctx->err))) \
201 const struct type
*type
;
206 const struct type
*type
;
207 struct local_arg
*argument
;
211 bool is_dereferenced_in_call_argument
;
227 struct tree_entry entry
;
232 struct build_function_context
{
233 const pcode_t
*pcode
;
234 const pcode_t
*pcode_limit
;
235 const pcode_t
*pcode_instr_end
;
240 pcode_t function_type
;
241 pcode_t n_local_types
;
243 frame_t n_local_variables
;
245 arg_t n_return_values
;
246 arg_t n_real_arguments
;
247 arg_t n_real_return_values
;
250 uint8_t *function_name
;
252 struct local_type
*local_types
;
253 struct pcode_type
*pcode_types
; /* indexed by pcode idx */
254 struct layout
*layout
;
255 struct local_variable
*local_variables
; /* indexed by slot */
256 struct local_variable_flags
*local_variables_flags
; /* indexed by slot */
258 struct color
*colors
;
262 struct label_ref
*label_ref
;
263 size_t label_ref_len
;
269 struct local_arg
*args
;
271 const struct type
**types
;
273 struct data
*ft_free
;
278 frame_t
*record_entries
;
279 size_t record_entries_len
;
281 struct record_definition
*record_definition
;
283 struct line_position
*lp
;
286 struct escape_data
*escape_data
;
288 unsigned checkpoint_num
;
293 pcode_t builtin_type_indices
[TYPE_TAG_N
];
296 static const pcode_t no_type_index
= -1;
297 static const pcode_t error_type_index
= -2;
298 static const size_t no_label
= (size_t)-1;
300 static void init_ctx(struct build_function_context
*ctx
)
303 ctx
->n_real_arguments
= 0;
304 ctx
->function_name
= NULL
;
305 ctx
->local_types
= NULL
;
306 ctx
->pcode_types
= NULL
;
308 ctx
->local_variables
= NULL
;
309 ctx
->local_variables_flags
= NULL
;
312 ctx
->label_ref
= NULL
;
314 tree_init(&ctx
->ld_tree
);
320 ctx
->record_entries
= NULL
;
321 ctx
->record_definition
= NULL
;
324 ctx
->escape_data
= NULL
;
325 ctx
->checkpoint_num
= 0;
327 for (i
= 0; i
< n_array_elements(ctx
->builtin_type_indices
); i
++)
328 ctx
->builtin_type_indices
[i
] = no_type_index
;
331 static void free_ld_tree(struct build_function_context
*ctx
)
333 while (!tree_is_empty(&ctx
->ld_tree
)) {
334 struct ld_ref
*ld_ref
= get_struct(tree_any(&ctx
->ld_tree
), struct ld_ref
, entry
);
335 tree_delete(&ld_ref
->entry
);
340 static void done_ctx(struct build_function_context
*ctx
)
342 if (ctx
->function_name
)
343 mem_free(ctx
->function_name
);
344 if (ctx
->local_types
)
345 mem_free(ctx
->local_types
);
346 if (ctx
->pcode_types
)
347 mem_free(ctx
->pcode_types
);
349 layout_free(ctx
->layout
);
350 if (ctx
->local_variables
)
351 mem_free(ctx
->local_variables
);
352 if (ctx
->local_variables_flags
)
353 mem_free(ctx
->local_variables_flags
);
355 mem_free(ctx
->colors
);
357 mem_free(ctx
->labels
);
359 mem_free(ctx
->label_ref
);
366 mem_free(ctx
->types
);
368 mem_free(ctx
->ft_free
);
371 if (ctx
->record_entries
)
372 mem_free(ctx
->record_entries
);
373 if (ctx
->record_definition
) {
374 mem_free(ctx
->record_definition
->idx_to_frame
);
375 mem_free(ctx
->record_definition
);
379 if (ctx
->escape_data
)
380 mem_free(ctx
->escape_data
);
383 static char *function_name(const struct build_function_context
*ctx
)
385 if (ctx
->function_name
)
386 return cast_ptr(char *, ctx
->function_name
);
390 static pcode_t
pcode_get_fn(struct build_function_context
*ctx argument_position
)
392 ajla_assert(ctx
->pcode
< ctx
->pcode_limit
, (caller_file_line
, "pcode_get_fn(%s): no pcode left", function_name(ctx
)));
393 return *ctx
->pcode
++;
395 #define pcode_get() pcode_get_fn(ctx pass_file_line)
397 static pcode_t
u_pcode_get_fn(struct build_function_context
*ctx argument_position
)
399 pcode_t p
= pcode_get_fn(ctx pass_position
);
400 ajla_assert(p
>= 0, (caller_file_line
, "u_pcode_get_fn(%s): negative pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)p
));
403 #define u_pcode_get() u_pcode_get_fn(ctx pass_file_line)
405 typedef const pcode_t
*pcode_position_save_t
;
407 static inline void pcode_position_save(struct build_function_context
*ctx
, pcode_position_save_t
*save
)
412 static inline void pcode_position_restore(struct build_function_context
*ctx
, const pcode_position_save_t
*save
)
417 typedef size_t code_position_save_t
;
419 static inline void code_position_save(struct build_function_context
*ctx
, code_position_save_t
*save
)
421 *save
= ctx
->code_len
;
424 static inline void code_position_restore(struct build_function_context
*ctx
, const code_position_save_t
*save
)
426 ajla_assert_lo(ctx
->code_len
>= *save
, (file_line
, "code_position_restore(%s): attempting to restore forward: %"PRIuMAX
" < %"PRIuMAX
"", function_name(ctx
), (uintmax_t)ctx
->code_len
, (uintmax_t)*save
));
427 ctx
->code_len
= *save
;
430 const struct type
*pcode_get_type(pcode_t q
)
432 const struct type
*t
;
435 t
= type_get_fixed(0, false);
438 t
= type_get_fixed(0, true);
441 t
= type_get_fixed(1, false);
444 t
= type_get_fixed(1, true);
447 t
= type_get_fixed(2, false);
450 t
= type_get_fixed(2, true);
453 t
= type_get_fixed(3, false);
456 t
= type_get_fixed(3, true);
459 t
= type_get_fixed(4, false);
462 t
= type_get_fixed(4, true);
466 t
= type_get_int(INT_DEFAULT_N
);
485 t
= type_get_real(0);
488 t
= type_get_real(1);
491 t
= type_get_real(2);
494 t
= type_get_real(3);
497 t
= type_get_real(4);
501 t
= type_get_flat_option();
505 t
= type_get_unknown();
515 static const struct type
*pcode_to_type(const struct build_function_context
*ctx
, pcode_t q
, ajla_error_t
*mayfail
)
517 const struct type
*t
;
519 ajla_assert_lo(q
< ctx
->n_local_types
, (file_line
, "pcode_to_type(%s): invalid local type: %"PRIdMAX
" >= %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
, (intmax_t)ctx
->n_local_types
));
520 return ctx
->local_types
[q
].type
;
522 t
= pcode_get_type(q
);
524 if (q
== T_SInt64
|| q
== T_UInt64
|| q
== T_SInt128
|| q
== T_UInt128
)
525 return pcode_get_type(T_Integer128
);
526 if (q
== T_Real16
|| q
== T_Real32
|| q
== T_Real64
|| q
== T_Real80
|| q
== T_Real128
)
527 return pcode_get_type(T_Integer128
);
528 if (unlikely(!mayfail
))
529 internal(file_line
, "pcode_to_type(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
530 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_NOT_SUPPORTED
);
535 static pcode_t
type_to_pcode(const struct type
*type
)
537 if (TYPE_TAG_IS_FIXED(type
->tag
))
538 return (pcode_t
)(T_SInt8
- TYPE_TAG_IDX_FIXED(type
->tag
));
539 else if (TYPE_TAG_IS_INT(type
->tag
))
540 return (pcode_t
)(T_Integer8
- TYPE_TAG_IDX_INT(type
->tag
));
541 else if (TYPE_TAG_IS_REAL(type
->tag
))
542 return (pcode_t
)(T_Real16
- TYPE_TAG_IDX_REAL(type
->tag
));
543 else if (type
->tag
== TYPE_TAG_flat_option
)
546 internal(file_line
, "type_to_pcode: invalid type %u", type
->tag
);
550 static pcode_t
pcode_to_type_index(struct build_function_context
*ctx
, pcode_t q
, bool non_flat
)
553 const struct type
*type
= pcode_to_type(ctx
, q
, NULL
);
554 if (!TYPE_IS_FLAT(type
) && non_flat
)
555 return no_type_index
;
558 result
= &ctx
->local_types
[q
].type_index
;
560 unsigned tag
= type
->tag
;
561 ajla_assert_lo(tag
< n_array_elements(ctx
->builtin_type_indices
), (file_line
, "pcode_to_type_index(%s): invalid type tag %u", function_name(ctx
), tag
));
562 result
= &ctx
->builtin_type_indices
[tag
];
564 if (*result
!= no_type_index
)
566 if (unlikely((pcode_t
)ctx
->types_len
< 0)) {
567 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "type array overflow");
568 return error_type_index
;
570 if (unlikely(!array_add_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, type
, NULL
, ctx
->err
)))
571 return error_type_index
;
572 return *result
= (pcode_t
)(ctx
->types_len
- 1);
575 #define pcode_get_var_deref(var, deref) \
577 pcode_t r_ = u_pcode_get(); \
578 ajla_assert_lo(!(r_ & ~(pcode_t)Flag_Free_Argument), (file_line, "pcode_get_ref(%s): invalid reference flag %"PRIdMAX"", function_name(ctx), (intmax_t)r_));\
579 *(deref) = !!(r_ & Flag_Free_Argument); \
580 *(var) = pcode_get(); \
583 #define var_elided(idx) (((idx) < zero) || ctx->pcode_types[idx].type == NULL)
585 static struct pcode_type
*get_var_type(struct build_function_context
*ctx
, pcode_t v
)
587 ajla_assert_lo(!var_elided(v
), (file_line
, "get_var_type(%s): variable %"PRIdMAX
" is elided", function_name(ctx
), (intmax_t)v
));
588 ajla_assert_lo((frame_t
)v
< ctx
->n_local_variables
, (file_line
, "get_var_type(%s): invalid local variable %"PRIdMAX
", limit %"PRIuMAX
"", function_name(ctx
), (intmax_t)v
, (uintmax_t)ctx
->n_local_variables
));
589 return &ctx
->pcode_types
[v
];
592 static bool pcode_load_blob(struct build_function_context
*ctx
, uint8_t **blob
, size_t *l
)
597 if (unlikely(!array_init_mayfail(uint8_t, blob
, l
, ctx
->err
)))
601 q
= 0; /* avoid warning */
603 for (i
= 0; i
< n
; i
++) {
611 if (unlikely(!array_add_mayfail(uint8_t, blob
, l
, (uint8_t)val
, NULL
, ctx
->err
)))
619 static bool pcode_generate_blob(uint8_t *str
, size_t str_len
, pcode_t
**res_blob
, size_t *res_len
, ajla_error_t
*err
)
622 if (unlikely(str_len
> signed_maximum(pcode_t
))) {
623 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), err
, "pcode overflow");
626 if (unlikely(!array_init_mayfail(pcode_t
, res_blob
, res_len
, err
)))
628 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, 0, NULL
, err
)))
630 for (i
= 0; i
< str_len
; i
++) {
632 if (!(**res_blob
% sizeof(pcode_t
))) {
633 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, b
, NULL
, err
)))
636 (*res_blob
)[*res_len
- 1] |= (upcode_t
)((b
) & 0xff) << (**res_blob
% sizeof(pcode_t
) * 8);
643 static pointer_t
*pcode_module_load_function(struct build_function_context
*ctx
)
648 uint8_t *blob
= NULL
;
650 struct module_designator
*md
= NULL
;
651 struct function_designator
*fd
= NULL
;
655 path_idx
= (unsigned)q
;
656 if (unlikely(q
!= (pcode_t
)path_idx
))
657 goto exception_overflow
;
658 program
= path_idx
& 1;
660 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
663 md
= module_designator_alloc(path_idx
, blob
, l
, program
, ctx
->err
);
667 mem_free(blob
), blob
= NULL
;
669 fd
= function_designator_alloc(ctx
->pcode
, ctx
->err
);
672 ctx
->pcode
+= fd
->n_entries
+ 1;
674 ptr
= module_load_function(md
, fd
, false, ctx
->err
);
678 module_designator_free(md
), md
= NULL
;
679 function_designator_free(fd
), fd
= NULL
;
684 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "pcode overflow");
689 module_designator_free(md
);
691 function_designator_free(fd
);
695 #define no_function_idx ((size_t)-1)
697 static int ld_tree_compare(const struct tree_entry
*e
, uintptr_t ptr
)
699 struct ld_ref
*ld_ref
= get_struct(e
, struct ld_ref
, entry
);
700 uintptr_t ld_ptr
= ptr_to_num(ld_ref
->ptr
);
708 static size_t pcode_module_load_function_idx(struct build_function_context
*ctx
, pointer_t
*ptr
, bool must_exist
)
710 struct tree_entry
*e
;
711 struct ld_ref
*ld_ref
;
712 struct tree_insert_position ins
;
714 e
= tree_find_for_insert(&ctx
->ld_tree
, ld_tree_compare
, ptr_to_num(ptr
), &ins
);
716 ld_ref
= get_struct(e
, struct ld_ref
, entry
);
720 if (unlikely(must_exist
))
721 internal(file_line
, "pcode_module_load_function_idx: local directory preload didn't work");
723 ld_ref
= mem_alloc_mayfail(struct ld_ref
*, sizeof(struct ld_ref
), ctx
->err
);
724 if (unlikely(!ld_ref
))
725 return no_function_idx
;
727 ld_ref
->idx
= ctx
->ld_len
;
729 tree_insert_after_find(&ld_ref
->entry
, &ins
);
731 if (unlikely(!array_add_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ptr
, NULL
, ctx
->err
)))
732 return no_function_idx
;
733 return ctx
->ld_len
- 1;
736 #define gen_code(n) \
738 if (unlikely(!array_add_mayfail(code_t, &ctx->code, &ctx->code_len, n, NULL, ctx->err)))\
743 #define gen_uint32(n) \
745 gen_code((code_t)((n) & 0xffff)); \
746 gen_code((code_t)((n) >> 15 >> 1)); \
749 #define gen_uint32(n) \
751 gen_code((code_t)((n) >> 15 >> 1)); \
752 gen_code((code_t)((n) & 0xffff)); \
756 #define gen_am(am, m) \
759 gen_code((code_t)(m)); \
760 } else if (am == 2) { \
763 internal(file_line, "gen_am(%s): arg mode %d", function_name(ctx), am);\
767 #define gen_am_two(am, m, n) \
770 gen_code((code_t)((m) + ((n) << 8))); \
771 } else if (am == 1) { \
772 gen_code((code_t)(m)); \
773 gen_code((code_t)(n)); \
774 } else if (am == 2) { \
778 internal(file_line, "gen_am_two(%s): arg mode %d", function_name(ctx), am);\
782 #define gen_relative_jump(lbl, diff) \
785 ajla_assert_lo((lbl) < ctx->n_labels, (file_line, "gen_relative_jump(%s): invalid label %"PRIdMAX"", function_name(ctx), (intmax_t)(lbl)));\
786 if (ctx->labels[lbl] == no_label) { \
787 struct label_ref lr; \
788 lr.code_pos = ctx->code_len; \
790 if (unlikely(!array_add_mayfail(struct label_ref, &ctx->label_ref, &ctx->label_ref_len, lr, NULL, ctx->err)))\
792 target = -(((uint32_t)(diff) + 1) / (uint32_t)sizeof(code_t) * (uint32_t)sizeof(code_t));\
794 target = ((uint32_t)ctx->labels[lbl] - (uint32_t)(ctx->code_len + SIZEOF_IP_T / (uint32_t)sizeof(code_t))) * (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
)
808 pcode_t n_used_params
;
810 if (unlikely(ctx
->is_eval
))
813 am
= INIT_ARG_MODE_1
;
814 get_arg_mode(am
, n_params
);
817 for (i
= 0; i
< n_params
; i
++) {
818 const struct pcode_type
*tv
;
819 pcode_t var
= params
[i
];
822 tv
= get_var_type(ctx
, var
);
823 get_arg_mode(am
, tv
->slot
);
827 code
= OPCODE_CHECKPOINT
;
828 code
+= am
* OPCODE_MODE_MULT
;
830 gen_am(ARG_MODE_N
- 1, ctx
->checkpoint_num
);
832 gen_am(am
, n_used_params
);
834 for (i
= 0; i
< n_params
; i
++) {
835 const struct pcode_type
*tv
;
836 pcode_t var
= params
[i
];
839 tv
= get_var_type(ctx
, var
);
840 gen_am(am
, tv
->slot
);
843 ctx
->checkpoint_num
++;
844 if (unlikely(!ctx
->checkpoint_num
)) {
845 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "checkpoint number overflow");
854 static bool pcode_free(struct build_function_context
*ctx
, pcode_t res
)
857 const struct pcode_type
*tr
;
859 const struct color
*c
;
861 if (unlikely(var_elided(res
)))
863 tr
= get_var_type(ctx
, res
);
865 get_arg_mode(am
, tr
->slot
);
866 c
= &ctx
->colors
[tr
->color
];
867 if (!TYPE_IS_FLAT(tr
->type
) && c
->is_argument
)
868 code
= OPCODE_DEREFERENCE_CLEAR
;
870 code
= OPCODE_DEREFERENCE
;
871 code
+= am
* OPCODE_MODE_MULT
;
873 gen_am(am
, tr
->slot
);
881 static bool pcode_copy(struct build_function_context
*ctx
, bool type_cast
, pcode_t res
, pcode_t a1
, bool a1_deref
)
883 const struct pcode_type
*tr
, *t1
;
887 tr
= get_var_type(ctx
, res
);
888 t1
= get_var_type(ctx
, a1
);
890 if (t1
->slot
== tr
->slot
) {
891 ajla_assert(a1_deref
, (file_line
, "pcode_copy(%s): dereference not set", function_name(ctx
)));
893 * If we copy a value to itself, we must clear may_be_borrowed,
894 * otherwise we get failure in start03.ajla and start04.ajla.
896 * (note that pcode_copy is called from pcode_structured_write)
898 * The reason for the crash is that may_be_borrowed is per-variable,
899 * not per-slot flag - if we copy to a different variable occupying
900 * the same slot, we won't see may_be_borrowed anymore.
903 if (t1
->type
->size
== 0) {
905 get_arg_mode(am
, t1
->slot
);
906 code
= OPCODE_TAKE_BORROWED
;
907 code
+= am
* OPCODE_MODE_MULT
;
909 gen_am(am
, t1
->slot
);
915 if ((t1
->type
->size
== 0 && tr
->type
->size
== 0) || type_cast
) {
916 const struct color
*c
= &ctx
->colors
[t1
->color
];
918 get_arg_mode(am
, t1
->slot
);
919 get_arg_mode(am
, tr
->slot
);
921 code
= a1_deref
? OPCODE_BOX_MOVE_CLEAR
: OPCODE_BOX_COPY
;
923 code
= a1_deref
? (c
->is_argument
? OPCODE_REF_MOVE_CLEAR
: OPCODE_REF_MOVE
) : OPCODE_REF_COPY
;
925 code
+= am
* OPCODE_MODE_MULT
;
927 gen_am_two(am
, t1
->slot
, tr
->slot
);
928 } else if (t1
->type
->tag
== TYPE_TAG_flat_record
|| t1
->type
->tag
== TYPE_TAG_flat_array
) {
929 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
));
931 get_arg_mode(am
, t1
->slot
);
932 get_arg_mode(am
, tr
->slot
);
933 code
= a1_deref
? OPCODE_FLAT_MOVE
: OPCODE_FLAT_COPY
;
934 code
+= am
* OPCODE_MODE_MULT
;
936 gen_am_two(am
, t1
->slot
, tr
->slot
);
938 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
));
940 get_arg_mode(am
, t1
->slot
);
941 get_arg_mode(am
, tr
->slot
);
942 code
= get_code(a1_deref
? Op_Mov
: Op_Copy
, t1
->type
);
943 code
+= am
* OPCODE_MODE_MULT
;
945 gen_am_two(am
, t1
->slot
, tr
->slot
);
953 static bool pcode_process_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
, pcode_t
*n_real_arguments
, arg_mode_t
*am
)
956 if (n_real_arguments
)
957 *n_real_arguments
= 0;
958 for (ai
= 0; ai
< n_arguments
; ai
++) {
960 struct pcode_type
*t1
;
962 pcode_get_var_deref(&a1
, &deref
);
963 if (unlikely(var_elided(a1
)))
965 t1
= get_var_type(ctx
, a1
);
966 if (n_real_arguments
) {
967 get_arg_mode(*am
, t1
->slot
);
968 (*n_real_arguments
)++;
969 t1
->is_dereferenced_in_call_argument
= deref
;
973 flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
974 if (!TYPE_IS_FLAT(t1
->type
))
975 flags
|= OPCODE_CALL_MAY_GIVE
;
977 if (!t1
->is_dereferenced_in_call_argument
&& !TYPE_IS_FLAT(t1
->type
))
978 flags
|= OPCODE_CALL_MAY_LEND
;
980 gen_am_two(*am
, t1
->slot
, flags
);
983 if (n_real_arguments
)
984 get_arg_mode(*am
, *n_real_arguments
);
991 static bool pcode_dereference_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
)
994 for (ai
= 0; ai
< n_arguments
; ai
++) {
997 pcode_get_var_deref(&a1
, &deref
);
999 if (unlikely(!pcode_free(ctx
, a1
)))
1009 static bool pcode_finish_call(struct build_function_context
*ctx
, const struct pcode_type
**rets
, size_t rets_l
, bool test_flat
)
1013 frame_t
*vars
= NULL
;
1018 for (i
= 0; i
< rets_l
; i
++) {
1019 const struct pcode_type
*tv
= rets
[i
];
1020 if (ARG_MODE_N
>= 3) {
1021 gen_uint32(tv
->slot
);
1023 gen_code((code_t
)tv
->slot
);
1025 gen_code(TYPE_IS_FLAT(tv
->type
) ? OPCODE_MAY_RETURN_FLAT
: 0);
1028 if (unlikely(test_flat
)) {
1031 if (unlikely(!gen_checkpoint(ctx
, NULL
, 0)))
1034 vars
= mem_alloc_array_mayfail(mem_alloc_mayfail
, frame_t
*, 0, 0, ctx
->n_slots
, sizeof(frame_t
), ctx
->err
);
1035 if (unlikely(!vars
))
1037 am
= INIT_ARG_MODE_1
;
1038 for (slot
= MIN_USEABLE_SLOT
; slot
< ctx
->n_slots
; slot
++) {
1039 if (ctx
->local_variables_flags
[slot
].must_be_flat
) {
1040 vars
[n_vars
++] = slot
;
1041 get_arg_mode(am
, slot
);
1046 get_arg_mode(am
, n_vars
);
1047 code
= OPCODE_ESCAPE_NONFLAT
;
1048 code
+= am
* OPCODE_MODE_MULT
;
1051 for (i
= 0; i
< n_vars
; i
++)
1052 gen_am(am
, vars
[i
]);
1066 static bool pcode_call(struct build_function_context
*ctx
, pcode_t instr
)
1069 arg_mode_t am
= INIT_ARG_MODE
;
1072 const struct pcode_type
*tr
= NULL
; /* avoid warning */
1073 const struct pcode_type
*ts
= NULL
; /* avoid warning */
1074 pcode_t call_mode
= 0; /* avoid warning */
1075 pcode_t src_fn
= 0; /* avoid warning */
1076 bool src_deref
= false; /* avoid warning */
1079 pcode_t n_arguments
, n_real_arguments
;
1080 arg_t n_return_values
, n_real_return_values
;
1081 size_t fn_idx
= 0; /* avoid warning */
1082 pcode_position_save_t saved
;
1083 const struct pcode_type
**rets
= NULL
;
1086 if (instr
== P_Load_Fn
|| instr
== P_Curry
) {
1087 res
= u_pcode_get();
1088 if (unlikely(var_elided(res
))) {
1091 tr
= get_var_type(ctx
, res
);
1092 get_arg_mode(am
, tr
->slot
);
1094 n_return_values
= 0; /* avoid warning */
1095 } else if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1096 call_mode
= u_pcode_get();
1098 n_return_values
= (arg_t
)q
;
1099 if (unlikely(q
!= (pcode_t
)n_return_values
))
1100 goto exception_overflow
;
1102 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1106 n_arguments
= (arg_t
)q
;
1107 if (unlikely(q
!= (pcode_t
)n_arguments
))
1108 goto exception_overflow
;
1109 if (instr
== P_Load_Fn
|| instr
== P_Call
) {
1111 if (instr
== P_Load_Fn
)
1112 u_pcode_get(); /* call mode */
1113 ptr
= pcode_module_load_function(ctx
);
1116 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, true);
1117 if (unlikely(fn_idx
== no_function_idx
))
1119 get_arg_mode(am
, fn_idx
);
1120 src_deref
= false; /* avoid warning */
1121 src_fn
= ~sign_bit(pcode_t
); /* avoid warning */
1123 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1124 pcode_get_var_deref(&src_fn
, &src_deref
);
1127 pcode_position_save(ctx
, &saved
);
1129 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1132 n_real_return_values
= 0;
1133 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1134 for (ai
= 0; ai
< n_return_values
; ai
++) {
1136 if (unlikely(var_elided(q
)))
1138 n_real_return_values
++;
1140 if (!n_real_return_values
)
1142 get_arg_mode(am
, n_return_values
);
1144 pcode_position_restore(ctx
, &saved
);
1146 if (unlikely(elide
)) {
1147 /* TODO: remove the function from local directory if we just added it */
1149 if (unlikely(!pcode_free(ctx
, src_fn
)))
1152 pcode_dereference_arguments(ctx
, n_arguments
);
1157 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1158 ts
= get_var_type(ctx
, src_fn
);
1159 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
));
1160 get_arg_mode(am
, ts
->slot
);
1161 fn_idx
= no_function_idx
; /* avoid warning */
1164 code
= 0; /* avoid warning */
1167 code
= OPCODE_LOAD_FN
;
1170 code
= OPCODE_CURRY
;
1173 switch (call_mode
) {
1174 case Call_Mode_Unspecified
:
1175 case Call_Mode_Normal
:
1178 case Call_Mode_Strict
:
1179 case Call_Mode_Inline
:
1180 code
= OPCODE_CALL_STRICT
;
1182 case Call_Mode_Spark
:
1183 code
= OPCODE_CALL_SPARK
;
1185 case Call_Mode_Lazy
:
1186 code
= OPCODE_CALL_LAZY
;
1188 case Call_Mode_Cache
:
1189 code
= OPCODE_CALL_CACHE
;
1191 case Call_Mode_Save
:
1192 code
= OPCODE_CALL_SAVE
;
1195 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1198 case P_Call_Indirect
:
1199 switch (call_mode
) {
1200 case Call_Mode_Unspecified
:
1201 case Call_Mode_Normal
:
1202 code
= OPCODE_CALL_INDIRECT
;
1204 case Call_Mode_Strict
:
1205 case Call_Mode_Inline
:
1206 code
= OPCODE_CALL_INDIRECT_STRICT
;
1208 case Call_Mode_Spark
:
1209 code
= OPCODE_CALL_INDIRECT_SPARK
;
1211 case Call_Mode_Lazy
:
1212 code
= OPCODE_CALL_INDIRECT_LAZY
;
1214 case Call_Mode_Cache
:
1215 code
= OPCODE_CALL_INDIRECT_CACHE
;
1217 case Call_Mode_Save
:
1218 code
= OPCODE_CALL_INDIRECT_SAVE
;
1221 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1225 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1228 code
+= am
* OPCODE_MODE_MULT
;
1230 if (instr
== P_Load_Fn
|| instr
== P_Curry
)
1231 gen_am_two(am
, n_real_arguments
, tr
->slot
);
1233 gen_am_two(am
, n_real_arguments
, n_real_return_values
);
1234 if (instr
== P_Load_Fn
|| instr
== P_Call
)
1237 gen_am_two(am
, ts
->slot
, src_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1239 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1242 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1243 if (unlikely(!array_init_mayfail(const struct pcode_type
*, &rets
, &rets_l
, ctx
->err
)))
1245 for (ai
= 0; ai
< n_return_values
; ai
++) {
1246 const struct pcode_type
*tv
;
1248 if (unlikely(var_elided(q
)))
1250 tv
= get_var_type(ctx
, q
);
1251 if (unlikely(!array_add_mayfail(const struct pcode_type
*, &rets
, &rets_l
, tv
, NULL
, ctx
->err
)))
1254 if (unlikely(!pcode_finish_call(ctx
, rets
, rets_l
, false)))
1263 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1270 ctx
->pcode
= ctx
->pcode_instr_end
;
1274 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
)
1277 struct module_designator
*md
= NULL
;
1278 struct function_designator
*fd
= NULL
;
1285 switch (t1
->extra_type
? t1
->extra_type
: tr
->extra_type
) {
1286 case T_SInt128
: module
= "private/long"; fn
= 0 * Op_N
; break;
1287 case T_UInt128
: module
= "private/long"; fn
= 1 * Op_N
; break;
1288 case T_Real16
: module
= "private/longreal"; fn
= 0 * Op_N
; break;
1289 case T_Real32
: module
= "private/longreal"; fn
= 1 * Op_N
; break;
1290 case T_Real64
: module
= "private/longreal"; fn
= 2 * Op_N
; break;
1291 case T_Real80
: module
= "private/longreal"; fn
= 3 * Op_N
; break;
1292 case T_Real128
: module
= "private/longreal"; fn
= 4 * Op_N
; break;
1294 internal(file_line
, "pcode_op_to_call: type %d, %d", t1
->extra_type
, tr
->extra_type
);
1298 md
= module_designator_alloc(0, cast_ptr(const uint8_t *, module
), strlen(module
), false, ctx
->err
);
1301 fd
= function_designator_alloc_single(fn
, ctx
->err
);
1304 ptr
= module_load_function(md
, fd
, false, ctx
->err
);
1307 module_designator_free(md
), md
= NULL
;
1308 function_designator_free(fd
), fd
= NULL
;
1309 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, !preload
);
1310 if (unlikely(fn_idx
== no_function_idx
))
1317 get_arg_mode(am
, fn_idx
);
1318 get_arg_mode(am
, t1
->slot
);
1320 get_arg_mode(am
, t2
->slot
);
1322 code
= OPCODE_CALL
+ am
* OPCODE_MODE_MULT
;
1324 gen_am_two(am
, t2
? 2 : 1, 1);
1326 gen_am_two(am
, t1
->slot
, flags1
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1328 gen_am_two(am
, t2
->slot
, flags2
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1330 if (unlikely(!pcode_finish_call(ctx
, &tr
, 1, true)))
1337 module_designator_free(md
);
1339 function_designator_free(fd
);
1345 while ((size_t)(pos) >= 8 * *blob_len) \
1346 if (unlikely(!array_add_mayfail(uint8_t, blob, blob_len, 0, NULL, err)))\
1353 (*blob)[(pos) >> 3] |= 1U << ((pos) & 7); \
1356 #define re(n, rtype, ntype, pack, unpack) \
1357 static bool cat(pcode_generate_,rtype)(ntype val, uint8_t **blob, size_t *blob_len, ajla_error_t *err)\
1359 int ex_bits, sig_bits; \
1360 int min_exp, max_exp, e; \
1364 case 0: ex_bits = 5; sig_bits = 11; break; \
1365 case 1: ex_bits = 8; sig_bits = 24; break; \
1366 case 2: ex_bits = 11; sig_bits = 53; break; \
1367 case 3: ex_bits = 15; sig_bits = 64; break; \
1368 case 4: ex_bits = 15; sig_bits = 113; break; \
1369 default: internal(file_line, "invalid real type %d", n);\
1371 min_exp = -(1 << (ex_bits - 1)) - sig_bits + 3; \
1372 max_exp = (1 << (ex_bits - 1)) - sig_bits + 2; \
1373 if (unlikely(cat(isnan_,ntype)(val))) { \
1374 fatal_mayfail(error_ajla(EC_SYNC, AJLA_ERROR_NAN), err, "NaN");\
1377 if (unlikely(val == 0)) { \
1378 if (unlikely(1. / val < 0)) \
1383 if (unlikely(val < 0)) { \
1387 if (unlikely(!cat(isfinite_,ntype)(val))) { \
1392 norm = cat(mathfunc_,ntype)(frexp)(val, &e); \
1394 pos = sig_bits - 1; \
1395 if (e < min_exp) { \
1396 pos -= min_exp - e; \
1399 while (pos >= 0) { \
1409 pos = sig_bits + 1; \
1410 while (e && e != -1) { \
1425 } while (pos & 7); \
1428 for_all_real(re
, for_all_empty
)
1433 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
)
1439 const struct type
*type
;
1441 type
= pcode_to_type(NULL
, pcode_type
, err
);
1442 if (unlikely(!type
))
1445 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &blob_len
, err
)))
1447 #define emit_byte(b) \
1449 if (unlikely(!array_add_mayfail(uint8_t, &blob, &blob_len, b, NULL, err)))\
1453 d
= pointer_get_data(ptr
);
1454 if (likely(da_tag(d
) == DATA_TAG_flat
)) {
1458 switch (type
->tag
) {
1459 #define fx(n, type, utype, sz, bits) \
1460 case TYPE_TAG_integer + n: \
1461 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_signed:\
1462 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_unsigned:\
1463 negative = *cast_ptr(type *, da_flat(d)) < 0;\
1464 value = *cast_ptr(type *, da_flat(d)); \
1467 #define re(n, rtype, ntype, pack, unpack) \
1468 case TYPE_TAG_real + n: { \
1469 if (unlikely(!cat(pcode_generate_,rtype)(unpack(*cast_ptr(rtype *, da_flat(d))), &blob, &blob_len, err)))\
1471 goto process_real; \
1474 for_all_real(re
, for_all_empty
);
1476 internal(file_line
, "pcode_generate_blob_from_value: invalid type tag %u", type
->tag
);
1483 for (i
= 0; i
< size
; i
++) {
1487 sign
= blob_len
&& blob
[blob_len
- 1] & 0x80;
1488 if (unlikely(sign
!= negative
))
1489 emit_byte(negative
? 0xff : 0x00);
1491 while (blob_len
>= 2 && blob
[blob_len
- 1] == (negative
? 0xff : 0x00) && (blob
[blob_len
- 2] & 0x80) == (negative
? 0x80 : 0x00))
1494 if (blob_len
== 1 && !blob
[0])
1497 } else if (unlikely(da_tag(d
) == DATA_TAG_longint
)) {
1499 if (unlikely(!mpint_export_to_blob(&da(d
,longint
)->mp
, &blob
, &blob_len
, err
)))
1501 } else if (likely(da_tag(d
) == DATA_TAG_option
)) {
1503 ajla_assert_lo(pointer_is_empty(da(d
,option
)->pointer
), (file_line
, "pcode_generate_blob_from_value: non-empty option"));
1504 opt
= da(d
,option
)->option
;
1506 emit_byte(opt
& 0xff);
1507 while ((opt
>>= 8));
1509 internal(file_line
, "pcode_generate_blob_from_value: invalid data tag %u", da_tag(d
));
1515 if (unlikely(!pcode_generate_blob(blob
, blob_len
, res_blob
, res_len
, err
))) {
1527 #define test(bit) ((size_t)(bit) < 8 * dl ? (d[(bit) >> 3] >> ((bit) & 7)) & 1 : dl ? d[dl - 1] >> 7 : 0)
1529 #define re(n, rtype, ntype, pack, unpack) \
1530 static inline rtype cat(strto_,rtype)(const unsigned char *d, size_t dl)\
1532 int ex_bits, sig_bits; \
1538 case 0: ex_bits = 5; sig_bits = 11; break; \
1539 case 1: ex_bits = 8; sig_bits = 24; break; \
1540 case 2: ex_bits = 11; sig_bits = 53; break; \
1541 case 3: ex_bits = 15; sig_bits = 64; break; \
1542 case 4: ex_bits = 15; sig_bits = 113; break; \
1543 default: internal(file_line, "invalid real type %d", n);\
1547 for (i = 0; i < ex_bits + 1; i++) { \
1548 b = test(sig_bits + 1 + i); \
1549 ex |= (int)b << i; \
1554 for (i = 0; i < sig_bits; i++) { \
1556 val += cat(mathfunc_,ntype)(ldexp)(1, ex + i); \
1559 if (test(sig_bits)) \
1563 for_all_real(re
, for_all_empty
)
1566 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
)
1568 switch (type
->tag
) {
1569 #define re(n, rtype, ntype, pack, unpack) \
1570 case TYPE_TAG_real + n: { \
1571 rtype val = cat(strto_,rtype)((const unsigned char *)blob, blob_l);\
1572 *result_len = round_up(sizeof(rtype), sizeof(code_t)) / sizeof(code_t);\
1573 if (unlikely(!(*result = mem_alloc_array_mayfail(mem_calloc_mayfail, code_t *, 0, 0, *result_len, sizeof(code_t), ctx->err))))\
1575 memcpy(*result, &val, sizeof(rtype)); \
1578 for_all_real(re
, for_all_empty
);
1580 internal(file_line
, "pcode_decode_real(%s): invalid type tag %u", function_name(ctx
), type
->tag
);
1590 static bool pcode_generate_constant_from_blob(struct build_function_context
*ctx
, pcode_t res
, uint8_t *blob
, size_t l
)
1592 const struct pcode_type
*pt
;
1593 bool is_emulated_fixed_8
, is_emulated_fixed_16
;
1594 const struct type
*type
;
1596 code_t
*raw_result
= NULL
;
1598 size_t requested_size
;
1605 pt
= get_var_type(ctx
, res
);
1607 is_emulated_fixed_8
= pt
->extra_type
== T_SInt64
|| pt
->extra_type
== T_UInt64
;
1608 is_emulated_fixed_16
= pt
->extra_type
== T_SInt128
|| pt
->extra_type
== T_UInt128
;
1612 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1613 if (TYPE_TAG_FIXED_IS_UNSIGNED(type
->tag
) && l
== (size_t)type
->size
+ 1 && blob
[l
- 1] == 0x00)
1615 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
));
1616 if (l
<= sizeof(code_t
))
1617 requested_size
= sizeof(code_t
);
1619 requested_size
= round_up(type
->size
, sizeof(code_t
));
1620 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1621 if (is_emulated_fixed_8
&& l
&& blob
[l
- 1] & 0x80)
1623 else if (is_emulated_fixed_16
&& l
&& blob
[l
- 1] & 0x80)
1624 requested_size
= 16;
1625 else if (l
<= sizeof(code_t
))
1626 requested_size
= sizeof(code_t
);
1627 else if (l
<= type
->size
)
1628 requested_size
= round_up(type
->size
, sizeof(code_t
));
1630 requested_size
= round_up(l
, sizeof(code_t
));
1631 } else if (TYPE_TAG_IS_REAL(type
->tag
)) {
1632 if (!unlikely(pcode_decode_real(ctx
, type
, cast_ptr(const char *, blob
), l
, &raw_result
, &requested_size
)))
1635 internal(file_line
, "pcode_generate_constant_from_blob(%s): unknown type %u", function_name(ctx
), type
->tag
);
1638 if (likely(!raw_result
)) {
1639 while (l
< requested_size
) {
1640 uint8_t c
= !l
? 0 : !(blob
[l
- 1] & 0x80) ? 0 : 0xff;
1641 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, c
, NULL
, ctx
->err
)))
1646 code
= get_code(Op_Ldc
, type
);
1647 const_swap
= !!CODE_ENDIAN
;
1649 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1650 if (requested_size
< type
->size
)
1651 code
+= (OPCODE_FIXED_OP_ldc16
- OPCODE_FIXED_OP_ldc
) * OPCODE_FIXED_OP_MULT
;
1652 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1653 if ((is_emulated_fixed_8
|| is_emulated_fixed_16
) && l
&& blob
[l
- 1] & 0x80) {
1654 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, 0, NULL
, ctx
->err
)))
1656 code
= OPCODE_INT_LDC_LONG
;
1657 } else if (requested_size
< type
->size
) {
1658 code
+= (OPCODE_INT_OP_ldc16
- OPCODE_INT_OP_ldc
) * OPCODE_INT_OP_MULT
;
1659 } else if (requested_size
> type
->size
&& orig_l
> type
->size
) {
1660 code
= OPCODE_INT_LDC_LONG
;
1665 get_arg_mode(am
, pt
->slot
);
1667 gen_code(code
+ am
* OPCODE_MODE_MULT
);
1668 gen_am(am
, pt
->slot
);
1669 if (unlikely(code
== OPCODE_INT_LDC_LONG
)) {
1670 gen_uint32(l
/ sizeof(code_t
));
1671 /*debug("load long constant: %zu (%d)", l, type->tag);*/
1673 if (unlikely(raw_result
!= NULL
)) {
1675 for (idx
= 0; idx
< requested_size
; idx
++)
1676 gen_code(raw_result
[idx
]);
1677 } else for (is
= 0; is
< l
; is
+= sizeof(code_t
)) {
1678 size_t idx
= !const_swap
? is
: l
- sizeof(code_t
) - is
;
1679 gen_code(blob
[idx
] + (blob
[idx
+ 1] << 8));
1682 mem_free(blob
), blob
= NULL
;
1683 if (unlikely(raw_result
!= NULL
))
1684 mem_free(raw_result
);
1692 mem_free(raw_result
);
1696 static bool pcode_generate_constant(struct build_function_context
*ctx
, pcode_t res
, int_default_t val
)
1700 uint_default_t uval
= (uint_default_t
)val
;
1702 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &l
, ctx
->err
)))
1706 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, (uint8_t)uval
, NULL
, ctx
->err
)))
1711 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1714 static bool pcode_generate_option_from_blob(struct build_function_context
*ctx
, const struct pcode_type
*tr
, uint8_t *blob
, size_t l
)
1722 for (i
= 0; i
< l
; i
++) {
1723 ajla_option_t o
= (ajla_option_t
)blob
[i
];
1724 opt
|= o
<< (i
* 8);
1725 if (unlikely(opt
>> (i
* 8) != o
))
1726 goto exception_overflow
;
1730 get_arg_mode(am
, tr
->slot
);
1731 if (likely(opt
== (ajla_option_t
)(ajla_flat_option_t
)opt
) && tr
->type
->tag
== TYPE_TAG_flat_option
) {
1732 code
= OPCODE_OPTION_CREATE_EMPTY_FLAT
;
1734 code
= OPCODE_OPTION_CREATE_EMPTY
;
1736 code
+= am
* OPCODE_MODE_MULT
;
1738 gen_am_two(am
, tr
->slot
, opt
);
1744 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1750 static bool pcode_load_constant(struct build_function_context
*ctx
)
1755 const struct pcode_type
*tr
;
1757 res
= u_pcode_get();
1758 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
1761 if (var_elided(res
)) {
1766 tr
= get_var_type(ctx
, res
);
1768 if (tr
->type
->tag
== TYPE_TAG_flat_option
|| tr
->type
->tag
== TYPE_TAG_unknown
) {
1769 return pcode_generate_option_from_blob(ctx
, tr
, blob
, l
);
1771 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1775 static bool pcode_structured_loop(struct build_function_context
*ctx
, pcode_t n_steps
, code_t extra_flags
, arg_mode_t
*am
, bool gen
)
1780 if (i
== n_steps
- 1)
1781 extra_flags
|= OPCODE_STRUCTURED_FLAG_END
;
1785 case Structured_Record
: {
1787 pcode_t rec_local
, q
, type_idx
;
1788 const struct record_definition
*def
;
1791 rec_local
= u_pcode_get();
1795 if (unlikely(q
!= (pcode_t
)idx
))
1796 goto exception_overflow
;
1798 def
= type_def(pcode_to_type(ctx
, rec_local
, NULL
),record
);
1800 if (record_definition_is_elided(def
, idx
)) {
1801 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided record entry in the second pass", function_name(ctx
)));
1805 type_idx
= pcode_to_type_index(ctx
, rec_local
, false);
1806 if (unlikely(type_idx
== error_type_index
))
1809 slot
= record_definition_slot(def
, idx
);
1811 get_arg_mode(*am
, slot
);
1812 get_arg_mode(*am
, type_idx
);
1814 gen_am_two(*am
, OPCODE_STRUCTURED_RECORD
| extra_flags
, slot
);
1815 gen_am(*am
, type_idx
);
1819 case Structured_Option
: {
1824 opt
= (ajla_option_t
)q
;
1825 if (unlikely(q
!= (pcode_t
)opt
))
1826 goto exception_overflow
;
1829 get_arg_mode(*am
, opt
);
1831 gen_am_two(*am
, OPCODE_STRUCTURED_OPTION
| extra_flags
, opt
);
1836 case Structured_Array
: {
1837 pcode_t var
, local_type
, local_idx
;
1838 const struct pcode_type
*var_type
;
1840 var
= u_pcode_get();
1842 local_type
= pcode_get();
1844 if (var_elided(var
)) {
1845 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided array index in the second pass", function_name(ctx
)));
1849 var_type
= get_var_type(ctx
, var
);
1850 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
));
1852 local_idx
= pcode_to_type_index(ctx
, local_type
, false);
1853 if (unlikely(local_idx
== error_type_index
))
1857 get_arg_mode(*am
, var_type
->slot
);
1858 get_arg_mode(*am
, local_idx
);
1860 gen_am_two(*am
, OPCODE_STRUCTURED_ARRAY
| extra_flags
, var_type
->slot
);
1861 gen_am(*am
, local_idx
);
1866 internal(file_line
, "pcode_structured_loop(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (uintmax_t)type
);
1868 } while (++i
< n_steps
);
1873 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1878 static bool pcode_structured_write(struct build_function_context
*ctx
)
1880 pcode_t structured
, scalar
, n_steps
;
1882 pcode_t structured_source
= 0; /* avoid warning */
1883 bool structured_source_deref
= false; /* avoid warning */
1884 const struct pcode_type
*structured_type
, *scalar_type
;
1885 code_t extra_flags
= 0;
1886 arg_mode_t am
= INIT_ARG_MODE
;
1888 pcode_position_save_t saved
;
1890 n_steps
= u_pcode_get();
1891 ajla_assert_lo(n_steps
!= 0, (file_line
, "pcode_structured_write(%s): zero n_steps", function_name(ctx
)));
1892 structured
= u_pcode_get();
1893 pcode_get_var_deref(&structured_source
, &structured_source_deref
);
1894 pcode_get_var_deref(&scalar
, &scalar_deref
);
1896 extra_flags
|= OPCODE_STRUCTURED_FREE_VARIABLE
;
1898 pcode_position_save(ctx
, &saved
);
1900 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, false))
1903 if (unlikely(var_elided(structured
)) || unlikely(var_elided(scalar
)))
1906 pcode_position_restore(ctx
, &saved
);
1908 if (!pcode_copy(ctx
, false, structured
, structured_source
, structured_source_deref
))
1911 structured_type
= get_var_type(ctx
, structured
);
1912 scalar_type
= get_var_type(ctx
, scalar
);
1913 get_arg_mode(am
, structured_type
->slot
);
1914 get_arg_mode(am
, scalar_type
->slot
);
1916 gen_code(OPCODE_STRUCTURED
+ am
* OPCODE_MODE_MULT
);
1917 gen_am_two(am
, structured_type
->slot
, scalar_type
->slot
);
1919 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, true))
1928 static bool pcode_record_create(struct build_function_context
*ctx
)
1931 pcode_position_save_t saved
;
1932 pcode_t n_arguments
, n_real_arguments
;
1933 const struct pcode_type
*tr
;
1934 arg_mode_t am
= INIT_ARG_MODE
;
1936 result
= u_pcode_get();
1938 n_arguments
= (arg_t
)q
;
1939 if (unlikely(q
!= (pcode_t
)n_arguments
))
1940 goto exception_overflow
;
1942 pcode_position_save(ctx
, &saved
);
1944 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1947 pcode_position_restore(ctx
, &saved
);
1949 if (unlikely(var_elided(result
))) {
1950 pcode_dereference_arguments(ctx
, n_arguments
);
1954 tr
= get_var_type(ctx
, result
);
1955 get_arg_mode(am
, tr
->slot
);
1957 gen_code(OPCODE_RECORD_CREATE
+ am
* OPCODE_MODE_MULT
);
1958 gen_am_two(am
, tr
->slot
, n_real_arguments
);
1960 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1966 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1971 static bool pcode_array_create(struct build_function_context
*ctx
)
1973 pcode_t result
, local_type
, length
, n_real_arguments
;
1974 pcode_position_save_t saved
;
1975 const struct pcode_type
*tr
;
1976 arg_mode_t am
= INIT_ARG_MODE
;
1978 result
= u_pcode_get();
1979 local_type
= pcode_get();
1980 length
= u_pcode_get();
1983 pcode_position_save(ctx
, &saved
);
1985 if (unlikely(!pcode_process_arguments(ctx
, length
, &n_real_arguments
, &am
)))
1988 pcode_position_restore(ctx
, &saved
);
1990 if (unlikely(var_elided(result
))) {
1991 pcode_dereference_arguments(ctx
, length
);
1995 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
));
1997 tr
= get_var_type(ctx
, result
);
1998 get_arg_mode(am
, tr
->slot
);
2001 pcode_t type_idx
= pcode_to_type_index(ctx
, local_type
, true);
2002 if (unlikely(type_idx
== error_type_index
))
2004 if (type_idx
== no_type_index
) {
2005 gen_code(OPCODE_ARRAY_CREATE_EMPTY
+ am
* OPCODE_MODE_MULT
);
2006 gen_am(am
, tr
->slot
);
2008 get_arg_mode(am
, type_idx
);
2009 gen_code(OPCODE_ARRAY_CREATE_EMPTY_FLAT
+ am
* OPCODE_MODE_MULT
);
2010 gen_am_two(am
, tr
->slot
, type_idx
);
2013 get_arg_mode(am
, length
);
2014 gen_code(OPCODE_ARRAY_CREATE
+ am
* OPCODE_MODE_MULT
);
2015 gen_am_two(am
, tr
->slot
, length
);
2016 if (unlikely(!pcode_process_arguments(ctx
, length
, NULL
, &am
)))
2026 static bool pcode_array_string(struct build_function_context
*ctx
)
2031 const struct pcode_type
*tr
;
2032 arg_mode_t am
= INIT_ARG_MODE
;
2034 result
= u_pcode_get();
2036 if (!pcode_load_blob(ctx
, &blob
, &blob_len
))
2038 if (likely(var_elided(result
))) {
2043 tr
= get_var_type(ctx
, result
);
2044 get_arg_mode(am
, tr
->slot
);
2045 get_arg_mode(am
, blob_len
);
2046 gen_code(OPCODE_ARRAY_STRING
+ am
* OPCODE_MODE_MULT
);
2047 gen_am_two(am
, tr
->slot
, blob_len
);
2048 for (i
= 0; i
< blob_len
; i
+= 2) {
2054 u
.b
[1] = i
+ 1 < blob_len
? blob
[i
+ 1] : 0;
2066 static bool pcode_array_unicode(struct build_function_context
*ctx
)
2070 const struct pcode_type
*tr
;
2071 arg_mode_t am
= INIT_ARG_MODE
;
2073 result
= u_pcode_get();
2075 len
= ctx
->pcode_instr_end
- ctx
->pcode
;
2077 tr
= get_var_type(ctx
, result
);
2078 get_arg_mode(am
, tr
->slot
);
2079 get_arg_mode(am
, len
);
2080 gen_code(OPCODE_ARRAY_UNICODE
+ am
* OPCODE_MODE_MULT
);
2081 gen_am_two(am
, tr
->slot
, len
);
2082 for (i
= 0; i
< len
; i
++) {
2098 static bool pcode_io(struct build_function_context
*ctx
)
2100 pcode_t io_type
, n_outputs
, n_inputs
, n_params
;
2102 bool elided
= false;
2103 code_position_save_t saved
;
2105 code_position_save(ctx
, &saved
);
2107 io_type
= u_pcode_get();
2108 n_outputs
= u_pcode_get();
2109 n_inputs
= u_pcode_get();
2110 n_params
= u_pcode_get();
2112 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
));
2114 gen_code(OPCODE_IO
);
2115 gen_code(io_type
| (n_outputs
<< 8));
2116 gen_code(n_inputs
| (n_params
<< 8));
2118 for (pass
= 0; pass
< 3; pass
++) {
2120 if (!pass
) val
= n_outputs
;
2121 else if (pass
== 1) val
= n_inputs
;
2122 else val
= n_params
;
2125 pcode_t var
= pcode_get();
2126 if (!pass
&& var_elided(var
))
2130 const struct pcode_type
*t1
;
2131 t1
= get_var_type(ctx
, var
);
2132 gen_uint32(t1
->slot
);
2141 code_position_restore(ctx
, &saved
);
2150 static bool pcode_args(struct build_function_context
*ctx
)
2152 const struct pcode_type
*tr
;
2155 ajla_assert_lo(!ctx
->args
, (file_line
, "pcode_args(%s): args already specified", function_name(ctx
)));
2157 ctx
->args
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct local_arg
*, 0, 0, ctx
->n_arguments
, sizeof(struct local_arg
), ctx
->err
);
2158 if (unlikely(!ctx
->args
))
2161 for (i
= 0, vv
= 0; i
< ctx
->n_arguments
; i
++) {
2162 pcode_t res
= pcode_get();
2163 if (unlikely(var_elided(res
)))
2165 tr
= get_var_type(ctx
, res
);
2166 ctx
->args
[vv
].slot
= tr
->slot
;
2167 ctx
->args
[vv
].may_be_borrowed
= !TYPE_IS_FLAT(tr
->type
);
2168 ctx
->args
[vv
].may_be_flat
= TYPE_IS_FLAT(tr
->type
);
2169 ctx
->pcode_types
[res
].argument
= &ctx
->args
[vv
];
2170 ctx
->colors
[tr
->color
].is_argument
= true;
2171 if (!TYPE_IS_FLAT(tr
->type
))
2172 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2175 ctx
->n_real_arguments
= vv
;
2181 struct pcode_return_struct
{
2186 static bool pcode_return(struct build_function_context
*ctx
)
2188 arg_mode_t am
= INIT_ARG_MODE
;
2190 struct pcode_return_struct
*prs
;
2192 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
);
2196 for (i
= 0, vv
= 0; i
< ctx
->n_return_values
; i
++) {
2197 const struct pcode_type
*tr
;
2198 pcode_t flags
= u_pcode_get();
2199 pcode_t res
= pcode_get();
2200 prs
[i
].flags
= flags
;
2202 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2204 tr
= get_var_type(ctx
, res
);
2205 get_arg_mode(am
, tr
->slot
);
2209 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
));
2211 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2212 if (unlikely((prs
[i
].flags
& (Flag_Free_Argument
| Flag_Return_Elided
)) == (Flag_Free_Argument
| Flag_Return_Elided
))) {
2214 arg_t q
= (arg_t
)-1;
2215 for (j
= 0; j
< i
; j
++)
2216 if (prs
[j
].res
== prs
[i
].res
&& !(prs
[j
].flags
& Flag_Return_Elided
))
2218 if (q
!= (arg_t
)-1) {
2219 prs
[q
].flags
|= Flag_Free_Argument
;
2221 if (!pcode_free(ctx
, prs
[i
].res
))
2224 prs
[i
].flags
&= ~Flag_Free_Argument
;
2228 gen_code(OPCODE_RETURN
+ am
* OPCODE_MODE_MULT
);
2230 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2231 unsigned code_flags
;
2232 const struct pcode_type
*tr
;
2233 pcode_t flags
= prs
[i
].flags
;
2234 pcode_t res
= prs
[i
].res
;
2235 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2237 tr
= get_var_type(ctx
, res
);
2239 if (flags
& Flag_Free_Argument
)
2240 code_flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
2241 gen_am_two(am
, tr
->slot
, code_flags
);
2253 static void pcode_get_instr(struct build_function_context
*ctx
, pcode_t
*instr
, pcode_t
*instr_params
)
2255 *instr
= u_pcode_get();
2256 *instr_params
= u_pcode_get();
2257 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
)));
2258 ctx
->pcode_instr_end
= ctx
->pcode
+ *instr_params
;
2262 static bool pcode_preload_ld(struct build_function_context
*ctx
)
2264 pcode_position_save_t saved
;
2266 pcode_position_save(ctx
, &saved
);
2267 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2268 pcode_t instr
, instr_params
;
2269 pcode_get_instr(ctx
, &instr
, &instr_params
);
2272 if (unlikely(!pcode_args(ctx
)))
2275 #if NEED_OP_EMULATION
2278 const struct pcode_type
*tr
, *t1
;
2279 pcode_t op
= u_pcode_get();
2280 pcode_t res
= u_pcode_get();
2281 pcode_t flags1
= u_pcode_get();
2282 pcode_t a1
= pcode_get();
2283 if (unlikely(var_elided(res
)))
2285 tr
= get_var_type(ctx
, res
);
2286 t1
= get_var_type(ctx
, a1
);
2287 if (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
)) {
2288 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, true)))
2299 ptr
= pcode_module_load_function(ctx
);
2302 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, false);
2303 if (unlikely(fn_idx
== no_function_idx
))
2308 ctx
->pcode
= ctx
->pcode_instr_end
;
2310 pcode_position_restore(ctx
, &saved
);
2318 static bool pcode_check_args(struct build_function_context
*ctx
)
2322 frame_t
*vars
= NULL
;
2325 vars
= mem_alloc_array_mayfail(mem_alloc_mayfail
, frame_t
*, 0, 0, ctx
->n_real_arguments
, sizeof(frame_t
), ctx
->err
);
2326 if (unlikely(!vars
))
2329 am
= INIT_ARG_MODE_1
;
2330 for (i
= 0; i
< ctx
->n_real_arguments
; i
++) {
2331 frame_t slot
= ctx
->args
[i
].slot
;
2332 if (ctx
->local_variables_flags
[slot
].must_be_flat
) {
2333 vars
[n_vars
++] = slot
;
2334 get_arg_mode(am
, slot
);
2339 get_arg_mode(am
, n_vars
);
2340 code
= OPCODE_ESCAPE_NONFLAT
;
2341 code
+= am
* OPCODE_MODE_MULT
;
2344 for (i
= 0; i
< n_vars
; i
++)
2345 gen_am(am
, vars
[i
]);
2358 static bool pcode_generate_instructions(struct build_function_context
*ctx
)
2360 if (unlikely(!gen_checkpoint(ctx
, NULL
, 0)))
2363 if (unlikely(!pcode_check_args(ctx
)))
2366 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2367 pcode_t instr
, instr_params
;
2368 pcode_get_instr(ctx
, &instr
, &instr_params
);
2370 pcode_t p
, op
, res
, a1
, a2
, aa
, flags
, flags1
, flags2
;
2371 const struct pcode_type
*tr
, *t1
, *t2
, *ta
;
2372 bool a1_deref
, a2_deref
;
2375 struct line_position lp
;
2376 struct record_definition
*def
;
2380 ajla_assert_lo(op
>= Op_N
|| Op_IsBinary(op
), (file_line
, "P_BinaryOp(%s): invalid binary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2381 res
= u_pcode_get();
2382 flags1
= u_pcode_get();
2384 flags2
= u_pcode_get();
2386 if (unlikely(var_elided(res
))) {
2387 if (flags1
& Flag_Free_Argument
)
2388 pcode_free(ctx
, a1
);
2389 if (flags2
& Flag_Free_Argument
)
2390 pcode_free(ctx
, a2
);
2393 tr
= get_var_type(ctx
, res
);
2394 t1
= get_var_type(ctx
, a1
);
2395 t2
= get_var_type(ctx
, a2
);
2396 ajla_assert_lo(op
>= Op_N
||
2397 (type_is_equal(t1
->type
, t2
->type
) &&
2398 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2399 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2400 : 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
));
2401 if (NEED_OP_EMULATION
&& unlikely(t1
->extra_type
)) {
2402 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, t2
, flags2
, false)))
2407 get_arg_mode(am
, t1
->slot
);
2408 get_arg_mode(am
, t2
->slot
);
2409 get_arg_mode(am
, tr
->slot
);
2410 code
= (code_t
)((likely(op
< Op_N
) ? get_code(op
, t1
->type
) : (code_t
)(op
- Op_N
)) + am
* OPCODE_MODE_MULT
);
2412 gen_am_two(am
, t1
->slot
, t2
->slot
);
2413 gen_am_two(am
, tr
->slot
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2414 if (flags1
& Flag_Free_Argument
) {
2415 if (t1
->slot
!= tr
->slot
)
2416 pcode_free(ctx
, a1
);
2418 if (flags2
& Flag_Free_Argument
) {
2419 if (t2
->slot
!= tr
->slot
)
2420 pcode_free(ctx
, a2
);
2425 ajla_assert_lo(op
>= Op_N
|| Op_IsUnary(op
), (file_line
, "P_UnaryOp(%s): invalid unary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2426 res
= u_pcode_get();
2427 flags1
= u_pcode_get();
2429 if (unlikely(var_elided(res
))) {
2430 if (flags1
& Flag_Free_Argument
)
2431 pcode_free(ctx
, a1
);
2434 tr
= get_var_type(ctx
, res
);
2435 t1
= get_var_type(ctx
, a1
);
2436 ajla_assert_lo(op
>= Op_N
|| op
== Un_ConvertFromInt
||
2437 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2438 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2439 : 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
));
2440 if (NEED_OP_EMULATION
&& (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
))) {
2441 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, false)))
2446 get_arg_mode(am
, t1
->slot
);
2447 get_arg_mode(am
, tr
->slot
);
2448 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
);
2450 gen_am_two(am
, t1
->slot
, tr
->slot
);
2451 gen_am(am
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2452 if (flags1
& Flag_Free_Argument
) {
2453 if (t1
->slot
!= tr
->slot
)
2454 pcode_free(ctx
, a1
);
2458 case P_Copy_Type_Cast
:
2459 res
= u_pcode_get();
2460 pcode_get_var_deref(&a1
, &a1_deref
);
2461 if (unlikely(var_elided(res
))) {
2463 if (unlikely(!pcode_free(ctx
, a1
)))
2468 if (unlikely(!pcode_copy(ctx
, instr
!= P_Copy
, res
, a1
, a1_deref
)))
2472 res
= u_pcode_get();
2473 if (unlikely(!pcode_free(ctx
, res
)))
2478 if (unlikely(var_elided(a1
)))
2480 t1
= get_var_type(ctx
, a1
);
2482 get_arg_mode(am
, t1
->slot
);
2484 code
+= am
* OPCODE_MODE_MULT
;
2486 gen_am(am
, t1
->slot
);
2492 res
= u_pcode_get();
2493 ajla_assert_lo(var_elided(res
), (file_line
, "P_Fn(%s): Fn result is not elided", function_name(ctx
)));
2496 for (p
= 0; p
< a1
; p
++)
2498 for (p
= 0; p
< a2
; p
++)
2501 case P_Load_Local_Type
:
2502 res
= u_pcode_get();
2503 ajla_assert_lo(var_elided(res
), (file_line
, "P_Load_Local_Type(%s): Load_Local_Type result is not elided", function_name(ctx
)));
2509 case P_Call_Indirect
:
2511 if (unlikely(!pcode_call(ctx
, instr
)))
2515 if (unlikely(!pcode_load_constant(ctx
)))
2518 case P_Structured_Write
:
2519 if (unlikely(!pcode_structured_write(ctx
)))
2524 for (p
= 0; p
< instr_params
; p
++)
2527 case P_Record_Create
:
2528 if (unlikely(!pcode_record_create(ctx
)))
2531 case P_Record_Load_Slot
:
2532 res
= u_pcode_get();
2535 tr
= get_var_type(ctx
, res
);
2536 t1
= get_var_type(ctx
, a1
);
2538 get_arg_mode(am
, tr
->slot
);
2539 get_arg_mode(am
, t1
->slot
);
2540 get_arg_mode(am
, op
);
2541 code
= OPCODE_RECORD_LOAD
;
2542 code
+= am
* OPCODE_MODE_MULT
;
2544 gen_am_two(am
, t1
->slot
, op
);
2545 gen_am_two(am
, tr
->slot
, OPCODE_OP_FLAG_STRICT
);
2548 res
= u_pcode_get();
2549 flags
= u_pcode_get();
2552 if (unlikely(var_elided(res
)))
2554 tr
= get_var_type(ctx
, res
);
2555 t1
= get_var_type(ctx
, a1
);
2556 if (TYPE_IS_FLAT(tr
->type
))
2557 flags
&= ~Flag_Borrow
;
2558 if (t1
->type
->tag
== TYPE_TAG_flat_record
) {
2559 def
= type_def(type_def(t1
->type
,flat_record
)->base
,record
);
2561 def
= type_def(t1
->type
,record
);
2563 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
));
2564 op
= record_definition_slot(def
, op
);
2566 get_arg_mode(am
, tr
->slot
);
2567 get_arg_mode(am
, t1
->slot
);
2568 get_arg_mode(am
, op
);
2569 code
= OPCODE_RECORD_LOAD
;
2570 code
+= am
* OPCODE_MODE_MULT
;
2572 gen_am_two(am
, t1
->slot
, op
);
2573 gen_am_two(am
, tr
->slot
,
2574 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2575 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2576 if (flags
& Flag_Borrow
)
2577 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2580 res
= u_pcode_get();
2581 flags
= u_pcode_get();
2584 if (unlikely(var_elided(res
)))
2586 tr
= get_var_type(ctx
, res
);
2587 t1
= get_var_type(ctx
, a1
);
2588 if (TYPE_IS_FLAT(tr
->type
))
2589 flags
&= ~Flag_Borrow
;
2591 get_arg_mode(am
, tr
->slot
);
2592 get_arg_mode(am
, t1
->slot
);
2593 get_arg_mode(am
, op
);
2594 code
= OPCODE_OPTION_LOAD
;
2595 code
+= am
* OPCODE_MODE_MULT
;
2597 gen_am_two(am
, t1
->slot
, op
);
2598 gen_am_two(am
, tr
->slot
,
2599 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2600 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2601 if (flags
& Flag_Borrow
)
2602 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2604 case P_Option_Create
:
2605 res
= u_pcode_get();
2607 pcode_get_var_deref(&a1
, &a1_deref
);
2608 if (unlikely(var_elided(res
))) {
2610 if (unlikely(!pcode_free(ctx
, a1
)))
2615 tr
= get_var_type(ctx
, res
);
2616 t1
= get_var_type(ctx
, a1
);
2617 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
));
2619 get_arg_mode(am
, tr
->slot
);
2620 get_arg_mode(am
, t1
->slot
);
2621 get_arg_mode(am
, op
);
2622 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2623 goto exception_overflow
;
2624 code
= OPCODE_OPTION_CREATE
;
2625 code
+= am
* OPCODE_MODE_MULT
;
2627 gen_am_two(am
, tr
->slot
, op
);
2628 gen_am_two(am
, t1
->slot
, a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
2631 res
= u_pcode_get();
2634 if (unlikely(var_elided(res
)))
2636 tr
= get_var_type(ctx
, res
);
2637 t1
= get_var_type(ctx
, a1
);
2638 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
));
2640 get_arg_mode(am
, tr
->slot
);
2641 get_arg_mode(am
, t1
->slot
);
2642 get_arg_mode(am
, op
);
2643 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2644 goto exception_overflow
;
2645 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2646 code
= OPCODE_OPTION_TEST_FLAT
;
2648 code
= OPCODE_OPTION_TEST
;
2649 code
+= am
* OPCODE_MODE_MULT
;
2651 gen_am_two(am
, t1
->slot
, op
);
2652 gen_am(am
, tr
->slot
);
2655 res
= u_pcode_get();
2657 if (unlikely(var_elided(res
)))
2659 tr
= get_var_type(ctx
, res
);
2660 t1
= get_var_type(ctx
, a1
);
2661 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
));
2663 get_arg_mode(am
, tr
->slot
);
2664 get_arg_mode(am
, t1
->slot
);
2665 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2666 code
= OPCODE_OPTION_ORD_FLAT
;
2668 code
= OPCODE_OPTION_ORD
;
2669 code
+= am
* OPCODE_MODE_MULT
;
2671 gen_am_two(am
, t1
->slot
, tr
->slot
);
2673 case P_Array_Flexible
:
2675 res
= u_pcode_get();
2676 ajla_assert_lo(var_elided(res
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible result is not elided", function_name(ctx
)));
2678 ajla_assert_lo(var_elided(a1
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible argument is not elided", function_name(ctx
)));
2679 if (instr
== P_Array_Fixed
)
2682 case P_Array_Create
:
2683 if (unlikely(!pcode_array_create(ctx
)))
2687 res
= u_pcode_get();
2688 pcode_get(); /* local type */
2690 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
));
2693 if (unlikely(var_elided(res
)))
2695 tr
= get_var_type(ctx
, res
);
2696 t1
= get_var_type(ctx
, a1
);
2697 t2
= get_var_type(ctx
, a2
);
2698 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
));
2700 get_arg_mode(am
, t1
->slot
);
2701 get_arg_mode(am
, t2
->slot
);
2702 get_arg_mode(am
, tr
->slot
);
2703 gen_code(OPCODE_ARRAY_FILL
+ am
* OPCODE_MODE_MULT
);
2704 gen_am_two(am
, t1
->slot
,
2705 ((op
& Flag_Free_Argument
) ? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2706 ((op
& Flag_Array_Fill_Sparse
) ? OPCODE_ARRAY_FILL_FLAG_SPARSE
: 0)
2708 gen_am_two(am
, t2
->slot
, tr
->slot
);
2710 case P_Array_String
:
2711 if (unlikely(!pcode_array_string(ctx
)))
2714 case P_Array_Unicode
:
2715 if (unlikely(!pcode_array_unicode(ctx
)))
2719 res
= u_pcode_get();
2720 flags
= u_pcode_get();
2723 if (unlikely(var_elided(res
)))
2725 tr
= get_var_type(ctx
, res
);
2726 t1
= get_var_type(ctx
, a1
);
2727 t2
= get_var_type(ctx
, a2
);
2728 if (TYPE_IS_FLAT(tr
->type
))
2729 flags
&= ~Flag_Borrow
;
2731 get_arg_mode(am
, tr
->slot
);
2732 get_arg_mode(am
, t1
->slot
);
2733 get_arg_mode(am
, t2
->slot
);
2734 code
= OPCODE_ARRAY_LOAD
;
2735 code
+= am
* OPCODE_MODE_MULT
;
2737 gen_am_two(am
, t1
->slot
, t2
->slot
);
2738 gen_am_two(am
, tr
->slot
,
2739 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2740 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0) |
2741 (flags
& Flag_Index_In_Range
? OPCODE_ARRAY_INDEX_IN_RANGE
: 0));
2742 if (flags
& Flag_Borrow
)
2743 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2746 res
= u_pcode_get();
2748 flags
= u_pcode_get();
2749 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2750 if (unlikely(var_elided(res
)))
2752 tr
= get_var_type(ctx
, res
);
2753 t1
= get_var_type(ctx
, a1
);
2754 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
));
2755 if (TYPE_IS_FLAT(t1
->type
)) {
2756 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
));
2757 if (unlikely(!pcode_generate_constant(ctx
, res
, (int_default_t
)type_def(t1
->type
,flat_array
)->n_elements
)))
2760 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
));
2762 get_arg_mode(am
, t1
->slot
);
2763 get_arg_mode(am
, tr
->slot
);
2764 gen_code(OPCODE_ARRAY_LEN
+ am
* OPCODE_MODE_MULT
);
2765 gen_am_two(am
, t1
->slot
, tr
->slot
);
2766 gen_am(am
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2769 case P_Array_Len_Greater_Than
:
2770 res
= u_pcode_get();
2773 flags
= u_pcode_get();
2774 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len_Greater_Than(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2775 if (unlikely(var_elided(res
)))
2777 tr
= get_var_type(ctx
, res
);
2778 t1
= get_var_type(ctx
, a1
);
2779 t2
= get_var_type(ctx
, a2
);
2780 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
));
2781 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
));
2784 get_arg_mode(am
, t1
->slot
);
2785 get_arg_mode(am
, t2
->slot
);
2786 get_arg_mode(am
, tr
->slot
);
2787 gen_code(OPCODE_ARRAY_LEN_GREATER_THAN
+ am
* OPCODE_MODE_MULT
);
2788 gen_am_two(am
, t1
->slot
, t2
->slot
);
2789 gen_am_two(am
, tr
->slot
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2792 res
= u_pcode_get();
2793 flags
= u_pcode_get();
2797 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Sub(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2798 if (unlikely(var_elided(res
)))
2800 tr
= get_var_type(ctx
, res
);
2801 ta
= get_var_type(ctx
, aa
);
2802 t1
= get_var_type(ctx
, a1
);
2803 t2
= get_var_type(ctx
, a2
);
2804 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
));
2805 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
));
2808 get_arg_mode(am
, ta
->slot
);
2809 get_arg_mode(am
, t1
->slot
);
2810 get_arg_mode(am
, t2
->slot
);
2811 get_arg_mode(am
, tr
->slot
);
2812 gen_code(OPCODE_ARRAY_SUB
+ am
* OPCODE_MODE_MULT
);
2813 gen_am_two(am
, ta
->slot
, t1
->slot
);
2814 gen_am_two(am
, t2
->slot
, tr
->slot
);
2816 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2817 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2821 res
= u_pcode_get();
2822 flags
= u_pcode_get();
2825 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Skip(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2826 if (unlikely(var_elided(res
)))
2828 tr
= get_var_type(ctx
, res
);
2829 ta
= get_var_type(ctx
, aa
);
2830 t1
= get_var_type(ctx
, a1
);
2831 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
));
2834 get_arg_mode(am
, ta
->slot
);
2835 get_arg_mode(am
, t1
->slot
);
2836 get_arg_mode(am
, tr
->slot
);
2837 gen_code(OPCODE_ARRAY_SKIP
+ am
* OPCODE_MODE_MULT
);
2838 gen_am_two(am
, ta
->slot
, t1
->slot
);
2839 gen_am_two(am
, tr
->slot
,
2840 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2841 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2844 case P_Array_Append
:
2845 case P_Array_Append_One
:
2846 res
= u_pcode_get();
2847 pcode_get_var_deref(&a1
, &a1_deref
);
2848 pcode_get_var_deref(&a2
, &a2_deref
);
2849 if (unlikely(var_elided(res
)))
2851 tr
= get_var_type(ctx
, res
);
2852 t1
= get_var_type(ctx
, a1
);
2853 t2
= get_var_type(ctx
, a2
);
2855 get_arg_mode(am
, tr
->slot
);
2856 get_arg_mode(am
, t1
->slot
);
2857 get_arg_mode(am
, t2
->slot
);
2858 if (instr
== P_Array_Append
) {
2859 gen_code(OPCODE_ARRAY_APPEND
+ am
* OPCODE_MODE_MULT
);
2861 if (TYPE_IS_FLAT(t2
->type
)) {
2862 gen_code(OPCODE_ARRAY_APPEND_ONE_FLAT
+ am
* OPCODE_MODE_MULT
);
2864 gen_code(OPCODE_ARRAY_APPEND_ONE
+ am
* OPCODE_MODE_MULT
);
2867 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0) | (a2_deref
? OPCODE_FLAG_FREE_ARGUMENT_2
: 0));
2868 gen_am_two(am
, t1
->slot
, t2
->slot
);
2870 case P_Array_Flatten
:
2871 res
= u_pcode_get();
2872 pcode_get_var_deref(&a1
, &a1_deref
);
2873 if (unlikely(var_elided(res
)))
2875 tr
= get_var_type(ctx
, res
);
2876 t1
= get_var_type(ctx
, a1
);
2878 get_arg_mode(am
, tr
->slot
);
2879 get_arg_mode(am
, t1
->slot
);
2880 gen_code(OPCODE_ARRAY_FLATTEN
+ am
* OPCODE_MODE_MULT
);
2881 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0));
2882 gen_am(am
, t1
->slot
);
2885 res
= u_pcode_get();
2886 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Jmp(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2888 if (ctx
->labels
[res
] != no_label
) {
2890 target
= (uint32_t)((ctx
->code_len
- ctx
->labels
[res
]) * sizeof(code_t
));
2891 if (likely(target
< 0x10000)) {
2892 gen_code(OPCODE_JMP_BACK_16
);
2893 gen_code((code_t
)target
);
2898 gen_code(OPCODE_JMP
);
2899 gen_relative_jump(res
, SIZEOF_IP_T
);
2903 tr
= get_var_type(ctx
, res
);
2904 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
));
2910 get_arg_mode(am
, tr
->slot
);
2911 code
= OPCODE_JMP_FALSE
+ am
* OPCODE_MODE_MULT
;
2913 gen_am(am
, tr
->slot
);
2914 gen_relative_jump(a1
, SIZEOF_IP_T
* 2);
2915 gen_relative_jump(a2
, SIZEOF_IP_T
);
2918 gen_code(OPCODE_LABEL
);
2919 res
= u_pcode_get();
2920 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Label(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2921 ajla_assert_lo(ctx
->labels
[res
] == no_label
, (file_line
, "P_Label(%s): label %"PRIdMAX
" already defined", function_name(ctx
), (intmax_t)res
));
2922 ctx
->labels
[res
] = ctx
->code_len
;
2925 if (unlikely(!pcode_io(ctx
)))
2929 ctx
->pcode
= ctx
->pcode_instr_end
;
2932 for (p
= 0; p
< instr_params
; p
++)
2936 if (unlikely(!pcode_return(ctx
)))
2940 if (unlikely(!gen_checkpoint(ctx
, ctx
->pcode
, instr_params
)))
2942 for (p
= 0; p
< instr_params
; p
++)
2946 lp
.line
= u_pcode_get();
2947 lp
.ip
= ctx
->code_len
;
2948 if (unlikely(!array_add_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, lp
, NULL
, ctx
->err
)))
2952 internal(file_line
, "pcode_generate_instructions(%s): invalid pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
2955 if (unlikely(ctx
->pcode
!= ctx
->pcode_instr_end
)) {
2960 for (pp
= ctx
->pcode_instr_end
- instr_params
- 2; pp
< ctx
->pcode
; pp
++) {
2961 str_add_char(&s
, &l
, ' ');
2962 str_add_signed(&s
, &l
, *pp
, 10);
2965 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
);
2968 if (unlikely(ctx
->code_len
> sign_bit(ip_t
) / sizeof(code_t
) + uzero
))
2969 goto exception_overflow
;
2973 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
2978 static bool pcode_generate_record(struct build_function_context
*ctx
)
2982 struct record_definition
*def
;
2983 if (unlikely(!array_init_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, ctx
->err
)))
2986 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, slot_size
, data_record_offset
, ctx
->err
);
2987 if (unlikely(!ctx
->layout
))
2990 for (; ctx
->pcode
!= ctx
->pcode_limit
; ctx
->pcode
= ctx
->pcode_instr_end
) {
2991 pcode_t instr
, instr_params
;
2992 pcode_get_instr(ctx
, &instr
, &instr_params
);
2994 if (instr
== P_Load_Local_Type
) {
2995 pcode_t var
, fn_var
;
2996 pcode_t attr_unused idx
;
2997 const struct pcode_type
*p
;
2998 const struct type
*t
;
3000 ajla_assert_lo(instr_params
== 3, (file_line
, "pcode_generate_record(%s): invalid number of parameters %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr_params
));
3002 var
= u_pcode_get();
3003 fn_var
= pcode_get();
3004 idx
= u_pcode_get();
3005 if (unlikely(fn_var
!= -1))
3007 if (unlikely(var
!= (pcode_t
)(frame_t
)var
))
3008 goto exception_overflow
;
3009 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
));
3011 if (unlikely(!array_add_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, var
, NULL
, ctx
->err
)))
3014 if (var_elided(var
))
3017 p
= get_var_type(ctx
, var
);
3020 if (unlikely(!layout_add(ctx
->layout
, maximum(t
->size
, 1), t
->align
, ctx
->err
)))
3025 array_finish(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
);
3027 if (unlikely(ctx
->record_entries_len
!= (size_t)(arg_t
)ctx
->record_entries_len
))
3028 goto exception_overflow
;
3030 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3034 def
= type_alloc_record_definition(layout_size(ctx
->layout
), ctx
->err
);
3037 def
->n_slots
= layout_size(ctx
->layout
);
3038 def
->alignment
= maximum(layout_alignment(ctx
->layout
), frame_align
);
3039 def
->n_entries
= (arg_t
)ctx
->record_entries_len
;
3042 for (ai
= 0; ai
< ctx
->record_entries_len
; ai
++) {
3044 const struct pcode_type
*te
;
3045 var
= ctx
->record_entries
[ai
];
3046 if (var_elided((pcode_t
)var
)) {
3047 ctx
->record_entries
[ai
] = NO_FRAME_T
;
3050 slot
= layout_get(ctx
->layout
, layout_idx
++);
3051 ctx
->record_entries
[ai
] = slot
;
3052 te
= get_var_type(ctx
, (pcode_t
)var
);
3053 def
->types
[slot
] = te
->type
;
3056 def
->idx_to_frame
= ctx
->record_entries
, ctx
->record_entries
= NULL
;
3057 ctx
->record_definition
= def
;
3059 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3064 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3070 * pointer_empty -> ret_ex
3071 * poitner_mark -> err
3072 * other -> thunk(error) or data(function)
3074 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
)
3077 pcode_t p
, q
, subfns
;
3081 struct data
*ft
, *fn
;
3082 struct function_descriptor
*sfd
;
3085 #if defined(HAVE_CODEGEN)
3086 union internal_arg ia
[1];
3089 struct build_function_context ctx_
;
3090 struct build_function_context
*ctx
= &ctx_
;
3095 ctx
->pcode_limit
= pcode
+ size
;
3098 q
= u_pcode_get() & Fn_Mask
;
3099 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
));
3100 ctx
->function_type
= q
;
3102 u_pcode_get(); /* call mode - used by the optimizer */
3104 subfns
= u_pcode_get();
3106 ctx
->n_local_types
= u_pcode_get();
3109 ctx
->n_local_variables
= (frame_t
)q
;
3110 if (unlikely(q
!= (pcode_t
)ctx
->n_local_variables
))
3111 goto exception_overflow
;
3114 ctx
->n_arguments
= (arg_t
)q
;
3115 ajla_assert_lo(q
== (pcode_t
)ctx
->n_arguments
, (file_line
, "pcode_build_function_core: overflow in n_arguments"));
3118 ctx
->n_return_values
= (arg_t
)q
;
3119 ajla_assert_lo(q
== (pcode_t
)ctx
->n_return_values
, (file_line
, "pcode_build_function_core: overflow in n_return_values"));
3121 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"));
3124 ctx
->n_real_return_values
= (arg_t
)q
;
3125 ajla_assert_lo(ctx
->n_real_return_values
<= ctx
->n_return_values
, (file_line
, "pcode_build_function_core: invalid n_real_return_values"));
3127 ctx
->n_labels
= u_pcode_get();
3129 if (unlikely(!pcode_load_blob(ctx
, &ctx
->function_name
, &is
)))
3131 if (unlikely(!array_add_mayfail(uint8_t, &ctx
->function_name
, &is
, 0, NULL
, ctx
->err
)))
3133 array_finish(uint8_t, &ctx
->function_name
, &is
);
3141 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
);
3142 if (unlikely(!ctx
->local_types
))
3145 for (p
= 0; p
< ctx
->n_local_types
; p
++) {
3147 struct data
*rec_fn
;
3148 const struct record_definition
*def
;
3149 pcode_t base_idx
, n_elements
;
3150 struct type_entry
*flat_rec
;
3152 const struct type
*tt
, *tp
;
3156 case Local_Type_Record
:
3157 ptr
= pcode_module_load_function(ctx
);
3160 pointer_follow(ptr
, false, rec_fn
, PF_WAIT
, fp
, ip
,
3162 ctx
->ret_val
= pointer_empty();
3164 thunk_reference(thunk_
);
3165 ctx
->ret_val
= pointer_thunk(thunk_
);
3168 ajla_assert_lo(da(rec_fn
,function
)->record_definition
!= NULL
, (file_line
, "pcode_build_function_core(%s): record has no definition", function_name(ctx
)));
3169 def
= type_def(da(rec_fn
,function
)->record_definition
,record
);
3172 case Local_Type_Flat_Record
:
3173 base_idx
= u_pcode_get();
3174 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
));
3175 n_elements
= u_pcode_get();
3176 def
= type_def(ctx
->local_types
[base_idx
].type
,record
);
3177 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
));
3178 flat_rec
= type_prepare_flat_record(&def
->type
, ctx
->err
);
3179 if (unlikely(!flat_rec
))
3180 goto record_not_flattened
;
3181 for (ai
= 0; ai
< def
->n_entries
; ai
++) {
3182 pcode_t typ
= pcode_get();
3183 tp
= pcode_to_type(ctx
, typ
, NULL
);
3184 if (unlikely(!TYPE_IS_FLAT(tp
))) {
3185 type_free_flat_record(flat_rec
);
3186 goto record_not_flattened
;
3188 type_set_flat_record_entry(flat_rec
, ai
, tp
);
3190 tt
= type_get_flat_record(flat_rec
, ctx
->err
);
3192 goto record_not_flattened
;
3194 record_not_flattened
:
3197 case Local_Type_Flat_Array
:
3198 base_idx
= pcode_get();
3199 n_elements
= pcode_get();
3200 tp
= pcode_to_type(ctx
, base_idx
, NULL
);
3201 if (unlikely(!TYPE_IS_FLAT(tp
)))
3202 goto array_not_flattened
;
3203 if (unlikely(n_elements
> signed_maximum(int_default_t
) + zero
))
3204 goto array_not_flattened
;
3205 tt
= type_get_flat_array(tp
, n_elements
, ctx
->err
);
3207 goto array_not_flattened
;
3209 array_not_flattened
:
3210 tt
= type_get_unknown();
3213 internal(file_line
, "pcode_build_function_core(%s): invalid local type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
3215 ctx
->local_types
[p
].type
= tt
;
3216 ctx
->local_types
[p
].type_index
= no_type_index
;
3219 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, frame_align
, frame_offset
, ctx
->err
);
3220 if (unlikely(!ctx
->layout
))
3223 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
);
3224 if (unlikely(!ctx
->pcode_types
))
3227 if (unlikely(!array_init_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, ctx
->err
)))
3230 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3231 struct pcode_type
*pt
;
3232 pcode_t typ
, color
, varflags
;
3236 color
= pcode_get();
3237 varflags
= u_pcode_get();
3238 pcode_load_blob(ctx
, NULL
, NULL
);
3239 pt
= &ctx
->pcode_types
[v
];
3240 pt
->argument
= NULL
;
3242 pt
->varflags
= varflags
;
3247 const struct type
*t
= pcode_to_type(ctx
, typ
, NULL
);
3248 struct color empty_color
= { 0, 0, false };
3253 if (typ
< 0 && !pcode_get_type(typ
))
3254 pt
->extra_type
= typ
;
3255 while ((size_t)color
>= ctx
->n_colors
)
3256 if (unlikely(!array_add_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, empty_color
, NULL
, ctx
->err
)))
3260 if (!ctx
->colors
[color
].align
) {
3261 ctx
->colors
[color
].size
= t
->size
;
3262 ctx
->colors
[color
].align
= t
->align
;
3264 ajla_assert_lo(ctx
->colors
[color
].size
== t
->size
&&
3265 ctx
->colors
[color
].align
== t
->align
,
3266 (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
));
3271 /*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);*/
3273 for (is
= 0; is
< ctx
->n_colors
; is
++) {
3274 const struct color
*c
= &ctx
->colors
[is
];
3276 if (unlikely(!layout_add(ctx
->layout
, maximum(c
->size
, 1), c
->align
, ctx
->err
)))
3279 if (unlikely(!layout_add(ctx
->layout
, 0, 1, ctx
->err
)))
3284 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3287 ctx
->n_slots
= layout_size(ctx
->layout
);
3289 ctx
->local_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct local_variable
*, 0, 0, ctx
->n_slots
, sizeof(struct local_variable
), ctx
->err
);
3290 if (unlikely(!ctx
->local_variables
))
3293 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
);
3294 if (unlikely(!ctx
->local_variables_flags
))
3297 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3298 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3300 pt
->slot
= NO_FRAME_T
;
3302 pt
->slot
= layout_get(ctx
->layout
, pt
->color
);
3303 ctx
->local_variables
[pt
->slot
].type
= pt
->type
;
3304 /*ctx->local_variables_flags[pt->slot].may_be_borrowed = false;*/
3305 ctx
->local_variables_flags
[pt
->slot
].must_be_flat
= !!(pt
->varflags
& VarFlag_Must_Be_Flat
) /*|| TYPE_TAG_IS_BUILTIN(pt->type->tag)*/;
3309 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3313 unsigned n_elided
= 0;
3314 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3315 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3319 debug("function, elided %d/%d", n_elided
, ctx
->n_local_variables
);
3323 if (unlikely(!array_init_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ctx
->err
)))
3326 if (unlikely(!pcode_preload_ld(ctx
)))
3330 sfd
= save_find_function_descriptor(md
, fd
);
3337 ctx
->code
= sfd
->code
;
3338 ctx
->code_len
= sfd
->code_size
;
3344 ctx
->labels
= mem_alloc_array_mayfail(mem_alloc_mayfail
, size_t *, 0, 0, ctx
->n_labels
, sizeof(size_t), ctx
->err
);
3345 if (unlikely(!ctx
->labels
))
3347 for (p
= 0; p
< ctx
->n_labels
; p
++)
3348 ctx
->labels
[p
] = no_label
;
3350 if (unlikely(!array_init_mayfail(struct label_ref
, &ctx
->label_ref
, &ctx
->label_ref_len
, ctx
->err
)))
3353 if (unlikely(!array_init_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, ctx
->err
)))
3356 if (unlikely(!array_init_mayfail(code_t
, &ctx
->code
, &ctx
->code_len
, ctx
->err
)))
3359 if (unlikely(!array_init_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, ctx
->err
)))
3362 if (unlikely(ctx
->function_type
== Fn_Record
) || unlikely(ctx
->function_type
== Fn_Option
)) {
3363 if (ctx
->function_type
== Fn_Record
) {
3364 if (unlikely(!pcode_generate_record(ctx
)))
3367 gen_code(OPCODE_UNREACHABLE
);
3369 if (unlikely(!pcode_generate_instructions(ctx
)))
3373 array_finish(code_t
, &ctx
->code
, &ctx
->code_len
);
3374 array_finish(struct line_position
, &ctx
->lp
, &ctx
->lp_size
);
3376 for (is
= 0; is
< ctx
->label_ref_len
; is
++) {
3378 struct label_ref
*lr
= &ctx
->label_ref
[is
];
3379 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
));
3380 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
));
3381 diff
= ((uint32_t)ctx
->labels
[lr
->label
] - (uint32_t)lr
->code_pos
) * sizeof(code_t
);
3382 if (SIZEOF_IP_T
== 2) {
3383 ctx
->code
[lr
->code_pos
] += (code_t
)diff
;
3384 } else if (SIZEOF_IP_T
== 4 && !CODE_ENDIAN
) {
3385 uint32_t val
= ctx
->code
[lr
->code_pos
] | ((uint32_t)ctx
->code
[lr
->code_pos
+ 1] << 16);
3387 ctx
->code
[lr
->code_pos
] = val
& 0xffff;
3388 ctx
->code
[lr
->code_pos
+ 1] = val
>> 16;
3389 } else if (SIZEOF_IP_T
== 4 && CODE_ENDIAN
) {
3390 uint32_t val
= ((uint32_t)ctx
->code
[lr
->code_pos
] << 16) | ctx
->code
[lr
->code_pos
+ 1];
3392 ctx
->code
[lr
->code_pos
] = val
>> 16;
3393 ctx
->code
[lr
->code_pos
+ 1] = val
& 0xffff;
3399 mem_free(ctx
->labels
), ctx
->labels
= NULL
;
3400 mem_free(ctx
->label_ref
), ctx
->label_ref
= NULL
;
3402 ft
= data_alloc_flexible(function_types
, types
, ctx
->types_len
, ctx
->err
);
3405 da(ft
,function_types
)->n_types
= ctx
->types_len
;
3406 memcpy(da(ft
,function_types
)->types
, ctx
->types
, ctx
->types_len
* sizeof(const struct type
*));
3407 mem_free(ctx
->types
);
3413 mem_free(ctx
->colors
), ctx
->colors
= NULL
;
3414 mem_free(ctx
->pcode_types
), ctx
->pcode_types
= NULL
;
3415 mem_free(ctx
->local_types
), ctx
->local_types
= NULL
;
3417 array_finish(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
);
3419 if (profiling_escapes
) {
3420 ctx
->escape_data
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct escape_data
*, 0, 0, ctx
->code_len
, sizeof(struct escape_data
), ctx
->err
);
3421 if (unlikely(!ctx
->escape_data
))
3425 fn
= data_alloc_flexible(function
, local_directory
, ctx
->ld_len
, ctx
->err
);
3429 da(fn
,function
)->frame_slots
= frame_offset
/ slot_size
+ ctx
->n_slots
;
3430 da(fn
,function
)->n_bitmap_slots
= bitmap_slots(ctx
->n_slots
);
3431 da(fn
,function
)->n_arguments
= ctx
->n_real_arguments
;
3432 da(fn
,function
)->n_return_values
= ctx
->n_real_return_values
;
3433 da(fn
,function
)->code
= ctx
->code
;
3434 da(fn
,function
)->code_size
= ctx
->code_len
;
3435 da(fn
,function
)->local_variables
= ctx
->local_variables
;
3437 da(fn
,function
)->local_variables_flags
= ctx
->local_variables_flags
;
3439 mem_free(ctx
->local_variables_flags
);
3440 da(fn
,function
)->local_variables_flags
= sfd
->local_variables_flags
;
3442 da(fn
,function
)->args
= ctx
->args
;
3443 da(fn
,function
)->types_ptr
= pointer_data(ft
);
3444 da(fn
,function
)->record_definition
= ctx
->record_definition
? &ctx
->record_definition
->type
: NULL
;
3445 da(fn
,function
)->function_name
= cast_ptr(char *, ctx
->function_name
);
3446 da(fn
,function
)->module_designator
= md
;
3447 da(fn
,function
)->function_designator
= fd
;
3449 da(fn
,function
)->lp
= ctx
->lp
;
3450 da(fn
,function
)->lp_size
= ctx
->lp_size
;
3452 da(fn
,function
)->lp
= sfd
->lp
;
3453 da(fn
,function
)->lp_size
= sfd
->lp_size
;
3455 memcpy(da(fn
,function
)->local_directory
, ctx
->ld
, ctx
->ld_len
* sizeof(pointer_t
*));
3456 da(fn
,function
)->local_directory_size
= ctx
->ld_len
;
3460 da(fn
,function
)->codegen
= function_build_internal_thunk(codegen_fn
, 1, ia
);
3461 store_relaxed(&da(fn
,function
)->codegen_failed
, 0);
3463 function_init_common(fn
);
3466 /*if (memcmp(ctx->code, sfd->code, ctx->code_len * sizeof(code_t))) internal(file_line, "code mismatch");*/
3467 da(fn
,function
)->loaded_cache
= sfd
->data_saved_cache
;
3468 /*if (da(fn,function)->loaded_cache) debug("loaded cache: %s", function_name(ctx));*/
3471 da(fn
,function
)->escape_data
= ctx
->escape_data
;
3472 da(fn
,function
)->leaf
= ctx
->leaf
;
3473 da(fn
,function
)->is_saved
= is_saved
;
3475 ipret_prefetch_functions(fn
);
3477 return pointer_data(fn
);
3480 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3482 ctx
->ret_val
= pointer_mark();
3485 return ctx
->ret_val
;
3488 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
)
3493 ptr
= pcode_build_function_core(fp
, ip
, pcode
, size
, md
, fd
, &ex
, &err
);
3494 if (unlikely(pointer_is_empty(ptr
)))
3496 if (unlikely(pointer_is_mark(ptr
)))
3497 return function_return(fp
, pointer_error(err
, NULL
, NULL pass_file_line
));
3498 return function_return(fp
, ptr
);
3501 void *pcode_build_function_from_builtin(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3503 const pcode_t
*start
;
3505 struct module_designator
*md
= arguments
[0].ptr
;
3506 struct function_designator
*fd
= arguments
[1].ptr
;
3507 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3508 return pcode_build_function(fp
, ip
, start
, size
, md
, arguments
[1].ptr
);
3511 void *pcode_build_function_from_array(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3515 struct thunk
*thunk
;
3518 const struct function_designator
*fd
;
3519 const pcode_t
*start
;
3522 ptr
= arguments
[0].ptr
;
3523 ex
= pointer_deep_eval(ptr
, fp
, ip
, &thunk
);
3524 if (unlikely(ex
!= POINTER_FOLLOW_THUNK_GO
)) {
3525 if (ex
== POINTER_FOLLOW_THUNK_EXCEPTION
) {
3526 return function_return(fp
, pointer_thunk(thunk
));
3531 array_to_bytes(ptr
, &bytes
, &bytes_l
);
3534 if (unlikely(bytes_l
% sizeof(pcode_t
) != 0))
3535 internal(file_line
, "pcode_build_function_from_array: invalid length: %lu", (unsigned long)bytes_l
);
3537 start
= cast_ptr(const pcode_t
*, bytes
);
3538 size
= bytes_l
/ sizeof(pcode_t
);
3539 fd
= arguments
[2].ptr
;
3541 /*builtin_walk_nested(&start, &size, fd->n_entries, fd->entries);*/
3543 ex
= pcode_build_function(fp
, ip
, start
, size
, arguments
[1].ptr
, fd
);
3550 void *pcode_array_from_builtin(frame_s
*fp
, const code_t attr_unused
*ip
, union internal_arg arguments
[])
3552 const struct type
*t
;
3555 const pcode_t
*start
;
3557 struct module_designator
*md
= arguments
[0].ptr
;
3558 struct function_designator
*fd
= arguments
[1].ptr
;
3560 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3562 t
= type_get_fixed(log_2(sizeof(pcode_t
)), false);
3563 d
= data_alloc_array_flat_mayfail(t
, size
, size
, false, &err pass_file_line
);
3565 return function_return(fp
, pointer_thunk(thunk_alloc_exception_error(err
, NULL
, NULL
, NULL pass_file_line
)));
3568 memcpy(da_array_flat(d
), start
, size
* sizeof(pcode_t
));
3570 return function_return(fp
, pointer_data(d
));
3574 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
)
3578 unsigned n_local_variables
;
3579 unsigned n_arguments
;
3583 if (unlikely(!array_init_mayfail(pcode_t
, &pc
, &pc_l
, err
)))
3587 if (unlikely(!array_add_mayfail(pcode_t, &pc, &pc_l, x, NULL, err)))\
3590 #define addstr(x, l) \
3592 if (unlikely(!array_add_multiple_mayfail(pcode_t, &pc, &pc_l, x, l, NULL, err)))\
3596 n_local_variables
= Op_IsUnary(op
) ? 2 : 3;
3597 n_arguments
= n_local_variables
- 1;
3600 add(Call_Mode_Strict
);
3603 add(n_local_variables
);
3610 for (i
= 0; i
< n_local_variables
; i
++) {
3611 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3623 add(1 + blob_1_len
);
3625 addstr(blob_1
, blob_1_len
);
3626 if (n_arguments
== 2) {
3628 add(1 + blob_2_len
);
3630 addstr(blob_2
, blob_2_len
);
3633 add(Op_IsUnary(op
) ? P_UnaryOp
: P_BinaryOp
);
3634 add(Op_IsUnary(op
) ? 4 : 6);
3637 add(Flag_Free_Argument
| Flag_Op_Strict
);
3639 if (n_arguments
== 2) {
3640 add(Flag_Free_Argument
);
3646 add(Flag_Free_Argument
);
3652 ptr
= pcode_build_function_core(NULL
, NULL
, pc
, pc_l
, NULL
, NULL
, NULL
, err
);
3661 return pointer_empty();
3665 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
)
3667 struct data
*function
;
3670 #ifdef POINTER_FOLLOW_IS_LOCKLESS
3671 const addrlock_depth lock_depth
= DEPTH_THUNK
;
3673 const addrlock_depth lock_depth
= DEPTH_POINTER
;
3677 pointer_follow(ptr
, false, function
, PF_WAIT
, fp
, ip
,
3680 return POINTER_FOLLOW_THUNK_RETRY
);
3682 if (likely(function
!= NULL
)) {
3684 return POINTER_FOLLOW_THUNK_RETRY
;
3687 fn_thunk
= function_build_internal_thunk(build_fn
, n_arguments
, ia
);
3689 barrier_write_before_lock();
3690 address_lock(ptr
, lock_depth
);
3691 if (likely(pointer_is_empty(*pointer_volatile(ptr
)))) {
3692 *pointer_volatile(ptr
) = fn_thunk
;
3693 address_unlock(ptr
, lock_depth
);
3695 address_unlock(ptr
, lock_depth
);
3696 pointer_dereference(fn_thunk
);
3702 static void *pcode_build_op_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3704 pcode_t src_type
= (pcode_t
)a
[0].i
;
3705 pcode_t dest_type
= (pcode_t
)a
[1].i
;
3706 pcode_t op
= (pcode_t
)a
[2].i
;
3707 unsigned flags
= (unsigned)a
[3].i
;
3709 unsigned n_local_variables
;
3710 unsigned n_arguments
;
3712 pcode_t
*pc
= pcode
;
3714 n_local_variables
= flags
& PCODE_FIND_OP_UNARY
? 2 : 3;
3715 n_arguments
= n_local_variables
- 1;
3717 *pc
++ = Fn_Function
;
3718 *pc
++ = Call_Mode_Strict
;
3721 *pc
++ = (pcode_t
)n_local_variables
;
3722 *pc
++ = (pcode_t
)n_arguments
;
3728 for (i
= 0; i
< n_local_variables
; i
++) {
3729 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3738 *pc
++ = n_arguments
;
3739 for (i
= 0; i
< n_arguments
; i
++)
3742 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? P_UnaryOp
: P_BinaryOp
);
3743 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? 4 : 6);
3745 *pc
++ = (pcode_t
)n_arguments
;
3746 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3748 if (!(flags
& PCODE_FIND_OP_UNARY
)) {
3749 *pc
++ = Flag_Free_Argument
;
3755 *pc
++ = Flag_Free_Argument
;
3756 *pc
++ = n_arguments
;
3758 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
));
3760 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3763 static pointer_t fixed_op_thunk
[TYPE_FIXED_N
][OPCODE_FIXED_OP_N
];
3764 static pointer_t int_op_thunk
[TYPE_INT_N
][OPCODE_INT_OP_N
];
3765 static pointer_t real_op_thunk
[TYPE_REAL_N
][OPCODE_REAL_OP_N
];
3766 static pointer_t bool_op_thunk
[OPCODE_BOOL_TYPE_MULT
];
3768 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
)
3770 union internal_arg ia
[4];
3773 type_tag_t tag
= likely(!(flags
& PCODE_CONVERT_FROM_INT
)) ? type
->tag
: rtype
->tag
;
3775 if (TYPE_TAG_IS_FIXED(tag
)) {
3776 unsigned idx
= (code
- OPCODE_FIXED_OP
- (TYPE_TAG_IDX_FIXED(tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
) / OPCODE_FIXED_OP_MULT
;
3777 ajla_assert(idx
< OPCODE_FIXED_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3778 ptr
= &fixed_op_thunk
[TYPE_TAG_IDX_FIXED(tag
) >> 1][idx
];
3779 } else if (TYPE_TAG_IS_INT(tag
)) {
3780 unsigned idx
= (code
- OPCODE_INT_OP
- TYPE_TAG_IDX_INT(tag
) * OPCODE_INT_TYPE_MULT
) / OPCODE_INT_OP_MULT
;
3781 ajla_assert(idx
< OPCODE_INT_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3782 ptr
= &int_op_thunk
[TYPE_TAG_IDX_INT(tag
)][idx
];
3783 ajla_assert(is_power_of_2(type
->size
), (file_line
, "pcode_find_op_function: invalid integer type size %"PRIuMAX
"", (uintmax_t)type
->size
));
3784 } else if (TYPE_TAG_IS_REAL(tag
)) {
3785 unsigned idx
= (code
- OPCODE_REAL_OP
- TYPE_TAG_IDX_REAL(tag
) * OPCODE_REAL_TYPE_MULT
) / OPCODE_REAL_OP_MULT
;
3786 ajla_assert(idx
< OPCODE_REAL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3787 ptr
= &real_op_thunk
[TYPE_TAG_IDX_REAL(tag
)][idx
];
3789 unsigned idx
= (code
- OPCODE_BOOL_OP
) / OPCODE_BOOL_OP_MULT
;
3790 ajla_assert(idx
< OPCODE_BOOL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3791 ptr
= &bool_op_thunk
[idx
];
3793 internal(file_line
, "pcode_find_op_function: invalid type %u", tag
);
3796 ia
[0].i
= type_to_pcode(type
);
3797 ia
[1].i
= type_to_pcode(rtype
);
3798 ia
[2].i
= code
+ Op_N
;
3801 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_op_function
, 4, ia
, result
);
3804 static void *pcode_build_is_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3807 pcode_t
*pc
= pcode
;
3809 *pc
++ = Fn_Function
;
3810 *pc
++ = Call_Mode_Strict
;
3820 *pc
++ = T_Undetermined
;
3821 *pc
++ = T_Undetermined
;
3826 *pc
++ = T_FlatOption
;
3827 *pc
++ = T_FlatOption
;
3838 *pc
++ = Un_IsException
;
3840 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3849 *pc
++ = Flag_Free_Argument
;
3852 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
)));
3854 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3857 static pointer_t is_exception_thunk
;
3859 void * attr_fastcall
pcode_find_is_exception(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3861 return pcode_alloc_op_function(&is_exception_thunk
, fp
, ip
, pcode_build_is_exception_function
, 0, NULL
, result
);
3864 static void *pcode_build_get_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3867 pcode_t
*pc
= pcode
;
3869 *pc
++ = Fn_Function
;
3870 *pc
++ = Call_Mode_Strict
;
3880 *pc
++ = T_Undetermined
;
3881 *pc
++ = T_Undetermined
;
3898 *pc
++ = Un_ExceptionClass
+ a
[0].i
;
3900 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3909 *pc
++ = Flag_Free_Argument
;
3912 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
)));
3914 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3917 static pointer_t get_exception_thunk
[3];
3919 void * attr_fastcall
pcode_find_get_exception(unsigned mode
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3921 union internal_arg ia
[1];
3923 return pcode_alloc_op_function(&get_exception_thunk
[mode
], fp
, ip
, pcode_build_get_exception_function
, 1, ia
, result
);
3926 static void *pcode_build_array_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3929 pcode_t
*pc
= pcode
;
3931 *pc
++ = Fn_Function
;
3932 *pc
++ = Call_Mode_Strict
;
3942 *pc
++ = T_Undetermined
;
3943 *pc
++ = T_Undetermined
;
3954 *pc
++ = T_Undetermined
;
3955 *pc
++ = T_Undetermined
;
3965 *pc
++ = P_Array_Load
;
3968 *pc
++ = Flag_Evaluate
;
3982 *pc
++ = Flag_Free_Argument
;
3985 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
)));
3987 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3990 static pointer_t array_load_thunk
;
3992 void * attr_fastcall
pcode_find_array_load_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3994 return pcode_alloc_op_function(&array_load_thunk
, fp
, ip
, pcode_build_array_load_function
, 0, NULL
, result
);
3997 static void *pcode_build_array_len_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4000 pcode_t
*pc
= pcode
;
4002 *pc
++ = Fn_Function
;
4003 *pc
++ = Call_Mode_Strict
;
4013 *pc
++ = T_Undetermined
;
4014 *pc
++ = T_Undetermined
;
4029 *pc
++ = P_Array_Len
;
4033 *pc
++ = Flag_Evaluate
;
4041 *pc
++ = Flag_Free_Argument
;
4044 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
)));
4046 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4049 static pointer_t array_len_thunk
;
4051 void * attr_fastcall
pcode_find_array_len_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4053 return pcode_alloc_op_function(&array_len_thunk
, fp
, ip
, pcode_build_array_len_function
, 0, NULL
, result
);
4056 static void *pcode_build_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4059 pcode_t
*pc
= pcode
;
4061 *pc
++ = Fn_Function
;
4062 *pc
++ = Call_Mode_Strict
;
4072 *pc
++ = T_Undetermined
;
4073 *pc
++ = T_Undetermined
;
4084 *pc
++ = T_FlatOption
;
4085 *pc
++ = T_FlatOption
;
4095 *pc
++ = P_Array_Len_Greater_Than
;
4100 *pc
++ = Flag_Evaluate
;
4112 *pc
++ = Flag_Free_Argument
;
4115 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
)));
4117 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4120 static pointer_t array_len_greater_than_thunk
;
4122 void * attr_fastcall
pcode_find_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4124 return pcode_alloc_op_function(&array_len_greater_than_thunk
, fp
, ip
, pcode_build_array_len_greater_than_function
, 0, NULL
, result
);
4127 static void *pcode_build_array_sub_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4130 pcode_t
*pc
= pcode
;
4132 *pc
++ = Fn_Function
;
4133 *pc
++ = Call_Mode_Strict
;
4143 *pc
++ = T_Undetermined
;
4144 *pc
++ = T_Undetermined
;
4161 *pc
++ = T_Undetermined
;
4162 *pc
++ = T_Undetermined
;
4173 *pc
++ = P_Array_Sub
;
4176 *pc
++ = Flag_Evaluate
;
4195 *pc
++ = Flag_Free_Argument
;
4198 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
)));
4200 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4203 static pointer_t array_sub_thunk
;
4205 void * attr_fastcall
pcode_find_array_sub_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4207 return pcode_alloc_op_function(&array_sub_thunk
, fp
, ip
, pcode_build_array_sub_function
, 0, NULL
, result
);
4210 static void *pcode_build_array_skip_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4213 pcode_t
*pc
= pcode
;
4215 *pc
++ = Fn_Function
;
4216 *pc
++ = Call_Mode_Strict
;
4226 *pc
++ = T_Undetermined
;
4227 *pc
++ = T_Undetermined
;
4238 *pc
++ = T_Undetermined
;
4239 *pc
++ = T_Undetermined
;
4249 *pc
++ = P_Array_Skip
;
4252 *pc
++ = Flag_Evaluate
;
4266 *pc
++ = Flag_Free_Argument
;
4269 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
)));
4271 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4274 static pointer_t array_skip_thunk
;
4276 void * attr_fastcall
pcode_find_array_skip_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4278 return pcode_alloc_op_function(&array_skip_thunk
, fp
, ip
, pcode_build_array_skip_function
, 0, NULL
, result
);
4281 static void *pcode_build_array_append_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4284 pcode_t
*pc
= pcode
;
4286 *pc
++ = Fn_Function
;
4287 *pc
++ = Call_Mode_Strict
;
4297 *pc
++ = T_Undetermined
;
4298 *pc
++ = T_Undetermined
;
4303 *pc
++ = T_Undetermined
;
4304 *pc
++ = T_Undetermined
;
4309 *pc
++ = T_Undetermined
;
4310 *pc
++ = T_Undetermined
;
4330 *pc
++ = P_Array_Append
;
4333 *pc
++ = Flag_Free_Argument
;
4335 *pc
++ = Flag_Free_Argument
;
4340 *pc
++ = Flag_Free_Argument
;
4342 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
)));
4344 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4347 static pointer_t array_append_thunk
;
4349 void * attr_fastcall
pcode_find_array_append_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4351 return pcode_alloc_op_function(&array_append_thunk
, fp
, ip
, pcode_build_array_append_function
, 0, NULL
, result
);
4355 static void *pcode_build_option_ord_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4358 pcode_t
*pc
= pcode
;
4360 *pc
++ = Fn_Function
;
4361 *pc
++ = Call_Mode_Strict
;
4371 *pc
++ = T_Undetermined
;
4372 *pc
++ = T_Undetermined
;
4391 *pc
++ = P_Option_Ord
;
4402 *pc
++ = Flag_Free_Argument
;
4405 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
)));
4407 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4410 static pointer_t option_ord_thunk
;
4412 void * attr_fastcall
pcode_find_option_ord_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4414 return pcode_alloc_op_function(&option_ord_thunk
, fp
, ip
, pcode_build_option_ord_function
, 0, NULL
, result
);
4418 struct function_key
{
4423 static void *pcode_build_record_option_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
4426 pcode_t
*pc
= pcode
;
4427 pcode_t result_type
= a
[0].i
== PCODE_FUNCTION_OPTION_TEST
? T_FlatOption
: T_Undetermined
;
4429 *pc
++ = Fn_Function
;
4430 *pc
++ = Call_Mode_Strict
;
4440 *pc
++ = T_Undetermined
;
4441 *pc
++ = T_Undetermined
;
4446 *pc
++ = result_type
;
4447 *pc
++ = result_type
;
4457 case PCODE_FUNCTION_RECORD_LOAD
:
4458 /* P_Record_Load_Slot already sets Flag_Evaluate */
4459 *pc
++ = P_Record_Load_Slot
;
4463 *pc
++ = (pcode_t
)a
[1].i
;
4465 case PCODE_FUNCTION_OPTION_LOAD
:
4466 *pc
++ = P_Option_Load
;
4469 *pc
++ = Flag_Evaluate
;
4471 *pc
++ = (pcode_t
)a
[1].i
;
4473 case PCODE_FUNCTION_OPTION_TEST
:
4477 *pc
++ = P_Option_Test
;
4481 *pc
++ = (pcode_t
)a
[1].i
;
4484 internal(file_line
, "pcode_build_record_option_load_function: invalid operation %"PRIuMAX
"", (uintmax_t)a
[0].i
);
4493 *pc
++ = Flag_Free_Argument
;
4496 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
)));
4498 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4501 struct pcode_function
{
4502 struct tree_entry entry
;
4503 struct function_key key
;
4507 shared_var
struct tree pcode_functions
;
4508 rwlock_decl(pcode_functions_mutex
);
4510 static int record_option_load_compare(const struct tree_entry
*e1
, uintptr_t e2
)
4512 struct pcode_function
*rl
= get_struct(e1
, struct pcode_function
, entry
);
4513 struct function_key
*key
= cast_cpp(struct function_key
*, num_to_ptr(e2
));
4514 if (rl
->key
.tag
!= key
->tag
)
4515 return (int)rl
->key
.tag
- key
->tag
;
4516 if (rl
->key
.id
< key
->id
)
4518 if (rl
->key
.id
> key
->id
)
4523 static pointer_t
*pcode_find_function_for_key(struct function_key
*key
)
4525 struct tree_entry
*e
;
4527 rwlock_lock_read(&pcode_functions_mutex
);
4528 e
= tree_find(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
));
4529 rwlock_unlock_read(&pcode_functions_mutex
);
4531 struct tree_insert_position ins
;
4532 rwlock_lock_write(&pcode_functions_mutex
);
4533 e
= tree_find_for_insert(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
), &ins
);
4536 struct pcode_function
*rl
;
4537 rl
= mem_alloc_mayfail(struct pcode_function
*, sizeof(struct pcode_function
), &sink
);
4538 if (unlikely(!rl
)) {
4539 rwlock_unlock_write(&pcode_functions_mutex
);
4543 rl
->ptr
= pointer_empty();
4545 tree_insert_after_find(e
, &ins
);
4547 rwlock_unlock_write(&pcode_functions_mutex
);
4549 return &get_struct(e
, struct pcode_function
, entry
)->ptr
;
4552 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
)
4554 struct function_key key
;
4556 union internal_arg ia
[2];
4558 if (unlikely((uintmax_t)slot
> (uintmax_t)signed_maximum(pcode_t
) + zero
)) {
4559 *result
= out_of_memory_ptr
;
4560 return POINTER_FOLLOW_THUNK_RETRY
;
4566 ptr
= pcode_find_function_for_key(&key
);
4567 if (unlikely(!ptr
)) {
4568 *result
= out_of_memory_ptr
;
4569 return POINTER_FOLLOW_THUNK_RETRY
;
4574 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_record_option_load_function
, 2, ia
, result
);
4577 static void thunk_init_run(pointer_t
*ptr
, unsigned n
)
4580 *ptr
= pointer_empty();
4585 static void thunk_free_run(pointer_t
*ptr
, unsigned n
)
4588 if (!pointer_is_empty(*ptr
))
4589 pointer_dereference(*ptr
);
4594 void name(pcode_init
)(void)
4598 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_init_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4599 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_init_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4600 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_init_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4601 thunk_init_run(&is_exception_thunk
, 1);
4602 thunk_init_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4603 thunk_init_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4604 thunk_init_run(&array_load_thunk
, 1);
4605 thunk_init_run(&array_len_thunk
, 1);
4606 thunk_init_run(&array_len_greater_than_thunk
, 1);
4607 thunk_init_run(&array_sub_thunk
, 1);
4608 thunk_init_run(&array_skip_thunk
, 1);
4609 thunk_init_run(&array_append_thunk
, 1);
4610 thunk_init_run(&option_ord_thunk
, 1);
4611 tree_init(&pcode_functions
);
4612 rwlock_init(&pcode_functions_mutex
);
4615 void name(pcode_done
)(void)
4618 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_free_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4619 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_free_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4620 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_free_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4621 thunk_free_run(&is_exception_thunk
, 1);
4622 thunk_free_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4623 thunk_free_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4624 thunk_free_run(&array_load_thunk
, 1);
4625 thunk_free_run(&array_len_thunk
, 1);
4626 thunk_free_run(&array_len_greater_than_thunk
, 1);
4627 thunk_free_run(&array_sub_thunk
, 1);
4628 thunk_free_run(&array_skip_thunk
, 1);
4629 thunk_free_run(&array_append_thunk
, 1);
4630 thunk_free_run(&option_ord_thunk
, 1);
4631 while (!tree_is_empty(&pcode_functions
)) {
4632 struct pcode_function
*rl
= get_struct(tree_any(&pcode_functions
), struct pcode_function
, entry
);
4633 if (!pointer_is_empty(rl
->ptr
))
4634 pointer_dereference(rl
->ptr
);
4635 tree_delete(&rl
->entry
);
4638 rwlock_done(&pcode_functions_mutex
);