* GNAT not generating any code for sub‑program: known bug?
@ 2013-04-27 21:08 Yannick Duchêne (Hibou57)
2013-04-27 22:22 ` Yannick Duchêne (Hibou57)
2013-04-28 22:35 ` Erroneous code generation from GNAT or GCC? Yannick Duchêne (Hibou57)
0 siblings, 2 replies; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-27 21:08 UTC (permalink / raw)
Hi all,
I will make a stripped‑down version of the case, later. So far I just
wonder if any one already encountered a similar case: GNAT not generating
any code for a sub‑program. Here what it generates instead, according to
the assembly file:
.cfi_startproc
ret
.cfi_endproc
And that's all. I could just notice it appears as soon as any `-On` option
is given and disappears when `-O0` is explicitly given to disallow any
optimization.
Is this a known bug?
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-27 21:08 GNAT not generating any code for sub‑program: known bug? Yannick Duchêne (Hibou57)
@ 2013-04-27 22:22 ` Yannick Duchêne (Hibou57)
2013-04-27 23:48 ` Yannick Duchêne (Hibou57)
2013-04-28 7:14 ` Simon Wright
2013-04-28 22:35 ` Erroneous code generation from GNAT or GCC? Yannick Duchêne (Hibou57)
1 sibling, 2 replies; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-27 22:22 UTC (permalink / raw)
Le Sat, 27 Apr 2013 23:08:52 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> Hi all,
>
> I will make a stripped‑down version of the case, later.
Here is:
http://www.les-ziboux.rasama.org/download/2013-04-28-cla-gnat-bug.zip
The bug disappears when optimization is disabled or else when the
sub‑program is made inlinable. That's not only with this single
sub‑program, I get it with all of the same kind. I've checked it's the
same whether I'm compiling with `gprbuild` or `gnatmake`. I've checked
this is not due to the heavily stripped down runtime (rather no runtime at
all) I am using, as this occurs also when compiling using the compiler's
default runtime. The case occurs with GNAT from GCC 4.8. I don't really
know if it's a GNAT bug or a GCC bug.
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-27 22:22 ` Yannick Duchêne (Hibou57)
@ 2013-04-27 23:48 ` Yannick Duchêne (Hibou57)
2013-04-28 7:14 ` Simon Wright
1 sibling, 0 replies; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-27 23:48 UTC (permalink / raw)
Le Sun, 28 Apr 2013 00:22:41 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> Le Sat, 27 Apr 2013 23:08:52 +0200, Yannick Duchêne (Hibou57)
> <yannick_duchene@yahoo.fr> a écrit:
>
>> Hi all,
>>
>> I will make a stripped‑down version of the case, later.
>
> Here is:
> http://www.les-ziboux.rasama.org/download/2013-04-28-cla-gnat-bug.zip
>
> The bug disappears when optimization is disabled or else when the
> sub‑program is made inlinable.
Seems there is an issue with sub‑program using Ada's machine‑code
insertion.
If the sub‑program which contains machine‑code insertion is not inlined,
then the machine‑code insertion part gets dropped by compiler
optimization, which so seems to be more a GCC bug than a GNAT bug. The
sub‑programs invoke this sub‑program either directly or indirectly, also
has to all be inlined too.
There is a work‑around: implement the sub‑program using machine‑code
insertion as a generic, say `GP`. Then implement `P` which use an
instantiation of `GP` internally, and it will works. `GP` cannot be
declared inlined, or else you will get a GNAT bug‑box. However, if `P`
declared inlined, then its containing `GP` instantiation will be properly
inlined. `P` will be generated when it's either inlined or not
(effectively workaround the bug), and will be really fully inline if
declared inlined (no efficiency cost).
Template as a summary:
generic
…
procedure/function GP (…);
-- No `Inline` here! either `True` or `False`,
-- or else GNAT says “kaboom”.
procedure/function GP (…) is
begin
-- Machine code insertion here
end;
procedure/function P (…)
[with Inline => True/False];
-- Works with either of the three.
procedure/function P (…) is
procedure/function Implementation is
new GP (…);
begin
[return] Implementation (…);
end;
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-27 22:22 ` Yannick Duchêne (Hibou57)
2013-04-27 23:48 ` Yannick Duchêne (Hibou57)
@ 2013-04-28 7:14 ` Simon Wright
2013-04-28 17:52 ` Yannick Duchêne (Hibou57)
1 sibling, 1 reply; 19+ messages in thread
From: Simon Wright @ 2013-04-28 7:14 UTC (permalink / raw)
"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> writes:
> Here is:
> http://www.les-ziboux.rasama.org/download/2013-04-28-cla-gnat-bug.zip
The code is
function Syscall
(Number : Positive;
Handle : Natural;
Address : System.Address;
Size : Natural)
return Integer
is
Result : Integer;
begin
System.Machine_Code.Asm
(Template => "int $0x80",
Outputs => Integer'Asm_Output ("=a", Result),
Inputs =>
(Positive'Asm_Input ("a", Number),
Natural'Asm_Input ("b", Handle),
System.Address'Asm_Input ("c", Address),
Natural'Asm_Input ("d", Size)),
Volatile => False);
return Result;
end;
and I think that the problem is that Template actually has to use the
inputs and outputs! So, while optimising, the compiler says
"int $0x80" doesn't use any of the inputs, so I can ignore them
"int $0x80" doesn't write to any of the outputs, so I can ignore them
Result isn't changed, so it's undefined
Therefore I don't need to do anything.
The assembler generated by GNAT GPL 2012 is different but equally
ineffective:
.globl _library__write
_library__write:
LFB3:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
leave
LCFI2:
ret
LFE3:
I think that you have to write the template to show how the parameters
are set up and returned. Here's one I wrote earlier:
with Ada.Unchecked_Conversion;
with System.Machine_Code;
separate (BC.Support.High_Resolution_Time)
function Clock return Time is
type Half is (Low, High);
type Low_High is array (Half) of Interfaces.Unsigned_32;
Lower, Upper : Interfaces.Unsigned_32;
function To_Time is new Ada.Unchecked_Conversion (Low_High, Time);
begin
System.Machine_Code.Asm
("rdtsc" & ASCII.LF & ASCII.HT &
"movl %%eax, %0"& ASCII.LF & ASCII.HT &
"movl %%edx, %1",
Outputs => (Interfaces.Unsigned_32'Asm_Output ("=g", Lower),
Interfaces.Unsigned_32'Asm_Output ("=g", Upper)),
Clobber => "eax, edx",
Volatile => True);
return To_Time ((Low => Lower, High => Upper));
end Clock;
By the way, this doesn't actually work as intended on kit such as the
Macbook Pro (more than one core? advanced power management?), presumably
because the core's clock is slowed down or stopped. Fortunately,
Ada.Calendar.Clock's resolution is 1 microsecond, good enough for most
purposes.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-28 7:14 ` Simon Wright
@ 2013-04-28 17:52 ` Yannick Duchêne (Hibou57)
2013-04-28 19:27 ` Yannick Duchêne (Hibou57)
2013-04-28 20:43 ` Simon Wright
0 siblings, 2 replies; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-28 17:52 UTC (permalink / raw)
Le Sun, 28 Apr 2013 09:14:55 +0200, Simon Wright <simon@pushface.org> a
écrit:
> and I think that the problem is that Template actually has to use the
> inputs and outputs! So, while optimising, the compiler says
>
> "int $0x80" doesn't use any of the inputs, so I can ignore them
> "int $0x80" doesn't write to any of the outputs, so I can ignore them
> Result isn't changed, so it's undefined
> Therefore I don't need to do anything.
I thought about the same previously (not my first attempt), and retried
what I tried before, with the same result:
function Syscall_3
(N : Number_Type;
P1 : P1_Type;
P2 : P2_Type;
P3 : P3_Type)
return Result_Type
is
use System.Machine_Code;
Result : Result_Type;
begin
Asm
(Template =>
"movl %1, %%eax" & ASCII.LF &
"movl %2, %%ebx" & ASCII.LF &
"movl %3, %%ecx" & ASCII.LF &
"movl %4, %%edx" & ASCII.LF &
"int $0x80" & ASCII.LF &
"movl %%eax, %0" & ASCII.LF,
Outputs => Result_Type'Asm_Output ("=g", Result),
Inputs =>
(Number_Type'Asm_Input ("g", N),
P1_Type'Asm_Input ("g", P1),
P2_Type'Asm_Input ("g", P2),
P3_Type'Asm_Input ("g", P3)),
Clobber => "eax, ebx, ecx, edx",
Volatile => True);
return Result;
end Syscall_3;
Here (except it's a generic to avoid error while copying similar things),
the template contains all of the instructions loading registers, to be
clear about the inputs the template uses. Then, I used a `Clobber` list
[1][3] to explicitly notify the compiler of the registers used in the
template and which must remains untouched, then I also added `Volatile =>
True` [2][3] to notify the compiler it should avoid unwanted optimization.
The result is still the same, and so, even if the generic instantiation is
not inlined (the generic declaration is not inlined neither). That's
enough for a a caller to be inlined for everything to be dropped, even if
the above subprogram itself not inlined. I agree I must tell the compiler
what it is dealing with and what not to do with it, but so far, I still
feel that looks like a compiler bug (GCC's fault or GNAT's fault?). Will
try something else later.
Side note: with the `type Low_High is array (Half) of
Interfaces.Unsigned_32;` in your snippet, shouldn't you specify the array
should be packed? Or may be that's already implied by the component type…
will have to check the RM.
[1]: http://docs.adacore.com/gnat-unw-docs/html/gnat_ugn_38.html#SEC382
[2]: http://docs.adacore.com/gnat-unw-docs/html/gnat_ugn_38.html#SEC383
[3]: http://docs.adacore.com/gnat-unw-docs/html/gnat_rm_15.html#SEC626
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-28 17:52 ` Yannick Duchêne (Hibou57)
@ 2013-04-28 19:27 ` Yannick Duchêne (Hibou57)
2013-04-28 20:46 ` Simon Wright
2013-04-28 20:43 ` Simon Wright
1 sibling, 1 reply; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-28 19:27 UTC (permalink / raw)
Le Sun, 28 Apr 2013 19:52:18 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> I still feel that looks like a compiler bug (GCC's fault or GNAT's
> fault?).
That's me who bugged and that's my fault :D
Explanations with two points.
1) In the archive linked in this thread, if I change `Volatile => False`
into `Volatile => True`, it works, without even a need to use `Clobber`.
Thus, the initial case is solved.
2) In a later message I tried something else, with `Volatile => True`,
this did not work neither as I said, while it should have work. That was
because something else also changed: the package specification hold a
`pragma Pure;` and that was wrong [1]. I changed `pragma Pure;` into
`pragma Preelaborate;` and it now works as expected.
[1]: http://www.ada-auth.org/standards/12rm/html/RM-10-2-1.html#p18
> If a library unit is declared pure, then the implementationis permitted
> to omit a call on a library-level subprogramof the library unit if the
> results are not needed after thecall. In addition, the implementation
> may omit a call on sucha subprogram and simply reuse the results
> produced by an earliercall on the same subprogram, provided that […]
That's a quoted from “Implementation permissions”, and I forget it. Well,
honestly, I believe this should part of the semantic. If you read the
semantic part (above), which is what I typically focus on, nothing there
implies or even suggest this implementation permission. The semantic part
should have an explicit reference to side effects, and not just
elaboration. By the way, the whole page is titled “Elaboration Control”,
not “Sub‑program invocation semantic”. It's unlikely someone will search
in elaboration control to learn about sub‑program call semantic, these are
two different things. Well, that's a personal opinion, and I may be wrong
with it (if so, please, tell me why).
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-28 17:52 ` Yannick Duchêne (Hibou57)
2013-04-28 19:27 ` Yannick Duchêne (Hibou57)
@ 2013-04-28 20:43 ` Simon Wright
1 sibling, 0 replies; 19+ messages in thread
From: Simon Wright @ 2013-04-28 20:43 UTC (permalink / raw)
"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> writes:
> Side note: with the `type Low_High is array (Half) of
> Interfaces.Unsigned_32;` in your snippet, shouldn't you specify the
> array should be packed? Or may be that's already implied by the
> component type... will have to check the RM.
It never occurred to me that it wouldn't be ... of course I'd get a GNAT
warning if the size of Low_High wasn't the size of a Time (64).
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: GNAT not generating any code for sub‑program: known bug?
2013-04-28 19:27 ` Yannick Duchêne (Hibou57)
@ 2013-04-28 20:46 ` Simon Wright
0 siblings, 0 replies; 19+ messages in thread
From: Simon Wright @ 2013-04-28 20:46 UTC (permalink / raw)
"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> writes:
> 1) In the archive linked in this thread, if I change `Volatile =>
> False` into `Volatile => True`, it works, without even a need to use
> Clobber`. Thus, the initial case is solved.
Or you could, less satisfactorily, say
procedure Write (Item : in String) is
Status : Integer with Volatile;
^ permalink raw reply [flat|nested] 19+ messages in thread
* Erroneous code generation from GNAT or GCC?
2013-04-27 21:08 GNAT not generating any code for sub‑program: known bug? Yannick Duchêne (Hibou57)
2013-04-27 22:22 ` Yannick Duchêne (Hibou57)
@ 2013-04-28 22:35 ` Yannick Duchêne (Hibou57)
2013-04-28 22:49 ` Yannick Duchêne (Hibou57)
2013-04-28 23:52 ` Yannick Duchêne (Hibou57)
1 sibling, 2 replies; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-28 22:35 UTC (permalink / raw)
Le Sat, 27 Apr 2013 23:08:52 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> Hi all,
>
> I will make a stripped‑down version of the case, later. So far I just
> wonder if any one already encountered a similar case: GNAT not
> generating any code for a sub‑program. Here what it generates instead,
> according to the assembly file:
>
> .cfi_startproc
> ret
> .cfi_endproc
>
> […]
> Is this a known bug?
This topic was solved, but in the while, I'm encountering something which
is frightening me a bit. That's not dropped code, but erroneous code
generation.
The context: a sub‑program use machine‑code insertion. For convenience and
avoid errors, this sub‑program is generic. Then, some sub‑program
instantiate this generic locally, as part of their implementations.
As a remainder, here is the generic using machine‑code insertion:
function Invoke_3
(N : Number_Type;
P1 : P1_Type;
P2 : P2_Type;
P3 : P3_Type)
return Result_Type
is
use System.Machine_Code;
Result : Result_Type;
begin
Asm
(Template => "int $0x80",
Outputs => Result_Type'Asm_Output ("=a", Result),
Inputs =>
(Number_Type'Asm_Input ("a", N),
P1_Type'Asm_Input ("b", P1),
P2_Type'Asm_Input ("c", P2),
P3_Type'Asm_Input ("d", P3)),
Volatile => True);
return Result;
end Invoke_3;
Now, here is a sample sub‑program instantiating this generic as part of
its implementation:
procedure Write (Item : in Character) is
use Syscall_Numbers;
use Syscalls;
use Types;
Status : Result_Type;
Size : constant Size_Type := (Character'Size / 8);
function Implementation
is new Invoke_3
(P1_Type => Handle_Type,
P2_Type => Address_Type,
P3_Type => Size_Type)
with Inline => True;
begin
Status := Implementation
(N => NR_write,
P1 => 1,
P2 => Item'Address,
P3 => Size);
end;
Note `P2`, which is the address argument, goes into ecx (see `Invoke_3`
above).
This sub‑program will print an ASCII character to the standard output,
using a Linux system‑call. It will later be changed a bit, to show an
issue. This one version is working.
Note: so far, `Status` are not interpreted, I know, don't care.
Now, as sample use would be:
Write ('[');
Note: the platform is 32 bits, so all stack operations are 32 bits
(push/pop/add and sub on esp).
Here is the generated code for the invocation of the working version:
movl $91, (%esp)
call library__write__2
First, the character code passed as an argument is written at [esp], the
the sub‑program in invoked, thus the character code argument is now at
[esp+4] (32 bits platform).
Now, the generated code of the working version, which is invoked by the
above:
library__write__2:
.LFB7:
.cfi_startproc
pushl %ebx #
.cfi_def_cfa_offset 8
.cfi_offset 3, -8
subl $12, %esp #,
.cfi_def_cfa_offset 20
movl 20(%esp), %eax # item, item
movb %al, (%esp) # item, item
movl $1, %edx #, tmp64
movl %esp, %ecx #, item.19
movl $4, %eax #, tmp63
movl %edx, %ebx # tmp64, tmp64
int $0x80
Remember when invoked, the argument is tat [esp+4]. The sub‑program pushes
ebx, so the argument is now at [esp+4]. Then it substract 12 to esp, so
the argument is now at [esp+20]. Then it reads the value at [esp+20],
store it in eax, then write eax at [esp], in finally store esp to ecx,
which is OK, ecx holds the address of the parameter. The system‑call is
successfully invoked.
Now, change `Write` to that it does not get the address of it's argument,
but get the address of a local copy of its argument (rather same as above,
changes are marked):
procedure Write (Item : in Character) is
use Syscall_Numbers;
use Syscalls;
use Types;
Element : Character := Item; -- <<< Copy of argument
Status : Result_Type;
Size : constant Size_Type := (Character'Size / 8);
function Implementation
is new Invoke_3
(P1_Type => Handle_Type,
P2_Type => Address_Type,
P3_Type => Size_Type)
with Inline => True;
begin
Status := Implementation
(N => NR_write,
P1 => 1,
P2 => Element'Address, -- <<< Address of the copy
P3 => Size);
end;
This one should behave the same, isn't it? It just store of `Item` to
local `Element` and so pass `Element'Address` to the system‑call, instead
of `Item'Address`. Sounds right…
The code generated by GNAT for the invocation part is the same as earlier
above:
movl $91, (%esp)
call library__write__2
Still the same, at the entry point of the sub‑program, the argument is at
[esp+4].
Now, here the code generated for the slightly modified subprogram:
library__write__2:
.LFB7:
.cfi_startproc
pushl %ebx #
.cfi_def_cfa_offset 8
.cfi_offset 3, -8
subl $24, %esp #,
.cfi_def_cfa_offset 32
movl $1, %edx #, tmp65
leal 15(%esp), %ecx #, element.19
movl $4, %eax #, tmp64
movl %edx, %ebx # tmp65, tmp65
int $0x80
As with the previous version, it starts pushing ebx, so the argument is
now at [esp+8]. Then it substract 24 to esp, so the argument is now at
[esp+32]. But look at what it stores to ecx: it's the effective address
(lea is the Intel assembly instruction Load Effective Address)
corresponding to [esp+15]. This is the wrong address, the good address is
17 bytes above. Above all, this address does not make any sense, it is not
even 32 bits aligned. Obviously, the system‑call does not print what's
expected (it print nothing, probably there is a non‑printable character at
[esp+15]).
Also note nowhere a copy is made (remember the `Element : constant
Character := Item;` above).
The generated code looks wrong to me: it does not get the good address, it
not even a normal address, whatever it did of `Element` as a local copy of
`Item`.
Sorry for being long with this post, I wanted to provide all the materials
required to clearly expose the case.
This case makes me remind of an issue I get with GNAT 4.6, when I
discovered GNATMake was not printing some error messages it should have
print. I noted according to the GNAT tools sources, the message should
have been printed, but it was not. Now I wonder if ever GNAT it‑self
sometimes suffers from a similar bug as above.
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-28 22:35 ` Erroneous code generation from GNAT or GCC? Yannick Duchêne (Hibou57)
@ 2013-04-28 22:49 ` Yannick Duchêne (Hibou57)
2013-04-28 23:52 ` Yannick Duchêne (Hibou57)
1 sibling, 0 replies; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-28 22:49 UTC (permalink / raw)
Le Mon, 29 Apr 2013 00:35:03 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
>
> function Implementation
> is new Invoke_3
> (P1_Type => Handle_Type,
> P2_Type => Address_Type,
> P3_Type => Size_Type)
> with Inline => True;
A note on this part: I get the exact same whether inlining is on or off.
So don't focus too much on the inlining representation clause.
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-28 22:35 ` Erroneous code generation from GNAT or GCC? Yannick Duchêne (Hibou57)
2013-04-28 22:49 ` Yannick Duchêne (Hibou57)
@ 2013-04-28 23:52 ` Yannick Duchêne (Hibou57)
2013-04-29 1:35 ` Yannick Duchêne (Hibou57)
1 sibling, 1 reply; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-28 23:52 UTC (permalink / raw)
Le Mon, 29 Apr 2013 00:35:03 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> Element : Character := Item; -- <<< Copy of argument
If this, is changed into:
Element :
Character := Item
with Volatile => True;
The issue is solved. Here is the generated code:
library__write__2:
.LFB7:
.cfi_startproc
pushl %ebx #
.cfi_def_cfa_offset 8
.cfi_offset 3, -8
subl $24, %esp #,
.cfi_def_cfa_offset 32
movl 32(%esp), %eax # item, item
movb %al, 15(%esp) # item, element
movl $1, %edx #, tmp65
leal 15(%esp), %ecx #, element.19
movl $4, %eax #, tmp64
movl %edx, %ebx # tmp65, tmp65
It is still reading at a non‑32 bits aligned address even if there is only
one character at that address (well, why not, Intel 32 bits CPU does not
triggers exceptions for this), but now it is at least making a copy of
`Item`, which is fetched from [esp+32] as I expected in the previous
message, then store it at [esp+15], so the address stored in ecx is now an
address which really correspond to an initialized memory area. The
system‑call invocation succeed.
I wonder if this is normal or not. What's your opinion?
Here is what the RM says:
http://www.ada-auth.org/standards/12rm/html/RM-C-6.html#p20
> The external effect of a program (see 1.1.3) is definedto include each
> read and update of a volatile or atomicobject. The implementation shall
> not generate any memoryreads or updates of atomic or volatile objects
> other thanthose specified by the program.
This is quoted from “C.6 Shared Variable Control”. But this is a local
variable, not a shared object, and I don't intuitively agree with GNAT or
GCC optimization here. Unless I'm wrong, in which case I welcome any
rationale relevant to explain why.
The parameters passed to a sub‑program may also be used or not, and GNAT
does not dropped them all. As it can be noticed, it did not dropped
parameter passing, and the parameter is not declared as being of a
volatile type.
Seems less care is taken by the compiler, with foreign machine‑code
insertion, even if via some level of indirection, than with it's own
generated code, while it should be the opposite.
Until now, I though the volatile aspect was typically to be used with
object which may be updated as a non‑visible side effect, like with a
peripheral writing at some memory area, asynchronously (or not, that's
still not directly visible anyway). But here, that's a local variable,
which is explicitly referred to and explicitly assigned. If the address is
passed, that should implies the address means something, especially if the
address is an input parameter as it is here. And what means the address of
an uninitialised area when that area was directed to be explicitly
initialized by the source? Isn't GNAT of GCC lacking some semantic
dependency tracking here?
May be I should make parameter types of the system‑call's generic
declaration, all volatile? If so, this would implies that can be said of
all machine‑code insertions?
But then, why isn't it automatic so?
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-28 23:52 ` Yannick Duchêne (Hibou57)
@ 2013-04-29 1:35 ` Yannick Duchêne (Hibou57)
2013-04-30 0:48 ` Yannick Duchêne (Hibou57)
0 siblings, 1 reply; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-29 1:35 UTC (permalink / raw)
Le Mon, 29 Apr 2013 01:52:22 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> Until now, I though the volatile aspect was typically to be used with
> object which may be updated as a non‑visible side effect, like with a
> peripheral writing at some memory area […]
This way of understanding things must not be entirely wrong.
In the above solution involving volatile (once again, like in the other
thread), the object is locally constant, as it is assigned, and never
modified. So wanted to turn its declaration into this:
Element :
constant Character := Item
with Volatile => True;
But GNAT complained, with a trustable reason, as it refers to the RM:
stand alone volatile constant must be imported (RM C.6(13))
Here, according to the RM, a volatile constant declared in the Ada world
and initialized in the Ada world, is not a valid candidate for a volatile
aspect:
RM C.6(13) says:
> If an aspect Volatile, Volatile_Components, Atomic, orAtomic_Components
> is directly specified to have the valueTrue for a stand-alone constant
> object, then the aspectImport shall also be specified as True for it.
(oops, the `Import` aspect is not of boolean type …but what it means is
still clear)
This suggest if the object is not modified, then the volatile aspect
should not be required, unless the so‑called constant is not a constant in
the strict Ada meaning (imported from the external world, and so which may
be initialized who‑know‑when, and may also be modified later, externally).
What would help, is a way to tell the compiler the address is used, not
for its own, but for what it refers to.
If all parameters must be volatile when there address attribute is used,
that implies systematic copy of everything, as types defined for Ada
programs, are not to be volatile. Ex. each string should be copied to an
array of characters whose components are volatile (there is a
`Volatile_Components` aspect).
Surprisingly, there is not such issue (or I've just never encountered any
case?) when linking to similar sub‑programs in C or assembly and declared
imported: there is no need to tell what's referred to by a pointer, is
really needed. I wanted to try to use machine‑code insertion, to have most
of or all things in Ada packages and to benefit from Ada checking.
I feel to not really understand how machine‑code insertion works or is
defined (especially when optimization is enabled), and it looks to me,
surprisingly a lot harder to set‑up than linking to similar imported
sub‑programs.
So now, I'm seeking for something which would have the effect of a (an
invalid) `pragma Volatile (Item'Address'Memory)` which seems to be
implicit or not required when interfacing to C.
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-29 1:35 ` Yannick Duchêne (Hibou57)
@ 2013-04-30 0:48 ` Yannick Duchêne (Hibou57)
2013-04-30 6:40 ` Simon Wright
0 siblings, 1 reply; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-30 0:48 UTC (permalink / raw)
Le Mon, 29 Apr 2013 03:35:53 +0200, Yannick Duchêne (Hibou57)
<yannick_duchene@yahoo.fr> a écrit:
> If all parameters must be volatile when there address attribute is used,
> that implies systematic copy of everything, as types defined for Ada
> programs, are not to be volatile
Finally, this may be seen as a kind of representation conversion, where
copying to buffers before sending to the outside world is also required.
Beside this, I noted something from the RM:
http://www.adaic.org/resources/add_content/standards/05aarm/html/AA-13-8.html
> If a subprogram_body contains any code_statements, then
> within this subprogram_body the only allowed form of statement
> is a code_statement (labeled or not), the only allowed declarative_items
> are use_clauses, and no exception_handler is allowed (comments and
> pragmas
> are allowed as usual).
This seems to mean object declarations are not allowed in this context.
But I did use object declarations in this context and GNAT did not
complained. Which is right and which is wrong?
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-30 0:48 ` Yannick Duchêne (Hibou57)
@ 2013-04-30 6:40 ` Simon Wright
2013-04-30 17:04 ` Yannick Duchêne (Hibou57)
0 siblings, 1 reply; 19+ messages in thread
From: Simon Wright @ 2013-04-30 6:40 UTC (permalink / raw)
"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> writes:
> Le Mon, 29 Apr 2013 03:35:53 +0200, Yannick Duchêne (Hibou57)
> <yannick_duchene@yahoo.fr> a écrit:
>> If all parameters must be volatile when there address attribute is
>> used, that implies systematic copy of everything, as types defined
>> for Ada programs, are not to be volatile
> Finally, this may be seen as a kind of representation conversion,
> where copying to buffers before sending to the outside world is also
> required.
I suspect that the problem may be the 'clobber'. In [1], it says "You
may not write a clobber description in a way that overlaps with an input
or output operand. For example, you may not have an operand describing a
register class with one member if you mention that register in the
clobber list." So the clobber description is for registers that are
overwritten implicitly.
> Beside this, I noted something from the RM:
>
> http://www.adaic.org/resources/add_content/standards/05aarm/html/AA-13-8.html
>> If a subprogram_body contains any code_statements, then
>> within this subprogram_body the only allowed form of statement
>> is a code_statement (labeled or not), the only allowed declarative_items
>> are use_clauses, and no exception_handler is allowed (comments and
>> pragmas
>> are allowed as usual).
>
> This seems to mean object declarations are not allowed in this
> context. But I did use object declarations in this context and GNAT
> did not complained. Which is right and which is wrong?
[2] says that the procedure version of the Asm subprograms "can be used
anywhere a procedure call would be valid, and correspond to what the RM
calls "intrinsic" routines. Such calls can be used to intersperse
machine instructions with other Ada statements.".
[1]
http://gcc.gnu.org/onlinedocs/gcc-4.6.0/gcc/Extended-Asm.html#Extended-Asm
[2]
http://gcc.gnu.org/onlinedocs/gcc-4.6.0/gnat_rm/Machine-Code-Insertions.html
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-30 6:40 ` Simon Wright
@ 2013-04-30 17:04 ` Yannick Duchêne (Hibou57)
2013-04-30 19:06 ` Simon Wright
0 siblings, 1 reply; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-30 17:04 UTC (permalink / raw)
Le Tue, 30 Apr 2013 08:40:35 +0200, Simon Wright <simon@pushface.org> a
écrit:
> I suspect that the problem may be the 'clobber'. In [1], it says "You
> may not write a clobber description in a way that overlaps with an input
> or output operand. For example, you may not have an operand describing a
> register class with one member if you mention that register in the
> clobber list." So the clobber description is for registers that are
> overwritten implicitly.
You're right about clobber, and GNAT takes care of it, when it tells you
the constraint cannot be satisfied if you use a register for both
input/output and in the clobber list.
In my use case, I don't use clobber, so that cannot be the reason. I
didn't need it, as everything is explicit and the whole statement is
volatile.
The issue in this thread seems to not be directly addressable with clobber
of volatile applied to the machine‑code statement; that's an issue with
indirection: a register holds an address to something, and the object at
that address must be made volatile, or else it may be optimized out. So I
wondered if when passing an address to something (the compiler knows if
comes from an address attribute), if this makes sense to generate the
address to the object while dropping the Ada instructions which creates
this object. That's why I said “may be GNAT or GCC are lacking some
semantic dependency tracking here”. That's just a question, I'm not sure
of the answer and just personally believe if the address is generated and
passed, then this should imply the Ada instructions creating the object
should not be dropped.
In the mean time, that's output to the external world, and it most of time
requires representation conversion which implies copying, so I will go
with copying to volatile buffers and consider it as a similar issue as
representation conversion is.
>> Beside this, I noted something from the RM:
>>
>> http://www.adaic.org/resources/add_content/standards/05aarm/html/AA-13-8.html
>>> If a subprogram_body contains any code_statements, then
>>> within this subprogram_body the only allowed form of statement
>>> is a code_statement (labeled or not), the only allowed
>>> declarative_items
>>> are use_clauses, and no exception_handler is allowed (comments and
>>> pragmas
>>> are allowed as usual).
>>
>> This seems to mean object declarations are not allowed in this
>> context. But I did use object declarations in this context and GNAT
>> did not complained. Which is right and which is wrong?
>
> [2] says that the procedure version of the Asm subprograms "can be used
> anywhere a procedure call would be valid, and correspond to what the RM
> calls "intrinsic" routines. Such calls can be used to intersperse
> machine instructions with other Ada statements.".
So when the RM says “if a subprogram_body contains any code_statements”,
what is the subject sub‑program body? I though it was the body containing
the `Asm` sub‑program. Or may be it's the `Asm` sub‑program itself?
That's not a big issue, that's just that I prefer to stick to the RM when
feasible, and if I have to write things a different way to conform to the
RM, I will do so.
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-30 17:04 ` Yannick Duchêne (Hibou57)
@ 2013-04-30 19:06 ` Simon Wright
2013-04-30 21:28 ` Yannick Duchêne (Hibou57)
2013-05-01 18:19 ` J-P. Rosen
0 siblings, 2 replies; 19+ messages in thread
From: Simon Wright @ 2013-04-30 19:06 UTC (permalink / raw)
"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> writes:
> So when the RM says "if a subprogram_body contains any
> code_statements", what is the subject sub‑program body? I though it
> was the body containing the 'Asm' sub‑program. Or may be it's the
> 'Asm' sub‑program itself?
The whole thing is bizarre: code statements are written using the form
of a qualified expression though clearly not a qualified expression
since it can't be assigned anywhere!
Each qualified expression typically represents one machine code
instruction or assembly directive.
If you are implementing a function using code statements you are
expected to know the calling convention, so that you can return the
result in the corrct way.
Clearly none of these apply to the code you wrote, so - I think - GNAT
takes advantage of the implementation permission in ARM13.8(11) [1] to
support intrinsic subprograms without all those tiresome restrictions.
As described in [2].
[2] also recommends using Volatile => True in most circumstances.
> That's not a big issue, that's just that I prefer to stick to the RM
> when feasible, and if I have to write things a different way to
> conform to the RM, I will do so.
Since everything to do with code statements/intrinsic subprograms is
compiler- and target-dependent, I don't see what you gain by this!
I was wondering what you meant by using constraints "a", "b", "c", "d"
.. I now see [3] that these are i386 constraints for the a..d registers
respectively, no wonder they gave wierd results on x86_64 where they
mean something quite different!
[1] http://www.ada-auth.org/standards/12rm/html/RM-13-8.html#p11
[2]
http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gnat_rm/Machine-Code-Insertions.html
[3] http://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Machine-Constraints.html
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-30 19:06 ` Simon Wright
@ 2013-04-30 21:28 ` Yannick Duchêne (Hibou57)
2013-04-30 22:22 ` Simon Wright
2013-05-01 18:19 ` J-P. Rosen
1 sibling, 1 reply; 19+ messages in thread
From: Yannick Duchêne (Hibou57) @ 2013-04-30 21:28 UTC (permalink / raw)
Le Tue, 30 Apr 2013 21:06:09 +0200, Simon Wright <simon@pushface.org> a
écrit:
> I was wondering what you meant by using constraints "a", "b", "c", "d"
> .. I now see [3] that these are i386 constraints for the a..d registers
> respectively, no wonder they gave wierd results on x86_64 where they
> mean something quite different!
They do exists with 64 bits instructions too. a is eax; b is ebx, etc, for
32 bits mode, and a is rax, b is rbx, etc, for 64 bits mode. There is also
ax/ah/al, ax/bh/bl, etc, as sub‑parts of the above, except ax, bx, etc, is
for 16 bits only, but ah, al, bh, bl are still a accessible in 32 bits
mode — I don't know if it's still the case in 64 bits mode.
--
“Syntactic sugar causes cancer of the semi-colons.” [1]
“Structured Programming supports the law of the excluded muddle.” [1]
[1]: Epigrams on Programming — Alan J. — P. Yale University
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-30 21:28 ` Yannick Duchêne (Hibou57)
@ 2013-04-30 22:22 ` Simon Wright
0 siblings, 0 replies; 19+ messages in thread
From: Simon Wright @ 2013-04-30 22:22 UTC (permalink / raw)
"Yannick Duchêne (Hibou57)" <yannick_duchene@yahoo.fr> writes:
> Le Tue, 30 Apr 2013 21:06:09 +0200, Simon Wright <simon@pushface.org>
> a écrit:
>> I was wondering what you meant by using constraints "a", "b", "c", "d"
>> .. I now see [3] that these are i386 constraints for the a..d registers
>> respectively, no wonder they gave wierd results on x86_64 where they
>> mean something quite different!
>
> They do exists with 64 bits instructions too. a is eax; b is ebx, etc,
> for 32 bits mode, and a is rax, b is rbx, etc, for 64 bits mode. There
> is also ax/ah/al, ax/bh/bl, etc, as sub-parts of the above, except ax,
> bx, etc, is for 16 bits only, but ah, al, bh, bl are still a
> accessible in 32 bits mode - I don't know if it's still the case in 64
> bits mode.
Your
System.Machine_Code.Asm
(Template => "int $0x80",
Outputs => Integer'Asm_Output ("=a", Result),
Inputs =>
(Positive'Asm_Input ("a", Number),
Natural'Asm_Input ("b", Handle),
System.Address'Asm_Input ("c", Address),
Natural'Asm_Input ("d", Size)),
Volatile => True);
translated to
movl %ecx, %edx
movl %edi, %eax
movl %esi, %ebx
movq %r8, %rcx
# 14 "library.adb" 1
int $0x80
but I think I really don't want to learn Intel assembler, lots of other
good things to do.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Erroneous code generation from GNAT or GCC?
2013-04-30 19:06 ` Simon Wright
2013-04-30 21:28 ` Yannick Duchêne (Hibou57)
@ 2013-05-01 18:19 ` J-P. Rosen
1 sibling, 0 replies; 19+ messages in thread
From: J-P. Rosen @ 2013-05-01 18:19 UTC (permalink / raw)
Le 30/04/2013 21:06, Simon Wright a écrit :
> The whole thing is bizarre: code statements are written using the form
> of a qualified expression though clearly not a qualified expression
> since it can't be assigned anywhere!
Ada 83 had a requirement to allow inclusion of machine code. There was
therefore a need to have a syntactic form that would fit every possible
machine code. It made sense to represent a machine instruction as a kind
of record, with fields like op-code, registers, address... Specifying
code statements as aggregates provided the necessary flexibility without
inventing a new syntactic form.
--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
Tel: +33 1 45 29 21 52, Fax: +33 1 45 29 25 00
http://www.adalog.fr
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2013-05-01 18:19 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-04-27 21:08 GNAT not generating any code for sub‑program: known bug? Yannick Duchêne (Hibou57)
2013-04-27 22:22 ` Yannick Duchêne (Hibou57)
2013-04-27 23:48 ` Yannick Duchêne (Hibou57)
2013-04-28 7:14 ` Simon Wright
2013-04-28 17:52 ` Yannick Duchêne (Hibou57)
2013-04-28 19:27 ` Yannick Duchêne (Hibou57)
2013-04-28 20:46 ` Simon Wright
2013-04-28 20:43 ` Simon Wright
2013-04-28 22:35 ` Erroneous code generation from GNAT or GCC? Yannick Duchêne (Hibou57)
2013-04-28 22:49 ` Yannick Duchêne (Hibou57)
2013-04-28 23:52 ` Yannick Duchêne (Hibou57)
2013-04-29 1:35 ` Yannick Duchêne (Hibou57)
2013-04-30 0:48 ` Yannick Duchêne (Hibou57)
2013-04-30 6:40 ` Simon Wright
2013-04-30 17:04 ` Yannick Duchêne (Hibou57)
2013-04-30 19:06 ` Simon Wright
2013-04-30 21:28 ` Yannick Duchêne (Hibou57)
2013-04-30 22:22 ` Simon Wright
2013-05-01 18:19 ` J-P. Rosen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox