zaskar9 / oberon-lang

An LLVM frontend for the Oberon programming language
MIT License
15 stars 2 forks source link

Cross platform support #33

Open tenko opened 3 months ago

tenko commented 3 months ago

I was thinking how to support the diverse number of target the LLVM infrastructure is supporting. There is targets for 64bit, 32bit and 16bit. 8bit target (AVR) is currently marked as "experimental".

(8bit may sound crazy, but these platforms is actually in use very much today in new designs as it replaces transistor/CMOS logic due to the low cost (order of 30 cents). Your christmas lights is probably run on one of these.)

We have the type CHAR and BYTE which should be fixed 8bit.

Then there is SHORTINT, INTEGER and LONGINT. I believe it makes sense to let LONGINT follow the platform pointer size and array size limit. The LEN procedure and SYSTEM.ADR all return a LONGINT.

SET should probably follow LONGINT size?

Proposal:

Platform 8Bit 16Bit 32Bit 64Bit
BYTE 8bit 8bit 8bit 8bit
CHAR 8bit 8bit 8bit 8bit
SHORTINT 8bit 8bit 8bit 8bit
INTEGER 16bit 16bit 16bit 32bit
LONGINT 16bit 16bit 32bit 64bit
SET 16bit 16bit 32bit 64bit
REAL 32bit 32bit 32bit 32bit
LONGREAL 64bit 64bit 64bit 64bit

Legacy Oberon-2 code probably have some assumptions tied to 32bit I guess and could fail on newer 64bit platforms as 64bit platforms was not so common. Legacy Oberon-2 code should work fine on 32bit platform as the bit sizes here are similar to the XDS compiler.

Then if Oberon-07 is to be followed with only REAL, BYTE, INTEGER & SET. INTEGER could be alias for LONGINT and LEN & SYSTEM.ADR etc should work on all platforms.

For Oberon-07 REAL should probably be then possible to select if 32bit or 64bit.

For interface with OS functionality or hardware registers probably fixed integer sizes should be added to SYSTEM. Otherwise this would be to fragile and 64bit integer is missing on 32bit platforms.

I see that many "modern" languages or modernized (C++11) now use fixed sizes. This creates the need for additional types for array sizes and pointers etc and I guess any library code which should be cross platform probably use some kind logic to select a suitable fast integer size for the target platform.

Not looked into any implementation details other than I found the compiler is smart enough to detect when upper bits is discarded in a return statement and acts accordingly for earlier operations.

EDIT : Changed SHORTINT to 8bit on all platforms.

zaskar9 commented 3 months ago

I very much like the idea of standardizing/defining how wide each type is w.r.t. to the target platform! The proposal you made for the different platforms looks reasonable to me!

My impression is that no version of Oberon ever truly targeted a 64-bit platform. For example, I've been looking at Andreas Pirklbauer's Extended Oberon as part of my effort to port some of the standard modules to oberon-lang. In Texts.WriteInt the argument is LONGINT, but is immediately assumed to be 32-bit on line 447.

IF ROR(x, 31) = 1 THEN WriteString(W, " -2147483648")

In dealing with legacy code and Oberon-07, I think it would make sense to have a switch to use 32-bit sizes, even on a 64-bit platform. Depending on how we detect the width of the platform, this could maybe even be achieved by "cross-compilation" based on the target triplet.

tenko commented 3 months ago

Yes, high probability legacy code would fail here anyway this is arranged with 64bit sizes in the mix.

On the XDS compiler the type LONGLONGINT is introduced to keep LONGINT 32bit. Then there is need for separate type for SYSTEM.ADR and LEN will be limited to 32bit which is not ideal, but legacy code will continue to work.

Note I changed the size of SHORTINT to be 8bit on all platforms. It seems the use cases I could find was operation on ORD(ch) or SYSTEM.VAL(BYTE, var) as arithmetic with numbers are not allowed on CHAR and BYTE.

GCC and CLANG have the -m16 .. -m32 flags to select the integer sizes. This could probably be reused here.

The default width could be taken from the target triple with the possibility of override with the -m flag. If LONGINT is forced to 32bit on a 64bit target with the -m32 flag, obviously SYSTEM.ADR would not work any more and a warnings probably should be given.