1 /*
2 * %CopyrightBegin%
3 *
4 * Copyright Ericsson AB 1996-2018. All Rights Reserved.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * %CopyrightEnd%
19 */
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include "sys.h"
26 #include "erl_vm.h"
27 #include "global.h"
28 #include "erl_version.h"
29 #include "erl_process.h"
30 #include "error.h"
31 #include "erl_driver.h"
32 #include "bif.h"
33 #include "external.h"
34 #include "beam_load.h"
35 #include "beam_bp.h"
36 #include "big.h"
37 #include "erl_bits.h"
38 #include "beam_catches.h"
39 #include "erl_binary.h"
40 #include "erl_zlib.h"
41 #include "erl_map.h"
42 #include "erl_process_dict.h"
43 #include "erl_unicode.h"
44
45 #ifdef HIPE
46 #include "hipe_bif0.h"
47 #include "hipe_mode_switch.h"
48 #include "hipe_arch.h"
49 #include "hipe_load.h"
50 #endif
51
52 ErlDrvBinary* erts_gzinflate_buffer(char*, int);
53
54 #define MAX_OPARGS 8
55 #define CALLED 0
56 #define DEFINED 1
57 #define EXPORTED 2
58
59 #if defined(WORDS_BIGENDIAN)
60 # define NATIVE_ENDIAN(F) \
61 if ((F).val & BSF_NATIVE) { \
62 (F).val &= ~(BSF_LITTLE|BSF_NATIVE); \
63 } else {}
64 #else
65 # define NATIVE_ENDIAN(F) \
66 if ((F).val & BSF_NATIVE) { \
67 (F).val &= ~BSF_NATIVE; \
68 (F).val |= BSF_LITTLE; \
69 } else {}
70 #endif
71
72 /*
73 * Errors returned from tranform_engine().
74 */
75 #define TE_OK 0
76 #define TE_FAIL (-1)
77 #define TE_SHORT_WINDOW (-2)
78
79 /*
80 * Type for a reference to a label that must be patched.
81 */
82
83 typedef struct {
84 Uint pos; /* Position of label reference to patch. */
85 Uint offset; /* Offset from patch location. */
86 int packed; /* 0 (not packed), 1 (lsw), 2 (msw) */
87 } LabelPatch;
88
89 /*
90 * Type for a label.
91 */
92
93 typedef struct {
94 Uint value; /* Value of label (0 if not known yet). */
95 Uint looprec_targeted; /* Non-zero if this label is the target of a loop_rec
96 * instruction.
97 */
98 LabelPatch* patches; /* Array of label patches. */
99 Uint num_patches; /* Number of patches in array. */
100 Uint num_allocated; /* Number of allocated patches. */
101 } Label;
102
103 /*
104 * Type for an operand for a generic instruction.
105 */
106
107 typedef struct {
108 unsigned type; /* Type of operand. */
109 BeamInstr val; /* Value of operand. */
110 } GenOpArg;
111
112 /*
113 * A generic operation.
114 */
115
116 typedef struct genop {
117 unsigned int op; /* Opcode. */
118 int arity; /* Number of arguments. */
119 GenOpArg def_args[MAX_OPARGS]; /* Default buffer for arguments. */
120 GenOpArg* a; /* The arguments. */
121 struct genop* next; /* Next genop. */
122 } GenOp;
123
124 /*
125 * The allocation unit for generic blocks.
126 */
127
128 typedef struct genop_block {
129 GenOp genop[32];
130 struct genop_block* next;
131 } GenOpBlock;
132
133 /*
134 * This structure contains information for an imported function or BIF.
135 */
136 typedef struct {
137 Eterm module; /* Tagged atom for module. */
138 Eterm function; /* Tagged atom for function. */
139 int arity; /* Arity. */
140 Uint patches; /* Index to locations in code to
141 * eventually patch with a pointer into
142 * the export entry.
143 */
144 BifFunction bf; /* Pointer to BIF function if BIF;
145 * NULL otherwise.
146 */
147 } ImportEntry;
148
149 /*
150 * This structure contains information for a function exported from a module.
151 */
152
153 typedef struct {
154 Eterm function; /* Tagged atom for function. */
155 int arity; /* Arity. */
156 BeamInstr* address; /* Address to function in code. */
157 } ExportEntry;
158
159 #define MakeIffId(a, b, c, d) \
160 (((Uint) (a) << 24) | ((Uint) (b) << 16) | ((Uint) (c) << 8) | (Uint) (d))
161
162 #define ATOM_CHUNK 0
163 #define CODE_CHUNK 1
164 #define STR_CHUNK 2
165 #define IMP_CHUNK 3
166 #define EXP_CHUNK 4
167 #define MIN_MANDATORY 1
168 #define MAX_MANDATORY 5
169
170 #define LAMBDA_CHUNK 5
171 #define LITERAL_CHUNK 6
172 #define ATTR_CHUNK 7
173 #define COMPILE_CHUNK 8
174 #define LINE_CHUNK 9
175 #define UTF8_ATOM_CHUNK 10
176
177 #define NUM_CHUNK_TYPES (sizeof(chunk_types)/sizeof(chunk_types[0]))
178
179 /*
180 * An array with all chunk types recognized by the loader.
181 */
182
183 static Uint chunk_types[] = {
184 /*
185 * Atom chunk types -- Atom or AtU8 MUST be present.
186 */
187 MakeIffId('A', 't', 'o', 'm'), /* 0 */
188
189 /*
190 * Mandatory chunk types -- these MUST be present.
191 */
192 MakeIffId('C', 'o', 'd', 'e'), /* 1 */
193 MakeIffId('S', 't', 'r', 'T'), /* 2 */
194 MakeIffId('I', 'm', 'p', 'T'), /* 3 */
195 MakeIffId('E', 'x', 'p', 'T'), /* 4 */
196
197 /*
198 * Optional chunk types -- the loader will use them if present.
199 */
200 MakeIffId('F', 'u', 'n', 'T'), /* 5 */
201 MakeIffId('L', 'i', 't', 'T'), /* 6 */
202 MakeIffId('A', 't', 't', 'r'), /* 7 */
203 MakeIffId('C', 'I', 'n', 'f'), /* 8 */
204 MakeIffId('L', 'i', 'n', 'e'), /* 9 */
205 MakeIffId('A', 't', 'U', '8'), /* 10 */
206 };
207
208 /*
209 * This structure keeps load-time information about a lambda.
210 */
211
212 typedef struct {
213 ErlFunEntry* fe; /* Entry in fun table. */
214 unsigned label; /* Label of function entry. */
215 Uint32 num_free; /* Number of free variables. */
216 Eterm function; /* Name of local function. */
217 int arity; /* Arity (including free variables). */
218 } Lambda;
219
220 /*
221 * This structure keeps load-time information about a literal.
222 */
223
224 typedef struct {
225 Eterm term; /* The tagged term (in the heap). */
226 ErlHeapFragment* heap_frags;
227 } Literal;
228
229 /*
230 * This structure keeps information about an operand that needs to be
231 * patched to contain the correct address of a literal when the code is
232 * frozen.
233 */
234
235 typedef struct literal_patch LiteralPatch;
236 struct literal_patch {
237 Uint pos; /* Position in code */
238 LiteralPatch* next;
239 };
240
241 /*
242 * This structure keeps information about an operand that needs to be
243 * patched to contain the correct address for an address into the string table.
244 */
245
246 typedef struct string_patch StringPatch;
247 struct string_patch {
248 int pos; /* Position in code */
249 StringPatch* next;
250 };
251
252 /*
253 * This structure associates a code offset with a source code location.
254 */
255
256 typedef struct {
257 int pos; /* Position in code */
258 Uint32 loc; /* Location in source code */
259 } LineInstr;
260
261 /*
262 * This structure contains all information about the module being loaded.
263 */
264 #define MD5_SIZE 16
265 typedef struct LoaderState {
266 /*
267 * The current logical file within the binary.
268 */
269
270 char* file_name; /* Name of file we are reading (usually chunk name). */
271 byte* file_p; /* Current pointer within file. */
272 unsigned file_left; /* Number of bytes left in file. */
273 ErlDrvBinary* bin; /* Binary holding BEAM file (or NULL) */
274
275 /*
276 * The following are used mainly for diagnostics.
277 */
278
279 Eterm group_leader; /* Group leader (for diagnostics). */
280 Eterm module; /* Tagged atom for module name. */
281 Eterm function; /* Tagged atom for current function
282 * (or 0 if none).
283 */
284 unsigned arity; /* Arity for current function. */
285
286 /*
287 * All found chunks.
288 */
289
290 struct {
291 byte* start; /* Start of chunk (in binary). */
292 unsigned size; /* Size of chunk. */
293 } chunks[NUM_CHUNK_TYPES];
294
295 /*
296 * Used for code loading (mainly).
297 */
298
299 byte* code_start; /* Start of code file. */
300 unsigned code_size; /* Size of code file. */
301 int specific_op; /* Specific opcode (-1 if not found). */
302 unsigned int num_functions; /* Number of functions in module. */
303 unsigned int num_labels; /* Number of labels. */
304 BeamCodeHeader* hdr; /* Loaded code header */
305 BeamInstr* codev; /* Loaded code buffer */
306 int codev_size; /* Size of code buffer in words. */
307 int ci; /* Current index into loaded code buffer. */
308 Label* labels;
309 StringPatch* string_patches; /* Linked list of position into string table to patch. */
310 BeamInstr catches; /* Linked list of catch_yf instructions. */
311 unsigned loaded_size; /* Final size of code when loaded. */
312 byte mod_md5[MD5_SIZE]; /* MD5 for module code. */
313 int may_load_nif; /* true if NIFs may later be loaded for this module */
314 int on_load; /* Index in the code for the on_load function
315 * (or 0 if there is no on_load function)
316 */
317 int otp_20_or_higher; /* Compiled with OTP 20 or higher */
318
319 /*
320 * Atom table.
321 */
322
323 unsigned int num_atoms; /* Number of atoms in atom table. */
324 Eterm* atom; /* Atom table. */
325
326 unsigned int num_exps; /* Number of exports. */
327 ExportEntry* export; /* Pointer to export table. */
328
329 unsigned int num_imports; /* Number of imports. */
330 ImportEntry* import; /* Import entry (translated information). */
331
332 /*
333 * Generic instructions.
334 */
335 GenOp* genop; /* The last generic instruction seen. */
336 GenOp* free_genop; /* List of free genops. */
337 GenOpBlock* genop_blocks; /* List of all block of allocated genops. */
338
339 /*
340 * Lambda table.
341 */
342
343 unsigned int num_lambdas; /* Number of lambdas in table. */
344 unsigned int lambdas_allocated; /* Size of allocated lambda table. */
345 Lambda* lambdas; /* Pointer to lambdas. */
346 Lambda def_lambdas[16]; /* Default storage for lambda table. */
347 char* lambda_error; /* Delayed missing 'FunT' error. */
348
349 /*
350 * Literals (constant pool).
351 */
352
353 unsigned int num_literals; /* Number of literals in table. */
354 unsigned int allocated_literals; /* Number of literal entries allocated. */
355 Literal* literals; /* Array of literals. */
356 LiteralPatch* literal_patches; /* Operands that need to be patched. */
357 Uint total_literal_size; /* Total heap size for all literals. */
358
359 /*
360 * Line table.
361 */
362 BeamInstr* line_item; /* Line items from the BEAM file. */
363 unsigned int num_line_items;/* Number of line items. */
364 LineInstr* line_instr; /* Line instructions */
365 unsigned int num_line_instrs; /* Maximum number of line instructions */
366 unsigned int current_li; /* Current line instruction */
367 unsigned int* func_line; /* Mapping from function to first line instr */
368 Eterm* fname; /* List of file names */
369 unsigned int num_fnames; /* Number of filenames in fname table */
370 int loc_size; /* Size of location info in bytes (2/4) */
371 } LoaderState;
372
373 #define GetTagAndValue(Stp, Tag, Val) \
374 do { \
375 BeamInstr __w; \
376 GetByte(Stp, __w); \
377 Tag = __w & 0x07; \
378 if ((__w & 0x08) == 0) { \
379 Val = __w >> 4; \
380 } else if ((__w & 0x10) == 0) { \
381 Val = ((__w >> 5) << 8); \
382 GetByte(Stp, __w); \
383 Val |= __w; \
384 } else { \
385 int __res = get_tag_and_value(Stp, __w, (Tag), &(Val)); \
386 if (__res < 0) goto load_error; \
387 Tag = (unsigned) __res; \
388 } \
389 } while (0)
390
391
392 #define LoadError0(Stp, Fmt) \
393 do { \
394 load_printf(__LINE__, Stp, Fmt); \
395 goto load_error; \
396 } while (0)
397
398 #define LoadError1(Stp, Fmt, Arg1) \
399 do { \
400 load_printf(__LINE__, stp, Fmt, Arg1); \
401 goto load_error; \
402 } while (0)
403
404 #define LoadError2(Stp, Fmt, Arg1, Arg2) \
405 do { \
406 load_printf(__LINE__, Stp, Fmt, Arg1, Arg2); \
407 goto load_error; \
408 } while (0)
409
410 #define LoadError3(Stp, Fmt, Arg1, Arg2, Arg3) \
411 do { \
412 load_printf(__LINE__, stp, Fmt, Arg1, Arg2, Arg3); \
413 goto load_error; \
414 } while (0)
415
416 #define EndOfFile(Stp) (stp->file_left == 0)
417
418 #define GetInt(Stp, N, Dest) \
419 if (Stp->file_left < (N)) { \
420 short_file(__LINE__, Stp, (N)); \
421 goto load_error; \
422 } else { \
423 int __n = (N); \
424 BeamInstr __result = 0; \
425 Stp->file_left -= (unsigned) __n; \
426 while (__n-- > 0) { \
427 __result = __result << 8 | *Stp->file_p++; \
428 } \
429 Dest = __result; \
430 }
431
432 #define GetByte(Stp, Dest) \
433 if ((Stp)->file_left < 1) { \
434 short_file(__LINE__, (Stp), 1); \
435 goto load_error; \
436 } else { \
437 Dest = *(Stp)->file_p++; \
438 (Stp)->file_left--; \
439 }
440
441 #define GetString(Stp, Dest, N) \
442 if (Stp->file_left < (N)) { \
443 short_file(__LINE__, Stp, (N)); \
444 goto load_error; \
445 } else { \
446 Dest = (Stp)->file_p; \
447 (Stp)->file_p += (N); \
448 (Stp)->file_left -= (N); \
449 }
450
451 #define GetAtom(Stp, Index, Dest) \
452 if ((Index) == 0) { \
453 LoadError1((Stp), "bad atom index 0 ([]) in %s", stp->file_name); \
454 } else if ((Index) < (Stp)->num_atoms) { \
455 Dest = (Stp)->atom[(Index)]; \
456 } else { \
457 LoadError2((Stp), "bad atom index %d in %s", (Index), stp->file_name); \
458 }
459
460 #ifdef DEBUG
461 # define GARBAGE 0xCC
462 # define DEBUG_INIT_GENOP(Dst) sys_memset(Dst, GARBAGE, sizeof(GenOp))
463 #else
464 # define DEBUG_INIT_GENOP(Dst)
465 #endif
466
467 #define NEW_GENOP(Stp, Dst) \
468 do { \
469 if ((Stp)->free_genop == NULL) { \
470 new_genop((Stp)); \
471 } \
472 Dst = (Stp)->free_genop; \
473 (Stp)->free_genop = (Stp)->free_genop->next; \
474 DEBUG_INIT_GENOP(Dst); \
475 (Dst)->a = (Dst)->def_args; \
476 } while (0)
477
478 #define FREE_GENOP(Stp, Genop) \
479 do { \
480 if ((Genop)->a != (Genop)->def_args) { \
481 erts_free(ERTS_ALC_T_LOADER_TMP, (Genop)->a); \
482 } \
483 (Genop)->next = (Stp)->free_genop; \
484 (Stp)->free_genop = (Genop); \
485 } while (0)
486
487 #define GENOP_ARITY(Genop, Arity) \
488 do { \
489 ASSERT((Genop)->a == (Genop)->def_args); \
490 (Genop)->arity = (Arity); \
491 (Genop)->a = erts_alloc(ERTS_ALC_T_LOADER_TMP, \
492 (Genop)->arity * sizeof(GenOpArg)); \
493 } while (0)
494
495
496 static void free_loader_state(Binary* magic);
497 static ErlHeapFragment* new_literal_fragment(Uint size);
498 static void free_literal_fragment(ErlHeapFragment*);
499 static int loader_state_dtor(Binary* magic);
500 #ifdef HIPE
501 static Eterm stub_insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
502 Eterm group_leader, Eterm module,
503 BeamCodeHeader* code_hdr, Uint size,
504 HipeModule *hipe_code);
505 #endif
506 static int init_iff_file(LoaderState* stp, byte* code, Uint size);
507 static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
508 Uint num_types);
509 static int verify_chunks(LoaderState* stp);
510 static int load_atom_table(LoaderState* stp, ErtsAtomEncoding enc);
511 static int load_import_table(LoaderState* stp);
512 static int read_export_table(LoaderState* stp);
513 static int is_bif(Eterm mod, Eterm func, unsigned arity);
514 static int read_lambda_table(LoaderState* stp);
515 static int read_literal_table(LoaderState* stp);
516 static int read_line_table(LoaderState* stp);
517 static int read_code_header(LoaderState* stp);
518 static void init_label(Label* lp);
519 static int load_code(LoaderState* stp);
520 static GenOp* gen_element(LoaderState* stp, GenOpArg Fail, GenOpArg Index,
521 GenOpArg Tuple, GenOpArg Dst);
522 static GenOp* gen_split_values(LoaderState* stp, GenOpArg S,
523 GenOpArg TypeFail, GenOpArg Fail,
524 GenOpArg Size, GenOpArg* Rest);
525 static GenOp* gen_select_val(LoaderState* stp, GenOpArg S, GenOpArg Fail,
526 GenOpArg Size, GenOpArg* Rest);
527 static GenOp* gen_select_literals(LoaderState* stp, GenOpArg S,
528 GenOpArg Fail, GenOpArg Size,
529 GenOpArg* Rest);
530 static GenOp* const_select_val(LoaderState* stp, GenOpArg S, GenOpArg Fail,
531 GenOpArg Size, GenOpArg* Rest);
532
533 static GenOp* gen_get_map_element(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
534 GenOpArg Size, GenOpArg* Rest);
535
536 static int freeze_code(LoaderState* stp);
537
538 static void final_touch(LoaderState* stp, struct erl_module_instance* inst_p);
539 static void short_file(int line, LoaderState* stp, unsigned needed);
540 static void load_printf(int line, LoaderState* context, char *fmt, ...);
541 static int transform_engine(LoaderState* st);
542 static void id_to_string(Uint id, char* s);
543 static void new_genop(LoaderState* stp);
544 static int get_tag_and_value(LoaderState* stp, Uint len_code,
545 unsigned tag, BeamInstr* result);
546 static int new_label(LoaderState* stp);
547 static void new_literal_patch(LoaderState* stp, int pos);
548 static void new_string_patch(LoaderState* stp, int pos);
549 static int find_literal(LoaderState* stp, Eterm needle, Uint *idx);
550 static Uint new_literal(LoaderState* stp, Eterm** hpp, Uint heap_size);
551 static int genopargcompare(GenOpArg* a, GenOpArg* b);
552 static Eterm get_module_info(Process* p, ErtsCodeIndex code_ix,
553 BeamCodeHeader*, Eterm module, Eterm what);
554 static Eterm exported_from_module(Process* p, ErtsCodeIndex code_ix,
555 Eterm mod);
556 static Eterm functions_in_module(Process* p, BeamCodeHeader*);
557 static Eterm nifs_in_module(Process* p, Eterm module);
558 static Eterm attributes_for_module(Process* p, BeamCodeHeader*);
559 static Eterm compilation_info_for_module(Process* p, BeamCodeHeader*);
560 static Eterm md5_of_module(Process* p, BeamCodeHeader*);
561 static Eterm has_native(BeamCodeHeader*);
562 static Eterm native_addresses(Process* p, BeamCodeHeader*);
563 static int safe_mul(UWord a, UWord b, UWord* resp);
564
565 static int must_swap_floats;
566
567 Uint erts_total_code_size;
568 /**********************************************************************/
569
init_load(void)570 void init_load(void)
571 {
572 FloatDef f;
573
574 erts_total_code_size = 0;
575
576 beam_catches_init();
577
578 f.fd = 1.0;
579 must_swap_floats = (f.fw[0] == 0);
580
581 erts_init_ranges();
582 }
583
584 static void
define_file(LoaderState * stp,char * name,int idx)585 define_file(LoaderState* stp, char* name, int idx)
586 {
587 stp->file_name = name;
588 stp->file_p = stp->chunks[idx].start;
589 stp->file_left = stp->chunks[idx].size;
590 }
591
592 Eterm
erts_preload_module(Process * c_p,ErtsProcLocks c_p_locks,Eterm group_leader,Eterm * modp,byte * code,Uint size)593 erts_preload_module(Process *c_p,
594 ErtsProcLocks c_p_locks,
595 Eterm group_leader, /* Group leader or NIL if none. */
596 Eterm* modp, /*
597 * Module name as an atom (NIL to not check).
598 * On return, contains the actual module name.
599 */
600 byte* code, /* Points to the code to load */
601 Uint size) /* Size of code to load. */
602 {
603 Binary* magic = erts_alloc_loader_state();
604 Eterm retval;
605
606 ASSERT(!erts_initialized);
607 retval = erts_prepare_loading(magic, c_p, group_leader, modp,
608 code, size);
609 if (retval != NIL) {
610 return retval;
611 }
612 return erts_finish_loading(magic, c_p, c_p_locks, modp);
613 }
614 /* #define LOAD_MEMORY_HARD_DEBUG 1*/
615
616 #if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
617 /* Requires allocators ERTS_ALLOC_UTIL_HARD_DEBUG also set in erl_alloc_util.h */
618 extern void check_allocators(void);
619 extern void check_allocated_block(Uint type, void *blk);
620 #define CHKALLOC() check_allocators()
621 #define CHKBLK(TYPE,BLK) if ((BLK) != NULL) check_allocated_block((TYPE),(BLK))
622 #else
623 #define CHKALLOC() /* nothing */
624 #define CHKBLK(TYPE,BLK) /* nothing */
625 #endif
626
627
628 Eterm
erts_prepare_loading(Binary * magic,Process * c_p,Eterm group_leader,Eterm * modp,byte * code,Uint unloaded_size)629 erts_prepare_loading(Binary* magic, Process *c_p, Eterm group_leader,
630 Eterm* modp, byte* code, Uint unloaded_size)
631 {
632 Eterm retval = am_badfile;
633 LoaderState* stp;
634
635 stp = ERTS_MAGIC_BIN_DATA(magic);
636 stp->module = *modp;
637 stp->group_leader = group_leader;
638
639 #if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
640 erts_fprintf(stderr,"Loading a module\n");
641 #endif
642
643 /*
644 * Scan the IFF file.
645 */
646
647 CHKALLOC();
648 CHKBLK(ERTS_ALC_T_CODE,stp->code);
649 if (!init_iff_file(stp, code, unloaded_size) ||
650 !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES) ||
651 !verify_chunks(stp)) {
652 goto load_error;
653 }
654
655 /*
656 * Read the header for the code chunk.
657 */
658
659 CHKBLK(ERTS_ALC_T_CODE,stp->code);
660 define_file(stp, "code chunk header", CODE_CHUNK);
661 if (!read_code_header(stp)) {
662 goto load_error;
663 }
664
665 /*
666 * Initialize code area.
667 */
668 stp->codev_size = 2048 + stp->num_functions;
669 stp->hdr = (BeamCodeHeader*) erts_alloc(ERTS_ALC_T_CODE,
670 (offsetof(BeamCodeHeader,functions)
671 + sizeof(BeamInstr) * stp->codev_size));
672
673 stp->hdr->num_functions = stp->num_functions;
674
675 /* Let the codev array start at functions[0] in order to index
676 * both function pointers and the loaded code itself that follows.
677 */
678 stp->codev = (BeamInstr*) &stp->hdr->functions;
679 stp->ci = stp->num_functions + 1;
680
681 stp->hdr->attr_ptr = NULL;
682 stp->hdr->attr_size = 0;
683 stp->hdr->attr_size_on_heap = 0;
684 stp->hdr->compile_ptr = NULL;
685 stp->hdr->compile_size = 0;
686 stp->hdr->compile_size_on_heap = 0;
687 stp->hdr->literal_area = NULL;
688 stp->hdr->md5_ptr = NULL;
689
690 /*
691 * Read the atom table.
692 */
693
694 CHKBLK(ERTS_ALC_T_CODE,stp->code);
695 if (stp->chunks[UTF8_ATOM_CHUNK].size > 0) {
696 define_file(stp, "utf8 atom table", UTF8_ATOM_CHUNK);
697 if (!load_atom_table(stp, ERTS_ATOM_ENC_UTF8)) {
698 goto load_error;
699 }
700 } else {
701 define_file(stp, "atom table", ATOM_CHUNK);
702 if (!load_atom_table(stp, ERTS_ATOM_ENC_LATIN1)) {
703 goto load_error;
704 }
705 }
706
707 /*
708 * Read the import table.
709 */
710
711 CHKBLK(ERTS_ALC_T_CODE,stp->code);
712 define_file(stp, "import table", IMP_CHUNK);
713 if (!load_import_table(stp)) {
714 goto load_error;
715 }
716
717 /*
718 * Read the lambda (fun) table.
719 */
720
721 CHKBLK(ERTS_ALC_T_CODE,stp->code);
722 if (stp->chunks[LAMBDA_CHUNK].size > 0) {
723 define_file(stp, "lambda (fun) table", LAMBDA_CHUNK);
724 if (!read_lambda_table(stp)) {
725 goto load_error;
726 }
727 }
728
729 /*
730 * Read the literal table.
731 */
732
733 CHKBLK(ERTS_ALC_T_CODE,stp->code);
734 if (stp->chunks[LITERAL_CHUNK].size > 0) {
735 define_file(stp, "literals table (constant pool)", LITERAL_CHUNK);
736 if (!read_literal_table(stp)) {
737 goto load_error;
738 }
739 }
740
741 /*
742 * Read the line table (if present).
743 */
744
745 CHKBLK(ERTS_ALC_T_CODE,stp->code);
746 if (stp->chunks[LINE_CHUNK].size > 0) {
747 define_file(stp, "line table", LINE_CHUNK);
748 if (!read_line_table(stp)) {
749 goto load_error;
750 }
751 }
752
753 /*
754 * Find out whether the code was compiled with OTP 20
755 * or higher.
756 */
757
758 stp->otp_20_or_higher = stp->chunks[UTF8_ATOM_CHUNK].size > 0;
759
760 /*
761 * Load the code chunk.
762 */
763
764 CHKBLK(ERTS_ALC_T_CODE,stp->code);
765 stp->file_name = "code chunk";
766 stp->file_p = stp->code_start;
767 stp->file_left = stp->code_size;
768 if (!load_code(stp)) {
769 goto load_error;
770 }
771 CHKBLK(ERTS_ALC_T_CODE,stp->code);
772 if (!freeze_code(stp)) {
773 goto load_error;
774 }
775
776
777 /*
778 * Read and validate the export table. (This must be done after
779 * loading the code, because it contains labels.)
780 */
781
782 CHKBLK(ERTS_ALC_T_CODE,stp->code);
783 define_file(stp, "export table", EXP_CHUNK);
784 if (!read_export_table(stp)) {
785 goto load_error;
786 }
787
788 /*
789 * Good so far.
790 */
791
792 retval = NIL;
793
794 load_error:
795 if (retval != NIL) {
796 free_loader_state(magic);
797 }
798 return retval;
799 }
800
801 Eterm
erts_finish_loading(Binary * magic,Process * c_p,ErtsProcLocks c_p_locks,Eterm * modp)802 erts_finish_loading(Binary* magic, Process* c_p,
803 ErtsProcLocks c_p_locks, Eterm* modp)
804 {
805 Eterm retval = NIL;
806 LoaderState* stp = ERTS_MAGIC_BIN_DATA(magic);
807 Module* mod_tab_p;
808 struct erl_module_instance* inst_p;
809 Uint size;
810
811 ERTS_LC_ASSERT(erts_initialized == 0 || erts_has_code_write_permission() ||
812 erts_thr_progress_is_blocking());
813 /*
814 * Make current code for the module old and insert the new code
815 * as current. This will fail if there already exists old code
816 * for the module.
817 */
818
819 mod_tab_p = erts_put_module(stp->module);
820 CHKBLK(ERTS_ALC_T_CODE,stp->code);
821 if (!stp->on_load) {
822 /*
823 * Normal case -- no -on_load() function.
824 */
825 retval = beam_make_current_old(c_p, c_p_locks, stp->module);
826 ASSERT(retval == NIL);
827 } else {
828 ErtsCodeIndex code_ix = erts_staging_code_ix();
829 Eterm module = stp->module;
830 int i, num_exps;
831
832 /*
833 * There is an -on_load() function. We will keep the current
834 * code, but we must turn off any tracing.
835 */
836 num_exps = export_list_size(code_ix);
837 for (i = 0; i < num_exps; i++) {
838 Export *ep = export_list(i, code_ix);
839 if (ep == NULL || ep->info.mfa.module != module) {
840 continue;
841 }
842 if (ep->addressv[code_ix] == ep->beam) {
843 if (BeamIsOpCode(ep->beam[0], op_apply_bif)) {
844 continue;
845 } else if (BeamIsOpCode(ep->beam[0], op_i_generic_breakpoint)) {
846 ERTS_LC_ASSERT(erts_thr_progress_is_blocking());
847 ASSERT(mod_tab_p->curr.num_traced_exports > 0);
848 erts_clear_export_break(mod_tab_p, &ep->info);
849 ep->addressv[code_ix] = (BeamInstr *) ep->beam[1];
850 ep->beam[1] = 0;
851 }
852 ASSERT(ep->beam[1] == 0);
853 }
854 }
855 ASSERT(mod_tab_p->curr.num_breakpoints == 0);
856 ASSERT(mod_tab_p->curr.num_traced_exports == 0);
857 }
858
859 /*
860 * Update module table.
861 */
862
863 size = stp->loaded_size;
864 erts_total_code_size += size;
865
866 if (!stp->on_load) {
867 inst_p = &mod_tab_p->curr;
868 } else {
869 mod_tab_p->on_load =
870 (struct erl_module_instance *)
871 erts_alloc(ERTS_ALC_T_PREPARED_CODE,
872 sizeof(struct erl_module_instance));
873 inst_p = mod_tab_p->on_load;
874 erts_module_instance_init(inst_p);
875 }
876
877 inst_p->code_hdr = stp->hdr;
878 inst_p->code_length = size;
879
880 /*
881 * Update ranges (used for finding a function from a PC value).
882 */
883
884 erts_update_ranges((BeamInstr*)inst_p->code_hdr, size);
885
886 /*
887 * Ready for the final touch: fixing the export table entries for
888 * exported and imported functions. This can't fail.
889 */
890
891 CHKBLK(ERTS_ALC_T_CODE,stp->code);
892 final_touch(stp, inst_p);
893
894 /*
895 * Loading succeded.
896 */
897 CHKBLK(ERTS_ALC_T_CODE,stp->code);
898 #if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
899 erts_fprintf(stderr,"Loaded %T\n",*modp);
900 #if 0
901 debug_dump_code(stp->code,stp->ci);
902 #endif
903 #endif
904 stp->hdr = NULL; /* Prevent code from being freed. */
905 stp->codev = NULL;
906 *modp = stp->module;
907
908 /*
909 * If there is an on_load function, signal an error to
910 * indicate that the on_load function must be run.
911 */
912 if (stp->on_load) {
913 retval = am_on_load;
914 }
915
916 free_loader_state(magic);
917 return retval;
918 }
919
920 Binary*
erts_alloc_loader_state(void)921 erts_alloc_loader_state(void)
922 {
923 LoaderState* stp;
924 Binary* magic;
925
926 magic = erts_create_magic_binary(sizeof(LoaderState),
927 loader_state_dtor);
928 erts_refc_inc(&magic->intern.refc, 1);
929 stp = ERTS_MAGIC_BIN_DATA(magic);
930 stp->bin = NULL;
931 stp->function = THE_NON_VALUE; /* Function not known yet */
932 stp->arity = 0;
933 stp->specific_op = -1;
934 stp->genop = NULL;
935 stp->atom = NULL;
936 stp->hdr = NULL;
937 stp->codev = NULL;
938 stp->labels = NULL;
939 stp->import = NULL;
940 stp->export = NULL;
941 stp->free_genop = NULL;
942 stp->genop_blocks = NULL;
943 stp->num_lambdas = 0;
944 stp->lambdas_allocated = sizeof(stp->def_lambdas)/sizeof(Lambda);
945 stp->lambdas = stp->def_lambdas;
946 stp->lambda_error = NULL;
947 stp->num_literals = 0;
948 stp->allocated_literals = 0;
949 stp->literals = 0;
950 stp->total_literal_size = 0;
951 stp->literal_patches = 0;
952 stp->string_patches = 0;
953 stp->may_load_nif = 0;
954 stp->on_load = 0;
955 stp->line_item = 0;
956 stp->line_instr = 0;
957 stp->func_line = 0;
958 stp->fname = 0;
959 return magic;
960 }
961
962 /*
963 * Return the module name (a tagged atom) for the prepared code
964 * in the magic binary, or NIL if the binary does not contain
965 * prepared code.
966 */
967 Eterm
erts_module_for_prepared_code(Binary * magic)968 erts_module_for_prepared_code(Binary* magic)
969 {
970 LoaderState* stp;
971
972 if (ERTS_MAGIC_BIN_DESTRUCTOR(magic) != loader_state_dtor) {
973 #ifdef HIPE
974 HipeLoaderState *hipe_stp;
975 if ((hipe_stp = hipe_get_loader_state(magic))
976 && hipe_stp->text_segment != 0) {
977 return hipe_stp->module;
978 }
979 #endif
980 return NIL;
981 }
982 stp = ERTS_MAGIC_BIN_DATA(magic);
983 if (stp->hdr != 0) {
984 return stp->module;
985 } else {
986 return NIL;
987 }
988 }
989
990 /*
991 * Return a non-zero value if the module has an on_load function,
992 * or 0 if it does not.
993 */
994
995 Eterm
erts_has_code_on_load(Binary * magic)996 erts_has_code_on_load(Binary* magic)
997 {
998 LoaderState* stp;
999
1000 if (ERTS_MAGIC_BIN_DESTRUCTOR(magic) != loader_state_dtor) {
1001 return NIL;
1002 }
1003 stp = ERTS_MAGIC_BIN_DATA(magic);
1004 return stp->on_load ? am_true : am_false;
1005 }
1006
1007 static void
free_loader_state(Binary * magic)1008 free_loader_state(Binary* magic)
1009 {
1010 loader_state_dtor(magic);
1011 erts_bin_release(magic);
1012 }
1013
new_literal_fragment(Uint size)1014 static ErlHeapFragment* new_literal_fragment(Uint size)
1015 {
1016 ErlHeapFragment* bp;
1017 bp = (ErlHeapFragment*) ERTS_HEAP_ALLOC(ERTS_ALC_T_PREPARED_CODE,
1018 ERTS_HEAP_FRAG_SIZE(size));
1019 ERTS_INIT_HEAP_FRAG(bp, size, size);
1020 return bp;
1021 }
1022
free_literal_fragment(ErlHeapFragment * bp)1023 static void free_literal_fragment(ErlHeapFragment* bp)
1024 {
1025 ASSERT(bp != NULL);
1026 do {
1027 ErlHeapFragment* next_bp = bp->next;
1028
1029 erts_cleanup_offheap(&bp->off_heap);
1030 ERTS_HEAP_FREE(ERTS_ALC_T_PREPARED_CODE, (void *) bp,
1031 ERTS_HEAP_FRAG_SIZE(bp->size));
1032 bp = next_bp;
1033 }while (bp != NULL);
1034 }
1035
1036 /*
1037 * This destructor function can safely be called multiple times.
1038 */
1039 static int
loader_state_dtor(Binary * magic)1040 loader_state_dtor(Binary* magic)
1041 {
1042 LoaderState* stp = ERTS_MAGIC_BIN_DATA(magic);
1043
1044 if (stp->bin != 0) {
1045 driver_free_binary(stp->bin);
1046 stp->bin = 0;
1047 }
1048 if (stp->hdr != 0) {
1049 if (stp->hdr->literal_area) {
1050 erts_release_literal_area(stp->hdr->literal_area);
1051 stp->hdr->literal_area = NULL;
1052 }
1053 erts_free(ERTS_ALC_T_CODE, stp->hdr);
1054 stp->hdr = 0;
1055 stp->codev = 0;
1056 }
1057 if (stp->labels != 0) {
1058 Uint num;
1059 for (num = 0; num < stp->num_labels; num++) {
1060 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->labels[num].patches);
1061 }
1062 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->labels);
1063 stp->labels = 0;
1064 }
1065 if (stp->atom != 0) {
1066 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->atom);
1067 stp->atom = 0;
1068 }
1069 if (stp->import != 0) {
1070 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->import);
1071 stp->import = 0;
1072 }
1073 if (stp->export != 0) {
1074 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->export);
1075 stp->export = 0;
1076 }
1077 if (stp->lambdas != stp->def_lambdas) {
1078 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->lambdas);
1079 stp->lambdas = stp->def_lambdas;
1080 }
1081 if (stp->literals != 0) {
1082 int i;
1083 for (i = 0; i < stp->num_literals; i++) {
1084 if (stp->literals[i].heap_frags != 0) {
1085 free_literal_fragment(stp->literals[i].heap_frags);
1086 stp->literals[i].heap_frags = 0;
1087 }
1088 }
1089 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->literals);
1090 stp->literals = 0;
1091 }
1092 while (stp->literal_patches != 0) {
1093 LiteralPatch* next = stp->literal_patches->next;
1094 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->literal_patches);
1095 stp->literal_patches = next;
1096 }
1097 while (stp->string_patches != 0) {
1098 StringPatch* next = stp->string_patches->next;
1099 erts_free(ERTS_ALC_T_PREPARED_CODE, (void *) stp->string_patches);
1100 stp->string_patches = next;
1101 }
1102
1103 if (stp->line_item != 0) {
1104 erts_free(ERTS_ALC_T_PREPARED_CODE, stp->line_item);
1105 stp->line_item = 0;
1106 }
1107
1108 if (stp->line_instr != 0) {
1109 erts_free(ERTS_ALC_T_PREPARED_CODE, stp->line_instr);
1110 stp->line_instr = 0;
1111 }
1112
1113 if (stp->func_line != 0) {
1114 erts_free(ERTS_ALC_T_PREPARED_CODE, stp->func_line);
1115 stp->func_line = 0;
1116 }
1117
1118 if (stp->fname != 0) {
1119 erts_free(ERTS_ALC_T_PREPARED_CODE, stp->fname);
1120 stp->fname = 0;
1121 }
1122
1123 /*
1124 * The following data items should have been freed earlier.
1125 */
1126
1127 ASSERT(stp->genop_blocks == 0);
1128 return 1;
1129 }
1130
1131 #ifdef HIPE
1132 static Eterm
stub_insert_new_code(Process * c_p,ErtsProcLocks c_p_locks,Eterm group_leader,Eterm module,BeamCodeHeader * code_hdr,Uint size,HipeModule * hipe_code)1133 stub_insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
1134 Eterm group_leader, Eterm module,
1135 BeamCodeHeader* code_hdr, Uint size,
1136 HipeModule *hipe_code)
1137 {
1138 Module* modp;
1139 Eterm retval;
1140
1141 if ((retval = beam_make_current_old(c_p, c_p_locks, module)) != NIL) {
1142 erts_dsprintf_buf_t *dsbufp = erts_create_logger_dsbuf();
1143 erts_dsprintf(dsbufp,
1144 "Module %T must be purged before loading\n",
1145 module);
1146 erts_send_error_to_logger(group_leader, dsbufp);
1147 return retval;
1148 }
1149
1150 /*
1151 * Update module table.
1152 */
1153
1154 erts_total_code_size += size;
1155 modp = erts_put_module(module);
1156 modp->curr.code_hdr = code_hdr;
1157 modp->curr.code_length = size;
1158 modp->curr.catches = BEAM_CATCHES_NIL; /* Will be filled in later. */
1159 DBG_TRACE_MFA(make_atom(modp->module), 0, 0, "insert_new_code "
1160 "first_hipe_ref = %p", hipe_code->first_hipe_ref);
1161 modp->curr.hipe_code = hipe_code;
1162
1163 /*
1164 * Update ranges (used for finding a function from a PC value).
1165 */
1166
1167 erts_update_ranges((BeamInstr*)modp->curr.code_hdr, size);
1168 return NIL;
1169 }
1170 #endif
1171
1172 static int
init_iff_file(LoaderState * stp,byte * code,Uint size)1173 init_iff_file(LoaderState* stp, byte* code, Uint size)
1174 {
1175 Uint form_id = MakeIffId('F', 'O', 'R', '1');
1176 Uint id;
1177 Uint count;
1178
1179 if (size < 4) {
1180 goto load_error;
1181 }
1182
1183 /*
1184 * Check if the module is compressed (or possibly invalid/corrupted).
1185 */
1186 if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) {
1187 stp->bin = (ErlDrvBinary *) erts_gzinflate_buffer((char*)code, size);
1188 if (stp->bin == NULL) {
1189 goto load_error;
1190 }
1191 code = (byte*)stp->bin->orig_bytes;
1192 size = stp->bin->orig_size;
1193 if (size < 4) {
1194 goto load_error;
1195 }
1196 }
1197
1198 /*
1199 * The binary must start with an IFF 'FOR1' chunk.
1200 */
1201 if (MakeIffId(code[0], code[1], code[2], code[3]) != form_id) {
1202 LoadError0(stp, "not a BEAM file: no IFF 'FOR1' chunk");
1203 }
1204
1205 /*
1206 * Initialize our "virtual file system".
1207 */
1208
1209 stp->file_name = "IFF header for Beam file";
1210 stp->file_p = code + 4;
1211 stp->file_left = size - 4;
1212
1213 /*
1214 * Retrieve the chunk size and verify it. If the size is equal to
1215 * or less than the size of the binary, it is ok and we will use it
1216 * as the limit for the logical file size.
1217 */
1218
1219 GetInt(stp, 4, count);
1220 if (count > stp->file_left) {
1221 LoadError2(stp, "form size %ld greater than size %ld of binary",
1222 count, stp->file_left);
1223 }
1224 stp->file_left = count;
1225
1226 /*
1227 * Verify that this is a BEAM file.
1228 */
1229
1230 GetInt(stp, 4, id);
1231 if (id != MakeIffId('B', 'E', 'A', 'M')) {
1232 LoadError0(stp, "not a BEAM file: IFF form type is not 'BEAM'");
1233 }
1234 return 1;
1235
1236 load_error:
1237 return 0;
1238 }
1239
1240 /*
1241 * Scan the IFF file. The header should have been verified by init_iff_file().
1242 */
1243 static int
scan_iff_file(LoaderState * stp,Uint * chunk_types,Uint num_types)1244 scan_iff_file(LoaderState* stp, Uint* chunk_types, Uint num_types)
1245 {
1246 Uint count;
1247 Uint id;
1248 int i;
1249
1250 /*
1251 * Initialize the chunks[] array in the state.
1252 */
1253
1254 for (i = 0; i < num_types; i++) {
1255 stp->chunks[i].start = NULL;
1256 stp->chunks[i].size = 0;
1257 }
1258
1259 /*
1260 * Now we can go ahead and read all chunks in the BEAM form.
1261 */
1262
1263 while (!EndOfFile(stp)) {
1264
1265 /*
1266 * Read the chunk id and verify that it contains ASCII characters.
1267 */
1268 GetInt(stp, 4, id);
1269 for (i = 0; i < 4; i++) {
1270 unsigned c = (id >> i*8) & 0xff;
1271 if (c < ' ' || c > 0x7E) {
1272 LoadError1(stp, "non-ascii garbage '%lx' instead of chunk type id",
1273 id);
1274 }
1275 }
1276
1277 /*
1278 * Read the count and verify it.
1279 */
1280
1281 GetInt(stp, 4, count);
1282 if (count > stp->file_left) {
1283 LoadError2(stp, "chunk size %ld for '%lx' greater than size %ld of binary",
1284 count, stp->file_left);
1285 }
1286
1287 /*
1288 * See if the chunk is useful for the loader.
1289 */
1290 for (i = 0; i < num_types; i++) {
1291 if (chunk_types[i] == id) {
1292 stp->chunks[i].start = stp->file_p;
1293 stp->chunks[i].size = count;
1294 break;
1295 }
1296 }
1297
1298 /*
1299 * Go on to the next chunk.
1300 */
1301 count = 4*((count+3)/4);
1302 stp->file_p += count;
1303 stp->file_left -= count;
1304 }
1305 return 1;
1306
1307 load_error:
1308 return 0;
1309 }
1310
1311 /*
1312 * Verify that all mandatory chunks are present and calculate
1313 * MD5 for the module.
1314 */
1315
1316 static int
verify_chunks(LoaderState * stp)1317 verify_chunks(LoaderState* stp)
1318 {
1319 int i;
1320 MD5_CTX context;
1321
1322 MD5Init(&context);
1323
1324 if (stp->chunks[UTF8_ATOM_CHUNK].start != NULL) {
1325 MD5Update(&context, stp->chunks[UTF8_ATOM_CHUNK].start, stp->chunks[UTF8_ATOM_CHUNK].size);
1326 } else if (stp->chunks[ATOM_CHUNK].start != NULL) {
1327 MD5Update(&context, stp->chunks[ATOM_CHUNK].start, stp->chunks[ATOM_CHUNK].size);
1328 } else {
1329 LoadError0(stp, "mandatory chunk of type 'Atom' or 'AtU8' not found\n");
1330 }
1331
1332 for (i = MIN_MANDATORY; i < MAX_MANDATORY; i++) {
1333 if (stp->chunks[i].start != NULL) {
1334 MD5Update(&context, stp->chunks[i].start, stp->chunks[i].size);
1335 } else {
1336 char sbuf[5];
1337
1338 id_to_string(chunk_types[i], sbuf);
1339 LoadError1(stp, "mandatory chunk of type '%s' not found\n", sbuf);
1340 }
1341 }
1342
1343 /*
1344 * If there is a lambda chunk, include parts of it in the MD5.
1345 */
1346 if (stp->chunks[LAMBDA_CHUNK].start != 0) {
1347 byte* start = stp->chunks[LAMBDA_CHUNK].start;
1348 Uint left = stp->chunks[LAMBDA_CHUNK].size;
1349
1350 /*
1351 * The idea here is to ignore the OldUniq field for the fun; it is
1352 * based on the old broken hash function, which can be different
1353 * on little endian and big endian machines.
1354 */
1355 if (left >= 4) {
1356 static byte zero[4];
1357 MD5Update(&context, start, 4);
1358 start += 4;
1359 left -= 4;
1360
1361 while (left >= 24) {
1362 /* Include: Function Arity Index NumFree */
1363 MD5Update(&context, start, 20);
1364 /* Set to zero: OldUniq */
1365 MD5Update(&context, zero, 4);
1366 start += 24;
1367 left -= 24;
1368 }
1369 }
1370 /* Can't happen for a correct 'FunT' chunk */
1371 if (left > 0) {
1372 MD5Update(&context, start, left);
1373 }
1374 }
1375
1376
1377 /*
1378 * If there is a literal chunk, include it in the MD5.
1379 */
1380 if (stp->chunks[LITERAL_CHUNK].start != 0) {
1381 MD5Update(&context, stp->chunks[LITERAL_CHUNK].start,
1382 stp->chunks[LITERAL_CHUNK].size);
1383 }
1384
1385 MD5Final(stp->mod_md5, &context);
1386 return 1;
1387
1388 load_error:
1389 return 0;
1390 }
1391
1392 static int
load_atom_table(LoaderState * stp,ErtsAtomEncoding enc)1393 load_atom_table(LoaderState* stp, ErtsAtomEncoding enc)
1394 {
1395 unsigned int i;
1396
1397 GetInt(stp, 4, stp->num_atoms);
1398 stp->num_atoms++;
1399 stp->atom = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1400 stp->num_atoms*sizeof(Eterm));
1401
1402 /*
1403 * Read all atoms.
1404 */
1405
1406 for (i = 1; i < stp->num_atoms; i++) {
1407 byte* atom;
1408 Uint n;
1409
1410 GetByte(stp, n);
1411 GetString(stp, atom, n);
1412 stp->atom[i] = erts_atom_put(atom, n, enc, 1);
1413 }
1414
1415 /*
1416 * Check the module name if a module name was given.
1417 */
1418
1419 if (is_nil(stp->module)) {
1420 stp->module = stp->atom[1];
1421 } else if (stp->atom[1] != stp->module) {
1422 char sbuf[MAX_ATOM_SZ_FROM_LATIN1];
1423 Atom* ap;
1424
1425 ap = atom_tab(atom_val(stp->atom[1]));
1426 sys_memcpy(sbuf, ap->name, ap->len);
1427 sbuf[ap->len] = '\0';
1428 LoadError1(stp, "module name in object code is %s", sbuf);
1429 }
1430
1431 return 1;
1432
1433 load_error:
1434 return 0;
1435 }
1436
1437 static int
load_import_table(LoaderState * stp)1438 load_import_table(LoaderState* stp)
1439 {
1440 unsigned int i;
1441
1442 GetInt(stp, 4, stp->num_imports);
1443 stp->import = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1444 stp->num_imports * sizeof(ImportEntry));
1445 for (i = 0; i < stp->num_imports; i++) {
1446 unsigned int n;
1447 Eterm mod;
1448 Eterm func;
1449 Uint arity;
1450 Export* e;
1451
1452 GetInt(stp, 4, n);
1453 if (n >= stp->num_atoms) {
1454 LoadError2(stp, "import entry %u: invalid atom number %u", i, n);
1455 }
1456 mod = stp->import[i].module = stp->atom[n];
1457 GetInt(stp, 4, n);
1458 if (n >= stp->num_atoms) {
1459 LoadError2(stp, "import entry %u: invalid atom number %u", i, n);
1460 }
1461 func = stp->import[i].function = stp->atom[n];
1462 GetInt(stp, 4, arity);
1463 if (arity > MAX_REG) {
1464 LoadError2(stp, "import entry %u: invalid arity %d", i, arity);
1465 }
1466 stp->import[i].arity = arity;
1467 stp->import[i].patches = 0;
1468 stp->import[i].bf = NULL;
1469
1470 /*
1471 * If the export entry refers to a BIF, get the pointer to
1472 * the BIF function.
1473 */
1474 if ((e = erts_active_export_entry(mod, func, arity)) != NULL) {
1475 if (BeamIsOpCode(e->beam[0], op_apply_bif)) {
1476 stp->import[i].bf = (BifFunction) e->beam[1];
1477 if (func == am_load_nif && mod == am_erlang && arity == 2) {
1478 stp->may_load_nif = 1;
1479 }
1480 }
1481 }
1482 }
1483 return 1;
1484
1485 load_error:
1486 return 0;
1487 }
1488
1489 static int
read_export_table(LoaderState * stp)1490 read_export_table(LoaderState* stp)
1491 {
1492 unsigned int i;
1493 BeamInstr* address;
1494
1495 GetInt(stp, 4, stp->num_exps);
1496 if (stp->num_exps > stp->num_functions) {
1497 LoadError2(stp, "%u functions exported; only %u functions defined",
1498 stp->num_exps, stp->num_functions);
1499 }
1500 stp->export
1501 = (ExportEntry *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1502 (stp->num_exps * sizeof(ExportEntry)));
1503
1504 for (i = 0; i < stp->num_exps; i++) {
1505 Uint n;
1506 Uint value;
1507 Eterm func;
1508 Uint arity;
1509
1510 GetInt(stp, 4, n);
1511 GetAtom(stp, n, func);
1512 stp->export[i].function = func;
1513 GetInt(stp, 4, arity);
1514 if (arity > MAX_REG) {
1515 LoadError2(stp, "export table entry %u: absurdly high arity %u", i, arity);
1516 }
1517 stp->export[i].arity = arity;
1518 GetInt(stp, 4, n);
1519 if (n >= stp->num_labels) {
1520 LoadError3(stp, "export table entry %u: invalid label %u (highest defined label is %u)", i, n, stp->num_labels);
1521 }
1522 value = stp->labels[n].value;
1523 if (value == 0) {
1524 LoadError2(stp, "export table entry %u: label %u not resolved", i, n);
1525 }
1526 stp->export[i].address = address = stp->codev + value;
1527
1528 /*
1529 * Find out if there is a BIF with the same name.
1530 */
1531
1532 if (!is_bif(stp->module, func, arity)) {
1533 continue;
1534 }
1535
1536 /*
1537 * This is a stub for a BIF.
1538 *
1539 * It should not be exported, and the information in its
1540 * func_info instruction should be invalidated so that it
1541 * can be filtered out by module_info(functions) and by
1542 * any other functions that walk through all local functions.
1543 */
1544
1545 if (stp->labels[n].num_patches > 0) {
1546 LoadError3(stp, "there are local calls to the stub for "
1547 "the BIF %T:%T/%d",
1548 stp->module, func, arity);
1549 }
1550 stp->export[i].address = NULL;
1551 address[-1] = 0;
1552 address[-2] = NIL;
1553 address[-3] = NIL;
1554 }
1555 return 1;
1556
1557 load_error:
1558 return 0;
1559 }
1560
1561
1562 static int
is_bif(Eterm mod,Eterm func,unsigned arity)1563 is_bif(Eterm mod, Eterm func, unsigned arity)
1564 {
1565 Export* e = erts_active_export_entry(mod, func, arity);
1566 if (e == NULL) {
1567 return 0;
1568 }
1569 if (! BeamIsOpCode(e->beam[0], op_apply_bif)) {
1570 return 0;
1571 }
1572 if (mod == am_erlang && func == am_apply && arity == 3) {
1573 /*
1574 * erlang:apply/3 is a special case -- it is implemented
1575 * as an instruction and it is OK to redefine it.
1576 */
1577 return 0;
1578 }
1579 return 1;
1580 }
1581
1582 static int
read_lambda_table(LoaderState * stp)1583 read_lambda_table(LoaderState* stp)
1584 {
1585 unsigned int i;
1586
1587 GetInt(stp, 4, stp->num_lambdas);
1588 if (stp->num_lambdas > stp->lambdas_allocated) {
1589 ASSERT(stp->lambdas == stp->def_lambdas);
1590 stp->lambdas_allocated = stp->num_lambdas;
1591 stp->lambdas = (Lambda *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1592 stp->num_lambdas * sizeof(Lambda));
1593 }
1594 for (i = 0; i < stp->num_lambdas; i++) {
1595 Uint n;
1596 Uint32 Index;
1597 Uint32 OldUniq;
1598 ErlFunEntry* fe;
1599 Uint arity;
1600
1601 GetInt(stp, 4, n); /* Function. */
1602 GetAtom(stp, n, stp->lambdas[i].function);
1603 GetInt(stp, 4, arity);
1604 if (arity > MAX_REG) {
1605 LoadError2(stp, "lambda entry %u: absurdly high arity %u", i, arity);
1606 }
1607 stp->lambdas[i].arity = arity;
1608 GetInt(stp, 4, n);
1609 if (n >= stp->num_labels) {
1610 LoadError3(stp, "lambda entry %u: invalid label %u (highest defined label is %u)",
1611 i, n, stp->num_labels);
1612 }
1613 stp->lambdas[i].label = n;
1614 GetInt(stp, 4, Index);
1615 GetInt(stp, 4, stp->lambdas[i].num_free);
1616 GetInt(stp, 4, OldUniq);
1617 fe = erts_put_fun_entry2(stp->module, OldUniq, i, stp->mod_md5,
1618 Index, arity-stp->lambdas[i].num_free);
1619 stp->lambdas[i].fe = fe;
1620 }
1621 return 1;
1622
1623 load_error:
1624 return 0;
1625 }
1626
1627
1628 static int
read_literal_table(LoaderState * stp)1629 read_literal_table(LoaderState* stp)
1630 {
1631 unsigned int i;
1632 uLongf uncompressed_sz;
1633 byte* uncompressed = 0;
1634
1635 GetInt(stp, 4, uncompressed_sz);
1636 uncompressed = erts_alloc(ERTS_ALC_T_TMP, uncompressed_sz);
1637 if (erl_zlib_uncompress(uncompressed, &uncompressed_sz,
1638 stp->file_p, stp->file_left) != Z_OK) {
1639 LoadError0(stp, "failed to uncompress literal table (constant pool)");
1640 }
1641 stp->file_p = uncompressed;
1642 stp->file_left = (unsigned) uncompressed_sz;
1643 GetInt(stp, 4, stp->num_literals);
1644 stp->literals = (Literal *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1645 stp->num_literals * sizeof(Literal));
1646 stp->allocated_literals = stp->num_literals;
1647
1648 for (i = 0; i < stp->num_literals; i++) {
1649 stp->literals[i].heap_frags = 0;
1650 }
1651
1652 for (i = 0; i < stp->num_literals; i++) {
1653 Uint sz;
1654 Sint heap_size;
1655 byte* p;
1656 Eterm val;
1657 ErtsHeapFactory factory;
1658
1659 GetInt(stp, 4, sz); /* Size of external term format. */
1660 GetString(stp, p, sz);
1661 if ((heap_size = erts_decode_ext_size(p, sz)) < 0) {
1662 LoadError1(stp, "literal %u: bad external format", i);
1663 }
1664
1665 if (heap_size > 0) {
1666 erts_factory_heap_frag_init(&factory,
1667 new_literal_fragment(heap_size));
1668 factory.alloc_type = ERTS_ALC_T_PREPARED_CODE;
1669 val = erts_decode_ext(&factory, &p, 0);
1670
1671 if (is_non_value(val)) {
1672 LoadError1(stp, "literal %u: bad external format", i);
1673 }
1674 erts_factory_close(&factory);
1675 stp->literals[i].heap_frags = factory.heap_frags;
1676 stp->total_literal_size += erts_used_frag_sz(factory.heap_frags);
1677 }
1678 else {
1679 erts_factory_dummy_init(&factory);
1680 val = erts_decode_ext(&factory, &p, 0);
1681 if (is_non_value(val)) {
1682 LoadError1(stp, "literal %u: bad external format", i);
1683 }
1684 ASSERT(is_immed(val));
1685 stp->literals[i].heap_frags = NULL;
1686 }
1687 stp->literals[i].term = val;
1688
1689 }
1690 erts_free(ERTS_ALC_T_TMP, uncompressed);
1691 return 1;
1692
1693 load_error:
1694 if (uncompressed) {
1695 erts_free(ERTS_ALC_T_TMP, uncompressed);
1696 }
1697 return 0;
1698 }
1699
1700 static int
read_line_table(LoaderState * stp)1701 read_line_table(LoaderState* stp)
1702 {
1703 unsigned version;
1704 ERTS_DECLARE_DUMMY(unsigned flags);
1705 unsigned int num_line_items;
1706 BeamInstr* lp;
1707 unsigned int i;
1708 BeamInstr fname_index;
1709 BeamInstr tag;
1710
1711 /*
1712 * If the emulator flag ignoring the line information was given,
1713 * return immediately.
1714 */
1715
1716 if (erts_no_line_info) {
1717 return 1;
1718 }
1719
1720 /*
1721 * Check version of line table.
1722 */
1723
1724 GetInt(stp, 4, version);
1725 if (version != 0) {
1726 /*
1727 * Wrong version. Silently ignore the line number chunk.
1728 */
1729 return 1;
1730 }
1731
1732 /*
1733 * Read the remaining header words. The flag word is reserved
1734 * for possible future use; for the moment we ignore it.
1735 */
1736 GetInt(stp, 4, flags);
1737 GetInt(stp, 4, stp->num_line_instrs);
1738 GetInt(stp, 4, num_line_items);
1739 GetInt(stp, 4, stp->num_fnames);
1740
1741 /*
1742 * Calculate space and allocate memory for the line item table.
1743 */
1744
1745 num_line_items++;
1746 lp = (BeamInstr *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1747 num_line_items * sizeof(BeamInstr));
1748 stp->line_item = lp;
1749 stp->num_line_items = num_line_items;
1750
1751 /*
1752 * The zeroth entry in the line item table is special.
1753 * It contains the undefined location.
1754 */
1755
1756 *lp++ = LINE_INVALID_LOCATION;
1757 num_line_items--;
1758
1759 /*
1760 * Read all the line items.
1761 */
1762
1763 stp->loc_size = stp->num_fnames ? 4 : 2;
1764 fname_index = 0;
1765 while (num_line_items-- > 0) {
1766 BeamInstr val;
1767 BeamInstr loc;
1768
1769 GetTagAndValue(stp, tag, val);
1770 if (tag == TAG_i) {
1771 if (IS_VALID_LOCATION(fname_index, val)) {
1772 loc = MAKE_LOCATION(fname_index, val);
1773 } else {
1774 /*
1775 * Too many files or huge line number. Silently invalidate
1776 * the location.
1777 */
1778 loc = LINE_INVALID_LOCATION;
1779 }
1780 *lp++ = loc;
1781 if (val > 0xFFFF) {
1782 stp->loc_size = 4;
1783 }
1784 } else if (tag == TAG_a) {
1785 if (val > stp->num_fnames) {
1786 LoadError2(stp, "file index overflow (%u/%u)",
1787 val, stp->num_fnames);
1788 }
1789 fname_index = val;
1790 num_line_items++;
1791 } else {
1792 LoadError1(stp, "bad tag '%c' (expected 'a' or 'i')",
1793 tag_to_letter[tag]);
1794 }
1795 }
1796
1797 /*
1798 * Read all filenames.
1799 */
1800
1801 if (stp->num_fnames != 0) {
1802 stp->fname = (Eterm *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1803 stp->num_fnames *
1804 sizeof(Eterm));
1805 for (i = 0; i < stp->num_fnames; i++) {
1806 byte* fname;
1807 Uint n;
1808
1809 GetInt(stp, 2, n);
1810 GetString(stp, fname, n);
1811 stp->fname[i] = erts_atom_put(fname, n, ERTS_ATOM_ENC_UTF8, 1);
1812 }
1813 }
1814
1815 /*
1816 * Allocate the arrays to be filled while code is being loaded.
1817 */
1818 stp->line_instr = (LineInstr *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1819 stp->num_line_instrs *
1820 sizeof(LineInstr));
1821 stp->current_li = 0;
1822 stp->func_line = (unsigned int *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1823 stp->num_functions *
1824 sizeof(int));
1825
1826 return 1;
1827
1828 load_error:
1829 return 0;
1830 }
1831
1832 static int
read_code_header(LoaderState * stp)1833 read_code_header(LoaderState* stp)
1834 {
1835 unsigned head_size;
1836 unsigned version;
1837 unsigned opcode_max;
1838 int i;
1839
1840 /*
1841 * Read size of sub-header for code information and from it calculate
1842 * where the code begins. Also, use the size to limit the file size
1843 * for header reading, so that we automatically get an error if the
1844 * size is set too small.
1845 */
1846
1847 GetInt(stp, 4, head_size);
1848 if (head_size > stp->file_left) {
1849 LoadError2(stp, "invalid code header size %u; bytes left %u",
1850 head_size, stp->file_left);
1851 }
1852 stp->code_start = stp->file_p + head_size;
1853 stp->code_size = stp->file_left - head_size;
1854 stp->file_left = head_size;
1855
1856 /*
1857 * Get and verify version of instruction set.
1858 */
1859
1860 GetInt(stp, 4, version);
1861 if (version != BEAM_FORMAT_NUMBER) {
1862 LoadError2(stp, "wrong instruction set %d; expected %d",
1863 version, BEAM_FORMAT_NUMBER);
1864 }
1865
1866 /*
1867 * Verify the number of the highest opcode used.
1868 */
1869 GetInt(stp, 4, opcode_max);
1870 if (opcode_max > MAX_GENERIC_OPCODE) {
1871 LoadError2(stp,
1872 "This BEAM file was compiled for a later version"
1873 " of the run-time system than " ERLANG_OTP_RELEASE ".\n"
1874 " To fix this, please recompile this module with an "
1875 ERLANG_OTP_RELEASE " compiler.\n"
1876 " (Use of opcode %d; this emulator supports "
1877 "only up to %d.)",
1878 opcode_max, MAX_GENERIC_OPCODE);
1879 }
1880
1881 GetInt(stp, 4, stp->num_labels);
1882 GetInt(stp, 4, stp->num_functions);
1883
1884 /*
1885 * Initialize label table.
1886 */
1887
1888 stp->labels = (Label *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1889 stp->num_labels * sizeof(Label));
1890 for (i = 0; i < stp->num_labels; i++) {
1891 init_label(&stp->labels[i]);
1892 }
1893
1894 stp->catches = 0;
1895 return 1;
1896
1897 load_error:
1898 return 0;
1899 }
1900
1901 #define VerifyTag(Stp, Actual, Expected) \
1902 if (Actual != Expected) { \
1903 LoadError2(Stp, "bad tag %d; expected %d", Actual, Expected); \
1904 } else {}
1905
1906 #define CodeNeed(w) do { \
1907 ASSERT(ci <= codev_size); \
1908 if (codev_size < ci+(w)) { \
1909 codev_size = 2*ci+(w); \
1910 stp->hdr = (BeamCodeHeader*) erts_realloc(ERTS_ALC_T_CODE, \
1911 (void *) stp->hdr, \
1912 (offsetof(BeamCodeHeader,functions) \
1913 + codev_size * sizeof(BeamInstr))); \
1914 code = stp->codev = (BeamInstr*) &stp->hdr->functions; \
1915 } \
1916 } while (0)
1917
1918 #define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm))))
1919
init_label(Label * lp)1920 static void init_label(Label* lp)
1921 {
1922 lp->value = 0;
1923 lp->looprec_targeted = 0;
1924 lp->num_patches = 0;
1925 lp->num_allocated = 4;
1926 lp->patches = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
1927 lp->num_allocated * sizeof(LabelPatch));
1928 }
1929
1930 static void
register_label_patch(LoaderState * stp,Uint label,Uint ci,Uint offset)1931 register_label_patch(LoaderState* stp, Uint label, Uint ci, Uint offset)
1932 {
1933 Label* lp;
1934
1935 ASSERT(label < stp->num_labels);
1936 lp = &stp->labels[label];
1937 if (lp->num_allocated <= lp->num_patches) {
1938 lp->num_allocated *= 2;
1939 lp->patches = erts_realloc(ERTS_ALC_T_PREPARED_CODE,
1940 (void *) lp->patches,
1941 lp->num_allocated * sizeof(LabelPatch));
1942 }
1943 lp->patches[lp->num_patches].pos = ci;
1944 lp->patches[lp->num_patches].offset = offset;
1945 lp->patches[lp->num_patches].packed = 0;
1946 lp->num_patches++;
1947 stp->codev[ci] = label;
1948 }
1949
1950 static int
load_code(LoaderState * stp)1951 load_code(LoaderState* stp)
1952 {
1953 int i;
1954 Uint ci;
1955 Uint last_instr_start; /* Needed for relative jumps */
1956 Uint last_func_start = 0; /* Needed by nif loading and line instructions */
1957 char* sign;
1958 int arg; /* Number of current argument. */
1959 int num_specific; /* Number of specific ops for current. */
1960 BeamInstr* code;
1961 int codev_size;
1962 int specific;
1963 Uint last_label = 0; /* Number of last label. */
1964 Uint function_number = 0;
1965 GenOp* last_op = NULL;
1966 GenOp** last_op_next = NULL;
1967 int arity;
1968 int retval = 1;
1969 #if defined(BEAM_WIDE_SHIFT)
1970 int num_trailing_f; /* Number of extra 'f' arguments in a list */
1971 #endif
1972
1973 /*
1974 * The size of the loaded func_info instruction is needed
1975 * by both the nif functionality and line instructions.
1976 */
1977 enum {
1978 FUNC_INFO_SZ = sizeof(ErtsCodeInfo) / sizeof(Eterm)
1979 };
1980
1981 code = stp->codev;
1982 codev_size = stp->codev_size;
1983 ci = stp->ci;
1984
1985 for (;;) {
1986 unsigned int new_op;
1987 GenOp* tmp_op;
1988
1989 ASSERT(ci <= codev_size);
1990
1991 get_next_instr:
1992 GetByte(stp, new_op);
1993 if (new_op >= NUM_GENERIC_OPS) {
1994 LoadError1(stp, "invalid opcode %u", new_op);
1995 }
1996 if (gen_opc[new_op].name[0] == '\0') {
1997 LoadError1(stp, "invalid opcode %u", new_op);
1998 }
1999
2000
2001 /*
2002 * Create a new generic operation and put it last in the chain.
2003 */
2004 if (last_op_next == NULL) {
2005 last_op_next = &(stp->genop);
2006 while (*last_op_next != NULL) {
2007 last_op_next = &(*last_op_next)->next;
2008 }
2009 }
2010
2011 NEW_GENOP(stp, last_op);
2012 last_op->next = NULL;
2013 last_op->op = new_op;
2014 *last_op_next = last_op;
2015 last_op_next = &(last_op->next);
2016 stp->specific_op = -1;
2017
2018 /*
2019 * Read all arguments for the current operation.
2020 */
2021
2022 arity = gen_opc[last_op->op].arity;
2023 last_op->arity = 0;
2024 ASSERT(arity <= MAX_OPARGS);
2025
2026 for (arg = 0; arg < arity; arg++) {
2027 GetTagAndValue(stp, last_op->a[arg].type, last_op->a[arg].val);
2028 switch (last_op->a[arg].type) {
2029 case TAG_i:
2030 case TAG_u:
2031 case TAG_q:
2032 case TAG_o:
2033 break;
2034 case TAG_x:
2035 if (last_op->a[arg].val >= MAX_REG) {
2036 LoadError1(stp, "invalid x register number: %u",
2037 last_op->a[arg].val);
2038 }
2039 break;
2040 case TAG_y:
2041 if (last_op->a[arg].val >= MAX_REG) {
2042 LoadError1(stp, "invalid y register number: %u",
2043 last_op->a[arg].val);
2044 }
2045 last_op->a[arg].val += CP_SIZE;
2046 break;
2047 case TAG_a:
2048 if (last_op->a[arg].val == 0) {
2049 last_op->a[arg].type = TAG_n;
2050 } else if (last_op->a[arg].val >= stp->num_atoms) {
2051 LoadError1(stp, "bad atom index: %d", last_op->a[arg].val);
2052 } else {
2053 last_op->a[arg].val = stp->atom[last_op->a[arg].val];
2054 }
2055 break;
2056 case TAG_f:
2057 if (last_op->a[arg].val == 0) {
2058 last_op->a[arg].type = TAG_p;
2059 } else if (last_op->a[arg].val >= stp->num_labels) {
2060 LoadError1(stp, "bad label: %d", last_op->a[arg].val);
2061 }
2062 break;
2063 case TAG_h:
2064 if (last_op->a[arg].val > 65535) {
2065 LoadError1(stp, "invalid range for character data type: %u",
2066 last_op->a[arg].val);
2067 }
2068 break;
2069 case TAG_z:
2070 {
2071 unsigned tag;
2072
2073 switch (last_op->a[arg].val) {
2074 case 0:
2075 /* Floating point number.
2076 * Not generated by the compiler in R16B and later.
2077 * (The literal pool is used instead.)
2078 */
2079 LoadError0(stp, "please re-compile this module with an "
2080 ERLANG_OTP_RELEASE " compiler");
2081 break;
2082 case 1: /* List. */
2083 if (arg+1 != arity) {
2084 LoadError0(stp, "list argument must be the last argument");
2085 }
2086 GetTagAndValue(stp, tag, last_op->a[arg].val);
2087 VerifyTag(stp, tag, TAG_u);
2088 last_op->a[arg].type = TAG_u;
2089 last_op->a =
2090 erts_alloc(ERTS_ALC_T_LOADER_TMP,
2091 (arity+last_op->a[arg].val)
2092 *sizeof(GenOpArg));
2093 sys_memcpy(last_op->a, last_op->def_args,
2094 arity*sizeof(GenOpArg));
2095 arity += last_op->a[arg].val;
2096 break;
2097 case 2: /* Float register. */
2098 GetTagAndValue(stp, tag, last_op->a[arg].val);
2099 VerifyTag(stp, tag, TAG_u);
2100 last_op->a[arg].type = TAG_l;
2101 break;
2102 case 3: /* Allocation list. */
2103 {
2104 BeamInstr n;
2105 BeamInstr type;
2106 BeamInstr val;
2107 BeamInstr words = 0;
2108
2109 GetTagAndValue(stp, tag, n);
2110 VerifyTag(stp, tag, TAG_u);
2111 while (n-- > 0) {
2112 GetTagAndValue(stp, tag, type);
2113 VerifyTag(stp, tag, TAG_u);
2114 GetTagAndValue(stp, tag, val);
2115 VerifyTag(stp, tag, TAG_u);
2116 switch (type) {
2117 case 0: /* Heap words */
2118 words += val;
2119 break;
2120 case 1:
2121 words += FLOAT_SIZE_OBJECT*val;
2122 break;
2123 default:
2124 LoadError1(stp, "alloc list: bad allocation "
2125 "descriptor %d", type);
2126 break;
2127 }
2128 }
2129 last_op->a[arg].type = TAG_u;
2130 last_op->a[arg].val = words;
2131 break;
2132 }
2133 case 4: /* Literal. */
2134 {
2135 BeamInstr val;
2136
2137 GetTagAndValue(stp, tag, val);
2138 VerifyTag(stp, tag, TAG_u);
2139 if (val >= stp->num_literals) {
2140 LoadError1(stp, "bad literal index %d", val);
2141 }
2142 last_op->a[arg].type = TAG_q;
2143 last_op->a[arg].val = val;
2144 break;
2145 }
2146 default:
2147 LoadError1(stp, "invalid extended tag %d",
2148 last_op->a[arg].val);
2149 break;
2150 }
2151 }
2152 break;
2153 default:
2154 LoadError1(stp, "bad tag %d", last_op->a[arg].type);
2155 break;
2156 }
2157 last_op->arity++;
2158 }
2159
2160 ASSERT(arity == last_op->arity);
2161
2162 do_transform:
2163 ASSERT(stp->genop != NULL);
2164 if (gen_opc[stp->genop->op].transform != -1) {
2165 if (stp->genop->next == NULL) {
2166 /*
2167 * Simple heuristic: Most transformations requires
2168 * at least two instructions, so make sure that
2169 * there are. That will reduce the number of
2170 * TE_SHORT_WINDOWs.
2171 */
2172 goto get_next_instr;
2173 }
2174 switch (transform_engine(stp)) {
2175 case TE_FAIL:
2176 /*
2177 * No transformation found. stp->genop != NULL and
2178 * last_op_next is still valid. Go ahead and load
2179 * the instruction.
2180 */
2181 break;
2182 case TE_OK:
2183 /*
2184 * Some transformation was applied. last_op_next is
2185 * no longer valid and stp->genop may be NULL.
2186 * Try to transform again.
2187 */
2188 if (stp->genop == NULL) {
2189 last_op_next = &stp->genop;
2190 goto get_next_instr;
2191 }
2192 last_op_next = NULL;
2193 goto do_transform;
2194 case TE_SHORT_WINDOW:
2195 /*
2196 * No transformation applied. stp->genop != NULL and
2197 * last_op_next is still valid. Fetch a new instruction
2198 * before trying the transformation again.
2199 */
2200 goto get_next_instr;
2201 }
2202 }
2203
2204 /*
2205 * From the collected generic instruction, find the specific
2206 * instruction.
2207 */
2208
2209 {
2210 Uint32 mask[3] = {0, 0, 0};
2211
2212 tmp_op = stp->genop;
2213 arity = gen_opc[tmp_op->op].arity;
2214 if (arity > 6) {
2215 LoadError0(stp, "no specific operation found (arity > 6)");
2216 }
2217 for (arg = 0; arg < arity; arg++) {
2218 mask[arg/2] |= ((Uint32)1 << (tmp_op->a[arg].type)) << ((arg%2)*16);
2219 }
2220 specific = gen_opc[tmp_op->op].specific;
2221 num_specific = gen_opc[tmp_op->op].num_specific;
2222 for (i = 0; i < num_specific; i++) {
2223 if (((opc[specific].mask[0] & mask[0]) == mask[0]) &&
2224 ((opc[specific].mask[1] & mask[1]) == mask[1]) &&
2225 ((opc[specific].mask[2] & mask[2]) == mask[2])) {
2226
2227 if (!opc[specific].involves_r) {
2228 break; /* No complications - match */
2229 }
2230
2231 /*
2232 * The specific operation uses the 'r' operand,
2233 * which is shorthand for x(0). Now things
2234 * get complicated. First we must check whether
2235 * all operands that should be of type 'r' use
2236 * x(0) (as opposed to some other X register).
2237 */
2238 for (arg = 0; arg < arity; arg++) {
2239 if (opc[specific].involves_r & (1 << arg) &&
2240 tmp_op->a[arg].type == TAG_x) {
2241 if (tmp_op->a[arg].val != 0) {
2242 break; /* Other X register than 0 */
2243 }
2244 }
2245 }
2246
2247 if (arg == arity) {
2248 /*
2249 * All 'r' operands use x(0) in the generic
2250 * operation. That means a match. Now we
2251 * will need to rewrite the generic instruction
2252 * to actually use 'r' instead of 'x(0)'.
2253 */
2254 for (arg = 0; arg < arity; arg++) {
2255 if (opc[specific].involves_r & (1 << arg) &&
2256 tmp_op->a[arg].type == TAG_x) {
2257 tmp_op->a[arg].type = TAG_r;
2258 }
2259 }
2260 break; /* Match */
2261 }
2262 }
2263 specific++;
2264 }
2265
2266 /*
2267 * No specific operation found.
2268 */
2269 if (i == num_specific) {
2270 stp->specific_op = -1;
2271 for (arg = 0; arg < tmp_op->arity; arg++) {
2272 /*
2273 * We'll give the error message here (instead of earlier)
2274 * to get a printout of the offending operation.
2275 */
2276 if (tmp_op->a[arg].type == TAG_h) {
2277 LoadError0(stp, "the character data type not supported");
2278 }
2279 }
2280
2281 /*
2282 * No specific operations and no transformations means that
2283 * the instruction is obsolete.
2284 */
2285 if (num_specific == 0 && gen_opc[tmp_op->op].transform == -1) {
2286 LoadError0(stp, "please re-compile this module with an "
2287 ERLANG_OTP_RELEASE " compiler ");
2288 }
2289
2290 /*
2291 * Some generic instructions should have a special
2292 * error message.
2293 */
2294 switch (stp->genop->op) {
2295 case genop_too_old_compiler_0:
2296 LoadError0(stp, "please re-compile this module with an "
2297 ERLANG_OTP_RELEASE " compiler");
2298 case genop_unsupported_guard_bif_3:
2299 {
2300 Eterm Mod = (Eterm) stp->genop->a[0].val;
2301 Eterm Name = (Eterm) stp->genop->a[1].val;
2302 Uint arity = (Uint) stp->genop->a[2].val;
2303 FREE_GENOP(stp, stp->genop);
2304 stp->genop = 0;
2305 LoadError3(stp, "unsupported guard BIF: %T:%T/%d\n",
2306 Mod, Name, arity);
2307 }
2308 default:
2309 LoadError0(stp, "no specific operation found");
2310 }
2311 }
2312
2313 stp->specific_op = specific;
2314 CodeNeed(opc[stp->specific_op].sz+16); /* Extra margin for packing */
2315 last_instr_start = ci + opc[stp->specific_op].adjust;
2316 code[ci++] = BeamOpCodeAddr(stp->specific_op);
2317 }
2318
2319 /*
2320 * Load the found specific operation.
2321 */
2322
2323 sign = opc[stp->specific_op].sign;
2324 ASSERT(sign != NULL);
2325 arg = 0;
2326 while (*sign) {
2327 Uint tag;
2328
2329 ASSERT(arg < stp->genop->arity);
2330 tag = stp->genop->a[arg].type;
2331 switch (*sign) {
2332 case 'r': /* x(0) */
2333 case 'n': /* Nil */
2334 VerifyTag(stp, tag_to_letter[tag], *sign);
2335 break;
2336 case 'x': /* x(N) */
2337 case 'y': /* y(N) */
2338 VerifyTag(stp, tag_to_letter[tag], *sign);
2339 code[ci++] = tmp_op->a[arg].val * sizeof(Eterm);
2340 break;
2341 case 'a': /* Tagged atom */
2342 VerifyTag(stp, tag_to_letter[tag], *sign);
2343 code[ci++] = tmp_op->a[arg].val;
2344 break;
2345 case 'i': /* Tagged integer */
2346 ASSERT(is_small(tmp_op->a[arg].val));
2347 VerifyTag(stp, tag_to_letter[tag], *sign);
2348 code[ci++] = tmp_op->a[arg].val;
2349 break;
2350 case 'c': /* Tagged constant */
2351 switch (tag) {
2352 case TAG_i:
2353 code[ci++] = (BeamInstr) make_small((Uint) tmp_op->a[arg].val);
2354 break;
2355 case TAG_a:
2356 code[ci++] = tmp_op->a[arg].val;
2357 break;
2358 case TAG_n:
2359 code[ci++] = NIL;
2360 break;
2361 case TAG_q:
2362 new_literal_patch(stp, ci);
2363 code[ci++] = tmp_op->a[arg].val;
2364 break;
2365 default:
2366 LoadError1(stp, "bad tag %d for tagged constant",
2367 tmp_op->a[arg].type);
2368 break;
2369 }
2370 break;
2371 case 's': /* Any source (tagged constant or register) */
2372 switch (tag) {
2373 case TAG_x:
2374 code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
2375 break;
2376 case TAG_y:
2377 code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
2378 break;
2379 case TAG_i:
2380 code[ci++] = (BeamInstr) make_small((Uint)tmp_op->a[arg].val);
2381 break;
2382 case TAG_a:
2383 code[ci++] = tmp_op->a[arg].val;
2384 break;
2385 case TAG_n:
2386 code[ci++] = NIL;
2387 break;
2388 case TAG_q:
2389 {
2390 BeamInstr val = tmp_op->a[arg].val;
2391 Eterm term = stp->literals[val].term;
2392 new_literal_patch(stp, ci);
2393 code[ci++] = val;
2394 switch (loader_tag(term)) {
2395 case LOADER_X_REG:
2396 case LOADER_Y_REG:
2397 LoadError1(stp, "the term '%T' would be confused "
2398 "with a register", term);
2399 }
2400 }
2401 break;
2402 default:
2403 LoadError1(stp, "bad tag %d for general source",
2404 tmp_op->a[arg].type);
2405 break;
2406 }
2407 break;
2408 case 'd': /* Destination (x(N), y(N) */
2409 case 'S': /* Source (x(N), y(N)) */
2410 switch (tag) {
2411 case TAG_x:
2412 code[ci++] = tmp_op->a[arg].val * sizeof(Eterm);
2413 break;
2414 case TAG_y:
2415 code[ci++] = tmp_op->a[arg].val * sizeof(Eterm) + 1;
2416 break;
2417 default:
2418 LoadError1(stp, "bad tag %d for destination",
2419 tmp_op->a[arg].type);
2420 break;
2421 }
2422 break;
2423 case 't': /* Small untagged integer (16 bits) -- can be packed. */
2424 case 'I': /* Untagged integer (32 bits) -- can be packed. */
2425 case 'W': /* Untagged integer or pointer (machine word). */
2426 #ifdef DEBUG
2427 switch (*sign) {
2428 case 't':
2429 if (tmp_op->a[arg].val >> 16 != 0) {
2430 load_printf(__LINE__, stp, "value %lu of type 't' does not fit in 16 bits",
2431 tmp_op->a[arg].val);
2432 ASSERT(0);
2433 }
2434 break;
2435 #ifdef ARCH_64
2436 case 'I':
2437 if (tmp_op->a[arg].val >> 32 != 0) {
2438 load_printf(__LINE__, stp, "value %lu of type 'I' does not fit in 32 bits",
2439 tmp_op->a[arg].val);
2440 ASSERT(0);
2441 }
2442 break;
2443 #endif
2444 }
2445 #endif
2446 VerifyTag(stp, tag, TAG_u);
2447 code[ci++] = tmp_op->a[arg].val;
2448 break;
2449 case 'A': /* Arity value. */
2450 VerifyTag(stp, tag, TAG_u);
2451 code[ci++] = make_arityval(tmp_op->a[arg].val);
2452 break;
2453 case 'f': /* Destination label */
2454 VerifyTag(stp, tag_to_letter[tag], *sign);
2455 register_label_patch(stp, tmp_op->a[arg].val, ci, -last_instr_start);
2456 ci++;
2457 break;
2458 case 'j': /* 'f' or 'p' */
2459 if (tag == TAG_p) {
2460 code[ci] = 0;
2461 } else if (tag == TAG_f) {
2462 register_label_patch(stp, tmp_op->a[arg].val, ci, -last_instr_start);
2463 } else {
2464 LoadError3(stp, "bad tag %d; expected %d or %d",
2465 tag, TAG_f, TAG_p);
2466 }
2467 ci++;
2468 break;
2469 case 'L': /* Define label */
2470 ci--; /* Remove label from loaded code */
2471 ASSERT(stp->specific_op == op_label_L);
2472 VerifyTag(stp, tag, TAG_u);
2473 last_label = tmp_op->a[arg].val;
2474 if (!(0 < last_label && last_label < stp->num_labels)) {
2475 LoadError2(stp, "invalid label num %u (0 < label < %u)",
2476 tmp_op->a[arg].val, stp->num_labels);
2477 }
2478 if (stp->labels[last_label].value != 0) {
2479 LoadError1(stp, "label %d defined more than once", last_label);
2480 }
2481 stp->labels[last_label].value = ci;
2482 break;
2483 case 'e': /* Export entry */
2484 VerifyTag(stp, tag, TAG_u);
2485 if (tmp_op->a[arg].val >= stp->num_imports) {
2486 LoadError1(stp, "invalid import table index %d", tmp_op->a[arg].val);
2487 }
2488 code[ci] = stp->import[tmp_op->a[arg].val].patches;
2489 stp->import[tmp_op->a[arg].val].patches = ci;
2490 ci++;
2491 break;
2492 case 'b':
2493 VerifyTag(stp, tag, TAG_u);
2494 i = tmp_op->a[arg].val;
2495 if (i >= stp->num_imports) {
2496 LoadError1(stp, "invalid import table index %d", i);
2497 }
2498 if (stp->import[i].bf == NULL) {
2499 LoadError1(stp, "not a BIF: import table index %d", i);
2500 }
2501 code[ci++] = (BeamInstr) stp->import[i].bf;
2502 break;
2503 case 'P': /* Byte offset into tuple or stack */
2504 case 'Q': /* Like 'P', but packable */
2505 VerifyTag(stp, tag, TAG_u);
2506 code[ci++] = (BeamInstr) ((tmp_op->a[arg].val+1) * sizeof(Eterm));
2507 break;
2508 case 'l': /* Floating point register. */
2509 VerifyTag(stp, tag_to_letter[tag], *sign);
2510 code[ci++] = tmp_op->a[arg].val * sizeof(FloatDef);
2511 break;
2512 case 'q': /* Literal */
2513 new_literal_patch(stp, ci);
2514 code[ci++] = tmp_op->a[arg].val;
2515 break;
2516 default:
2517 LoadError1(stp, "bad argument tag: %d", *sign);
2518 }
2519 sign++;
2520 arg++;
2521 }
2522
2523 /*
2524 * The packing engine.
2525 */
2526 if (opc[stp->specific_op].pack[0]) {
2527 char* prog; /* Program for packing engine. */
2528 struct pack_stack {
2529 BeamInstr instr;
2530 Uint* patch_pos;
2531 } stack[8]; /* Stack. */
2532 struct pack_stack* sp = stack; /* Points to next free position. */
2533 BeamInstr packed = 0; /* Accumulator for packed operations. */
2534 LabelPatch* packed_label = 0;
2535
2536 for (prog = opc[stp->specific_op].pack; *prog; prog++) {
2537 switch (*prog) {
2538 case 'g': /* Get operand and push on stack. */
2539 ci--;
2540 sp->instr = code[ci];
2541 sp->patch_pos = 0;
2542 sp++;
2543 break;
2544 case 'f': /* Get possible 'f' operand and push on stack. */
2545 {
2546 Uint w = code[--ci];
2547 sp->instr = w;
2548 sp->patch_pos = 0;
2549
2550 if (w != 0) {
2551 LabelPatch* lbl_p;
2552 int num_patches;
2553 int patch;
2554
2555 ASSERT(w < stp->num_labels);
2556 lbl_p = stp->labels[w].patches;
2557 num_patches = stp->labels[w].num_patches;
2558 for (patch = num_patches - 1; patch >= 0; patch--) {
2559 if (lbl_p[patch].pos == ci) {
2560 sp->patch_pos = &lbl_p[patch].pos;
2561 break;
2562 }
2563 }
2564 ASSERT(sp->patch_pos);
2565 }
2566 sp++;
2567 }
2568 break;
2569 case 'q': /* Get possible 'q' operand and push on stack. */
2570 {
2571 LiteralPatch* lp;
2572
2573 ci--;
2574 sp->instr = code[ci];
2575 sp->patch_pos = 0;
2576
2577 for (lp = stp->literal_patches;
2578 lp && lp->pos > ci-MAX_OPARGS;
2579 lp = lp->next) {
2580 if (lp->pos == ci) {
2581 sp->patch_pos = &lp->pos;
2582 break;
2583 }
2584 }
2585 sp++;
2586 }
2587 break;
2588 #ifdef ARCH_64
2589 case '1': /* Tightest shift (always 10 bits) */
2590 ci--;
2591 ASSERT((code[ci] & ~0x1FF8ull) == 0); /* Fits in 10 bits */
2592 packed = (packed << BEAM_TIGHTEST_SHIFT);
2593 packed |= code[ci] >> 3;
2594 if (packed_label) {
2595 packed_label->packed++;
2596 }
2597 break;
2598 #endif
2599 case '2': /* Tight shift (10 or 16 bits) */
2600 packed = (packed << BEAM_TIGHT_SHIFT) | code[--ci];
2601 if (packed_label) {
2602 packed_label->packed++;
2603 }
2604 break;
2605 case '3': /* Loose shift (16 bits) */
2606 packed = (packed << BEAM_LOOSE_SHIFT) | code[--ci];
2607 if (packed_label) {
2608 packed_label->packed++;
2609 }
2610 break;
2611 #ifdef ARCH_64
2612 case '4': /* Wide shift (32 bits) */
2613 {
2614 Uint w = code[--ci];
2615
2616 if (packed_label) {
2617 packed_label->packed++;
2618 }
2619
2620 /*
2621 * 'w' can handle both labels ('f' and 'j'), as well
2622 * as 'I'. Test whether this is a label.
2623 */
2624
2625 if (w < stp->num_labels) {
2626 /*
2627 * Probably a label. Look for patch pointing to this
2628 * position.
2629 */
2630 LabelPatch* lp = stp->labels[w].patches;
2631 int num_patches = stp->labels[w].num_patches;
2632 int patch;
2633 for (patch = num_patches - 1; patch >= 0; patch--) {
2634 if (lp[patch].pos == ci) {
2635 lp[patch].packed = 1;
2636 packed_label = &lp[patch];
2637 break;
2638 }
2639 }
2640 }
2641 packed = (packed << BEAM_WIDE_SHIFT) |
2642 (code[ci] & BEAM_WIDE_MASK);
2643 }
2644 break;
2645 #endif
2646 case 'p': /* Put instruction (from stack). */
2647 --sp;
2648 code[ci] = sp->instr;
2649 if (sp->patch_pos) {
2650 *sp->patch_pos = ci;
2651 }
2652 ci++;
2653 break;
2654 case 'P': /* Put packed operands (on the stack). */
2655 sp->instr = packed;
2656 sp->patch_pos = 0;
2657 if (packed_label) {
2658 sp->patch_pos = &packed_label->pos;
2659 packed_label = 0;
2660 }
2661 sp++;
2662 packed = 0;
2663 break;
2664 #if defined(ARCH_64) && defined(CODE_MODEL_SMALL)
2665 case '#': /* -1 */
2666 case '$': /* -2 */
2667 case '%': /* -3 */
2668 case '&': /* -4 */
2669 case '\'': /* -5 */
2670 case '(': /* -6 */
2671 /* Pack accumulator contents into instruction word. */
2672 {
2673 Sint pos = ci - (*prog - '#' + 1);
2674 /* Are the high 32 bits of the instruction word zero? */
2675 ASSERT((code[pos] & ~((1ull << BEAM_WIDE_SHIFT)-1)) == 0);
2676 code[pos] |= packed << BEAM_WIDE_SHIFT;
2677 if (packed_label) {
2678 ASSERT(packed_label->packed == 1);
2679 packed_label->pos = pos;
2680 packed_label->packed = 2;
2681 packed_label = 0;
2682 }
2683 packed >>= BEAM_WIDE_SHIFT;
2684 }
2685 break;
2686 #endif
2687 default:
2688 erts_exit(ERTS_ERROR_EXIT, "beam_load: invalid packing op: %c\n", *prog);
2689 }
2690 }
2691 ASSERT(sp == stack); /* Incorrect program? */
2692 }
2693
2694 /*
2695 * Load any list arguments using the primitive tags.
2696 */
2697
2698 #if defined(BEAM_WIDE_SHIFT)
2699 num_trailing_f = 0;
2700 #endif
2701 for ( ; arg < tmp_op->arity; arg++) {
2702 #if defined(BEAM_WIDE_SHIFT)
2703 if (tmp_op->a[arg].type == TAG_f) {
2704 num_trailing_f++;
2705 } else {
2706 num_trailing_f = 0;
2707 }
2708 #endif
2709 switch (tmp_op->a[arg].type) {
2710 case TAG_i:
2711 CodeNeed(1);
2712 code[ci++] = make_small(tmp_op->a[arg].val);
2713 break;
2714 case TAG_u:
2715 case TAG_a:
2716 case TAG_v:
2717 CodeNeed(1);
2718 code[ci++] = tmp_op->a[arg].val;
2719 break;
2720 case TAG_f:
2721 CodeNeed(1);
2722 register_label_patch(stp, tmp_op->a[arg].val, ci, -last_instr_start);
2723 ci++;
2724 break;
2725 case TAG_x:
2726 CodeNeed(1);
2727 code[ci++] = make_loader_x_reg(tmp_op->a[arg].val);
2728 break;
2729 case TAG_y:
2730 CodeNeed(1);
2731 code[ci++] = make_loader_y_reg(tmp_op->a[arg].val);
2732 break;
2733 case TAG_n:
2734 CodeNeed(1);
2735 code[ci++] = NIL;
2736 break;
2737 case TAG_q:
2738 CodeNeed(1);
2739 new_literal_patch(stp, ci);
2740 code[ci++] = tmp_op->a[arg].val;
2741 break;
2742 default:
2743 LoadError1(stp, "unsupported primitive type '%c'",
2744 tag_to_letter[tmp_op->a[arg].type]);
2745 }
2746 }
2747
2748 /*
2749 * If all the extra arguments were 'f' operands,
2750 * and the wordsize is 64 bits, pack two 'f' operands
2751 * into each word.
2752 */
2753
2754 #if defined(BEAM_WIDE_SHIFT)
2755 if (num_trailing_f >= 1) {
2756 Uint src_index = ci - num_trailing_f;
2757 Uint src_limit = ci;
2758 Uint dst_limit = src_index + (num_trailing_f+1)/2;
2759
2760 ci = src_index;
2761 while (ci < dst_limit) {
2762 Uint w[2];
2763 BeamInstr packed = 0;
2764 int wi;
2765
2766 w[0] = code[src_index];
2767 if (src_index+1 < src_limit) {
2768 w[1] = code[src_index+1];
2769 } else {
2770 w[1] = 0;
2771 }
2772 for (wi = 0; wi < 2; wi++) {
2773 Uint lbl = w[wi];
2774 LabelPatch* lp = stp->labels[lbl].patches;
2775 int num_patches = stp->labels[lbl].num_patches;
2776
2777 #if defined(WORDS_BIGENDIAN)
2778 packed <<= BEAM_WIDE_SHIFT;
2779 packed |= lbl & BEAM_WIDE_MASK;
2780 #else
2781 packed >>= BEAM_WIDE_SHIFT;
2782 packed |= lbl << BEAM_WIDE_SHIFT;
2783 #endif
2784 while (num_patches-- > 0) {
2785 if (lp->pos == src_index + wi) {
2786 lp->pos = ci;
2787 #if defined(WORDS_BIGENDIAN)
2788 lp->packed = 2 - wi;
2789 #else
2790 lp->packed = wi + 1;
2791 #endif
2792 break;
2793 }
2794 lp++;
2795 }
2796 }
2797 code[ci++] = packed;
2798 src_index += 2;
2799 }
2800 }
2801 #endif
2802
2803 /*
2804 * Handle a few special cases.
2805 */
2806 switch (stp->specific_op) {
2807 case op_i_func_info_IaaI:
2808 {
2809 Sint offset;
2810 if (function_number >= stp->num_functions) {
2811 LoadError1(stp, "too many functions in module (header said %u)",
2812 stp->num_functions);
2813 }
2814
2815 if (stp->may_load_nif) {
2816 const int finfo_ix = ci - FUNC_INFO_SZ;
2817 if (finfo_ix - last_func_start < BEAM_NIF_MIN_FUNC_SZ && last_func_start) {
2818 /* Must make room for call_nif op */
2819 int pad = BEAM_NIF_MIN_FUNC_SZ - (finfo_ix - last_func_start);
2820 ASSERT(pad > 0 && pad < BEAM_NIF_MIN_FUNC_SZ);
2821 CodeNeed(pad);
2822 sys_memmove(&code[finfo_ix+pad], &code[finfo_ix],
2823 FUNC_INFO_SZ*sizeof(BeamInstr));
2824 sys_memset(&code[finfo_ix], 0, pad*sizeof(BeamInstr));
2825 ci += pad;
2826 stp->labels[last_label].value += pad;
2827 }
2828 }
2829 last_func_start = ci;
2830
2831 /*
2832 * Save current offset of into the line instruction array.
2833 */
2834
2835 if (stp->func_line) {
2836 stp->func_line[function_number] = stp->current_li;
2837 }
2838
2839 /*
2840 * Save context for error messages.
2841 */
2842 stp->function = code[ci-2];
2843 stp->arity = code[ci-1];
2844
2845 /* When this assert is triggered, it is normally a sign that
2846 the size of the ops.tab i_func_info instruction is not
2847 the same as FUNC_INFO_SZ */
2848 ASSERT(stp->labels[last_label].value == ci - FUNC_INFO_SZ);
2849 offset = function_number;
2850 register_label_patch(stp, last_label, offset, 0);
2851 function_number++;
2852 if (stp->arity > MAX_ARG) {
2853 LoadError1(stp, "too many arguments: %d", stp->arity);
2854 }
2855 #ifdef DEBUG
2856 ASSERT(stp->labels[0].num_patches == 0); /* Should not be referenced. */
2857 for (i = 1; i < stp->num_labels; i++) {
2858 ASSERT(stp->labels[i].num_patches <= stp->labels[i].num_allocated);
2859 }
2860 #endif
2861 }
2862 break;
2863 case op_on_load:
2864 ci--; /* Get rid of the instruction */
2865
2866 /* Remember offset for the on_load function. */
2867 stp->on_load = ci;
2868 break;
2869 case op_bs_put_string_WW:
2870 case op_i_bs_match_string_xfWW:
2871 new_string_patch(stp, ci-1);
2872 break;
2873
2874 case op_catch_yf:
2875 /* code[ci-3] &&lb_catch_yf
2876 * code[ci-2] y-register offset in E
2877 * code[ci-1] label; index tagged as CATCH at runtime
2878 */
2879 code[ci-3] = stp->catches;
2880 stp->catches = ci-3;
2881 break;
2882
2883 case op_line_I:
2884 if (stp->line_item) {
2885 BeamInstr item = code[ci-1];
2886 BeamInstr loc;
2887 unsigned int li;
2888 if (item >= stp->num_line_items) {
2889 LoadError2(stp, "line instruction index overflow (%u/%u)",
2890 item, stp->num_line_items);
2891 }
2892 li = stp->current_li;
2893 if (li >= stp->num_line_instrs) {
2894 LoadError2(stp, "line instruction table overflow (%u/%u)",
2895 li, stp->num_line_instrs);
2896 }
2897 loc = stp->line_item[item];
2898
2899 if (ci - 2 == last_func_start) {
2900 /*
2901 * This line instruction directly follows the func_info
2902 * instruction. Its address must be adjusted to point to
2903 * func_info instruction.
2904 */
2905 stp->line_instr[li].pos = last_func_start - FUNC_INFO_SZ;
2906 stp->line_instr[li].loc = stp->line_item[item];
2907 stp->current_li++;
2908 } else if (li <= stp->func_line[function_number-1] ||
2909 stp->line_instr[li-1].loc != loc) {
2910 /*
2911 * Only store the location if it is different
2912 * from the previous location in the same function.
2913 */
2914 stp->line_instr[li].pos = ci - 2;
2915 stp->line_instr[li].loc = stp->line_item[item];
2916 stp->current_li++;
2917 }
2918 }
2919 ci -= 2; /* Get rid of the instruction */
2920 break;
2921
2922 /*
2923 * End of code found.
2924 */
2925 case op_int_code_end:
2926 if (function_number != stp->num_functions) {
2927 LoadError2(stp, "too few functions (%u) in module (header said %u)",
2928 function_number, stp->num_functions);
2929 }
2930 stp->codev_size = codev_size;
2931 stp->ci = ci;
2932 stp->function = THE_NON_VALUE;
2933 stp->genop = NULL;
2934 stp->specific_op = -1;
2935 retval = 1;
2936 goto cleanup;
2937 }
2938
2939 /*
2940 * Delete the generic instruction just loaded.
2941 */
2942 {
2943 GenOp* next = stp->genop->next;
2944 FREE_GENOP(stp, stp->genop);
2945 if ((stp->genop = next) == NULL) {
2946 last_op_next = &stp->genop;
2947 goto get_next_instr;
2948 }
2949 goto do_transform;
2950 }
2951 }
2952
2953 load_error:
2954 retval = 0;
2955
2956 cleanup:
2957 /*
2958 * Clean up everything that is not needed any longer.
2959 */
2960
2961 while (stp->genop_blocks) {
2962 GenOpBlock* next = stp->genop_blocks->next;
2963 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) stp->genop_blocks);
2964 stp->genop_blocks = next;
2965 }
2966 return retval;
2967 }
2968
2969 #define succ(St, X, Y) ((X).type == (Y).type && (X).val + 1 == (Y).val)
2970 #define succ2(St, X, Y) ((X).type == (Y).type && (X).val + 2 == (Y).val)
2971 #define succ3(St, X, Y) ((X).type == (Y).type && (X).val + 3 == (Y).val)
2972
2973 #ifdef NO_FPE_SIGNALS
2974 #define no_fpe_signals(St) 1
2975 #else
2976 #define no_fpe_signals(St) 0
2977 #endif
2978
2979 #define never(St) 0
2980
2981 static int
compiled_with_otp_20_or_higher(LoaderState * stp)2982 compiled_with_otp_20_or_higher(LoaderState* stp)
2983 {
2984 return stp->otp_20_or_higher;
2985 }
2986
2987 /*
2988 * Predicate that tests whether a jump table can be used.
2989 */
2990
2991 static int
use_jump_tab(LoaderState * stp,GenOpArg Size,GenOpArg * Rest)2992 use_jump_tab(LoaderState* stp, GenOpArg Size, GenOpArg* Rest)
2993 {
2994 Sint min, max;
2995 Sint i;
2996
2997 if (Size.val < 2 || Size.val % 2 != 0) {
2998 return 0;
2999 }
3000
3001 /* we may be called with sequences of tagged fixnums or atoms;
3002 return early in latter case, before we access the values */
3003 if (Rest[0].type != TAG_i || Rest[1].type != TAG_f)
3004 return 0;
3005 min = max = Rest[0].val;
3006 for (i = 2; i < Size.val; i += 2) {
3007 if (Rest[i].type != TAG_i || Rest[i+1].type != TAG_f) {
3008 return 0;
3009 }
3010 if (Rest[i].val < min) {
3011 min = Rest[i].val;
3012 } else if (max < Rest[i].val) {
3013 max = Rest[i].val;
3014 }
3015 }
3016
3017 return max - min <= Size.val;
3018 }
3019
3020 /*
3021 * Predicate to test whether all values in a table are either
3022 * floats or bignums.
3023 */
3024
3025 static int
floats_or_bignums(LoaderState * stp,GenOpArg Size,GenOpArg * Rest)3026 floats_or_bignums(LoaderState* stp, GenOpArg Size, GenOpArg* Rest)
3027 {
3028 int i;
3029
3030 if (Size.val < 2 || Size.val % 2 != 0) {
3031 return 0;
3032 }
3033
3034 for (i = 0; i < Size.val; i += 2) {
3035 if (Rest[i].type != TAG_q) {
3036 return 0;
3037 }
3038 if (Rest[i+1].type != TAG_f) {
3039 return 0;
3040 }
3041 }
3042
3043 return 1;
3044 }
3045
3046
3047 /*
3048 * Predicate to test whether all values in a table have a fixed size.
3049 */
3050
3051 static int
fixed_size_values(LoaderState * stp,GenOpArg Size,GenOpArg * Rest)3052 fixed_size_values(LoaderState* stp, GenOpArg Size, GenOpArg* Rest)
3053 {
3054 int i;
3055
3056 if (Size.val < 2 || Size.val % 2 != 0) {
3057 return 0;
3058 }
3059
3060 for (i = 0; i < Size.val; i += 2) {
3061 if (Rest[i+1].type != TAG_f)
3062 return 0;
3063 switch (Rest[i].type) {
3064 case TAG_a:
3065 case TAG_i:
3066 case TAG_v:
3067 break;
3068 case TAG_q:
3069 return is_float(stp->literals[Rest[i].val].term);
3070 default:
3071 return 0;
3072 }
3073 }
3074
3075 return 1;
3076 }
3077
3078 static int
mixed_types(LoaderState * stp,GenOpArg Size,GenOpArg * Rest)3079 mixed_types(LoaderState* stp, GenOpArg Size, GenOpArg* Rest)
3080 {
3081 int i;
3082 Uint type;
3083
3084 if (Size.val < 2 || Size.val % 2 != 0) {
3085 return 0;
3086 }
3087
3088 type = Rest[0].type;
3089 for (i = 0; i < Size.val; i += 2) {
3090 if (Rest[i].type != type)
3091 return 1;
3092 }
3093
3094 return 0;
3095 }
3096
3097 static int
is_killed_apply(LoaderState * stp,GenOpArg Reg,GenOpArg Live)3098 is_killed_apply(LoaderState* stp, GenOpArg Reg, GenOpArg Live)
3099 {
3100 return Reg.type == TAG_x && Live.type == TAG_u &&
3101 Live.val+2 <= Reg.val;
3102 }
3103
3104 static int
is_killed(LoaderState * stp,GenOpArg Reg,GenOpArg Live)3105 is_killed(LoaderState* stp, GenOpArg Reg, GenOpArg Live)
3106 {
3107 return Reg.type == TAG_x && Live.type == TAG_u &&
3108 Live.val <= Reg.val;
3109 }
3110
3111 /*
3112 * Generate an instruction for element/2.
3113 */
3114
3115 static GenOp*
gen_element(LoaderState * stp,GenOpArg Fail,GenOpArg Index,GenOpArg Tuple,GenOpArg Dst)3116 gen_element(LoaderState* stp, GenOpArg Fail, GenOpArg Index,
3117 GenOpArg Tuple, GenOpArg Dst)
3118 {
3119 GenOp* op;
3120
3121 NEW_GENOP(stp, op);
3122 op->arity = 4;
3123 op->next = NULL;
3124
3125 if (Index.type == TAG_i && Index.val > 0 &&
3126 Index.val <= ERTS_MAX_TUPLE_SIZE &&
3127 (Tuple.type == TAG_x || Tuple.type == TAG_y)) {
3128 op->op = genop_i_fast_element_4;
3129 op->a[0] = Tuple;
3130 op->a[1] = Fail;
3131 op->a[2].type = TAG_u;
3132 op->a[2].val = Index.val;
3133 op->a[3] = Dst;
3134 } else {
3135 op->op = genop_i_element_4;
3136 op->a[0] = Tuple;
3137 op->a[1] = Fail;
3138 op->a[2] = Index;
3139 op->a[3] = Dst;
3140 }
3141
3142 return op;
3143 }
3144
3145 static GenOp*
gen_bs_save(LoaderState * stp,GenOpArg Reg,GenOpArg Index)3146 gen_bs_save(LoaderState* stp, GenOpArg Reg, GenOpArg Index)
3147 {
3148 GenOp* op;
3149
3150 NEW_GENOP(stp, op);
3151 op->op = genop_i_bs_save2_2;
3152 op->arity = 2;
3153 op->a[0] = Reg;
3154 op->a[1] = Index;
3155 if (Index.type == TAG_u) {
3156 op->a[1].val = Index.val+1;
3157 } else if (Index.type == TAG_a && Index.val == am_start) {
3158 op->a[1].type = TAG_u;
3159 op->a[1].val = 0;
3160 }
3161 op->next = NULL;
3162 return op;
3163 }
3164
3165 static GenOp*
gen_bs_restore(LoaderState * stp,GenOpArg Reg,GenOpArg Index)3166 gen_bs_restore(LoaderState* stp, GenOpArg Reg, GenOpArg Index)
3167 {
3168 GenOp* op;
3169
3170 NEW_GENOP(stp, op);
3171 op->op = genop_i_bs_restore2_2;
3172 op->arity = 2;
3173 op->a[0] = Reg;
3174 op->a[1] = Index;
3175 if (Index.type == TAG_u) {
3176 op->a[1].val = Index.val+1;
3177 } else if (Index.type == TAG_a && Index.val == am_start) {
3178 op->a[1].type = TAG_u;
3179 op->a[1].val = 0;
3180 }
3181 op->next = NULL;
3182 return op;
3183 }
3184
3185 /*
3186 * Generate the fastest instruction to fetch an integer from a binary.
3187 */
3188
3189 static GenOp*
gen_get_integer2(LoaderState * stp,GenOpArg Fail,GenOpArg Ms,GenOpArg Live,GenOpArg Size,GenOpArg Unit,GenOpArg Flags,GenOpArg Dst)3190 gen_get_integer2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
3191 GenOpArg Size, GenOpArg Unit,
3192 GenOpArg Flags, GenOpArg Dst)
3193 {
3194 GenOp* op;
3195 UWord bits;
3196
3197 NEW_GENOP(stp, op);
3198
3199 NATIVE_ENDIAN(Flags);
3200 if (Size.type == TAG_i) {
3201 if (!safe_mul(Size.val, Unit.val, &bits)) {
3202 goto error;
3203 } else if ((Flags.val & BSF_SIGNED) != 0) {
3204 goto generic;
3205 } else if (bits == 8) {
3206 op->op = genop_i_bs_get_integer_8_3;
3207 op->arity = 3;
3208 op->a[0] = Ms;
3209 op->a[1] = Fail;
3210 op->a[2] = Dst;
3211 } else if (bits == 16 && (Flags.val & BSF_LITTLE) == 0) {
3212 op->op = genop_i_bs_get_integer_16_3;
3213 op->arity = 3;
3214 op->a[0] = Ms;
3215 op->a[1] = Fail;
3216 op->a[2] = Dst;
3217 #ifdef ARCH_64
3218 } else if (bits == 32 && (Flags.val & BSF_LITTLE) == 0) {
3219 op->op = genop_i_bs_get_integer_32_3;
3220 op->arity = 3;
3221 op->a[0] = Ms;
3222 op->a[1] = Fail;
3223 op->a[2] = Dst;
3224 #endif
3225 } else {
3226 generic:
3227 if (bits < SMALL_BITS) {
3228 op->op = genop_i_bs_get_integer_small_imm_5;
3229 op->arity = 5;
3230 op->a[0] = Ms;
3231 op->a[1].type = TAG_u;
3232 op->a[1].val = bits;
3233 op->a[2] = Fail;
3234 op->a[3] = Flags;
3235 op->a[4] = Dst;
3236 } else {
3237 op->op = genop_i_bs_get_integer_imm_6;
3238 op->arity = 6;
3239 op->a[0] = Ms;
3240 op->a[1].type = TAG_u;
3241 op->a[1].val = bits;
3242 op->a[2] = Live;
3243 op->a[3] = Fail;
3244 op->a[4] = Flags;
3245 op->a[5] = Dst;
3246 }
3247 }
3248 } else if (Size.type == TAG_q) {
3249 Eterm big = stp->literals[Size.val].term;
3250 Uint bigval;
3251
3252 if (!term_to_Uint(big, &bigval)) {
3253 error:
3254 op->op = genop_jump_1;
3255 op->arity = 1;
3256 op->a[0] = Fail;
3257 } else {
3258 if (!safe_mul(bigval, Unit.val, &bits)) {
3259 goto error;
3260 }
3261 goto generic;
3262 }
3263 } else {
3264 op->op = genop_i_bs_get_integer_6;
3265 op->arity = 6;
3266 op->a[0] = Fail;
3267 op->a[1] = Live;
3268 op->a[2].type = TAG_u;
3269 op->a[2].val = (Unit.val << 3) | Flags.val;
3270 op->a[3] = Ms;
3271 op->a[4] = Size;
3272 op->a[5] = Dst;
3273 op->next = NULL;
3274 return op;
3275 }
3276 op->next = NULL;
3277 return op;
3278 }
3279
3280 /*
3281 * Generate the fastest instruction to fetch a binary from a binary.
3282 */
3283
3284 static GenOp*
gen_get_binary2(LoaderState * stp,GenOpArg Fail,GenOpArg Ms,GenOpArg Live,GenOpArg Size,GenOpArg Unit,GenOpArg Flags,GenOpArg Dst)3285 gen_get_binary2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
3286 GenOpArg Size, GenOpArg Unit,
3287 GenOpArg Flags, GenOpArg Dst)
3288 {
3289 GenOp* op;
3290 NEW_GENOP(stp, op);
3291
3292 NATIVE_ENDIAN(Flags);
3293 if (Size.type == TAG_a && Size.val == am_all) {
3294 if (Ms.type == Dst.type && Ms.val == Dst.val) {
3295 op->op = genop_i_bs_get_binary_all_reuse_3;
3296 op->arity = 3;
3297 op->a[0] = Ms;
3298 op->a[1] = Fail;
3299 op->a[2] = Unit;
3300 } else {
3301 op->op = genop_i_bs_get_binary_all2_5;
3302 op->arity = 5;
3303 op->a[0] = Fail;
3304 op->a[1] = Ms;
3305 op->a[2] = Live;
3306 op->a[3] = Unit;
3307 op->a[4] = Dst;
3308 }
3309 } else if (Size.type == TAG_i) {
3310 op->op = genop_i_bs_get_binary_imm2_6;
3311 op->arity = 6;
3312 op->a[0] = Fail;
3313 op->a[1] = Ms;
3314 op->a[2] = Live;
3315 op->a[3].type = TAG_u;
3316 if (!safe_mul(Size.val, Unit.val, &op->a[3].val)) {
3317 goto error;
3318 }
3319 op->a[4] = Flags;
3320 op->a[5] = Dst;
3321 } else if (Size.type == TAG_q) {
3322 Eterm big = stp->literals[Size.val].term;
3323 Uint bigval;
3324
3325 if (!term_to_Uint(big, &bigval)) {
3326 error:
3327 op->op = genop_jump_1;
3328 op->arity = 1;
3329 op->a[0] = Fail;
3330 } else {
3331 op->op = genop_i_bs_get_binary_imm2_6;
3332 op->arity = 6;
3333 op->a[0] = Fail;
3334 op->a[1] = Ms;
3335 op->a[2] = Live;
3336 op->a[3].type = TAG_u;
3337 if (!safe_mul(bigval, Unit.val, &op->a[3].val)) {
3338 goto error;
3339 }
3340 op->a[4] = Flags;
3341 op->a[5] = Dst;
3342 }
3343 } else {
3344 op->op = genop_i_bs_get_binary2_6;
3345 op->arity = 6;
3346 op->a[0] = Fail;
3347 op->a[1] = Ms;
3348 op->a[2] = Live;
3349 op->a[3] = Size;
3350 op->a[4].type = TAG_u;
3351 op->a[4].val = (Unit.val << 3) | Flags.val;
3352 op->a[5] = Dst;
3353 }
3354 op->next = NULL;
3355 return op;
3356 }
3357
3358 /*
3359 * Predicate to test whether a binary construction is too big.
3360 */
3361
3362 static int
binary_too_big(LoaderState * stp,GenOpArg Size)3363 binary_too_big(LoaderState* stp, GenOpArg Size)
3364 {
3365 return Size.type == TAG_o ||
3366 (Size.type == TAG_u && ((Size.val >> (8*sizeof(Uint)-3)) != 0));
3367 }
3368
3369 static GenOp*
gen_put_binary(LoaderState * stp,GenOpArg Fail,GenOpArg Size,GenOpArg Unit,GenOpArg Flags,GenOpArg Src)3370 gen_put_binary(LoaderState* stp, GenOpArg Fail,GenOpArg Size,
3371 GenOpArg Unit, GenOpArg Flags, GenOpArg Src)
3372 {
3373 GenOp* op;
3374 NEW_GENOP(stp, op);
3375
3376 NATIVE_ENDIAN(Flags);
3377 if (Size.type == TAG_a && Size.val == am_all) {
3378 op->op = genop_i_new_bs_put_binary_all_3;
3379 op->arity = 3;
3380 op->a[0] = Fail;
3381 op->a[1] = Src;
3382 op->a[2] = Unit;
3383 } else if (Size.type == TAG_i) {
3384 op->op = genop_i_new_bs_put_binary_imm_3;
3385 op->arity = 3;
3386 op->a[0] = Fail;
3387 op->a[1].type = TAG_u;
3388 if (safe_mul(Size.val, Unit.val, &op->a[1].val)) {
3389 op->a[2] = Src;
3390 } else {
3391 op->op = genop_badarg_1;
3392 op->arity = 1;
3393 op->a[0] = Fail;
3394 }
3395 } else {
3396 op->op = genop_i_new_bs_put_binary_4;
3397 op->arity = 4;
3398 op->a[0] = Fail;
3399 op->a[1] = Size;
3400 op->a[2].type = TAG_u;
3401 op->a[2].val = (Unit.val << 3) | (Flags.val & 7);
3402 op->a[3] = Src;
3403 }
3404
3405 op->next = NULL;
3406 return op;
3407 }
3408
3409 static GenOp*
gen_put_integer(LoaderState * stp,GenOpArg Fail,GenOpArg Size,GenOpArg Unit,GenOpArg Flags,GenOpArg Src)3410 gen_put_integer(LoaderState* stp, GenOpArg Fail, GenOpArg Size,
3411 GenOpArg Unit, GenOpArg Flags, GenOpArg Src)
3412 {
3413 GenOp* op;
3414 NEW_GENOP(stp, op);
3415
3416 NATIVE_ENDIAN(Flags);
3417 /* Negative size must fail */
3418 if (Size.type == TAG_i) {
3419 op->op = genop_i_new_bs_put_integer_imm_4;
3420 op->arity = 4;
3421 op->a[0] = Fail;
3422 op->a[1].type = TAG_u;
3423 if (!safe_mul(Size.val, Unit.val, &op->a[1].val)) {
3424 error:
3425 op->op = genop_badarg_1;
3426 op->arity = 1;
3427 op->a[0] = Fail;
3428 op->next = NULL;
3429 return op;
3430 }
3431 op->a[1].val = Size.val * Unit.val;
3432 op->a[2].type = Flags.type;
3433 op->a[2].val = (Flags.val & 7);
3434 op->a[3] = Src;
3435 } else if (Size.type == TAG_q) {
3436 Eterm big = stp->literals[Size.val].term;
3437 Uint bigval;
3438
3439 if (!term_to_Uint(big, &bigval)) {
3440 goto error;
3441 } else {
3442 op->op = genop_i_new_bs_put_integer_imm_4;
3443 op->arity = 4;
3444 op->a[0] = Fail;
3445 op->a[1].type = TAG_u;
3446 op->a[1].val = bigval * Unit.val;
3447 op->a[2].type = Flags.type;
3448 op->a[2].val = (Flags.val & 7);
3449 op->a[3] = Src;
3450 }
3451 } else {
3452 op->op = genop_i_new_bs_put_integer_4;
3453 op->arity = 4;
3454 op->a[0] = Fail;
3455 op->a[1] = Size;
3456 op->a[2].type = TAG_u;
3457 op->a[2].val = (Unit.val << 3) | (Flags.val & 7);
3458 op->a[3] = Src;
3459 }
3460 op->next = NULL;
3461 return op;
3462 }
3463
3464 static GenOp*
gen_put_float(LoaderState * stp,GenOpArg Fail,GenOpArg Size,GenOpArg Unit,GenOpArg Flags,GenOpArg Src)3465 gen_put_float(LoaderState* stp, GenOpArg Fail, GenOpArg Size,
3466 GenOpArg Unit, GenOpArg Flags, GenOpArg Src)
3467 {
3468 GenOp* op;
3469 NEW_GENOP(stp, op);
3470
3471 NATIVE_ENDIAN(Flags);
3472 if (Size.type == TAG_i) {
3473 op->op = genop_i_new_bs_put_float_imm_4;
3474 op->arity = 4;
3475 op->a[0] = Fail;
3476 op->a[1].type = TAG_u;
3477 if (!safe_mul(Size.val, Unit.val, &op->a[1].val)) {
3478 op->op = genop_badarg_1;
3479 op->arity = 1;
3480 op->a[0] = Fail;
3481 } else {
3482 op->a[2] = Flags;
3483 op->a[3] = Src;
3484 }
3485 } else {
3486 op->op = genop_i_new_bs_put_float_4;
3487 op->arity = 4;
3488 op->a[0] = Fail;
3489 op->a[1] = Size;
3490 op->a[2].type = TAG_u;
3491 op->a[2].val = (Unit.val << 3) | (Flags.val & 7);
3492 op->a[3] = Src;
3493 }
3494 op->next = NULL;
3495 return op;
3496 }
3497
3498 /*
3499 * Generate an instruction to fetch a float from a binary.
3500 */
3501
3502 static GenOp*
gen_get_float2(LoaderState * stp,GenOpArg Fail,GenOpArg Ms,GenOpArg Live,GenOpArg Size,GenOpArg Unit,GenOpArg Flags,GenOpArg Dst)3503 gen_get_float2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
3504 GenOpArg Size, GenOpArg Unit, GenOpArg Flags, GenOpArg Dst)
3505 {
3506 GenOp* op;
3507 NEW_GENOP(stp, op);
3508
3509 NATIVE_ENDIAN(Flags);
3510 op->op = genop_i_bs_get_float2_6;
3511 op->arity = 6;
3512 op->a[0] = Fail;
3513 op->a[1] = Ms;
3514 op->a[2] = Live;
3515 op->a[3] = Size;
3516 op->a[4].type = TAG_u;
3517 op->a[4].val = (Unit.val << 3) | Flags.val;
3518 op->a[5] = Dst;
3519 op->next = NULL;
3520 return op;
3521 }
3522
3523 /*
3524 * Generate the fastest instruction for bs_skip_bits.
3525 */
3526
3527 static GenOp*
gen_skip_bits2(LoaderState * stp,GenOpArg Fail,GenOpArg Ms,GenOpArg Size,GenOpArg Unit,GenOpArg Flags)3528 gen_skip_bits2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms,
3529 GenOpArg Size, GenOpArg Unit, GenOpArg Flags)
3530 {
3531 GenOp* op;
3532
3533 NATIVE_ENDIAN(Flags);
3534 NEW_GENOP(stp, op);
3535 if (Size.type == TAG_a && Size.val == am_all) {
3536 op->op = genop_i_bs_skip_bits_all2_3;
3537 op->arity = 3;
3538 op->a[0] = Fail;
3539 op->a[1] = Ms;
3540 op->a[2] = Unit;
3541 } else if (Size.type == TAG_i) {
3542 op->op = genop_i_bs_skip_bits_imm2_3;
3543 op->arity = 3;
3544 op->a[0] = Fail;
3545 op->a[1] = Ms;
3546 op->a[2].type = TAG_u;
3547 if (!safe_mul(Size.val, Unit.val, &op->a[2].val)) {
3548 goto error;
3549 }
3550 } else if (Size.type == TAG_q) {
3551 Eterm big = stp->literals[Size.val].term;
3552 Uint bigval;
3553
3554 if (!term_to_Uint(big, &bigval)) {
3555 error:
3556 op->op = genop_jump_1;
3557 op->arity = 1;
3558 op->a[0] = Fail;
3559 } else {
3560 op->op = genop_i_bs_skip_bits_imm2_3;
3561 op->arity = 3;
3562 op->a[0] = Fail;
3563 op->a[1] = Ms;
3564 op->a[2].type = TAG_u;
3565 if (!safe_mul(bigval, Unit.val, &op->a[2].val)) {
3566 goto error;
3567 }
3568 }
3569 } else {
3570 op->op = genop_i_bs_skip_bits2_4;
3571 op->arity = 4;
3572 op->a[0] = Fail;
3573 op->a[1] = Ms;
3574 op->a[2] = Size;
3575 op->a[3] = Unit;
3576 }
3577 op->next = NULL;
3578 return op;
3579 }
3580
3581 static GenOp*
gen_increment(LoaderState * stp,GenOpArg Reg,GenOpArg Integer,GenOpArg Live,GenOpArg Dst)3582 gen_increment(LoaderState* stp, GenOpArg Reg, GenOpArg Integer,
3583 GenOpArg Live, GenOpArg Dst)
3584 {
3585 GenOp* op;
3586
3587 NEW_GENOP(stp, op);
3588 op->op = genop_i_increment_4;
3589 op->arity = 4;
3590 op->next = NULL;
3591 op->a[0] = Reg;
3592 op->a[1].type = TAG_u;
3593 op->a[1].val = Integer.val;
3594 op->a[2] = Live;
3595 op->a[3] = Dst;
3596 return op;
3597 }
3598
3599 static GenOp*
gen_increment_from_minus(LoaderState * stp,GenOpArg Reg,GenOpArg Integer,GenOpArg Live,GenOpArg Dst)3600 gen_increment_from_minus(LoaderState* stp, GenOpArg Reg, GenOpArg Integer,
3601 GenOpArg Live, GenOpArg Dst)
3602 {
3603 GenOp* op;
3604
3605 NEW_GENOP(stp, op);
3606 op->op = genop_i_increment_4;
3607 op->arity = 4;
3608 op->next = NULL;
3609 op->a[0] = Reg;
3610 op->a[1].type = TAG_u;
3611 op->a[1].val = -Integer.val;
3612 op->a[2] = Live;
3613 op->a[3] = Dst;
3614 return op;
3615 }
3616
3617 /*
3618 * Test whether the negation of the given number is small.
3619 */
3620 static int
negation_is_small(LoaderState * stp,GenOpArg Int)3621 negation_is_small(LoaderState* stp, GenOpArg Int)
3622 {
3623 /* Check for the rare case of overflow in BeamInstr (UWord) -> Sint
3624 * Cast to the correct type before using IS_SSMALL (Sint) */
3625 return Int.type == TAG_i &&
3626 !(Int.val & ~((((BeamInstr)1) << ((sizeof(Sint)*8)-1))-1)) &&
3627 IS_SSMALL(-((Sint)Int.val));
3628 }
3629
3630 /*
3631 * Mark this label.
3632 */
3633 static int
smp_mark_target_label(LoaderState * stp,GenOpArg L)3634 smp_mark_target_label(LoaderState* stp, GenOpArg L)
3635 {
3636 ASSERT(L.type == TAG_f);
3637 stp->labels[L.val].looprec_targeted = 1;
3638 return 1;
3639 }
3640
3641 /*
3642 * Test whether this label was targeted by a loop_rec/2 instruction.
3643 */
3644
3645 static int
smp_already_locked(LoaderState * stp,GenOpArg L)3646 smp_already_locked(LoaderState* stp, GenOpArg L)
3647 {
3648 ASSERT(L.type == TAG_u);
3649 return stp->labels[L.val].looprec_targeted;
3650 }
3651
3652 /*
3653 * Generate a timeout instruction for a literal timeout.
3654 */
3655
3656 static GenOp*
gen_literal_timeout(LoaderState * stp,GenOpArg Fail,GenOpArg Time)3657 gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
3658 {
3659 GenOp* op;
3660 Sint timeout;
3661
3662 NEW_GENOP(stp, op);
3663 op->op = genop_wait_timeout_unlocked_int_2;
3664 op->next = NULL;
3665 op->arity = 2;
3666 op->a[0].type = TAG_u;
3667 op->a[1] = Fail;
3668
3669 if (Time.type == TAG_i && (timeout = Time.val) >= 0 &&
3670 #if defined(ARCH_64)
3671 (timeout >> 32) == 0
3672 #else
3673 1
3674 #endif
3675 ) {
3676 op->a[0].val = timeout;
3677 #if !defined(ARCH_64)
3678 } else if (Time.type == TAG_q) {
3679 Eterm big;
3680
3681 big = stp->literals[Time.val].term;
3682 if (is_not_big(big)) {
3683 goto error;
3684 }
3685 if (big_arity(big) > 1 || big_sign(big)) {
3686 goto error;
3687 } else {
3688 Uint u;
3689 (void) term_to_Uint(big, &u);
3690 op->a[0].val = (BeamInstr) u;
3691 }
3692 #endif
3693 } else {
3694 #if !defined(ARCH_64)
3695 error:
3696 #endif
3697 op->op = genop_i_wait_error_0;
3698 op->arity = 0;
3699 }
3700 return op;
3701 }
3702
3703 static GenOp*
gen_literal_timeout_locked(LoaderState * stp,GenOpArg Fail,GenOpArg Time)3704 gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
3705 {
3706 GenOp* op;
3707 Sint timeout;
3708
3709 NEW_GENOP(stp, op);
3710 op->op = genop_wait_timeout_locked_int_2;
3711 op->next = NULL;
3712 op->arity = 2;
3713 op->a[0].type = TAG_u;
3714 op->a[1] = Fail;
3715
3716 if (Time.type == TAG_i && (timeout = Time.val) >= 0 &&
3717 #if defined(ARCH_64)
3718 (timeout >> 32) == 0
3719 #else
3720 1
3721 #endif
3722 ) {
3723 op->a[0].val = timeout;
3724 #if !defined(ARCH_64)
3725 } else if (Time.type == TAG_q) {
3726 Eterm big;
3727
3728 big = stp->literals[Time.val].term;
3729 if (is_not_big(big)) {
3730 goto error;
3731 }
3732 if (big_arity(big) > 1 || big_sign(big)) {
3733 goto error;
3734 } else {
3735 Uint u;
3736 (void) term_to_Uint(big, &u);
3737 op->a[0].val = (BeamInstr) u;
3738 }
3739 #endif
3740 } else {
3741 #if !defined(ARCH_64)
3742 error:
3743 #endif
3744 op->op = genop_i_wait_error_locked_0;
3745 op->arity = 0;
3746 }
3747 return op;
3748 }
3749
3750 /*
3751 * Tag the list of values with tuple arity tags.
3752 */
3753
3754 static GenOp*
gen_select_tuple_arity(LoaderState * stp,GenOpArg S,GenOpArg Fail,GenOpArg Size,GenOpArg * Rest)3755 gen_select_tuple_arity(LoaderState* stp, GenOpArg S, GenOpArg Fail,
3756 GenOpArg Size, GenOpArg* Rest)
3757
3758 {
3759 GenOp* op;
3760 GenOpArg *tmp;
3761 int arity = Size.val + 3;
3762 int size = Size.val / 2;
3763 int i, j, align = 0;
3764
3765 /*
3766 * Verify the validity of the list.
3767 */
3768
3769 if (Size.val % 2 != 0)
3770 return NULL;
3771 for (i = 0; i < Size.val; i += 2) {
3772 if (Rest[i].type != TAG_u || Rest[i+1].type != TAG_f) {
3773 return NULL;
3774 }
3775 }
3776
3777 /*
3778 * Use a special-cased instruction if there are only two values.
3779 */
3780 if (size == 2) {
3781 NEW_GENOP(stp, op);
3782 op->next = NULL;
3783 op->op = genop_i_select_tuple_arity2_4;
3784 GENOP_ARITY(op, arity - 1);
3785 op->a[0] = S;
3786 op->a[1] = Fail;
3787 op->a[2].type = TAG_u;
3788 op->a[2].val = Rest[0].val;
3789 op->a[3].type = TAG_u;
3790 op->a[3].val = Rest[2].val;
3791 op->a[4] = Rest[1];
3792 op->a[5] = Rest[3];
3793
3794 return op;
3795 }
3796
3797 /*
3798 * Generate the generic instruction.
3799 * Assumption:
3800 * Few different tuple arities to select on (fewer than 20).
3801 * Use linear scan approach.
3802 */
3803
3804 align = 1;
3805
3806 arity += 2*align;
3807 size += align;
3808
3809 NEW_GENOP(stp, op);
3810 op->next = NULL;
3811 op->op = genop_i_select_tuple_arity_3;
3812 GENOP_ARITY(op, arity);
3813 op->a[0] = S;
3814 op->a[1] = Fail;
3815 op->a[2].type = TAG_u;
3816 op->a[2].val = size;
3817
3818 tmp = (GenOpArg *) erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(GenOpArg)*(arity-2*align));
3819
3820 for (i = 3; i < arity - 2*align; i+=2) {
3821 tmp[i-3].type = TAG_v;
3822 tmp[i-3].val = make_arityval(Rest[i-3].val);
3823 tmp[i-2] = Rest[i-2];
3824 }
3825
3826 /*
3827 * Sort the values to make them useful for a sentinel search
3828 */
3829
3830 qsort(tmp, size - align, 2*sizeof(GenOpArg),
3831 (int (*)(const void *, const void *)) genopargcompare);
3832
3833 j = 3;
3834 for (i = 3; i < arity - 2*align; i += 2) {
3835 op->a[j] = tmp[i-3];
3836 op->a[j + size] = tmp[i-2];
3837 j++;
3838 }
3839
3840 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) tmp);
3841
3842 op->a[j].type = TAG_u;
3843 op->a[j].val = ~((BeamInstr)0);
3844 op->a[j+size] = Fail;
3845
3846 return op;
3847 }
3848
3849 /*
3850 * Split a list consisting of both small and bignumbers into two
3851 * select_val instructions.
3852 */
3853
3854 static GenOp*
gen_split_values(LoaderState * stp,GenOpArg S,GenOpArg TypeFail,GenOpArg Fail,GenOpArg Size,GenOpArg * Rest)3855 gen_split_values(LoaderState* stp, GenOpArg S, GenOpArg TypeFail,
3856 GenOpArg Fail, GenOpArg Size, GenOpArg* Rest)
3857
3858 {
3859 GenOp* op1;
3860 GenOp* op2;
3861 GenOp* label;
3862 GenOp* is_integer;
3863 int i;
3864
3865 ASSERT(Size.val >= 2 && Size.val % 2 == 0);
3866
3867 NEW_GENOP(stp, is_integer);
3868 is_integer->op = genop_is_integer_2;
3869 is_integer->arity = 2;
3870 is_integer->a[0] = TypeFail;
3871 is_integer->a[1] = S;
3872
3873 NEW_GENOP(stp, label);
3874 label->op = genop_label_1;
3875 label->arity = 1;
3876 label->a[0].type = TAG_u;
3877 label->a[0].val = new_label(stp);
3878
3879 NEW_GENOP(stp, op1);
3880 op1->op = genop_select_val_3;
3881 GENOP_ARITY(op1, 3 + Size.val);
3882 op1->arity = 3;
3883 op1->a[0] = S;
3884 op1->a[1].type = TAG_f;
3885 op1->a[1].val = label->a[0].val;
3886 op1->a[2].type = TAG_u;
3887 op1->a[2].val = 0;
3888
3889 NEW_GENOP(stp, op2);
3890 op2->op = genop_select_val_3;
3891 GENOP_ARITY(op2, 3 + Size.val);
3892 op2->arity = 3;
3893 op2->a[0] = S;
3894 op2->a[1] = Fail;
3895 op2->a[2].type = TAG_u;
3896 op2->a[2].val = 0;
3897
3898 /*
3899 * Split the list.
3900 */
3901
3902 ASSERT(Size.type == TAG_u);
3903 for (i = 0; i < Size.val; i += 2) {
3904 GenOp* op = (Rest[i].type == TAG_q) ? op2 : op1;
3905 int dst = 3 + op->a[2].val;
3906
3907 ASSERT(Rest[i+1].type == TAG_f);
3908 op->a[dst] = Rest[i];
3909 op->a[dst+1] = Rest[i+1];
3910 op->arity += 2;
3911 op->a[2].val += 2;
3912 }
3913 ASSERT(op1->a[2].val > 0);
3914 ASSERT(op2->a[2].val > 0);
3915
3916 /*
3917 * Order the instruction sequence appropriately.
3918 */
3919
3920 if (TypeFail.val == Fail.val) {
3921 /*
3922 * select_val L1 S ... (small numbers)
3923 * label L1
3924 * is_integer Fail S
3925 * select_val Fail S ... (bignums)
3926 */
3927 op1->next = label;
3928 label->next = is_integer;
3929 is_integer->next = op2;
3930 } else {
3931 /*
3932 * is_integer TypeFail S
3933 * select_val L1 S ... (small numbers)
3934 * label L1
3935 * select_val Fail S ... (bignums)
3936 */
3937 is_integer->next = op1;
3938 op1->next = label;
3939 label->next = op2;
3940 op1 = is_integer;
3941 }
3942 op2->next = NULL;
3943
3944 return op1;
3945 }
3946
3947 /*
3948 * Generate a jump table.
3949 */
3950
3951 static GenOp*
gen_jump_tab(LoaderState * stp,GenOpArg S,GenOpArg Fail,GenOpArg Size,GenOpArg * Rest)3952 gen_jump_tab(LoaderState* stp, GenOpArg S, GenOpArg Fail, GenOpArg Size, GenOpArg* Rest)
3953 {
3954 Sint min, max;
3955 Sint i;
3956 Sint size;
3957 Sint arity;
3958 int fixed_args;
3959 GenOp* op;
3960
3961 ASSERT(Size.val >= 2 && Size.val % 2 == 0);
3962
3963 /*
3964 * If there is only one choice, don't generate a jump table.
3965 */
3966 if (Size.val == 2) {
3967 GenOp* jump;
3968
3969 NEW_GENOP(stp, op);
3970 op->arity = 3;
3971 op->op = genop_is_ne_exact_3;
3972 op->a[0] = Rest[1];
3973 op->a[1] = S;
3974 op->a[2] = Rest[0];
3975
3976 NEW_GENOP(stp, jump);
3977 jump->next = NULL;
3978 jump->arity = 1;
3979 jump->op = genop_jump_1;
3980 jump->a[0] = Fail;
3981
3982 op->next = jump;
3983 return op;
3984 }
3985
3986 /*
3987 * Calculate the minimum and maximum values and size of jump table.
3988 */
3989
3990 ASSERT(Rest[0].type == TAG_i);
3991 min = max = Rest[0].val;
3992 for (i = 2; i < Size.val; i += 2) {
3993 ASSERT(Rest[i].type == TAG_i && Rest[i+1].type == TAG_f);
3994 if (Rest[i].val < min) {
3995 min = Rest[i].val;
3996 } else if (max < Rest[i].val) {
3997 max = Rest[i].val;
3998 }
3999 }
4000 size = max - min + 1;
4001
4002 /*
4003 * Allocate structure and fill in the fixed fields.
4004 */
4005
4006 NEW_GENOP(stp, op);
4007 op->next = NULL;
4008 if (min == 0) {
4009 op->op = genop_i_jump_on_val_zero_3;
4010 fixed_args = 3;
4011 } else {
4012 op->op = genop_i_jump_on_val_4;
4013 fixed_args = 4;
4014 }
4015 arity = fixed_args + size;
4016 GENOP_ARITY(op, arity);
4017 op->a[0] = S;
4018 op->a[1] = Fail;
4019 op->a[2].type = TAG_u;
4020 op->a[2].val = size;
4021 op->a[3].type = TAG_u;
4022 op->a[3].val = min;
4023
4024
4025 /*
4026 * Fill in the jump table.
4027 */
4028
4029 for (i = fixed_args; i < arity; i++) {
4030 op->a[i] = Fail;
4031 }
4032 for (i = 0; i < Size.val; i += 2) {
4033 Sint index;
4034 index = fixed_args+Rest[i].val-min;
4035 ASSERT(fixed_args <= index && index < arity);
4036 op->a[index] = Rest[i+1];
4037 }
4038 return op;
4039 }
4040
4041 /*
4042 * Compare function for qsort().
4043 */
4044
4045 static int
genopargcompare(GenOpArg * a,GenOpArg * b)4046 genopargcompare(GenOpArg* a, GenOpArg* b)
4047 {
4048 if (a->val < b->val)
4049 return -1;
4050 else if (a->val == b->val)
4051 return 0;
4052 else
4053 return 1;
4054 }
4055
4056 /*
4057 * Generate a select_val instruction. We know that a jump table
4058 * is not suitable, and that all values are of the same type
4059 * (integer or atoms).
4060 */
4061
4062 static GenOp*
gen_select_val(LoaderState * stp,GenOpArg S,GenOpArg Fail,GenOpArg Size,GenOpArg * Rest)4063 gen_select_val(LoaderState* stp, GenOpArg S, GenOpArg Fail,
4064 GenOpArg Size, GenOpArg* Rest)
4065 {
4066 GenOp* op;
4067 GenOpArg *tmp;
4068 int arity = Size.val + 3;
4069 int size = Size.val / 2;
4070 int i, j, align = 0;
4071
4072 if (size == 2) {
4073 /*
4074 * Use a special-cased instruction if there are only two values.
4075 */
4076
4077 NEW_GENOP(stp, op);
4078 op->next = NULL;
4079 op->op = genop_i_select_val2_4;
4080 GENOP_ARITY(op, arity - 1);
4081 op->a[0] = S;
4082 op->a[1] = Fail;
4083 op->a[2] = Rest[0];
4084 op->a[3] = Rest[2];
4085 op->a[4] = Rest[1];
4086 op->a[5] = Rest[3];
4087
4088 return op;
4089 }
4090
4091 if (size <= 10) {
4092 /* Use linear search. Reserve place for a sentinel. */
4093 align = 1;
4094 }
4095
4096 arity += 2*align;
4097 size += align;
4098
4099 NEW_GENOP(stp, op);
4100 op->next = NULL;
4101 op->op = (align == 0) ? genop_i_select_val_bins_3 : genop_i_select_val_lins_3;
4102 GENOP_ARITY(op, arity);
4103 op->a[0] = S;
4104 op->a[1] = Fail;
4105 op->a[2].type = TAG_u;
4106 op->a[2].val = size;
4107
4108 tmp = (GenOpArg *) erts_alloc(ERTS_ALC_T_LOADER_TMP, sizeof(GenOpArg)*(arity-2*align));
4109
4110 for (i = 3; i < arity - 2*align; i++) {
4111 tmp[i-3] = Rest[i-3];
4112 }
4113
4114 /*
4115 * Sort the values to make them useful for a binary or sentinel search.
4116 */
4117
4118 qsort(tmp, size - align, 2*sizeof(GenOpArg),
4119 (int (*)(const void *, const void *)) genopargcompare);
4120
4121 j = 3;
4122 for (i = 3; i < arity - 2*align; i += 2) {
4123 op->a[j] = tmp[i-3];
4124 op->a[j+size] = tmp[i-2];
4125 j++;
4126 }
4127
4128 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) tmp);
4129
4130 if (align) {
4131 /* Add sentinel for linear search. */
4132 op->a[j].type = TAG_u;
4133 op->a[j].val = ~((BeamInstr)0);
4134 op->a[j+size] = Fail;
4135 }
4136
4137 #ifdef DEBUG
4138 for (i = 0; i < size - 1; i++) {
4139 ASSERT(op->a[i+3].val <= op->a[i+4].val);
4140 }
4141 #endif
4142
4143 return op;
4144 }
4145
4146 /*
4147 * Generate a select_val instruction for big numbers.
4148 */
4149
4150 static GenOp*
gen_select_literals(LoaderState * stp,GenOpArg S,GenOpArg Fail,GenOpArg Size,GenOpArg * Rest)4151 gen_select_literals(LoaderState* stp, GenOpArg S, GenOpArg Fail,
4152 GenOpArg Size, GenOpArg* Rest)
4153 {
4154 GenOp* op;
4155 GenOp* jump;
4156 GenOp** prev_next = &op;
4157
4158 int i;
4159
4160 for (i = 0; i < Size.val; i += 2) {
4161 GenOp* op;
4162 ASSERT(Rest[i].type == TAG_q);
4163
4164 NEW_GENOP(stp, op);
4165 op->op = genop_is_ne_exact_3;
4166 op->arity = 3;
4167 op->a[0] = Rest[i+1];
4168 op->a[1] = S;
4169 op->a[2] = Rest[i];
4170 *prev_next = op;
4171 prev_next = &op->next;
4172 }
4173
4174 NEW_GENOP(stp, jump);
4175 jump->next = NULL;
4176 jump->op = genop_jump_1;
4177 jump->arity = 1;
4178 jump->a[0] = Fail;
4179 *prev_next = jump;
4180 return op;
4181 }
4182
4183
4184 /*
4185 * Replace a select_val instruction with a constant controlling expression
4186 * with a jump instruction.
4187 */
4188
4189 static GenOp*
const_select_val(LoaderState * stp,GenOpArg S,GenOpArg Fail,GenOpArg Size,GenOpArg * Rest)4190 const_select_val(LoaderState* stp, GenOpArg S, GenOpArg Fail,
4191 GenOpArg Size, GenOpArg* Rest)
4192 {
4193 GenOp* op;
4194 int i;
4195
4196 ASSERT(Size.type == TAG_u);
4197
4198 NEW_GENOP(stp, op);
4199 op->next = NULL;
4200 op->op = genop_jump_1;
4201 op->arity = 1;
4202
4203 /*
4204 * Search for a literal matching the controlling expression.
4205 */
4206
4207 switch (S.type) {
4208 case TAG_q:
4209 {
4210 Eterm expr = stp->literals[S.val].term;
4211 for (i = 0; i < Size.val; i += 2) {
4212 if (Rest[i].type == TAG_q) {
4213 Eterm term = stp->literals[Rest[i].val].term;
4214 if (eq(term, expr)) {
4215 ASSERT(Rest[i+1].type == TAG_f);
4216 op->a[0] = Rest[i+1];
4217 return op;
4218 }
4219 }
4220 }
4221 }
4222 break;
4223 case TAG_i:
4224 case TAG_a:
4225 for (i = 0; i < Size.val; i += 2) {
4226 if (Rest[i].val == S.val && Rest[i].type == S.type) {
4227 ASSERT(Rest[i+1].type == TAG_f);
4228 op->a[0] = Rest[i+1];
4229 return op;
4230 }
4231 }
4232 break;
4233 }
4234
4235 /*
4236 * No match. Use the failure label.
4237 */
4238
4239 op->a[0] = Fail;
4240 return op;
4241 }
4242
4243 static GenOp*
gen_make_fun2(LoaderState * stp,GenOpArg idx)4244 gen_make_fun2(LoaderState* stp, GenOpArg idx)
4245 {
4246 ErlFunEntry* fe;
4247 GenOp* op;
4248
4249 if (idx.val >= stp->num_lambdas) {
4250 stp->lambda_error = "missing or short chunk 'FunT'";
4251 fe = 0;
4252 } else {
4253 fe = stp->lambdas[idx.val].fe;
4254 }
4255
4256 NEW_GENOP(stp, op);
4257 op->op = genop_i_make_fun_2;
4258 op->arity = 2;
4259 op->a[0].type = TAG_u;
4260 op->a[0].val = (BeamInstr) fe;
4261 op->a[1].type = TAG_u;
4262 op->a[1].val = stp->lambdas[idx.val].num_free;
4263 op->next = NULL;
4264 return op;
4265 }
4266
4267 static GenOp*
translate_gc_bif(LoaderState * stp,GenOp * op,GenOpArg Bif)4268 translate_gc_bif(LoaderState* stp, GenOp* op, GenOpArg Bif)
4269 {
4270 const ErtsGcBif* p;
4271 BifFunction bf;
4272
4273 bf = stp->import[Bif.val].bf;
4274 for (p = erts_gc_bifs; p->bif != 0; p++) {
4275 if (p->bif == bf) {
4276 op->a[1].type = TAG_u;
4277 op->a[1].val = (BeamInstr) p->gc_bif;
4278 return op;
4279 }
4280 }
4281
4282 op->op = genop_unsupported_guard_bif_3;
4283 op->arity = 3;
4284 op->a[0].type = TAG_a;
4285 op->a[0].val = stp->import[Bif.val].module;
4286 op->a[1].type = TAG_a;
4287 op->a[1].val = stp->import[Bif.val].function;
4288 op->a[2].type = TAG_u;
4289 op->a[2].val = stp->import[Bif.val].arity;
4290 return op;
4291 }
4292
4293 /*
4294 * Rewrite gc_bifs with one parameter (the common case).
4295 */
4296 static GenOp*
gen_guard_bif1(LoaderState * stp,GenOpArg Fail,GenOpArg Live,GenOpArg Bif,GenOpArg Src,GenOpArg Dst)4297 gen_guard_bif1(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
4298 GenOpArg Src, GenOpArg Dst)
4299 {
4300 GenOp* op;
4301
4302 NEW_GENOP(stp, op);
4303 op->next = NULL;
4304 op->op = genop_i_gc_bif1_5;
4305 op->arity = 5;
4306 op->a[0] = Fail;
4307 /* op->a[1] is set by translate_gc_bif() */
4308 op->a[2] = Src;
4309 op->a[3] = Live;
4310 op->a[4] = Dst;
4311 return translate_gc_bif(stp, op, Bif);
4312 }
4313
4314 /*
4315 * This is used by the ops.tab rule that rewrites gc_bifs with two parameters.
4316 */
4317 static GenOp*
gen_guard_bif2(LoaderState * stp,GenOpArg Fail,GenOpArg Live,GenOpArg Bif,GenOpArg S1,GenOpArg S2,GenOpArg Dst)4318 gen_guard_bif2(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
4319 GenOpArg S1, GenOpArg S2, GenOpArg Dst)
4320 {
4321 GenOp* op;
4322
4323 NEW_GENOP(stp, op);
4324 op->next = NULL;
4325 op->op = genop_i_gc_bif2_6;
4326 op->arity = 6;
4327 op->a[0] = Fail;
4328 /* op->a[1] is set by translate_gc_bif() */
4329 op->a[2] = Live;
4330 op->a[3] = S1;
4331 op->a[4] = S2;
4332 op->a[5] = Dst;
4333 return translate_gc_bif(stp, op, Bif);
4334 }
4335
4336 /*
4337 * This is used by the ops.tab rule that rewrites gc_bifs with three parameters.
4338 */
4339 static GenOp*
gen_guard_bif3(LoaderState * stp,GenOpArg Fail,GenOpArg Live,GenOpArg Bif,GenOpArg S1,GenOpArg S2,GenOpArg S3,GenOpArg Dst)4340 gen_guard_bif3(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
4341 GenOpArg S1, GenOpArg S2, GenOpArg S3, GenOpArg Dst)
4342 {
4343 GenOp* op;
4344
4345 NEW_GENOP(stp, op);
4346 op->next = NULL;
4347 op->op = genop_ii_gc_bif3_7;
4348 op->arity = 7;
4349 op->a[0] = Fail;
4350 /* op->a[1] is set by translate_gc_bif() */
4351 op->a[2] = Live;
4352 op->a[3] = S1;
4353 op->a[4] = S2;
4354 op->a[5] = S3;
4355 op->a[6] = Dst;
4356 return translate_gc_bif(stp, op, Bif);
4357 }
4358
4359 static GenOp*
tuple_append_put5(LoaderState * stp,GenOpArg Arity,GenOpArg Dst,GenOpArg * Puts,GenOpArg S1,GenOpArg S2,GenOpArg S3,GenOpArg S4,GenOpArg S5)4360 tuple_append_put5(LoaderState* stp, GenOpArg Arity, GenOpArg Dst,
4361 GenOpArg* Puts, GenOpArg S1, GenOpArg S2, GenOpArg S3,
4362 GenOpArg S4, GenOpArg S5)
4363 {
4364 GenOp* op;
4365 int arity = Arity.val; /* Arity of tuple, not the instruction */
4366 int i;
4367
4368 NEW_GENOP(stp, op);
4369 op->next = NULL;
4370 GENOP_ARITY(op, arity+2+5);
4371 op->op = genop_i_put_tuple_2;
4372 op->a[0] = Dst;
4373 op->a[1].type = TAG_u;
4374 op->a[1].val = arity + 5;
4375 for (i = 0; i < arity; i++) {
4376 op->a[i+2] = Puts[i];
4377 }
4378 op->a[arity+2] = S1;
4379 op->a[arity+3] = S2;
4380 op->a[arity+4] = S3;
4381 op->a[arity+5] = S4;
4382 op->a[arity+6] = S5;
4383 return op;
4384 }
4385
4386 static GenOp*
tuple_append_put(LoaderState * stp,GenOpArg Arity,GenOpArg Dst,GenOpArg * Puts,GenOpArg S)4387 tuple_append_put(LoaderState* stp, GenOpArg Arity, GenOpArg Dst,
4388 GenOpArg* Puts, GenOpArg S)
4389 {
4390 GenOp* op;
4391 int arity = Arity.val; /* Arity of tuple, not the instruction */
4392 int i;
4393
4394 NEW_GENOP(stp, op);
4395 op->next = NULL;
4396 GENOP_ARITY(op, arity+2+1);
4397 op->op = genop_i_put_tuple_2;
4398 op->a[0] = Dst;
4399 op->a[1].type = TAG_u;
4400 op->a[1].val = arity + 1;
4401 for (i = 0; i < arity; i++) {
4402 op->a[i+2] = Puts[i];
4403 }
4404 op->a[arity+2] = S;
4405 return op;
4406 }
4407
4408 /*
4409 * Predicate to test whether the given literal is a map.
4410 */
4411
4412 static int
literal_is_map(LoaderState * stp,GenOpArg Lit)4413 literal_is_map(LoaderState* stp, GenOpArg Lit)
4414 {
4415 Eterm term;
4416
4417 ASSERT(Lit.type == TAG_q);
4418 term = stp->literals[Lit.val].term;
4419 return is_map(term);
4420 }
4421
4422 /*
4423 * Predicate to test whether all of the given new small map keys are literals
4424 */
4425 static int
is_small_map_literal_keys(LoaderState * stp,GenOpArg Size,GenOpArg * Rest)4426 is_small_map_literal_keys(LoaderState* stp, GenOpArg Size, GenOpArg* Rest)
4427 {
4428 if (Size.val > MAP_SMALL_MAP_LIMIT) {
4429 return 0;
4430 }
4431
4432 /*
4433 * Operations with non-literals have always only one key.
4434 */
4435 if (Size.val != 2) {
4436 return 1;
4437 }
4438
4439 switch (Rest[0].type) {
4440 case TAG_a:
4441 case TAG_i:
4442 case TAG_n:
4443 case TAG_q:
4444 return 1;
4445 default:
4446 return 0;
4447 }
4448 }
4449
4450 static GenOp*
gen_new_small_map_lit(LoaderState * stp,GenOpArg Dst,GenOpArg Live,GenOpArg Size,GenOpArg * Rest)4451 gen_new_small_map_lit(LoaderState* stp, GenOpArg Dst, GenOpArg Live,
4452 GenOpArg Size, GenOpArg* Rest)
4453 {
4454 unsigned size = Size.val;
4455 Uint lit;
4456 unsigned i;
4457 GenOp* op;
4458 GenOpArg* dst;
4459 Eterm* hp;
4460 Eterm* tmp;
4461 Eterm* thp;
4462 Eterm keys;
4463
4464 NEW_GENOP(stp, op);
4465 GENOP_ARITY(op, 3 + size/2);
4466 op->next = NULL;
4467 op->op = genop_i_new_small_map_lit_3;
4468
4469 tmp = thp = erts_alloc(ERTS_ALC_T_LOADER_TMP, (1 + size/2) * sizeof(*tmp));
4470 keys = make_tuple(thp);
4471 *thp++ = make_arityval(size/2);
4472
4473 dst = op->a+3;
4474
4475 for (i = 0; i < size; i += 2) {
4476 switch (Rest[i].type) {
4477 case TAG_a:
4478 *thp++ = Rest[i].val;
4479 ASSERT(is_atom(Rest[i].val));
4480 break;
4481 case TAG_i:
4482 *thp++ = make_small(Rest[i].val);
4483 break;
4484 case TAG_n:
4485 *thp++ = NIL;
4486 break;
4487 case TAG_q:
4488 *thp++ = stp->literals[Rest[i].val].term;
4489 break;
4490 }
4491 *dst++ = Rest[i + 1];
4492 }
4493
4494 if (!find_literal(stp, keys, &lit)) {
4495 lit = new_literal(stp, &hp, 1 + size/2);
4496 sys_memcpy(hp, tmp, (1 + size/2) * sizeof(*tmp));
4497 }
4498 erts_free(ERTS_ALC_T_LOADER_TMP, tmp);
4499
4500 op->a[0] = Dst;
4501 op->a[1] = Live;
4502 op->a[2].type = TAG_q;
4503 op->a[2].val = lit;
4504
4505 return op;
4506 }
4507
4508 /*
4509 * Predicate to test whether the given literal is an empty map.
4510 */
4511
4512 static int
is_empty_map(LoaderState * stp,GenOpArg Lit)4513 is_empty_map(LoaderState* stp, GenOpArg Lit)
4514 {
4515 Eterm term;
4516
4517 if (Lit.type != TAG_q) {
4518 return 0;
4519 }
4520 term = stp->literals[Lit.val].term;
4521 return is_flatmap(term) && flatmap_get_size(flatmap_val(term)) == 0;
4522 }
4523
4524 /*
4525 * Predicate to test whether the given literal is an export.
4526 */
4527 static int
literal_is_export(LoaderState * stp,GenOpArg Lit)4528 literal_is_export(LoaderState* stp, GenOpArg Lit)
4529 {
4530 Eterm term;
4531
4532 ASSERT(Lit.type == TAG_q);
4533 term = stp->literals[Lit.val].term;
4534 return is_export(term);
4535 }
4536
4537 /*
4538 * Pseudo predicate map_key_sort that will sort the Rest operand for
4539 * map instructions as a side effect.
4540 */
4541
4542 typedef struct SortGenOpArg {
4543 Eterm term; /* Term to use for comparing */
4544 GenOpArg arg; /* Original data */
4545 } SortGenOpArg;
4546
4547 static int
genopargtermcompare(SortGenOpArg * a,SortGenOpArg * b)4548 genopargtermcompare(SortGenOpArg* a, SortGenOpArg* b)
4549 {
4550 Sint res = CMP_TERM(a->term, b->term);
4551
4552 if (res < 0) {
4553 return -1;
4554 } else if (res > 0) {
4555 return 1;
4556 }
4557
4558 return 0;
4559 }
4560
4561 static int
map_key_sort(LoaderState * stp,GenOpArg Size,GenOpArg * Rest)4562 map_key_sort(LoaderState* stp, GenOpArg Size, GenOpArg* Rest)
4563 {
4564 SortGenOpArg* t;
4565 unsigned size = Size.val;
4566 unsigned i;
4567
4568 if (size == 2) {
4569 return 1; /* Already sorted. */
4570 }
4571
4572
4573 t = (SortGenOpArg *) erts_alloc(ERTS_ALC_T_TMP, size*sizeof(SortGenOpArg));
4574
4575 /*
4576 * Copy original data and sort keys to a temporary array.
4577 */
4578 for (i = 0; i < size; i += 2) {
4579 t[i].arg = Rest[i];
4580 switch (Rest[i].type) {
4581 case TAG_a:
4582 t[i].term = Rest[i].val;
4583 ASSERT(is_atom(t[i].term));
4584 break;
4585 case TAG_i:
4586 t[i].term = make_small(Rest[i].val);
4587 break;
4588 case TAG_n:
4589 t[i].term = NIL;
4590 break;
4591 case TAG_q:
4592 t[i].term = stp->literals[Rest[i].val].term;
4593 break;
4594 default:
4595 /*
4596 * Not a literal key. Not allowed. Only a single
4597 * variable key is allowed in each map instruction.
4598 */
4599 erts_free(ERTS_ALC_T_TMP, (void *) t);
4600 return 0;
4601 }
4602 #ifdef DEBUG
4603 t[i+1].term = THE_NON_VALUE;
4604 #endif
4605 t[i+1].arg = Rest[i+1];
4606 }
4607
4608 /*
4609 * Sort the temporary array.
4610 */
4611 qsort((void *) t, size / 2, 2 * sizeof(SortGenOpArg),
4612 (int (*)(const void *, const void *)) genopargtermcompare);
4613
4614 /*
4615 * Copy back the sorted, original data.
4616 */
4617 for (i = 0; i < size; i++) {
4618 Rest[i] = t[i].arg;
4619 }
4620
4621 erts_free(ERTS_ALC_T_TMP, (void *) t);
4622 return 1;
4623 }
4624
4625 static int
hash_genop_arg(LoaderState * stp,GenOpArg Key,Uint32 * hx)4626 hash_genop_arg(LoaderState* stp, GenOpArg Key, Uint32* hx)
4627 {
4628 switch (Key.type) {
4629 case TAG_a:
4630 *hx = hashmap_make_hash(Key.val);
4631 return 1;
4632 case TAG_i:
4633 *hx = hashmap_make_hash(make_small(Key.val));
4634 return 1;
4635 case TAG_n:
4636 *hx = hashmap_make_hash(NIL);
4637 return 1;
4638 case TAG_q:
4639 *hx = hashmap_make_hash(stp->literals[Key.val].term);
4640 return 1;
4641 default:
4642 return 0;
4643 }
4644 }
4645
4646 /*
4647 * Replace a get_map_elements with one key to an instruction with one
4648 * element.
4649 */
4650
4651 static GenOp*
gen_get_map_element(LoaderState * stp,GenOpArg Fail,GenOpArg Src,GenOpArg Size,GenOpArg * Rest)4652 gen_get_map_element(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
4653 GenOpArg Size, GenOpArg* Rest)
4654 {
4655 GenOp* op;
4656 GenOpArg Key;
4657 Uint32 hx = 0;
4658
4659 ASSERT(Size.type == TAG_u);
4660
4661 NEW_GENOP(stp, op);
4662 op->next = NULL;
4663 op->a[0] = Fail;
4664 op->a[1] = Src;
4665 op->a[2] = Rest[0];
4666
4667 Key = Rest[0];
4668 if (hash_genop_arg(stp, Key, &hx)) {
4669 op->arity = 5;
4670 op->op = genop_i_get_map_element_hash_5;
4671 op->a[3].type = TAG_u;
4672 op->a[3].val = (BeamInstr) hx;
4673 op->a[4] = Rest[1];
4674 } else {
4675 op->arity = 4;
4676 op->op = genop_i_get_map_element_4;
4677 op->a[3] = Rest[1];
4678 }
4679 return op;
4680 }
4681
4682 static int
hash_internal_genop_arg(LoaderState * stp,GenOpArg Key,Uint32 * hx)4683 hash_internal_genop_arg(LoaderState* stp, GenOpArg Key, Uint32* hx)
4684 {
4685 Eterm key_term;
4686 switch (Key.type) {
4687 case TAG_a:
4688 key_term = Key.val;
4689 break;
4690 case TAG_i:
4691 key_term = make_small(Key.val);
4692 break;
4693 case TAG_n:
4694 key_term = NIL;
4695 break;
4696 case TAG_q:
4697 key_term = stp->literals[Key.val].term;
4698 break;
4699 default:
4700 return 0;
4701 }
4702 *hx = erts_pd_make_hx(key_term);
4703 return 1;
4704 }
4705
4706
4707 static GenOp*
gen_get(LoaderState * stp,GenOpArg Src,GenOpArg Dst)4708 gen_get(LoaderState* stp, GenOpArg Src, GenOpArg Dst)
4709 {
4710 GenOp* op;
4711 Uint32 hx = 0;
4712
4713 NEW_GENOP(stp, op);
4714 op->next = NULL;
4715 if (hash_internal_genop_arg(stp, Src, &hx)) {
4716 op->arity = 3;
4717 op->op = genop_i_get_hash_3;
4718 op->a[0] = Src;
4719 op->a[1].type = TAG_u;
4720 op->a[1].val = (BeamInstr) hx;
4721 op->a[2] = Dst;
4722 } else {
4723 op->arity = 2;
4724 op->op = genop_i_get_2;
4725 op->a[0] = Src;
4726 op->a[1] = Dst;
4727 }
4728 return op;
4729 }
4730
4731
4732 static GenOp*
gen_get_map_elements(LoaderState * stp,GenOpArg Fail,GenOpArg Src,GenOpArg Size,GenOpArg * Rest)4733 gen_get_map_elements(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
4734 GenOpArg Size, GenOpArg* Rest)
4735 {
4736 GenOp* op;
4737 Uint32 hx;
4738 Uint i;
4739 GenOpArg* dst;
4740 #ifdef DEBUG
4741 int good_hash;
4742 #endif
4743
4744 ERTS_UNDEF(hx, 0);
4745 ASSERT(Size.type == TAG_u);
4746
4747 NEW_GENOP(stp, op);
4748 op->op = genop_i_get_map_elements_3;
4749 GENOP_ARITY(op, 3 + 3*(Size.val/2));
4750 op->next = NULL;
4751 op->a[0] = Fail;
4752 op->a[1] = Src;
4753 op->a[2].type = TAG_u;
4754 op->a[2].val = 3*(Size.val/2);
4755
4756 dst = op->a+3;
4757 for (i = 0; i < Size.val / 2; i++) {
4758 dst[0] = Rest[2*i];
4759 dst[1] = Rest[2*i+1];
4760 #ifdef DEBUG
4761 good_hash =
4762 #endif
4763 hash_genop_arg(stp, dst[0], &hx);
4764 #ifdef DEBUG
4765 ASSERT(good_hash);
4766 #endif
4767 dst[2].type = TAG_u;
4768 dst[2].val = (BeamInstr) hx;
4769 dst += 3;
4770 }
4771 return op;
4772 }
4773
4774 static GenOp*
gen_has_map_fields(LoaderState * stp,GenOpArg Fail,GenOpArg Src,GenOpArg Size,GenOpArg * Rest)4775 gen_has_map_fields(LoaderState* stp, GenOpArg Fail, GenOpArg Src,
4776 GenOpArg Size, GenOpArg* Rest)
4777 {
4778 GenOp* op;
4779 Uint i;
4780 Uint n;
4781
4782 ASSERT(Size.type == TAG_u);
4783 n = Size.val;
4784
4785 NEW_GENOP(stp, op);
4786 GENOP_ARITY(op, 3 + 2*n);
4787 op->next = NULL;
4788 op->op = genop_get_map_elements_3;
4789
4790 op->a[0] = Fail;
4791 op->a[1] = Src;
4792 op->a[2].type = TAG_u;
4793 op->a[2].val = 2*n;
4794
4795 for (i = 0; i < n; i++) {
4796 op->a[3+2*i] = Rest[i];
4797 op->a[3+2*i+1].type = TAG_x;
4798 op->a[3+2*i+1].val = SCRATCH_X_REG; /* Ignore result */
4799 }
4800 return op;
4801 }
4802
4803 /*
4804 * Freeze the code in memory, move the string table into place,
4805 * resolve all labels.
4806 */
4807
4808 static int
freeze_code(LoaderState * stp)4809 freeze_code(LoaderState* stp)
4810 {
4811 BeamCodeHeader* code_hdr = stp->hdr;
4812 BeamInstr* codev = (BeamInstr*) &stp->hdr->functions;
4813 int i;
4814 byte* str_table;
4815 unsigned strtab_size = stp->chunks[STR_CHUNK].size;
4816 unsigned attr_size = stp->chunks[ATTR_CHUNK].size;
4817 unsigned compile_size = stp->chunks[COMPILE_CHUNK].size;
4818 Uint size;
4819 Sint decoded_size;
4820 Uint line_size;
4821
4822 /*
4823 * Verify that there was a correct 'FunT' chunk if there were
4824 * make_fun2 instructions in the file.
4825 */
4826
4827 if (stp->lambda_error != NULL) {
4828 LoadError0(stp, stp->lambda_error);
4829 }
4830
4831 /*
4832 * Calculate the final size of the code.
4833 */
4834 if (stp->line_instr == 0) {
4835 line_size = 0;
4836 } else {
4837 line_size = (offsetof(BeamCodeLineTab,func_tab)
4838 + (stp->num_functions + 1) * sizeof(BeamInstr**) /* func_tab */
4839 + (stp->current_li + 1) * sizeof(BeamInstr*) /* line items */
4840 + stp->num_fnames * sizeof(Eterm) /* fname table */
4841 + (stp->current_li + 1) * stp->loc_size); /* loc_tab */
4842 }
4843 size = offsetof(BeamCodeHeader,functions) + (stp->ci * sizeof(BeamInstr)) +
4844 strtab_size + attr_size + compile_size + MD5_SIZE + line_size;
4845
4846 /*
4847 * Move the code to its final location.
4848 */
4849
4850 code_hdr = (BeamCodeHeader*) erts_realloc(ERTS_ALC_T_CODE, (void *) code_hdr, size);
4851 codev = (BeamInstr*) &code_hdr->functions;
4852 CHKBLK(ERTS_ALC_T_CODE,code_hdr);
4853 /*
4854 * Place a pointer to the op_int_code_end instruction in the
4855 * function table in the beginning of the file.
4856 */
4857
4858 code_hdr->functions[stp->num_functions] = (ErtsCodeInfo*)(codev + stp->ci - 1);
4859 CHKBLK(ERTS_ALC_T_CODE,code_hdr);
4860
4861 /*
4862 * Store the pointer to the on_load function.
4863 */
4864
4865 if (stp->on_load) {
4866 code_hdr->on_load_function_ptr = codev + stp->on_load;
4867 } else {
4868 code_hdr->on_load_function_ptr = NULL;
4869 }
4870 CHKBLK(ERTS_ALC_T_CODE,code_hdr);
4871
4872 /*
4873 * Place the literals in their own allocated heap (for fast range check)
4874 * and fix up all instructions that refer to it.
4875 */
4876 {
4877 Eterm* ptr;
4878 LiteralPatch* lp;
4879 ErlOffHeap code_off_heap;
4880 ErtsLiteralArea *literal_area;
4881 Uint lit_asize;
4882
4883 ERTS_INIT_OFF_HEAP(&code_off_heap);
4884
4885 lit_asize = ERTS_LITERAL_AREA_ALLOC_SIZE(stp->total_literal_size);
4886 literal_area = erts_alloc(ERTS_ALC_T_LITERAL, lit_asize);
4887 ptr = &literal_area->start[0];
4888 literal_area->end = ptr + stp->total_literal_size;
4889
4890 for (i = 0; i < stp->num_literals; i++) {
4891 if (is_not_immed(stp->literals[i].term)) {
4892 erts_move_multi_frags(&ptr, &code_off_heap,
4893 stp->literals[i].heap_frags,
4894 &stp->literals[i].term, 1, 1);
4895 ASSERT(erts_is_literal(stp->literals[i].term,
4896 ptr_val(stp->literals[i].term)));
4897 }
4898 }
4899 literal_area->off_heap = code_off_heap.first;
4900 lp = stp->literal_patches;
4901 while (lp != 0) {
4902 BeamInstr* op_ptr;
4903 Literal* lit;
4904
4905 op_ptr = codev + lp->pos;
4906 lit = &stp->literals[op_ptr[0]];
4907 op_ptr[0] = lit->term;
4908 lp = lp->next;
4909 }
4910 code_hdr->literal_area = literal_area;
4911 }
4912 CHKBLK(ERTS_ALC_T_CODE,code);
4913
4914 /*
4915 * If there is line information, place it here.
4916 */
4917 if (stp->line_instr == 0) {
4918 code_hdr->line_table = NULL;
4919 str_table = (byte *) (codev + stp->ci);
4920 } else {
4921 BeamCodeLineTab* const line_tab = (BeamCodeLineTab *) (codev+stp->ci);
4922 const unsigned int ftab_size = stp->num_functions;
4923 const unsigned int num_instrs = stp->current_li;
4924 const BeamInstr** const line_items =
4925 (const BeamInstr**) &line_tab->func_tab[ftab_size + 1];
4926
4927 code_hdr->line_table = line_tab;
4928
4929 for (i = 0; i < ftab_size; i++) {
4930 line_tab->func_tab[i] = line_items + stp->func_line[i];
4931 }
4932 line_tab->func_tab[i] = line_items + num_instrs;
4933
4934 for (i = 0; i < num_instrs; i++) {
4935 line_items[i] = codev + stp->line_instr[i].pos;
4936 }
4937 line_items[i] = codev + stp->ci - 1;
4938
4939 line_tab->fname_ptr = (Eterm*) &line_items[i + 1];
4940 if (stp->num_fnames)
4941 sys_memcpy(line_tab->fname_ptr, stp->fname,
4942 stp->num_fnames*sizeof(Eterm));
4943
4944 line_tab->loc_size = stp->loc_size;
4945 if (stp->loc_size == 2) {
4946 Uint16* locp = (Uint16 *) &line_tab->fname_ptr[stp->num_fnames];
4947 line_tab->loc_tab.p2 = locp;
4948 for (i = 0; i < num_instrs; i++) {
4949 *locp++ = (Uint16) stp->line_instr[i].loc;
4950 }
4951 *locp++ = LINE_INVALID_LOCATION;
4952 str_table = (byte *) locp;
4953 } else {
4954 Uint32* locp = (Uint32 *) &line_tab->fname_ptr[stp->num_fnames];
4955 ASSERT(stp->loc_size == 4);
4956 line_tab->loc_tab.p4 = locp;
4957 for (i = 0; i < num_instrs; i++) {
4958 *locp++ = stp->line_instr[i].loc;
4959 }
4960 *locp++ = LINE_INVALID_LOCATION;
4961 str_table = (byte *) locp;
4962 }
4963 CHKBLK(ERTS_ALC_T_CODE,code);
4964 }
4965
4966 /*
4967 * Place the string table and, optionally, attributes here.
4968 */
4969 sys_memcpy(str_table, stp->chunks[STR_CHUNK].start, strtab_size);
4970 CHKBLK(ERTS_ALC_T_CODE,code);
4971 if (attr_size) {
4972 byte* attr = str_table + strtab_size;
4973 sys_memcpy(attr, stp->chunks[ATTR_CHUNK].start, stp->chunks[ATTR_CHUNK].size);
4974 code_hdr->attr_ptr = attr;
4975 code_hdr->attr_size = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
4976 decoded_size = erts_decode_ext_size(attr, attr_size);
4977 if (decoded_size < 0) {
4978 LoadError0(stp, "bad external term representation of module attributes");
4979 }
4980 code_hdr->attr_size_on_heap = decoded_size;
4981 }
4982 CHKBLK(ERTS_ALC_T_CODE,code);
4983 if (compile_size) {
4984 byte* compile_info = str_table + strtab_size + attr_size;
4985 CHKBLK(ERTS_ALC_T_CODE,code);
4986 sys_memcpy(compile_info, stp->chunks[COMPILE_CHUNK].start,
4987 stp->chunks[COMPILE_CHUNK].size);
4988
4989 CHKBLK(ERTS_ALC_T_CODE,code);
4990 code_hdr->compile_ptr = compile_info;
4991 CHKBLK(ERTS_ALC_T_CODE,code);
4992 code_hdr->compile_size = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
4993 CHKBLK(ERTS_ALC_T_CODE,code);
4994 decoded_size = erts_decode_ext_size(compile_info, compile_size);
4995 CHKBLK(ERTS_ALC_T_CODE,code);
4996 if (decoded_size < 0) {
4997 LoadError0(stp, "bad external term representation of compilation information");
4998 }
4999 CHKBLK(ERTS_ALC_T_CODE,code);
5000 code_hdr->compile_size_on_heap = decoded_size;
5001 }
5002 CHKBLK(ERTS_ALC_T_CODE,code);
5003 {
5004 byte* md5_sum = str_table + strtab_size + attr_size + compile_size;
5005 CHKBLK(ERTS_ALC_T_CODE,code);
5006 sys_memcpy(md5_sum, stp->mod_md5, MD5_SIZE);
5007 CHKBLK(ERTS_ALC_T_CODE,code);
5008 code_hdr->md5_ptr = md5_sum;
5009 CHKBLK(ERTS_ALC_T_CODE,code);
5010 }
5011 CHKBLK(ERTS_ALC_T_CODE,code);
5012
5013 /*
5014 * Make sure that we have not overflowed the allocated code space.
5015 */
5016 ASSERT(str_table + strtab_size + attr_size + compile_size + MD5_SIZE ==
5017 ((byte *) code_hdr) + size);
5018
5019 /*
5020 * Patch all instructions that refer to the string table.
5021 */
5022 {
5023 StringPatch* sp = stp->string_patches;
5024
5025 while (sp != 0) {
5026 BeamInstr* op_ptr;
5027 byte* strp;
5028
5029 op_ptr = codev + sp->pos;
5030 strp = str_table + op_ptr[0];
5031 op_ptr[0] = (BeamInstr) strp;
5032 sp = sp->next;
5033 }
5034 }
5035 CHKBLK(ERTS_ALC_T_CODE,code_hdr);
5036
5037 /*
5038 * Resolve all labels.
5039 */
5040
5041 for (i = 0; i < stp->num_labels; i++) {
5042 Uint patch;
5043 Uint value = stp->labels[i].value;
5044
5045 if (value == 0 && stp->labels[i].num_patches != 0) {
5046 LoadError1(stp, "label %d not resolved", i);
5047 }
5048 ASSERT(value < stp->ci);
5049 for (patch = 0; patch < stp->labels[i].num_patches; patch++) {
5050 LabelPatch* lp = &stp->labels[i].patches[patch];
5051 Uint pos = lp->pos;
5052 ASSERT(pos < stp->ci);
5053 if (pos < stp->num_functions) {
5054 /*
5055 * This is the array of pointers to the beginning of
5056 * each function. The pointers must remain absolute.
5057 */
5058 codev[pos] = (BeamInstr) (codev + value);
5059 } else {
5060 #if defined(DEBUG) && defined(BEAM_WIDE_MASK)
5061 Uint w;
5062 #endif
5063 Sint32 rel = lp->offset + value;
5064 switch (lp->packed) {
5065 case 0: /* Not packed */
5066 ASSERT(codev[pos] == i);
5067 codev[pos] = rel;
5068 break;
5069 #ifdef BEAM_WIDE_MASK
5070 case 1: /* Least significant word. */
5071 #ifdef DEBUG
5072 w = codev[pos] & BEAM_WIDE_MASK;
5073 /* Correct label in least significant word? */
5074 ASSERT(w == i);
5075 #endif
5076 codev[pos] = (codev[pos] & ~BEAM_WIDE_MASK) |
5077 (rel & BEAM_WIDE_MASK);
5078 break;
5079 case 2: /* Most significant word */
5080 #ifdef DEBUG
5081 w = (codev[pos] >> BEAM_WIDE_SHIFT) & BEAM_WIDE_MASK;
5082 /* Correct label in most significant word? */
5083 ASSERT(w == i);
5084 #endif
5085 codev[pos] = ((Uint)rel << BEAM_WIDE_SHIFT) |
5086 (codev[pos] & BEAM_WIDE_MASK);
5087 break;
5088 #endif
5089 default:
5090 ASSERT(0);
5091 }
5092 }
5093 }
5094 }
5095 CHKBLK(ERTS_ALC_T_CODE,code_hdr);
5096
5097 /*
5098 * Save the updated code pointer and code size.
5099 */
5100
5101 stp->hdr = code_hdr;
5102 stp->codev = codev;
5103 stp->loaded_size = size;
5104
5105 CHKBLK(ERTS_ALC_T_CODE,code_hdr);
5106 return 1;
5107
5108 load_error:
5109 /*
5110 * Make sure that the caller frees the newly reallocated block, and
5111 * not the old one (in case it has moved).
5112 */
5113 stp->hdr = code_hdr;
5114 stp->codev = codev;
5115 return 0;
5116 }
5117
5118 static void
final_touch(LoaderState * stp,struct erl_module_instance * inst_p)5119 final_touch(LoaderState* stp, struct erl_module_instance* inst_p)
5120 {
5121 unsigned int i;
5122 int on_load = stp->on_load;
5123 unsigned catches;
5124 Uint index;
5125 BeamInstr* codev = stp->codev;
5126
5127 /*
5128 * Allocate catch indices and fix up all catch_yf instructions.
5129 */
5130
5131 index = stp->catches;
5132 catches = BEAM_CATCHES_NIL;
5133 while (index != 0) {
5134 BeamInstr next = codev[index];
5135 BeamInstr* abs_addr;
5136 codev[index] = BeamOpCodeAddr(op_catch_yf);
5137 /* We must make the address of the label absolute again. */
5138 abs_addr = (BeamInstr *)codev + index + codev[index+2];
5139 catches = beam_catches_cons(abs_addr, catches);
5140 codev[index+2] = make_catch(catches);
5141 index = next;
5142 }
5143 inst_p->catches = catches;
5144
5145 /*
5146 * Export functions.
5147 */
5148
5149 for (i = 0; i < stp->num_exps; i++) {
5150 Export* ep;
5151 BeamInstr* address = stp->export[i].address;
5152
5153 if (address == NULL) {
5154 /* Skip stub for a BIF */
5155 continue;
5156 }
5157 ep = erts_export_put(stp->module, stp->export[i].function,
5158 stp->export[i].arity);
5159 if (on_load) {
5160 /*
5161 * on_load: Don't make any of the exported functions
5162 * callable yet. Keep any function in the current
5163 * code callable.
5164 */
5165 ep->beam[1] = (BeamInstr) address;
5166 }
5167 else
5168 ep->addressv[erts_staging_code_ix()] = address;
5169 }
5170
5171 /*
5172 * Import functions and patch all callers.
5173 */
5174
5175 for (i = 0; i < stp->num_imports; i++) {
5176 Eterm mod;
5177 Eterm func;
5178 Uint arity;
5179 BeamInstr import;
5180 Uint current;
5181 Uint next;
5182
5183 mod = stp->import[i].module;
5184 func = stp->import[i].function;
5185 arity = stp->import[i].arity;
5186 import = (BeamInstr) erts_export_put(mod, func, arity);
5187 current = stp->import[i].patches;
5188 while (current != 0) {
5189 ASSERT(current < stp->ci);
5190 next = stp->codev[current];
5191 stp->codev[current] = import;
5192 current = next;
5193 }
5194 }
5195
5196 /*
5197 * Fix all funs.
5198 */
5199
5200 if (stp->num_lambdas > 0) {
5201 for (i = 0; i < stp->num_lambdas; i++) {
5202 unsigned entry_label = stp->lambdas[i].label;
5203 ErlFunEntry* fe = stp->lambdas[i].fe;
5204 BeamInstr* code_ptr = stp->codev + stp->labels[entry_label].value;
5205
5206 if (fe->address[0] != 0) {
5207 /*
5208 * We are hiding a pointer into older code.
5209 */
5210 erts_refc_dec(&fe->refc, 1);
5211 }
5212 fe->address = code_ptr;
5213 #ifdef HIPE
5214 hipe_set_closure_stub(fe);
5215 #endif
5216 }
5217 }
5218 }
5219
5220 static int
transform_engine(LoaderState * st)5221 transform_engine(LoaderState* st)
5222 {
5223 Uint op;
5224 int ap; /* Current argument. */
5225 const Uint* restart; /* Where to restart if current match fails. */
5226 GenOpArg var[TE_MAX_VARS]; /* Buffer for variables. */
5227 GenOpArg* rest_args = NULL;
5228 int num_rest_args = 0;
5229 int i; /* General index. */
5230 Uint mask;
5231 GenOp* instr;
5232 GenOp* first = st->genop;
5233 GenOp* keep = NULL;
5234 const Uint* pc;
5235 static Uint restart_fail[1] = {TOP_fail};
5236
5237 ASSERT(gen_opc[first->op].transform != -1);
5238 restart = op_transform + gen_opc[first->op].transform;
5239
5240 restart:
5241 ASSERT(restart != NULL);
5242 pc = restart;
5243 ASSERT(*pc < NUM_TOPS); /* Valid instruction? */
5244 instr = first;
5245
5246 #ifdef DEBUG
5247 restart = NULL;
5248 #endif
5249 ap = 0;
5250 for (;;) {
5251 op = *pc++;
5252
5253 switch (op) {
5254 case TOP_next_instr:
5255 instr = instr->next;
5256 ap = 0;
5257 if (instr == NULL) {
5258 /*
5259 * We'll need at least one more instruction to decide whether
5260 * this combination matches or not.
5261 */
5262 return TE_SHORT_WINDOW;
5263 }
5264 if (*pc++ != instr->op)
5265 goto restart;
5266 break;
5267 case TOP_is_type:
5268 mask = *pc++;
5269
5270 ASSERT(ap < instr->arity);
5271 ASSERT(instr->a[ap].type < BEAM_NUM_TAGS);
5272 if (((1 << instr->a[ap].type) & mask) == 0)
5273 goto restart;
5274 break;
5275 case TOP_pred:
5276 i = *pc++;
5277 switch (i) {
5278 #define RVAL i
5279 #include "beam_pred_funcs.h"
5280 #undef RVAL
5281 default:
5282 ASSERT(0);
5283 }
5284 if (i == 0)
5285 goto restart;
5286 break;
5287 #if defined(TOP_is_eq)
5288 case TOP_is_eq:
5289 ASSERT(ap < instr->arity);
5290 if (*pc++ != instr->a[ap].val)
5291 goto restart;
5292 break;
5293 #endif
5294 case TOP_is_type_eq:
5295 mask = *pc++;
5296
5297 ASSERT(ap < instr->arity);
5298 ASSERT(instr->a[ap].type < BEAM_NUM_TAGS);
5299 if (((1 << instr->a[ap].type) & mask) == 0)
5300 goto restart;
5301 if (*pc++ != instr->a[ap].val)
5302 goto restart;
5303 break;
5304 case TOP_is_same_var:
5305 ASSERT(ap < instr->arity);
5306 i = *pc++;
5307 ASSERT(i < TE_MAX_VARS);
5308 if (var[i].type != instr->a[ap].type)
5309 goto restart;
5310 switch (var[i].type) {
5311 case TAG_n:
5312 break;
5313 default:
5314 if (var[i].val != instr->a[ap].val)
5315 goto restart;
5316 }
5317 break;
5318 #if defined(TOP_is_bif)
5319 case TOP_is_bif:
5320 {
5321 int bif_number = *pc++;
5322
5323 /*
5324 * In debug build, the type must be 'u'.
5325 * In a real build, don't match. (I.e. retain the original
5326 * call instruction, this will work, but it will be a
5327 * slight performance loss.)
5328 */
5329
5330 ASSERT(instr->a[ap].type == TAG_u);
5331 if (instr->a[ap].type != TAG_u)
5332 goto restart;
5333
5334 /*
5335 * In debug build, the assertion will catch invalid indexes
5336 * immediately. In a real build, the loader will issue
5337 * an diagnostic later when the instruction is loaded.
5338 */
5339
5340 i = instr->a[ap].val;
5341 ASSERT(i < st->num_imports);
5342 if (i >= st->num_imports || st->import[i].bf == NULL)
5343 goto restart;
5344 if (bif_number != -1 &&
5345 bif_export[bif_number]->beam[1] != (BeamInstr) st->import[i].bf) {
5346 goto restart;
5347 }
5348 }
5349 break;
5350
5351 #endif
5352 #if defined(TOP_is_not_bif)
5353 case TOP_is_not_bif:
5354 {
5355 pc++;
5356
5357 /*
5358 * In debug build, the type must be 'u'.
5359 */
5360
5361 ASSERT(instr->a[ap].type == TAG_u);
5362 if (instr->a[ap].type != TAG_u) {
5363 goto restart;
5364 }
5365 i = instr->a[ap].val;
5366
5367 /*
5368 * erlang:apply/2,3 are strange. They exist as (dummy) BIFs
5369 * so that they are included in the export table before
5370 * the erlang module is loaded. They also exist in the erlang
5371 * module as functions. When used in code, a special Beam
5372 * instruction is used.
5373 *
5374 * Below we specially recognize erlang:apply/2,3 as special.
5375 * This is necessary because after setting a trace pattern on
5376 * them, you cannot no longer see from the export entry that
5377 * they are special.
5378 */
5379 if (i < st->num_imports) {
5380 if (st->import[i].bf != NULL ||
5381 (st->import[i].module == am_erlang &&
5382 st->import[i].function == am_apply &&
5383 (st->import[i].arity == 2 || st->import[i].arity == 3))) {
5384 goto restart;
5385 }
5386 }
5387 }
5388 break;
5389
5390 #endif
5391 #if defined(TOP_is_func)
5392 case TOP_is_func:
5393 {
5394 Eterm mod = *pc++;
5395 Eterm func = *pc++;
5396 int arity = *pc++;
5397
5398 ASSERT(instr->a[ap].type == TAG_u);
5399 if (instr->a[ap].type != TAG_u) {
5400 goto restart;
5401 }
5402 i = instr->a[ap].val;
5403 ASSERT(i < st->num_imports);
5404 if (i >= st->num_imports || st->import[i].module != mod ||
5405 st->import[i].function != func ||
5406 (arity < MAX_ARG && st->import[i].arity != arity)) {
5407 goto restart;
5408 }
5409 }
5410 break;
5411 #endif
5412 case TOP_set_var_next_arg:
5413 ASSERT(ap < instr->arity);
5414 i = *pc++;
5415 ASSERT(i < TE_MAX_VARS);
5416 var[i].type = instr->a[ap].type;
5417 var[i].val = instr->a[ap].val;
5418 ap++;
5419 break;
5420
5421 #if defined(TOP_rest_args)
5422 case TOP_rest_args:
5423 {
5424 int formal_arity = gen_opc[instr->op].arity;
5425 num_rest_args = instr->arity - formal_arity;
5426 rest_args = instr->a + formal_arity;
5427 }
5428 break;
5429 #endif
5430 case TOP_next_arg:
5431 ap++;
5432 break;
5433 case TOP_commit:
5434 instr = instr->next; /* The next_instr was optimized away. */
5435 keep = instr;
5436 st->genop = instr;
5437 #ifdef DEBUG
5438 instr = 0;
5439 #endif
5440 break;
5441 #if defined(TOP_keep)
5442 case TOP_keep:
5443 /* Keep the current instruction unchanged. */
5444 keep = instr;
5445 st->genop = instr;
5446 #ifdef DEBUG
5447 instr = 0;
5448 #endif
5449 break;
5450 #endif
5451 #if defined(TOP_call_end)
5452 case TOP_call_end:
5453 {
5454 GenOp** lastp;
5455 GenOp* new_instr;
5456
5457 i = *pc++;
5458 switch (i) {
5459 #define RVAL new_instr
5460 #include "beam_tr_funcs.h"
5461 #undef RVAL
5462 default:
5463 new_instr = NULL; /* Silence compiler warning. */
5464 ASSERT(0);
5465 }
5466 if (new_instr == NULL) {
5467 goto restart;
5468 }
5469
5470 lastp = &new_instr;
5471 while (*lastp != NULL) {
5472 lastp = &((*lastp)->next);
5473 }
5474
5475 keep = instr->next; /* The next_instr was optimized away. */
5476 *lastp = keep;
5477 st->genop = new_instr;
5478 }
5479 /* FALLTHROUGH */
5480 #endif
5481 case TOP_end:
5482 while (first != keep) {
5483 GenOp* next = first->next;
5484 FREE_GENOP(st, first);
5485 first = next;
5486 }
5487 return TE_OK;
5488 case TOP_new_instr:
5489 /*
5490 * Note that the instructions are generated in reverse order.
5491 */
5492 NEW_GENOP(st, instr);
5493 instr->next = st->genop;
5494 st->genop = instr;
5495 instr->op = op = *pc++;
5496 instr->arity = gen_opc[op].arity;
5497 ap = 0;
5498 break;
5499 #ifdef TOP_rename
5500 case TOP_rename:
5501 instr->op = op = *pc++;
5502 instr->arity = gen_opc[op].arity;
5503 return TE_OK;
5504 #endif
5505 case TOP_store_type:
5506 i = *pc++;
5507 instr->a[ap].type = i;
5508 instr->a[ap].val = 0;
5509 break;
5510 case TOP_store_val:
5511 i = *pc++;
5512 instr->a[ap].val = i;
5513 break;
5514 case TOP_store_var_next_arg:
5515 i = *pc++;
5516 ASSERT(i < TE_MAX_VARS);
5517 instr->a[ap].type = var[i].type;
5518 instr->a[ap].val = var[i].val;
5519 ap++;
5520 break;
5521 #if defined(TOP_store_rest_args)
5522 case TOP_store_rest_args:
5523 {
5524 GENOP_ARITY(instr, instr->arity+num_rest_args);
5525 sys_memcpy(instr->a, instr->def_args, ap*sizeof(GenOpArg));
5526 sys_memcpy(instr->a+ap, rest_args, num_rest_args*sizeof(GenOpArg));
5527 ap += num_rest_args;
5528 }
5529 break;
5530 #endif
5531 case TOP_try_me_else:
5532 restart = pc + 1;
5533 restart += *pc++;
5534 ASSERT(*pc < NUM_TOPS); /* Valid instruction? */
5535 break;
5536 case TOP_try_me_else_fail:
5537 restart = restart_fail;
5538 break;
5539 case TOP_fail:
5540 return TE_FAIL;
5541 default:
5542 ASSERT(0);
5543 }
5544 }
5545 }
5546
5547 static void
short_file(int line,LoaderState * stp,unsigned needed)5548 short_file(int line, LoaderState* stp, unsigned needed)
5549 {
5550 load_printf(line, stp, "unexpected end of %s when reading %d byte(s)",
5551 stp->file_name, needed);
5552 }
5553
5554 static void
load_printf(int line,LoaderState * context,char * fmt,...)5555 load_printf(int line, LoaderState* context, char *fmt,...)
5556 {
5557 erts_dsprintf_buf_t *dsbufp;
5558 va_list va;
5559
5560 if (is_non_value(context->module)) {
5561 /* Suppressed by code:get_chunk/2 */
5562 return;
5563 }
5564
5565 dsbufp = erts_create_logger_dsbuf();
5566
5567 erts_dsprintf(dsbufp, "%s(%d): Error loading ", __FILE__, line);
5568
5569 if (is_atom(context->function))
5570 erts_dsprintf(dsbufp, "function %T:%T/%d", context->module,
5571 context->function, context->arity);
5572 else
5573 erts_dsprintf(dsbufp, "module %T", context->module);
5574
5575 if (context->genop)
5576 erts_dsprintf(dsbufp, ": op %s", gen_opc[context->genop->op].name);
5577
5578 if (context->specific_op != -1)
5579 erts_dsprintf(dsbufp, ": %s", opc[context->specific_op].sign);
5580 else if (context->genop) {
5581 int i;
5582 for (i = 0; i < context->genop->arity; i++)
5583 erts_dsprintf(dsbufp, " %c",
5584 tag_to_letter[context->genop->a[i].type]);
5585 }
5586
5587 erts_dsprintf(dsbufp, ":\n ");
5588
5589 va_start(va, fmt);
5590 erts_vdsprintf(dsbufp, fmt, va);
5591 va_end(va);
5592
5593 erts_dsprintf(dsbufp, "\n");
5594 #ifdef DEBUG
5595 erts_fprintf(stderr, "%s", dsbufp->str);
5596 #endif
5597 erts_send_error_to_logger(context->group_leader, dsbufp);
5598 }
5599
5600 static int
get_tag_and_value(LoaderState * stp,Uint len_code,unsigned tag,BeamInstr * result)5601 get_tag_and_value(LoaderState* stp, Uint len_code,
5602 unsigned tag, BeamInstr* result)
5603 {
5604 Uint count;
5605 Sint val;
5606 byte default_byte_buf[128];
5607 byte* byte_buf = default_byte_buf;
5608 Eterm default_big_buf[128/sizeof(Eterm)];
5609 Eterm* big_buf = default_big_buf;
5610 Eterm tmp_big;
5611 byte* s;
5612 int i;
5613 int neg = 0;
5614 Uint words_needed;
5615 Eterm* hp;
5616
5617 /*
5618 * Retrieve the size of the value in bytes.
5619 */
5620
5621 len_code >>= 5;
5622 if (len_code < 7) {
5623 count = len_code + 2;
5624 } else {
5625 unsigned sztag;
5626 UWord len_word;
5627
5628 ASSERT(len_code == 7);
5629 GetTagAndValue(stp, sztag, len_word);
5630 VerifyTag(stp, sztag, TAG_u);
5631 count = len_word + 9;
5632 }
5633
5634 /*
5635 * The value for tags except TAG_i must be an unsigned integer
5636 * fitting in an Uint. If it does not fit, we'll indicate overflow
5637 * by changing the tag to TAG_o.
5638 */
5639
5640 if (tag != TAG_i) {
5641 if (count == sizeof(Uint)+1) {
5642 Uint msb;
5643
5644 /*
5645 * The encoded value has one more byte than an Uint.
5646 * It will still fit in an Uint if the most significant
5647 * byte is 0.
5648 */
5649 GetByte(stp, msb);
5650 GetInt(stp, sizeof(Uint), *result);
5651 if (msb != 0) {
5652 /* Overflow: Negative or too big. */
5653 return TAG_o;
5654 }
5655 } else if (count == sizeof(Uint)) {
5656 /*
5657 * The value must be positive (or the encoded value would
5658 * have been one byte longer).
5659 */
5660 GetInt(stp, count, *result);
5661 } else if (count < sizeof(Uint)) {
5662 GetInt(stp, count, *result);
5663
5664 /*
5665 * If the sign bit is set, the value is negative
5666 * (not allowed).
5667 */
5668 if (*result & ((Uint)1 << (count*8-1))) {
5669 return TAG_o;
5670 }
5671 } else {
5672 GetInt(stp, count, *result);
5673 return TAG_o;
5674 }
5675 return tag;
5676 }
5677
5678 /*
5679 * TAG_i: First handle values up to the size of an Uint (i.e. either
5680 * a small or a bignum).
5681 */
5682
5683 if (count <= sizeof(val)) {
5684 GetInt(stp, count, val);
5685
5686 val = ((val << 8*(sizeof(val)-count)) >> 8*(sizeof(val)-count));
5687 if (IS_SSMALL(val)) {
5688 *result = val;
5689 return TAG_i;
5690 } else {
5691 tmp_big = small_to_big(val, big_buf);
5692 if (!find_literal(stp, tmp_big, result)) {
5693 *result = new_literal(stp, &hp, BIG_UINT_HEAP_SIZE);
5694 sys_memcpy(hp, big_buf, BIG_UINT_HEAP_SIZE*sizeof(Eterm));
5695 }
5696 return TAG_q;
5697 }
5698 }
5699
5700 /*
5701 * Make sure that the number will fit in our temporary buffer
5702 * (including margin).
5703 */
5704
5705 if (count+8 > sizeof(default_byte_buf)) {
5706 byte_buf = erts_alloc(ERTS_ALC_T_LOADER_TMP, count+8);
5707 }
5708
5709 /*
5710 * Copy the number reversed to our temporary buffer.
5711 */
5712
5713 GetString(stp, s, count);
5714 for (i = 0; i < count; i++) {
5715 byte_buf[count-i-1] = *s++;
5716 }
5717
5718 /*
5719 * Check if the number is negative, and negate it if so.
5720 */
5721
5722 if ((byte_buf[count-1] & 0x80) != 0) {
5723 unsigned carry = 1;
5724
5725 neg = 1;
5726 for (i = 0; i < count; i++) {
5727 byte_buf[i] = ~byte_buf[i] + carry;
5728 carry = (byte_buf[i] == 0 && carry == 1);
5729 }
5730 ASSERT(carry == 0);
5731 }
5732
5733 /*
5734 * Align to word boundary.
5735 */
5736
5737 if (byte_buf[count-1] == 0) {
5738 count--;
5739 }
5740 if (byte_buf[count-1] == 0) {
5741 LoadError0(stp, "bignum not normalized");
5742 }
5743 while (count % sizeof(Eterm) != 0) {
5744 byte_buf[count++] = 0;
5745 }
5746
5747 /*
5748 * Convert to a bignum.
5749 */
5750
5751 words_needed = count/sizeof(Eterm) + 1;
5752 if (words_needed*sizeof(Eterm) > sizeof(default_big_buf)) {
5753 big_buf = erts_alloc(ERTS_ALC_T_LOADER_TMP, words_needed*sizeof(Eterm));
5754 }
5755 tmp_big = bytes_to_big(byte_buf, count, neg, big_buf);
5756 if (is_nil(tmp_big)) {
5757 goto load_error;
5758 }
5759
5760 /*
5761 * Create a literal if there is no previous literal with the same value.
5762 */
5763
5764 if (!find_literal(stp, tmp_big, result)) {
5765 *result = new_literal(stp, &hp, words_needed);
5766 sys_memcpy(hp, big_buf, words_needed*sizeof(Eterm));
5767 }
5768
5769 if (byte_buf != default_byte_buf) {
5770 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) byte_buf);
5771 }
5772 if (big_buf != default_big_buf) {
5773 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) big_buf);
5774 }
5775 return TAG_q;
5776
5777 load_error:
5778 if (byte_buf != default_byte_buf) {
5779 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) byte_buf);
5780 }
5781 if (big_buf != default_big_buf) {
5782 erts_free(ERTS_ALC_T_LOADER_TMP, (void *) big_buf);
5783 }
5784 return -1;
5785 }
5786
5787 /*
5788 * Converts an IFF id to a printable string.
5789 */
5790
5791 static void
id_to_string(Uint id,char * s)5792 id_to_string(Uint id, char* s)
5793 {
5794 int i;
5795
5796 for (i = 3; i >= 0; i--) {
5797 *s++ = (id >> i*8) & 0xff;
5798 }
5799 *s++ = '\0';
5800 }
5801
5802 static void
new_genop(LoaderState * stp)5803 new_genop(LoaderState* stp)
5804 {
5805 GenOpBlock* p = (GenOpBlock *) erts_alloc(ERTS_ALC_T_LOADER_TMP,
5806 sizeof(GenOpBlock));
5807 int i;
5808
5809 p->next = stp->genop_blocks;
5810 stp->genop_blocks = p;
5811 for (i = 0; i < sizeof(p->genop)/sizeof(p->genop[0])-1; i++) {
5812 p->genop[i].next = p->genop + i + 1;
5813 }
5814 p->genop[i].next = NULL;
5815 stp->free_genop = p->genop;
5816 }
5817
5818 static int
new_label(LoaderState * stp)5819 new_label(LoaderState* stp)
5820 {
5821 unsigned int num = stp->num_labels;
5822
5823 stp->num_labels++;
5824 stp->labels = (Label *) erts_realloc(ERTS_ALC_T_PREPARED_CODE,
5825 (void *) stp->labels,
5826 stp->num_labels * sizeof(Label));
5827 init_label(&stp->labels[num]);
5828 return num;
5829 }
5830
5831 static void
new_literal_patch(LoaderState * stp,int pos)5832 new_literal_patch(LoaderState* stp, int pos)
5833 {
5834 LiteralPatch* p = erts_alloc(ERTS_ALC_T_PREPARED_CODE,
5835 sizeof(LiteralPatch));
5836 p->pos = pos;
5837 p->next = stp->literal_patches;
5838 stp->literal_patches = p;
5839 }
5840
5841 static void
new_string_patch(LoaderState * stp,int pos)5842 new_string_patch(LoaderState* stp, int pos)
5843 {
5844 StringPatch* p = erts_alloc(ERTS_ALC_T_PREPARED_CODE, sizeof(StringPatch));
5845 p->pos = pos;
5846 p->next = stp->string_patches;
5847 stp->string_patches = p;
5848 }
5849
5850 static Uint
new_literal(LoaderState * stp,Eterm ** hpp,Uint heap_size)5851 new_literal(LoaderState* stp, Eterm** hpp, Uint heap_size)
5852 {
5853 Literal* lit;
5854
5855 if (stp->allocated_literals == 0) {
5856 Uint need;
5857
5858 ASSERT(stp->literals == 0);
5859 ASSERT(stp->num_literals == 0);
5860 stp->allocated_literals = 8;
5861 need = stp->allocated_literals * sizeof(Literal);
5862 stp->literals = (Literal *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
5863 need);
5864 } else if (stp->allocated_literals <= stp->num_literals) {
5865 Uint need;
5866
5867 stp->allocated_literals *= 2;
5868 need = stp->allocated_literals * sizeof(Literal);
5869 stp->literals = (Literal *) erts_realloc(ERTS_ALC_T_PREPARED_CODE,
5870 (void *) stp->literals,
5871 need);
5872 }
5873
5874 stp->total_literal_size += heap_size;
5875 lit = stp->literals + stp->num_literals;
5876 lit->heap_frags = new_literal_fragment(heap_size);
5877 lit->term = make_boxed(lit->heap_frags->mem);
5878 *hpp = lit->heap_frags->mem;
5879 return stp->num_literals++;
5880 }
5881
5882 static int
find_literal(LoaderState * stp,Eterm needle,Uint * idx)5883 find_literal(LoaderState* stp, Eterm needle, Uint *idx)
5884 {
5885 int i;
5886
5887 /*
5888 * The search is done backwards since the most recent literals
5889 * allocated by the loader itself will be placed at the end
5890 */
5891 for (i = stp->num_literals - 1; i >= 0; i--) {
5892 if (EQ(needle, stp->literals[i].term)) {
5893 *idx = (Uint) i;
5894 return 1;
5895 }
5896 }
5897 return 0;
5898 }
5899
5900 Eterm
erts_module_info_0(Process * p,Eterm module)5901 erts_module_info_0(Process* p, Eterm module)
5902 {
5903 Module* modp;
5904 ErtsCodeIndex code_ix = erts_active_code_ix();
5905 BeamCodeHeader* code_hdr;
5906 Eterm *hp;
5907 Eterm list = NIL;
5908 Eterm tup;
5909
5910 if (is_not_atom(module)) {
5911 return THE_NON_VALUE;
5912 }
5913
5914 modp = erts_get_module(module, code_ix);
5915 if (modp == NULL) {
5916 return THE_NON_VALUE;
5917 }
5918
5919 code_hdr = modp->curr.code_hdr;
5920 if (code_hdr == NULL) {
5921 return THE_NON_VALUE;
5922 }
5923
5924 #define BUILD_INFO(What) \
5925 tup = get_module_info(p, code_ix, code_hdr, module, What); \
5926 hp = HAlloc(p, 5); \
5927 tup = TUPLE2(hp, What, tup); \
5928 hp += 3; \
5929 list = CONS(hp, tup, list)
5930
5931 BUILD_INFO(am_md5);
5932 #ifdef HIPE
5933 BUILD_INFO(am_native);
5934 #endif
5935 BUILD_INFO(am_compile);
5936 BUILD_INFO(am_attributes);
5937 BUILD_INFO(am_exports);
5938 BUILD_INFO(am_module);
5939 #undef BUILD_INFO
5940 return list;
5941 }
5942
5943 Eterm
erts_module_info_1(Process * p,Eterm module,Eterm what)5944 erts_module_info_1(Process* p, Eterm module, Eterm what)
5945 {
5946 Module* modp;
5947 ErtsCodeIndex code_ix = erts_active_code_ix();
5948 BeamCodeHeader* code_hdr;
5949
5950 if (is_not_atom(module)) {
5951 return THE_NON_VALUE;
5952 }
5953
5954 modp = erts_get_module(module, code_ix);
5955 if (modp == NULL) {
5956 return THE_NON_VALUE;
5957 }
5958
5959 code_hdr = modp->curr.code_hdr;
5960 if (code_hdr == NULL) {
5961 return THE_NON_VALUE;
5962 }
5963
5964 return get_module_info(p, code_ix, code_hdr, module, what);
5965 }
5966
5967 static Eterm
get_module_info(Process * p,ErtsCodeIndex code_ix,BeamCodeHeader * code_hdr,Eterm module,Eterm what)5968 get_module_info(Process* p, ErtsCodeIndex code_ix, BeamCodeHeader* code_hdr,
5969 Eterm module, Eterm what)
5970 {
5971 if (what == am_module) {
5972 return module;
5973 } else if (what == am_md5) {
5974 return md5_of_module(p, code_hdr);
5975 } else if (what == am_exports) {
5976 return exported_from_module(p, code_ix, module);
5977 } else if (what == am_functions) {
5978 return functions_in_module(p, code_hdr);
5979 } else if (what == am_nifs) {
5980 return nifs_in_module(p, module);
5981 } else if (what == am_attributes) {
5982 return attributes_for_module(p, code_hdr);
5983 } else if (what == am_compile) {
5984 return compilation_info_for_module(p, code_hdr);
5985 } else if (what == am_native_addresses) {
5986 return native_addresses(p, code_hdr);
5987 } else if (what == am_native) {
5988 return has_native(code_hdr);
5989 }
5990 return THE_NON_VALUE;
5991 }
5992
5993 /*
5994 * Builds a list of all functions in the given module:
5995 * [{Name, Arity},...]
5996 */
5997
5998 Eterm
functions_in_module(Process * p,BeamCodeHeader * code_hdr)5999 functions_in_module(Process* p, /* Process whose heap to use. */
6000 BeamCodeHeader* code_hdr)
6001 {
6002 int i;
6003 Uint num_functions;
6004 Uint need;
6005 Eterm* hp;
6006 Eterm* hp_end;
6007 Eterm result = NIL;
6008
6009 num_functions = code_hdr->num_functions;
6010 need = 5*num_functions;
6011 hp = HAlloc(p, need);
6012 hp_end = hp + need;
6013 for (i = num_functions-1; i >= 0 ; i--) {
6014 ErtsCodeInfo* ci = code_hdr->functions[i];
6015 Eterm tuple;
6016
6017 /*
6018 * If the function name is [], this entry is a stub for
6019 * a BIF that should be ignored.
6020 */
6021 ASSERT(is_atom(ci->mfa.function) || is_nil(ci->mfa.function));
6022 if (is_atom(ci->mfa.function)) {
6023 tuple = TUPLE2(hp, ci->mfa.function, make_small(ci->mfa.arity));
6024 hp += 3;
6025 result = CONS(hp, tuple, result);
6026 hp += 2;
6027 }
6028 }
6029 HRelease(p, hp_end, hp);
6030 return result;
6031 }
6032
6033 /*
6034 * Builds a list of all NIFs in the given module:
6035 * [{Name, Arity},...]
6036 */
6037 Eterm
nifs_in_module(Process * p,Eterm module)6038 nifs_in_module(Process* p, Eterm module)
6039 {
6040 Eterm nif_list, *hp;
6041 Module *mod;
6042
6043 mod = erts_get_module(module, erts_active_code_ix());
6044 nif_list = NIL;
6045
6046 if (mod->curr.nif != NULL) {
6047 int func_count, func_ix;
6048 ErlNifFunc *funcs;
6049
6050 func_count = erts_nif_get_funcs(mod->curr.nif, &funcs);
6051 hp = HAlloc(p, func_count * 5);
6052
6053 for (func_ix = func_count - 1; func_ix >= 0; func_ix--) {
6054 Eterm name, arity, pair;
6055 ErlNifFunc *func;
6056
6057 func = &funcs[func_ix];
6058
6059 name = am_atom_put(func->name, sys_strlen(func->name));
6060 arity = make_small(func->arity);
6061
6062 pair = TUPLE2(hp, name, arity);
6063 hp += 3;
6064
6065 nif_list = CONS(hp, pair, nif_list);
6066 hp += 2;
6067 }
6068 }
6069
6070 return nif_list;
6071 }
6072
6073 /*
6074 * Returns 'true' if mod has any native compiled functions, otherwise 'false'
6075 */
6076
6077 static Eterm
has_native(BeamCodeHeader * code_hdr)6078 has_native(BeamCodeHeader *code_hdr)
6079 {
6080 Eterm result = am_false;
6081 #ifdef HIPE
6082 if (erts_is_module_native(code_hdr)) {
6083 result = am_true;
6084 }
6085 #endif
6086 return result;
6087 }
6088
6089 void
erts_release_literal_area(ErtsLiteralArea * literal_area)6090 erts_release_literal_area(ErtsLiteralArea* literal_area)
6091 {
6092 struct erl_off_heap_header* oh;
6093
6094 if (!literal_area)
6095 return;
6096
6097 oh = literal_area->off_heap;
6098
6099 while (oh) {
6100 switch (thing_subtag(oh->thing_word)) {
6101 case REFC_BINARY_SUBTAG:
6102 {
6103 Binary* bptr = ((ProcBin*)oh)->val;
6104 erts_bin_release(bptr);
6105 break;
6106 }
6107 case FUN_SUBTAG:
6108 {
6109 ErlFunEntry* fe = ((ErlFunThing*)oh)->fe;
6110 if (erts_refc_dectest(&fe->refc, 0) == 0) {
6111 erts_erase_fun_entry(fe);
6112 }
6113 break;
6114 }
6115 case REF_SUBTAG:
6116 {
6117 ErtsMagicBinary *bptr;
6118 ASSERT(is_magic_ref_thing(oh));
6119 bptr = ((ErtsMRefThing *) oh)->mb;
6120 erts_bin_release((Binary *) bptr);
6121 break;
6122 }
6123 default:
6124 ASSERT(is_external_header(oh->thing_word));
6125 erts_deref_node_entry(((ExternalThing*)oh)->node);
6126 }
6127 oh = oh->next;
6128 }
6129 erts_free(ERTS_ALC_T_LITERAL, literal_area);
6130 }
6131
6132 int
erts_is_module_native(BeamCodeHeader * code_hdr)6133 erts_is_module_native(BeamCodeHeader* code_hdr)
6134 {
6135 Uint i, num_functions;
6136
6137 /* Check NativeAdress of first real function in module */
6138 if (code_hdr != NULL) {
6139 num_functions = code_hdr->num_functions;
6140 for (i=0; i<num_functions; i++) {
6141 ErtsCodeInfo* ci = code_hdr->functions[i];
6142 if (is_atom(ci->mfa.function)) {
6143 return erts_is_function_native(ci);
6144 }
6145 else ASSERT(is_nil(ci->mfa.function)); /* ignore BIF stubs */
6146 }
6147 }
6148 return 0;
6149 }
6150
6151 int
erts_is_function_native(ErtsCodeInfo * ci)6152 erts_is_function_native(ErtsCodeInfo *ci)
6153 {
6154 #ifdef HIPE
6155 ASSERT(BeamIsOpCode(ci->op, op_i_func_info_IaaI));
6156 return BeamIsOpCode(erts_codeinfo_to_code(ci)[0], op_hipe_trap_call) ||
6157 BeamIsOpCode(erts_codeinfo_to_code(ci)[0], op_hipe_trap_call_closure);
6158 #else
6159 return 0;
6160 #endif
6161 }
6162
6163 /*
6164 * Builds a list of all functions including native addresses.
6165 * [{Name,Arity,NativeAddress},...]
6166 */
6167
6168 static Eterm
native_addresses(Process * p,BeamCodeHeader * code_hdr)6169 native_addresses(Process* p, BeamCodeHeader* code_hdr)
6170 {
6171 Eterm result = NIL;
6172 #ifdef HIPE
6173 int i;
6174 Eterm* hp;
6175 Uint num_functions;
6176 Uint need;
6177 Eterm* hp_end;
6178
6179 num_functions = code_hdr->num_functions;
6180 need = (6+BIG_UINT_HEAP_SIZE)*num_functions;
6181 hp = HAlloc(p, need);
6182 hp_end = hp + need;
6183 for (i = num_functions-1; i >= 0 ; i--) {
6184 ErtsCodeInfo *ci = code_hdr->functions[i];
6185 Eterm tuple;
6186
6187 ASSERT(is_atom(ci->mfa.function)
6188 || is_nil(ci->mfa.function)); /* [] if BIF stub */
6189 if (ci->u.ncallee != NULL) {
6190 Eterm addr;
6191 ASSERT(is_atom(ci->mfa.function));
6192 addr = erts_bld_uint(&hp, NULL, (Uint)ci->u.ncallee);
6193 tuple = erts_bld_tuple(&hp, NULL, 3, ci->mfa.function,
6194 make_small(ci->mfa.arity), addr);
6195 result = erts_bld_cons(&hp, NULL, tuple, result);
6196 }
6197 }
6198 HRelease(p, hp_end, hp);
6199 #endif
6200 return result;
6201 }
6202
6203 /*
6204 * Builds a list of all exported functions in the given module:
6205 * [{Name, Arity},...]
6206 */
6207
6208 Eterm
exported_from_module(Process * p,ErtsCodeIndex code_ix,Eterm mod)6209 exported_from_module(Process* p, /* Process whose heap to use. */
6210 ErtsCodeIndex code_ix,
6211 Eterm mod) /* Tagged atom for module. */
6212 {
6213 int i, num_exps;
6214 Eterm* hp = NULL;
6215 Eterm* hend = NULL;
6216 Eterm result = NIL;
6217
6218 num_exps = export_list_size(code_ix);
6219 for (i = 0; i < num_exps; i++) {
6220 Export* ep = export_list(i,code_ix);
6221
6222 if (ep->info.mfa.module == mod) {
6223 Eterm tuple;
6224
6225 if (ep->addressv[code_ix] == ep->beam &&
6226 BeamIsOpCode(ep->beam[0], op_call_error_handler)) {
6227 /* There is a call to the function, but it does not exist. */
6228 continue;
6229 }
6230
6231 if (hp == hend) {
6232 int need = 10 * 5;
6233 hp = HAlloc(p, need);
6234 hend = hp + need;
6235 }
6236 tuple = TUPLE2(hp, ep->info.mfa.function,
6237 make_small(ep->info.mfa.arity));
6238 hp += 3;
6239 result = CONS(hp, tuple, result);
6240 hp += 2;
6241 }
6242 }
6243 HRelease(p,hend,hp);
6244 return result;
6245 }
6246
6247 /*
6248 * Returns a list of all attributes for the module.
6249 */
6250
6251 Eterm
attributes_for_module(Process * p,BeamCodeHeader * code_hdr)6252 attributes_for_module(Process* p, /* Process whose heap to use. */
6253 BeamCodeHeader* code_hdr)
6254 {
6255 byte* ext;
6256 Eterm result = NIL;
6257
6258 ext = code_hdr->attr_ptr;
6259 if (ext != NULL) {
6260 ErtsHeapFactory factory;
6261 erts_factory_proc_prealloc_init(&factory, p, code_hdr->attr_size_on_heap);
6262 result = erts_decode_ext(&factory, &ext, 0);
6263 if (is_value(result)) {
6264 erts_factory_close(&factory);
6265 }
6266 }
6267 return result;
6268 }
6269
6270 /*
6271 * Returns a list containing compilation information.
6272 */
6273
6274 Eterm
compilation_info_for_module(Process * p,BeamCodeHeader * code_hdr)6275 compilation_info_for_module(Process* p, /* Process whose heap to use. */
6276 BeamCodeHeader* code_hdr)
6277 {
6278 byte* ext;
6279 Eterm result = NIL;
6280
6281 ext = code_hdr->compile_ptr;
6282 if (ext != NULL) {
6283 ErtsHeapFactory factory;
6284 erts_factory_proc_prealloc_init(&factory, p, code_hdr->compile_size_on_heap);
6285 result = erts_decode_ext(&factory, &ext, 0);
6286 if (is_value(result)) {
6287 erts_factory_close(&factory);
6288 }
6289 }
6290 return result;
6291 }
6292
6293 /*
6294 * Returns the MD5 checksum for a module
6295 */
6296
6297 Eterm
md5_of_module(Process * p,BeamCodeHeader * code_hdr)6298 md5_of_module(Process* p, /* Process whose heap to use. */
6299 BeamCodeHeader* code_hdr)
6300 {
6301 return new_binary(p, code_hdr->md5_ptr, MD5_SIZE);
6302 }
6303
6304 /*
6305 * Build a single {M,F,A,Loction} item to be part of
6306 * a stack trace.
6307 */
6308 Eterm*
erts_build_mfa_item(FunctionInfo * fi,Eterm * hp,Eterm args,Eterm * mfa_p)6309 erts_build_mfa_item(FunctionInfo* fi, Eterm* hp, Eterm args, Eterm* mfa_p)
6310 {
6311 Eterm loc = NIL;
6312
6313 if (fi->loc != LINE_INVALID_LOCATION) {
6314 Eterm tuple;
6315 int line = LOC_LINE(fi->loc);
6316 int file = LOC_FILE(fi->loc);
6317 Eterm file_term = NIL;
6318
6319 if (file == 0) {
6320 Atom* ap = atom_tab(atom_val(fi->mfa->module));
6321 file_term = buf_to_intlist(&hp, ".erl", 4, NIL);
6322 file_term = buf_to_intlist(&hp, (char*)ap->name, ap->len, file_term);
6323 } else {
6324 file_term = erts_atom_to_string(&hp, (fi->fname_ptr)[file-1]);
6325 }
6326
6327 tuple = TUPLE2(hp, am_line, make_small(line));
6328 hp += 3;
6329 loc = CONS(hp, tuple, loc);
6330 hp += 2;
6331 tuple = TUPLE2(hp, am_file, file_term);
6332 hp += 3;
6333 loc = CONS(hp, tuple, loc);
6334 hp += 2;
6335 }
6336
6337 if (is_list(args) || is_nil(args)) {
6338 *mfa_p = TUPLE4(hp, fi->mfa->module, fi->mfa->function,
6339 args, loc);
6340 } else {
6341 Eterm arity = make_small(fi->mfa->arity);
6342 *mfa_p = TUPLE4(hp, fi->mfa->module, fi->mfa->function,
6343 arity, loc);
6344 }
6345 return hp + 5;
6346 }
6347
6348 /*
6349 * Force setting of the current function in a FunctionInfo
6350 * structure. No source code location will be associated with
6351 * the function.
6352 */
6353 void
erts_set_current_function(FunctionInfo * fi,ErtsCodeMFA * mfa)6354 erts_set_current_function(FunctionInfo* fi, ErtsCodeMFA* mfa)
6355 {
6356 fi->mfa = mfa;
6357 fi->needed = 5;
6358 fi->loc = LINE_INVALID_LOCATION;
6359 }
6360
6361
6362 /*
6363 * Returns a pointer to {module, function, arity}, or NULL if not found.
6364 */
6365 ErtsCodeMFA*
find_function_from_pc(BeamInstr * pc)6366 find_function_from_pc(BeamInstr* pc)
6367 {
6368 FunctionInfo fi;
6369
6370 erts_lookup_function_info(&fi, pc, 0);
6371 return fi.mfa;
6372 }
6373
6374 /*
6375 * Read a specific chunk from a Beam binary.
6376 */
6377
6378 BIF_RETTYPE
code_get_chunk_2(BIF_ALIST_2)6379 code_get_chunk_2(BIF_ALIST_2)
6380 {
6381 Process* p = BIF_P;
6382 Eterm Bin = BIF_ARG_1;
6383 Eterm Chunk = BIF_ARG_2;
6384 Binary* magic = 0;
6385 LoaderState* stp;
6386 Uint chunk = 0;
6387 ErlSubBin* sb;
6388 Uint offset;
6389 Uint bitoffs;
6390 Uint bitsize;
6391 byte* start;
6392 int i;
6393 Eterm res;
6394 Eterm real_bin;
6395 byte* temp_alloc = NULL;
6396
6397 magic = erts_alloc_loader_state();
6398 stp = ERTS_MAGIC_BIN_DATA(magic);
6399 if ((start = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) {
6400 error:
6401 erts_free_aligned_binary_bytes(temp_alloc);
6402 if (magic) {
6403 free_loader_state(magic);
6404 }
6405 BIF_ERROR(p, BADARG);
6406 }
6407 stp->module = THE_NON_VALUE; /* Suppress diagnostics */
6408 for (i = 0; i < 4; i++) {
6409 Eterm* chunkp;
6410 Eterm num;
6411 if (is_not_list(Chunk)) {
6412 goto error;
6413 }
6414 chunkp = list_val(Chunk);
6415 num = CAR(chunkp);
6416 Chunk = CDR(chunkp);
6417 if (!is_byte(num)) {
6418 goto error;
6419 }
6420 chunk = chunk << 8 | unsigned_val(num);
6421 }
6422 if (is_not_nil(Chunk)) {
6423 goto error;
6424 }
6425 if (!init_iff_file(stp, start, binary_size(Bin)) ||
6426 !scan_iff_file(stp, &chunk, 1) ||
6427 stp->chunks[0].start == NULL) {
6428 res = am_undefined;
6429 goto done;
6430 }
6431 ERTS_GET_REAL_BIN(Bin, real_bin, offset, bitoffs, bitsize);
6432 if (bitoffs) {
6433 res = new_binary(p, stp->chunks[0].start, stp->chunks[0].size);
6434 } else {
6435 sb = (ErlSubBin *) HAlloc(p, ERL_SUB_BIN_SIZE);
6436 sb->thing_word = HEADER_SUB_BIN;
6437 sb->orig = real_bin;
6438 sb->size = stp->chunks[0].size;
6439 sb->bitsize = 0;
6440 sb->bitoffs = 0;
6441 sb->offs = offset + (stp->chunks[0].start - start);
6442 sb->is_writable = 0;
6443 res = make_binary(sb);
6444 }
6445
6446 done:
6447 erts_free_aligned_binary_bytes(temp_alloc);
6448 free_loader_state(magic);
6449 return res;
6450 }
6451
6452 /*
6453 * Calculate the MD5 for a module.
6454 */
6455
6456 BIF_RETTYPE
code_module_md5_1(BIF_ALIST_1)6457 code_module_md5_1(BIF_ALIST_1)
6458 {
6459 Process* p = BIF_P;
6460 Eterm Bin = BIF_ARG_1;
6461 Binary* magic;
6462 LoaderState* stp;
6463 byte* bytes;
6464 byte* temp_alloc = NULL;
6465 Eterm res;
6466
6467 magic = erts_alloc_loader_state();
6468 stp = ERTS_MAGIC_BIN_DATA(magic);
6469 if ((bytes = erts_get_aligned_binary_bytes(Bin, &temp_alloc)) == NULL) {
6470 free_loader_state(magic);
6471 BIF_ERROR(p, BADARG);
6472 }
6473 stp->module = THE_NON_VALUE; /* Suppress diagnostiscs */
6474 if (!init_iff_file(stp, bytes, binary_size(Bin)) ||
6475 !scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES) ||
6476 !verify_chunks(stp)) {
6477 res = am_undefined;
6478 goto done;
6479 }
6480 res = new_binary(p, stp->mod_md5, MD5_SIZE);
6481
6482 done:
6483 erts_free_aligned_binary_bytes(temp_alloc);
6484 free_loader_state(magic);
6485 return res;
6486 }
6487
6488 #ifdef HIPE
6489 #define WORDS_PER_FUNCTION (sizeof(ErtsCodeInfo) / sizeof(UWord) + 1)
6490
6491 static BeamInstr*
make_stub(ErtsCodeInfo * info,Eterm mod,Eterm func,Uint arity,Uint native,BeamInstr OpCode)6492 make_stub(ErtsCodeInfo* info, Eterm mod, Eterm func, Uint arity, Uint native, BeamInstr OpCode)
6493 {
6494 DBG_TRACE_MFA(mod,func,arity,"make beam stub at %p", erts_codeinfo_to_code(info));
6495 ASSERT(WORDS_PER_FUNCTION == 6);
6496 info->op = BeamOpCodeAddr(op_i_func_info_IaaI);
6497 info->u.ncallee = (void (*)(void)) native;
6498 info->mfa.module = mod;
6499 info->mfa.function = func;
6500 info->mfa.arity = arity;
6501 erts_codeinfo_to_code(info)[0] = OpCode;
6502 return erts_codeinfo_to_code(info)+1;
6503 }
6504
6505 static byte*
stub_copy_info(LoaderState * stp,int chunk,byte * info,byte ** ptr_word,BeamInstr * size_word,BeamInstr * size_on_heap_word)6506 stub_copy_info(LoaderState* stp,
6507 int chunk, /* Chunk: ATTR_CHUNK or COMPILE_CHUNK */
6508 byte* info, /* Where to store info. */
6509 byte** ptr_word, /* Where to store pointer into info. */
6510 BeamInstr* size_word, /* Where to store size into info. */
6511 BeamInstr* size_on_heap_word) /* Where to store size on heap. */
6512 {
6513 Sint decoded_size;
6514 Uint size = stp->chunks[chunk].size;
6515 if (size != 0) {
6516 sys_memcpy(info, stp->chunks[chunk].start, size);
6517 *ptr_word = info;
6518 decoded_size = erts_decode_ext_size(info, size);
6519 if (decoded_size < 0) {
6520 return 0;
6521 }
6522 *size_word = (BeamInstr) size;
6523 *size_on_heap_word = decoded_size;
6524 }
6525 return info + size;
6526 }
6527
6528 static int
stub_read_export_table(LoaderState * stp)6529 stub_read_export_table(LoaderState* stp)
6530 {
6531 unsigned int i;
6532
6533 GetInt(stp, 4, stp->num_exps);
6534 if (stp->num_exps > stp->num_functions) {
6535 LoadError2(stp, "%u functions exported; only %u functions defined",
6536 stp->num_exps, stp->num_functions);
6537 }
6538 stp->export
6539 = (ExportEntry *) erts_alloc(ERTS_ALC_T_PREPARED_CODE,
6540 stp->num_exps * sizeof(ExportEntry));
6541
6542 for (i = 0; i < stp->num_exps; i++) {
6543 Uint n;
6544
6545 GetInt(stp, 4, n);
6546 GetAtom(stp, n, stp->export[i].function);
6547 GetInt(stp, 4, n);
6548 if (n > MAX_REG) {
6549 LoadError2(stp, "export table entry %u: absurdly high arity %u", i, n);
6550 }
6551 stp->export[i].arity = n;
6552 GetInt(stp, 4, n); /* Ignore label */
6553 }
6554 return 1;
6555
6556 load_error:
6557 return 0;
6558 }
6559
6560 static void
stub_final_touch(LoaderState * stp,ErtsCodeInfo * ci)6561 stub_final_touch(LoaderState* stp, ErtsCodeInfo* ci)
6562 {
6563 unsigned int i;
6564 unsigned int n = stp->num_exps;
6565 Lambda* lp;
6566
6567 if (is_bif(ci->mfa.module, ci->mfa.function, ci->mfa.arity)) {
6568 ci->u.ncallee = NULL;
6569 ci->mfa.module = 0;
6570 ci->mfa.function = 0;
6571 ci->mfa.arity = 0;
6572 return;
6573 }
6574
6575 /*
6576 * Test if the function should be exported.
6577 */
6578
6579 for (i = 0; i < n; i++) {
6580 if (stp->export[i].function == ci->mfa.function &&
6581 stp->export[i].arity == ci->mfa.arity) {
6582 Export* ep = erts_export_put(ci->mfa.module,
6583 ci->mfa.function,
6584 ci->mfa.arity);
6585 ep->addressv[erts_staging_code_ix()] = erts_codeinfo_to_code(ci);
6586 DBG_TRACE_MFA_P(&ci->mfa,"set beam stub at %p in export at %p (code_ix=%d)",
6587 erts_codeinfo_to_code(ci), ep, erts_staging_code_ix());
6588 return;
6589 }
6590 }
6591
6592 /*
6593 * Must be a plain local function or a lambda local function.
6594 * Search the lambda table to find out which.
6595 */
6596
6597 n = stp->num_lambdas;
6598 for (i = 0, lp = stp->lambdas; i < n; i++, lp++) {
6599 ErlFunEntry* fe = stp->lambdas[i].fe;
6600 if (lp->function == ci->mfa.function && lp->arity == ci->mfa.arity) {
6601 *erts_codeinfo_to_code(ci) = BeamOpCodeAddr(op_hipe_trap_call_closure);
6602 fe->address = erts_codeinfo_to_code(ci);
6603 }
6604 }
6605 return;
6606 }
6607
6608
6609 /* Takes an erlang list of addresses:
6610 [{Adr, Patchtyppe} | Addresses]
6611 and the address of a fun_entry.
6612 */
6613 static int
patch(Eterm Addresses,Uint fe)6614 patch(Eterm Addresses, Uint fe)
6615 {
6616 Eterm* listp;
6617 Eterm tuple;
6618 Eterm* tp;
6619 Eterm patchtype;
6620 Uint AddressToPatch;
6621
6622 while (!is_nil(Addresses)) {
6623 listp = list_val(Addresses);
6624
6625 tuple = CAR(listp);
6626 if (is_not_tuple(tuple)) {
6627 return 0; /* Signal error */
6628 }
6629
6630 tp = tuple_val(tuple);
6631 if (tp[0] != make_arityval(2)) {
6632 return 0; /* Signal error */
6633 }
6634
6635 if(term_to_Uint(tp[1], &AddressToPatch) == 0) {
6636 return 0; /* Signal error */
6637 }
6638
6639 patchtype = tp[2];
6640 if (is_not_atom(patchtype)) {
6641 return 0; /* Signal error */
6642 }
6643
6644 hipe_patch_address((Uint *)AddressToPatch, patchtype, fe);
6645
6646 Addresses = CDR(listp);
6647
6648
6649 }
6650
6651 return 1;
6652 }
6653
6654
6655 static int
patch_funentries(Eterm Patchlist)6656 patch_funentries(Eterm Patchlist)
6657 {
6658 while (!is_nil(Patchlist)) {
6659 Eterm Info;
6660 Eterm MFA;
6661 Eterm Addresses;
6662 Eterm tuple;
6663 Eterm Mod;
6664 Eterm* listp;
6665 Eterm* tp;
6666 ErlFunEntry* fe;
6667 Uint index;
6668 Uint uniq;
6669 Uint native_address;
6670
6671 listp = list_val(Patchlist);
6672 tuple = CAR(listp);
6673 Patchlist = CDR(listp);
6674
6675 if (is_not_tuple(tuple)) {
6676 return 0; /* Signal error */
6677 }
6678
6679 tp = tuple_val(tuple);
6680 if (tp[0] != make_arityval(3)) {
6681 return 0; /* Signal error */
6682 }
6683
6684 Info = tp[1];
6685 if (is_not_tuple(Info)) {
6686 return 0; /* Signal error */
6687 }
6688 Addresses = tp[2];
6689 if (is_not_list(Addresses)) {
6690 return 0; /* Signal error */
6691 }
6692
6693 if(term_to_Uint(tp[3], &native_address) == 0) {
6694 return 0; /* Signal error */
6695 }
6696
6697
6698
6699 tp = tuple_val(Info);
6700 if (tp[0] != make_arityval(3)) {
6701 return 0; /* Signal error */
6702 }
6703 MFA = tp[1];
6704 if (is_not_tuple(MFA)) {
6705 return 0; /* Signal error */
6706 }
6707 if(term_to_Uint(tp[2], &uniq) == 0){
6708 return 0; /* Signal error */
6709 }
6710 if(term_to_Uint(tp[3], &index) == 0) {
6711 return 0; /* Signal error */
6712 }
6713
6714
6715
6716
6717 tp = tuple_val(MFA);
6718 if (tp[0] != make_arityval(3)) {
6719 return 0; /* Signal error */
6720 }
6721 Mod = tp[1];
6722 if (is_not_atom(Mod)) {
6723 return 0; /* Signal error */
6724 }
6725
6726
6727
6728 fe = erts_get_fun_entry(Mod, uniq, index);
6729 fe->native_address = (Uint *)native_address;
6730
6731 erts_refc_dec(&fe->refc, 1);
6732
6733 if (!patch(Addresses, (Uint) fe))
6734 return 0;
6735
6736 }
6737 return 1; /* Signal that all went well */
6738 }
6739
6740 /*
6741 * Do a dummy load of a module. No threaded code will be loaded.
6742 * Used for loading native code.
6743 * Will also patch all references to fun_entries to point to
6744 * the new fun_entries created.
6745 */
6746 Eterm
erts_make_stub_module(Process * p,Eterm hipe_magic_bin,Eterm Beam,Eterm Info)6747 erts_make_stub_module(Process* p, Eterm hipe_magic_bin, Eterm Beam, Eterm Info)
6748 {
6749 Binary* magic;
6750 Binary* hipe_magic;
6751 LoaderState* stp;
6752 HipeLoaderState* hipe_stp;
6753 HipeModule *hipe_code;
6754 BeamInstr Funcs;
6755 BeamInstr Patchlist;
6756 Eterm MD5Bin;
6757 Eterm* tp;
6758 BeamCodeHeader* code_hdr;
6759 BeamInstr* code_base;
6760 BeamInstr* fp;
6761 byte* info;
6762 Sint n;
6763 int code_size;
6764 int rval;
6765 Sint i;
6766 byte* temp_alloc = NULL;
6767 byte* bytes;
6768 Uint size;
6769
6770 /*
6771 * Must initialize stp->lambdas here because the error handling code
6772 * at label 'error' uses it.
6773 */
6774 magic = erts_alloc_loader_state();
6775 stp = ERTS_MAGIC_BIN_DATA(magic);
6776 hipe_code = erts_alloc(ERTS_ALC_T_HIPE_LL, sizeof(*hipe_code));
6777
6778 if (!is_internal_magic_ref(hipe_magic_bin) ||
6779 !(hipe_magic = erts_magic_ref2bin(hipe_magic_bin),
6780 hipe_stp = hipe_get_loader_state(hipe_magic)) ||
6781 hipe_stp->module == NIL || hipe_stp->text_segment == 0) {
6782 goto error;
6783 }
6784 if (is_not_tuple(Info)) {
6785 goto error;
6786 }
6787 tp = tuple_val(Info);
6788 if (tp[0] != make_arityval(3)) {
6789 goto error;
6790 }
6791 Funcs = tp[1];
6792 Patchlist = tp[2];
6793 MD5Bin = tp[3];
6794 if (is_not_binary(MD5Bin) || (binary_size(MD5Bin) != MD5_SIZE)) {
6795 goto error;
6796 }
6797 if ((n = erts_list_length(Funcs)) < 0) {
6798 goto error;
6799 }
6800 if ((bytes = erts_get_aligned_binary_bytes(Beam, &temp_alloc)) == NULL) {
6801 goto error;
6802 }
6803 size = binary_size(Beam);
6804
6805 /*
6806 * Scan the Beam binary and read the interesting sections.
6807 */
6808
6809 stp->module = hipe_stp->module;
6810 stp->group_leader = p->group_leader;
6811 stp->num_functions = n;
6812 if (!init_iff_file(stp, bytes, size)) {
6813 goto error;
6814 }
6815 if (!scan_iff_file(stp, chunk_types, NUM_CHUNK_TYPES) ||
6816 !verify_chunks(stp)) {
6817 goto error;
6818 }
6819 define_file(stp, "code chunk header", CODE_CHUNK);
6820 if (!read_code_header(stp)) {
6821 goto error;
6822 }
6823 if (stp->chunks[UTF8_ATOM_CHUNK].size > 0) {
6824 define_file(stp, "utf8 atom table", UTF8_ATOM_CHUNK);
6825 if (!load_atom_table(stp, ERTS_ATOM_ENC_UTF8)) {
6826 goto error;
6827 }
6828 } else {
6829 define_file(stp, "atom table", ATOM_CHUNK);
6830 if (!load_atom_table(stp, ERTS_ATOM_ENC_LATIN1)) {
6831 goto error;
6832 }
6833 }
6834 define_file(stp, "export table", EXP_CHUNK);
6835 if (!stub_read_export_table(stp)) {
6836 goto error;
6837 }
6838
6839 if (stp->chunks[LAMBDA_CHUNK].size > 0) {
6840 define_file(stp, "lambda (fun) table", LAMBDA_CHUNK);
6841 if (!read_lambda_table(stp)) {
6842 goto error;
6843 }
6844 }
6845
6846 /*
6847 * Allocate memory for the stub module.
6848 */
6849
6850 code_size = (offsetof(BeamCodeHeader,functions)
6851 + ((n+1) * sizeof(BeamInstr*))
6852 + (WORDS_PER_FUNCTION*n + 1) * sizeof(BeamInstr)
6853 + stp->chunks[ATTR_CHUNK].size
6854 + stp->chunks[COMPILE_CHUNK].size
6855 + MD5_SIZE);
6856 code_hdr = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
6857 if (!code_hdr) {
6858 goto error;
6859 }
6860
6861 /*
6862 * Initialize code header.
6863 */
6864
6865 code_hdr->num_functions = n;
6866 code_hdr->attr_ptr = NULL;
6867 code_hdr->attr_size = 0;
6868 code_hdr->attr_size_on_heap = 0;
6869 code_hdr->compile_ptr = NULL;
6870 code_hdr->compile_size = 0;
6871 code_hdr->compile_size_on_heap = 0;
6872 code_hdr->literal_area = NULL;
6873 code_hdr->on_load_function_ptr = NULL;
6874 code_hdr->line_table = NULL;
6875 code_hdr->md5_ptr = NULL;
6876
6877 /*
6878 * Make stubs for all functions.
6879 */
6880
6881 fp = code_base = (BeamInstr*) &code_hdr->functions[n+1];
6882 for (i = 0; i < n; i++) {
6883 Eterm* listp;
6884 Eterm tuple;
6885 Eterm* tp;
6886 Eterm func;
6887 Eterm arity_term;
6888 Sint arity;
6889 Uint native_address;
6890 Eterm op;
6891
6892 if (is_nil(Funcs)) {
6893 break;
6894 }
6895 listp = list_val(Funcs);
6896 tuple = CAR(listp);
6897 Funcs = CDR(listp);
6898
6899 /* Error checking */
6900 if (is_not_tuple(tuple)) {
6901 goto error;
6902 }
6903 tp = tuple_val(tuple);
6904 if (tp[0] != make_arityval(3)) {
6905 goto error;
6906 }
6907 func = tp[1];
6908 arity_term = tp[2];
6909 if (is_not_atom(func) || is_not_small(arity_term)) {
6910 goto error;
6911 }
6912 arity = signed_val(arity_term);
6913 if (arity < 0) {
6914 goto error;
6915 }
6916 if (term_to_Uint(tp[3], &native_address) == 0) {
6917 goto error;
6918 }
6919
6920 /*
6921 * Set the pointer and make the stub. Put a return instruction
6922 * as the body until we know what kind of trap we should put there.
6923 */
6924 code_hdr->functions[i] = (ErtsCodeInfo*)fp;
6925 op = BeamOpCodeAddr(op_hipe_trap_call); /* Might be changed later. */
6926 fp = make_stub((ErtsCodeInfo*)fp, hipe_stp->module, func, arity,
6927 (Uint)native_address, op);
6928 }
6929
6930 /*
6931 * Insert the last pointer and the int_code_end instruction.
6932 */
6933
6934 code_hdr->functions[i] = (ErtsCodeInfo*)fp;
6935 *fp++ = BeamOpCodeAddr(op_int_code_end);
6936
6937 /*
6938 * Copy attributes and compilation information.
6939 */
6940
6941 info = (byte *) fp;
6942 info = stub_copy_info(stp, ATTR_CHUNK, info,
6943 &code_hdr->attr_ptr,
6944 &code_hdr->attr_size,
6945 &code_hdr->attr_size_on_heap);
6946 if (info == NULL) {
6947 goto error;
6948 }
6949 info = stub_copy_info(stp, COMPILE_CHUNK, info,
6950 &code_hdr->compile_ptr,
6951 &code_hdr->compile_size,
6952 &code_hdr->compile_size_on_heap);
6953 if (info == NULL) {
6954 goto error;
6955 }
6956 {
6957 byte *tmp = NULL;
6958 byte *md5 = NULL;
6959 if ((md5 = erts_get_aligned_binary_bytes(MD5Bin, &tmp)) != NULL) {
6960 sys_memcpy(info, md5, MD5_SIZE);
6961 code_hdr->md5_ptr = info;
6962 }
6963 erts_free_aligned_binary_bytes(tmp);
6964 }
6965
6966 /*
6967 * Initialise HiPE module
6968 */
6969 hipe_code->text_segment = hipe_stp->text_segment;
6970 hipe_code->text_segment_size = hipe_stp->text_segment_size;
6971 hipe_code->data_segment = hipe_stp->data_segment;
6972 hipe_code->first_hipe_ref = hipe_stp->new_hipe_refs;
6973 hipe_code->first_hipe_sdesc = hipe_stp->new_hipe_sdesc;
6974
6975 /*
6976 * Insert the module in the module table.
6977 */
6978
6979 rval = stub_insert_new_code(p, 0, p->group_leader, hipe_stp->module,
6980 code_hdr, code_size, hipe_code);
6981 if (rval != NIL) {
6982 goto error;
6983 }
6984
6985 /*
6986 * Export all stub functions and insert the correct type of HiPE trap.
6987 */
6988
6989 fp = code_base;
6990 for (i = 0; i < n; i++) {
6991 stub_final_touch(stp, (ErtsCodeInfo*)fp);
6992 fp += WORDS_PER_FUNCTION;
6993 }
6994
6995 if (patch_funentries(Patchlist)) {
6996 Eterm mod = hipe_stp->module;
6997 /* Prevent code from being freed */
6998 hipe_stp->text_segment = 0;
6999 hipe_stp->data_segment = 0;
7000 hipe_stp->new_hipe_refs = NULL;
7001 hipe_stp->new_hipe_sdesc = NULL;
7002
7003 erts_free_aligned_binary_bytes(temp_alloc);
7004 free_loader_state(magic);
7005 hipe_free_loader_state(hipe_stp);
7006
7007 return mod;
7008 }
7009
7010 error:
7011 erts_free(ERTS_ALC_T_HIPE_LL, hipe_code);
7012 erts_free_aligned_binary_bytes(temp_alloc);
7013 free_loader_state(magic);
7014 BIF_ERROR(p, BADARG);
7015 }
7016
erts_commit_hipe_patch_load(Eterm hipe_magic_bin)7017 int erts_commit_hipe_patch_load(Eterm hipe_magic_bin)
7018 {
7019 Binary* hipe_magic;
7020 HipeLoaderState* hipe_stp;
7021 HipeModule *hipe_code;
7022 Module* modp;
7023
7024 if (!is_internal_magic_ref(hipe_magic_bin) ||
7025 !(hipe_magic = erts_magic_ref2bin(hipe_magic_bin),
7026 hipe_stp = hipe_get_loader_state(hipe_magic)) ||
7027 hipe_stp->module == NIL || hipe_stp->text_segment == 0) {
7028 return 0;
7029 }
7030
7031 modp = erts_get_module(hipe_stp->module, erts_active_code_ix());
7032 if (!modp)
7033 return 0;
7034
7035 /*
7036 * Initialise HiPE module
7037 */
7038 hipe_code = erts_alloc(ERTS_ALC_T_HIPE_LL, sizeof(*hipe_code));
7039 hipe_code->text_segment = hipe_stp->text_segment;
7040 hipe_code->text_segment_size = hipe_stp->text_segment_size;
7041 hipe_code->data_segment = hipe_stp->data_segment;
7042 hipe_code->first_hipe_ref = hipe_stp->new_hipe_refs;
7043 hipe_code->first_hipe_sdesc = hipe_stp->new_hipe_sdesc;
7044
7045 modp->curr.hipe_code = hipe_code;
7046
7047 /* Prevent code from being freed */
7048 hipe_stp->text_segment = 0;
7049 hipe_stp->data_segment = 0;
7050 hipe_stp->new_hipe_refs = NULL;
7051 hipe_stp->new_hipe_sdesc = NULL;
7052
7053 hipe_redirect_to_module(modp);
7054
7055 return 1;
7056 }
7057
7058 #undef WORDS_PER_FUNCTION
7059 #endif /* HIPE */
7060
7061
safe_mul(UWord a,UWord b,UWord * resp)7062 static int safe_mul(UWord a, UWord b, UWord* resp)
7063 {
7064 Uint res = a * b; /* XXX:Pan - used in bit syntax, the multiplication has to be stored in Uint */
7065 *resp = res;
7066
7067 if (b == 0) {
7068 return 1;
7069 } else {
7070 return (res / b) == a;
7071 }
7072 }
7073
7074 #ifdef ENABLE_DBG_TRACE_MFA
7075
7076 #define MFA_MAX 10
7077 Eterm dbg_trace_m[MFA_MAX];
7078 Eterm dbg_trace_f[MFA_MAX];
7079 Uint dbg_trace_a[MFA_MAX];
7080 unsigned int dbg_trace_ix = 0;
7081
dbg_set_traced_mfa(const char * m,const char * f,Uint a)7082 void dbg_set_traced_mfa(const char* m, const char* f, Uint a)
7083 {
7084 unsigned i = dbg_trace_ix++;
7085 ASSERT(i < MFA_MAX);
7086 dbg_trace_m[i] = am_atom_put(m, sys_strlen(m));
7087 dbg_trace_f[i] = am_atom_put(f, sys_strlen(f));
7088 dbg_trace_a[i] = a;
7089 }
7090
dbg_is_traced_mfa(Eterm m,Eterm f,Uint a)7091 int dbg_is_traced_mfa(Eterm m, Eterm f, Uint a)
7092 {
7093 unsigned int i;
7094 for (i = 0; i < dbg_trace_ix; ++i) {
7095 if (m == dbg_trace_m[i] &&
7096 (!f || (f == dbg_trace_f[i] && a == dbg_trace_a[i]))) {
7097
7098 return i+1;
7099 }
7100 }
7101 return 0;
7102 }
7103
dbg_vtrace_mfa(unsigned ix,const char * format,...)7104 void dbg_vtrace_mfa(unsigned ix, const char* format, ...)
7105 {
7106 va_list arglist;
7107 va_start(arglist, format);
7108 ASSERT(--ix < MFA_MAX);
7109 erts_fprintf(stderr, "MFA TRACE %T:%T/%u: ",
7110 dbg_trace_m[ix], dbg_trace_f[ix], (int)dbg_trace_a[ix]);
7111
7112 erts_vfprintf(stderr, format, arglist);
7113 va_end(arglist);
7114 }
7115
7116 #endif /* ENABLE_DBG_TRACE_MFA */
7117