On Mar 6, 2006, at 23:16, Jonathan Worthington wrote:
"Leopold Toetsch" <[EMAIL PROTECTED]> wrote:
$I0 = pio.'print'("sample data\n") # return sucess (>=0) or
failure (<0)
pio.'print'("sample data\n") # throw exception on failure
Could perhaps get fun for compilers though - what if the program just
throws away the return value? So some optimizer that doesn't know this
subtlety sees this code and throws away the unused return value or
just never emits the assignment, and the behaviour changes. I'm not
sure I like this idea.
Good point. Then I prefer exceptions + return value (which may be
ignored eventually - depending on strictness of retval/result count
error checking).
Depending on the arch (32 vs 64 bits) one of these opcodes is
suboptimal. With a new "L" (Long) register type the functionality
could be handled transparently:
$L0 = pio.'tell'()
Yes, but as you add more register types you get a combinatorial
blow-up on various opcodes.
This depends on the implementation of 'opcodes'. With the current
scheme any such extension isn't really implementable because of the
combinatorial opcode explosion. I've written a (still internal)
proposal that would prevent the combinatorial issue. It (or some
similar thing) would be indeed necessary to even think about more
register types like int8, int16, int32/int64 or float32.
My understanding was that "I" registers were native integers so you
could get good performance, and you used a PMC if you wanted some
guarantees about what size you were talking about.
In the long run, we certainly don't want to use PMCs for e.g.
immplementing bytes (int8) or some such for performance reasons. 'long
long' aka int64 is usually supported by compilers and has for sure by
far better performanche than a BigInt PMC.
Actually using 'int8' or 'float32' is usually only important, if you
have huge arrays of these. That means that there's a very limited need
for opcodes using these types, just some basic math mainly and array
fetch/store. Or in other words: what is supported by the hardware CPU.
The register allocator would map 'L0' either to a pair (I0, I1) on 32
bit arch or just to 'I0' on 64 bit arch.
Yes, but surely it becomes somewhat more than just a mapping problem?
For example, what do we do about:
add L0, L1, L2
mul L0, L1, L2
I don't see any problem with above code.
The register mapping rules would be something like:
- Lx occupies registers I(2x, 2x+1) - this is compile time,
that is 'L1' prevents 'I2' and 'I3' from being assigned by the
register allocator
- the runtime mapping isn't portable due to endianess and sizeof types
'L1' might be 'I1' on 64-bit arch or (I2,I3) or (I3,I2) on 32-bit arch
- if you write PASM, overlapping Ix/Ly may cause warnings or errors,
but could be used in a non-portable way, if you know what you are doing
on a specific platform.
Jonathan
leo