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 typedef unsigned char arg_mode_t
;
174 static bool adjust_arg_mode(arg_mode_t
*am
, uintmax_t offs
, ajla_error_t
*mayfail
)
177 if (offs
+ uzero
<= 0xff) my_am
= 0;
178 else if (offs
+ uzero
<= 0xffffU
) my_am
= 1;
179 else if (offs
+ uzero
<= 0xffffffffUL
+ uzero
) my_am
= 2;
181 if (unlikely(my_am
>= ARG_MODE_N
)) {
183 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
186 internal(file_line
, "adjust_arg_mode: too big arg mode: offset %"PRIuMAX
", max mode %d", (uintmax_t)offs
, ARG_MODE_N
);
188 if (unlikely(my_am
> *am
))
193 #define get_arg_mode(am, val) \
195 if (unlikely(!adjust_arg_mode(&(am), (val), ctx->err))) \
200 const struct type
*type
;
205 const struct type
*type
;
206 struct local_arg
*argument
;
210 bool is_dereferenced_in_call_argument
;
225 struct tree_entry entry
;
230 struct build_function_context
{
231 const pcode_t
*pcode
;
232 const pcode_t
*pcode_limit
;
233 const pcode_t
*pcode_instr_end
;
238 pcode_t function_type
;
239 pcode_t n_local_types
;
241 frame_t n_local_variables
;
243 arg_t n_return_values
;
244 arg_t n_real_arguments
;
245 arg_t n_real_return_values
;
248 uint8_t *function_name
;
250 struct local_type
*local_types
;
251 struct pcode_type
*pcode_types
; /* indexed by pcode idx */
252 struct layout
*layout
;
253 struct local_variable
*local_variables
; /* indexed by slot */
254 struct local_variable_flags
*local_variables_flags
; /* indexed by slot */
256 struct color
*colors
;
260 struct label_ref
*label_ref
;
261 size_t label_ref_len
;
267 struct local_arg
*args
;
269 const struct type
**types
;
271 struct data
*ft_free
;
276 frame_t
*record_entries
;
277 size_t record_entries_len
;
279 struct record_definition
*record_definition
;
281 struct line_position
*lp
;
284 struct escape_data
*escape_data
;
286 unsigned checkpoint_num
;
291 pcode_t builtin_type_indices
[TYPE_TAG_N
];
294 static const pcode_t no_type_index
= -1;
295 static const pcode_t error_type_index
= -2;
296 static const size_t no_label
= (size_t)-1;
298 static void init_ctx(struct build_function_context
*ctx
)
301 ctx
->n_real_arguments
= 0;
302 ctx
->function_name
= NULL
;
303 ctx
->local_types
= NULL
;
304 ctx
->pcode_types
= NULL
;
306 ctx
->local_variables
= NULL
;
307 ctx
->local_variables_flags
= NULL
;
310 ctx
->label_ref
= NULL
;
312 tree_init(&ctx
->ld_tree
);
318 ctx
->record_entries
= NULL
;
319 ctx
->record_definition
= NULL
;
322 ctx
->escape_data
= NULL
;
323 ctx
->checkpoint_num
= 0;
325 for (i
= 0; i
< n_array_elements(ctx
->builtin_type_indices
); i
++)
326 ctx
->builtin_type_indices
[i
] = no_type_index
;
329 static void free_ld_tree(struct build_function_context
*ctx
)
331 while (!tree_is_empty(&ctx
->ld_tree
)) {
332 struct ld_ref
*ld_ref
= get_struct(tree_any(&ctx
->ld_tree
), struct ld_ref
, entry
);
333 tree_delete(&ld_ref
->entry
);
338 static void done_ctx(struct build_function_context
*ctx
)
340 if (ctx
->function_name
)
341 mem_free(ctx
->function_name
);
342 if (ctx
->local_types
)
343 mem_free(ctx
->local_types
);
344 if (ctx
->pcode_types
)
345 mem_free(ctx
->pcode_types
);
347 layout_free(ctx
->layout
);
348 if (ctx
->local_variables
)
349 mem_free(ctx
->local_variables
);
350 if (ctx
->local_variables_flags
)
351 mem_free(ctx
->local_variables_flags
);
353 mem_free(ctx
->colors
);
355 mem_free(ctx
->labels
);
357 mem_free(ctx
->label_ref
);
364 mem_free(ctx
->types
);
366 mem_free(ctx
->ft_free
);
369 if (ctx
->record_entries
)
370 mem_free(ctx
->record_entries
);
371 if (ctx
->record_definition
) {
372 mem_free(ctx
->record_definition
->idx_to_frame
);
373 mem_free(ctx
->record_definition
);
377 if (ctx
->escape_data
)
378 mem_free(ctx
->escape_data
);
381 static char *function_name(const struct build_function_context
*ctx
)
383 if (ctx
->function_name
)
384 return cast_ptr(char *, ctx
->function_name
);
388 static pcode_t
pcode_get_fn(struct build_function_context
*ctx argument_position
)
390 ajla_assert(ctx
->pcode
< ctx
->pcode_limit
, (caller_file_line
, "pcode_get_fn(%s): no pcode left", function_name(ctx
)));
391 return *ctx
->pcode
++;
393 #define pcode_get() pcode_get_fn(ctx pass_file_line)
395 static pcode_t
u_pcode_get_fn(struct build_function_context
*ctx argument_position
)
397 pcode_t p
= pcode_get_fn(ctx pass_position
);
398 ajla_assert(p
>= 0, (caller_file_line
, "u_pcode_get_fn(%s): negative pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)p
));
401 #define u_pcode_get() u_pcode_get_fn(ctx pass_file_line)
403 typedef const pcode_t
*pcode_position_save_t
;
405 static inline void pcode_position_save(struct build_function_context
*ctx
, pcode_position_save_t
*save
)
410 static inline void pcode_position_restore(struct build_function_context
*ctx
, const pcode_position_save_t
*save
)
415 typedef size_t code_position_save_t
;
417 static inline void code_position_save(struct build_function_context
*ctx
, code_position_save_t
*save
)
419 *save
= ctx
->code_len
;
422 static inline void code_position_restore(struct build_function_context
*ctx
, const code_position_save_t
*save
)
424 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
));
425 ctx
->code_len
= *save
;
428 const struct type
*pcode_get_type(pcode_t q
)
430 const struct type
*t
;
433 t
= type_get_fixed(0, false);
436 t
= type_get_fixed(0, true);
439 t
= type_get_fixed(1, false);
442 t
= type_get_fixed(1, true);
445 t
= type_get_fixed(2, false);
448 t
= type_get_fixed(2, true);
451 t
= type_get_fixed(3, false);
454 t
= type_get_fixed(3, true);
457 t
= type_get_fixed(4, false);
460 t
= type_get_fixed(4, true);
464 t
= type_get_int(INT_DEFAULT_N
);
483 t
= type_get_real(0);
486 t
= type_get_real(1);
489 t
= type_get_real(2);
492 t
= type_get_real(3);
495 t
= type_get_real(4);
499 t
= type_get_flat_option();
503 t
= type_get_unknown();
513 static const struct type
*pcode_to_type(const struct build_function_context
*ctx
, pcode_t q
, ajla_error_t
*mayfail
)
515 const struct type
*t
;
517 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
));
518 return ctx
->local_types
[q
].type
;
520 t
= pcode_get_type(q
);
522 if (q
== T_SInt64
|| q
== T_UInt64
|| q
== T_SInt128
|| q
== T_UInt128
)
523 return pcode_get_type(T_Integer128
);
524 if (q
== T_Real16
|| q
== T_Real32
|| q
== T_Real64
|| q
== T_Real80
|| q
== T_Real128
)
525 return pcode_get_type(T_Integer128
);
526 if (unlikely(!mayfail
))
527 internal(file_line
, "pcode_to_type(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
528 *mayfail
= error_ajla(EC_ASYNC
, AJLA_ERROR_NOT_SUPPORTED
);
533 static pcode_t
type_to_pcode(const struct type
*type
)
535 if (TYPE_TAG_IS_FIXED(type
->tag
))
536 return (pcode_t
)(T_SInt8
- TYPE_TAG_IDX_FIXED(type
->tag
));
537 else if (TYPE_TAG_IS_INT(type
->tag
))
538 return (pcode_t
)(T_Integer8
- TYPE_TAG_IDX_INT(type
->tag
));
539 else if (TYPE_TAG_IS_REAL(type
->tag
))
540 return (pcode_t
)(T_Real16
- TYPE_TAG_IDX_REAL(type
->tag
));
541 else if (type
->tag
== TYPE_TAG_flat_option
)
544 internal(file_line
, "type_to_pcode: invalid type %u", type
->tag
);
548 static pcode_t
pcode_to_type_index(struct build_function_context
*ctx
, pcode_t q
, bool non_flat
)
551 const struct type
*type
= pcode_to_type(ctx
, q
, NULL
);
552 if (!TYPE_IS_FLAT(type
) && non_flat
)
553 return no_type_index
;
556 result
= &ctx
->local_types
[q
].type_index
;
558 unsigned tag
= type
->tag
;
559 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
));
560 result
= &ctx
->builtin_type_indices
[tag
];
562 if (*result
!= no_type_index
)
564 if (unlikely((pcode_t
)ctx
->types_len
< 0)) {
565 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "type array overflow");
566 return error_type_index
;
568 if (unlikely(!array_add_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, type
, NULL
, ctx
->err
)))
569 return error_type_index
;
570 return *result
= (pcode_t
)(ctx
->types_len
- 1);
573 #define pcode_get_var_deref(var, deref) \
575 pcode_t r_ = u_pcode_get(); \
576 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_));\
577 *(deref) = !!(r_ & Flag_Free_Argument); \
578 *(var) = pcode_get(); \
581 #define var_elided(idx) (((idx) < zero) || ctx->pcode_types[idx].type == NULL)
583 static struct pcode_type
*get_var_type(struct build_function_context
*ctx
, pcode_t v
)
585 ajla_assert_lo(!var_elided(v
), (file_line
, "get_var_type(%s): variable %"PRIdMAX
" is elided", function_name(ctx
), (intmax_t)v
));
586 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
));
587 return &ctx
->pcode_types
[v
];
590 static bool pcode_load_blob(struct build_function_context
*ctx
, uint8_t **blob
, size_t *l
)
595 if (unlikely(!array_init_mayfail(uint8_t, blob
, l
, ctx
->err
)))
599 q
= 0; /* avoid warning */
601 for (i
= 0; i
< n
; i
++) {
609 if (unlikely(!array_add_mayfail(uint8_t, blob
, l
, (uint8_t)val
, NULL
, ctx
->err
)))
617 static bool pcode_generate_blob(uint8_t *str
, size_t str_len
, pcode_t
**res_blob
, size_t *res_len
, ajla_error_t
*err
)
620 if (unlikely(str_len
> signed_maximum(pcode_t
))) {
621 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), err
, "pcode overflow");
624 if (unlikely(!array_init_mayfail(pcode_t
, res_blob
, res_len
, err
)))
626 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, 0, NULL
, err
)))
628 for (i
= 0; i
< str_len
; i
++) {
630 if (!(**res_blob
% sizeof(pcode_t
))) {
631 if (unlikely(!array_add_mayfail(pcode_t
, res_blob
, res_len
, b
, NULL
, err
)))
634 (*res_blob
)[*res_len
- 1] |= (upcode_t
)((b
) & 0xff) << (**res_blob
% sizeof(pcode_t
) * 8);
641 static pointer_t
*pcode_module_load_function(struct build_function_context
*ctx
)
646 uint8_t *blob
= NULL
;
648 struct module_designator
*md
= NULL
;
649 struct function_designator
*fd
= NULL
;
653 path_idx
= (unsigned)q
;
654 if (unlikely(q
!= (pcode_t
)path_idx
))
655 goto exception_overflow
;
656 program
= path_idx
& 1;
658 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
661 md
= module_designator_alloc(path_idx
, blob
, l
, program
, ctx
->err
);
665 mem_free(blob
), blob
= NULL
;
667 fd
= function_designator_alloc(ctx
->pcode
, ctx
->err
);
670 ctx
->pcode
+= fd
->n_entries
+ 1;
672 ptr
= module_load_function(md
, fd
, false, ctx
->err
);
676 module_designator_free(md
), md
= NULL
;
677 function_designator_free(fd
), fd
= NULL
;
682 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "pcode overflow");
687 module_designator_free(md
);
689 function_designator_free(fd
);
693 #define no_function_idx ((size_t)-1)
695 static int ld_tree_compare(const struct tree_entry
*e
, uintptr_t ptr
)
697 struct ld_ref
*ld_ref
= get_struct(e
, struct ld_ref
, entry
);
698 uintptr_t ld_ptr
= ptr_to_num(ld_ref
->ptr
);
706 static size_t pcode_module_load_function_idx(struct build_function_context
*ctx
, pointer_t
*ptr
, bool must_exist
)
708 struct tree_entry
*e
;
709 struct ld_ref
*ld_ref
;
710 struct tree_insert_position ins
;
712 e
= tree_find_for_insert(&ctx
->ld_tree
, ld_tree_compare
, ptr_to_num(ptr
), &ins
);
714 ld_ref
= get_struct(e
, struct ld_ref
, entry
);
718 if (unlikely(must_exist
))
719 internal(file_line
, "pcode_module_load_function_idx: local directory preload didn't work");
721 ld_ref
= mem_alloc_mayfail(struct ld_ref
*, sizeof(struct ld_ref
), ctx
->err
);
722 if (unlikely(!ld_ref
))
723 return no_function_idx
;
725 ld_ref
->idx
= ctx
->ld_len
;
727 tree_insert_after_find(&ld_ref
->entry
, &ins
);
729 if (unlikely(!array_add_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ptr
, NULL
, ctx
->err
)))
730 return no_function_idx
;
731 return ctx
->ld_len
- 1;
734 #define gen_code(n) \
736 if (unlikely(!array_add_mayfail(code_t, &ctx->code, &ctx->code_len, n, NULL, ctx->err)))\
741 #define gen_uint32(n) \
743 gen_code((code_t)((n) & 0xffff)); \
744 gen_code((code_t)((n) >> 15 >> 1)); \
747 #define gen_uint32(n) \
749 gen_code((code_t)((n) >> 15 >> 1)); \
750 gen_code((code_t)((n) & 0xffff)); \
754 #define gen_am(am, m) \
757 gen_code((code_t)(m)); \
758 } else if (am == 2) { \
761 internal(file_line, "gen_am(%s): arg mode %d", function_name(ctx), am);\
765 #define gen_am_two(am, m, n) \
768 gen_code((code_t)((m) + ((n) << 8))); \
769 } else if (am == 1) { \
770 gen_code((code_t)(m)); \
771 gen_code((code_t)(n)); \
772 } else if (am == 2) { \
776 internal(file_line, "gen_am_two(%s): arg mode %d", function_name(ctx), am);\
780 #define gen_relative_jump(lbl, diff) \
783 ajla_assert_lo((lbl) < ctx->n_labels, (file_line, "gen_relative_jump(%s): invalid label %"PRIdMAX"", function_name(ctx), (intmax_t)(lbl)));\
784 if (ctx->labels[lbl] == no_label) { \
785 struct label_ref lr; \
786 lr.code_pos = ctx->code_len; \
788 if (unlikely(!array_add_mayfail(struct label_ref, &ctx->label_ref, &ctx->label_ref_len, lr, NULL, ctx->err)))\
790 target = -(((uint32_t)(diff) + 1) / (uint32_t)sizeof(code_t) * (uint32_t)sizeof(code_t));\
792 target = ((uint32_t)ctx->labels[lbl] - (uint32_t)(ctx->code_len + SIZEOF_IP_T / (uint32_t)sizeof(code_t))) * (uint32_t)sizeof(code_t);\
794 if (SIZEOF_IP_T == 2) \
795 gen_code((code_t)target); \
796 else if (SIZEOF_IP_T == 4) \
797 gen_uint32(target); \
798 else not_reached(); \
801 static bool gen_checkpoint(struct build_function_context
*ctx
, arg_mode_t am
)
808 get_arg_mode(am
, ctx
->checkpoint_num
);
810 code
= OPCODE_CHECKPOINT
;
811 code
+= am
* OPCODE_MODE_MULT
;
813 gen_am(am
, ctx
->checkpoint_num
);
815 ctx
->checkpoint_num
++;
816 if (unlikely(!ctx
->checkpoint_num
)) {
817 fatal_mayfail(error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
), ctx
->err
, "checkpoint number overflow");
826 static bool pcode_free(struct build_function_context
*ctx
, pcode_t res
)
829 const struct pcode_type
*tr
;
831 const struct color
*c
;
833 if (unlikely(var_elided(res
)))
835 tr
= get_var_type(ctx
, res
);
837 get_arg_mode(am
, tr
->slot
);
838 c
= &ctx
->colors
[tr
->color
];
839 if (!TYPE_IS_FLAT(tr
->type
) && c
->is_argument
)
840 code
= OPCODE_DEREFERENCE_CLEAR
;
842 code
= OPCODE_DEREFERENCE
;
843 code
+= am
* OPCODE_MODE_MULT
;
845 gen_am(am
, tr
->slot
);
853 static bool pcode_copy(struct build_function_context
*ctx
, bool type_cast
, pcode_t res
, pcode_t a1
, bool a1_deref
)
855 const struct pcode_type
*tr
, *t1
;
859 tr
= get_var_type(ctx
, res
);
860 t1
= get_var_type(ctx
, a1
);
862 if (t1
->slot
== tr
->slot
) {
863 ajla_assert(a1_deref
, (file_line
, "pcode_copy(%s): dereference not set", function_name(ctx
)));
865 * If we copy a value to itself, we must clear may_be_borrowed,
866 * otherwise we get failure in start03.ajla and start04.ajla.
868 * (note that pcode_copy is called from pcode_structured_write)
870 * The reason for the crash is that may_be_borrowed is per-variable,
871 * not per-slot flag - if we copy to a different variable occupying
872 * the same slot, we won't see may_be_borrowed anymore.
875 if (t1
->type
->size
== 0) {
877 get_arg_mode(am
, t1
->slot
);
878 code
= OPCODE_TAKE_BORROWED
;
879 code
+= am
* OPCODE_MODE_MULT
;
881 gen_am(am
, t1
->slot
);
887 if ((t1
->type
->size
== 0 && tr
->type
->size
== 0) || type_cast
) {
888 const struct color
*c
= &ctx
->colors
[t1
->color
];
890 get_arg_mode(am
, t1
->slot
);
891 get_arg_mode(am
, tr
->slot
);
893 code
= a1_deref
? OPCODE_BOX_MOVE_CLEAR
: OPCODE_BOX_COPY
;
895 code
= a1_deref
? (c
->is_argument
? OPCODE_REF_MOVE_CLEAR
: OPCODE_REF_MOVE
) : OPCODE_REF_COPY
;
897 code
+= am
* OPCODE_MODE_MULT
;
899 gen_am_two(am
, t1
->slot
, tr
->slot
);
900 } else if (t1
->type
->tag
== TYPE_TAG_flat_record
|| t1
->type
->tag
== TYPE_TAG_flat_array
) {
901 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
));
903 get_arg_mode(am
, t1
->slot
);
904 get_arg_mode(am
, tr
->slot
);
905 code
= a1_deref
? OPCODE_FLAT_MOVE
: OPCODE_FLAT_COPY
;
906 code
+= am
* OPCODE_MODE_MULT
;
908 gen_am_two(am
, t1
->slot
, tr
->slot
);
910 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
));
912 get_arg_mode(am
, t1
->slot
);
913 get_arg_mode(am
, tr
->slot
);
914 code
= get_code(a1_deref
? Op_Mov
: Op_Copy
, t1
->type
);
915 code
+= am
* OPCODE_MODE_MULT
;
917 gen_am_two(am
, t1
->slot
, tr
->slot
);
925 static bool pcode_process_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
, pcode_t
*n_real_arguments
, arg_mode_t
*am
)
928 if (n_real_arguments
)
929 *n_real_arguments
= 0;
930 for (ai
= 0; ai
< n_arguments
; ai
++) {
932 struct pcode_type
*t1
;
934 pcode_get_var_deref(&a1
, &deref
);
935 if (unlikely(var_elided(a1
)))
937 t1
= get_var_type(ctx
, a1
);
938 if (n_real_arguments
) {
939 get_arg_mode(*am
, t1
->slot
);
940 (*n_real_arguments
)++;
941 t1
->is_dereferenced_in_call_argument
= deref
;
945 flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
946 if (!TYPE_IS_FLAT(t1
->type
))
947 flags
|= OPCODE_CALL_MAY_GIVE
;
949 if (!t1
->is_dereferenced_in_call_argument
&& !TYPE_IS_FLAT(t1
->type
))
950 flags
|= OPCODE_CALL_MAY_LEND
;
952 gen_am_two(*am
, t1
->slot
, flags
);
955 if (n_real_arguments
)
956 get_arg_mode(*am
, *n_real_arguments
);
963 static bool pcode_dereference_arguments(struct build_function_context
*ctx
, pcode_t n_arguments
)
966 for (ai
= 0; ai
< n_arguments
; ai
++) {
969 pcode_get_var_deref(&a1
, &deref
);
971 if (unlikely(!pcode_free(ctx
, a1
)))
981 static bool pcode_call(struct build_function_context
*ctx
, pcode_t instr
)
984 arg_mode_t am
= INIT_ARG_MODE
;
987 const struct pcode_type
*tr
= NULL
; /* avoid warning */
988 const struct pcode_type
*ts
= NULL
; /* avoid warning */
989 pcode_t call_mode
= 0; /* avoid warning */
990 pcode_t src_fn
= 0; /* avoid warning */
991 bool src_deref
= false; /* avoid warning */
994 pcode_t n_arguments
, n_real_arguments
;
995 arg_t n_return_values
, n_real_return_values
;
996 size_t fn_idx
= 0; /* avoid warning */
997 pcode_position_save_t saved
;
999 if (instr
== P_Load_Fn
|| instr
== P_Curry
) {
1000 res
= u_pcode_get();
1001 if (unlikely(var_elided(res
))) {
1004 tr
= get_var_type(ctx
, res
);
1005 get_arg_mode(am
, tr
->slot
);
1007 n_return_values
= 0; /* avoid warning */
1008 } else if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1009 call_mode
= u_pcode_get();
1011 n_return_values
= (arg_t
)q
;
1012 if (unlikely(q
!= (pcode_t
)n_return_values
))
1013 goto exception_overflow
;
1015 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1019 n_arguments
= (arg_t
)q
;
1020 if (unlikely(q
!= (pcode_t
)n_arguments
))
1021 goto exception_overflow
;
1022 if (instr
== P_Load_Fn
|| instr
== P_Call
) {
1024 if (instr
== P_Load_Fn
)
1025 u_pcode_get(); /* call mode */
1026 ptr
= pcode_module_load_function(ctx
);
1029 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, true);
1030 if (unlikely(fn_idx
== no_function_idx
))
1032 get_arg_mode(am
, fn_idx
);
1033 src_deref
= false; /* avoid warning */
1034 src_fn
= ~sign_bit(pcode_t
); /* avoid warning */
1036 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1037 pcode_get_var_deref(&src_fn
, &src_deref
);
1040 pcode_position_save(ctx
, &saved
);
1042 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1045 n_real_return_values
= 0;
1046 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1047 for (ai
= 0; ai
< n_return_values
; ai
++) {
1049 if (unlikely(var_elided(q
)))
1051 n_real_return_values
++;
1053 if (!n_real_return_values
)
1055 get_arg_mode(am
, n_return_values
);
1057 pcode_position_restore(ctx
, &saved
);
1059 if (unlikely(elide
)) {
1060 /* TODO: remove the function from local directory if we just added it */
1062 if (unlikely(!pcode_free(ctx
, src_fn
)))
1065 pcode_dereference_arguments(ctx
, n_arguments
);
1070 if (instr
== P_Curry
|| instr
== P_Call_Indirect
) {
1071 ts
= get_var_type(ctx
, src_fn
);
1072 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
));
1073 get_arg_mode(am
, ts
->slot
);
1074 fn_idx
= no_function_idx
; /* avoid warning */
1077 code
= 0; /* avoid warning */
1080 code
= OPCODE_LOAD_FN
;
1083 code
= OPCODE_CURRY
;
1086 switch (call_mode
) {
1087 case Call_Mode_Unspecified
:
1088 case Call_Mode_Normal
:
1091 case Call_Mode_Strict
:
1092 case Call_Mode_Inline
:
1093 code
= OPCODE_CALL_STRICT
;
1095 case Call_Mode_Spark
:
1096 code
= OPCODE_CALL_SPARK
;
1098 case Call_Mode_Lazy
:
1099 code
= OPCODE_CALL_LAZY
;
1101 case Call_Mode_Cache
:
1102 code
= OPCODE_CALL_CACHE
;
1104 case Call_Mode_Save
:
1105 code
= OPCODE_CALL_SAVE
;
1108 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1111 case P_Call_Indirect
:
1112 switch (call_mode
) {
1113 case Call_Mode_Unspecified
:
1114 case Call_Mode_Normal
:
1115 code
= OPCODE_CALL_INDIRECT
;
1117 case Call_Mode_Strict
:
1118 case Call_Mode_Inline
:
1119 code
= OPCODE_CALL_INDIRECT_STRICT
;
1121 case Call_Mode_Spark
:
1122 code
= OPCODE_CALL_INDIRECT_SPARK
;
1124 case Call_Mode_Lazy
:
1125 code
= OPCODE_CALL_INDIRECT_LAZY
;
1127 case Call_Mode_Cache
:
1128 code
= OPCODE_CALL_INDIRECT_CACHE
;
1130 case Call_Mode_Save
:
1131 code
= OPCODE_CALL_INDIRECT_SAVE
;
1134 internal(file_line
, "pcode_call(%s): invalid call mode %ld", function_name(ctx
), (long)call_mode
);
1138 internal(file_line
, "pcode_call(%s): invalid instruction %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
1141 code
+= am
* OPCODE_MODE_MULT
;
1143 if (instr
== P_Load_Fn
|| instr
== P_Curry
)
1144 gen_am_two(am
, n_real_arguments
, tr
->slot
);
1146 gen_am_two(am
, n_real_arguments
, n_real_return_values
);
1147 if (instr
== P_Load_Fn
|| instr
== P_Call
)
1150 gen_am_two(am
, ts
->slot
, src_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1152 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1155 if (instr
== P_Call
|| instr
== P_Call_Indirect
) {
1156 for (ai
= 0; ai
< n_return_values
; ai
++) {
1157 const struct pcode_type
*tv
;
1159 if (unlikely(var_elided(q
)))
1161 tv
= get_var_type(ctx
, q
);
1162 if (ARG_MODE_N
>= 3) {
1163 gen_uint32(tv
->slot
);
1165 gen_code((code_t
)tv
->slot
);
1167 gen_code(TYPE_IS_FLAT(tv
->type
) ? OPCODE_MAY_RETURN_FLAT
: 0);
1170 if (unlikely(!gen_checkpoint(ctx
, ARG_MODE_N
- 1)))
1177 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1182 ctx
->pcode
= ctx
->pcode_instr_end
;
1186 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
)
1189 struct module_designator
*md
= NULL
;
1190 struct function_designator
*fd
= NULL
;
1197 switch (t1
->extra_type
? t1
->extra_type
: tr
->extra_type
) {
1198 case T_SInt128
: module
= "private/long"; fn
= 0 * Op_N
; break;
1199 case T_UInt128
: module
= "private/long"; fn
= 1 * Op_N
; break;
1200 case T_Real16
: module
= "private/longreal"; fn
= 0 * Op_N
; break;
1201 case T_Real32
: module
= "private/longreal"; fn
= 1 * Op_N
; break;
1202 case T_Real64
: module
= "private/longreal"; fn
= 2 * Op_N
; break;
1203 case T_Real80
: module
= "private/longreal"; fn
= 3 * Op_N
; break;
1204 case T_Real128
: module
= "private/longreal"; fn
= 4 * Op_N
; break;
1206 internal(file_line
, "pcode_op_to_call: type %d, %d", t1
->extra_type
, tr
->extra_type
);
1210 md
= module_designator_alloc(0, cast_ptr(const uint8_t *, module
), strlen(module
), false, ctx
->err
);
1213 fd
= function_designator_alloc_single(fn
, ctx
->err
);
1216 ptr
= module_load_function(md
, fd
, false, ctx
->err
);
1219 module_designator_free(md
), md
= NULL
;
1220 function_designator_free(fd
), fd
= NULL
;
1221 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, !preload
);
1222 if (unlikely(fn_idx
== no_function_idx
))
1229 get_arg_mode(am
, fn_idx
);
1230 get_arg_mode(am
, t1
->slot
);
1232 get_arg_mode(am
, t2
->slot
);
1234 code
= OPCODE_CALL
+ am
* OPCODE_MODE_MULT
;
1236 gen_am_two(am
, t2
? 2 : 1, 1);
1238 gen_am_two(am
, t1
->slot
, flags1
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1240 gen_am_two(am
, t2
->slot
, flags2
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
1241 if (ARG_MODE_N
>= 3) {
1242 gen_uint32(tr
->slot
);
1246 gen_code(OPCODE_MAY_RETURN_FLAT
);
1249 if (unlikely(!gen_checkpoint(ctx
, ARG_MODE_N
- 1)))
1256 module_designator_free(md
);
1258 function_designator_free(fd
);
1264 while ((size_t)(pos) >= 8 * *blob_len) \
1265 if (unlikely(!array_add_mayfail(uint8_t, blob, blob_len, 0, NULL, err)))\
1272 (*blob)[(pos) >> 3] |= 1U << ((pos) & 7); \
1275 #define re(n, rtype, ntype, pack, unpack) \
1276 static bool cat(pcode_generate_,rtype)(ntype val, uint8_t **blob, size_t *blob_len, ajla_error_t *err)\
1278 int ex_bits, sig_bits; \
1279 int min_exp, max_exp, e; \
1283 case 0: ex_bits = 5; sig_bits = 11; break; \
1284 case 1: ex_bits = 8; sig_bits = 24; break; \
1285 case 2: ex_bits = 11; sig_bits = 53; break; \
1286 case 3: ex_bits = 15; sig_bits = 64; break; \
1287 case 4: ex_bits = 15; sig_bits = 113; break; \
1288 default: internal(file_line, "invalid real type %d", n);\
1290 min_exp = -(1 << (ex_bits - 1)) - sig_bits + 3; \
1291 max_exp = (1 << (ex_bits - 1)) - sig_bits + 2; \
1292 if (unlikely(cat(isnan_,ntype)(val))) { \
1293 fatal_mayfail(error_ajla(EC_SYNC, AJLA_ERROR_NAN), err, "NaN");\
1296 if (unlikely(val == 0)) { \
1297 if (unlikely(1. / val < 0)) \
1302 if (unlikely(val < 0)) { \
1306 if (unlikely(!cat(isfinite_,ntype)(val))) { \
1311 norm = cat(mathfunc_,ntype)(frexp)(val, &e); \
1313 pos = sig_bits - 1; \
1314 if (e < min_exp) { \
1315 pos -= min_exp - e; \
1318 while (pos >= 0) { \
1328 pos = sig_bits + 1; \
1329 while (e && e != -1) { \
1344 } while (pos & 7); \
1347 for_all_real(re
, for_all_empty
)
1352 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
)
1358 const struct type
*type
;
1360 type
= pcode_to_type(NULL
, pcode_type
, err
);
1361 if (unlikely(!type
))
1364 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &blob_len
, err
)))
1366 #define emit_byte(b) \
1368 if (unlikely(!array_add_mayfail(uint8_t, &blob, &blob_len, b, NULL, err)))\
1372 d
= pointer_get_data(ptr
);
1373 if (likely(da_tag(d
) == DATA_TAG_flat
)) {
1377 switch (type
->tag
) {
1378 #define fx(n, type, utype, sz, bits) \
1379 case TYPE_TAG_integer + n: \
1380 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_signed:\
1381 case TYPE_TAG_fixed + 2 * n + TYPE_TAG_fixed_unsigned:\
1382 negative = *cast_ptr(type *, da_flat(d)) < 0;\
1383 value = *cast_ptr(type *, da_flat(d)); \
1386 #define re(n, rtype, ntype, pack, unpack) \
1387 case TYPE_TAG_real + n: { \
1388 if (unlikely(!cat(pcode_generate_,rtype)(unpack(*cast_ptr(rtype *, da_flat(d))), &blob, &blob_len, err)))\
1390 goto process_real; \
1393 for_all_real(re
, for_all_empty
);
1395 internal(file_line
, "pcode_generate_blob_from_value: invalid type tag %u", type
->tag
);
1402 for (i
= 0; i
< size
; i
++) {
1406 sign
= blob_len
&& blob
[blob_len
- 1] & 0x80;
1407 if (unlikely(sign
!= negative
))
1408 emit_byte(negative
? 0xff : 0x00);
1410 while (blob_len
>= 2 && blob
[blob_len
- 1] == (negative
? 0xff : 0x00) && (blob
[blob_len
- 2] & 0x80) == (negative
? 0x80 : 0x00))
1413 if (blob_len
== 1 && !blob
[0])
1416 } else if (unlikely(da_tag(d
) == DATA_TAG_longint
)) {
1418 if (unlikely(!mpint_export_to_blob(&da(d
,longint
)->mp
, &blob
, &blob_len
, err
)))
1420 } else if (likely(da_tag(d
) == DATA_TAG_option
)) {
1422 ajla_assert_lo(pointer_is_empty(da(d
,option
)->pointer
), (file_line
, "pcode_generate_blob_from_value: non-empty option"));
1423 opt
= da(d
,option
)->option
;
1425 emit_byte(opt
& 0xff);
1426 while ((opt
>>= 8));
1428 internal(file_line
, "pcode_generate_blob_from_value: invalid data tag %u", da_tag(d
));
1434 if (unlikely(!pcode_generate_blob(blob
, blob_len
, res_blob
, res_len
, err
))) {
1446 #define test(bit) ((size_t)(bit) < 8 * dl ? (d[(bit) >> 3] >> ((bit) & 7)) & 1 : dl ? d[dl - 1] >> 7 : 0)
1448 #define re(n, rtype, ntype, pack, unpack) \
1449 static inline rtype cat(strto_,rtype)(const unsigned char *d, size_t dl)\
1451 int ex_bits, sig_bits; \
1457 case 0: ex_bits = 5; sig_bits = 11; break; \
1458 case 1: ex_bits = 8; sig_bits = 24; break; \
1459 case 2: ex_bits = 11; sig_bits = 53; break; \
1460 case 3: ex_bits = 15; sig_bits = 64; break; \
1461 case 4: ex_bits = 15; sig_bits = 113; break; \
1462 default: internal(file_line, "invalid real type %d", n);\
1466 for (i = 0; i < ex_bits + 1; i++) { \
1467 b = test(sig_bits + 1 + i); \
1468 ex |= (int)b << i; \
1473 for (i = 0; i < sig_bits; i++) { \
1475 val += cat(mathfunc_,ntype)(ldexp)(1, ex + i); \
1478 if (test(sig_bits)) \
1482 for_all_real(re
, for_all_empty
)
1485 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
)
1487 switch (type
->tag
) {
1488 #define re(n, rtype, ntype, pack, unpack) \
1489 case TYPE_TAG_real + n: { \
1490 rtype val = cat(strto_,rtype)((const unsigned char *)blob, blob_l);\
1491 *result_len = round_up(sizeof(rtype), sizeof(code_t)) / sizeof(code_t);\
1492 if (unlikely(!(*result = mem_alloc_array_mayfail(mem_calloc_mayfail, code_t *, 0, 0, *result_len, sizeof(code_t), ctx->err))))\
1494 memcpy(*result, &val, sizeof(rtype)); \
1497 for_all_real(re
, for_all_empty
);
1499 internal(file_line
, "pcode_decode_real(%s): invalid type tag %u", function_name(ctx
), type
->tag
);
1509 static bool pcode_generate_constant_from_blob(struct build_function_context
*ctx
, pcode_t res
, uint8_t *blob
, size_t l
)
1511 const struct pcode_type
*pt
;
1512 bool is_emulated_fixed_8
, is_emulated_fixed_16
;
1513 const struct type
*type
;
1515 code_t
*raw_result
= NULL
;
1517 size_t requested_size
;
1524 pt
= get_var_type(ctx
, res
);
1526 is_emulated_fixed_8
= pt
->extra_type
== T_SInt64
|| pt
->extra_type
== T_UInt64
;
1527 is_emulated_fixed_16
= pt
->extra_type
== T_SInt128
|| pt
->extra_type
== T_UInt128
;
1531 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1532 if (TYPE_TAG_FIXED_IS_UNSIGNED(type
->tag
) && l
== (size_t)type
->size
+ 1 && blob
[l
- 1] == 0x00)
1534 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
));
1535 if (l
<= sizeof(code_t
))
1536 requested_size
= sizeof(code_t
);
1538 requested_size
= round_up(type
->size
, sizeof(code_t
));
1539 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1540 if (is_emulated_fixed_8
&& l
&& blob
[l
- 1] & 0x80)
1542 else if (is_emulated_fixed_16
&& l
&& blob
[l
- 1] & 0x80)
1543 requested_size
= 16;
1544 else if (l
<= sizeof(code_t
))
1545 requested_size
= sizeof(code_t
);
1546 else if (l
<= type
->size
)
1547 requested_size
= round_up(type
->size
, sizeof(code_t
));
1549 requested_size
= round_up(l
, sizeof(code_t
));
1550 } else if (TYPE_TAG_IS_REAL(type
->tag
)) {
1551 if (!unlikely(pcode_decode_real(ctx
, type
, cast_ptr(const char *, blob
), l
, &raw_result
, &requested_size
)))
1554 internal(file_line
, "pcode_generate_constant_from_blob(%s): unknown type %u", function_name(ctx
), type
->tag
);
1557 if (likely(!raw_result
)) {
1558 while (l
< requested_size
) {
1559 uint8_t c
= !l
? 0 : !(blob
[l
- 1] & 0x80) ? 0 : 0xff;
1560 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, c
, NULL
, ctx
->err
)))
1565 code
= get_code(Op_Ldc
, type
);
1566 const_swap
= !!CODE_ENDIAN
;
1568 if (TYPE_TAG_IS_FIXED(type
->tag
)) {
1569 if (requested_size
< type
->size
)
1570 code
+= (OPCODE_FIXED_OP_ldc16
- OPCODE_FIXED_OP_ldc
) * OPCODE_FIXED_OP_MULT
;
1571 } else if (TYPE_TAG_IS_INT(type
->tag
)) {
1572 if ((is_emulated_fixed_8
|| is_emulated_fixed_16
) && l
&& blob
[l
- 1] & 0x80) {
1573 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, 0, NULL
, ctx
->err
)))
1575 code
= OPCODE_INT_LDC_LONG
;
1576 } else if (requested_size
< type
->size
) {
1577 code
+= (OPCODE_INT_OP_ldc16
- OPCODE_INT_OP_ldc
) * OPCODE_INT_OP_MULT
;
1578 } else if (requested_size
> type
->size
&& orig_l
> type
->size
) {
1579 code
= OPCODE_INT_LDC_LONG
;
1584 get_arg_mode(am
, pt
->slot
);
1586 gen_code(code
+ am
* OPCODE_MODE_MULT
);
1587 gen_am(am
, pt
->slot
);
1588 if (unlikely(code
== OPCODE_INT_LDC_LONG
)) {
1589 gen_uint32(l
/ sizeof(code_t
));
1590 /*debug("load long constant: %zu (%d)", l, type->tag);*/
1592 if (unlikely(raw_result
!= NULL
)) {
1594 for (idx
= 0; idx
< requested_size
; idx
++)
1595 gen_code(raw_result
[idx
]);
1596 } else for (is
= 0; is
< l
; is
+= sizeof(code_t
)) {
1597 size_t idx
= !const_swap
? is
: l
- sizeof(code_t
) - is
;
1598 gen_code(blob
[idx
] + (blob
[idx
+ 1] << 8));
1601 mem_free(blob
), blob
= NULL
;
1602 if (unlikely(raw_result
!= NULL
))
1603 mem_free(raw_result
);
1611 mem_free(raw_result
);
1615 static bool pcode_generate_constant(struct build_function_context
*ctx
, pcode_t res
, int_default_t val
)
1619 uint_default_t uval
= (uint_default_t
)val
;
1621 if (unlikely(!array_init_mayfail(uint8_t, &blob
, &l
, ctx
->err
)))
1625 if (unlikely(!array_add_mayfail(uint8_t, &blob
, &l
, (uint8_t)uval
, NULL
, ctx
->err
)))
1630 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1633 static bool pcode_generate_option_from_blob(struct build_function_context
*ctx
, const struct pcode_type
*tr
, uint8_t *blob
, size_t l
)
1641 for (i
= 0; i
< l
; i
++) {
1642 ajla_option_t o
= (ajla_option_t
)blob
[i
];
1643 opt
|= o
<< (i
* 8);
1644 if (unlikely(opt
>> (i
* 8) != o
))
1645 goto exception_overflow
;
1649 get_arg_mode(am
, tr
->slot
);
1650 if (likely(opt
== (ajla_option_t
)(ajla_flat_option_t
)opt
) && tr
->type
->tag
== TYPE_TAG_flat_option
) {
1651 code
= OPCODE_OPTION_CREATE_EMPTY_FLAT
;
1653 code
= OPCODE_OPTION_CREATE_EMPTY
;
1655 code
+= am
* OPCODE_MODE_MULT
;
1657 gen_am_two(am
, tr
->slot
, opt
);
1663 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1669 static bool pcode_load_constant(struct build_function_context
*ctx
)
1674 const struct pcode_type
*tr
;
1676 res
= u_pcode_get();
1677 if (unlikely(!pcode_load_blob(ctx
, &blob
, &l
)))
1680 if (var_elided(res
)) {
1685 tr
= get_var_type(ctx
, res
);
1687 if (tr
->type
->tag
== TYPE_TAG_flat_option
|| tr
->type
->tag
== TYPE_TAG_unknown
) {
1688 return pcode_generate_option_from_blob(ctx
, tr
, blob
, l
);
1690 return pcode_generate_constant_from_blob(ctx
, res
, blob
, l
);
1694 static bool pcode_structured_loop(struct build_function_context
*ctx
, pcode_t n_steps
, code_t extra_flags
, arg_mode_t
*am
, bool gen
)
1699 if (i
== n_steps
- 1)
1700 extra_flags
|= OPCODE_STRUCTURED_FLAG_END
;
1704 case Structured_Record
: {
1706 pcode_t rec_local
, q
, type_idx
;
1707 const struct record_definition
*def
;
1710 rec_local
= u_pcode_get();
1714 if (unlikely(q
!= (pcode_t
)idx
))
1715 goto exception_overflow
;
1717 def
= type_def(pcode_to_type(ctx
, rec_local
, NULL
),record
);
1719 if (record_definition_is_elided(def
, idx
)) {
1720 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided record entry in the second pass", function_name(ctx
)));
1724 type_idx
= pcode_to_type_index(ctx
, rec_local
, false);
1725 if (unlikely(type_idx
== error_type_index
))
1728 slot
= record_definition_slot(def
, idx
);
1730 get_arg_mode(*am
, slot
);
1731 get_arg_mode(*am
, type_idx
);
1733 gen_am_two(*am
, OPCODE_STRUCTURED_RECORD
| extra_flags
, slot
);
1734 gen_am(*am
, type_idx
);
1738 case Structured_Option
: {
1743 opt
= (ajla_option_t
)q
;
1744 if (unlikely(q
!= (pcode_t
)opt
))
1745 goto exception_overflow
;
1748 get_arg_mode(*am
, opt
);
1750 gen_am_two(*am
, OPCODE_STRUCTURED_OPTION
| extra_flags
, opt
);
1755 case Structured_Array
: {
1756 pcode_t var
, local_type
, local_idx
;
1757 const struct pcode_type
*var_type
;
1759 var
= u_pcode_get();
1761 local_type
= pcode_get();
1763 if (var_elided(var
)) {
1764 ajla_assert_lo(!gen
, (file_line
, "pcode_structured_loop(%s): elided array index in the second pass", function_name(ctx
)));
1768 var_type
= get_var_type(ctx
, var
);
1769 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
));
1771 local_idx
= pcode_to_type_index(ctx
, local_type
, false);
1772 if (unlikely(local_idx
== error_type_index
))
1776 get_arg_mode(*am
, var_type
->slot
);
1777 get_arg_mode(*am
, local_idx
);
1779 gen_am_two(*am
, OPCODE_STRUCTURED_ARRAY
| extra_flags
, var_type
->slot
);
1780 gen_am(*am
, local_idx
);
1785 internal(file_line
, "pcode_structured_loop(%s): invalid type %"PRIdMAX
"", function_name(ctx
), (uintmax_t)type
);
1787 } while (++i
< n_steps
);
1792 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1797 static bool pcode_structured_write(struct build_function_context
*ctx
)
1799 pcode_t structured
, scalar
, n_steps
;
1801 pcode_t structured_source
= 0; /* avoid warning */
1802 bool structured_source_deref
= false; /* avoid warning */
1803 const struct pcode_type
*structured_type
, *scalar_type
;
1804 code_t extra_flags
= 0;
1805 arg_mode_t am
= INIT_ARG_MODE
;
1807 pcode_position_save_t saved
;
1809 n_steps
= u_pcode_get();
1810 ajla_assert_lo(n_steps
!= 0, (file_line
, "pcode_structured_write(%s): zero n_steps", function_name(ctx
)));
1811 structured
= u_pcode_get();
1812 pcode_get_var_deref(&structured_source
, &structured_source_deref
);
1813 pcode_get_var_deref(&scalar
, &scalar_deref
);
1815 extra_flags
|= OPCODE_STRUCTURED_FREE_VARIABLE
;
1817 pcode_position_save(ctx
, &saved
);
1819 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, false))
1822 if (unlikely(var_elided(structured
)) || unlikely(var_elided(scalar
)))
1825 pcode_position_restore(ctx
, &saved
);
1827 if (!pcode_copy(ctx
, false, structured
, structured_source
, structured_source_deref
))
1830 structured_type
= get_var_type(ctx
, structured
);
1831 scalar_type
= get_var_type(ctx
, scalar
);
1832 get_arg_mode(am
, structured_type
->slot
);
1833 get_arg_mode(am
, scalar_type
->slot
);
1835 gen_code(OPCODE_STRUCTURED
+ am
* OPCODE_MODE_MULT
);
1836 gen_am_two(am
, structured_type
->slot
, scalar_type
->slot
);
1838 if (!pcode_structured_loop(ctx
, n_steps
, extra_flags
, &am
, true))
1847 static bool pcode_record_create(struct build_function_context
*ctx
)
1850 pcode_position_save_t saved
;
1851 pcode_t n_arguments
, n_real_arguments
;
1852 const struct pcode_type
*tr
;
1853 arg_mode_t am
= INIT_ARG_MODE
;
1855 result
= u_pcode_get();
1857 n_arguments
= (arg_t
)q
;
1858 if (unlikely(q
!= (pcode_t
)n_arguments
))
1859 goto exception_overflow
;
1861 pcode_position_save(ctx
, &saved
);
1863 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, &n_real_arguments
, &am
)))
1866 pcode_position_restore(ctx
, &saved
);
1868 if (unlikely(var_elided(result
))) {
1869 pcode_dereference_arguments(ctx
, n_arguments
);
1873 tr
= get_var_type(ctx
, result
);
1874 get_arg_mode(am
, tr
->slot
);
1876 gen_code(OPCODE_RECORD_CREATE
+ am
* OPCODE_MODE_MULT
);
1877 gen_am_two(am
, tr
->slot
, n_real_arguments
);
1879 if (unlikely(!pcode_process_arguments(ctx
, n_arguments
, NULL
, &am
)))
1885 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
1890 static bool pcode_array_create(struct build_function_context
*ctx
)
1892 pcode_t result
, local_type
, length
, n_real_arguments
;
1893 pcode_position_save_t saved
;
1894 const struct pcode_type
*tr
;
1895 arg_mode_t am
= INIT_ARG_MODE
;
1897 result
= u_pcode_get();
1898 local_type
= pcode_get();
1899 length
= u_pcode_get();
1902 pcode_position_save(ctx
, &saved
);
1904 if (unlikely(!pcode_process_arguments(ctx
, length
, &n_real_arguments
, &am
)))
1907 pcode_position_restore(ctx
, &saved
);
1909 if (unlikely(var_elided(result
))) {
1910 pcode_dereference_arguments(ctx
, length
);
1914 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
));
1916 tr
= get_var_type(ctx
, result
);
1917 get_arg_mode(am
, tr
->slot
);
1920 pcode_t type_idx
= pcode_to_type_index(ctx
, local_type
, true);
1921 if (unlikely(type_idx
== error_type_index
))
1923 if (type_idx
== no_type_index
) {
1924 gen_code(OPCODE_ARRAY_CREATE_EMPTY
+ am
* OPCODE_MODE_MULT
);
1925 gen_am(am
, tr
->slot
);
1927 get_arg_mode(am
, type_idx
);
1928 gen_code(OPCODE_ARRAY_CREATE_EMPTY_FLAT
+ am
* OPCODE_MODE_MULT
);
1929 gen_am_two(am
, tr
->slot
, type_idx
);
1932 get_arg_mode(am
, length
);
1933 gen_code(OPCODE_ARRAY_CREATE
+ am
* OPCODE_MODE_MULT
);
1934 gen_am_two(am
, tr
->slot
, length
);
1935 if (unlikely(!pcode_process_arguments(ctx
, length
, NULL
, &am
)))
1945 static bool pcode_array_string(struct build_function_context
*ctx
)
1950 const struct pcode_type
*tr
;
1951 arg_mode_t am
= INIT_ARG_MODE
;
1953 result
= u_pcode_get();
1955 if (!pcode_load_blob(ctx
, &blob
, &blob_len
))
1957 if (likely(var_elided(result
))) {
1962 tr
= get_var_type(ctx
, result
);
1963 get_arg_mode(am
, tr
->slot
);
1964 get_arg_mode(am
, blob_len
);
1965 gen_code(OPCODE_ARRAY_STRING
+ am
* OPCODE_MODE_MULT
);
1966 gen_am_two(am
, tr
->slot
, blob_len
);
1967 for (i
= 0; i
< blob_len
; i
+= 2) {
1973 u
.b
[1] = i
+ 1 < blob_len
? blob
[i
+ 1] : 0;
1985 static bool pcode_array_unicode(struct build_function_context
*ctx
)
1989 const struct pcode_type
*tr
;
1990 arg_mode_t am
= INIT_ARG_MODE
;
1992 result
= u_pcode_get();
1994 len
= ctx
->pcode_instr_end
- ctx
->pcode
;
1996 tr
= get_var_type(ctx
, result
);
1997 get_arg_mode(am
, tr
->slot
);
1998 get_arg_mode(am
, len
);
1999 gen_code(OPCODE_ARRAY_UNICODE
+ am
* OPCODE_MODE_MULT
);
2000 gen_am_two(am
, tr
->slot
, len
);
2001 for (i
= 0; i
< len
; i
++) {
2017 static bool pcode_io(struct build_function_context
*ctx
)
2019 pcode_t io_type
, n_outputs
, n_inputs
, n_params
;
2021 bool elided
= false;
2022 code_position_save_t saved
;
2024 code_position_save(ctx
, &saved
);
2026 io_type
= u_pcode_get();
2027 n_outputs
= u_pcode_get();
2028 n_inputs
= u_pcode_get();
2029 n_params
= u_pcode_get();
2031 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
));
2033 gen_code(OPCODE_IO
);
2034 gen_code(io_type
| (n_outputs
<< 8));
2035 gen_code(n_inputs
| (n_params
<< 8));
2037 for (pass
= 0; pass
< 3; pass
++) {
2039 if (!pass
) val
= n_outputs
;
2040 else if (pass
== 1) val
= n_inputs
;
2041 else val
= n_params
;
2044 pcode_t var
= pcode_get();
2045 if (!pass
&& var_elided(var
))
2049 const struct pcode_type
*t1
;
2050 t1
= get_var_type(ctx
, var
);
2051 gen_uint32(t1
->slot
);
2060 code_position_restore(ctx
, &saved
);
2069 static bool pcode_args(struct build_function_context
*ctx
)
2071 const struct pcode_type
*tr
;
2074 ajla_assert_lo(!ctx
->args
, (file_line
, "pcode_args(%s): args already specified", function_name(ctx
)));
2076 ctx
->args
= mem_alloc_array_mayfail(mem_alloc_mayfail
, struct local_arg
*, 0, 0, ctx
->n_arguments
, sizeof(struct local_arg
), ctx
->err
);
2077 if (unlikely(!ctx
->args
))
2080 for (i
= 0, vv
= 0; i
< ctx
->n_arguments
; i
++) {
2081 pcode_t res
= pcode_get();
2082 if (unlikely(var_elided(res
)))
2084 tr
= get_var_type(ctx
, res
);
2085 ctx
->args
[vv
].slot
= tr
->slot
;
2086 ctx
->args
[vv
].may_be_borrowed
= !TYPE_IS_FLAT(tr
->type
);
2087 ctx
->args
[vv
].may_be_flat
= TYPE_IS_FLAT(tr
->type
);
2088 ctx
->pcode_types
[res
].argument
= &ctx
->args
[vv
];
2089 ctx
->colors
[tr
->color
].is_argument
= true;
2090 if (!TYPE_IS_FLAT(tr
->type
))
2091 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2094 ctx
->n_real_arguments
= vv
;
2100 struct pcode_return_struct
{
2105 static bool pcode_return(struct build_function_context
*ctx
)
2107 arg_mode_t am
= INIT_ARG_MODE
;
2109 struct pcode_return_struct
*prs
;
2111 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
);
2115 for (i
= 0, vv
= 0; i
< ctx
->n_return_values
; i
++) {
2116 const struct pcode_type
*tr
;
2117 pcode_t flags
= u_pcode_get();
2118 pcode_t res
= pcode_get();
2119 prs
[i
].flags
= flags
;
2121 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2123 tr
= get_var_type(ctx
, res
);
2124 get_arg_mode(am
, tr
->slot
);
2128 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
));
2130 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2131 if (unlikely((prs
[i
].flags
& (Flag_Free_Argument
| Flag_Return_Elided
)) == (Flag_Free_Argument
| Flag_Return_Elided
))) {
2133 arg_t q
= (arg_t
)-1;
2134 for (j
= 0; j
< i
; j
++)
2135 if (prs
[j
].res
== prs
[i
].res
&& !(prs
[j
].flags
& Flag_Return_Elided
))
2137 if (q
!= (arg_t
)-1) {
2138 prs
[q
].flags
|= Flag_Free_Argument
;
2140 if (!pcode_free(ctx
, prs
[i
].res
))
2143 prs
[i
].flags
&= ~Flag_Free_Argument
;
2147 gen_code(OPCODE_RETURN
+ am
* OPCODE_MODE_MULT
);
2149 for (i
= 0; i
< ctx
->n_return_values
; i
++) {
2150 unsigned code_flags
;
2151 const struct pcode_type
*tr
;
2152 pcode_t flags
= prs
[i
].flags
;
2153 pcode_t res
= prs
[i
].res
;
2154 if (unlikely((flags
& Flag_Return_Elided
) != 0))
2156 tr
= get_var_type(ctx
, res
);
2158 if (flags
& Flag_Free_Argument
)
2159 code_flags
|= OPCODE_FLAG_FREE_ARGUMENT
;
2160 gen_am_two(am
, tr
->slot
, code_flags
);
2172 static void pcode_get_instr(struct build_function_context
*ctx
, pcode_t
*instr
, pcode_t
*instr_params
)
2174 *instr
= u_pcode_get();
2175 *instr_params
= u_pcode_get();
2176 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
)));
2177 ctx
->pcode_instr_end
= ctx
->pcode
+ *instr_params
;
2181 static bool pcode_preload_ld(struct build_function_context
*ctx
)
2183 pcode_position_save_t saved
;
2185 pcode_position_save(ctx
, &saved
);
2186 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2187 pcode_t instr
, instr_params
;
2188 pcode_get_instr(ctx
, &instr
, &instr_params
);
2191 if (unlikely(!pcode_args(ctx
)))
2194 #if NEED_OP_EMULATION
2197 const struct pcode_type
*tr
, *t1
;
2198 pcode_t op
= u_pcode_get();
2199 pcode_t res
= u_pcode_get();
2200 pcode_t flags1
= u_pcode_get();
2201 pcode_t a1
= pcode_get();
2202 if (unlikely(var_elided(res
)))
2204 tr
= get_var_type(ctx
, res
);
2205 t1
= get_var_type(ctx
, a1
);
2206 if (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
)) {
2207 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, true)))
2218 ptr
= pcode_module_load_function(ctx
);
2221 fn_idx
= pcode_module_load_function_idx(ctx
, ptr
, false);
2222 if (unlikely(fn_idx
== no_function_idx
))
2227 ctx
->pcode
= ctx
->pcode_instr_end
;
2229 pcode_position_restore(ctx
, &saved
);
2237 static bool pcode_generate_instructions(struct build_function_context
*ctx
)
2239 if (unlikely(!gen_checkpoint(ctx
, INIT_ARG_MODE
)))
2242 while (ctx
->pcode
!= ctx
->pcode_limit
) {
2243 pcode_t instr
, instr_params
;
2244 pcode_get_instr(ctx
, &instr
, &instr_params
);
2246 pcode_t p
, op
, res
, a1
, a2
, aa
, flags
, flags1
, flags2
;
2247 const struct pcode_type
*tr
, *t1
, *t2
, *ta
;
2248 bool a1_deref
, a2_deref
;
2251 struct line_position lp
;
2252 struct record_definition
*def
;
2256 ajla_assert_lo(op
>= Op_N
|| Op_IsBinary(op
), (file_line
, "P_BinaryOp(%s): invalid binary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2257 res
= u_pcode_get();
2258 flags1
= u_pcode_get();
2260 flags2
= u_pcode_get();
2262 if (unlikely(var_elided(res
))) {
2263 if (flags1
& Flag_Free_Argument
)
2264 pcode_free(ctx
, a1
);
2265 if (flags2
& Flag_Free_Argument
)
2266 pcode_free(ctx
, a2
);
2269 tr
= get_var_type(ctx
, res
);
2270 t1
= get_var_type(ctx
, a1
);
2271 t2
= get_var_type(ctx
, a2
);
2272 ajla_assert_lo(op
>= Op_N
||
2273 (type_is_equal(t1
->type
, t2
->type
) &&
2274 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2275 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2276 : 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
));
2277 if (NEED_OP_EMULATION
&& unlikely(t1
->extra_type
)) {
2278 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, t2
, flags2
, false)))
2283 get_arg_mode(am
, t1
->slot
);
2284 get_arg_mode(am
, t2
->slot
);
2285 get_arg_mode(am
, tr
->slot
);
2286 code
= (code_t
)((likely(op
< Op_N
) ? get_code(op
, t1
->type
) : (code_t
)(op
- Op_N
)) + am
* OPCODE_MODE_MULT
);
2288 gen_am_two(am
, t1
->slot
, t2
->slot
);
2289 gen_am_two(am
, tr
->slot
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2290 if (flags1
& Flag_Free_Argument
) {
2291 if (t1
->slot
!= tr
->slot
)
2292 pcode_free(ctx
, a1
);
2294 if (flags2
& Flag_Free_Argument
) {
2295 if (t2
->slot
!= tr
->slot
)
2296 pcode_free(ctx
, a2
);
2301 ajla_assert_lo(op
>= Op_N
|| Op_IsUnary(op
), (file_line
, "P_UnaryOp(%s): invalid unary op %"PRIdMAX
"", function_name(ctx
), (intmax_t)op
));
2302 res
= u_pcode_get();
2303 flags1
= u_pcode_get();
2305 if (unlikely(var_elided(res
))) {
2306 if (flags1
& Flag_Free_Argument
)
2307 pcode_free(ctx
, a1
);
2310 tr
= get_var_type(ctx
, res
);
2311 t1
= get_var_type(ctx
, a1
);
2312 ajla_assert_lo(op
>= Op_N
|| op
== Un_ConvertFromInt
||
2313 type_is_equal(tr
->type
, (Op_IsBool(op
) ? type_get_flat_option()
2314 : Op_IsInt(op
) ? type_get_int(INT_DEFAULT_N
)
2315 : 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
));
2316 if (NEED_OP_EMULATION
&& (unlikely(t1
->extra_type
) || unlikely(tr
->extra_type
))) {
2317 if (unlikely(!pcode_op_to_call(ctx
, op
, tr
, t1
, flags1
, NULL
, 0, false)))
2322 get_arg_mode(am
, t1
->slot
);
2323 get_arg_mode(am
, tr
->slot
);
2324 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
);
2326 gen_am_two(am
, t1
->slot
, tr
->slot
);
2327 gen_am(am
, flags1
& Flag_Op_Strict
? OPCODE_OP_FLAG_STRICT
: 0);
2328 if (flags1
& Flag_Free_Argument
) {
2329 if (t1
->slot
!= tr
->slot
)
2330 pcode_free(ctx
, a1
);
2334 case P_Copy_Type_Cast
:
2335 res
= u_pcode_get();
2336 pcode_get_var_deref(&a1
, &a1_deref
);
2337 if (unlikely(var_elided(res
))) {
2339 if (unlikely(!pcode_free(ctx
, a1
)))
2344 if (unlikely(!pcode_copy(ctx
, instr
!= P_Copy
, res
, a1
, a1_deref
)))
2348 res
= u_pcode_get();
2349 if (unlikely(!pcode_free(ctx
, res
)))
2354 if (unlikely(var_elided(a1
)))
2356 t1
= get_var_type(ctx
, a1
);
2358 get_arg_mode(am
, t1
->slot
);
2360 code
+= am
* OPCODE_MODE_MULT
;
2362 gen_am(am
, t1
->slot
);
2368 res
= u_pcode_get();
2369 ajla_assert_lo(var_elided(res
), (file_line
, "P_Fn(%s): Fn result is not elided", function_name(ctx
)));
2372 for (p
= 0; p
< a1
; p
++)
2374 for (p
= 0; p
< a2
; p
++)
2377 case P_Load_Local_Type
:
2378 res
= u_pcode_get();
2379 ajla_assert_lo(var_elided(res
), (file_line
, "P_Load_Local_Type(%s): Load_Local_Type result is not elided", function_name(ctx
)));
2385 case P_Call_Indirect
:
2387 if (unlikely(!pcode_call(ctx
, instr
)))
2391 if (unlikely(!pcode_load_constant(ctx
)))
2394 case P_Structured_Write
:
2395 if (unlikely(!pcode_structured_write(ctx
)))
2400 for (p
= 0; p
< instr_params
; p
++)
2403 case P_Record_Create
:
2404 if (unlikely(!pcode_record_create(ctx
)))
2407 case P_Record_Load_Slot
:
2408 res
= u_pcode_get();
2411 tr
= get_var_type(ctx
, res
);
2412 t1
= get_var_type(ctx
, a1
);
2414 get_arg_mode(am
, tr
->slot
);
2415 get_arg_mode(am
, t1
->slot
);
2416 get_arg_mode(am
, op
);
2417 code
= OPCODE_RECORD_LOAD
;
2418 code
+= am
* OPCODE_MODE_MULT
;
2420 gen_am_two(am
, t1
->slot
, op
);
2421 gen_am_two(am
, tr
->slot
, OPCODE_OP_FLAG_STRICT
);
2424 res
= u_pcode_get();
2425 flags
= u_pcode_get();
2428 if (unlikely(var_elided(res
)))
2430 tr
= get_var_type(ctx
, res
);
2431 t1
= get_var_type(ctx
, a1
);
2432 if (TYPE_IS_FLAT(tr
->type
))
2433 flags
&= ~Flag_Borrow
;
2434 if (t1
->type
->tag
== TYPE_TAG_flat_record
) {
2435 def
= type_def(type_def(t1
->type
,flat_record
)->base
,record
);
2437 def
= type_def(t1
->type
,record
);
2439 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
));
2440 op
= record_definition_slot(def
, op
);
2442 get_arg_mode(am
, tr
->slot
);
2443 get_arg_mode(am
, t1
->slot
);
2444 get_arg_mode(am
, op
);
2445 code
= OPCODE_RECORD_LOAD
;
2446 code
+= am
* OPCODE_MODE_MULT
;
2448 gen_am_two(am
, t1
->slot
, op
);
2449 gen_am_two(am
, tr
->slot
,
2450 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2451 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2452 if (flags
& Flag_Borrow
)
2453 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2456 res
= u_pcode_get();
2457 flags
= u_pcode_get();
2460 if (unlikely(var_elided(res
)))
2462 tr
= get_var_type(ctx
, res
);
2463 t1
= get_var_type(ctx
, a1
);
2464 if (TYPE_IS_FLAT(tr
->type
))
2465 flags
&= ~Flag_Borrow
;
2467 get_arg_mode(am
, tr
->slot
);
2468 get_arg_mode(am
, t1
->slot
);
2469 get_arg_mode(am
, op
);
2470 code
= OPCODE_OPTION_LOAD
;
2471 code
+= am
* OPCODE_MODE_MULT
;
2473 gen_am_two(am
, t1
->slot
, op
);
2474 gen_am_two(am
, tr
->slot
,
2475 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2476 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0));
2477 if (flags
& Flag_Borrow
)
2478 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2480 case P_Option_Create
:
2481 res
= u_pcode_get();
2483 pcode_get_var_deref(&a1
, &a1_deref
);
2484 if (unlikely(var_elided(res
))) {
2486 if (unlikely(!pcode_free(ctx
, a1
)))
2491 tr
= get_var_type(ctx
, res
);
2492 t1
= get_var_type(ctx
, a1
);
2493 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
));
2495 get_arg_mode(am
, tr
->slot
);
2496 get_arg_mode(am
, t1
->slot
);
2497 get_arg_mode(am
, op
);
2498 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2499 goto exception_overflow
;
2500 code
= OPCODE_OPTION_CREATE
;
2501 code
+= am
* OPCODE_MODE_MULT
;
2503 gen_am_two(am
, tr
->slot
, op
);
2504 gen_am_two(am
, t1
->slot
, a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0);
2507 res
= u_pcode_get();
2510 if (unlikely(var_elided(res
)))
2512 tr
= get_var_type(ctx
, res
);
2513 t1
= get_var_type(ctx
, a1
);
2514 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
));
2516 get_arg_mode(am
, tr
->slot
);
2517 get_arg_mode(am
, t1
->slot
);
2518 get_arg_mode(am
, op
);
2519 if (unlikely(op
!= (pcode_t
)(ajla_option_t
)op
))
2520 goto exception_overflow
;
2521 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2522 code
= OPCODE_OPTION_TEST_FLAT
;
2524 code
= OPCODE_OPTION_TEST
;
2525 code
+= am
* OPCODE_MODE_MULT
;
2527 gen_am_two(am
, t1
->slot
, op
);
2528 gen_am(am
, tr
->slot
);
2531 res
= u_pcode_get();
2533 if (unlikely(var_elided(res
)))
2535 tr
= get_var_type(ctx
, res
);
2536 t1
= get_var_type(ctx
, a1
);
2537 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
));
2539 get_arg_mode(am
, tr
->slot
);
2540 get_arg_mode(am
, t1
->slot
);
2541 if (t1
->type
->tag
== TYPE_TAG_flat_option
)
2542 code
= OPCODE_OPTION_ORD_FLAT
;
2544 code
= OPCODE_OPTION_ORD
;
2545 code
+= am
* OPCODE_MODE_MULT
;
2547 gen_am_two(am
, t1
->slot
, tr
->slot
);
2549 case P_Array_Flexible
:
2551 res
= u_pcode_get();
2552 ajla_assert_lo(var_elided(res
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible result is not elided", function_name(ctx
)));
2554 ajla_assert_lo(var_elided(a1
), (file_line
, "P_Array_Flexible(%s): P_Array_Flexible argument is not elided", function_name(ctx
)));
2555 if (instr
== P_Array_Fixed
)
2558 case P_Array_Create
:
2559 if (unlikely(!pcode_array_create(ctx
)))
2563 res
= u_pcode_get();
2564 pcode_get(); /* local type */
2566 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
));
2569 if (unlikely(var_elided(res
)))
2571 tr
= get_var_type(ctx
, res
);
2572 t1
= get_var_type(ctx
, a1
);
2573 t2
= get_var_type(ctx
, a2
);
2574 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
));
2576 get_arg_mode(am
, t1
->slot
);
2577 get_arg_mode(am
, t2
->slot
);
2578 get_arg_mode(am
, tr
->slot
);
2579 gen_code(OPCODE_ARRAY_FILL
+ am
* OPCODE_MODE_MULT
);
2580 gen_am_two(am
, t1
->slot
,
2581 ((op
& Flag_Free_Argument
) ? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2582 ((op
& Flag_Array_Fill_Sparse
) ? OPCODE_ARRAY_FILL_FLAG_SPARSE
: 0)
2584 gen_am_two(am
, t2
->slot
, tr
->slot
);
2586 case P_Array_String
:
2587 if (unlikely(!pcode_array_string(ctx
)))
2590 case P_Array_Unicode
:
2591 if (unlikely(!pcode_array_unicode(ctx
)))
2595 res
= u_pcode_get();
2596 flags
= u_pcode_get();
2599 if (unlikely(var_elided(res
)))
2601 tr
= get_var_type(ctx
, res
);
2602 t1
= get_var_type(ctx
, a1
);
2603 t2
= get_var_type(ctx
, a2
);
2604 if (TYPE_IS_FLAT(tr
->type
))
2605 flags
&= ~Flag_Borrow
;
2607 get_arg_mode(am
, tr
->slot
);
2608 get_arg_mode(am
, t1
->slot
);
2609 get_arg_mode(am
, t2
->slot
);
2610 code
= OPCODE_ARRAY_LOAD
;
2611 code
+= am
* OPCODE_MODE_MULT
;
2613 gen_am_two(am
, t1
->slot
, t2
->slot
);
2614 gen_am_two(am
, tr
->slot
,
2615 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0) |
2616 (flags
& Flag_Borrow
? OPCODE_STRUCT_MAY_BORROW
: 0) |
2617 (flags
& Flag_Index_In_Range
? OPCODE_ARRAY_INDEX_IN_RANGE
: 0));
2618 if (flags
& Flag_Borrow
)
2619 ctx
->local_variables_flags
[tr
->slot
].may_be_borrowed
= true;
2622 res
= u_pcode_get();
2624 flags
= u_pcode_get();
2625 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2626 if (unlikely(var_elided(res
)))
2628 tr
= get_var_type(ctx
, res
);
2629 t1
= get_var_type(ctx
, a1
);
2630 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
));
2631 if (TYPE_IS_FLAT(t1
->type
)) {
2632 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
));
2633 if (unlikely(!pcode_generate_constant(ctx
, res
, (int_default_t
)type_def(t1
->type
,flat_array
)->n_elements
)))
2636 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
));
2638 get_arg_mode(am
, t1
->slot
);
2639 get_arg_mode(am
, tr
->slot
);
2640 gen_code(OPCODE_ARRAY_LEN
+ am
* OPCODE_MODE_MULT
);
2641 gen_am_two(am
, t1
->slot
, tr
->slot
);
2642 gen_am(am
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2645 case P_Array_Len_Greater_Than
:
2646 res
= u_pcode_get();
2649 flags
= u_pcode_get();
2650 ajla_assert_lo(!(flags
& ~Flag_Evaluate
), (file_line
, "P_Array_Len_Greater_Than(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2651 if (unlikely(var_elided(res
)))
2653 tr
= get_var_type(ctx
, res
);
2654 t1
= get_var_type(ctx
, a1
);
2655 t2
= get_var_type(ctx
, a2
);
2656 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
));
2657 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
));
2660 get_arg_mode(am
, t1
->slot
);
2661 get_arg_mode(am
, t2
->slot
);
2662 get_arg_mode(am
, tr
->slot
);
2663 gen_code(OPCODE_ARRAY_LEN_GREATER_THAN
+ am
* OPCODE_MODE_MULT
);
2664 gen_am_two(am
, t1
->slot
, t2
->slot
);
2665 gen_am_two(am
, tr
->slot
, flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0);
2668 res
= u_pcode_get();
2669 flags
= u_pcode_get();
2673 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Sub(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2674 if (unlikely(var_elided(res
)))
2676 tr
= get_var_type(ctx
, res
);
2677 ta
= get_var_type(ctx
, aa
);
2678 t1
= get_var_type(ctx
, a1
);
2679 t2
= get_var_type(ctx
, a2
);
2680 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
));
2681 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
));
2684 get_arg_mode(am
, ta
->slot
);
2685 get_arg_mode(am
, t1
->slot
);
2686 get_arg_mode(am
, t2
->slot
);
2687 get_arg_mode(am
, tr
->slot
);
2688 gen_code(OPCODE_ARRAY_SUB
+ am
* OPCODE_MODE_MULT
);
2689 gen_am_two(am
, ta
->slot
, t1
->slot
);
2690 gen_am_two(am
, t2
->slot
, tr
->slot
);
2692 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2693 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2697 res
= u_pcode_get();
2698 flags
= u_pcode_get();
2701 ajla_assert_lo(!(flags
& ~(Flag_Free_Argument
| Flag_Evaluate
)), (file_line
, "P_Array_Skip(%s): invalid flags %"PRIuMAX
"", function_name(ctx
), (uintmax_t)flags
));
2702 if (unlikely(var_elided(res
)))
2704 tr
= get_var_type(ctx
, res
);
2705 ta
= get_var_type(ctx
, aa
);
2706 t1
= get_var_type(ctx
, a1
);
2707 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
));
2710 get_arg_mode(am
, ta
->slot
);
2711 get_arg_mode(am
, t1
->slot
);
2712 get_arg_mode(am
, tr
->slot
);
2713 gen_code(OPCODE_ARRAY_SKIP
+ am
* OPCODE_MODE_MULT
);
2714 gen_am_two(am
, ta
->slot
, t1
->slot
);
2715 gen_am_two(am
, tr
->slot
,
2716 (flags
& Flag_Free_Argument
? OPCODE_FLAG_FREE_ARGUMENT
: 0) |
2717 (flags
& Flag_Evaluate
? OPCODE_OP_FLAG_STRICT
: 0)
2720 case P_Array_Append
:
2721 case P_Array_Append_One
:
2722 res
= u_pcode_get();
2723 pcode_get_var_deref(&a1
, &a1_deref
);
2724 pcode_get_var_deref(&a2
, &a2_deref
);
2725 if (unlikely(var_elided(res
)))
2727 tr
= get_var_type(ctx
, res
);
2728 t1
= get_var_type(ctx
, a1
);
2729 t2
= get_var_type(ctx
, a2
);
2731 get_arg_mode(am
, tr
->slot
);
2732 get_arg_mode(am
, t1
->slot
);
2733 get_arg_mode(am
, t2
->slot
);
2734 if (instr
== P_Array_Append
) {
2735 gen_code(OPCODE_ARRAY_APPEND
+ am
* OPCODE_MODE_MULT
);
2737 if (TYPE_IS_FLAT(t2
->type
)) {
2738 gen_code(OPCODE_ARRAY_APPEND_ONE_FLAT
+ am
* OPCODE_MODE_MULT
);
2740 gen_code(OPCODE_ARRAY_APPEND_ONE
+ am
* OPCODE_MODE_MULT
);
2743 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0) | (a2_deref
? OPCODE_FLAG_FREE_ARGUMENT_2
: 0));
2744 gen_am_two(am
, t1
->slot
, t2
->slot
);
2746 case P_Array_Flatten
:
2747 res
= u_pcode_get();
2748 pcode_get_var_deref(&a1
, &a1_deref
);
2749 if (unlikely(var_elided(res
)))
2751 tr
= get_var_type(ctx
, res
);
2752 t1
= get_var_type(ctx
, a1
);
2754 get_arg_mode(am
, tr
->slot
);
2755 get_arg_mode(am
, t1
->slot
);
2756 gen_code(OPCODE_ARRAY_FLATTEN
+ am
* OPCODE_MODE_MULT
);
2757 gen_am_two(am
, tr
->slot
, (a1_deref
? OPCODE_FLAG_FREE_ARGUMENT
: 0));
2758 gen_am(am
, t1
->slot
);
2761 res
= u_pcode_get();
2762 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Jmp(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2764 if (ctx
->labels
[res
] != no_label
) {
2766 if (unlikely(!gen_checkpoint(ctx
, INIT_ARG_MODE
)))
2768 target
= (uint32_t)((ctx
->code_len
- ctx
->labels
[res
]) * sizeof(code_t
));
2769 if (likely(target
< 0x10000)) {
2770 gen_code(OPCODE_JMP_BACK_16
);
2771 gen_code((code_t
)target
);
2776 if (ctx
->labels
[res
] != no_label
)
2777 if (unlikely(!gen_checkpoint(ctx
, INIT_ARG_MODE
)))
2779 gen_code(OPCODE_JMP
);
2780 gen_relative_jump(res
, SIZEOF_IP_T
);
2784 tr
= get_var_type(ctx
, res
);
2785 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
));
2790 if (ctx
->labels
[a1
] != no_label
|| ctx
->labels
[a2
] != no_label
)
2791 if (unlikely(!gen_checkpoint(ctx
, INIT_ARG_MODE
)))
2795 get_arg_mode(am
, tr
->slot
);
2796 code
= OPCODE_JMP_FALSE
+ am
* OPCODE_MODE_MULT
;
2798 gen_am(am
, tr
->slot
);
2799 gen_relative_jump(a1
, SIZEOF_IP_T
* 2);
2800 gen_relative_jump(a2
, SIZEOF_IP_T
);
2803 gen_code(OPCODE_LABEL
);
2804 res
= u_pcode_get();
2805 ajla_assert_lo(res
< ctx
->n_labels
, (file_line
, "P_Label(%s): invalid label %"PRIdMAX
"", function_name(ctx
), (intmax_t)res
));
2806 ajla_assert_lo(ctx
->labels
[res
] == no_label
, (file_line
, "P_Label(%s): label %"PRIdMAX
" already defined", function_name(ctx
), (intmax_t)res
));
2807 ctx
->labels
[res
] = ctx
->code_len
;
2810 if (unlikely(!pcode_io(ctx
)))
2814 ctx
->pcode
= ctx
->pcode_instr_end
;
2817 for (p
= 0; p
< instr_params
; p
++)
2821 if (unlikely(!pcode_return(ctx
)))
2825 lp
.line
= u_pcode_get();
2826 lp
.ip
= ctx
->code_len
;
2827 if (unlikely(!array_add_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, lp
, NULL
, ctx
->err
)))
2831 internal(file_line
, "pcode_generate_instructions(%s): invalid pcode %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr
);
2834 if (unlikely(ctx
->pcode
!= ctx
->pcode_instr_end
)) {
2839 for (pp
= ctx
->pcode_instr_end
- instr_params
- 2; pp
< ctx
->pcode
; pp
++) {
2840 str_add_char(&s
, &l
, ' ');
2841 str_add_signed(&s
, &l
, *pp
, 10);
2844 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
);
2847 if (unlikely(ctx
->code_len
> sign_bit(ip_t
) / sizeof(code_t
) + uzero
))
2848 goto exception_overflow
;
2852 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
2857 static bool pcode_generate_record(struct build_function_context
*ctx
)
2861 struct record_definition
*def
;
2862 if (unlikely(!array_init_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, ctx
->err
)))
2865 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, slot_size
, data_record_offset
, ctx
->err
);
2866 if (unlikely(!ctx
->layout
))
2869 for (; ctx
->pcode
!= ctx
->pcode_limit
; ctx
->pcode
= ctx
->pcode_instr_end
) {
2870 pcode_t instr
, instr_params
;
2871 pcode_get_instr(ctx
, &instr
, &instr_params
);
2873 if (instr
== P_Load_Local_Type
) {
2874 pcode_t var
, fn_var
;
2875 pcode_t attr_unused idx
;
2876 const struct pcode_type
*p
;
2877 const struct type
*t
;
2879 ajla_assert_lo(instr_params
== 3, (file_line
, "pcode_generate_record(%s): invalid number of parameters %"PRIdMAX
"", function_name(ctx
), (intmax_t)instr_params
));
2881 var
= u_pcode_get();
2882 fn_var
= pcode_get();
2883 idx
= u_pcode_get();
2884 if (unlikely(fn_var
!= -1))
2886 if (unlikely(var
!= (pcode_t
)(frame_t
)var
))
2887 goto exception_overflow
;
2888 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
));
2890 if (unlikely(!array_add_mayfail(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
, var
, NULL
, ctx
->err
)))
2893 if (var_elided(var
))
2896 p
= get_var_type(ctx
, var
);
2899 if (unlikely(!layout_add(ctx
->layout
, maximum(t
->size
, 1), t
->align
, ctx
->err
)))
2904 array_finish(frame_t
, &ctx
->record_entries
, &ctx
->record_entries_len
);
2906 if (unlikely(ctx
->record_entries_len
!= (size_t)(arg_t
)ctx
->record_entries_len
))
2907 goto exception_overflow
;
2909 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
2913 def
= type_alloc_record_definition(layout_size(ctx
->layout
), ctx
->err
);
2916 def
->n_slots
= layout_size(ctx
->layout
);
2917 def
->alignment
= maximum(layout_alignment(ctx
->layout
), frame_align
);
2918 def
->n_entries
= (arg_t
)ctx
->record_entries_len
;
2921 for (ai
= 0; ai
< ctx
->record_entries_len
; ai
++) {
2923 const struct pcode_type
*te
;
2924 var
= ctx
->record_entries
[ai
];
2925 if (var_elided((pcode_t
)var
)) {
2926 ctx
->record_entries
[ai
] = NO_FRAME_T
;
2929 slot
= layout_get(ctx
->layout
, layout_idx
++);
2930 ctx
->record_entries
[ai
] = slot
;
2931 te
= get_var_type(ctx
, (pcode_t
)var
);
2932 def
->types
[slot
] = te
->type
;
2935 def
->idx_to_frame
= ctx
->record_entries
, ctx
->record_entries
= NULL
;
2936 ctx
->record_definition
= def
;
2938 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
2943 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
2949 * pointer_empty -> ret_ex
2950 * poitner_mark -> err
2951 * other -> thunk(error) or data(function)
2953 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
)
2956 pcode_t p
, q
, subfns
;
2960 struct data
*ft
, *fn
;
2961 struct function_descriptor
*sfd
;
2964 #if defined(HAVE_CODEGEN)
2965 union internal_arg ia
[1];
2968 struct build_function_context ctx_
;
2969 struct build_function_context
*ctx
= &ctx_
;
2974 ctx
->pcode_limit
= pcode
+ size
;
2977 q
= u_pcode_get() & Fn_Mask
;
2978 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
));
2979 ctx
->function_type
= q
;
2981 u_pcode_get(); /* call mode - used by the optimizer */
2983 subfns
= u_pcode_get();
2985 ctx
->n_local_types
= u_pcode_get();
2988 ctx
->n_local_variables
= (frame_t
)q
;
2989 if (unlikely(q
!= (pcode_t
)ctx
->n_local_variables
))
2990 goto exception_overflow
;
2993 ctx
->n_arguments
= (arg_t
)q
;
2994 ajla_assert_lo(q
== (pcode_t
)ctx
->n_arguments
, (file_line
, "pcode_build_function_core: overflow in n_arguments"));
2997 ctx
->n_return_values
= (arg_t
)q
;
2998 ajla_assert_lo(q
== (pcode_t
)ctx
->n_return_values
, (file_line
, "pcode_build_function_core: overflow in n_return_values"));
3000 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"));
3003 ctx
->n_real_return_values
= (arg_t
)q
;
3004 ajla_assert_lo(ctx
->n_real_return_values
<= ctx
->n_return_values
, (file_line
, "pcode_build_function_core: invalid n_real_return_values"));
3006 ctx
->n_labels
= u_pcode_get();
3008 if (unlikely(!pcode_load_blob(ctx
, &ctx
->function_name
, &is
)))
3010 if (unlikely(!array_add_mayfail(uint8_t, &ctx
->function_name
, &is
, 0, NULL
, ctx
->err
)))
3012 array_finish(uint8_t, &ctx
->function_name
, &is
);
3020 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
);
3021 if (unlikely(!ctx
->local_types
))
3024 for (p
= 0; p
< ctx
->n_local_types
; p
++) {
3026 struct data
*rec_fn
;
3027 const struct record_definition
*def
;
3028 pcode_t base_idx
, n_elements
;
3029 struct type_entry
*flat_rec
;
3031 const struct type
*tt
, *tp
;
3035 case Local_Type_Record
:
3036 ptr
= pcode_module_load_function(ctx
);
3039 pointer_follow(ptr
, false, rec_fn
, PF_WAIT
, fp
, ip
,
3041 ctx
->ret_val
= pointer_empty();
3043 thunk_reference(thunk_
);
3044 ctx
->ret_val
= pointer_thunk(thunk_
);
3047 ajla_assert_lo(da(rec_fn
,function
)->record_definition
!= NULL
, (file_line
, "pcode_build_function_core(%s): record has no definition", function_name(ctx
)));
3048 def
= type_def(da(rec_fn
,function
)->record_definition
,record
);
3051 case Local_Type_Flat_Record
:
3052 base_idx
= u_pcode_get();
3053 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
));
3054 n_elements
= u_pcode_get();
3055 def
= type_def(ctx
->local_types
[base_idx
].type
,record
);
3056 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
));
3057 flat_rec
= type_prepare_flat_record(&def
->type
, ctx
->err
);
3058 if (unlikely(!flat_rec
))
3059 goto record_not_flattened
;
3060 for (ai
= 0; ai
< def
->n_entries
; ai
++) {
3061 pcode_t typ
= pcode_get();
3062 tp
= pcode_to_type(ctx
, typ
, NULL
);
3063 if (unlikely(!TYPE_IS_FLAT(tp
))) {
3064 type_free_flat_record(flat_rec
);
3065 goto record_not_flattened
;
3067 type_set_flat_record_entry(flat_rec
, ai
, tp
);
3069 tt
= type_get_flat_record(flat_rec
, ctx
->err
);
3071 goto record_not_flattened
;
3073 record_not_flattened
:
3076 case Local_Type_Flat_Array
:
3077 base_idx
= pcode_get();
3078 n_elements
= pcode_get();
3079 tp
= pcode_to_type(ctx
, base_idx
, NULL
);
3080 if (unlikely(!TYPE_IS_FLAT(tp
)))
3081 goto array_not_flattened
;
3082 if (unlikely(n_elements
> signed_maximum(int_default_t
) + zero
))
3083 goto array_not_flattened
;
3084 tt
= type_get_flat_array(tp
, n_elements
, ctx
->err
);
3086 goto array_not_flattened
;
3088 array_not_flattened
:
3089 tt
= type_get_unknown();
3092 internal(file_line
, "pcode_build_function_core(%s): invalid local type %"PRIdMAX
"", function_name(ctx
), (intmax_t)q
);
3094 ctx
->local_types
[p
].type
= tt
;
3095 ctx
->local_types
[p
].type_index
= no_type_index
;
3098 ctx
->layout
= layout_start(slot_bits
, frame_flags_per_slot_bits
, frame_align
, frame_offset
, ctx
->err
);
3099 if (unlikely(!ctx
->layout
))
3102 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
);
3103 if (unlikely(!ctx
->pcode_types
))
3106 if (unlikely(!array_init_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, ctx
->err
)))
3109 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3110 struct pcode_type
*pt
;
3115 color
= pcode_get();
3116 pcode_load_blob(ctx
, NULL
, NULL
);
3117 pt
= &ctx
->pcode_types
[v
];
3118 pt
->argument
= NULL
;
3124 const struct type
*t
= pcode_to_type(ctx
, typ
, NULL
);
3125 struct color empty_color
= { 0, 0, false };
3130 if (typ
< 0 && !pcode_get_type(typ
))
3131 pt
->extra_type
= typ
;
3132 while ((size_t)color
>= ctx
->n_colors
)
3133 if (unlikely(!array_add_mayfail(struct color
, &ctx
->colors
, &ctx
->n_colors
, empty_color
, NULL
, ctx
->err
)))
3137 if (!ctx
->colors
[color
].align
) {
3138 ctx
->colors
[color
].size
= t
->size
;
3139 ctx
->colors
[color
].align
= t
->align
;
3141 ajla_assert_lo(ctx
->colors
[color
].size
== t
->size
&&
3142 ctx
->colors
[color
].align
== t
->align
,
3143 (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
));
3148 /*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);*/
3150 for (is
= 0; is
< ctx
->n_colors
; is
++) {
3151 const struct color
*c
= &ctx
->colors
[is
];
3153 if (unlikely(!layout_add(ctx
->layout
, maximum(c
->size
, 1), c
->align
, ctx
->err
)))
3156 if (unlikely(!layout_add(ctx
->layout
, 0, 1, ctx
->err
)))
3161 if (unlikely(!layout_compute(ctx
->layout
, false, ctx
->err
)))
3164 ctx
->n_slots
= layout_size(ctx
->layout
);
3166 ctx
->local_variables
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct local_variable
*, 0, 0, ctx
->n_slots
, sizeof(struct local_variable
), ctx
->err
);
3167 if (unlikely(!ctx
->local_variables
))
3170 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
);
3171 if (unlikely(!ctx
->local_variables_flags
))
3174 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3175 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3177 pt
->slot
= NO_FRAME_T
;
3179 pt
->slot
= layout_get(ctx
->layout
, pt
->color
);
3180 ctx
->local_variables
[pt
->slot
].type
= pt
->type
;
3181 ctx
->local_variables_flags
[pt
->slot
].may_be_borrowed
= false;
3185 layout_free(ctx
->layout
), ctx
->layout
= NULL
;
3189 unsigned n_elided
= 0;
3190 for (v
= 0; v
< ctx
->n_local_variables
; v
++) {
3191 struct pcode_type
*pt
= &ctx
->pcode_types
[v
];
3195 debug("function, elided %d/%d", n_elided
, ctx
->n_local_variables
);
3199 if (unlikely(!array_init_mayfail(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
, ctx
->err
)))
3202 if (unlikely(!pcode_preload_ld(ctx
)))
3206 sfd
= save_find_function_descriptor(md
, fd
);
3213 ctx
->code
= sfd
->code
;
3214 ctx
->code_len
= sfd
->code_size
;
3220 ctx
->labels
= mem_alloc_array_mayfail(mem_alloc_mayfail
, size_t *, 0, 0, ctx
->n_labels
, sizeof(size_t), ctx
->err
);
3221 if (unlikely(!ctx
->labels
))
3223 for (p
= 0; p
< ctx
->n_labels
; p
++)
3224 ctx
->labels
[p
] = no_label
;
3226 if (unlikely(!array_init_mayfail(struct label_ref
, &ctx
->label_ref
, &ctx
->label_ref_len
, ctx
->err
)))
3229 if (unlikely(!array_init_mayfail(const struct type
*, &ctx
->types
, &ctx
->types_len
, ctx
->err
)))
3232 if (unlikely(!array_init_mayfail(code_t
, &ctx
->code
, &ctx
->code_len
, ctx
->err
)))
3235 if (unlikely(!array_init_mayfail(struct line_position
, &ctx
->lp
, &ctx
->lp_size
, ctx
->err
)))
3238 if (unlikely(ctx
->function_type
== Fn_Record
) || unlikely(ctx
->function_type
== Fn_Option
)) {
3239 if (ctx
->function_type
== Fn_Record
) {
3240 if (unlikely(!pcode_generate_record(ctx
)))
3243 gen_code(OPCODE_UNREACHABLE
);
3245 if (unlikely(!pcode_generate_instructions(ctx
)))
3249 array_finish(code_t
, &ctx
->code
, &ctx
->code_len
);
3250 array_finish(struct line_position
, &ctx
->lp
, &ctx
->lp_size
);
3252 for (is
= 0; is
< ctx
->label_ref_len
; is
++) {
3254 struct label_ref
*lr
= &ctx
->label_ref
[is
];
3255 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
));
3256 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
));
3257 diff
= ((uint32_t)ctx
->labels
[lr
->label
] - (uint32_t)lr
->code_pos
) * sizeof(code_t
);
3258 if (SIZEOF_IP_T
== 2) {
3259 ctx
->code
[lr
->code_pos
] += (code_t
)diff
;
3260 } else if (SIZEOF_IP_T
== 4 && !CODE_ENDIAN
) {
3261 uint32_t val
= ctx
->code
[lr
->code_pos
] | ((uint32_t)ctx
->code
[lr
->code_pos
+ 1] << 16);
3263 ctx
->code
[lr
->code_pos
] = val
& 0xffff;
3264 ctx
->code
[lr
->code_pos
+ 1] = val
>> 16;
3265 } else if (SIZEOF_IP_T
== 4 && CODE_ENDIAN
) {
3266 uint32_t val
= ((uint32_t)ctx
->code
[lr
->code_pos
] << 16) | ctx
->code
[lr
->code_pos
+ 1];
3268 ctx
->code
[lr
->code_pos
] = val
>> 16;
3269 ctx
->code
[lr
->code_pos
+ 1] = val
& 0xffff;
3275 mem_free(ctx
->labels
), ctx
->labels
= NULL
;
3276 mem_free(ctx
->label_ref
), ctx
->label_ref
= NULL
;
3278 ft
= data_alloc_flexible(function_types
, types
, ctx
->types_len
, ctx
->err
);
3281 da(ft
,function_types
)->n_types
= ctx
->types_len
;
3282 memcpy(da(ft
,function_types
)->types
, ctx
->types
, ctx
->types_len
* sizeof(const struct type
*));
3283 mem_free(ctx
->types
);
3289 mem_free(ctx
->colors
), ctx
->colors
= NULL
;
3290 mem_free(ctx
->pcode_types
), ctx
->pcode_types
= NULL
;
3291 mem_free(ctx
->local_types
), ctx
->local_types
= NULL
;
3293 array_finish(pointer_t
*, &ctx
->ld
, &ctx
->ld_len
);
3295 if (profiling_escapes
) {
3296 ctx
->escape_data
= mem_alloc_array_mayfail(mem_calloc_mayfail
, struct escape_data
*, 0, 0, ctx
->code_len
, sizeof(struct escape_data
), ctx
->err
);
3297 if (unlikely(!ctx
->escape_data
))
3301 fn
= data_alloc_flexible(function
, local_directory
, ctx
->ld_len
, ctx
->err
);
3305 da(fn
,function
)->frame_slots
= frame_offset
/ slot_size
+ ctx
->n_slots
;
3306 da(fn
,function
)->n_bitmap_slots
= bitmap_slots(ctx
->n_slots
);
3307 da(fn
,function
)->n_arguments
= ctx
->n_real_arguments
;
3308 da(fn
,function
)->n_return_values
= ctx
->n_real_return_values
;
3309 da(fn
,function
)->code
= ctx
->code
;
3310 da(fn
,function
)->code_size
= ctx
->code_len
;
3311 da(fn
,function
)->local_variables
= ctx
->local_variables
;
3313 da(fn
,function
)->local_variables_flags
= ctx
->local_variables_flags
;
3315 mem_free(ctx
->local_variables_flags
);
3316 da(fn
,function
)->local_variables_flags
= sfd
->local_variables_flags
;
3318 da(fn
,function
)->n_slots
= ctx
->n_slots
;
3319 da(fn
,function
)->args
= ctx
->args
;
3320 da(fn
,function
)->types_ptr
= pointer_data(ft
);
3321 da(fn
,function
)->record_definition
= ctx
->record_definition
? &ctx
->record_definition
->type
: NULL
;
3322 da(fn
,function
)->function_name
= cast_ptr(char *, ctx
->function_name
);
3323 da(fn
,function
)->module_designator
= md
;
3324 da(fn
,function
)->function_designator
= fd
;
3326 da(fn
,function
)->lp
= ctx
->lp
;
3327 da(fn
,function
)->lp_size
= ctx
->lp_size
;
3329 da(fn
,function
)->lp
= sfd
->lp
;
3330 da(fn
,function
)->lp_size
= sfd
->lp_size
;
3332 memcpy(da(fn
,function
)->local_directory
, ctx
->ld
, ctx
->ld_len
* sizeof(pointer_t
*));
3333 da(fn
,function
)->local_directory_size
= ctx
->ld_len
;
3337 da(fn
,function
)->codegen
= function_build_internal_thunk(codegen_fn
, 1, ia
);
3338 store_relaxed(&da(fn
,function
)->codegen_failed
, 0);
3340 function_init_common(fn
);
3343 /*if (memcmp(ctx->code, sfd->code, ctx->code_len * sizeof(code_t))) internal(file_line, "code mismatch");*/
3344 da(fn
,function
)->loaded_cache
= sfd
->data_saved_cache
;
3345 /*if (da(fn,function)->loaded_cache) debug("loaded cache: %s", function_name(ctx));*/
3348 da(fn
,function
)->escape_data
= ctx
->escape_data
;
3349 da(fn
,function
)->leaf
= ctx
->leaf
;
3350 da(fn
,function
)->is_saved
= is_saved
;
3352 ipret_prefetch_functions(fn
);
3354 return pointer_data(fn
);
3357 *ctx
->err
= error_ajla(EC_ASYNC
, AJLA_ERROR_SIZE_OVERFLOW
);
3359 ctx
->ret_val
= pointer_mark();
3362 return ctx
->ret_val
;
3365 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
)
3370 ptr
= pcode_build_function_core(fp
, ip
, pcode
, size
, md
, fd
, &ex
, &err
);
3371 if (unlikely(pointer_is_empty(ptr
)))
3373 if (unlikely(pointer_is_mark(ptr
)))
3374 return function_return(fp
, pointer_error(err
, NULL
, NULL pass_file_line
));
3375 return function_return(fp
, ptr
);
3378 void *pcode_build_function_from_builtin(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3380 const pcode_t
*start
;
3382 struct module_designator
*md
= arguments
[0].ptr
;
3383 struct function_designator
*fd
= arguments
[1].ptr
;
3384 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3385 return pcode_build_function(fp
, ip
, start
, size
, md
, arguments
[1].ptr
);
3388 void *pcode_build_function_from_array(frame_s
*fp
, const code_t
*ip
, union internal_arg arguments
[])
3392 struct thunk
*thunk
;
3395 const struct function_designator
*fd
;
3396 const pcode_t
*start
;
3399 ptr
= arguments
[0].ptr
;
3400 ex
= pointer_deep_eval(ptr
, fp
, ip
, &thunk
);
3401 if (unlikely(ex
!= POINTER_FOLLOW_THUNK_GO
)) {
3402 if (ex
== POINTER_FOLLOW_THUNK_EXCEPTION
) {
3403 return function_return(fp
, pointer_thunk(thunk
));
3408 array_to_bytes(ptr
, &bytes
, &bytes_l
);
3411 if (unlikely(bytes_l
% sizeof(pcode_t
) != 0))
3412 internal(file_line
, "pcode_build_function_from_array: invalid length: %lu", (unsigned long)bytes_l
);
3414 start
= cast_ptr(const pcode_t
*, bytes
);
3415 size
= bytes_l
/ sizeof(pcode_t
);
3416 fd
= arguments
[2].ptr
;
3418 /*builtin_walk_nested(&start, &size, fd->n_entries, fd->entries);*/
3420 ex
= pcode_build_function(fp
, ip
, start
, size
, arguments
[1].ptr
, fd
);
3427 void *pcode_array_from_builtin(frame_s
*fp
, const code_t attr_unused
*ip
, union internal_arg arguments
[])
3429 const struct type
*t
;
3432 const pcode_t
*start
;
3434 struct module_designator
*md
= arguments
[0].ptr
;
3435 struct function_designator
*fd
= arguments
[1].ptr
;
3437 builtin_find_function(md
->path
, md
->path_len
, fd
->n_entries
, fd
->entries
, &start
, &size
);
3439 t
= type_get_fixed(log_2(sizeof(pcode_t
)), false);
3440 d
= data_alloc_array_flat_mayfail(t
, size
, size
, false, &err pass_file_line
);
3442 return function_return(fp
, pointer_thunk(thunk_alloc_exception_error(err
, NULL
, NULL
, NULL pass_file_line
)));
3445 memcpy(da_array_flat(d
), start
, size
* sizeof(pcode_t
));
3447 return function_return(fp
, pointer_data(d
));
3451 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
)
3455 unsigned n_local_variables
;
3456 unsigned n_arguments
;
3460 if (unlikely(!array_init_mayfail(pcode_t
, &pc
, &pc_l
, err
)))
3464 if (unlikely(!array_add_mayfail(pcode_t, &pc, &pc_l, x, NULL, err)))\
3467 #define addstr(x, l) \
3469 if (unlikely(!array_add_multiple_mayfail(pcode_t, &pc, &pc_l, x, l, NULL, err)))\
3473 n_local_variables
= Op_IsUnary(op
) ? 2 : 3;
3474 n_arguments
= n_local_variables
- 1;
3477 add(Call_Mode_Strict
);
3480 add(n_local_variables
);
3487 for (i
= 0; i
< n_local_variables
; i
++) {
3488 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3499 add(1 + blob_1_len
);
3501 addstr(blob_1
, blob_1_len
);
3502 if (n_arguments
== 2) {
3504 add(1 + blob_2_len
);
3506 addstr(blob_2
, blob_2_len
);
3509 add(Op_IsUnary(op
) ? P_UnaryOp
: P_BinaryOp
);
3510 add(Op_IsUnary(op
) ? 4 : 6);
3513 add(Flag_Free_Argument
| Flag_Op_Strict
);
3515 if (n_arguments
== 2) {
3516 add(Flag_Free_Argument
);
3522 add(Flag_Free_Argument
);
3528 ptr
= pcode_build_function_core(NULL
, NULL
, pc
, pc_l
, NULL
, NULL
, NULL
, err
);
3537 return pointer_empty();
3541 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
)
3543 struct data
*function
;
3546 #ifdef POINTER_FOLLOW_IS_LOCKLESS
3547 const addrlock_depth lock_depth
= DEPTH_THUNK
;
3549 const addrlock_depth lock_depth
= DEPTH_POINTER
;
3553 pointer_follow(ptr
, false, function
, PF_WAIT
, fp
, ip
,
3556 return POINTER_FOLLOW_THUNK_RETRY
);
3558 if (likely(function
!= NULL
)) {
3560 return POINTER_FOLLOW_THUNK_RETRY
;
3563 fn_thunk
= function_build_internal_thunk(build_fn
, n_arguments
, ia
);
3565 barrier_write_before_lock();
3566 address_lock(ptr
, lock_depth
);
3567 if (likely(pointer_is_empty(*pointer_volatile(ptr
)))) {
3568 *pointer_volatile(ptr
) = fn_thunk
;
3569 address_unlock(ptr
, lock_depth
);
3571 address_unlock(ptr
, lock_depth
);
3572 pointer_dereference(fn_thunk
);
3578 static void *pcode_build_op_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3580 pcode_t src_type
= (pcode_t
)a
[0].i
;
3581 pcode_t dest_type
= (pcode_t
)a
[1].i
;
3582 pcode_t op
= (pcode_t
)a
[2].i
;
3583 unsigned flags
= (unsigned)a
[3].i
;
3585 unsigned n_local_variables
;
3586 unsigned n_arguments
;
3588 pcode_t
*pc
= pcode
;
3590 n_local_variables
= flags
& PCODE_FIND_OP_UNARY
? 2 : 3;
3591 n_arguments
= n_local_variables
- 1;
3593 *pc
++ = Fn_Function
;
3594 *pc
++ = Call_Mode_Strict
;
3597 *pc
++ = (pcode_t
)n_local_variables
;
3598 *pc
++ = (pcode_t
)n_arguments
;
3604 for (i
= 0; i
< n_local_variables
; i
++) {
3605 pcode_t t
= i
< n_arguments
? src_type
: dest_type
;
3613 *pc
++ = n_arguments
;
3614 for (i
= 0; i
< n_arguments
; i
++)
3617 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? P_UnaryOp
: P_BinaryOp
);
3618 *pc
++ = (pcode_t
)(flags
& PCODE_FIND_OP_UNARY
? 4 : 6);
3620 *pc
++ = (pcode_t
)n_arguments
;
3621 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3623 if (!(flags
& PCODE_FIND_OP_UNARY
)) {
3624 *pc
++ = Flag_Free_Argument
;
3630 *pc
++ = Flag_Free_Argument
;
3631 *pc
++ = n_arguments
;
3633 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
));
3635 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3638 static pointer_t fixed_op_thunk
[TYPE_FIXED_N
][OPCODE_FIXED_OP_N
];
3639 static pointer_t int_op_thunk
[TYPE_INT_N
][OPCODE_INT_OP_N
];
3640 static pointer_t real_op_thunk
[TYPE_REAL_N
][OPCODE_REAL_OP_N
];
3641 static pointer_t bool_op_thunk
[OPCODE_BOOL_TYPE_MULT
];
3643 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
)
3645 union internal_arg ia
[4];
3648 type_tag_t tag
= likely(!(flags
& PCODE_CONVERT_FROM_INT
)) ? type
->tag
: rtype
->tag
;
3650 if (TYPE_TAG_IS_FIXED(tag
)) {
3651 unsigned idx
= (code
- OPCODE_FIXED_OP
- (TYPE_TAG_IDX_FIXED(tag
) >> 1) * OPCODE_FIXED_TYPE_MULT
) / OPCODE_FIXED_OP_MULT
;
3652 ajla_assert(idx
< OPCODE_FIXED_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3653 ptr
= &fixed_op_thunk
[TYPE_TAG_IDX_FIXED(tag
) >> 1][idx
];
3654 } else if (TYPE_TAG_IS_INT(tag
)) {
3655 unsigned idx
= (code
- OPCODE_INT_OP
- TYPE_TAG_IDX_INT(tag
) * OPCODE_INT_TYPE_MULT
) / OPCODE_INT_OP_MULT
;
3656 ajla_assert(idx
< OPCODE_INT_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3657 ptr
= &int_op_thunk
[TYPE_TAG_IDX_INT(tag
)][idx
];
3658 ajla_assert(is_power_of_2(type
->size
), (file_line
, "pcode_find_op_function: invalid integer type size %"PRIuMAX
"", (uintmax_t)type
->size
));
3659 } else if (TYPE_TAG_IS_REAL(tag
)) {
3660 unsigned idx
= (code
- OPCODE_REAL_OP
- TYPE_TAG_IDX_REAL(tag
) * OPCODE_REAL_TYPE_MULT
) / OPCODE_REAL_OP_MULT
;
3661 ajla_assert(idx
< OPCODE_REAL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3662 ptr
= &real_op_thunk
[TYPE_TAG_IDX_REAL(tag
)][idx
];
3664 unsigned idx
= (code
- OPCODE_BOOL_OP
) / OPCODE_BOOL_OP_MULT
;
3665 ajla_assert(idx
< OPCODE_BOOL_OP_N
, (file_line
, "pcode_find_op_function: invalid parameters, type %u, code %04x", tag
, code
));
3666 ptr
= &bool_op_thunk
[idx
];
3668 internal(file_line
, "pcode_find_op_function: invalid type %u", tag
);
3671 ia
[0].i
= type_to_pcode(type
);
3672 ia
[1].i
= type_to_pcode(rtype
);
3673 ia
[2].i
= code
+ Op_N
;
3676 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_op_function
, 4, ia
, result
);
3679 static void *pcode_build_is_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3682 pcode_t
*pc
= pcode
;
3684 *pc
++ = Fn_Function
;
3685 *pc
++ = Call_Mode_Strict
;
3695 *pc
++ = T_Undetermined
;
3696 *pc
++ = T_Undetermined
;
3700 *pc
++ = T_FlatOption
;
3701 *pc
++ = T_FlatOption
;
3711 *pc
++ = Un_IsException
;
3713 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3722 *pc
++ = Flag_Free_Argument
;
3725 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
)));
3727 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3730 static pointer_t is_exception_thunk
;
3732 void * attr_fastcall
pcode_find_is_exception(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3734 return pcode_alloc_op_function(&is_exception_thunk
, fp
, ip
, pcode_build_is_exception_function
, 0, NULL
, result
);
3737 static void *pcode_build_get_exception_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
3740 pcode_t
*pc
= pcode
;
3742 *pc
++ = Fn_Function
;
3743 *pc
++ = Call_Mode_Strict
;
3753 *pc
++ = T_Undetermined
;
3754 *pc
++ = T_Undetermined
;
3769 *pc
++ = Un_ExceptionClass
+ a
[0].i
;
3771 *pc
++ = Flag_Free_Argument
| Flag_Op_Strict
;
3780 *pc
++ = Flag_Free_Argument
;
3783 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
)));
3785 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3788 static pointer_t get_exception_thunk
[3];
3790 void * attr_fastcall
pcode_find_get_exception(unsigned mode
, frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3792 union internal_arg ia
[1];
3794 return pcode_alloc_op_function(&get_exception_thunk
[mode
], fp
, ip
, pcode_build_get_exception_function
, 1, ia
, result
);
3797 static void *pcode_build_array_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3800 pcode_t
*pc
= pcode
;
3802 *pc
++ = Fn_Function
;
3803 *pc
++ = Call_Mode_Strict
;
3813 *pc
++ = T_Undetermined
;
3814 *pc
++ = T_Undetermined
;
3823 *pc
++ = T_Undetermined
;
3824 *pc
++ = T_Undetermined
;
3833 *pc
++ = P_Array_Load
;
3836 *pc
++ = Flag_Evaluate
;
3850 *pc
++ = Flag_Free_Argument
;
3853 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
)));
3855 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3858 static pointer_t array_load_thunk
;
3860 void * attr_fastcall
pcode_find_array_load_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3862 return pcode_alloc_op_function(&array_load_thunk
, fp
, ip
, pcode_build_array_load_function
, 0, NULL
, result
);
3865 static void *pcode_build_array_len_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3868 pcode_t
*pc
= pcode
;
3870 *pc
++ = Fn_Function
;
3871 *pc
++ = Call_Mode_Strict
;
3881 *pc
++ = T_Undetermined
;
3882 *pc
++ = T_Undetermined
;
3895 *pc
++ = P_Array_Len
;
3899 *pc
++ = Flag_Evaluate
;
3907 *pc
++ = Flag_Free_Argument
;
3910 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
)));
3912 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3915 static pointer_t array_len_thunk
;
3917 void * attr_fastcall
pcode_find_array_len_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3919 return pcode_alloc_op_function(&array_len_thunk
, fp
, ip
, pcode_build_array_len_function
, 0, NULL
, result
);
3922 static void *pcode_build_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3925 pcode_t
*pc
= pcode
;
3927 *pc
++ = Fn_Function
;
3928 *pc
++ = Call_Mode_Strict
;
3938 *pc
++ = T_Undetermined
;
3939 *pc
++ = T_Undetermined
;
3948 *pc
++ = T_FlatOption
;
3949 *pc
++ = T_FlatOption
;
3958 *pc
++ = P_Array_Len_Greater_Than
;
3963 *pc
++ = Flag_Evaluate
;
3975 *pc
++ = Flag_Free_Argument
;
3978 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
)));
3980 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
3983 static pointer_t array_len_greater_than_thunk
;
3985 void * attr_fastcall
pcode_find_array_len_greater_than_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
3987 return pcode_alloc_op_function(&array_len_greater_than_thunk
, fp
, ip
, pcode_build_array_len_greater_than_function
, 0, NULL
, result
);
3990 static void *pcode_build_array_sub_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
3993 pcode_t
*pc
= pcode
;
3995 *pc
++ = Fn_Function
;
3996 *pc
++ = Call_Mode_Strict
;
4006 *pc
++ = T_Undetermined
;
4007 *pc
++ = T_Undetermined
;
4021 *pc
++ = T_Undetermined
;
4022 *pc
++ = T_Undetermined
;
4032 *pc
++ = P_Array_Sub
;
4035 *pc
++ = Flag_Evaluate
;
4054 *pc
++ = Flag_Free_Argument
;
4057 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
)));
4059 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4062 static pointer_t array_sub_thunk
;
4064 void * attr_fastcall
pcode_find_array_sub_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4066 return pcode_alloc_op_function(&array_sub_thunk
, fp
, ip
, pcode_build_array_sub_function
, 0, NULL
, result
);
4069 static void *pcode_build_array_skip_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4072 pcode_t
*pc
= pcode
;
4074 *pc
++ = Fn_Function
;
4075 *pc
++ = Call_Mode_Strict
;
4085 *pc
++ = T_Undetermined
;
4086 *pc
++ = T_Undetermined
;
4095 *pc
++ = T_Undetermined
;
4096 *pc
++ = T_Undetermined
;
4105 *pc
++ = P_Array_Skip
;
4108 *pc
++ = Flag_Evaluate
;
4122 *pc
++ = Flag_Free_Argument
;
4125 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
)));
4127 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4130 static pointer_t array_skip_thunk
;
4132 void * attr_fastcall
pcode_find_array_skip_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4134 return pcode_alloc_op_function(&array_skip_thunk
, fp
, ip
, pcode_build_array_skip_function
, 0, NULL
, result
);
4137 static void *pcode_build_array_append_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4140 pcode_t
*pc
= pcode
;
4142 *pc
++ = Fn_Function
;
4143 *pc
++ = Call_Mode_Strict
;
4153 *pc
++ = T_Undetermined
;
4154 *pc
++ = T_Undetermined
;
4158 *pc
++ = T_Undetermined
;
4159 *pc
++ = T_Undetermined
;
4163 *pc
++ = T_Undetermined
;
4164 *pc
++ = T_Undetermined
;
4183 *pc
++ = P_Array_Append
;
4186 *pc
++ = Flag_Free_Argument
;
4188 *pc
++ = Flag_Free_Argument
;
4193 *pc
++ = Flag_Free_Argument
;
4195 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
)));
4197 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4200 static pointer_t array_append_thunk
;
4202 void * attr_fastcall
pcode_find_array_append_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4204 return pcode_alloc_op_function(&array_append_thunk
, fp
, ip
, pcode_build_array_append_function
, 0, NULL
, result
);
4208 static void *pcode_build_option_ord_function(frame_s
*fp
, const code_t
*ip
, union internal_arg attr_unused a
[])
4211 pcode_t
*pc
= pcode
;
4213 *pc
++ = Fn_Function
;
4214 *pc
++ = Call_Mode_Strict
;
4224 *pc
++ = T_Undetermined
;
4225 *pc
++ = T_Undetermined
;
4242 *pc
++ = P_Option_Ord
;
4253 *pc
++ = Flag_Free_Argument
;
4256 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
)));
4258 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4261 static pointer_t option_ord_thunk
;
4263 void * attr_fastcall
pcode_find_option_ord_function(frame_s
*fp
, const code_t
*ip
, pointer_t
**result
)
4265 return pcode_alloc_op_function(&option_ord_thunk
, fp
, ip
, pcode_build_option_ord_function
, 0, NULL
, result
);
4269 struct function_key
{
4274 static void *pcode_build_record_option_load_function(frame_s
*fp
, const code_t
*ip
, union internal_arg a
[])
4277 pcode_t
*pc
= pcode
;
4278 pcode_t result_type
= a
[0].i
== PCODE_FUNCTION_OPTION_TEST
? T_FlatOption
: T_Undetermined
;
4280 *pc
++ = Fn_Function
;
4281 *pc
++ = Call_Mode_Strict
;
4291 *pc
++ = T_Undetermined
;
4292 *pc
++ = T_Undetermined
;
4296 *pc
++ = result_type
;
4297 *pc
++ = result_type
;
4306 case PCODE_FUNCTION_RECORD_LOAD
:
4307 /* P_Record_Load_Slot already sets Flag_Evaluate */
4308 *pc
++ = P_Record_Load_Slot
;
4312 *pc
++ = (pcode_t
)a
[1].i
;
4314 case PCODE_FUNCTION_OPTION_LOAD
:
4315 *pc
++ = P_Option_Load
;
4318 *pc
++ = Flag_Evaluate
;
4320 *pc
++ = (pcode_t
)a
[1].i
;
4322 case PCODE_FUNCTION_OPTION_TEST
:
4326 *pc
++ = P_Option_Test
;
4330 *pc
++ = (pcode_t
)a
[1].i
;
4333 internal(file_line
, "pcode_build_record_option_load_function: invalid operation %"PRIuMAX
"", (uintmax_t)a
[0].i
);
4342 *pc
++ = Flag_Free_Argument
;
4345 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
)));
4347 return pcode_build_function(fp
, ip
, pcode
, pc
- pcode
, NULL
, NULL
);
4350 struct pcode_function
{
4351 struct tree_entry entry
;
4352 struct function_key key
;
4356 shared_var
struct tree pcode_functions
;
4357 rwlock_decl(pcode_functions_mutex
);
4359 static int record_option_load_compare(const struct tree_entry
*e1
, uintptr_t e2
)
4361 struct pcode_function
*rl
= get_struct(e1
, struct pcode_function
, entry
);
4362 struct function_key
*key
= cast_cpp(struct function_key
*, num_to_ptr(e2
));
4363 if (rl
->key
.tag
!= key
->tag
)
4364 return (int)rl
->key
.tag
- key
->tag
;
4365 if (rl
->key
.id
< key
->id
)
4367 if (rl
->key
.id
> key
->id
)
4372 static pointer_t
*pcode_find_function_for_key(struct function_key
*key
)
4374 struct tree_entry
*e
;
4376 rwlock_lock_read(&pcode_functions_mutex
);
4377 e
= tree_find(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
));
4378 rwlock_unlock_read(&pcode_functions_mutex
);
4380 struct tree_insert_position ins
;
4381 rwlock_lock_write(&pcode_functions_mutex
);
4382 e
= tree_find_for_insert(&pcode_functions
, record_option_load_compare
, ptr_to_num(key
), &ins
);
4385 struct pcode_function
*rl
;
4386 rl
= mem_alloc_mayfail(struct pcode_function
*, sizeof(struct pcode_function
), &sink
);
4387 if (unlikely(!rl
)) {
4388 rwlock_unlock_write(&pcode_functions_mutex
);
4392 rl
->ptr
= pointer_empty();
4394 tree_insert_after_find(e
, &ins
);
4396 rwlock_unlock_write(&pcode_functions_mutex
);
4398 return &get_struct(e
, struct pcode_function
, entry
)->ptr
;
4401 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
)
4403 struct function_key key
;
4405 union internal_arg ia
[2];
4407 if (unlikely((uintmax_t)slot
> (uintmax_t)signed_maximum(pcode_t
) + zero
)) {
4408 *result
= out_of_memory_ptr
;
4409 return POINTER_FOLLOW_THUNK_RETRY
;
4415 ptr
= pcode_find_function_for_key(&key
);
4416 if (unlikely(!ptr
)) {
4417 *result
= out_of_memory_ptr
;
4418 return POINTER_FOLLOW_THUNK_RETRY
;
4423 return pcode_alloc_op_function(ptr
, fp
, ip
, pcode_build_record_option_load_function
, 2, ia
, result
);
4426 static void thunk_init_run(pointer_t
*ptr
, unsigned n
)
4429 *ptr
= pointer_empty();
4434 static void thunk_free_run(pointer_t
*ptr
, unsigned n
)
4437 if (!pointer_is_empty(*ptr
))
4438 pointer_dereference(*ptr
);
4443 void name(pcode_init
)(void)
4447 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_init_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4448 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_init_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4449 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_init_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4450 thunk_init_run(&is_exception_thunk
, 1);
4451 thunk_init_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4452 thunk_init_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4453 thunk_init_run(&array_load_thunk
, 1);
4454 thunk_init_run(&array_len_thunk
, 1);
4455 thunk_init_run(&array_len_greater_than_thunk
, 1);
4456 thunk_init_run(&array_sub_thunk
, 1);
4457 thunk_init_run(&array_skip_thunk
, 1);
4458 thunk_init_run(&array_append_thunk
, 1);
4459 thunk_init_run(&option_ord_thunk
, 1);
4460 tree_init(&pcode_functions
);
4461 rwlock_init(&pcode_functions_mutex
);
4464 void name(pcode_done
)(void)
4467 for (i
= 0; i
< TYPE_FIXED_N
+ uzero
; i
++) thunk_free_run(fixed_op_thunk
[i
], OPCODE_FIXED_OP_N
);
4468 for (i
= 0; i
< TYPE_INT_N
; i
++) thunk_free_run(int_op_thunk
[i
], OPCODE_INT_OP_N
);
4469 for (i
= 0; i
< TYPE_REAL_N
+ uzero
; i
++) thunk_free_run(real_op_thunk
[i
], OPCODE_REAL_OP_N
);
4470 thunk_free_run(&is_exception_thunk
, 1);
4471 thunk_free_run(get_exception_thunk
, n_array_elements(get_exception_thunk
));
4472 thunk_free_run(bool_op_thunk
, OPCODE_BOOL_OP_N
);
4473 thunk_free_run(&array_load_thunk
, 1);
4474 thunk_free_run(&array_len_thunk
, 1);
4475 thunk_free_run(&array_len_greater_than_thunk
, 1);
4476 thunk_free_run(&array_sub_thunk
, 1);
4477 thunk_free_run(&array_skip_thunk
, 1);
4478 thunk_free_run(&array_append_thunk
, 1);
4479 thunk_free_run(&option_ord_thunk
, 1);
4480 while (!tree_is_empty(&pcode_functions
)) {
4481 struct pcode_function
*rl
= get_struct(tree_any(&pcode_functions
), struct pcode_function
, entry
);
4482 if (!pointer_is_empty(rl
->ptr
))
4483 pointer_dereference(rl
->ptr
);
4484 tree_delete(&rl
->entry
);
4487 rwlock_done(&pcode_functions_mutex
);