Records

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

Records

Carsten Bager
We are moving a lot of code from an old platform where it is
allowed to compare 2 records like this.

Type
  A_typ=array[0..3] of integer;
Var
 A1,A2:A_typ;

Begin
  If A1=A2 then
End;

I know that I can typecast to an array of char to compare but
is there an easier way.

---

I have never could understand when this is allowed
A1:=A2;

Why this is not allowed
If A1=A2 then

in most Pascal compilers.

Regards Carsten

--
Carsten Bager
Bøvlingbjerg El-automatik
Brørupvænget 10
7650 Bøvlingbjerg
Tlf. +4597885222 Fax +4597885434
http://www.beas.dk

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Adriaan van Os-2
Carsten Bager wrote:

> We are moving a lot of code from an old platform where it is
> allowed to compare 2 records like this.
>
> Type
>   A_typ=array[0..3] of integer;
> Var
>  A1,A2:A_typ;
>
> Begin
>   If A1=A2 then
> End;
>
> I know that I can typecast to an array of char to compare but
> is there an easier way.
>
> ---
>
> I have never could understand when this is allowed
> A1:=A2;
>
> Why this is not allowed
> If A1=A2 then
>
> in most Pascal compilers.

Because you can't simply compare the memory ranges occupied by records
A and B. They could have different pad bytes (and bits) but still be
the same. Therefore, implementation is non-trivial. For the same
reason, the above typecast is incorrect.

Regards,

Adriaan van Os

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Florian Klämpfl
Adriaan van Os wrote:

> Carsten Bager wrote:
>
>> We are moving a lot of code from an old platform where it is
>> allowed to compare 2 records like this.
>>
>> Type
>>   A_typ=array[0..3] of integer;
>> Var
>>  A1,A2:A_typ;
>>
>> Begin
>>   If A1=A2 then
>> End;
>>
>> I know that I can typecast to an array of char to compare but
>> is there an easier way.
>>
>> ---
>>
>> I have never could understand when this is allowed
>> A1:=A2;
>>
>> Why this is not allowed
>> If A1=A2 then
>>
>> in most Pascal compilers.
>
>
> Because you can't simply compare the memory ranges occupied by records A
> and B. They could have different pad bytes (and bits) but still be the
> same. Therefore, implementation is non-trivial. For the same reason, the
> above typecast is incorrect.
>

We could implement such a comparisation based on rtti ...
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Carsten Bager
> Adriaan van Os wrote:
>
> > Carsten Bager wrote:
> >
> >> We are moving a lot of code from an old platform where it is
> >> allowed to compare 2 records like this.
> >>
> >> Type
> >>   A_typ=array[0..3] of integer;
> >> Var
> >>  A1,A2:A_typ;
> >>
> >> Begin
> >>   If A1=A2 then
> >> End;
> >>
> >> I know that I can typecast to an array of char to compare but
> >> is there an easier way.
> >>
> >> ---
> >>
> >> I have never could understand when this is allowed
> >> A1:=A2;
> >>
> >> Why this is not allowed
> >> If A1=A2 then
> >>
> >> in most Pascal compilers.
> >
> >
> > Because you can't simply compare the memory ranges occupied by records A
> > and B. They could have different pad bytes (and bits) but still be the
> > same. Therefore, implementation is non-trivial. For the same reason, the
> > above typecast is incorrect.

I have never used this without initializing records first
(A1:=A2). I have used it on deferent platforms (on  PC's with
typecast). It has all ways don what I expected.
It could be a demand that records should be packed, but
that triggers another problem on some (ARM) platforms.

> >
>
> We could implement such a comparisation based on rtti ...

I assume that rtti means "Runtime Type Information",
something a have never used, but if it can do the job I would
be happy.

Regards Carsten



> _______________________________________________
> fpc-pascal maillist  -  [hidden email]
> http://lists.freepascal.org/mailman/listinfo/fpc-pascal


_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Micha Nelissen
In reply to this post by Adriaan van Os-2
Adriaan van Os wrote:

>> I have never could understand when this is allowed
>> A1:=A2;
>>
>> Why this is not allowed
>> If A1=A2 then
>>
>> in most Pascal compilers.
>
>
> Because you can't simply compare the memory ranges occupied by records A
> and B. They could have different pad bytes (and bits) but still be the
> same.

Isn't the number of pad bytes a property of a type ? So when two vars
are of the same type, they also have the same number of pad bytes ?

Or: the compiler could also do the equivalent of sizeof(a1)=sizeof(a2),
if equal then can compare "easy" (same number of pad bytes), otherwise
give appropriate error (size of type differs, or so).

Micha

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Jonas Maebe-2

On 26 okt 2005, at 10:11, Micha Nelissen wrote:

>> Because you can't simply compare the memory ranges occupied by  
>> records A and B. They could have different pad bytes (and bits)  
>> but still be the same.
>
> Isn't the number of pad bytes a property of a type ? So when two  
> vars are of the same type, they also have the same number of pad  
> bytes ?

Yes, but two different variables of the same type could have  
different values for those pad bytes. So you have to compare  
everything but the pad bytes.


Jonas
_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Micha Nelissen
Jonas Maebe wrote:
>
> Yes, but two different variables of the same type could have  different
> values for those pad bytes. So you have to compare  everything but the
> pad bytes.

Oh right! Something like a masked compare or so...probably not
implementable in an efficient way indeed I guess.

Micha

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Adriaan van Os-2
In reply to this post by Jonas Maebe-2
Jonas Maebe wrote:

> Micha Nelissen wrote:
>
>>> Because you can't simply compare the memory ranges occupied by
>>> records A and B. They could have different pad bytes (and bits) but
>>> still be the same.
>>
>> Isn't the number of pad bytes a property of a type ? So when two vars
>> are of the same type, they also have the same number of pad bytes ?
>
> Yes, but two different variables of the same type could have different
> values for those pad bytes. So you have to compare everything but the
> pad bytes.

Yes, consider

        type myRec = record b: boolean; l: longint end;

Dependent on the alignment (and packing) mode there can be 0, 1 or 3
pad bytes between the two fields.

By the way, in a similar thread about this subject for gpc
(<http://www.gnu-pascal.de/crystal/gpc/en/thread12594.html>) a perl
script was posted
(<http://www.gnu-pascal.de/crystal/gpc/en/mail12604.html>) that
automatically creates comparison operators for record types. I haven't
checked if it works with fpc.

Regards,

Adriaan van Os

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Vinzent Höfler
In reply to this post by Micha Nelissen
On Wednesday 26 October 2005 09:26, Micha Nelissen wrote:
> Jonas Maebe wrote:
> > Yes, but two different variables of the same type could have
> > different values for those pad bytes. So you have to compare
> > everything but the pad bytes.
>
> Oh right! Something like a masked compare or so...probably not
> implementable in an efficient way indeed I guess.

Whatever you call efficient. A simple memory compare won't do, as others
already pointed out, and everything else depends on the actual layout
of the structure.

Let's take a look at a compiler which does such nasty things:

--8< -- snip --
with Ada.Text_IO;

procedure t is

   type Padded_Record is
      record
         A : Integer range 0 .. 3;
         B : Integer range 0 .. 30000;
      end record;

   for Padded_Record use
      record
         A at 0 range 3 ..  5; -- use bits [5:3] of byte 0
         B at 3 range 1 .. 15; -- use bits [15:1] of bytes 3 and 4
      end record;

   function Compare (Left, Right : Padded_Record) return Boolean is
   begin
      return Left = Right;
   end Compare;

   X, Y : Padded_Record;
begin
   X.A := 2;
   X.B := 20000;

   Y := X;

   Ada.Text_IO.Put_Line (Boolean'Image (Compare (X, Y)));
end t;
--8< -- snip --

The interesting compare function after compiled with gcc3.1.1's
"gnatmake -f -S -O3 -fomit-frame-pointer t.adb" we get:

-- 8< -- snip --
t__compare.0:
        pushl %esi
        xorl %esi, %esi
        pushl %ebx
        pushl %ebx
        movl %ecx, (%esp)
        movl 20(%esp), %ebx
        movl 16(%esp), %ecx
        movb (%ebx), %al
        movb (%ecx), %dl
        andl $56, %eax
        andl $56, %edx
        cmpb %al, %dl
        je .L49
.L42:
        movl %esi, %eax
        popl %edx
        popl %ebx
        popl %esi
        ret
        .p2align 4,,7
.L49:
        movb 3(%ecx), %dl
        xorl %eax, %eax
        movb 4(%ecx), %cl
        movb 4(%ebx), %al
        shrb %dl
        andl $255, %ecx
        sall $7, %ecx
        andl $255, %edx
        sall $7, %eax
        orl %edx, %ecx
        movb 3(%ebx), %dl
        shrb %dl
        andl $255, %edx
        orl %edx, %eax
        cmpw %ax, %cx
        jne .L42
        movl $1, %esi
        jmp .L42
-- 8< -- snip --

Of course, the type layout I forced here is really nasty, the resulting
code looks quite a lot better to me when B start at bit 0 again.


Vinzent.

--
public key: http://www.t-domaingrabbing.ch/publickey.asc

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

attachment0 (196 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Records

Micha Nelissen
Vinzent Hoefler wrote:
>>Oh right! Something like a masked compare or so...probably not
>>implementable in an efficient way indeed I guess.
>
>
> Whatever you call efficient. A simple memory compare won't do, as others
> already pointed out, and everything else depends on the actual layout
> of the structure.

Your structure is very short, code length will explode for larger
structures. It's inefficient compared to "REPE CMPSD" with proper
context, this is only a few lines.

> andl $56, %eax
> andl $56, %edx
> cmpb %al, %dl
> je .L49
> .L42:
> movl %esi, %eax
> popl %edx
> popl %ebx
> popl %esi
> ret

What does this part do btw? Compare lengths?

Micha

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Records

Vinzent Höfler
On Wednesday 26 October 2005 10:06, Micha Nelissen wrote:

> Vinzent Hoefler wrote:
> >>Oh right! Something like a masked compare or so...probably not
> >>implementable in an efficient way indeed I guess.
> >
> > Whatever you call efficient. A simple memory compare won't do, as
> > others already pointed out, and everything else depends on the
> > actual layout of the structure.
>
> Your structure is very short, code length will explode for larger
> structures.
Yes, of course, especially when the structures do not contain large
fields of contiguous data which can be compared with "repe cmpsd" or
whatever equivalents other processors besides x86 might have.

But that would - of course - also be the case, if you write your own
comparison function in the higher level language (without specialized
typecasts).

> It's inefficient compared to "REPE CMPSD" with proper
> context, this is only a few lines.

Precisely. But that's just the way it has to be, there's no way around
it unless you assume that unused padding bits/bytes always have the
same value (which could be a wrong assumption in quite a lot of cases -
try reading such values from an external hardware device with unused
connections left floating).

For these sort of things, it will be as inefficient as it can get either
way, no matter if you let the compiler do the work or if you come up
with your own comparison function.

> > andl $56, %eax
> > andl $56, %edx
> > cmpb %al, %dl
> > je .L49
> > .L42:
> > movl %esi, %eax
> > popl %edx
> > popl %ebx
> > popl %esi
> > ret
>
> What does this part do btw? Compare lengths?
No, it masks off the unused bits (Padded_Record.A is located in the
middle of an octett like this XXX---XXX) and then does the comparison,
I would suppose. It falls through directly to the exit code (restoring
saved registers, and then returning the value) at .L42 if the
comparison already fails. I really meant it, when I wrote, that the
structure I told the compiler to build up is quite nasty. ;-)


Vinzent.

--
public key: http://www.t-domaingrabbing.ch/publickey.asc

_______________________________________________
fpc-pascal maillist  -  [hidden email]
http://lists.freepascal.org/mailman/listinfo/fpc-pascal

attachment0 (196 bytes) Download Attachment