M0 constants segment, deref, and value vs pointer registers

Nathan Brown nbrown04 at gmail.com
Wed Apr 4 04:36:09 UTC 2012


Hello M0 parrot folks,

I've been trying to make M0 pass all of the tests in the repository
and match the spec as best I can, but I'm running into a fundamental
issue in either my understanding or the spec. The exec summary is:

The loading of integer and floating point values out of the constants
segment needs to be handled differently than the loading of strings
and pointers. The simplest solution that I can think of is to deref
integer and floating point values twice and strings and pointers once.
I implemented this and converted all the tests in a branch that can be
found at: https://github.com/nbrown/parrot/tree/m0-c-double-deref
All the tests pass (except the hash and poke_caller ones which I
haven't gotten around to making work yet).

Thanks,
Nate

Here are the gory details:

The C implementation uses the following method to load constants out
of the constants segment:
For each entry in the binary constant segment:
   1) malloc space for the constant data and assign to a void pointer
   2) read the constant data out of the data table into the space
discussed in 1)
   3) store the address of the pointer from 1) into the constant
structure defined at
https://github.com/nbrown/parrot/blob/m0/src/m0/c/include/m0_mob_structures.h#L3

In the end, the const structure is an array of pointers to constant data.

Now, in just about every m0 example and test, you will see some
variation on the following code:
    .version 0
    .chunk "hello"
    .constants
    0 1
    1 "hello, world"
    2 0x0A00
    3 0
    .metadata
    .bytecode
    #I0 is 1
    set_imm I0, 0, 0
    deref   I0, CONSTS, I0

    #I1 is "hello"
    set_imm I1, 0, 1
    deref   I1, CONSTS, I1

This code looks like it loads the constant integer value 1 into
register I0 and the string value "hello world" into I1. Of course
"hello world" cannot be loaded into I1 because the string is greater
than 8 bytes, so my conclusion is that I1 should end up with the
pointer to the string. If deref does the same things for integers and
strings, I0 will have a pointer to the value 1 instead of the value
itself. This isn't really desired since all of the *_i ops expect the
registers to have an actual integer value and not a pointer to that
value.

One straightforward solution is: for any integer or floating point
value to be loaded out of the constant segment, it must be derefed
twice. The second one would use an index of zero. The above sample
would look like:

    .version 0
    .chunk "hello"
    .constants
    0 1
    1 "hello, world"
    2 0x0A00
    3 0
    .metadata
    .bytecode
    #I0 is 1
    set_imm I0, 0, 0
    deref   I0, CONSTS, I0
    deref   I0, I0, 0

    #I1 is "hello"
    set_imm I1, 0, 1
    deref   I1, CONSTS, I1

The second solution would be to leave deref defined as it is right now
and define a second op that would be used to load integer and floating
point constant values correctly.

The last and slightly less straightforward solution to is implement
some logic in the deref op (or a new op) that treats pointers and
strings differently than integers and numeric values. The tricky part
of this is telling when the data fed into the deref op should be
treated as a pointer and string or integer and numeric. (To be
perfectly honest, I already tried to do this by checking the
destination register, but I'm pretty convinced that's not a good idea)

Sooooooo, what do people think? Is the right approach?

If you read this whole thing, thank you very much,
Nate


More information about the parrot-dev mailing list