[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 anlauf at gcc dot gnu.org changed: What|Removed |Added Status|ASSIGNED|RESOLVED Target Milestone|--- |14.0 Resolution|--- |FIXED --- Comment #44 from anlauf at gcc dot gnu.org --- Fixed for gcc-14.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #43 from CVS Commits --- The master branch has been updated by Harald Anlauf : https://gcc.gnu.org/g:9ade70bb86c8744f4416a48bb69cf4705f00905a commit r14-3254-g9ade70bb86c8744f4416a48bb69cf4705f00905a Author: Harald Anlauf Date: Wed Aug 16 22:00:49 2023 +0200 Fortran: fix memleak for character,value dummy of bind(c) procedure [PR110360] Testcase gfortran.dg/bind_c_usage_13.f03 exhibited a memleak in the frontend occuring when passing a character literal to a character,value dummy of a bind(c) procedure, due to a missing cleanup in the conversion of the actual argument expression. Reduced testcase: program p interface subroutine val_c (c) bind(c) use iso_c_binding, only: c_char character(len=1,kind=c_char), value :: c end subroutine val_c end interface call val_c ("A") end gcc/fortran/ChangeLog: PR fortran/110360 * trans-expr.cc (conv_scalar_char_value): Use gfc_replace_expr to avoid leaking replaced gfc_expr.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #42 from Mikael Morin --- (In reply to anlauf from comment #41) > (In reply to Mikael Morin from comment #40) > > Harald, I have just closed the followup PR110419. > > I think this PR can be closed as well, or is there something left to be > > done? > > It is pretty much done. > > There is a minor memleak for the bind(c) case left that can be seen for > testcase gfortran.dg/bind_c_usage_13.f03 or the reduced version: > > program p > interface > subroutine val_c (c) bind(c) >use iso_c_binding, only: c_char >character(len=1,kind=c_char), value :: c > end subroutine val_c > end interface > call val_c ("A") > end > > The leak is plugged by the first part of the patch attached to comment#37: > > diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc > index 52cd88f5b00..ee3cd47cf91 100644 > --- a/gcc/fortran/trans-expr.cc > +++ b/gcc/fortran/trans-expr.cc > @@ -4044,8 +4044,9 @@ conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, > gfc_expr **expr) >gfc_typespec ts; >gfc_clear_ts (); > > - *expr = gfc_get_int_expr (gfc_default_character_kind, NULL, > - (*expr)->value.character.string[0]); > + gfc_expr *tmp = gfc_get_int_expr (gfc_default_character_kind, NULL, > + (*expr)->value.character.string[0]); > + gfc_replace_expr (*expr, tmp); > } >else if (se != NULL && (*expr)->expr_type == EXPR_VARIABLE) > { > > Shall we commit this one? Sure, go ahead.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #41 from anlauf at gcc dot gnu.org --- (In reply to Mikael Morin from comment #40) > Harald, I have just closed the followup PR110419. > I think this PR can be closed as well, or is there something left to be done? It is pretty much done. There is a minor memleak for the bind(c) case left that can be seen for testcase gfortran.dg/bind_c_usage_13.f03 or the reduced version: program p interface subroutine val_c (c) bind(c) use iso_c_binding, only: c_char character(len=1,kind=c_char), value :: c end subroutine val_c end interface call val_c ("A") end The leak is plugged by the first part of the patch attached to comment#37: diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc index 52cd88f5b00..ee3cd47cf91 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -4044,8 +4044,9 @@ conv_scalar_char_value (gfc_symbol *sym, gfc_se *se, gfc_expr **expr) gfc_typespec ts; gfc_clear_ts (); - *expr = gfc_get_int_expr (gfc_default_character_kind, NULL, - (*expr)->value.character.string[0]); + gfc_expr *tmp = gfc_get_int_expr (gfc_default_character_kind, NULL, + (*expr)->value.character.string[0]); + gfc_replace_expr (*expr, tmp); } else if (se != NULL && (*expr)->expr_type == EXPR_VARIABLE) { Shall we commit this one?
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #40 from Mikael Morin --- Harald, I have just closed the followup PR110419. I think this PR can be closed as well, or is there something left to be done?
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #39 from CVS Commits --- The master branch has been updated by Mikael Morin : https://gcc.gnu.org/g:564b637f4a32883cbf3c3019d3cfcf0b0aec9b82 commit r14-3207-g564b637f4a32883cbf3c3019d3cfcf0b0aec9b82 Author: Mikael Morin Date: Mon Aug 14 21:51:54 2023 +0200 fortran: Fix length one character dummy arg type [PR110419] Revision r14-2171-g8736d6b14a4dfdfb58c80ccd398981b0fb5d00aa changed the argument passing convention for length 1 value dummy arguments to pass just the single character by value. However, the procedure declarations weren't updated to reflect the change in the argument types. This change does the missing argument type update. The change of argument types generated an internal error in gfc_conv_string_parameter with value_9.f90. Indeed, that function is not prepared for bare character type, so it is updated as well. The condition guarding the single character argument passing code is loosened to not exclude non-interoperable kind (this fixes a regression with c_char_tests_2.f03). Finally, the constant string argument passing code is updated as well to extract the single char and pass it instead of passing it as a length one string. As the code taking care of non-constant arguments was already doing this, the condition guarding it is just removed. With these changes, value_9.f90 passes on 32 bits big-endian powerpc. PR fortran/110360 PR fortran/110419 gcc/fortran/ChangeLog: * trans-types.cc (gfc_sym_type): Use a bare character type for length one value character dummy arguments. * trans-expr.cc (gfc_conv_string_parameter): Handle single character case. (gfc_conv_procedure_call): Don't exclude interoperable kinds from single character handling. For single character dummy arguments, extend the existing handling of non-constant expressions to constant expressions. gcc/testsuite/ChangeLog: * gfortran.dg/bind_c_usage_13.f03: Update tree dump patterns.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 David Edelsohn changed: What|Removed |Added CC||tkoenig at gcc dot gnu.org --- Comment #38 from David Edelsohn --- As mentioned by Mikael in PR110419, GFORTRAN calling convention has a hole. The problem on PowerPC Big Endian is that sometimes GFORTRAN passes a character as a character and sometimes it passes a character as a STRING of length 1 passed by value. On Little Endian systems, the single value happens to end up in the same location in the register. On Big Endian systems, the values are at opposite ends of the register. Or to put it another way, the GFORTRAN internal "type" of CHARACTER as represented by/to GCC type system is inconsistent. GFORTRAN is breaking the GCC type system, which causes the parameter to be represented differently in the register.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #37 from anlauf at gcc dot gnu.org --- Created attachment 55661 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55661=edit Tentative patch for the bind(c) case The attached lightly-tested patch tries to fix (at least at the technical level) the issues exhibited in comment#33 for the calls to val_c. On x86 (LE) it fixes the 3rd case by dereferencing the temporary. For BE platforms it apparently used to work for the character literal only because it was internally converted to an integer(kind=1), so the patch now tries to achieve that for the other two cases. I am not too happy about the actual patch, because I do not yet see how to cleanly adapt it to the non-bind(c) case (val). But understanding the val_c case might be key to proceeding. BTW: the patch fixes a minor memleak in conv_scalar_char_value.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #36 from David Edelsohn --- I don't know enough FORTRAN90 to instruct the compiler to use an external function as if it were native. EXTERNAL :: MYFUNC changes the calling convention. But if I manually change the assembly code so that "val" calls a C function a print the values #include void val_0 (int x, int y) { printf ("char(0x%x = %d) = %c 0 0 %c (LEN = %d)\n", x, x, (char) (x>>24), (char) (x), y); } it produces the following output (32 bit): char(0x4100 = 1090519040) = A 0 0 (LEN = 1) char(0x41 = 65) = 0 0 A (LEN = 1) char(0x41 = 65) = 0 0 A (LEN = 1) for call val ("A") call val (c) call val (char(a)) to demonstrate exactly what I see on big endian POWER.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #35 from anlauf at gcc dot gnu.org --- (In reply to David Edelsohn from comment #34) > AIX POWER BE output: > > $ ./a.out > val(fortran): 65 A > val(fortran):0 > val(fortran):0 > val_c: char(65)='A' > val_c: char(65)='A' > val_c: char(804399656)='(' Ah, that is helpful. The handling of literals is thus fine and can be taken as reference.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #34 from David Edelsohn --- AIX POWER BE output: $ ./a.out val(fortran): 65 A val(fortran):0 val(fortran):0 val_c: char(65)='A' val_c: char(65)='A' val_c: char(804399656)='('
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #33 from anlauf at gcc dot gnu.org --- (In reply to David Edelsohn from comment #32) > I'm leaning back to big-endian vs little-endian, and not a struct issue. A > little-endian STRING will start at the lowest address and a big-endian > STRING will start at the highest address. OK. I've thought a little and came to the following testcase that might help to understand what we have right now (a mess). It tests 6 = 3 x 2 variations, namely passing a literal constant, a variable, and a function result via a temporary to either a fortran subroutine or a C function: % cat value_10_c.c #include void val_c (char c) { printf ("val_c: char(%d)='%c'\n", (int) c, c); } % cat value_10_f.f90 program p implicit none interface subroutine val_c (c) bind(c) use iso_c_binding, only: c_char character(c_char), value :: c end subroutine val_c end interface integer :: a = 65 character :: c = char(65) call val ("A") call val (c) call val (char(a)) call val_c ("A") call val_c (c) call val_c (char(a)) contains subroutine val (c) character(kind=1), value :: c print *, "val(fortran): ", iachar (c), c end end With the Intel compiler on x86 I get what I expect: val(fortran): 65 A val(fortran): 65 A val(fortran): 65 A val_c: char(65)='A' val_c: char(65)='A' val_c: char(65)='A' With current 14-trunk on x86 I get: % gfc-14 value_10_f.f90 value_10_c.c && ./a.out val(fortran): 65 A val(fortran): 65 A val(fortran): 65 A val_c: char(65)='A' val_c: char(65)='A' val_c: char(-122)='�' The last line of output is junk, which is understood by looking at the dump, as in that case we wrongly pass a reference instead of the value. The C interface part hasn't been touched by the patches in the current PR and obviously also needs a fix. So the next thing is to understand how the C interface works and get it right and consistent (both for LE and BE), and with that knowledge find out how the Fortran part might be.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #32 from David Edelsohn --- i think that I see part of the difference. The 005t.original dump shows (intermingled with sources) ! call val ("B","B") val (&"B"[1]{lb: 1 sz: 1}, "B", 1, 1); ! call val ("A",char(65)) val (&"A"[1]{lb: 1 sz: 1}, "A", 1, 1); ! call val ("A",char(a)) { character(kind=1) char.6; char.6 = (character(kind=1)) a; val (&"A"[1]{lb: 1 sz: 1}, char.6, 1, 1); } ! call val ("A",mychar(65)) { static integer(kind=4) C.2654 = 65; character(kind=1) str.7[1]; mychar ((character(kind=1)[1:1] *) , 1, ); val (&"A"[1]{lb: 1 sz: 1}, str.7[0], 1, 1); } ! call val ("A",mychar(a)) { character(kind=1) str.8[1]; mychar ((character(kind=1)[1:1] *) , 1, ); val (&"A"[1]{lb: 1 sz: 1}, str.8[0], 1, 1); } char(65) is folded by the FORTRAN front-end to "A", so it is passed in the same manner that elicits the shift. The rest of the calls pass 65. The string is left-shifted and the number is right-shifted. GFORTRAN seems to assume that passing a STRING by value will be padded the same as a number or character, which isn't accurate. I'm leaning back to big-endian vs little-endian, and not a struct issue. A little-endian STRING will start at the lowest address and a big-endian STRING will start at the highest address.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #31 from David Edelsohn --- Yes, &"B"[1], is not shifted because it is a reference. The important different is "B" is passed left-shifted, but 65 is passed right-shifted. call val ("B","B") OK call val ("A",char(65)) OK call val ("A",char(a)) WRONG call val ("A",mychar(65)) WRONG call val ("A",mychar(a))WRONG call val ("1",c) call val ("1",(c)) subroutine val (x, c) character(kind=1), intent(in) :: x ! control: pass by reference character(kind=1), value :: c print *, "by value(kind=1): ", x print *, "by value(kind=1): ", c end character function mychar (i) integer, intent(in) :: i mychar = char (i) end I'm confused that char(65) produces correct code, while char(a), mychar(65) and mychar(a) all produce incorrect code, especially char(65) versus char(a), where a=65. If I check in mychar, it receives the value 65 and char(65) produces 'A'. I don't understand why GFORTRAN believes that char(65) should produce a left-shifted value, and "A" passed by reference is shifted in memory to compare correctly.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #30 from anlauf at gcc dot gnu.org --- (In reply to David Edelsohn from comment #29) > Maybe something about the way that GFORTRAN is passing the string by value. > 257.optimized shows > > val (&"B"[1]{lb: 1 sz: 1}, "B", 1, 1); > val (&"A"[1]{lb: 1 sz: 1}, "A", 1, 1); > val (&"A"[1]{lb: 1 sz: 1}, 65, 1, 1); > val (&"A"[1]{lb: 1 sz: 1}, 65, 1, 1); > val (&"A"[1]{lb: 1 sz: 1}, 65, 1, 1); > _37 = c[1]{lb: 1 sz: 1}; > val (&"1"[1]{lb: 1 sz: 1}, _37, 1, 1); > _38 = c[1]{lb: 1 sz: 1}; > val (&"1"[1]{lb: 1 sz: 1}, _38, 1, 1); > > &"B"[1] is not shifted. 65 is not shifted. "B" is shifted. > > GFORTRAN is passing the value in different ways that trigger different parts > of the target ABI. It seems to be assuming that those different parts of > the ABI and forms of parameter passing will produce the same results in > terms of padding, but that is not guaranteed. Is it possible that a VIEW_CONVERT_EXPR is needed for handling this, and that this is forgotten or wrong for one of those variants? There exists native_encode_expr, which appears to handle constant exprs, and which might pass "B" to native_encode_string, and we need to emulate this conversion for non-constant char expressions. (Just guessing.) That &"B"[1] is not shifted is not surprising: we are passing this argument by reference, not value.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #29 from David Edelsohn --- I don't know if this is a BE issue or a struct issue. AIX doesn't pass characters in structs normally. Is there any other debugging output from the GFORTRAN other than parse? -fdump-lang-all doesn't seem to produce any additional output. I'm trying to guess / brainstorm about why GCC sometimes would shift the char value and other times would not. Maybe something about the way that GFORTRAN is passing the string by value. 257.optimized shows val (&"B"[1]{lb: 1 sz: 1}, "B", 1, 1); val (&"A"[1]{lb: 1 sz: 1}, "A", 1, 1); val (&"A"[1]{lb: 1 sz: 1}, 65, 1, 1); val (&"A"[1]{lb: 1 sz: 1}, 65, 1, 1); val (&"A"[1]{lb: 1 sz: 1}, 65, 1, 1); _37 = c[1]{lb: 1 sz: 1}; val (&"1"[1]{lb: 1 sz: 1}, _37, 1, 1); _38 = c[1]{lb: 1 sz: 1}; val (&"1"[1]{lb: 1 sz: 1}, _38, 1, 1); &"B"[1] is not shifted. 65 is not shifted. "B" is shifted. GFORTRAN is passing the value in different ways that trigger different parts of the target ABI. It seems to be assuming that those different parts of the ABI and forms of parameter passing will produce the same results in terms of padding, but that is not guaranteed.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #28 from anlauf at gcc dot gnu.org --- (In reply to David Edelsohn from comment #27) > If GFORTRAN assumes that a scalar value and a value in a struct are passed > in registers with the same padding, that is not a valid, general assumption. I do understand that this makes a difference for BE. But what does this mean in this context? Does a constant literal character as in the testcase get padded because AIX wants to pass it in a struct? Is this done (in)transparently in gcc? Where and how? And do we need for this reason to explicitly convert a character temporary as in { character(kind=1) char.6; char.6 = (character(kind=1)) a; val (&"A"[1]{lb: 1 sz: 1}, char.6, 1, 1); } to a struct before calling val? What is the right way to do this is a platform-independent way? I do not see anything wrong in the tree-dump, maybe due to my lack of experience. Maybe the tree-dump is just not expressive enough here.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #27 from David Edelsohn --- GFORTRAN parse output describes the characters as follow symtree: 'char'|| symbol: 'char' type spec : (UNKNOWN 0) attributes: (PROCEDURE INTRINSIC-PROC FUNCTION ARRAY-OUTER-DEPENDENCY) result: char symtree: 'mychar' || symbol: 'mychar' type spec : (CHARACTER 1 1) attributes: (PROCEDURE INTERNAL-PROC FUNCTION IMPLICIT-PURE CONTAINED) result: mychar Formal arglist: i CALL val (('B') ('B')) CALL val (('A') ('A')) CALL val (('A') (__char_1_i4[[((p:a) ((arg not-present)))]])) CALL val (('A') (mychar[[((65))]])) CALL val (('A') (mychar[[((p:a))]])) 258r.expand shows the shift of the function parameter: (insn 114 113 115 11 (set (reg:SI 4 4) (ashift:SI (reg:SI 4 4) (const_int 24 [0x18]))) "value_9.f90":23:21 -1 (nil)) (insn 115 114 116 11 (set (reg:SI 3 3) (reg:SI 185)) "value_9.f90":23:21 -1 (nil)) (call_insn 116 115 117 11 (parallel [ (call (mem:SI (symbol_ref:SI ("val.4[DS]") [flags 0x3] ) [0 val S4 A8]) (const_int 32 [0x20])) (use (const_int 0 [0])) (clobber (reg:SI 96 lr)) ]) "value_9.f90":23:21 -1 (expr_list:REG_EH_REGION (const_int 0 [0]) (nil)) (expr_list (use (reg:SI 2 2)) (expr_list:SI (use (reg:SI 3 3)) (expr_list:QI (use (reg:SI 4 4)) (expr_list:SI (use (reg:SI 5 5)) (expr_list:SI (use (reg:SI 6 6)) (nil))) The original tree is static void val (character(kind=1)[1:1] & restrict, character(kind=1)[1:1], integer(kind=4), integer(kind=4)); static integer(kind=4) a = 65; static character(kind=1) c[1:1] = "1"; static character(kind=4) c4[1:1] = "\x00\x00\x004"; val (&"B"[1]{lb: 1 sz: 1}, "B", 1, 1); val (&"A"[1]{lb: 1 sz: 1}, "A", 1, 1); { character(kind=1) char.6; char.6 = (character(kind=1)) a; val (&"A"[1]{lb: 1 sz: 1}, char.6, 1, 1); } { static integer(kind=4) C.2654 = 65; character(kind=1) str.7[1]; mychar ((character(kind=1)[1:1] *) , 1, ); val (&"A"[1]{lb: 1 sz: 1}, str.7[0], 1, 1); } { character(kind=1) str.8[1]; mychar ((character(kind=1)[1:1] *) , 1, ); val (&"A"[1]{lb: 1 sz: 1}, str.8[0], 1, 1); } val (&"1"[1]{lb: 1 sz: 1}, c[1]{lb: 1 sz: 1}, 1, 1); val (&"1"[1]{lb: 1 sz: 1}, c[1]{lb: 1 sz: 1}, 1, 1); The issue may not be endianness but assumptions about struct padding. I don't know exactly how GFORTRAN represents CHARACTER. I can elicit the same behavior in C if I embed a "char" in a struct like struct mychar { char c1; }; struct mychar mc; mc.c1 = 'A'; On AIX, structs are left padded. A char passed in a 32 bit register is - |x|x|x|A| - but a char passed by value in a struct is - |A|x|x|x| - If GFORTRAN assumes that a scalar value and a value in a struct are passed in registers with the same padding, that is not a valid, general assumption.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #26 from anlauf at gcc dot gnu.org --- (In reply to David Edelsohn from comment #25) > The problem on big endian systems is that GFortran is passing the character > with the wrong padding. [...] > GFortran is not taking account of endianness for the layout of values in > memory compared to constants loaded into registers. This isn't an ABI issue > of the target, this is a memory layout and register layout issue of GFortran. Frankly speaking, this is a place where I have zero knowledge. > Let me know if you need more information or tests. There is pr110419 which tracks the testsuite regression on BE systems. Mikael added some info there. Maybe you can have a look, too.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 David Edelsohn changed: What|Removed |Added CC||dje at gcc dot gnu.org --- Comment #25 from David Edelsohn --- The problem on big endian systems is that GFortran is passing the character with the wrong padding. I have changed val() to print both c and x, and not halt. subroutine val (x, c) character(kind=1), intent(in) :: x ! control: pass by reference character(kind=1), value :: c print *, "by value(kind=1): ", x print *, "by value(kind=1): ", c !if (c /= x) stop 1 c = "*" if (c /= "*") stop 2 end The output is: by value(kind=1): B by value(kind=1): B by value(kind=1): A by value(kind=1): A by value(kind=1): A by value(kind=1):<- c by value(kind=1): A by value(kind=1):<- c by value(kind=1): A by value(kind=1):<- c by value(kind=1): 1 by value(kind=1):<- c by value(kind=1): 1 by value(kind=1):<- c The assembly language for the first few calls is # call val ("B","B") lwz 31,LC..5(2) LOAD ADDRESS of x mr 3,31 COPY address to first parameter li 6,1 li 5,1 lbzu 4,148(3)LOAD BYTE of c as second parameter slwi 4,4,24 SHIFT c 24 bits bl .val.4 # call val ("A",char(65)) mr 30,31 COPY ADDRESS of x li 6,1 li 5,1 lbzu 4,152(30) LOAD BYTE of c as second parameter slwi 4,4,24 SHIFT c 24 bits mr 3,30 COPY address of first parameter bl .val.4 # call val ("A",char(a)) li 6,1 li 5,1 li 4,65 <- c NOT SHIFTED mr 3,30 <- x bl .val.4 # call val ("A",mychar(65)) li 6,1 li 5,1 li 4,65 <- c NOT SHIFTED mr 3,30 <- x bl .val.4 # call val ("A",mychar(a)) li 6,1 li 5,1 li 4,65 <- c NOT SHIFTED mr 3,30 <- x bl .val.4 GFortran is not taking account of endianness for the layout of values in memory compared to constants loaded into registers. This isn't an ABI issue of the target, this is a memory layout and register layout issue of GFortran. Let me know if you need more information or tests.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #24 from CVS Commits --- The master branch has been updated by Harald Anlauf : https://gcc.gnu.org/g:8736d6b14a4dfdfb58c80ccd398981b0fb5d00aa commit r14-2171-g8736d6b14a4dfdfb58c80ccd398981b0fb5d00aa Author: Harald Anlauf Date: Wed Jun 28 22:16:18 2023 +0200 Fortran: ABI for scalar CHARACTER(LEN=1),VALUE dummy argument [PR110360] gcc/fortran/ChangeLog: PR fortran/110360 * trans-expr.cc (gfc_conv_procedure_call): For non-constant string argument passed to CHARACTER(LEN=1),VALUE dummy, ensure proper dereferencing and truncation of string to length 1. gcc/testsuite/ChangeLog: PR fortran/110360 * gfortran.dg/value_9.f90: Add tests for intermediate regression.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #23 from Mikael Morin --- (In reply to anlauf from comment #22) > Created attachment 55418 [details] > Slighty revised version of 3rd patch > > I've looked at gfc_conv_string_parameter, which I was not aware of. > This can be used for a more readable patch. > Looks good. > It appears one could even use the revised part for constant arguments, too. > However, this changes the tree-dump for gfortran.dg/bind_c_usage_13.f03 > slightly in two places, implying the need for an adjustment of the pattern. > As I am not entirely sure whether the result of that change is correct, > I refrained from using that version. > OK, let's play it safe. > (The partial output from Power BE appears to suggest that constant argument > is still right.) > > Mikael: do you want to test on Power, or shall I proceed? Sorry, still can't login at the moment. Reading the account creation message again, I may need to wait "a few days". So please proceed.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #22 from anlauf at gcc dot gnu.org --- Created attachment 55418 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55418=edit Slighty revised version of 3rd patch I've looked at gfc_conv_string_parameter, which I was not aware of. This can be used for a more readable patch. It appears one could even use the revised part for constant arguments, too. However, this changes the tree-dump for gfortran.dg/bind_c_usage_13.f03 slightly in two places, implying the need for an adjustment of the pattern. As I am not entirely sure whether the result of that change is correct, I refrained from using that version. (The partial output from Power BE appears to suggest that constant argument is still right.) Mikael: do you want to test on Power, or shall I proceed? I will extend the testcase to cover the failures from comment#17.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #21 from Mikael Morin --- (In reply to anlauf from comment #20) > Created attachment 55407 [details] > Third patch set > > Here's a lightly tested 3rd patch that tries to handle the chaos I created... > > Can you have a look? This looks good. There is gfc_conv_string_parameter that seems to be used often with gfc_string_to_single_character and that you could use to generate the address, but it is basically equivalent to your solution, I think. .
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #20 from anlauf at gcc dot gnu.org --- Created attachment 55407 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55407=edit Third patch set Here's a lightly tested 3rd patch that tries to handle the chaos I created... Can you have a look?
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #19 from Mikael Morin --- (In reply to Mikael Morin from comment #18) > There is the "obvious" problem that gfc_build_wide_string_const creates a > bare array, whereas gfc_string_to_single_character expects a pointer > wrapping around it. > I was wrong saying above that "A" is a pointer. It is converted to a > pointer if passed as argument in C, but the middle-end clearly distinguishes > between arrays and pointers, and "A" is an array, not a pointer to an array. Sorry, you can scratch that, the failing case is the NON-constant case.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #18 from Mikael Morin --- (In reply to Mikael Morin from comment #15) > I have asked for an account on the compile farm (see > https://gcc.gnu.org/wiki/CompileFarm) to have access to a powerpc machine. It was pretty fast to get the green light, but then the machines have to see the change of configuration to accept my logging in. It's not working yet. (In reply to anlauf from comment #17) > Running under gdb seems to tell that gfc_string_to_single_character returns > a NULL_TREE for yet unknown reason. There is the "obvious" problem that gfc_build_wide_string_const creates a bare array, whereas gfc_string_to_single_character expects a pointer wrapping around it. I was wrong saying above that "A" is a pointer. It is converted to a pointer if passed as argument in C, but the middle-end clearly distinguishes between arrays and pointers, and "A" is an array, not a pointer to an array.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #17 from anlauf at gcc dot gnu.org --- It appears that gfc_string_to_single_character does not fulfill my expectation. The following ICEs now: subroutine s implicit none interface subroutine ref (c) character:: c end subroutine val (c) character, value :: c end end interface character(len=1) :: c = "A" character(len=10) :: d = "D" call ref (c) call ref (d) call ref (c // d) call val (c // d) ! OK call val (c) ! bad (ok for 13-branch) call val (d) ! bad end The tree-dump shows that 13-branch generates correct code only for the indicated call val (c), while the other two are wrong. Current 14-branch is correct for the case with the temporary e.g. for the string concatenation, and the other two are a complete fail... Running under gdb seems to tell that gfc_string_to_single_character returns a NULL_TREE for yet unknown reason.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #16 from anlauf at gcc dot gnu.org --- In the meantime Bill opened pr110419 and posted: spawn [open ...] by value(kind=1): B by value(kind=1): A Program received signal SIGSEGV: Segmentation fault - invalid memory reference. Backtrace for this error: #0 0xf7ba03f3 in ??? #1 0x1d34 in val at /home/seurer/gcc/git/gcc-test/gcc/testsuite/gfortran.dg/value_9.f90:47 #2 0x19db in p at /home/seurer/gcc/git/gcc-test/gcc/testsuite/gfortran.dg/value_9.f90:20 #3 0x19db in main at /home/seurer/gcc/git/gcc-test/gcc/testsuite/gfortran.dg/value_9.f90:45 FAIL: gfortran.dg/value_9.f90 -O3 -g execution test Line 20 corresponds to call val ("A",char(65)) which means that there should be a temporary holding the result of char(65) which should be passed by value.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #15 from Mikael Morin --- (In reply to anlauf from comment #14)> > Let's hope that somebody with access to such a system can run the testcase > manually and append the output to this PR. I have asked for an account on the compile farm (see https://gcc.gnu.org/wiki/CompileFarm) to have access to a powerpc machine. You may want to do the same, can prove handy sometimes. I'll investigate tomorrow and post the missing information here.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #14 from anlauf at gcc dot gnu.org --- After r14-2064, gcc-testresults shows the following for big-endian Power platforms: Running target unix/-m32 FAIL: gfortran.dg/value_9.f90 -O0 execution test FAIL: gfortran.dg/value_9.f90 -O1 execution test FAIL: gfortran.dg/value_9.f90 -O2 execution test FAIL: gfortran.dg/value_9.f90 -O3 -fomit-frame-pointer -funroll-loops -fpeel-loops -ftracer -finline-functions execution test FAIL: gfortran.dg/value_9.f90 -O3 -g execution test FAIL: gfortran.dg/value_9.f90 -Os execution test No failure for Running target unix/-m64 Let's hope that somebody with access to such a system can run the testcase manually and append the output to this PR.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #13 from CVS Commits --- The master branch has been updated by Harald Anlauf : https://gcc.gnu.org/g:3f97d10aa1ff5984d6fd657f246d3f251b254ff1 commit r14-2064-g3f97d10aa1ff5984d6fd657f246d3f251b254ff1 Author: Harald Anlauf Date: Sat Jun 24 20:36:53 2023 +0200 Fortran: ABI for scalar CHARACTER(LEN=1),VALUE dummy argument [PR110360] gcc/fortran/ChangeLog: PR fortran/110360 * trans-expr.cc (gfc_conv_procedure_call): Truncate constant string argument of length > 1 passed to scalar CHARACTER(1),VALUE dummy.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #12 from anlauf at gcc dot gnu.org --- (In reply to anlauf from comment #11) > Created attachment 55393 [details] > Patch to truncate string argument longer than 1 > > This truncates the string to length 1 and appears to work on x86 / -m32 . > Would be interesting to get feedback on big-endian platforms. As this works here, cross-checked with valgrind, and not feedback so far, I'll push this update and watch the testers.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #11 from anlauf at gcc dot gnu.org --- Created attachment 55393 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55393=edit Patch to truncate string argument longer than 1 This truncates the string to length 1 and appears to work on x86 / -m32 . Would be interesting to get feedback on big-endian platforms.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #10 from anlauf at gcc dot gnu.org --- Hmm, the testers show failures for the new testcase for the following cases: x86 / -m32 / -O1 and higher, Power9 BE, all optimization levels. I can reproduce the case of x86 / -m32 / -O1 for the following reduced test: program p implicit none call val4 (4_"A" , 4_"A" ) ! OK call val4 (4_"V**", 4_"V" ) ! OK call val4 (4_"V**", 4_"V//") ! fail contains subroutine val4 (x, c) character(kind=4), intent(in) :: x ! control: pass by reference character(kind=4), value :: c print *, "by value(kind=4): ", c, " ", x if (c /= x) stop 3 c = 4_"#" if (c /= 4_"#") stop 4 end end This is a pre-existing issue for constant character argument (len>1) and can be reproduced with e.g. gcc-13. It does not seem to occur with -m64. Maybe we are giving the middle end a bad representation of the argument.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #9 from CVS Commits --- The master branch has been updated by Harald Anlauf : https://gcc.gnu.org/g:d130ae8499e0c615e1636258d6901372316dfd93 commit r14-2050-gd130ae8499e0c615e1636258d6901372316dfd93 Author: Harald Anlauf Date: Thu Jun 22 22:07:41 2023 +0200 Fortran: ABI for scalar CHARACTER(LEN=1),VALUE dummy argument [PR110360] gcc/fortran/ChangeLog: PR fortran/110360 * trans-expr.cc (gfc_conv_procedure_call): Pass actual argument to scalar CHARACTER(1),VALUE dummy argument by value. gcc/testsuite/ChangeLog: PR fortran/110360 * gfortran.dg/value_9.f90: New test.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #8 from Mikael Morin --- (In reply to anlauf from comment #6) > (In reply to Mikael Morin from comment #4) > > > Looks good. > > I would suggest to create an overload that avoids duplicating the > > build_int_cst (integer_type_node, 1) in several places. > > Shouldn't it be build_int_cst (gfc_charlen_type_node, 1) by the way? > > That's true. I copied that from another snippet. > > It is not clear to me what you mean by "overload" here. Do you want to > elaborate? > Yes, sorry. It is a sibling function to the function gfc_string_to_single_character. It would have the same name but wouldn't have the len argument (it would create it with value build_int_cst (gfc_charlen_type_node, 1)).
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #7 from anlauf at gcc dot gnu.org --- Submitted: https://gcc.gnu.org/pipermail/fortran/2023-June/059503.html
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #6 from anlauf at gcc dot gnu.org --- (In reply to Mikael Morin from comment #4) > (In reply to anlauf from comment #0) > > but the second line contains junk, as the tree-dump shows: > > > > static void val (character(kind=1)[1:1], integer(kind=8)); > > static integer(kind=4) a = 65; > > > > val ("A", 1); > > { > > character(kind=1) char.1; > > > > char.1 = (character(kind=1)) a; > > val (, 1); > > } > > > > Clearly, the second case is inconsistent with the ABI, see the prototype, > > and > > > Yes, but it's not worse than the first one: "A" is a pointer, not a value. > I would say that it is the middle-end that is inconsistent here. Hmm. Have a look at the following: subroutine s implicit none interface subroutine val (c) character, value :: c end end interface call val ("A") call val ("ABCDEF") end Dump-tree: val ("A", 1); val ("ABCDEF", 6); I am not good at reading assembler, but it appears that "ABCDEF" is awfully copied (pushed?) on the stack. --> missed optimization. (I've played a little but didn't find a quick, working solution for the truncation, only some awful lengthy code. Will add a TODO in the patch.) Changing the interface to use "character, intent(in) :: c" produces what I assume is the ordinary by-reference. > Looks good. > I would suggest to create an overload that avoids duplicating the > build_int_cst (integer_type_node, 1) in several places. > Shouldn't it be build_int_cst (gfc_charlen_type_node, 1) by the way? That's true. I copied that from another snippet. It is not clear to me what you mean by "overload" here. Do you want to elaborate? I've also extended the testcase to sample most things that came to my mind, except for the [character, value, bind(c)] case. We'd better track this elsewhere.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #5 from Mikael Morin --- This is out of the scope of this PR, but in the [character, value, bind(c)] case, only constant values and variables are supported?
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 Mikael Morin changed: What|Removed |Added CC||mikael at gcc dot gnu.org --- Comment #4 from Mikael Morin --- (In reply to anlauf from comment #0) > but the second line contains junk, as the tree-dump shows: > > static void val (character(kind=1)[1:1], integer(kind=8)); > static integer(kind=4) a = 65; > > val ("A", 1); > { > character(kind=1) char.1; > > char.1 = (character(kind=1)) a; > val (, 1); > } > > Clearly, the second case is inconsistent with the ABI, see the prototype, and > Yes, but it's not worse than the first one: "A" is a pointer, not a value. I would say that it is the middle-end that is inconsistent here. (In reply to anlauf from comment #3) > Created attachment 55381 [details] > Revised patch > > This patch actually regtests OK. The previous one failed on one of the > c_char_tests. Looks good. I would suggest to create an overload that avoids duplicating the build_int_cst (integer_type_node, 1) in several places. Shouldn't it be build_int_cst (gfc_charlen_type_node, 1) by the way?
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 anlauf at gcc dot gnu.org changed: What|Removed |Added Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2023-06-21 Assignee|unassigned at gcc dot gnu.org |anlauf at gcc dot gnu.org Ever confirmed|0 |1
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 anlauf at gcc dot gnu.org changed: What|Removed |Added Attachment #55380|0 |1 is obsolete|| --- Comment #3 from anlauf at gcc dot gnu.org --- Created attachment 55381 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55381=edit Revised patch This patch actually regtests OK. The previous one failed on one of the c_char_tests.
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #2 from anlauf at gcc dot gnu.org --- For reference: testcase, cross-checked with NAG 7.1: ! { dg-do run } ! PR fortran/110360 program p implicit none character, allocatable :: ca character, pointer :: cp character(kind=4), allocatable :: ca4 character(kind=4), pointer :: cp4 integer :: a = 65 allocate (ca, cp, ca4, cp4) ca = "c"; cp = "d" ca4 = 4_"c"; cp4 = 4_"d" call val ("A",char(65)) call val ("A",char(a)) call val4 (4_"A",char(65,kind=4)) call val4 (4_"A",char(a,kind=4)) call val (ca,ca) call val (cp,cp) call val4 (ca4,ca4) call val4 (cp4,cp4) deallocate (ca, cp, ca4, cp4) contains subroutine val (x, c) character(kind=1):: x character(kind=1), value :: c print *, "by value(kind=1): ", c if (x /= c) stop 1 end subroutine val4 (x, c) character(kind=4):: x character(kind=4), value :: c print *, "by value(kind=4): ", c if (x /= c) stop 2 end end
[Bug fortran/110360] ABI issue with character,value dummy argument
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110360 --- Comment #1 from anlauf at gcc dot gnu.org --- Created attachment 55380 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55380=edit Patch The attached patch fixes up the case of non-constant string expressions passed to CHARACTER,VALUE dummy arguments of constant length 1.