Jump to page: 1 2 3
Thread overview
D design problem on platforms with <32 bit pointer width
Aug 19
Dukc
Aug 19
Dom DiSc
Aug 19
Dukc
Aug 19
sighoya
Aug 19
sighoya
Aug 19
Dom DiSc
Aug 19
Johan
Aug 22
Dukc
Aug 24
Dukc
Aug 20
Johan
Aug 25
Dukc
Aug 20
Johan
Aug 22
Dukc
Aug 22
Dukc
August 19

This is a request for comments. I've written it as a Git gist as opposed to forum post because it's pretty long and may warrant some editing at some point.

Link: https://gist.github.com/dukc/04ea4d4a248ff4709f89d5808f67a5fe

Discussion can remain here though.

August 19

On Saturday, 19 August 2023 at 10:09:56 UTC, Dukc wrote:

>

This is a request for comments. I've written it as a Git gist as opposed to forum post because it's pretty long and may warrant some editing at some point.

Link: https://gist.github.com/dukc/04ea4d4a248ff4709f89d5808f67a5fe

Discussion can remain here though.

I hate those stupid promotion rules.
Every literal should be of the smallest type that can represent it
(e.g. 0..255 should be ubyte, 256..65535 should be ushort, etc., -1..-127 should be byte, -128..-32767 should be short, ...) and can be promoted to whatever is needed implicitly.
Yes, I think -128 should NOT be byte. this would stupid and error prone because abs(-128) cannot be byte. In fact 0x80 should be the NaN of byte, 0x8000 the NaN of short, etc. instead of exceptional negative values.
Also the operations should stay within the same type (largest of the involved operands), e.g. short+short = short.
Internally it may be best to work with the machine word size (whatever that is - could be even 8 bit) but should be truncated to the intended result if not otherwise stated (via cast).

August 19

On Saturday, 19 August 2023 at 10:43:59 UTC, Dom DiSc wrote:

>

I hate those stupid promotion rules.
Every literal should be of the smallest type that can represent it
(e.g. 0..255 should be ubyte, 256..65535 should be ushort, etc., -1..-127 should be byte, -128..-32767 should be short, ...) and can be promoted to whatever is needed implicitly.

It's not quite that simple. Consider:

auto x = 40;
// 1600 now, 64 with your rules
x *= x;

Inference happens at initialisation of the variable. In this case, it's ubyte because nothing bigger is needed to hold the initialisation value. Inference can't detect what is needed later, that is why int literals default to 32 bits.

August 19

On Saturday, 19 August 2023 at 10:09:56 UTC, Dukc wrote:

>

This is a request for comments. I've written it as a Git gist as opposed to forum post because it's pretty long and may warrant some editing at some point.

Link: https://gist.github.com/dukc/04ea4d4a248ff4709f89d5808f67a5fe

Nice, thanks.
I've added my comment (make a table of all interesting cases!) to the gist.

cheers,
Johan

August 19

On Saturday, 19 August 2023 at 10:55:45 UTC, Dukc wrote:

>

Inference happens at initialisation of the variable. In this case, it's ubyte because nothing bigger is needed to hold the initialisation value. Inference can't detect what is needed later, that is why int literals default to 32 bits.

It would be better if 8 bit or 16 bit systems provide some sort of segmented pointer such that allocating 32 bit would be require a struct Ptr {ubyte firstSegment, ubyte secondSegment, ubyte thirdSegment, ubyte fourthSegment} on 8 bit architecture and struct Ptr {ubyte firstSegment, ubyte secondSegment} on 16 bit systems.

August 19

On Saturday, 19 August 2023 at 12:58:48 UTC, sighoya wrote:

>

struct Ptr {ubyte firstSegment, ubyte secondSegment} on
16 bit systems.

ubyte shold be ushort, sorry

August 19

On Saturday, 19 August 2023 at 10:55:45 UTC, Dukc wrote:

>
auto x = 40;
// 1600 now, 64 with your rules
x *= x;

Inference happens at initialisation of the variable.

Sorry, but if you say nothing about which type you want, you may always be surprised unless you know the inference rules.
You could have written

int x = 40;

which incidentally is even one character shorter. And then you have the guarantee that you have 31 bit (+sign) for your calculations - no matter on which hardware you're working.
In your example you expect the C rules. But if the program runs on a 8-bit system, what you get will be a (signed) byte! So the result of your square may be even negative, breaking a whole lot of further assumptions on the result.

August 20
Thanks for taking the time to sum up the issues.

I have a ton of experience with 16 bit code. Abandoning it was an explicit decision for D, mainly to make code portable. Writing code that was portable between 16 and 32 bit was always a major effort for non-trivial code. Fortunately, these days, porting between 32 and 64 bit is trivial.

Some things are impractical for 16 bit code:

1. exception handling
2. garbage collection
3. typeinfo
4. classes (unless using the far memory model)
5. likely the bulk of druntime

I.e. sticking with betterC is more practical.

Some things are impractical for D:

1. mixed near/far pointers

It's fine if a D targeted at 16 bit code has somewhat different semantics. I oppose changing the semantics of 32/64 bit D, as it would break everything.

32 bit integer arithmetic is going to be too slow and consume too much code space, likely unnecessarily.

You correctly identified integer promotion as the cause of most trouble.

So, I propose the following modification for 16 bit code generation:

Keep integer promotion, but have it promote to short rather than int. I haven't thought about it deeply, but first impression says that it will resolve most of the issues.

This will require changing many of the ints in the source code to shorts. How onerous that would be, I do not know. One could do something like:

    version (SixteenBit)
        alias xint = short;
    else
        alias xint = int;

which would make the source code more portable, but keep in mind that integer overflow in the 16 bit world is a major source of unintended problems. 32 bit D code converted to 16 bit will need a thorough review.

Programs targeted at 16 bits are, naturally, going to be small programs. I doubt many D programs are that small. So there shouldn't be too much source code that needs modifying.

Anyhow, it seems like a fun project you're working on!
August 20
To be clear, my proposal would mean that size_t would be an alias for ushort, and ptrdiff_t would be an alias for short.
August 21
On 21/08/2023 7:13 AM, Walter Bright wrote:
> Keep integer promotion, but have it promote to short rather than int. I haven't thought about it deeply, but first impression says that it will resolve most of the issues.

This does beg another question. Should we make integer promotion tied to the largest general purpose (fast) registers for a given target? So AMD64 that'll be (u)long. Whereas 16bit x86 that'll be (u)short.
« First   ‹ Prev
1 2 3