aboutsummaryrefslogtreecommitdiffstats
path: root/erts/emulator/beam/beam_load.c
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2010-03-22 14:51:35 +0000
committerErlang/OTP <[email protected]>2010-03-22 15:56:43 +0100
commita4b4d36cdbbd692123443a1d3f19f1c452963201 (patch)
tree218002c4a2b38f69eb67d6388c8034820812fd47 /erts/emulator/beam/beam_load.c
parent835dba95f810cc925ac856171014b9dbea8c90be (diff)
parent24095d93fb28bdd60abe771a426e39c6ff0f72c7 (diff)
downloadotp-a4b4d36cdbbd692123443a1d3f19f1c452963201.tar.gz
otp-a4b4d36cdbbd692123443a1d3f19f1c452963201.tar.bz2
otp-a4b4d36cdbbd692123443a1d3f19f1c452963201.zip
Merge branch 'pan/otp_8332_halfword' into dev
* pan/otp_8332_halfword: Teach testcase in driver_suite the new prototype for driver_async wx: Correct usage of driver callbacks from wx thread Adopt the new (R13B04) Nif functionality to the halfword codebase Support monitoring and demonitoring from driver threads Fix further test-suite problems Correct the VM to work for more test suites Teach {wordsize,internal|external} to system_info/1 Make tracing and distribution work Turn on instruction packing in the loader and virtual machine Add the BeamInstr data type for loaded BEAM code Fix the BEAM dissambler for the half-word emulator Store pointers to heap data in 32-bit words Add a custom mmap wrapper to force heaps into the lower address range Fit all heap data into the 32-bit address range
Diffstat (limited to 'erts/emulator/beam/beam_load.c')
-rw-r--r--erts/emulator/beam/beam_load.c408
1 files changed, 245 insertions, 163 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index 99fab28dce..bbfeac5397 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -1,19 +1,19 @@
/*
* %CopyrightBegin%
- *
- * Copyright Ericsson AB 1996-2009. All Rights Reserved.
- *
+ *
+ * Copyright Ericsson AB 1996-2010. All Rights Reserved.
+ *
* The contents of this file are subject to the Erlang Public License,
* Version 1.1, (the "License"); you may not use this file except in
* compliance with the License. You should have received a copy of the
* Erlang Public License along with this software. If not, it can be
* retrieved online at http://www.erlang.org/.
- *
+ *
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
- *
+ *
* %CopyrightEnd%
*/
@@ -51,9 +51,9 @@ ErlDrvBinary* erts_gzinflate_buffer(char*, int);
#define EXPORTED 2
#ifdef NO_JUMP_TABLE
-# define BeamOpCode(Op) ((Uint)(Op))
+# define BeamOpCode(Op) ((BeamInstr)(Op))
#else
-# define BeamOpCode(Op) ((Eterm)beam_ops[Op])
+# define BeamOpCode(Op) ((BeamInstr)beam_ops[Op])
#endif
#if defined(WORDS_BIGENDIAN)
@@ -94,7 +94,7 @@ typedef struct {
typedef struct {
unsigned type; /* Type of operand. */
- Uint val; /* Value of operand. */
+ BeamInstr val; /* Value of operand. */
Uint bigarity; /* Arity for bignumbers (only). */
} GenOpArg;
@@ -142,7 +142,7 @@ typedef struct {
typedef struct {
Eterm function; /* Tagged atom for function. */
int arity; /* Arity. */
- Eterm* address; /* Address to function in code. */
+ BeamInstr* address; /* Address to function in code. */
} ExportEntry;
#define MakeIffId(a, b, c, d) \
@@ -274,13 +274,13 @@ typedef struct {
int num_functions; /* Number of functions in module. */
int num_labels; /* Number of labels. */
int code_buffer_size; /* Size of code buffer in words. */
- Eterm* code; /* Loaded code. */
+ BeamInstr* code; /* Loaded code. */
int ci; /* Current index into loaded code. */
Label* labels;
- Uint put_strings; /* Linked list of put_string instructions. */
- Uint new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */
+ BeamInstr put_strings; /* Linked list of put_string instructions. */
+ BeamInstr new_bs_put_strings; /* Linked list of i_new_bs_put_string instructions. */
StringPatch* string_patches; /* Linked list of position into string table to patch. */
- Uint catches; /* Linked list of catch_yf instructions. */
+ BeamInstr catches; /* Linked list of catch_yf instructions. */
unsigned loaded_size; /* Final size of code when loaded. */
byte mod_md5[16]; /* MD5 for module code. */
int may_load_nif; /* true if NIFs may later be loaded for this module */
@@ -341,7 +341,7 @@ typedef struct {
#define GetTagAndValue(Stp, Tag, Val) \
do { \
- Uint __w; \
+ BeamInstr __w; \
GetByte(Stp, __w); \
Tag = __w & 0x07; \
if ((__w & 0x08) == 0) { \
@@ -388,7 +388,7 @@ typedef struct {
goto load_error; \
} else { \
int __n = (N); \
- Uint __result = 0; \
+ BeamInstr __result = 0; \
Stp->file_left -= (unsigned) __n; \
while (__n-- > 0) { \
__result = __result << 8 | *Stp->file_p++; \
@@ -465,7 +465,7 @@ static int bin_load(Process *c_p, ErtsProcLocks c_p_locks,
static void init_state(LoaderState* stp);
static int insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
Eterm group_leader, Eterm module,
- Eterm* code, Uint size, Uint catches);
+ BeamInstr* code, Uint size, BeamInstr catches);
static int scan_iff_file(LoaderState* stp, Uint* chunk_types,
Uint num_types, Uint num_mandatory);
static int load_atom_table(LoaderState* stp);
@@ -499,8 +499,8 @@ static void load_printf(int line, LoaderState* context, char *fmt, ...);
static int transform_engine(LoaderState* st);
static void id_to_string(Uint id, char* s);
static void new_genop(LoaderState* stp);
-static int get_int_val(LoaderState* stp, Uint len_code, Uint* result);
-static int get_erlang_integer(LoaderState* stp, Uint len_code, Uint* result);
+static int get_int_val(LoaderState* stp, Uint len_code, BeamInstr* result);
+static int get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result);
static int new_label(LoaderState* stp);
static void new_literal_patch(LoaderState* stp, int pos);
static void new_string_patch(LoaderState* stp, int pos);
@@ -513,7 +513,7 @@ static Eterm compilation_info_for_module(Process* p, Eterm mod);
static Eterm native_addresses(Process* p, Eterm mod);
int patch_funentries(Eterm Patchlist);
int patch(Eterm Addresses, Uint fe);
-static int safe_mul(Uint a, Uint b, Uint* resp);
+static int safe_mul(UWord a, UWord b, UWord* resp);
static int must_swap_floats;
@@ -591,7 +591,18 @@ erts_load_module(Process *c_p,
}
return result;
}
-
+/* #define LOAD_MEMORY_HARD_DEBUG 1*/
+
+#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
+/* Requires allocators ERTS_ALLOC_UTIL_HARD_DEBUG also set in erl_alloc_util.h */
+extern void check_allocators(void);
+extern void check_allocated_block(Uint type, void *blk);
+#define CHKALLOC() check_allocators()
+#define CHKBLK(TYPE,BLK) if ((BLK) != NULL) check_allocated_block((TYPE),(BLK))
+#else
+#define CHKALLOC() /* nothing */
+#define CHKBLK(TYPE,BLK) /* nothing */
+#endif
static int
bin_load(Process *c_p, ErtsProcLocks c_p_locks,
@@ -608,6 +619,12 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Scan the IFF file.
*/
+#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
+ erts_fprintf(stderr,"Loading a module\n");
+#endif
+
+ CHKALLOC();
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
state.file_name = "IFF header for Beam file";
state.file_p = bytes;
state.file_left = unloaded_size;
@@ -619,6 +636,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the header for the code chunk.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
define_file(&state, "code chunk header", CODE_CHUNK);
if (!read_code_header(&state)) {
goto load_error;
@@ -628,6 +646,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the atom table.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
define_file(&state, "atom table", ATOM_CHUNK);
if (!load_atom_table(&state)) {
goto load_error;
@@ -637,6 +656,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the import table.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
define_file(&state, "import table", IMP_CHUNK);
if (!load_import_table(&state)) {
goto load_error;
@@ -646,6 +666,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the lambda (fun) table.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
if (state.chunks[LAMBDA_CHUNK].size > 0) {
define_file(&state, "lambda (fun) table", LAMBDA_CHUNK);
if (!read_lambda_table(&state)) {
@@ -657,6 +678,7 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Read the literal table.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
if (state.chunks[LITERAL_CHUNK].size > 0) {
define_file(&state, "literals table (constant pool)", LITERAL_CHUNK);
if (!read_literal_table(&state)) {
@@ -668,18 +690,25 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* Load the code chunk.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
state.file_name = "code chunk";
state.file_p = state.code_start;
state.file_left = state.code_size;
- if (!load_code(&state) || !freeze_code(&state)) {
+ if (!load_code(&state)) {
goto load_error;
}
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
+ if (!freeze_code(&state)) {
+ goto load_error;
+ }
+
/*
* Read and validate the export table. (This must be done after
* loading the code, because it contains labels.)
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
define_file(&state, "export table", EXP_CHUNK);
if (!read_export_table(&state)) {
goto load_error;
@@ -690,16 +719,25 @@ bin_load(Process *c_p, ErtsProcLocks c_p_locks,
* exported and imported functions. This can't fail.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
rval = insert_new_code(c_p, c_p_locks, state.group_leader, state.module,
state.code, state.loaded_size, state.catches);
if (rval < 0) {
goto load_error;
}
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
final_touch(&state);
/*
* Loading succeded.
*/
+ CHKBLK(ERTS_ALC_T_CODE,state.code);
+#if defined(LOAD_MEMORY_HARD_DEBUG) && defined(DEBUG)
+ erts_fprintf(stderr,"Loaded %T\n",*modp);
+#if 0
+ debug_dump_code(state.code,state.ci);
+#endif
+#endif
rval = 0;
state.code = NULL; /* Prevent code from being freed. */
*modp = state.module;
@@ -791,7 +829,7 @@ init_state(LoaderState* stp)
static int
insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
- Eterm group_leader, Eterm module, Eterm* code, Uint size, Uint catches)
+ Eterm group_leader, Eterm module, BeamInstr* code, Uint size, BeamInstr catches)
{
Module* modp;
int rval;
@@ -833,7 +871,7 @@ insert_new_code(Process *c_p, ErtsProcLocks c_p_locks,
modules[i] = modules[i-1];
}
modules[i].start = code;
- modules[i].end = (Eterm *) (((byte *)code) + size);
+ modules[i].end = (BeamInstr *) (((byte *)code) + size);
num_loaded_modules++;
mid_module = &modules[num_loaded_modules/2];
return 0;
@@ -1083,7 +1121,7 @@ load_import_table(LoaderState* stp)
* the BIF function.
*/
if ((e = erts_find_export_entry(mod, func, arity)) != NULL) {
- if (e->code[3] == (Uint) em_apply_bif) {
+ if (e->code[3] == (BeamInstr) em_apply_bif) {
stp->import[i].bf = (BifFunction) e->code[4];
if (func == am_load_nif && mod == am_erlang && arity == 2) {
stp->may_load_nif = 1;
@@ -1151,7 +1189,7 @@ read_export_table(LoaderState* stp)
* redefine).
*/
if ((e = erts_find_export_entry(stp->module, func, arity)) != NULL) {
- if (e->code[3] == (Uint) em_apply_bif) {
+ if (e->code[3] == (BeamInstr) em_apply_bif) {
int j;
for (j = 0; j < sizeof(allow_redef)/sizeof(allow_redef[0]); j++) {
@@ -1220,7 +1258,7 @@ static int
read_literal_table(LoaderState* stp)
{
int i;
- Uint uncompressed_sz;
+ BeamInstr uncompressed_sz;
byte* uncompressed = 0;
GetInt(stp, 4, uncompressed_sz);
@@ -1338,8 +1376,8 @@ read_code_header(LoaderState* stp)
* Initialize code area.
*/
stp->code_buffer_size = erts_next_heap_size(2048 + stp->num_functions, 0);
- stp->code = (Eterm*) erts_alloc(ERTS_ALC_T_CODE,
- sizeof(Eterm) * stp->code_buffer_size);
+ stp->code = (BeamInstr *) erts_alloc(ERTS_ALC_T_CODE,
+ sizeof(BeamInstr) * stp->code_buffer_size);
stp->code[MI_NUM_FUNCTIONS] = stp->num_functions;
stp->ci = MI_FUNCTIONS + stp->num_functions + 1;
@@ -1365,16 +1403,18 @@ read_code_header(LoaderState* stp)
LoadError2(Stp, "bad tag %d; expected %d", Actual, Expected); \
} else {}
-#define Need(w) \
- ASSERT(ci <= code_buffer_size); \
- if (code_buffer_size < ci+(w)) { \
- code_buffer_size = erts_next_heap_size(ci+(w), 0); \
- stp->code = code \
- = (Eterm *) erts_realloc(ERTS_ALC_T_CODE, \
- (void *) code, \
- code_buffer_size * sizeof(Eterm)); \
- }
+#define CodeNeed(w) do { \
+ ASSERT(ci <= code_buffer_size); \
+ if (code_buffer_size < ci+(w)) { \
+ code_buffer_size = erts_next_heap_size(ci+(w), 0); \
+ stp->code = code \
+ = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, \
+ (void *) code, \
+ code_buffer_size * sizeof(BeamInstr)); \
+ } \
+} while (0)
+#define TermWords(t) (((t) / (sizeof(BeamInstr)/sizeof(Eterm))) + !!((t) % (sizeof(BeamInstr)/sizeof(Eterm))))
static int
@@ -1387,7 +1427,7 @@ load_code(LoaderState* stp)
char* sign;
int arg; /* Number of current argument. */
int num_specific; /* Number of specific ops for current. */
- Eterm* code;
+ BeamInstr* code;
int code_buffer_size;
int specific;
Uint last_label = 0; /* Number of last label. */
@@ -1446,7 +1486,7 @@ load_code(LoaderState* stp)
if (((First) & 0x08) == 0) { \
Val = (First) >> 4; \
} else if (((First) & 0x10) == 0) { \
- Uint __w; \
+ BeamInstr __w; \
GetByte(Stp, __w); \
Val = (((First) >> 5) << 8) | __w; \
} else { \
@@ -1455,7 +1495,7 @@ load_code(LoaderState* stp)
} while (0)
for (arg = 0; arg < arity; arg++) {
- Uint first;
+ BeamInstr first;
GetByte(stp, first);
last_op->a[arg].type = first & 0x07;
@@ -1464,7 +1504,7 @@ load_code(LoaderState* stp)
if ((first & 0x08) == 0) {
last_op->a[arg].val = first >> 4;
} else if ((first & 0x10) == 0) {
- Uint w;
+ BeamInstr w;
GetByte(stp, w);
ASSERT(first < 0x800);
last_op->a[arg].val = ((first >> 5) << 8) | w;
@@ -1523,7 +1563,7 @@ load_code(LoaderState* stp)
break;
case TAG_z:
{
- Uint ext_tag;
+ BeamInstr ext_tag;
unsigned tag;
GetValue(stp, first, ext_tag);
@@ -1531,14 +1571,14 @@ load_code(LoaderState* stp)
case 0: /* Floating point number */
{
Eterm* hp;
-# ifndef ARCH_64
+#if !defined(ARCH_64) || HALFWORD_HEAP /* XXX:PaN - Should use ARCH_64 variant instead */
Uint high, low;
# endif
last_op->a[arg].val = new_literal(stp, &hp,
FLOAT_SIZE_OBJECT);
hp[0] = HEADER_FLONUM;
last_op->a[arg].type = TAG_q;
-# ifdef ARCH_64
+#if defined(ARCH_64) && !HALFWORD_HEAP
GetInt(stp, 8, hp[1]);
# else
GetInt(stp, 4, high);
@@ -1575,10 +1615,10 @@ load_code(LoaderState* stp)
break;
case 3: /* Allocation list. */
{
- Uint n;
- Uint type;
- Uint val;
- Uint words = 0;
+ BeamInstr n;
+ BeamInstr type;
+ BeamInstr val;
+ BeamInstr words = 0;
stp->new_float_instructions = 1;
GetTagAndValue(stp, tag, n);
@@ -1607,7 +1647,7 @@ load_code(LoaderState* stp)
}
case 4: /* Literal. */
{
- Uint val;
+ BeamInstr val;
GetTagAndValue(stp, tag, val);
VerifyTag(stp, tag, TAG_u);
@@ -1734,7 +1774,7 @@ load_code(LoaderState* stp)
}
stp->specific_op = specific;
- Need(opc[stp->specific_op].sz+2); /* Extra margin for packing */
+ CodeNeed(opc[stp->specific_op].sz+2); /* Extra margin for packing */
code[ci++] = BeamOpCode(stp->specific_op);
}
@@ -1772,7 +1812,7 @@ load_code(LoaderState* stp)
case 'c': /* Tagged constant */
switch (tag) {
case TAG_i:
- code[ci++] = make_small(tmp_op->a[arg].val);
+ code[ci++] = (BeamInstr) make_small((Uint) tmp_op->a[arg].val);
break;
case TAG_a:
code[ci++] = tmp_op->a[arg].val;
@@ -1802,7 +1842,7 @@ load_code(LoaderState* stp)
code[ci++] = make_yreg(tmp_op->a[arg].val);
break;
case TAG_i:
- code[ci++] = make_small(tmp_op->a[arg].val);
+ code[ci++] = (BeamInstr) make_small((Uint)tmp_op->a[arg].val);
break;
case TAG_a:
code[ci++] = tmp_op->a[arg].val;
@@ -1896,12 +1936,12 @@ load_code(LoaderState* stp)
if (stp->import[i].bf == NULL) {
LoadError1(stp, "not a BIF: import table index %d", i);
}
- code[ci++] = (Eterm) stp->import[i].bf;
+ code[ci++] = (BeamInstr) stp->import[i].bf;
break;
- case 'P': /* Byte offset into tuple */
+ case 'P': /* Byte offset into tuple */ /* XXX:PaN - * sizeof(Eterm or Eterm *) ? */
VerifyTag(stp, tag, TAG_u);
tmp = tmp_op->a[arg].val;
- code[ci++] = (Eterm) ((tmp_op->a[arg].val+1) * sizeof(Eterm *));
+ code[ci++] = (BeamInstr) ((tmp_op->a[arg].val+1) * sizeof(Eterm));
break;
case 'l': /* Floating point register. */
VerifyTag(stp, tag_to_letter[tag], *sign);
@@ -1925,17 +1965,17 @@ load_code(LoaderState* stp)
for ( ; arg < tmp_op->arity; arg++) {
switch (tmp_op->a[arg].type) {
case TAG_i:
- Need(1);
+ CodeNeed(1);
code[ci++] = make_small(tmp_op->a[arg].val);
break;
case TAG_u:
case TAG_a:
case TAG_v:
- Need(1);
+ CodeNeed(1);
code[ci++] = tmp_op->a[arg].val;
break;
case TAG_f:
- Need(1);
+ CodeNeed(1);
code[ci] = stp->labels[tmp_op->a[arg].val].patches;
stp->labels[tmp_op->a[arg].val].patches = ci;
ci++;
@@ -1947,24 +1987,41 @@ load_code(LoaderState* stp)
lit = stp->literals[tmp_op->a[arg].val].term;
if (is_big(lit)) {
Eterm* bigp;
+ Eterm *tmp;
Uint size;
+ Uint term_size;
bigp = big_val(lit);
- size = bignum_header_arity(*bigp);
- Need(size+1);
- code[ci++] = *bigp++;
- while (size-- > 0) {
- code[ci++] = *bigp++;
+ term_size = bignum_header_arity(*bigp);
+ size = TermWords(term_size + 1);
+ CodeNeed(size);
+ tmp = (Eterm *) (code + ci);
+ *tmp++ = *bigp++;
+ while (term_size-- > 0) {
+ *tmp++ = *bigp++;
}
+ ci +=size;
} else if (is_float(lit)) {
-#ifdef ARCH_64
- Need(1);
+#if defined(ARCH_64) && !HALFWORD_HEAP
+ CodeNeed(1);
code[ci++] = float_val(stp->literals[tmp_op->a[arg].val].term)[1];
+#elif HALFWORD_HEAP
+ Eterm* fptr;
+ Uint size;
+ Eterm *tmp;
+
+ fptr = float_val(stp->literals[tmp_op->a[arg].val].term)+1;
+ size = TermWords(2);
+ CodeNeed(size);
+ tmp = (Eterm *) (code + ci);
+ *tmp++ = *fptr++;
+ *tmp = *fptr;
+ ci += size;
#else
Eterm* fptr;
fptr = float_val(stp->literals[tmp_op->a[arg].val].term)+1;
- Need(2);
+ CodeNeed(2);
code[ci++] = *fptr++;
code[ci++] = *fptr;
#endif
@@ -1984,10 +2041,10 @@ load_code(LoaderState* stp)
*/
if (opc[stp->specific_op].pack[0]) {
char* prog; /* Program for packing engine. */
- Uint stack[8]; /* Stack. */
- Uint* sp = stack; /* Points to next free position. */
- Uint packed = 0; /* Accumulator for packed operations. */
-
+ BeamInstr stack[8]; /* Stack. */
+ BeamInstr* sp = stack; /* Points to next free position. */
+ BeamInstr packed = 0; /* Accumulator for packed operations. */
+
for (prog = opc[stp->specific_op].pack; *prog; prog++) {
switch (*prog) {
case 'g': /* Get instruction; push on stack. */
@@ -2000,7 +2057,7 @@ load_code(LoaderState* stp)
packed = (packed << BEAM_TIGHT_SHIFT) | code[--ci];
break;
case '6': /* Shift 16 steps */
- packed = (packed << 16) | code[--ci];
+ packed = (packed << BEAM_LOOSE_SHIFT) | code[--ci];
break;
case 'p': /* Put instruction (from stack). */
code[ci++] = *--sp;
@@ -2037,9 +2094,9 @@ load_code(LoaderState* stp)
/* Must make room for call_nif op */
int pad = MIN_FUNC_SZ - (finfo_ix - last_func_start);
ASSERT(pad > 0 && pad < MIN_FUNC_SZ);
- Need(pad);
- sys_memmove(&code[finfo_ix+pad], &code[finfo_ix], FINFO_SZ*sizeof(Eterm));
- sys_memset(&code[finfo_ix], 0, pad*sizeof(Eterm));
+ CodeNeed(pad);
+ sys_memmove(&code[finfo_ix+pad], &code[finfo_ix], FINFO_SZ*sizeof(BeamInstr));
+ sys_memset(&code[finfo_ix], 0, pad*sizeof(BeamInstr));
ci += pad;
stp->labels[last_label].value += pad;
}
@@ -2050,6 +2107,7 @@ load_code(LoaderState* stp)
*/
stp->function = code[ci-2];
stp->arity = code[ci-1];
+
ASSERT(stp->labels[last_label].value == ci - FINFO_SZ);
offset = MI_FUNCTIONS + function_number;
code[offset] = stp->labels[last_label].patches;
@@ -2161,7 +2219,6 @@ load_code(LoaderState* stp)
}
}
-#undef Need
load_error:
return 0;
@@ -2373,7 +2430,7 @@ gen_get_integer2(LoaderState* stp, GenOpArg Fail, GenOpArg Ms, GenOpArg Live,
GenOpArg Flags, GenOpArg Dst)
{
GenOp* op;
- Uint bits;
+ UWord bits;
NEW_GENOP(stp, op);
@@ -2838,14 +2895,14 @@ gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
op->a[1].type = TAG_u;
if (Time.type == TAG_i && (timeout = Time.val) >= 0 &&
-#ifdef ARCH_64
+#if defined(ARCH_64) && !HALFWORD_HEAP
(timeout >> 32) == 0
#else
1
#endif
) {
op->a[1].val = timeout;
-#if !defined(ARCH_64)
+#if !defined(ARCH_64) || HALFWORD_HEAP
} else if (Time.type == TAG_q) {
Eterm big;
@@ -2856,11 +2913,13 @@ gen_literal_timeout(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
if (big_arity(big) > 1 || big_sign(big)) {
goto error;
} else {
- (void) term_to_Uint(big, &op->a[1].val);
+ Uint u;
+ (void) term_to_Uint(big, &u);
+ op->a[1].val = (BeamInstr) u;
}
#endif
} else {
-#if !defined(ARCH_64)
+#if !defined(ARCH_64) || HALFWORD_HEAP
error:
#endif
op->op = genop_i_wait_error_0;
@@ -2883,14 +2942,14 @@ gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
op->a[1].type = TAG_u;
if (Time.type == TAG_i && (timeout = Time.val) >= 0 &&
-#ifdef ARCH_64
+#if defined(ARCH_64) && !HALFWORD_HEAP
(timeout >> 32) == 0
#else
1
#endif
) {
op->a[1].val = timeout;
-#ifndef ARCH_64
+#if !defined(ARCH_64) || HALFWORD_HEAP
} else if (Time.type == TAG_q) {
Eterm big;
@@ -2901,11 +2960,13 @@ gen_literal_timeout_locked(LoaderState* stp, GenOpArg Fail, GenOpArg Time)
if (big_arity(big) > 1 || big_sign(big)) {
goto error;
} else {
- (void) term_to_Uint(big, &op->a[1].val);
+ Uint u;
+ (void) term_to_Uint(big, &u);
+ op->a[1].val = (BeamInstr) u;
}
#endif
} else {
-#ifndef ARCH_64
+#if !defined(ARCH_64) || HALFWORD_HEAP
error:
#endif
op->op = genop_i_wait_error_locked_0;
@@ -3321,7 +3382,7 @@ gen_make_fun2(LoaderState* stp, GenOpArg idx)
op->op = genop_i_make_fun_2;
op->arity = 2;
op->a[0].type = TAG_u;
- op->a[0].val = (Uint) fe;
+ op->a[0].val = (BeamInstr) fe;
op->a[1].type = TAG_u;
op->a[1].val = stp->lambdas[idx.val].num_free;
op->next = NULL;
@@ -3342,21 +3403,21 @@ gen_guard_bif(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
op->a[1].type = TAG_u;
bf = stp->import[Bif.val].bf;
if (bf == length_1) {
- op->a[1].val = (Uint) (void *) erts_gc_length_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_length_1;
} else if (bf == size_1) {
- op->a[1].val = (Uint) (void *) erts_gc_size_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_size_1;
} else if (bf == bit_size_1) {
- op->a[1].val = (Uint) (void *) erts_gc_bit_size_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_bit_size_1;
} else if (bf == byte_size_1) {
- op->a[1].val = (Uint) (void *) erts_gc_byte_size_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_byte_size_1;
} else if (bf == abs_1) {
- op->a[1].val = (Uint) (void *) erts_gc_abs_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_abs_1;
} else if (bf == float_1) {
- op->a[1].val = (Uint) (void *) erts_gc_float_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_float_1;
} else if (bf == round_1) {
- op->a[1].val = (Uint) (void *) erts_gc_round_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_round_1;
} else if (bf == trunc_1) {
- op->a[1].val = (Uint) (void *) erts_gc_trunc_1;
+ op->a[1].val = (BeamInstr) (void *) erts_gc_trunc_1;
} else {
abort();
}
@@ -3376,7 +3437,8 @@ gen_guard_bif(LoaderState* stp, GenOpArg Fail, GenOpArg Live, GenOpArg Bif,
static int
freeze_code(LoaderState* stp)
{
- Eterm* code = stp->code;
+ BeamInstr* code = stp->code;
+ Uint *literal_end = NULL;
Uint index;
int i;
byte* str_table;
@@ -3401,46 +3463,49 @@ freeze_code(LoaderState* stp)
* Calculate the final size of the code.
*/
- size = (stp->ci + stp->total_literal_size) * sizeof(Eterm) +
+ size = (stp->ci * sizeof(BeamInstr)) + (stp->total_literal_size * sizeof(Eterm)) +
strtab_size + attr_size + compile_size;
/*
* Move the code to its final location.
*/
- code = (Eterm *) erts_realloc(ERTS_ALC_T_CODE, (void *) code, size);
-
+ code = (BeamInstr *) erts_realloc(ERTS_ALC_T_CODE, (void *) code, size);
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Place a pointer to the op_int_code_end instruction in the
* function table in the beginning of the file.
*/
- code[MI_FUNCTIONS+stp->num_functions] = (Eterm) (code + stp->ci - 1);
+ code[MI_FUNCTIONS+stp->num_functions] = (BeamInstr) (code + stp->ci - 1);
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Store the pointer to the on_load function.
*/
if (stp->on_load) {
- code[MI_ON_LOAD_FUNCTION_PTR] = (Eterm) (code + stp->on_load);
+ code[MI_ON_LOAD_FUNCTION_PTR] = (BeamInstr) (code + stp->on_load);
} else {
code[MI_ON_LOAD_FUNCTION_PTR] = 0;
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ literal_end = (Uint *) (code+stp->ci);
/*
* Place the literal heap directly after the code and fix up all
* put_literal instructions that refer to it.
*/
{
- Eterm* ptr;
- Eterm* low;
- Eterm* high;
+ Uint* ptr;
+ Uint* low;
+ Uint* high;
LiteralPatch* lp;
- low = code+stp->ci;
+ low = (Uint *) (code+stp->ci);
high = low + stp->total_literal_size;
- code[MI_LITERALS_START] = (Eterm) low;
- code[MI_LITERALS_END] = (Eterm) high;
+ code[MI_LITERALS_START] = (BeamInstr) low;
+ code[MI_LITERALS_END] = (BeamInstr) high;
ptr = low;
for (i = 0; i < stp->num_literals; i++) {
Uint offset;
@@ -3472,7 +3537,7 @@ freeze_code(LoaderState* stp)
}
lp = stp->literal_patches;
while (lp != 0) {
- Uint* op_ptr;
+ BeamInstr* op_ptr;
Uint literal;
Literal* lit;
@@ -3485,38 +3550,48 @@ freeze_code(LoaderState* stp)
op_ptr[0] = literal;
lp = lp->next;
}
- stp->ci += stp->total_literal_size;
+ literal_end += stp->total_literal_size;
}
/*
* Place the string table and, optionally, attributes, after the literal heap.
*/
+ CHKBLK(ERTS_ALC_T_CODE,code);
- sys_memcpy(code+stp->ci, stp->chunks[STR_CHUNK].start, strtab_size);
- str_table = (byte *) (code+stp->ci);
+ sys_memcpy(literal_end, stp->chunks[STR_CHUNK].start, strtab_size);
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ str_table = (byte *) literal_end;
if (attr_size) {
byte* attr = str_table + strtab_size;
sys_memcpy(attr, stp->chunks[ATTR_CHUNK].start, stp->chunks[ATTR_CHUNK].size);
- code[MI_ATTR_PTR] = (Eterm) attr;
- code[MI_ATTR_SIZE] = (Eterm) stp->chunks[ATTR_CHUNK].size;
+ code[MI_ATTR_PTR] = (BeamInstr) attr;
+ code[MI_ATTR_SIZE] = (BeamInstr) stp->chunks[ATTR_CHUNK].size;
decoded_size = erts_decode_ext_size(attr, attr_size, 0);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of module attributes");
}
code[MI_ATTR_SIZE_ON_HEAP] = decoded_size;
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
if (compile_size) {
byte* compile_info = str_table + strtab_size + attr_size;
+ CHKBLK(ERTS_ALC_T_CODE,code);
sys_memcpy(compile_info, stp->chunks[COMPILE_CHUNK].start,
stp->chunks[COMPILE_CHUNK].size);
- code[MI_COMPILE_PTR] = (Eterm) compile_info;
- code[MI_COMPILE_SIZE] = (Eterm) stp->chunks[COMPILE_CHUNK].size;
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ code[MI_COMPILE_PTR] = (BeamInstr) compile_info;
+ CHKBLK(ERTS_ALC_T_CODE,code);
+ code[MI_COMPILE_SIZE] = (BeamInstr) stp->chunks[COMPILE_CHUNK].size;
+ CHKBLK(ERTS_ALC_T_CODE,code);
decoded_size = erts_decode_ext_size(compile_info, compile_size, 0);
+ CHKBLK(ERTS_ALC_T_CODE,code);
if (decoded_size < 0) {
LoadError0(stp, "bad external term representation of compilation information");
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
code[MI_COMPILE_SIZE_ON_HEAP] = decoded_size;
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
@@ -3529,9 +3604,10 @@ freeze_code(LoaderState* stp)
while (index != 0) {
Uint next = code[index];
code[index] = BeamOpCode(op_put_string_IId);
- code[index+2] = (Uint) (str_table + code[index+2] + code[index+1] - 1);
+ code[index+2] = (BeamInstr) (str_table + code[index+2] + code[index+1] - 1);
index = next;
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Go through all i_new_bs_put_strings instructions, restore the pointer to
@@ -3543,23 +3619,25 @@ freeze_code(LoaderState* stp)
while (index != 0) {
Uint next = code[index];
code[index] = BeamOpCode(op_bs_put_string_II);
- code[index+2] = (Uint) (str_table + code[index+2]);
+ code[index+2] = (BeamInstr) (str_table + code[index+2]);
index = next;
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
{
StringPatch* sp = stp->string_patches;
while (sp != 0) {
- Uint* op_ptr;
+ BeamInstr* op_ptr;
byte* strp;
op_ptr = code + sp->pos;
strp = str_table + op_ptr[0];
- op_ptr[0] = (Eterm) strp;
+ op_ptr[0] = (BeamInstr) strp;
sp = sp->next;
}
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Resolve all labels.
@@ -3579,10 +3657,11 @@ freeze_code(LoaderState* stp)
ASSERT(this_patch < stp->ci);
next_patch = code[this_patch];
ASSERT(next_patch < stp->ci);
- code[this_patch] = (Uint) (code + value);
+ code[this_patch] = (BeamInstr) (code + value);
this_patch = next_patch;
}
}
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Fix all catch_yf instructions.
@@ -3590,13 +3669,14 @@ freeze_code(LoaderState* stp)
index = stp->catches;
catches = BEAM_CATCHES_NIL;
while (index != 0) {
- Uint next = code[index];
+ BeamInstr next = code[index];
code[index] = BeamOpCode(op_catch_yf);
- catches = beam_catches_cons((Uint*)code[index+2], catches);
+ catches = beam_catches_cons((BeamInstr *)code[index+2], catches);
code[index+2] = make_catch(catches);
index = next;
}
stp->catches = catches;
+ CHKBLK(ERTS_ALC_T_CODE,code);
/*
* Save the updated code pointer and code size.
@@ -3605,6 +3685,7 @@ freeze_code(LoaderState* stp)
stp->code = code;
stp->loaded_size = size;
+ CHKBLK(ERTS_ALC_T_CODE,code);
return 1;
load_error:
@@ -3638,7 +3719,7 @@ final_touch(LoaderState* stp)
* callable yet.
*/
ep->address = ep->code+3;
- ep->code[4] = (Eterm) stp->export[i].address;
+ ep->code[4] = (BeamInstr) stp->export[i].address;
}
}
@@ -3650,14 +3731,14 @@ final_touch(LoaderState* stp)
Eterm mod;
Eterm func;
Uint arity;
- Uint import;
+ BeamInstr import;
Uint current;
Uint next;
mod = stp->import[i].module;
func = stp->import[i].function;
arity = stp->import[i].arity;
- import = (Uint) erts_export_put(mod, func, arity);
+ import = (BeamInstr) erts_export_put(mod, func, arity);
current = stp->import[i].patches;
while (current != 0) {
ASSERT(current < stp->ci);
@@ -3675,7 +3756,7 @@ final_touch(LoaderState* stp)
for (i = 0; i < stp->num_lambdas; i++) {
unsigned entry_label = stp->lambdas[i].label;
ErlFunEntry* fe = stp->lambdas[i].fe;
- Eterm* code_ptr = (Eterm *) (stp->code + stp->labels[entry_label].value);
+ BeamInstr* code_ptr = (BeamInstr *) (stp->code + stp->labels[entry_label].value);
if (fe->address[0] != 0) {
/*
@@ -3807,7 +3888,7 @@ transform_engine(LoaderState* st)
if (i >= st->num_imports || st->import[i].bf == NULL)
goto restart;
if (bif_number != -1 &&
- bif_export[bif_number]->code[4] != (Uint) st->import[i].bf) {
+ bif_export[bif_number]->code[4] != (BeamInstr) st->import[i].bf) {
goto restart;
}
}
@@ -4071,7 +4152,7 @@ load_printf(int line, LoaderState* context, char *fmt,...)
static int
-get_int_val(LoaderState* stp, Uint len_code, Uint* result)
+get_int_val(LoaderState* stp, Uint len_code, BeamInstr* result)
{
Uint count;
Uint val;
@@ -4103,7 +4184,7 @@ get_int_val(LoaderState* stp, Uint len_code, Uint* result)
static int
-get_erlang_integer(LoaderState* stp, Uint len_code, Uint* result)
+get_erlang_integer(LoaderState* stp, Uint len_code, BeamInstr* result)
{
Uint count;
Sint val;
@@ -4124,11 +4205,12 @@ get_erlang_integer(LoaderState* stp, Uint len_code, Uint* result)
count = len_code + 2;
} else {
Uint tag;
+ UWord len_word;
ASSERT(len_code == 7);
- GetTagAndValue(stp, tag, len_code);
+ GetTagAndValue(stp, tag, len_word);
VerifyTag(stp, TAG_u, tag);
- count = len_code + 9;
+ count = len_word + 9;
}
/*
@@ -4376,7 +4458,7 @@ functions_in_module(Process* p, /* Process whose heap to use. */
Eterm mod) /* Tagged atom for module. */
{
Module* modp;
- Eterm* code;
+ BeamInstr* code;
int i;
Uint num_functions;
Eterm* hp;
@@ -4394,9 +4476,9 @@ functions_in_module(Process* p, /* Process whose heap to use. */
num_functions = code[MI_NUM_FUNCTIONS];
hp = HAlloc(p, 5*num_functions);
for (i = num_functions-1; i >= 0 ; i--) {
- Eterm* func_info = (Eterm *) code[MI_FUNCTIONS+i];
- Eterm name = func_info[3];
- int arity = func_info[4];
+ BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ Eterm name = (Eterm) func_info[3];
+ int arity = (int) func_info[4];
Eterm tuple;
ASSERT(is_atom(name));
@@ -4419,7 +4501,7 @@ static Eterm
native_addresses(Process* p, Eterm mod)
{
Module* modp;
- Eterm* code;
+ BeamInstr* code;
int i;
Eterm* hp;
Uint num_functions;
@@ -4442,9 +4524,9 @@ native_addresses(Process* p, Eterm mod)
hp = HAlloc(p, need);
hp_end = hp + need;
for (i = num_functions-1; i >= 0 ; i--) {
- Eterm* func_info = (Eterm *) code[MI_FUNCTIONS+i];
- Eterm name = func_info[3];
- int arity = func_info[4];
+ BeamInstr* func_info = (BeamInstr *) code[MI_FUNCTIONS+i];
+ Eterm name = (Eterm) func_info[3];
+ int arity = (int) func_info[4];
Eterm tuple;
ASSERT(is_atom(name));
@@ -4486,7 +4568,7 @@ exported_from_module(Process* p, /* Process whose heap to use. */
Eterm tuple;
if (ep->address == ep->code+3 &&
- ep->code[3] == (Eterm) em_call_error_handler) {
+ ep->code[3] == (BeamInstr) em_call_error_handler) {
/* There is a call to the function, but it does not exist. */
continue;
}
@@ -4519,7 +4601,7 @@ attributes_for_module(Process* p, /* Process whose heap to use. */
{
Module* modp;
- Eterm* code;
+ BeamInstr* code;
Eterm* hp;
byte* ext;
Eterm result = NIL;
@@ -4559,7 +4641,7 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
Eterm mod) /* Tagged atom for module. */
{
Module* modp;
- Eterm* code;
+ BeamInstr* code;
Eterm* hp;
byte* ext;
Eterm result = NIL;
@@ -4591,8 +4673,8 @@ compilation_info_for_module(Process* p, /* Process whose heap to use. */
/*
* Returns a pointer to {module, function, arity}, or NULL if not found.
*/
-Eterm*
-find_function_from_pc(Eterm* pc)
+BeamInstr *
+find_function_from_pc(BeamInstr* pc)
{
Range* low = modules;
Range* high = low + num_loaded_modules;
@@ -4604,9 +4686,9 @@ find_function_from_pc(Eterm* pc)
} else if (pc > mid->end) {
low = mid + 1;
} else {
- Eterm** low1 = (Eterm **) (mid->start + MI_FUNCTIONS);
- Eterm** high1 = low1 + mid->start[MI_NUM_FUNCTIONS];
- Eterm** mid1;
+ BeamInstr** low1 = (BeamInstr **) (mid->start + MI_FUNCTIONS);
+ BeamInstr** high1 = low1 + mid->start[MI_NUM_FUNCTIONS];
+ BeamInstr** mid1;
while (low1 < high1) {
mid1 = low1 + (high1-low1) / 2;
@@ -4719,10 +4801,10 @@ code_module_md5_1(Process* p, Eterm Bin)
#define WORDS_PER_FUNCTION 6
-static Eterm*
-make_stub(Eterm* fp, Eterm mod, Eterm func, Uint arity, Uint native, Eterm OpCode)
+static BeamInstr*
+make_stub(BeamInstr* fp, Eterm mod, Eterm func, Uint arity, Uint native, BeamInstr OpCode)
{
- fp[0] = (Eterm) BeamOp(op_i_func_info_IaaI);
+ fp[0] = (BeamInstr) BeamOp(op_i_func_info_IaaI);
fp[1] = native;
fp[2] = mod;
fp[3] = func;
@@ -4741,14 +4823,14 @@ static byte*
stub_copy_info(LoaderState* stp,
int chunk, /* Chunk: ATTR_CHUNK or COMPILE_CHUNK */
byte* info, /* Where to store info. */
- Eterm* ptr_word, /* Where to store pointer into info. */
- Eterm* size_word) /* Where to store size of info. */
+ BeamInstr* ptr_word, /* Where to store pointer into info. */
+ BeamInstr* size_word) /* Where to store size of info. */
{
Sint decoded_size;
Uint size = stp->chunks[chunk].size;
if (size != 0) {
memcpy(info, stp->chunks[chunk].start, size);
- *ptr_word = (Eterm) info;
+ *ptr_word = (BeamInstr) info;
decoded_size = erts_decode_ext_size(info, size, 0);
if (decoded_size < 0) {
return 0;
@@ -4791,7 +4873,7 @@ stub_read_export_table(LoaderState* stp)
}
static void
-stub_final_touch(LoaderState* stp, Eterm* fp)
+stub_final_touch(LoaderState* stp, BeamInstr* fp)
{
int i;
int n = stp->num_exps;
@@ -4978,12 +5060,12 @@ Eterm
erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
{
LoaderState state;
- Eterm Funcs;
- Eterm Patchlist;
+ BeamInstr Funcs;
+ BeamInstr Patchlist;
Eterm* tp;
- Eterm* code = NULL;
- Eterm* ptrs;
- Eterm* fp;
+ BeamInstr* code = NULL;
+ BeamInstr* ptrs;
+ BeamInstr* fp;
byte* info;
Uint ci;
int n;
@@ -5072,7 +5154,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Allocate memory for the stub module.
*/
- code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(Eterm);
+ code_size = ((WORDS_PER_FUNCTION+1)*n + MI_FUNCTIONS + 2) * sizeof(BeamInstr);
code_size += state.chunks[ATTR_CHUNK].size;
code_size += state.chunks[COMPILE_CHUNK].size;
code = erts_alloc_fnf(ERTS_ALC_T_CODE, code_size);
@@ -5141,7 +5223,7 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Set the pointer and make the stub. Put a return instruction
* as the body until we know what kind of trap we should put there.
*/
- ptrs[i] = (Eterm) fp;
+ ptrs[i] = (BeamInstr) fp;
#ifdef HIPE
op = (Eterm) BeamOpCode(op_hipe_trap_call); /* Might be changed later. */
#else
@@ -5154,8 +5236,8 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
* Insert the last pointer and the int_code_end instruction.
*/
- ptrs[i] = (Eterm) fp;
- *fp++ = (Eterm) BeamOp(op_int_code_end);
+ ptrs[i] = (BeamInstr) fp;
+ *fp++ = (BeamInstr) BeamOp(op_int_code_end);
/*
* Copy attributes and compilation information.
@@ -5222,9 +5304,9 @@ erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info)
#undef WORDS_PER_FUNCTION
-static int safe_mul(Uint a, Uint b, Uint* resp)
+static int safe_mul(UWord a, UWord b, UWord* resp)
{
- Uint res = a * b;
+ Uint res = a * b; /* XXX:Pan - used in bit syntax, the multiplication has to be stored in Uint */
*resp = res;
if (b == 0) {