gm2
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Portability Considerations


From: Alice Osako
Subject: Re: Portability Considerations
Date: Mon, 18 Mar 2024 01:38:05 -0400
User-agent: Mozilla Thunderbird

Following Benjamin Kowarsch's advice, I am looking into what it would take to write a suitable API definition for basic bitwise operations, and even in the earliest stages I am already running into a significant problem: the lack of defined sizes for primitive values.

While the Modula-2 language design seems predicated on the assumption that most operations will be on specified sub-sets of the primitive types - a wise but tricky design choice, especially in a systems language where the system word size is often of paramount importance - this assumption only makes sense if the primitive base type is as wide as possible, preferably even multi-word/BigNum widths if the language designer could manage it.

This isn't the case with Modula-2, where there is no mandate for even minimum primitive widths as far as I can tell. Is it really safe to assume that a CARDINAL will be at least 32-bits wide? Perhaps on a modern compiler, but is it really 'portable' if legacy systems are ignored? This is exactly the sort of thing that breaks portability.

For the library to be portable, it has to either define separate byte, 16-bit, 32-bit, and 64-bit procedures for each operation (and hope that the last of those is supported at all), or define a separate type specifically for bitwise operations with a fixed size across all possible platforms (i.e., PACKEDSET/BITSET, but without any native support or operators).

Generics would alleviate this problem, except that generics are themselves not available in PIM, and are a non-standard extension even in ISO.

I noticed that the GCC base libraries include BitByteOps and BitWordOps libraries, but these are not merely non-portable, they are (as far as I can tell) undocumented. Even if this weren't the case, I would rather not have to imitate this design choice - separate, parallel libraries for different word sizes - if I can avoid it.

Again, I am still a novice with Modula-2, so it is entirely possible that I am overlooking something obvious.

While it is only a bare sketch of an API at this point, what I have for now is something along the lines of:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

DEFINITION MODULE Bitwise;

EXPORT QUALIFIED Test, Set,
                 ShiftLeft, ShiftRight, ArithShiftRight,
                 RotateLeft, RotateRight,
                 Not, And, Or, XOr, Impl, NAnd, NOr;

PROCEDURE Test(value: CARDINAL; index: CARDINAL): BOOLEAN;
(* Test - Test whether a given bit in a value is set. *)

PROCEDURE Set(value: CARDINAL; index: CARDINAL): CARDINAL;
(* Set - Set a given bit in a value. *)


PROCEDURE ShiftLeft(value: CARDINAL; shift: CARDINAL): CARDINAL;
(* ShiftLeft - Shift a given value to the left by a certain number of bits. *)

PROCEDURE ShiftRight(value: CARDINAL; shift: CARDINAL): CARDINAL;
(* ShiftRight - Shift a given value to the right by a certain number of bits.  *)

PROCEDURE ArithShiftRight(value: INTEGER; shift: CARDINAL): INTEGER;
(* ArithShiftRight - Shift a given value to the right by a certain number of bits,
                     sign extended.  *)


PROCEDURE RotateLeft(value: CARDINAL; shift: CARDINAL): CARDINAL;
(* RotateLeft - Rotate a given value to the left by a certain number of bits. *)

PROCEDURE RotateRight(value: CARDINAL; shift: CARDINAL): CARDINAL;
(* RotateRight - Rotate a given value to the right by a certain number of bits. *)


PROCEDURE Not(value: CARDINAL): CARDINAL;
(* Not - Invert the bits of value. *)

PROCEDURE And(op1: CARDINAL;  op2: CARDINAL): CARDINAL;
(* And - Returns the bitwise AND of op1 and op2. *)

PROCEDURE Or(op1: CARDINAL;  op2: CARDINAL): CARDINAL;
(* Or - Returns the bitwise OR of op1 and op2. *)

PROCEDURE XOr(op1: CARDINAL;  op2: CARDINAL): CARDINAL;
(* XOr - Returns the bitwise Exclusive-OR of op1 and op2. *)

PROCEDURE Impl(op1: CARDINAL;  op2: CARDINAL): CARDINAL;
(* Impl - Returns the bitwise Implication of op1 and op2. *)

PROCEDURE NAnd(op1: CARDINAL;  op2: CARDINAL): CARDINAL;
(* NAnd - Returns the bitwise NOT AND of op1 and op2. *)

PROCEDURE NOr(op1: CARDINAL;  op2: CARDINAL): CARDINAL;
(* NOr - Returns the bitwise NOT OR of op1 and op2. *)

END Bitwise.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Please recommend any other operations I may have overlooked.

(And yes, I am well aware that IMPL, NAND, and NOR are easily constructed from NOT, AND, and OR, but I still feel that they are worth including. Similarly, I felt that the Rotate operations should be included for completeness.)

I considered adding a 'width' argument to each of these, but it felt like it would be clutter in most cases.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]