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