Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2004-10

FPC_REQUIRES_PROPER_ALIGNMENT

15 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Marc Weustink

Hi,

Florian and I had a discussion on IRC and we decided to continue it here.

F:> I guess the main problem will be that the typeinfo structures has changed to fit sparc 's alignment
M:> this will be on sparc only ?
F:> on cpus which define FPC_REQUIRES_PROPER_ALIGNMENT F:> mainly, the data after strings in type info must be aligned F:> the key is function aligntoptr(p : pointer) : pointer; F:> in typeinfo, it is used to do the alignment
M:> trying examples/hello
M:> Program received signal SIGBUS, Bus error.
F:> yes, SIGBUS is an alignment exception
F:> the compiler contains also several packed ifdef'ed by FPC_REQUIRES_PROPER_ALIGNMENT

M:> about alignment:
M:> I don't know if the average Lazarus user will be happy with taking care of alignment
M:> IMO, for compiler internals yes, but as an enduser I think it is a task of the compiler
M:> I know that unalignged memory access in this case has a large performance penalty, but IMO is should be allowed

F:> there are two options: (to allow unaligned accesses) F:> - catch the sigbus and "fix" the access; requires a lot of work to implement
F:> - always assume unaligned accesses: hugh speed penalty: load byte by byte and shift/or the result
F:> so I think we should follow the C way of doing it: the user has to take care of alignment
F:> if a data access is unaligned: do a
move(unaligneddata,aligneddataloc,sizeof(unaligneddata));

M:> Is a sigbus catchable so that you can read the data and continue as if nothing happened (or is that something at OS level) M:> I know that some arm implementations can read this way (unfortunately not the one we're using at work). I thought it was more a OS thingy M:> @2) You don't have to read byte by byte in all cases. You can check first if it is unalligned, after that you can read regsize instead of bytesize M:> Let the user take care of alignment makes me a bit itchy. I don't get a good feeling with it.
M:> But how are members of packed records accessed ?

Marc

Reply by email

Jonas Maebe
to Marc Weustink
Marc Weustink wrote
M:> Is a sigbus catchable so that you can read the data and continue as if nothing happened (or is that something at OS level)

That is normally possible, yes. But as Florian said, it's quite a bit of work and also extremely slow (you get 4 context switches per unaligned access, + the work to load the value).

M:> Let the user take care of alignment makes me a bit itchy. I don't get a good feeling with it.

I think it's normal he has to. We also don't emulate the 80-bit extended type on processors which only have a 64-bit double precision fpu. We also don't emulate endianess. Portability has a lot of pitfalls.

M:> But how are members of packed records accessed ?

Just like members of regular records. The difference is that there are simply no alignment bytes between the different fields of the record.

Jonas

Reply by email

Florian Klaempfl
to Jonas Maebe
Jonas Maebe wrote 7 lines
> M:> But how are members of packed records accessed ? Just like members of regular records. The difference is that there are simply no alignment bytes between the different fields of the record.

If you've to access an unaligned member, you've to use a move as you do in C, where a memcpy is used.

Reply by email

Marc Weustink
to Jonas Maebe: That is normally possible, yes. But as Florian said, it's quite a bit of work and also…
Jonas Maebe wrote 8 lines
On 12 okt 2004, at 22:12, Marc Weustink wrote: >M:> Is a sigbus catchable so that you can read the data and continue as >if nothing happened (or is that something at OS level) That is normally possible, yes. But as Florian said, it's quite a bit of work and also extremely slow (you get 4 context switches per unaligned access, + the work to load the value).

Yes I do realize that there is a penalty for doing unaligned access. That is something different than not allowing it.
With this option normal alligned access if fast. If someone wants to access memory unaligned... so be it.

>M:> Let the user take care of alignment makes me a bit itchy. I don't get >a good feeling with it. I think it's normal he has to.

Ow...

We also don't emulate the 80-bit extended type on processors which only have a 64-bit double precision fpu.

That is something different IMO. But I see no reason why it can't be done. Why it math supported on targets without fpu ? Why is int64 supported on targets not having a 64 register ?
Ok, it are all choises and a matter of time, but not a reason to do or skip other things.

We also don't emulate endianess. Portability has a lot of pitfalls.

In a matter of fact, you do support endianness. As an enduser I don't have to take care ot the phisical representation of an integer for instance. An integer and $FF is still a value between 0 and 255. An integer shl 2 is still doubled no matter its representation in memory.

>M:> But how are members of packed records accessed ? Just like members of regular records. The difference is that there are simply no alignment bytes between the different fields of the record.

So accessing them result in a bus error ?

Florian replied to this:

If you've to access an unaligned member, you've to use a move as you do in C, where a memcpy is used.

I'm not talking C here. This is pascal.

When I've to interface with a record like:
   Rec: packed record
     B: Byte;
     I: Integer;
   end;

you are saying that to access Rec.I I have to do something like:

   MyInt := PInteger(aligntoptr(@Rec.I))^;

(what about writing to it ?)

This will throw away all advantages away form pascal (like strong typing etc). And if you forget to make it aligned, you get all kinds of errors.

I hope I got this all wrong, otherwise I would be better of using a C compiler for this (then I've the ability to use macros to get around this)

Marc (hopes he understood this wrong)

Reply by email

Florian Klaempfl
to Marc Weustink
Marc Weustink wrote 14 lines
At 16:38 13-10-2004, Jonas Maebe wrote: > On 12 okt 2004, at 22:12, Marc Weustink wrote: > >> M:> Is a sigbus catchable so that you can read the data and continue >> as if nothing happened (or is that something at OS level) > > > That is normally possible, yes. But as Florian said, it's quite a bit > of work and also extremely slow (you get 4 context switches per > unaligned access, + the work to load the value). Yes I do realize that there is a penalty for doing unaligned access.

It's not a penalty, it's death regarding speed ;) A solution I could imagine is that packed records are accessed correctly, i.e. shifting and oring but catching sigbus is too much imo and will cause serious performance problems.

BTW: Does anybody have TP 5.5 for m68k and can test what it does :)?

gpc accesses packed records correctly but it doesn't allow to take the address of a field of a packed record.

gpc example:

program test;
procedure p(var i : integer);
   begin
   end;
var
   r : packed record
     c : char;
     i : integer;
   end;
begin
   r.i:=1; <--- works
   p(r.i); <--- test.p:15: packed fields may not be used as `var' parameters
end.
Show quoted text 7 lines
This will throw away all advantages away form pascal (like strong typing etc). And if you forget to make it aligned, you get all kinds of errors. I hope I got this all wrong, otherwise I would be better of using a C compiler for this (then I've the ability to use macros to get around this)

FPC always tries to do the best of both worlds, I guess you don't want the gpc behaviour either :)

Reply by email

Marc Weustink
to Florian Klaempfl
Florian Klaempfl wrote 17 lines
Marc Weustink wrote: >At 16:38 13-10-2004, Jonas Maebe wrote: > >>On 12 okt 2004, at 22:12, Marc Weustink wrote: >> >>>M:> Is a sigbus catchable so that you can read the data and continue as >>>if nothing happened (or is that something at OS level) >> >> >>That is normally possible, yes. But as Florian said, it's quite a bit of >>work and also extremely slow (you get 4 context switches per unaligned >>access, + the work to load the value). > >Yes I do realize that there is a penalty for doing unaligned access. It's not a penalty, it's death regarding speed ;)

But there is still an infinite speed difference in no access and dead slow access :)

A solution I could imagine is that packed records are accessed correctly, i.e. shifting and oring but catching sigbus is too much imo and will cause serious performance problems.

As a first attempt solution, yes. I was talkin about situations where everything else failed.

Aligning pointers, shifting and oring doesn't conflict with having a fallback.

The other option is to assume all pointer access unaligned and check if it is the case and ifso, do shift&or. But this will affect normal alligned access as well. (Or not if a compiler derective is introduced to turn this behaviour locally on and off)

(alltough the last option isn't complete transparant, I personally would prefer it above catching buserrors)

Show quoted text 32 lines
BTW: Does anybody have TP 5.5 for m68k and can test what it does :)? gpc accesses packed records correctly but it doesn't allow to take the address of a field of a packed record. gpc example: program test; procedure p(var i : integer); begin end; var r : packed record c : char; i : integer; end; begin r.i:=1; <--- works p(r.i); <--- test.p:15: packed fields may not be used as `var' parameters end. >This will throw away all advantages away form pascal (like strong typing >etc). >And if you forget to make it aligned, you get all kinds of errors. >I hope I got this all wrong, otherwise I would be better of using a C >compiler for this (then I've the ability to use macros to get around this) FPC always tries to do the best of both worlds, I guess you don't want the gpc behaviour either :)

Maybe I do, but without the (IMO silly) error.

To call p() in your example, you have to know if r.i is aligned or not (and that alignment is required andsuch).

if alignment is needed, you need a local var in this case like:

var
   h: integer;
begin
   h := r.i;
   p(h);
   r.i := h;
end;

Since the compiler already knows that r.i is unalligned (otherwise it wouldn't give the error), it could generate this "wrapper" itself more efficient than you can instead of giving an error.

Something related, how are the following arrays accessed ?
array[0..10] of Byte;
packed array[0..10] of Byte;
array[0..10] of Word;
packed array[0..10] of Word;

Marc

Reply by email

Jonas Maebe
to Marc Weustink: Yes I do realize that there is a penalty for doing unaligned access. That is something…
Marc Weustink wrote 8 lines
> We also don't emulate endianess. Portability has a lot of pitfalls. In a matter of fact, you do support endianness. As an enduser I don't have to take care ot the phisical representation of an integer for instance. An integer and $FF is still a value between 0 and 255. An integer shl 2 is still doubled no matter its representation in memory.

That's because internally all processors are big endian, not because we do something special.

Jonas

Reply by email

Olle Raab
to Jonas Maebe: That is normally possible, yes. But as Florian said, it's quite a bit of work and also…

04-10-13 16.38, skrev Jonas Maebe följande:

We also don't emulate the 80-bit extended type on processors which only have a 64-bit double precision fpu. We also don't emulate endianess. Portability has a lot of pitfalls.

Some time ago Florian did mention to add emulation of 80-bit Extended typ, to make it possible to create e. g. powerpc-intel-cross-compilers...

It was needed because Extended constant expressions is to be evaluated during compile time.

Olle

Reply by email

Jonas Maebe
to Olle Raab
Olle Raab wrote 6 lines
Some time ago Florian did mention to add emulation of 80-bit Extended typ, to make it possible to create e. g. powerpc-intel-cross-compilers... It was needed because Extended constant expressions is to be evaluated during compile time.

Actually, I thought it would be 128bit. But it would only be for usage inside the compiler, not as an emulation library in the RTL for usage by user-written programs.

Jonas

Reply by email

Florian Klaempfl
to Marc Weustink: But there is still an infinite speed difference in no access and dead slow access :) As a…
Marc Weustink wrote 26 lines
At 00:15 14-10-2004, Florian Klaempfl wrote: > Marc Weustink wrote: > >> At 16:38 13-10-2004, Jonas Maebe wrote: >> >>> On 12 okt 2004, at 22:12, Marc Weustink wrote: >>> >>>> M:> Is a sigbus catchable so that you can read the data and >>>> continue as if nothing happened (or is that something at OS level) >>> >>> >>> >>> That is normally possible, yes. But as Florian said, it's quite a >>> bit of work and also extremely slow (you get 4 context switches per >>> unaligned access, + the work to load the value). >> >> >> Yes I do realize that there is a penalty for doing unaligned access. > > > It's not a penalty, it's death regarding speed ;) But there is still an infinite speed difference in no access and dead slow access :)

But the fault allows the programmer to optimize his program :) Don't forget: Unaligned accesses also give _huge_ penalties on processors which even don't fault.

Show quoted text 19 lines
> A solution I could imagine is that packed records are accessed > correctly, i.e. shifting and oring but catching sigbus is too much imo > and will cause serious performance problems. As a first attempt solution, yes. I was talkin about situations where everything else failed. Aligning pointers, shifting and oring doesn't conflict with having a fallback. The other option is to assume all pointer access unaligned and check if it is the case and ifso, do shift&or. But this will affect normal alligned access as well. (Or not if a compiler derective is introduced to turn this behaviour locally on and off) (alltough the last option isn't complete transparant, I personally would prefer it above catching buserrors)

We aren't talking even about pointer accesses, we're talking about simple data accesses. If we assume that every access could be unaligned, we should better write an interpreter.

Show quoted text 22 lines
> FPC always tries to do the best of both worlds, I guess you don't want > the gpc behaviour either :) Maybe I do, but without the (IMO silly) error. To call p() in your example, you have to know if r.i is aligned or not (and that alignment is required andsuch). if alignment is needed, you need a local var in this case like: var h: integer; begin h := r.i; p(h); r.i := h; end; Since the compiler already knows that r.i is unalligned (otherwise it wouldn't give the error), it could generate this "wrapper" itself more efficient than you can instead of giving an error.

Using a helper is a different calling convention (copy back). Copy back was already thrown away with Fortran 66 I think because it caused too much trouble. r.i could have also an alias so the example above isn't equal to a direct usage of r.i.

Show quoted text 6 lines
Something related, how are the following arrays accessed ? array[0..10] of Byte; packed array[0..10] of Byte; array[0..10] of Word; packed array[0..10] of Word;

The are equal in FPC and are simply accessed with byte and word reads without any trouble.

And keep in mind: the problem is much smaller than you think :) Normal pascal (without packed, ugly pointer arithmetics or absolute) compiles fine in 99.99 per cent of all cases. Further, all C/C++ code of e.g. KDE, GNOME, OpenOffice etc. works on cpus requiring alignment of data without special compiler tricks, ugly programmer tricks or heavy usage of memcpy.

Reply by email

Olle Raab
to Chess Player: If packed records are such a problem, don't use packed records. We're not programming…

04-10-16 19.40, skrev Chess Player följande:

If packed records are such a problem, don't use packed records. We're not programming for computers with 640kb of RAM.

"packed" is sometime used to make the binary representation of the record more predictable, which you might need if you mix fpc with other languages or want to save the data to disk. Of course you can only rely on this at your own risque.

And the Mac OS Universal Interfaces uses "packed" a lot.

Olle

Reply by email

Florian Klaempfl
to Olle Raab
Olle Raab wrote 13 lines
04-10-16 19.40, skrev Chess Player följande: >If packed records are such a problem, don't use packed records. We're not >programming for computers with 640kb of RAM. "packed" is sometime used to make the binary representation of the record more predictable, which you might need if you mix fpc with other languages or want to save the data to disk. Of course you can only rely on this at your own risque. And the Mac OS Universal Interfaces uses "packed" a lot.

Yes, but they are probably packed properly and taking care of alignment. Further, the powerpc doesn't "sigbus" on unaligned data usually.

Reply by email

Marc Weustink
to Florian Klaempfl: But the fault allows the programmer to optimize his program :) Don't forget: Unaligned…
Florian Klaempfl wrote 29 lines
Marc Weustink wrote: >At 00:15 14-10-2004, Florian Klaempfl wrote: > >>Marc Weustink wrote: >> >>>At 16:38 13-10-2004, Jonas Maebe wrote: >>> >>>>On 12 okt 2004, at 22:12, Marc Weustink wrote: >>>> >>>>>M:> Is a sigbus catchable so that you can read the data and continue >>>>>as if nothing happened (or is that something at OS level) >>>> >>>> >>>> >>>>That is normally possible, yes. But as Florian said, it's quite a bit >>>>of work and also extremely slow (you get 4 context switches per >>>>unaligned access, + the work to load the value). >>> >>> >>>Yes I do realize that there is a penalty for doing unaligned access. >> >> >>It's not a penalty, it's death regarding speed ;) > >But there is still an infinite speed difference in no access and dead >slow access :) But the fault allows the programmer to optimize his program :)

Hints could also have done.

Don't forget: Unaligned accesses also give _huge_ penalties on processors which even don't fault.

I do understand now that fpc doesn't support pll to write sloppy code. IMO that is a valid reason.

Show quoted text 18 lines
>>A solution I could imagine is that packed records are accessed >>correctly, i.e. shifting and oring but catching sigbus is too much imo >>and will cause serious performance problems. > >As a first attempt solution, yes. I was talkin about situations where >everything else failed. >Aligning pointers, shifting and oring doesn't conflict with having a >fallback. >The other option is to assume all pointer access unaligned and check if >it is the case and ifso, do shift&or. But this will affect normal >alligned access as well. (Or not if a compiler derective is introduced to >turn this behaviour locally on and off) >(alltough the last option isn't complete transparant, I personally would >prefer it above catching buserrors) We aren't talking even about pointer accesses, we're talking about simple data accesses. If we assume that every access could be unaligned, we should better write an interpreter.

Sorry, I mixed things up. For simple dataaccess we know what is unalingend.

Show quoted text 19 lines
>>FPC always tries to do the best of both worlds, I guess you don't want >>the gpc behaviour either :) > >Maybe I do, but without the (IMO silly) error. >To call p() in your example, you have to know if r.i is aligned or not >(and that alignment is required andsuch). >if alignment is needed, you need a local var in this case like: >var > h: integer; >begin > h := r.i; > p(h); > r.i := h; >end; >Since the compiler already knows that r.i is unalligned (otherwise it >wouldn't give the error), it could generate this "wrapper" itself more >efficient than you can instead of giving an error. Using a helper is a different calling convention (copy back).

OK, it has even a name.

Copy back was already thrown away with Fortran 66 I think because it caused too much trouble.

I'll believe it will give troubles in certain situations, I only have no idea where (then again, I'm only a compiler user).

r.i could have also an alias so the example above isn't equal to a direct usage of r.i.

alias ??

Show quoted text 5 lines
And keep in mind: the problem is much smaller than you think :) Normal pascal (without packed, ugly pointer arithmetics or absolute) compiles fine in 99.99 per cent of all cases. Further, all C/C++ code of e.g. KDE, GNOME, OpenOffice etc. works on cpus requiring alignment of data without special compiler tricks, ugly programmer tricks or heavy usage of memcpy.

The reason why I started this thread was that I was a bit disappointed that running Lazarus on sparc failed. To apply all kinds of patches and ifdefs for platforms not supporting unaligned access was not an option for me. Today I realized that the only sensible use of packed records is when interfacing with external libraries. The chance that this is needed unaligned on a sparc is pretty much zero. So my request for unalinged access makes no sense.
I'll have a look why packed records are used internally.

Marc

Reply by email

Florian Klaempfl
to Marc Weustink
Marc Weustink wrote 13 lines
> Copy back was already thrown away with Fortran 66 I think because it > caused too much trouble. I'll believe it will give troubles in certain situations, I only have no idea where (then again, I'm only a compiler user). > r.i could have also an alias so the example above isn't equal to a > direct usage of r.i. alias ??
var
    p : plongint;
    i : longint;
...
;
Show quoted text 19 lines
> And keep in mind: the problem is much smaller than you think :) Normal > pascal (without packed, ugly pointer arithmetics or absolute) compiles > fine in 99.99 per cent of all cases. Further, all C/C++ code of e.g. > KDE, GNOME, OpenOffice etc. works on cpus requiring alignment of data > without special compiler tricks, ugly programmer tricks or heavy usage > of memcpy. The reason why I started this thread was that I was a bit disappointed that running Lazarus on sparc failed. To apply all kinds of patches and ifdefs for platforms not supporting unaligned access was not an option for me. Today I realized that the only sensible use of packed records is when interfacing with external libraries. The chance that this is needed unaligned on a sparc is pretty much zero. So my request for unalinged access makes no sense. I'll have a look why packed records are used internally.

That's what I meant: usually, alignment issues are caused only by legacy code which uses packed. Newly created code doesn't cause problems usually.

Reply by email