parrotcode: Some utility functions Contents | C

# NAME

src/utils.c - Some utility functions

# DESCRIPTION

Prototypes are in src/misc.h.

Opcode helper functions that don't really fit elsewhere.

## Functions

`INTVAL intval_mod`

NOTE: This "corrected mod" algorithm is based on the C code on page 70 of [1]. Assuming correct behavior of the built-in mod operator (%) with positive arguments, this algorithm implements a mathematically convenient version of mod, defined thus:

`    x mod y = x - y * floor(x / y)`
For more information on this definition of mod, see section 3.4 of [2], pages 81-85.

References:

[1] Donald E. Knuth, *MMIXware: A RISC Computer for the Third Millennium* Springer, 1999.

[2] Ronald L. Graham, Donald E. Knuth and Oren Patashnik, *Concrete Mathematics*, Second Edition. Addison-Wesley, 1994.

`FLOATVAL floatval_mod`

Returns `n2 mod n3`.

Includes a workaround for buggy code generation in the `lcc` compiler.

## Random Number Generator

Based on the `rand48()` family of functions.

`static void next_rand`

Returns the next random number in `X`.

`static FLOATVAL _erand48`

Returns a `double` in the interval `[0.0, 1.0)`.

`static FLOATVAL _drand48`

Returns a `double` in the interval `[0.0, 1.0)`.

`static long _jrand48`

Returns a `long` in the interval `[-2^31, 2^31)`.

`static long _nrand48`

Returns a `long` in the interval `[0, 2^31)`.

`static long _lrand48`

Returns a `long` in the interval `[0, 2^31)`.

`static long _mrand48`

Returns a `long` in the interval `[-2^31, 2^31)`.

`static void _srand48`

Sets the high order 32 bits to the argument `seed`. The low order 16 bits are set to the arbitrary value 0x330e.

`FLOATVAL Parrot_float_rand`

Returns a `FLOATVAL` in the interval `[0.0, 1.0)`.

`how_random` is ignored.

`INTVAL Parrot_uint_rand`

Returns an `INTVAL` in the interval `[0, 2^31)`.

`how_random` is ignored.

`INTVAL Parrot_int_rand`

Returns an `INTVAL` in the interval `[-2^31, 2^31)`.

`how_random` is ignored.

`INTVAL Parrot_range_rand`

Returns an `INTVAL` in the range `[from, to]`.

`how_random` is ignored.

`void Parrot_srand` Seeds the random number generator with `seed`.

## Array Functions

`void *Parrot_make_la`

Creates a C array of `long`s with one more element than the number of elements in `*array`. The elements are then copied from `*array` to the new array, and the last (extra) element is set to 0.

Used in `src/nci.c`.

`void Parrot_destroy_la`

Use this to destroy an array created with `Parrot_make_la()`.

`void *Parrot_make_cpa`

Creates a C array of `char *`s with one more element than the number of elements in `*array`. The elements are then copied from `*array` to the new array, and the last (extra) element is set to 0.

Currently unused.

Note that you need to free this array with `Parrot_destroy_cpa()`.

`void Parrot_destroy_cpa`

Use this to destroy an array created with `Parrot_make_cpa()`.

`PMC *tm_to_array`

Helper to convert a struct tm * to an Array

`INTVAL Parrot_byte_index`

RT#48260: Not yet documented!!!

`INTVAL Parrot_byte_rindex`

RT#48260: Not yet documented!!!

`static void rec_climb_back_and_mark`

Recursive function, used by Parrot_register_move to climb back the graph of register moves operations.

The node must have a predecessor: it is implicit because if a node has a node_index, it must have a predecessor because the node_index are the index of registers in dest_regs[] array, so by definition they have a corrsponding src_regs register.

Then it emits the move operation with its predecessor, or its backup if already used/visited.

Then continues the climbing if the predecessor was not modified, anf in that case marks it, and set node_index as its backup.

```  node_index  ... the index of a destination (i.e. with a pred.) register
c           ... the graph and all the needed params : the context```
`static void process_cycle_without_exit`

Recursive function, used by Parrot_register_move to handle the case of cycles without exits, that are cycles of move ops between registers where each register has exactly one predecessor and one successor

For instance: 1-->2, 2-->3, 3-->1

```  node_index  ... the index of a destination (i.e. with a pred.) register
c           ... the graph and all the needed params : the context```
`static void move_reg`

should be self-speaking

`void Parrot_register_move`

Move `n_regs` from the given register list `src_regs` to `dest_regs`.

```  n_regs    ... amount of registers to move
dest_regs ... list of register numbers 0..255
src_regs  ... list of register numbers 0..255
temp_reg  ... a register number not in one of these lists
mov       ... a register move function to be called to move one register
mov_alt   ... a register move function to be called to move one register
which triese fetching from an alternate src (or NULLfunc):

(void)  (mov)(interp, dest, src, info);
moved = (mov_alt)(interp, dest, src, info);```
Some `dest_regs` might be the same as `src_regs`, which makes this a bit non-trivial, because if the destination is already clobbered, using it later as source doesn"t work. E.g.

```  0 <- 1
1 <- 0     # register 0 already clobbered```
or

```  2 <- 0
0 <- 1
3 <- 2      # register 2 already clobbered - reorder moves```
To handle such cases, we do:

```  a) rearrange the order of moves (not possible in the first case)
and/or if that failed:
b) if an alternate move function is available, it may fetch the
source from a different (non-clobbered) location - call it.
if the function returns 0 also use c)
c) if no alternate move function is available, use the temp reg```
The amount of register moves should of course be minimal.

TODO The current implementation will not work for following cases

Talked to Leo and he said those cases are not likely (Vishal Soni). 1. I0->I1 I1->I0 I0->I3 2. I1->I2 I3->I2

TODO: Add tests for the above conditions.

# HISTORY

Initial version by leo 2003.09.09.