Hi
I have built gpc-20040516 for AMD64 (platform: Fedora Core 2, 64-bit).
Binaries can be obtained here: http://gnu-pascal.de/contrib/chief/fedora-2/
Built and tested on an Athlon-64 3.2+, the testsuite ran fine, except for these: TEST asmtest.pas: SKIPPED: only for IA32 TEST az20.pas: ./test_run: line 334: 4929 Segmentation fault ./"$A_OUT" "$1" TEST confarr5.pas: ./test_run: line 334: 9516 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST jj5.pas: SKIPPED: `attribute (stdcall)' not available TEST martin3.pas: ./test_run: line 334: 27275 Segmentation fault ./"$A_OUT" "$1" TEST pack10.pas: ./test_run: line 334: 30277 Segmentation fault ./"$A_OUT" "$1" TEST pack5.pas: ./test_run: line 334: 30396 Segmentation fault ./"$A_OUT" "$1"
One curious thing. "Writeln (sizeof (Integer))" prints "4", as does "Writeln (sizeof (Cardinal))". Shouldn't these be 64-bit?
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
I have built gpc-20040516 for AMD64 (platform: Fedora Core 2, 64-bit).
Binaries can be obtained here: http://gnu-pascal.de/contrib/chief/fedora-2/
Built and tested on an Athlon-64 3.2+, the testsuite ran fine, except for these: TEST asmtest.pas: SKIPPED: only for IA32 TEST az20.pas: ./test_run: line 334: 4929 Segmentation fault ./"$A_OUT" "$1" TEST confarr5.pas: ./test_run: line 334: 9516 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST jj5.pas: SKIPPED: `attribute (stdcall)' not available TEST martin3.pas: ./test_run: line 334: 27275 Segmentation fault ./"$A_OUT" "$1" TEST pack10.pas: ./test_run: line 334: 30277 Segmentation fault ./"$A_OUT" "$1" TEST pack5.pas: ./test_run: line 334: 30396 Segmentation fault ./"$A_OUT" "$1"
The failing tests are known problem: bit-packed arrays do not work on amd64 with 3.x backend. Fixed in 3.4.0. You do not mention `fjf762a.pas' -- I was convinced that is should fail on all 64-bit machines.
One curious thing. "Writeln (sizeof (Integer))" prints "4", as does "Writeln (sizeof (Cardinal))". Shouldn't these be 64-bit?
The manual promises that `Integer' is the same size as C `int'. AFAIK on most 64-bit machines `int' is 32 bit. The consequences of C brain damage are rather unpleasent: -- all use of 64 bit integers became non-standard -- string length is limited to 32 bits -- spurious overflows/truncations since procision by default is limited to 32 bits
On the other hand correcting the problem would break backwards compatibility. Simplest correction would be to say that Pascal `Integer' is equvalent to C `long'. Since on most 32-bit machines both `int' and `long' are 32 bits such a change would not affect popular systems 32-bit systems. Note that currently most m68k systems use 16-bit integers and change to 32 bits would correct many problems.
However, making `Integer' the same as C `long' also has drawbacks: -- 8 and 16 bit processors have 32-bit longs, which may be too large as default size -- AFAIK Microsoft decided to use 32-bit `long' on 64-bit processors (they wont to use `long long' as 64-bit type).
Alternatively, we can exlude Pascal `Integer' from compatibility rules and choose good size in the front end. Or we can make `Integer' the same size as C `size_t'.
I think that main question is if we are willing to break backwards compatibility. Since change in `Integer' size is quite serious difference we can not do this lightly.
Any thoughts?
Waldek Hebisch wrote:
The manual promises that `Integer' is the same size as C `int'. AFAIK on most 64-bit machines `int' is 32 bit. The consequences of C brain damage are rather unpleasent: -- all use of 64 bit integers became non-standard -- string length is limited to 32 bits
I'm not sure if the standard requires it to be limited to `Integer' (of course, that's a bit difficult to decide, since the standard doesn't have any bigger types). But even if we could change it (without changing `Integer'), I don't think it would be worth it, since it's only a small part of the problem.
-- spurious overflows/truncations since procision by default is limited to 32 bits
Of course only if one relies on `Integer' being 64 bits, or `Integer' being able to hold a `Pointer' value. Both are things one shouldn't do anyway.
But I agree that it's not nice -- especially if 32 bit operations are less inefficient, but also otherwise.
On the other hand correcting the problem would break backwards compatibility. Simplest correction would be to say that Pascal `Integer' is equvalent to C `long'. Since on most 32-bit machines both `int' and `long' are 32 bits such a change would not affect popular systems 32-bit systems. Note that currently most m68k systems use 16-bit integers and change to 32 bits would correct many problems.
However, making `Integer' the same as C `long' also has drawbacks: -- 8 and 16 bit processors have 32-bit longs, which may be too large as default size
Does the backend support any 8 or 16 bit platform now?
-- AFAIK Microsoft decided to use 32-bit `long' on 64-bit processors (they wont to use `long long' as 64-bit type).
Even more BD. (Reminds me a bit of Borland keeping `Integer' 16 bits on 32 bit Delphi. BTW, have they finally changed it in newer versions?)
Alternatively, we can exlude Pascal `Integer' from compatibility rules and choose good size in the front end. Or we can make `Integer' the same size as C `size_t'.
That's `SizeType' for us.
I think that main question is if we are willing to break backwards compatibility. Since change in `Integer' size is quite serious difference we can not do this lightly.
It may be too late for a change, I'm not sure ...
As I said, I see the main problems in C interfaces (which so far rely on `Integer = int', while most other places really should not really on exact type sizes etc.). So *if* we change it, we should only change one type, something like `Integer = "undefined" in C', and `CInteger' (or whatever) = `int', so C interfaces would only have to s/Integer/CInteger/g. (And similar for `Cardinal'/`Word', even if nonstandard, but so we keep the fact that `Integer' and `Cardinal' have the same size.)
Of course, we'd also need a transition period here -- add `CInteger' now, let everyone change their interfaces (using GPC-version conditionals to avoid breaking compatibility with older GPCs), sometime change `Integer'. Unpleasant indeed ...
Frank
On 4 Jun 2004 at 4:12, Frank Heckenbach wrote:
[...]
-- AFAIK Microsoft decided to use 32-bit `long' on 64-bit processors (they wont to use `long long' as 64-bit type).
Even more BD. (Reminds me a bit of Borland keeping `Integer' 16 bits on 32 bit Delphi. BTW, have they finally changed it in newer versions?)
"Integer" has always been 32-bit on 32-bit Delphi platforms. It is "Word" that has remained 16-bit (and it still is 16-bit). "Cardinal" is 32-bit, and so is "LongWord".
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Frank Heckenbach wrote:
Waldek Hebisch wrote:
The manual promises that `Integer' is the same size as C `int'. AFAIK on most 64-bit machines `int' is 32 bit. The consequences of C brain damage are rather unpleasent: -- all use of 64 bit integers became non-standard -- string length is limited to 32 bits
I'm not sure if the standard requires it to be limited to `Integer' (of course, that's a bit difficult to decide, since the standard doesn't have any bigger types). But even if we could change it (without changing `Integer'), I don't think it would be worth it, since it's only a small part of the problem.
-- spurious overflows/truncations since procision by default is limited to 32 bits
Of course only if one relies on `Integer' being 64 bits, or `Integer' being able to hold a `Pointer' value. Both are things one shouldn't do anyway.
look at:
const c = 1000*1000*1000*1000; { More readible then 1000000000000 }
the comptiler reports arithmetic overflow (I have fixed that example, but have to check if my fix did not couse bad side effects). And if we inside the compiler fall into the trap I bet that many programs will be (are) affected -- according to the standard `integer' is biggest and the only integer type that adjusts to the machine. So for example `integer' is natural choice as index type for "unlimited" arrays (as the type of schema discriminant).
But I agree that it's not nice -- especially if 32 bit operations are less inefficient, but also otherwise.
Scott Moore wrote:
To reach 32 bit operations in AMD 64, you have to use a mode prefix (from 64 bit mode). Hence, there is an instruction length penalty.
Efficiency is somewhat tricky here. On AMD64 instucions by default use 32 bit operands (but 64 bit addresses). To operate on 64 bits or to use extra registers one have to add a prefix. So 64 bit instructions are longer. But to use a number as an array index one have to extend it to 64 bits, so there are extra instructions. Also, the prefix byte encodes four extra bits, so if it is needed for one reason (say to use extra register) then the penalty is already paid.
AFAIK one of reasons that C uses 32 bit `int' was size -- limiting volume of data to process is belived to have much bigger effect then relative execution efficiency of 32 versus 64 bit instructions.
Note that C mandates wraparoud for unsigned type. Pascal has "affine" point of view, so Pascal backend is allowed to use higher precision if that is faster (but now we get what C folks give us: wraparoud).
On the other hand correcting the problem would break backwards compatibility. Simplest correction would be to say that Pascal `Integer' is equvalent to C `long'. Since on most 32-bit machines both `int' and `long' are 32 bits such a change would not affect popular systems 32-bit systems. Note that currently most m68k systems use 16-bit integers and change to 32 bits would correct many problems.
However, making `Integer' the same as C `long' also has drawbacks: -- 8 and 16 bit processors have 32-bit longs, which may be too large as default size
Does the backend support any 8 or 16 bit platform now?
In standard distribution:
8 bit : AVR 16 bit : 68HC11, H8/300S, pdp11, DSP1600, Xstormy16
there were also attempts to create z80 port.
I think that main question is if we are willing to break backwards compatibility. Since change in `Integer' size is quite serious difference we can not do this lightly.
It may be too late for a change, I'm not sure ...
As I said, I see the main problems in C interfaces (which so far rely on `Integer = int', while most other places really should not really on exact type sizes etc.). So *if* we change it, we should only change one type, something like `Integer = "undefined" in C', and `CInteger' (or whatever) = `int', so C interfaces would only have to s/Integer/CInteger/g. (And similar for `Cardinal'/`Word', even if nonstandard, but so we keep the fact that `Integer' and `Cardinal' have the same size.)
Of course, we'd also need a transition period here -- add `CInteger' now, let everyone change their interfaces (using GPC-version conditionals to avoid breaking compatibility with older GPCs), sometime change `Integer'. Unpleasant indeed ...
Let me try to estimate impact. AFAICS candidate for change are:
m68k 16 --> 32
and 64 bit targets:
alpha, s390x, ia64, ppc64, pa64, sparc64, mips64, sh, amd64
It seems that at the moment alpha and ia64 are really using 64-bit mode, but I have read that developmenet on other platforms is mostly 32 bit. I know that Mandrake included 64 bit version of gpc-20030830, and quite likely other disribution will follow (or already followed). On the other hand Mandrake version had serious bugs, and nobody complained, so the actual usage is likely to be quite small.
Similarely, m68k version was buggy (and we learned about them only thanks to Debian builds).
Also, a buch of bugs that I fixed on AMD64 were generic 64 bit bugs, so I think that at the moment usage on 64 bit machines is quite small.
I would say that now is last chance to do the change. In few month actual use on 64 bit machines is likely to grow considerably -- mostly due to AMD64 (and Intel clone :) but also ppc64 is on mass market (in new Power Macs).
While other targets also would be forced to change type names, since the types would remain the same the change shuild be painless for them.
Waldek Hebisch wrote:
Frank Heckenbach wrote:
Waldek Hebisch wrote:
The manual promises that `Integer' is the same size as C `int'. AFAIK on most 64-bit machines `int' is 32 bit. The consequences of C brain damage are rather unpleasent: -- all use of 64 bit integers became non-standard -- string length is limited to 32 bits
I'm not sure if the standard requires it to be limited to `Integer' (of course, that's a bit difficult to decide, since the standard doesn't have any bigger types). But even if we could change it (without changing `Integer'), I don't think it would be worth it, since it's only a small part of the problem.
-- spurious overflows/truncations since procision by default is limited to 32 bits
Of course only if one relies on `Integer' being 64 bits, or `Integer' being able to hold a `Pointer' value. Both are things one shouldn't do anyway.
look at:
const c = 1000*1000*1000*1000; { More readible then 1000000000000 }
the comptiler reports arithmetic overflow (I have fixed that example, but have to check if my fix did not couse bad side effects).
I see. (Of course, this still relies on there being a 64 bit type or similar, but IMHO that's reasonable assumption in general, although the 8 and 16 bit platforms may have problems, or do they emulate 64 bit operations?)
And if we inside the compiler fall into the trap I bet that many programs will be (are) affected -- according to the standard `integer' is biggest and the only integer type that adjusts to the machine.
The standard doesn't say anything about "adjusts to the machine". The standard only defines one integer type (apart from subranges), but as in many other cases we provide extensions (which are disabled in standard mode).
So for example `integer' is natural choice as index type for "unlimited" arrays (as the type of schema discriminant).
Yes, that's a problem.
But I agree that it's not nice -- especially if 32 bit operations are less inefficient, but also otherwise.
Note that C mandates wraparoud for unsigned type. Pascal has "affine" point of view, so Pascal backend is allowed to use higher precision if that is faster (but now we get what C folks give us: wraparoud).
That's another bug (missing overflow checking). As long as we declare `MaxInt' to be the maximum value of the type `Integer' (not necessarily of any integer type provided as an extension) we're at least conformant here (even though we may add unnecessary restrictions, it's not actually incorrect).
As I said, I see the main problems in C interfaces (which so far rely on `Integer = int', while most other places really should not really on exact type sizes etc.). So *if* we change it, we should only change one type, something like `Integer = "undefined" in C', and `CInteger' (or whatever) = `int', so C interfaces would only have to s/Integer/CInteger/g. (And similar for `Cardinal'/`Word', even if nonstandard, but so we keep the fact that `Integer' and `Cardinal' have the same size.)
Of course, we'd also need a transition period here -- add `CInteger' now, let everyone change their interfaces (using GPC-version conditionals to avoid breaking compatibility with older GPCs), sometime change `Integer'. Unpleasant indeed ...
Let me try to estimate impact. AFAICS candidate for change are:
m68k 16 --> 32
and 64 bit targets:
alpha, s390x, ia64, ppc64, pa64, sparc64, mips64, sh, amd64
It seems that at the moment alpha and ia64 are really using 64-bit mode, but I have read that developmenet on other platforms is mostly 32 bit. I know that Mandrake included 64 bit version of gpc-20030830, and quite likely other disribution will follow (or already followed). On the other hand Mandrake version had serious bugs, and nobody complained, so the actual usage is likely to be quite small.
Similarely, m68k version was buggy (and we learned about them only thanks to Debian builds).
Also, a buch of bugs that I fixed on AMD64 were generic 64 bit bugs, so I think that at the moment usage on 64 bit machines is quite small.
I would say that now is last chance to do the change. In few month actual use on 64 bit machines is likely to grow considerably -- mostly due to AMD64 (and Intel clone :) but also ppc64 is on mass market (in new Power Macs).
While other targets also would be forced to change type names, since the types would remain the same the change shuild be painless for them.
I see it a bit differently. I don't like to use a "wrong" type (i.e., `Integer' for `int' when it's actually `long', just because it happens to match on most platforms). In fact, to me it means that such instances will be harder to find for people (most have no access to a 64 bit platform).
But I agree that if we change it, we should do it quickly. Some arguments for and against the change have been given, but I'm still undecided (or rather, I personally wouldn't mind either way).
If we change it, we must agree on which changes exactly -- as I said, I propose `CInteger', `CCardinal', `CWord'(?) as equivalent to `[unsigned] int', and `Integer', `Cardinal', `Word' to be equivalent to `[unsigned] long int', at least on some platforms (Waldek seems to know better, which ones). This would keep the impact on C interfaces minimal AFAICS.
Frank
Frank Heckenbach wrote:
Waldek Hebisch wrote:
Frank Heckenbach wrote:
As I said, I see the main problems in C interfaces (which so far rely on `Integer = int', while most other places really should not really on exact type sizes etc.). So *if* we change it, we should only change one type, something like `Integer = "undefined" in C', and `CInteger' (or whatever) = `int', so C interfaces would only have to s/Integer/CInteger/g. (And similar for `Cardinal'/`Word', even if nonstandard, but so we keep the fact that `Integer' and `Cardinal' have the same size.)
Of course, we'd also need a transition period here -- add `CInteger' now, let everyone change their interfaces (using GPC-version conditionals to avoid breaking compatibility with older GPCs), sometime change `Integer'. Unpleasant indeed ...
Let me try to estimate impact. AFAICS candidate for change are:
m68k 16 --> 32
and 64 bit targets:
alpha, s390x, ia64, ppc64, pa64, sparc64, mips64, sh, amd64
While other targets also would be forced to change type names, since the types would remain the same the change shuild be painless for them.
I see it a bit differently. I don't like to use a "wrong" type (i.e., `Integer' for `int' when it's actually `long', just because it happens to match on most platforms). In fact, to me it means that such instances will be harder to find for people (most have no access to a 64 bit platform).
But I agree that if we change it, we should do it quickly. Some arguments for and against the change have been given, but I'm still undecided (or rather, I personally wouldn't mind either way).
If we change it, we must agree on which changes exactly -- as I said, I propose `CInteger', `CCardinal', `CWord'(?) as equivalent to `[unsigned] int', and `Integer', `Cardinal', `Word' to be equivalent to `[unsigned] long int', at least on some platforms (Waldek seems to know better, which ones). This would keep the impact on C interfaces minimal AFAICS.
I propose to make `Integer' equivalent to `PtrInt', `Cardinal' to `PtrCard', `Word' to `PtrWord' (so also `PtrCard'). And `CInteger', `CCardinal', `CWord' should be equivalent to `[unsigned] int'.
Why: `PtrInt' should be of correct size as index of any array,, so there is no need to special case (C `long' may be to big or even to small). On the other hand on most platforms `PtrInt' is of the same size as C `int', so the impact is limited (as I wrote above).
Waldek Hebisch wrote:
Frank Heckenbach wrote:
Waldek Hebisch wrote:
Frank Heckenbach wrote:
As I said, I see the main problems in C interfaces (which so far rely on `Integer = int', while most other places really should not really on exact type sizes etc.). So *if* we change it, we should only change one type, something like `Integer = "undefined" in C', and `CInteger' (or whatever) = `int', so C interfaces would only have to s/Integer/CInteger/g. (And similar for `Cardinal'/`Word', even if nonstandard, but so we keep the fact that `Integer' and `Cardinal' have the same size.)
Of course, we'd also need a transition period here -- add `CInteger' now, let everyone change their interfaces (using GPC-version conditionals to avoid breaking compatibility with older GPCs), sometime change `Integer'. Unpleasant indeed ...
Let me try to estimate impact. AFAICS candidate for change are:
m68k 16 --> 32
and 64 bit targets:
alpha, s390x, ia64, ppc64, pa64, sparc64, mips64, sh, amd64
While other targets also would be forced to change type names, since the types would remain the same the change shuild be painless for them.
I see it a bit differently. I don't like to use a "wrong" type (i.e., `Integer' for `int' when it's actually `long', just because it happens to match on most platforms). In fact, to me it means that such instances will be harder to find for people (most have no access to a 64 bit platform).
But I agree that if we change it, we should do it quickly. Some arguments for and against the change have been given, but I'm still undecided (or rather, I personally wouldn't mind either way).
If we change it, we must agree on which changes exactly -- as I said, I propose `CInteger', `CCardinal', `CWord'(?) as equivalent to `[unsigned] int', and `Integer', `Cardinal', `Word' to be equivalent to `[unsigned] long int', at least on some platforms (Waldek seems to know better, which ones). This would keep the impact on C interfaces minimal AFAICS.
I propose to make `Integer' equivalent to `PtrInt', `Cardinal' to `PtrCard', `Word' to `PtrWord' (so also `PtrCard'). And `CInteger', `CCardinal', `CWord' should be equivalent to `[unsigned] int'.
Why: `PtrInt' should be of correct size as index of any array,, so there is no need to special case (C `long' may be to big or even to small). On the other hand on most platforms `PtrInt' is of the same size as C `int', so the impact is limited (as I wrote above).
The bottom line is, is GPC going to be a Pascal, or is it going to be a C look-alike ? The traditions and the standard for Pascal are explicit: integer is supposed to be the largest size that does not carry extra cost on the target machine. Specifying smaller sizes is clearly the scope of subranges, specification of larger types (like double precision) is not covered by either the original or standardized languages (which is not the same thing as non-existent).
Pascal gives methods for specifying the exact type in an (extremely) portable way. Somewhere it became normal with many Pascals to adopt C's method instead, despite the fact that it is less portable (ie, every size has a predefined, labeled type).
Even that aside, "dragging" integer or int is a loosing strategy even in C. It puts off the inevitable change to the larger size until tomorrow, meaning that programmers have more time to entrench programs using the wrong size. Only the slow realization that the natural word width of the (by then most common) machine is being wasted counters that, and the result is programmers distrusting the int or integer type, and instead forcing more use of specifically sized types with special labels, furthering the scattering of dependencies.
Yes, I know I am being a bit preachy on the subject, but its an important one.
Scott Moore wrote:
Waldek Hebisch wrote:
Frank Heckenbach wrote:
Waldek Hebisch wrote:
Frank Heckenbach wrote:
As I said, I see the main problems in C interfaces (which so far rely on `Integer = int', while most other places really should not really on exact type sizes etc.). So *if* we change it, we should only change one type, something like `Integer = "undefined" in C', and `CInteger' (or whatever) = `int', so C interfaces would only have to s/Integer/CInteger/g. (And similar for `Cardinal'/`Word', even if nonstandard, but so we keep the fact that `Integer' and `Cardinal' have the same size.)
Of course, we'd also need a transition period here -- add `CInteger' now, let everyone change their interfaces (using GPC-version conditionals to avoid breaking compatibility with older GPCs), sometime change `Integer'. Unpleasant indeed ...
Let me try to estimate impact. AFAICS candidate for change are:
m68k 16 --> 32
and 64 bit targets:
alpha, s390x, ia64, ppc64, pa64, sparc64, mips64, sh, amd64
While other targets also would be forced to change type names, since the types would remain the same the change shuild be painless for them.
I see it a bit differently. I don't like to use a "wrong" type (i.e., `Integer' for `int' when it's actually `long', just because it happens to match on most platforms). In fact, to me it means that such instances will be harder to find for people (most have no access to a 64 bit platform).
But I agree that if we change it, we should do it quickly. Some arguments for and against the change have been given, but I'm still undecided (or rather, I personally wouldn't mind either way).
If we change it, we must agree on which changes exactly -- as I said, I propose `CInteger', `CCardinal', `CWord'(?) as equivalent to `[unsigned] int', and `Integer', `Cardinal', `Word' to be equivalent to `[unsigned] long int', at least on some platforms (Waldek seems to know better, which ones). This would keep the impact on C interfaces minimal AFAICS.
I propose to make `Integer' equivalent to `PtrInt', `Cardinal' to `PtrCard', `Word' to `PtrWord' (so also `PtrCard'). And `CInteger', `CCardinal', `CWord' should be equivalent to `[unsigned] int'.
Why: `PtrInt' should be of correct size as index of any array,, so there is no need to special case (C `long' may be to big or even to small). On the other hand on most platforms `PtrInt' is of the same size as C `int', so the impact is limited (as I wrote above).
I agree. (BTW, you mentioned some 8 and 16 bit targets, Waldek. Is this change also ok there, or do we need exceptions for them? I don't know details about any of them.)
I've just talked with Peter, and he also agrees.
The changes in the compiler are not difficult, of course. We see the most effort in changing C interfaces. I suggest something like this:
{$if __GPC_RELEASE__ < 20040801} type CInteger = Integer; CCardinal = Cardinal; CWord = Word; {$endif}
And replace `Integer', `Cardinal' and `Word' in the declarations with `C...'.
With the above conditional, the interfaces will keep working with existing GPC releases, and the change can be made already now (as soon as we've agreed on this, of course), so this should be least painful.
Eike, if you're reading this, since you wrote a lot of C interfaces: Is this OK with you?
The bottom line is, is GPC going to be a Pascal, or is it going to be a C look-alike ? The traditions and the standard for Pascal are explicit: integer is supposed to be the largest size that does not carry extra cost on the target machine. Specifying smaller sizes is clearly the scope of subranges, specification of larger types (like double precision) is not covered by either the original or standardized languages (which is not the same thing as non-existent).
Well, in a strictly standard compiler (such as GPC with `--classic-pascal' or `--extended-pascal') it's the same thing.
Pascal gives methods for specifying the exact type in an (extremely) portable way.
Not really. The standards do not specify type sizes in any way. Subranges can have the same or a smaller size than `Integer'. You might prefer the latter, I do the former. (For several reasons, (a) efficiency, especially on processors without built-in sub-word operations, (b) conceptually, I like to consider subranges as the same type as the original (i.e., the type of the bounds), with additional constraints; in the same way I could imagine subsets of other types, such as Real (but I don't want to go into this now), (c) with enum types, having types of different sizes would add unnecessary (IMHO) complexity).
Somewhere it became normal with many Pascals to adopt C's method instead, despite the fact that it is less portable (ie, every size has a predefined, labeled type).
Of course, I don't like this method at all. But we have to consider different purposes:
- Types of exact sizes (e.g., for file formats, though there are other considerations, such as endianness): GPC has `attribute size' here, and since neither C nor standard Pascal really have something like this at all, IMHO it's the best we can get.
- C compatibility types (needed in interfaces, of course). Here we have to follow the C model, but we're free to choose our names (such as `CInteger' in the proposed model).
- Types to hold certain ranges of values which should be handled efficiently, without caring about storage details. That's where subranges are best suited.
- etc. (there may be more purposes to consider when choosing types) ...
Even that aside, "dragging" integer or int is a loosing strategy even in C. It puts off the inevitable change to the larger size until tomorrow, meaning that programmers have more time to entrench programs using the wrong size.
BTW, I'm not sure that C ABIs will actually change in the future. Maybe C programmers will simply become used to using `long' almost everywhere, just like programmers of Borland Pascal and, especially, compatible 32 bit compilers, use `LongInt' regularly ...
Only the slow realization that the natural word width of the (by then most common) machine is being wasted counters that, and the result is programmers distrusting the int or integer type, and instead forcing more use of specifically sized types with special labels, furthering the scattering of dependencies.
Yes, I know I am being a bit preachy on the subject, but its an important one.
In fact, in C it might not even be regarded as a problem since `long' is a built-in type just as well as `int'.
But in Pascal `Integer' has a special status, so IMHO it's right to take the issue seriously.
And I think we agree on Waldek's proposal, don't we?
Frank
On 11 Jul 2004 at 15:32, Frank Heckenbach wrote: [....]
Yes, I know I am being a bit preachy on the subject, but its an important one.
In fact, in C it might not even be regarded as a problem since `long' is a built-in type just as well as `int'.
But in Pascal `Integer' has a special status, so IMHO it's right to take the issue seriously.
And I think we agree on Waldek's proposal, don't we?
It's all fine for me ...
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Frank Heckenbach wrote:
Waldek Hebisch wrote:
I propose to make `Integer' equivalent to `PtrInt', `Cardinal' to `PtrCard', `Word' to `PtrWord' (so also `PtrCard'). And `CInteger', `CCardinal', `CWord' should be equivalent to `[unsigned] int'.
<snip>
The changes in the compiler are not difficult, of course. We see the most effort in changing C interfaces. I suggest something like this:
{$if __GPC_RELEASE__ < 20040801} type CInteger = Integer; CCardinal = Cardinal; CWord = Word; {$endif}
And replace `Integer', `Cardinal' and `Word' in the declarations with `C...'.
<snip>
- C compatibility types (needed in interfaces, of course). Here we have to follow the C model, but we're free to choose our names (such as `CInteger' in the proposed model).
<snip>
And I think we agree on Waldek's proposal, don't we?
I agree on the size issue, but not on the proposed nomenclature. Since the purpose of the C-type names is C-header conversion, C-like names will be more practical.
CChar CSignedChar CUnsignedChar CShort CSignedShort CUnsignedShort CInt CSignedInt CUnsignedInt CLong CSignedLong CUnsignedLong CLongLong CSignedLongLong CUnsignedLongLong
Regards,
Adriaan van Os
Adriaan van Os wrote:
I agree on the size issue, but not on the proposed nomenclature. Since the purpose of the C-type names is C-header conversion, C-like names will be more practical.
CChar CSignedChar CUnsignedChar CShort CSignedShort CUnsignedShort CInt CSignedInt CUnsignedInt CLong CSignedLong CUnsignedLong CLongLong CSignedLongLong CUnsignedLongLong
Well, Peter and I have thought about this, but came to the conclusion that the effort (much more renaming, and more types in total, since we'd, e.g., have `CLongLong' and (Pascal extension) `LongInt' with the same meaning) is not justified by the cleaner nomenclature. Especially since in the future we plan to have an automatic translator to care about the C names.
As for `CInt' vs. `CInteger', I don't mind very much, but since we have `CString' and not `CCharStar' ;-), I thought `CInteger' to me reasonable ...
Frank
Frank Heckenbach wrote:
Well, Peter and I have thought about this, but came to the conclusion that the effort (much more renaming, and more types in total, since we'd, e.g., have `CLongLong' and (Pascal extension) `LongInt' with the same meaning) is not justified by the cleaner nomenclature. Especially since in the future we plan to have an automatic translator to care about the C names.
An automatic C-header translator would be quite useful.
As for `CInt' vs. `CInteger', I don't mind very much, but since we have `CString' and not `CCharStar' ;-), I thought `CInteger' to me reasonable ...
I dislike "CString" because it obfuscates the difference between a data structure and a pointer to a datastructure -- not to mention the runtime issues involded. Same with Delphi. To me, a "CString" is a sequence of characters, followed by a char( 0). This is not the same as a pointer to those characters, allocated dynamically on the heap. Sidebar -- what happens is the dynamic allocation fails ?
In my perception, a well written algorithm is the reflection of clear thinking, Clear thinking is inextricably bound to clear terminology and utmost attention to detail.
Regards.
Adriaan van Os
Adriaan van Os wrote:
I dislike "CString" because it obfuscates the difference between a data structure and a pointer to a datastructure -- not to mention the runtime issues involded. Same with Delphi. To me, a "CString" is a sequence of characters, followed by a char( 0). This is not the same as a pointer to those characters, allocated dynamically on the heap. Sidebar -- what happens is the dynamic allocation fails ?
Well, to be fair, `CString' (or `char *') doesn't say anything about the allocation method. It can point to any character sequence.
If a C allocation fails, it returns nil (NULL). What programs do with that is left to them (as always in C). Some libc routines/versions accept NULL, others don't. GPC tries to (and treats them as empty strings), e.g. in `CString2String'.
In my perception, a well written algorithm is the reflection of clear thinking, Clear thinking is inextricably bound to clear terminology and utmost attention to detail.
I think we don't need to discuss C's deficiencies here. :-)
We have `CString' mostly to interface to C code, not to write Pascal algorithms with it (though, unfortunately, in BP this has become somewhat usual practice, probably influenced by its lack of a longer than 255 char Pascal string type, and Borland's promotion of `CString', in turn probably because of their unwillingness to make a proper Pascal interface for the Windows functions ...). Anyway.
Frank
Frank Heckenbach wrote:
BTW, I'm not sure that C ABIs will actually change in the future. Maybe C programmers will simply become used to using `long' almost everywhere, just like programmers of Borland Pascal and, especially, compatible 32 bit compilers, use `LongInt' regularly ...
It would seem to come down to whether you might consider the C standard types as fixed to their original definitions on the DEC PDP-11 (actually PDP-8, to be pedantic), or if they were intended to "breathe" with the machine word size. The original whitebook stated:
Machine Bits ======================= PDP-11 16 Honeywell 6000 36 IBM 370 32 Interdata 8/32 32
The ANSI version eliminated the reference to specific sizes, but I think the intent was clearly on the side of int being the natural register size for the machine. If there is doubt, the question can always be carried to comp.lang.c, Dennis Ritchie himself reads the group.
There is also clearly a precedent for int eventually promoting. The PDP-11 was 16 bits int, the PC was 16 bits int, and now 32 bits. The 16 bit to 32 bit promotion algorithim appears to have been to leave the int size at the "old" 16 bit meaning, then finally upgrading it to 32 bits when it became clear that 16 bit machines were dying off on the desktop.
The trend for 32 bit adaption on the desktop was:
Introduction of 80386 October, 1985 Majority of desktops changed to 32 bit processors Approx 1990 Widespread use of 32 bit software 1995-
The changeover of desktops to 32 bits without software to run on them was accomplished mainly by Intels willingness to sell the the 80386 as faster 16 bit processor as well, which AMD is doing, and apparently Intel will follow.
Now thats 10 years from introduction of a 32 bit processor to widespread program conversion (typically programmers won't use a model that isn't the majority of installed user base).
I personally think thats longer than the 64 bit conversion length will be. The 32 bit applications mainly waited for the operating system to convert, and this is occurring faster for the 32 bit to 64 bit changeover. The limit this time is more likely to be the approximate 3 to 5 year time it takes for the majority of desktops to experience a hardware upgrade.
Scott Moore wrote:
Frank Heckenbach wrote:
BTW, I'm not sure that C ABIs will actually change in the future. Maybe C programmers will simply become used to using `long' almost everywhere, just like programmers of Borland Pascal and, especially, compatible 32 bit compilers, use `LongInt' regularly ...
It would seem to come down to whether you might consider the C standard types as fixed to their original definitions on the DEC PDP-11 (actually PDP-8, to be pedantic), or if they were intended to "breathe" with the machine word size.
The ANSI version eliminated the reference to specific sizes, but I think the intent was clearly on the side of int being the natural register size for the machine.
Sure. But I'm not sure if the ABI for one particular target, once determined, will change in the future.
Future new 64 targets might well have 64 bit `int' indeed. But AFAIK for the existing 64 targets (such as Intel, AMD, Sparc, Alpha) ABIs have been determined, and I think it's unlikely to see completely new 64 bit targets soon ...
There is also clearly a precedent for int eventually promoting. The PDP-11 was 16 bits int, the PC was 16 bits int, and now 32 bits. The 16 bit to 32 bit promotion algorithim appears to have been to leave the int size at the "old" 16 bit meaning, then finally upgrading it to 32 bits when it became clear that 16 bit machines were dying off on the desktop.
But for any given target (16 bit Dos, 16 bit Windows, 32 bit Windows, 32 bit Linux, BSD, ...) there's only been one ABI, and the new ABIs discussed are already for 64 bit AMD|Intel Unix|Windows, aren't they? So I wouldn't expect a change here anytime soon.
Frank
Frank Heckenbach wrote:
Scott Moore wrote:
Frank Heckenbach wrote:
BTW, I'm not sure that C ABIs will actually change in the future. Maybe C programmers will simply become used to using `long' almost everywhere, just like programmers of Borland Pascal and, especially, compatible 32 bit compilers, use `LongInt' regularly ...
It would seem to come down to whether you might consider the C standard types as fixed to their original definitions on the DEC PDP-11 (actually PDP-8, to be pedantic), or if they were intended to "breathe" with the machine word size.
The ANSI version eliminated the reference to specific sizes, but I think the intent was clearly on the side of int being the natural register size for the machine.
Sure. But I'm not sure if the ABI for one particular target, once determined, will change in the future.
Future new 64 targets might well have 64 bit `int' indeed. But AFAIK for the existing 64 targets (such as Intel, AMD, Sparc, Alpha) ABIs have been determined, and I think it's unlikely to see completely new 64 bit targets soon ...
The ABIs in existance for AMD64 are:
1. The ABI as published by AMD. 2. The ABI advanced by Microsoft for Windows.
Linux has adapted the AMD ABI. The Microsoft ABI does not match it. They went their own way (surprise).
Both ABIs are C oriented, if that matters.
The AMD ABI states that int is 32 bits, but this makes no difference to the ABI, since each register parameter occupies a full 64 bit register. On the stack, all parameters are specified as aligned to 64 bits, which means that assuming int as 64 bit would make no practical difference there, either.
The net difference of int vs. long is in structures, where int takes only 32 bits. I don't really consider that a calling convention matter, since you can declare record elements as subranges (or whatever).
There is also clearly a precedent for int eventually promoting. The PDP-11 was 16 bits int, the PC was 16 bits int, and now 32 bits. The 16 bit to 32 bit promotion algorithim appears to have been to leave the int size at the "old" 16 bit meaning, then finally upgrading it to 32 bits when it became clear that 16 bit machines were dying off on the desktop.
But for any given target (16 bit Dos, 16 bit Windows, 32 bit Windows, 32 bit Linux, BSD, ...) there's only been one ABI, and the new ABIs discussed are already for 64 bit AMD|Intel Unix|Windows, aren't they? So I wouldn't expect a change here anytime soon.
Frank
I believe the (practical) result is both existing ABIs are int length agnostic. If I missed something, my apologies.
Scott Moore wrote:
The ABIs in existance for AMD64 are:
- The ABI as published by AMD.
- The ABI advanced by Microsoft for Windows.
Linux has adapted the AMD ABI. The Microsoft ABI does not match it. They went their own way (surprise).
Both ABIs are C oriented, if that matters.
The AMD ABI states that int is 32 bits, but this makes no difference to the ABI, since each register parameter occupies a full 64 bit register. On the stack, all parameters are specified as aligned to 64 bits, which means that assuming int as 64 bit would make no practical difference there, either.
The net difference of int vs. long is in structures, where int takes only 32 bits. I don't really consider that a calling convention matter, since you can declare record elements as subranges (or whatever).
I don't understand the last part. If a parameter is of record type, and the caller doesn't follow the ABI (e.g., has int 64 bits), it won't work. So it is a calling convention matter.
I believe the (practical) result is both existing ABIs are int length agnostic. If I missed something, my apologies.
Besides the previous issue, it's only on little-endian machines that 32 and 64 bit integers can (sometimes) be interchanged on the stack. Another problem is if the caller puts a 32 bit value on the stack and the callee expects a 64 bit one, the upper 32 bits are undefined.
So I don't really agree. I think that ABIs should be followed exactly, anything else is just calling for trouble. This applies both to us (i.e., we should match C types exactly for interfaces defined in C terms) and to future C versions (i.e., I don't think they'll redefine `int' on a given ABI on such shaky ground).
Frank
Frank Heckenbach wrote:
Scott Moore wrote:
The ABIs in existance for AMD64 are:
- The ABI as published by AMD.
- The ABI advanced by Microsoft for Windows.
Linux has adapted the AMD ABI. The Microsoft ABI does not match it. They went their own way (surprise).
Both ABIs are C oriented, if that matters.
The AMD ABI states that int is 32 bits, but this makes no difference to the ABI, since each register parameter occupies a full 64 bit register. On the stack, all parameters are specified as aligned to 64 bits, which means that assuming int as 64 bit would make no practical difference there, either.
The net difference of int vs. long is in structures, where int takes only 32 bits. I don't really consider that a calling convention matter, since you can declare record elements as subranges (or whatever).
I don't understand the last part. If a parameter is of record type, and the caller doesn't follow the ABI (e.g., has int 64 bits), it won't work. So it is a calling convention matter.
Whats passed is a pointer (to the record/struct). The layout of a record in memory can, and should be, directly specified. In C by specific types, in Pascal with subranges.
I believe the (practical) result is both existing ABIs are int length agnostic. If I missed something, my apologies.
Besides the previous issue, it's only on little-endian machines that 32 and 64 bit integers can (sometimes) be interchanged on the stack. Another problem is if the caller puts a 32 bit value on the stack and the callee expects a 64 bit one, the upper 32 bits are undefined.
On Intel, the standard way to achieve aligned stack pushes is to push the dword/qword register. In any case, AMD changed the rule. The upper 32 bits aren't undefied, they are zero extended by default.
So I don't really agree. I think that ABIs should be followed exactly, anything else is just calling for trouble. This applies both to us (i.e., we should match C types exactly for interfaces defined in C terms) and to future C versions (i.e., I don't think they'll redefine `int' on a given ABI on such shaky ground).
Frank
Scott Moore wrote:
Frank Heckenbach wrote:
Scott Moore wrote:
The ABIs in existance for AMD64 are:
- The ABI as published by AMD.
- The ABI advanced by Microsoft for Windows.
Linux has adapted the AMD ABI. The Microsoft ABI does not match it. They went their own way (surprise).
Both ABIs are C oriented, if that matters.
The AMD ABI states that int is 32 bits, but this makes no difference to the ABI, since each register parameter occupies a full 64 bit register. On the stack, all parameters are specified as aligned to 64 bits, which means that assuming int as 64 bit would make no practical difference there, either.
The net difference of int vs. long is in structures, where int takes only 32 bits. I don't really consider that a calling convention matter, since you can declare record elements as subranges (or whatever).
I don't understand the last part. If a parameter is of record type, and the caller doesn't follow the ABI (e.g., has int 64 bits), it won't work. So it is a calling convention matter.
Whats passed is a pointer (to the record/struct). The layout of a record in memory can, and should be, directly specified. In C by specific types, in Pascal with subranges.
We're moving in circles. Again, Pascal subranges do not specify the memory layout.
Yes, in C by specific types, therefore types sizes must match, so a compiler with different sizes than the ABI will break in such cases. That's what I was saying. So we agree?
I believe the (practical) result is both existing ABIs are int length agnostic. If I missed something, my apologies.
Besides the previous issue, it's only on little-endian machines that 32 and 64 bit integers can (sometimes) be interchanged on the stack. Another problem is if the caller puts a 32 bit value on the stack and the callee expects a 64 bit one, the upper 32 bits are undefined.
On Intel, the standard way to achieve aligned stack pushes is to push the dword/qword register.
But not the only way. A compiler can (and I think gcc does sometimes) decrement the stack pointer (or keep it decremented from a previous call) and move values directly to the stack slots. Of course, one could force them to zero-extend (sign-extend?).
That's basically saying that all parameters promote to (at least) 64 bits. This will avoid many of the type size problems, but not all.
Frank
Frank Heckenbach wrote:
Sure. But I'm not sure if the ABI for one particular target, once determined, will change in the future.
Future new 64 targets might well have 64 bit `int' indeed. But AFAIK for the existing 64 targets (such as Intel, AMD, Sparc, Alpha) ABIs have been determined, and I think it's unlikely to see completely new 64 bit targets soon ...
The upcoming release of Mac OS X supports 64-bit binaries: long, long long and void* will be 64-bit, int will be 32-bit (see http://www.apple.com/macosx/tiger/64bit.html).
Regards,
Adriaan van Os
Adriaan van Os wrote:
Frank Heckenbach wrote:
Sure. But I'm not sure if the ABI for one particular target, once determined, will change in the future.
Future new 64 targets might well have 64 bit `int' indeed. But AFAIK for the existing 64 targets (such as Intel, AMD, Sparc, Alpha) ABIs have been determined, and I think it's unlikely to see completely new 64 bit targets soon ...
The upcoming release of Mac OS X supports 64-bit binaries: long, long long and void* will be 64-bit, int will be 32-bit (see http://www.apple.com/macosx/tiger/64bit.html).
Yes, so I don't expect `int' to ever become 64 bit on Mac OS X (at least until the appearance of 128 bit binaries perhaps :-).
BTW, maybe that's all just because they'd have no 32 bit type otherwise. `short' remains 16 bit (I suppose), and adding a name between `short' and `int' was perhaps deemed less desirable than adding more `long's. But we can't influence this anyway ...
Frank
On 4 Jun 2004 at 3:12, Waldek Hebisch wrote:
Prof A Olowofoyeku (The African Chief) wrote:
I have built gpc-20040516 for AMD64 (platform: Fedora Core 2, 64-bit).
Binaries can be obtained here: http://gnu-pascal.de/contrib/chief/fedora-2/
Built and tested on an Athlon-64 3.2+, the testsuite ran fine, except for these: TEST asmtest.pas: SKIPPED: only for IA32 TEST az20.pas: ./test_run: line 334: 4929 Segmentation fault ./"$A_OUT" "$1" TEST confarr5.pas: ./test_run: line 334: 9516 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST jj5.pas: SKIPPED: `attribute (stdcall)' not available TEST martin3.pas: ./test_run: line 334: 27275 Segmentation fault ./"$A_OUT" "$1" TEST pack10.pas: ./test_run: line 334: 30277 Segmentation fault ./"$A_OUT" "$1" TEST pack5.pas: ./test_run: line 334: 30396 Segmentation fault ./"$A_OUT" "$1"
The failing tests are known problem: bit-packed arrays do not work on amd64 with 3.x backend. Fixed in 3.4.0. You do not mention `fjf762a.pas' -- I was convinced that is should fail on all 64-bit machines.
My mistake: "TEST fjf762a.pas: failed: "
Best regards, The Chief -------- Prof. Abimbola A. Olowofoyeku (The African Chief) web: http://www.greatchief.plus.com/
Prof A Olowofoyeku (The African Chief) wrote:
I have built gpc-20040516 for AMD64 (platform: Fedora Core 2, 64-bit).
Binaries can be obtained here: http://gnu-pascal.de/contrib/chief/fedora-2/
Thanks.
Built and tested on an Athlon-64 3.2+, the testsuite ran fine, except for these: TEST az20.pas: ./test_run: line 334: 4929 Segmentation fault ./"$A_OUT" "$1" TEST confarr5.pas: ./test_run: line 334: 9516 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST martin3.pas: ./test_run: line 334: 27275 Segmentation fault ./"$A_OUT" "$1" TEST pack10.pas: ./test_run: line 334: 30277 Segmentation fault ./"$A_OUT" "$1" TEST pack5.pas: ./test_run: line 334: 30396 Segmentation fault ./"$A_OUT" "$1"
Known problems with packed arrays (all) on certain platforms, AFAIK.
One curious thing. "Writeln (sizeof (Integer))" prints "4", as does "Writeln (sizeof (Cardinal))". Shouldn't these be 64-bit?
GPC follows the C model here. Apparently `int' is 32 bit, and `long int' (`MedInt' in GPC) is probably 64 bits.
I'm not sure if this is optimal (I don't know exactly if this and other 64 bit processors can do 32 bit operations efficiently), but it would probably be more problematic to deviate from the C types, as far as C interfaces are concerned ... :-/
Frank
Frank Heckenbach wrote:
Prof A Olowofoyeku (The African Chief) wrote:
I have built gpc-20040516 for AMD64 (platform: Fedora Core 2, 64-bit).
Binaries can be obtained here: http://gnu-pascal.de/contrib/chief/fedora-2/
Thanks.
Built and tested on an Athlon-64 3.2+, the testsuite ran fine, except for these: TEST az20.pas: ./test_run: line 334: 4929 Segmentation fault ./"$A_OUT" "$1" TEST confarr5.pas: ./test_run: line 334: 9516 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST fjf746.pas: ./test_run: line 334: 14662 Segmentation fault ./"$A_OUT" "$1" TEST martin3.pas: ./test_run: line 334: 27275 Segmentation fault ./"$A_OUT" "$1" TEST pack10.pas: ./test_run: line 334: 30277 Segmentation fault ./"$A_OUT" "$1" TEST pack5.pas: ./test_run: line 334: 30396 Segmentation fault ./"$A_OUT" "$1"
Known problems with packed arrays (all) on certain platforms, AFAIK.
One curious thing. "Writeln (sizeof (Integer))" prints "4", as does "Writeln (sizeof (Cardinal))". Shouldn't these be 64-bit?
GPC follows the C model here. Apparently `int' is 32 bit, and `long int' (`MedInt' in GPC) is probably 64 bits.
I'm not sure if this is optimal (I don't know exactly if this and other 64 bit processors can do 32 bit operations efficiently), but it would probably be more problematic to deviate from the C types, as far as C interfaces are concerned ... :-/
Frank
To reach 32 bit operations in AMD 64, you have to use a mode prefix (from 64 bit mode). Hence, there is an instruction length penalty.
For the idea of a "mudstuck integer", it would not be the first time; lots of x86 implementations left integer at 16 bit when the architecture moved forward.
In any case, the ISO 7185 standard is clear: The range of integer is -maxint to maxint, and all calculations shall occur in that range, ie., integer is the maximum range type on any system. The program is supposed to use maxint to adjust its specific behavior, as required, or specifically declare a subrange, perhaps to give a compile time message about it being larger than the target is capable of.
By the way, the AMD ABI or calling/sizing convention which gcc is based on, and requires ints remain 32 bits, violates the standard for C as well.
Scott Moore wrote:
To reach 32 bit operations in AMD 64, you have to use a mode prefix (from 64 bit mode). Hence, there is an instruction length penalty.
That's already bad. Even worse if it can only read/write 64 bit words, so in particular 32 bit writes get quite cumbersome. (Do you know if this is so?)
In any case, the ISO 7185 standard is clear: The range of integer is -maxint to maxint, and all calculations shall occur in that range, ie., integer is the maximum range type on any system. The program is supposed to use maxint to adjust its specific behavior, as required, or specifically declare a subrange, perhaps to give a compile time message about it being larger than the target is capable of.
That's fulfilled whatever me make `Integer' to be, since `MaxInt' will always refer to this particular type. The longer types are disabled in standard modes (and they have `MaxLongInt' etc.).
By the way, the AMD ABI or calling/sizing convention which gcc is based on, and requires ints remain 32 bits, violates the standard for C as well.
What does it demand? (I'm not really an expert on C standards. ;-)
Frank
Dixitur illum ih8mj@fjf.gnu.de scribere...
That's already bad. Even worse if it can only read/write 64 bit words, so in particular 32 bit writes get quite cumbersome. (Do you know if this is so?)
x86 has never been like this, and FWIW the instruction set is still optimized for 32-bit operations, even in 64-bit mode (eg, a .intel_syntax noprefix .code32 add ax,1 will not change the high 16 bit of eax, but a .code64 add eax,1 will set the high 32 bit of rax to 0).
Reference: www.amd.com -> manuals -r--r--r-- 1 tg tg 3019773 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 1: Application Programming.pdf -r--r--r-- 1 tg tg 4261489 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 2: System Programming.pdf -r--r--r-- 1 tg tg 4659928 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions.pdf -r--r--r-- 1 tg tg 2696640 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 4: 128-Bit Media Instructions.pdf -r--r--r-- 1 tg tg 2470923 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 5: 64-Bit Media and x87 Floating-Point Instructions.pdf
bye, //Thorsten
Thorsten Glaser wrote:
Dixitur illum ih8mj@fjf.gnu.de scribere...
That's already bad. Even worse if it can only read/write 64 bit words, so in particular 32 bit writes get quite cumbersome. (Do you know if this is so?)
x86 has never been like this, and FWIW the instruction set is still optimized for 32-bit operations,
BTW, I was referring to memory writes. I hope you too.
even in 64-bit mode (eg, a .intel_syntax noprefix .code32 add ax,1 will not change the high 16 bit of eax, but a .code64 add eax,1 will set the high 32 bit of rax to 0).
OK, then it may not be so bad WRT efficiency.
The main argument for a change is that with 32 bit `Integer', e.g. a schema (n: Integer) = array [1 .. n] ... will be more limited than necessary, and that's the biggest form in EP.
The main argument against it is compatibility, of course.
(continued in next mail)
Reference: www.amd.com -> manuals -r--r--r-- 1 tg tg 3019773 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 1: Application Programming.pdf -r--r--r-- 1 tg tg 4261489 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 2: System Programming.pdf -r--r--r-- 1 tg tg 4659928 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 3: General-Purpose and System Instructions.pdf -r--r--r-- 1 tg tg 2696640 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 4: 128-Bit Media Instructions.pdf -r--r--r-- 1 tg tg 2470923 Oct 13 2003 AMD64 Architecture Programmer's Manual Volume 5: 64-Bit Media and x87 Floating-Point Instructions.pdf
Thanks, for whom it may concern. Unfortunately I don't have the time to read some 15 MB of PDF files just for one processor's `Integer' type ...
Frank
Frank Heckenbach wrote:
Scott Moore wrote:
To reach 32 bit operations in AMD 64, you have to use a mode prefix (from 64 bit mode). Hence, there is an instruction length penalty.
That's already bad. Even worse if it can only read/write 64 bit words, so in particular 32 bit writes get quite cumbersome. (Do you know if this is so?)
Not really. The design (which is really just the 32 bit method extended) was to flip all operations to 64 bits, then provide lots of new move modes to make up for the loss of efficentcy in 32 bit operations. So there is a direct load/store of byte, word (16 bit), 32 bit, and 64 bit. 64 bits can be moved as an immediate, which is required because all of the immediates on common instructions stayed at 32 bits. For example add rax,imm, imm is 32 bits only. The loads, of course, have various signed and unsigned extention modes.
So the short answer is the processor is getting more RISC like, relying more on loads and stores, while the other instructions with load and store modes like add get penalized.
Having common immediate modes stay at 32 bits was one of the secrets that allow x86_64 bit code to be as small as x86 code (in my compiles, using GCC, the difference in large program sizes with both modes was practically nil). There is a price: AMD64 cannot practically have a program larger than 2gb in size (the range of a relative jump). There is no way to encode a 64 bit jump, unless you do something like load it to a register, then jump to that.
In any case, the ISO 7185 standard is clear: The range of integer is -maxint to maxint, and all calculations shall occur in that range, ie., integer is the maximum range type on any system. The program is supposed to use maxint to adjust its specific behavior, as required, or specifically declare a subrange, perhaps to give a compile time message about it being larger than the target is capable of.
That's fulfilled whatever me make `Integer' to be, since `MaxInt' will always refer to this particular type. The longer types are disabled in standard modes (and they have `MaxLongInt' etc.).
Yes, but that really negates the intent of the standard, which intended that integer represent the most efficient word length on the machine.
By the way, the AMD ABI or calling/sizing convention which gcc is based on, and requires ints remain 32 bits, violates the standard for C as well.
What does it demand? (I'm not really an expert on C standards. ;-)
Frank
Oh, well, I was afraid you would call me on that. I taught a class on the AMD64 arch, and it came up in my research. However, its probally a valid point for you, so I will go find it.
Scott Moore wrote:
Frank Heckenbach wrote:
By the way, the AMD ABI or calling/sizing convention which gcc is based on, and requires ints remain 32 bits, violates the standard for C as well.
What does it demand? (I'm not really an expert on C standards. ;-)
Frank
Oh, well, I was afraid you would call me on that. I taught a class on the AMD64 arch, and it came up in my research. However, its probally a valid point for you, so I will go find it.
I looked through the material, I can't find the point I had back then, so I'll retract that, sorry.