* 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 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
* 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
* 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