Discussion:
[fpc-devel] OSX: Setting up parameters to objc_msgSend()
David Jenkins
2018-10-11 19:41:25 UTC
Permalink
This is specifically about objectivce C bridge.  Hopefully this is the
right forum.

I am seeing a problem with how BOOL values are passed to objc_msgSend. 
The example is a call to NSMenuItem.setEnable(BOOL) from the
lcl/interfaces/cocoa/cocoawsmenus.pas file.  Here is the code:

class function TCocoaWSMenuItem.SetEnable(const AMenuItem: TMenuItem;
  const Enabled: boolean): boolean;
begin
  Result:=Assigned(AMenuItem) and (AMenuItem.Handle<>0);
  if not Result then Exit;
  NSMenuItem(AMenuItem.Handle).setEnabled( Enabled );
end;

Here is the assembly code generated by fpc (3.1.1) for just the section
where .setEnabled(Enabled) is called

->  0x1001ba68d <+61>:  movq   -0x8(%rbp), %rdi
    0x1001ba691 <+65>:  callq  0x1002016d0               ; GETHANDLE at
menuitem.inc:515
    0x1001ba696 <+70>:  movq   %rax, %rbx
    0x1001ba699 <+73>:  movq   0x329ee0(%rip), %rsi      ; "setEnabled:"
    0x1001ba6a0 <+80>:  movb   -0x10(%rbp), %dl
    0x1001ba6a3 <+83>:  movq   %rbx, %rdi
    0x1001ba6a6 <+86>:  callq  0x1002d23da               ; symbol stub
for: objc_msgSend

Notice the the value of Enabled (a BOOL) is treated as 8bit (which BOOL
is) and placed into the lowest 8 bits of edx with the line 'movb  
-0x10(%rbp), %dl'.  Which means that the upper 24 bits of edx are not
changed (not cleared, not signed extended, nothing, just left alone).

Here is the assembly code generated by XCode for a similar call to
NSMenuItem.setEnable() from objective c code:
0x100001258 <+440>: movq   -0x40(%rbp), %rax
    0x10000125c <+444>: movb   -0x19(%rbp), %cl
    0x10000125f <+447>: movq   0x185a(%rip), %rsi        ; "setEnabled:"
    0x100001266 <+454>: movq   %rax, %rdi
    0x100001269 <+457>: movsbl %cl, %edx
    0x10000126c <+460>: callq  *0xd9e(%rip)              ; (void
*)0x00007fff55e30e80: objc_msgSend

Register 'edx' is the register of concern again.  In this case the 8 bit
BOOL value stored in %cl is placed into %edx with the line 'movsbl %cl,
%edx'.  In other words the 8 bit BOOL value is sign extended through all
the bits of %edx.

This is different than what fpc does and I think causing a problem. The
top level symptom of the problem that lead me to look at this is that
currently I cannot manually enable/disable NSMenuItem's because calling
.setEnable doesn't work.

Looking at the disassembly for .setEnable I see that the 'disable' flag
for the object is stored in a 32bit record bitfield (bit 8) in
NSMenuItem._miFlags;  The code loads %ecx with the _miFlags, shifts left
8 to get the 'disable' bit in to 0 position, and then ands with
0x00000001 to mask off all other bits.  It then does a cmpl of %edx and
%ecx to determine if the NSMenuITem is already in the desired state or
not.  If it is in the desired state then the code exists without
changing the state.

here is the assembly for the first part of NSMenuItem.setEnabled:

AppKit`-[NSMenuItem setEnabled:]:
->  0x7fff2bff1a5f <+0>:   pushq  %rbp
    0x7fff2bff1a60 <+1>:   movq   %rsp, %rbp
    0x7fff2bff1a63 <+4>:   pushq  %r15
    0x7fff2bff1a65 <+6>:   pushq  %r14
    0x7fff2bff1a67 <+8>:   pushq  %rbx
    0x7fff2bff1a68 <+9>:   pushq  %rax
    0x7fff2bff1a69 <+10>:  movq   %rdi, %rbx
     0x7fff2bff1a6c <+13>:  movq   0x5c365045(%rip), %rax    ;
NSMenuItem._miFlags
    0x7fff2bff1a73 <+20>:  movl   (%rbx,%rax), %esi
    0x7fff2bff1a76 <+23>:  movl   %esi, %ecx
    0x7fff2bff1a78 <+25>:  shrl   $0x8, %ecx
    0x7fff2bff1a7b <+28>:  andl   $0x1, %ecx
    0x7fff2bff1a7e <+31>:  cmpl   %edx, %ecx
    0x7fff2bff1a80 <+33>:  jne    0x7fff2bff1ae8            ; <+137>


The FPC code works when %edx upper bits are, by luck, empty but not when
they have non-zero bits.  On my machine coming into the above LCL code
%edx always has upper bits set and I cannot get .setEnable to work.

It appears to me that objc_msgSend is expecting that parameters passed
in are signed extended and that any code called by objc_msgSend will
treat the registers as such.  I spent some time trying to find
documentation for objc runtime / objc_msgSend that shows this but didn't
find anything that went into that level of detail.

If objc_msgSend does expect this then I think the FPC objective c
bridging is not correct.  Can any of you all verify this?

David Jenkins
Scooter Software





_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Jonas Maebe
2018-10-11 20:16:22 UTC
Permalink
Post by David Jenkins
Here is the assembly code generated by fpc (3.1.1) for just the section
where .setEnabled(Enabled) is called
->  0x1001ba68d <+61>:  movq   -0x8(%rbp), %rdi
    0x1001ba691 <+65>:  callq  0x1002016d0               ; GETHANDLE at
menuitem.inc:515
    0x1001ba696 <+70>:  movq   %rax, %rbx
    0x1001ba699 <+73>:  movq   0x329ee0(%rip), %rsi      ; "setEnabled:"
    0x1001ba6a0 <+80>:  movb   -0x10(%rbp), %dl
    0x1001ba6a3 <+83>:  movq   %rbx, %rdi
    0x1001ba6a6 <+86>:  callq  0x1002d23da               ; symbol stub
for: objc_msgSend
Notice the the value of Enabled (a BOOL) is treated as 8bit (which BOOL
is) and placed into the lowest 8 bits of edx with the line 'movb
-0x10(%rbp), %dl'.  Which means that the upper 24 bits of edx are not
changed (not cleared, not signed extended, nothing, just left alone).
That's because the x86-64 ABI says
(https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
):

***
When a value of type _Bool is returned or passed in a register or on the
stack, bit 0 contains the truth value and bits 1 to 7 shall be zero. (14)

...

(14) Other bits are left unspecified, hence the consumer side of those
values can rely on it being 0 or 1 when truncated to 8 bit
***

However, the Objective-C BOOL type does not map to _Bool on x86-64, but
to signed char. And values of that type indeed do need to (sign)
extended. So this needs to be fixed in the compiler. Please file a bug
report, and thanks for the analysis.


Jonas
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists
David Jenkins
2018-10-11 21:51:05 UTC
Permalink
Thanks.  I'll get a bug report in tomorrow morning.
Post by Jonas Maebe
Post by David Jenkins
Here is the assembly code generated by fpc (3.1.1) for just the
section where .setEnabled(Enabled) is called
->  0x1001ba68d <+61>:  movq   -0x8(%rbp), %rdi
     0x1001ba691 <+65>:  callq  0x1002016d0 ; GETHANDLE at
menuitem.inc:515
     0x1001ba696 <+70>:  movq   %rax, %rbx
     0x1001ba699 <+73>:  movq   0x329ee0(%rip), %rsi ; "setEnabled:"
     0x1001ba6a0 <+80>:  movb   -0x10(%rbp), %dl
     0x1001ba6a3 <+83>:  movq   %rbx, %rdi
objc_msgSend
Notice the the value of Enabled (a BOOL) is treated as 8bit (which
BOOL is) and placed into the lowest 8 bits of edx with the line 'movb
-0x10(%rbp), %dl'.  Which means that the upper 24 bits of edx are not
changed (not cleared, not signed extended, nothing, just left alone).
That's because the x86-64 ABI says
(https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf
***
When a value of type _Bool is returned or passed in a register or on
the stack, bit 0 contains the truth value and bits 1 to 7 shall be
zero. (14)
...
(14) Other bits are left unspecified, hence the consumer side of those
values can rely on it being 0 or 1 when truncated to 8 bit
***
However, the Objective-C BOOL type does not map to _Bool on x86-64,
but to signed char. And values of that type indeed do need to (sign)
extended. So this needs to be fixed in the compiler. Please file a bug
report, and thanks for the analysis.
Jonas
_______________________________________________
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cg
Dmitry Boyarintsev
2018-10-12 00:07:04 UTC
Permalink
Post by Jonas Maebe
However, the Objective-C BOOL type does not map to _Bool on x86-64, but
to signed char. And values of that type indeed do need to (sign)
extended.
Should use of ByteBool resolve the problems for ObjC mapped headers for the
current version of the compiler?
is "ByteBool" an alias for Boolean, or is it forcefully "char" sized for
x86_64 ABI?

thanks,
Dmitry
Sven Barth via fpc-devel
2018-10-12 05:50:53 UTC
Permalink
Post by Dmitry Boyarintsev
Post by Jonas Maebe
However, the Objective-C BOOL type does not map to _Bool on x86-64, but
to signed char. And values of that type indeed do need to (sign)
extended.
Should use of ByteBool resolve the problems for ObjC mapped headers for
the current version of the compiler?
is "ByteBool" an alias for Boolean, or is it forcefully "char" sized for
x86_64 ABI?
Even Boolean has the correct size of 1 Byte. The difference is the value of
True: For Boolean its always 1, for ByteBool it's "not 0".

Regards,
Sven
Dmitry Boyarintsev
2018-10-12 13:17:30 UTC
Permalink
On Fri, Oct 12, 2018 at 1:51 AM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
Post by Dmitry Boyarintsev
Post by Jonas Maebe
However, the Objective-C BOOL type does not map to _Bool on x86-64, but
to signed char. And values of that type indeed do need to (sign)
extended.
Should use of ByteBool resolve the problems for ObjC mapped headers for
the current version of the compiler?
is "ByteBool" an alias for Boolean, or is it forcefully "char" sized for
x86_64 ABI?
Even Boolean has the correct size of 1 Byte. The difference is the value
of True: For Boolean its always 1, for ByteBool it's "not 0".
But it feels like "signed chars" are treated differently, where the value
would extended to the remaining bits of the register.
That's why I was wondering if "ByteBool" would be passed differently than
"Boolean" on 64-bit.

Here's a similar discussion
https://stackoverflow.com/questions/31267325/bool-with-64-bit-on-ios

It actually states that true _Bool is only used for 64-bit ARM and no other
targets.

So, I'm wondering if it's actually a compiler issue or headers issue.
and can ByteBool be used as a substitute for signed char.

thanks,
Dmitry
David Jenkins
2018-10-12 14:38:06 UTC
Permalink
Post by Dmitry Boyarintsev
So, I'm wondering if it's actually a compiler issue or headers issue.
and can ByteBool be used as a substitute for signed char.
thanks,
Dmitry
_______________________________________________
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel
Changing the header for NSMenuItem.setEnable(BOOL) to
NSMenuItem(ByteBool) results in the following code in
TCocoaWSmenuITem.setEnable:

    0x1001ba67e <+70>:  movq   %rax, %rbx
    0x1001ba681 <+73>:  movq   0x329ef8(%rip), %rsi      ; "setEnabled:"
    0x1001ba688 <+80>:  movb   -0x10(%rbp), %al
    0x1001ba68b <+83>:  orb    %al, %al
    0x1001ba68d <+85>:  setne  %dl
    0x1001ba690 <+88>:  negb   %dl
    0x1001ba692 <+90>:  movsbl %dl, %edx
    0x1001ba695 <+93>:  movq   %rbx, %rdi
    0x1001ba698 <+96>:  callq  0x1002d23da               ; symbol stub
for: objc

The movsbl %dl, %edx is good.  Unfortunately the value of %edx is
0xffffffff not 0x00000001.  This is the same result I saw when I changed
it to LongBool.

David
David Jenkins
2018-10-12 15:07:11 UTC
Permalink
Bug report is entered: Mantis #0034411

David


_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepasc
Dmitry Boyarintsev
2018-10-12 15:09:59 UTC
Permalink
The movsbl %dl, %edx is good. Unfortunately the value of %edx is
0xffffffff not 0x00000001. This is the same result I saw when I changed it
to LongBool.
I presume this is due to the definition of YES macro in objc, which is 1
(rather than ~NO)
https://developer.apple.com/documentation/objectivec/objective-c_runtime/boolean_values?language=objchttps://developer.apple.com/documentation/objectivec/bool

so, far the only reliable approach to fix the issue (for the current
compiler version) is something like that:

unit cocoa_extra;

type
OBJCBOOL = ShortInt;
...
NSMenuFix = objccategory external (NSMenu)
function itemAtIndex(index: NSInteger): NSMenuItem; message
'itemAtIndex:';
function setEnabled_(aenabled: OBJCBOOL ): NSMenuItem; message
'setEnabled:'; // same method, different parameter type
end;

class function TCocoaWSMenuItem.SetEnable(const AMenuItem: TMenuItem;
const Enabled: boolean): boolean;
begin
Result:=Assigned(AMenuItem) and (AMenuItem.Handle<>0);
if not Result then Exit;
NSMenuItem(AMenuItem.Handle).setEnabled_( Ord(Enabled) ); // totally
matches ObjC YES / NO definitions
end;

Not really sure, if it can be properly be solved through the compiler.
Because it either would break Boolean (_Bool) or ByteBool.
OR ByteBool needs to be more strict on it's Ord() value (optionally?)

thanks,
Dmitry
Dmitry Boyarintsev
2018-10-12 15:25:54 UTC
Permalink
On Fri, Oct 12, 2018 at 11:09 AM Dmitry Boyarintsev <
Post by Dmitry Boyarintsev
so, far the only reliable approach to fix the issue (for the current
Maybe "Boolean8" type should help instead?
David, could you please test with Boolean8 instead of ByteBool?

thanks,
Dmitry
Sven Barth via fpc-devel
2018-10-12 17:06:51 UTC
Permalink
Post by Dmitry Boyarintsev
On Fri, Oct 12, 2018 at 11:09 AM Dmitry Boyarintsev <
Post by Dmitry Boyarintsev
so, far the only reliable approach to fix the issue (for the current
Maybe "Boolean8" type should help instead?
David, could you please test with Boolean8 instead of ByteBool?
Boolean8 is an alias to Boolean. But if you need to work with 1 and 0, but
have 4 Byte width then you could try Boolean32.

Regards,
Sven
Dmitry Boyarintsev
2018-10-12 17:21:49 UTC
Permalink
On Fri, Oct 12, 2018 at 1:07 PM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
Post by Dmitry Boyarintsev
Maybe "Boolean8" type should help instead?
David, could you please test with Boolean8 instead of ByteBool?
Boolean8 is an alias to Boolean. But if you need to work with 1 and 0, but
have 4 Byte width then you could try Boolean32.
Hmm, this is odd.
https://www.freepascal.org/docs-html/ref/refsu4.html
Boolean8, size=1, ord=1
"In addition to the simple Boolean type, the additional Boolean8,
Boolean16, Boolean32 and Boolean64 types exist. There are in fact integer
types, which are assignment-compatible with the simple boolean type. As an
integer, the values for True and False are 1 and 0. This can be used to
interfac with C code that defines a boolean of this size with values 0 and
1."

Boolean8 is not exactly an alias to Boolean, as it's expected to act as an
integer, rather than _Bool. (and would be expected? to be passed an
integer).
However, fpc 3.0.4 doesn't have Boolean8 as builtin type. Instead it
provides Boolean16+ only. Maybe it's available in trunk only.

thanks,
Dmitry
Jonas Maebe
2018-10-12 18:31:28 UTC
Permalink
Post by Dmitry Boyarintsev
Boolean8 is not exactly an alias to Boolean, as it's expected to act as
an integer,
The documentation is wrong.
Post by Dmitry Boyarintsev
rather than _Bool. (and would be expected? to be passed an
Boolean8 is defined as an alias for Boolean in the RTL, so it won't
help. The only ways I can think of to fix this are to either add a new
ObjCBool type to the compiler (or make Pasbool8 a built-in type that is
different from Boolean, which amounts to the same thing), or to remove
the optimization for passing boolean types that's specified in the
x86-64 ABI.


Jonas
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/m
Dmitry Boyarintsev
2018-10-12 18:53:28 UTC
Permalink
Post by Jonas Maebe
The documentation is wrong.
Boolean8 is defined as an alias for Boolean in the RTL, so it won't
help.
If the intent of BooleanN is to help interfacing C-libraries.
Would it make sense to change BooleanN from being an alias to more
consistent behavior with its 16,32 and 64 counterparts?
Post by Jonas Maebe
The only ways I can think of to fix this are to either add a new
ObjCBool type to the compiler (or make Pasbool8 a built-in type that is
different from Boolean, which amounts to the same thing),
There are chances that other libraries might benefit from Boolean8. Not
limited to ObjC declaration/use.
Post by Jonas Maebe
or to remove
the optimization for passing boolean types that's specified in the
x86-64 ABI.
Wouldn't it break the compatibility with any existing x86_64 _Bool code?

If it's the same amount of work anyway, why not to make Boolean8 work as
described in the documentation.
It would save time on fixing docs for sure :)

thanks,
Dmitry
Sven Barth via fpc-devel
2018-10-12 19:51:13 UTC
Permalink
Post by Dmitry Boyarintsev
On Fri, Oct 12, 2018 at 1:07 PM Sven Barth via fpc-devel
Maybe "Boolean8"  type should help instead? 
David, could you please test with Boolean8 instead of ByteBool?
Boolean8 is an alias to Boolean. But if you need to work with 1 and
0, but have 4 Byte width then you could try Boolean32. 
Hmm, this is odd.
https://www.freepascal.org/docs-html/ref/refsu4.html
Boolean8, size=1, ord=1 
"In addition to the simple Boolean type, the additional Boolean8,
Boolean16, Boolean32 and Boolean64 types exist. There are in fact
integer types, which are assignment-compatible with the simple boolean
type. As an integer, the values for True and False are 1 and 0. This can
be used to interfac with C code that defines a boolean of this size with
values 0 and 1."
Boolean8 is not exactly an alias to Boolean, as it's expected to act as
an integer, rather than _Bool. (and would be expected? to be passed an
integer).
However, fpc 3.0.4 doesn't have Boolean8 as builtin type. Instead it
provides Boolean16+ only.  Maybe it's available in trunk only.
All the Pascal Boolean types are not "Integer types". You can't assign
any of them to a Integer or whatever without typecasting. They *all*
behave like Boolean, because that was the way they were added. They are
all 1-bit zero extended to the specified size. Look at the compiler
sources, they are all implemented as pasboolSIZE, including Boolean. The
documentation simply is *wrong* here.
Compare this to the *Bool family of types that are 1-bit *sign*-extended
to the specified size.

Now for the problem at hand the question is either if the ABI is
implemented incorrectly or that a new kind of Boolean type is required
to correctly represent the _Bool type needed by Objective C.

Regards,
Sven
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.or
Michael Van Canneyt
2018-10-12 20:00:33 UTC
Permalink
Post by Sven Barth via fpc-devel
Post by Dmitry Boyarintsev
On Fri, Oct 12, 2018 at 1:07 PM Sven Barth via fpc-devel
Maybe "Boolean8"  type should help instead? 
David, could you please test with Boolean8 instead of ByteBool?
Boolean8 is an alias to Boolean. But if you need to work with 1 and
0, but have 4 Byte width then you could try Boolean32. 
Hmm, this is odd.
https://www.freepascal.org/docs-html/ref/refsu4.html
Boolean8, size=1, ord=1 
"In addition to the simple Boolean type, the additional Boolean8,
Boolean16, Boolean32 and Boolean64 types exist. There are in fact
integer types, which are assignment-compatible with the simple boolean
type. As an integer, the values for True and False are 1 and 0. This can
be used to interfac with C code that defines a boolean of this size with
values 0 and 1."
Boolean8 is not exactly an alias to Boolean, as it's expected to act as
an integer, rather than _Bool. (and would be expected? to be passed an
integer).
However, fpc 3.0.4 doesn't have Boolean8 as builtin type. Instead it
provides Boolean16+ only.  Maybe it's available in trunk only.
All the Pascal Boolean types are not "Integer types". You can't assign
any of them to a Integer or whatever without typecasting. They *all*
behave like Boolean, because that was the way they were added. They are
all 1-bit zero extended to the specified size. Look at the compiler
sources, they are all implemented as pasboolSIZE, including Boolean. The
documentation simply is *wrong* here.
What exactly is wrong ?

boolean8 has been removed from the docs some time ago after a bugreport.
It should be online for 3.2

The statement about ord(true) being 1 is correct.

home:~/docs> fpc b1.pp
home:~/docs> ./b1
1
home:~/docs> cat b1.pp
var
B16 : Boolean16;

begin
B16:=True;
Writeln(ord(B16));
end.

So what is still wrong ?

Michael.
Jonas Maebe
2018-10-12 20:08:54 UTC
Permalink
Post by Michael Van Canneyt
What exactly is wrong ?
Boolean8/16/32/64 are ordinal and boolean types, but not integer types.


Jonas
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org
Michael Van Canneyt
2018-10-12 20:54:30 UTC
Permalink
Post by Jonas Maebe
Post by Michael Van Canneyt
What exactly is wrong ?
Boolean8/16/32/64 are ordinal and boolean types, but not integer types.
OK. I will rephrase the wording. Thanks!

Michael.
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi-bin/mailman/lis
Dmitry Boyarintsev
2018-10-12 20:54:51 UTC
Permalink
On Fri, Oct 12, 2018 at 3:51 PM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
All the Pascal Boolean types are not "Integer types". You can't assign
any of them to a Integer or whatever without typecasting. They *all*
behave like Boolean, because that was the way they were added. They are
all 1-bit zero extended to the specified size.
It's true for pascal sources, but the issue is not with pascal, but rather
interfacing C-world (where before C99 boolean didn't quite exist).
And the whole family of boolean types (if the documentation can be trusted)
was introduced for this whole purpose.

Documentation itself lays out pretty structured and consistent layout:
BooleanX - indicates a boolean of a size N-bits, and if the value is
requested, it would be translated to either 0 or 1.
NNNNBool - indicates a boolean of a sizeof(NNNN), and if the value is
requested, it can be anything that is non zero.

But since the documentation is wrong, I believe there's no consistency, and
everything is pretty much target dependent. (and it's sad).
Post by Sven Barth via fpc-devel
Now for the problem at hand the question is either if the ABI is
implemented incorrectly or that a new kind of Boolean type is required
to correctly represent the _Bool type needed by Objective C.
I do not believe that it is Objective-C specific issue.
Declared BOOL macro can be used in a plain C-function call and would have
the exact side effect.
(Apple puts it a special consideration
https://developer.apple.com/documentation/objectivec/bool)

thanks,
Dmitry
Sven Barth via fpc-devel
2018-10-12 22:48:06 UTC
Permalink
Post by Dmitry Boyarintsev
On Fri, Oct 12, 2018 at 3:51 PM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
All the Pascal Boolean types are not "Integer types". You can't assign
any of them to a Integer or whatever without typecasting. They *all*
behave like Boolean, because that was the way they were added. They are
all 1-bit zero extended to the specified size.
It's true for pascal sources, but the issue is not with pascal, but rather
interfacing C-world (where before C99 boolean didn't quite exist).
And the whole family of boolean types (if the documentation can be
trusted) was introduced for this whole purpose.
Not quite: the Boolean16, Boolean32 and Boolean64 types were introduced
because the libraries provided by GTK required a 4-Byte boolean type that
worked like Object Pascal's Boolean. Until then only Boolean and the *Bool
types existed (and in Delphi that is still true). And Boolean exists this
way because it existed this way in Turbo Pascal.
Post by Dmitry Boyarintsev
BooleanX - indicates a boolean of a size N-bits, and if the value is
requested, it would be translated to either 0 or 1.
NNNNBool - indicates a boolean of a sizeof(NNNN), and if the value is
requested, it can be anything that is non zero.
But since the documentation is wrong, I believe there's no consistency,
and everything is pretty much target dependent. (and it's sad).
It's not target dependent, it works the same on all platforms that FPC
supports.

Also the documentation is now going to be revised as the meaning should
have been that these Boolean types are *ordinals* not *integers*.
Post by Dmitry Boyarintsev
Post by Sven Barth via fpc-devel
Now for the problem at hand the question is either if the ABI is
implemented incorrectly or that a new kind of Boolean type is required
to correctly represent the _Bool type needed by Objective C.
I do not believe that it is Objective-C specific issue.
Declared BOOL macro can be used in a plain C-function call and would have
the exact side effect.
(Apple puts it a special consideration
https://developer.apple.com/documentation/objectivec/bool)
Then maybe it's an issue about the ABI (maybe all values with a size < 4
need to be correctly extended due to the ABI).

Regards,
Sven
Dmitry Boyarintsev
2018-10-12 23:56:53 UTC
Permalink
On Fri, Oct 12, 2018 at 6:48 PM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
Not quite: the Boolean16, Boolean32 and Boolean64 types were introduced
because the libraries provided by GTK required a 4-Byte boolean type that
worked like Object Pascal's Boolean.
That's interesting.
Let me ask a couple of things here:

1) gboolean is a size of int (
https://www.gtk.org/api/2.6/glib/glib-Basic-Types.html#gboolean)
where FALSE is 0 and TRUE is not FALSE.
https://www.gtk.org/api/2.6/glib/glib-Standard-Macros.html#TRUE:CAPS
so, it's more -1, rather than 1 and it doesn't quite maps to Boolean and/or
Boolean32. It's matches to LongBool.

var
b : Boolean;
lb : LongBool;
b32 : Boolean32;
begin
b := true;
lb := true;
b32 := true;
writeln(byte(b),' ',LongWord(b32),' ',LongWord(lb));
writeln(ord(b),' ',Ord(b32),' ',Ord(lb));
end.
Results in:
1 1 4294967295
1 1 -1
(matches documentation)

2) why the were they named booleanN rather than gtkboolean or something?
(I'm referring to the suggestion of using objcbool name. It seem to fit)
Post by Sven Barth via fpc-devel
Then maybe it's an issue about the ABI (maybe all values with a size < 4
need to be correctly extended due to the ABI).
I think Jonas clearly stated that ABI call works properly (to the word of
the specification)
The issues is that BOOL in objective-C is for Intel (macOS) is not _Bool
but rather a signed char.

As of today, Pascal doesn't provide Boolean type that behaves like a signed
char in ABI terms.
(Boolean, and Boolean8 are size of _Bool which matched the size of signed
char, though treated are passed as "_Bool" following ABI rules)

thanks,
Dmitry
Michael Van Canneyt
2018-10-13 07:08:14 UTC
Permalink
Post by Dmitry Boyarintsev
2) why the were they named booleanN rather than gtkboolean or something?
(I'm referring to the suggestion of using objcbool name. It seem to fit)
Because introducing a type in a language and naming it after some library is
not done. objcbool at least refers to another language.

Michael.

_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://
Dmitry Boyarintsev
2018-10-13 13:55:08 UTC
Permalink
Post by Michael Van Canneyt
Because introducing a type in a language and naming it after some library is
not done. objcbool at least refers to another language.
ObjC language doesn't have its own boolean type.
It's either C "_Bool" for ARM, or "a signed char" for Intel/PPC, with 1 for
TRUE and 0 for FALSE.

So, in sources we could declare objcbool as such:
type
objcbool = {IFDEF ARM}Boolean{$ELSE}Bool???{$ENDIF};

Bool??? - what type?
ByteBool - doesn't fit, because it's true value is not false ($FF)
Boolean - doesn't fit, because it's _Bool type (and that makes difference
for 64-bit, because passing parameters is different)
Boolean8 - doesn't fit, because it's just and alias to Boolean.
ShortInt or Byte - obviously don't fit, because they cannot accept boolean
values.

thanks,
Dmitry
Dmitry Boyarintsev
2018-10-13 14:45:06 UTC
Permalink
On Sat, Oct 13, 2018 at 9:55 AM Dmitry Boyarintsev <
Post by Dmitry Boyarintsev
ObjC language doesn't have its own boolean type.
No. I'm convienced now: http://wiki.freepascal.org/ObjC_Bool
It appears the the compiler is always clearing the entire register to pass
the paramater. No matter _Bool or BOOL (signed char).
No special treatment for _Bool.

thanks,
Dmitry
Jonas Maebe
2018-10-13 15:44:17 UTC
Permalink
Post by Dmitry Boyarintsev
On Sat, Oct 13, 2018 at 9:55 AM Dmitry Boyarintsev
ObjC language doesn't have its own boolean type.
No. I'm convienced now: http://wiki.freepascal.org/ObjC_Bool
It appears the the compiler is always clearing the entire register to
pass the paramater. No matter _Bool or BOOL (signed char).
No special treatment for _Bool.
A single test program compiled at a single optimization level does not
demonstrate how a particular compiler generates code in all possible
situations. In addition, the ABI specification trumps a particular
compiler's implementation in any case.


Jonas
_______________________________________________
fpc-devel maillist - fpc-***@lists.freepascal.org
http://lists.freepascal.org/cgi
Dmitry Boyarintsev
2018-10-13 16:03:52 UTC
Permalink
Post by Jonas Maebe
A single test program compiled at a single optimization level does not
demonstrate how a particular compiler generates code in all possible
situations. In addition, the ABI specification trumps a particular
compiler's implementation in any case.
Fair enough.
Are there any particular cases/optimizations you’re interested in?

Thanks,
Dmitry

Sven Barth via fpc-devel
2018-10-13 07:40:50 UTC
Permalink
Post by Dmitry Boyarintsev
On Fri, Oct 12, 2018 at 6:48 PM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
Not quite: the Boolean16, Boolean32 and Boolean64 types were introduced
because the libraries provided by GTK required a 4-Byte boolean type that
worked like Object Pascal's Boolean.
That's interesting.
1) gboolean is a size of int (
https://www.gtk.org/api/2.6/glib/glib-Basic-Types.html#gboolean)
where FALSE is 0 and TRUE is not FALSE.
https://www.gtk.org/api/2.6/glib/glib-Standard-Macros.html#TRUE:CAPS
so, it's more -1, rather than 1 and it doesn't quite maps to Boolean
and/or Boolean32. It's matches to LongBool.
var
b : Boolean;
lb : LongBool;
b32 : Boolean32;
begin
b := true;
lb := true;
b32 := true;
writeln(byte(b),' ',LongWord(b32),' ',LongWord(lb));
writeln(ord(b),' ',Ord(b32),' ',Ord(lb));
end.
1 1 4294967295
1 1 -1
(matches documentation)
This was the reason they were added:
https://bugs.freepascal.org/view.php?id=17400
Post by Dmitry Boyarintsev
2) why the were they named booleanN rather than gtkboolean or something?
(I'm referring to the suggestion of using objcbool name. It seem to fit)
They're an extension of the existing Boolean type with merely a different
size, so why should they be named any differently? (in addition to what
Michael wrote)
Post by Dmitry Boyarintsev
Post by Sven Barth via fpc-devel
Then maybe it's an issue about the ABI (maybe all values with a size < 4
need to be correctly extended due to the ABI).
I think Jonas clearly stated that ABI call works properly (to the word of
the specification)
The issues is that BOOL in objective-C is for Intel (macOS) is not _Bool
but rather a signed char.
As of today, Pascal doesn't provide Boolean type that behaves like a
signed char in ABI terms.
(Boolean, and Boolean8 are size of _Bool which matched the size of signed
char, though treated are passed as "_Bool" following ABI rules)
Then maybe the type used to represent that BOOL should be a "type char"
alias instead of using one of the build in Boolean types.

Regards,
Sven
Dmitry Boyarintsev
2018-10-12 18:27:11 UTC
Permalink
On Fri, Oct 12, 2018 at 1:07 PM Sven Barth via fpc-devel <
Post by Sven Barth via fpc-devel
Boolean8 is an alias to Boolean. But if you need to work with 1 and 0, but
have 4 Byte width then you could try Boolean32.
Indeed. It's scheduled for 3.2.0 release as alias for Boolean.
However, it would work the same as Boolean type. so the issue would not
resolved.
It would surely be nice to have that difference between Boolean (treated as
_Bool) and Boolean8 (treated as signer char with Ord(1)) type.

thanks,
Dmitry
Loading...