gcc for mvs
GCC 3.2.3 has been built for MVS 3.8, MVS/XA, OS/390, Z/OS and VM/CMS. You can find the modified source and binaries here: http://www.softlib.org/GCCMVS/gccmvs.html Only the C compiler has been ported. BFN. Paul.
i370 - block move needs 16 MiB limit
Hi. On the i370 port of GCC 3.2.3 (which can be run in 31-bit mode on z/OS), we have the below code to do a builtin_memcpy(). But as per description in i370.md, it is restricted to moving LESS than 16 MiB. If we have 16 MiB or more, I am happy to just call the memcpy() function. I have tried various incantations to try to stop this code from being used when the block size is greater than or equal to 16 MiB, but I have not been successful. I was successful with putting in this code change: C:\devel\pdos\pdpclib>cvs diff -r 1.19 -r 1.20 string.h Index: string.h === RCS file: /cvsroot/pdos/pdos/pdpclib/string.h,v retrieving revision 1.19 retrieving revision 1.20 diff -r1.19 -r1.20 89,90c89,98 < #define memcpy(a,b,c) (__builtin_memcpy((a),(b),(c))) < #define memcmp(s1,s2,n) (__builtin_memcmp((s1),(s2),(n))) --- #define memcpy(s1,s2,n) ( \ (n >= 0x0100) ? \ ((memcpy)((s1),(s2),(n))) : \ (__builtin_memcpy((s1),(s2),(n))) \ ) #define memcmp(s1,s2,n) ( \ (n >= 0x0100) ? \ ((memcmp)((s1),(s2),(n))) : \ (__builtin_memcmp((s1),(s2),(n))) \ ) C:\devel\pdos\pdpclib> But I believe that is considered to be technically incorrect, because the "n" argument is evaluated more than once. Am I correct in believing that the code in builtins.c shouldn't be changed, because that is correct for all platforms, and that the required change needs to go in i370.md or some other i370-specific file? If so, can anyone tell me how to solve this problem? Note that compare has an identical issue - CLCL is like MVCL. Thanks. Paul. /* Expand a call to the memcpy builtin, with arguments in ARGLIST. Return 0 if we failed, the caller should emit a normal call, otherwise try to get the result in TARGET, if convenient (and in mode MODE if that's convenient). */ static rtx expand_builtin_memcpy (arglist, target, mode) tree arglist; rtx target; enum machine_mode mode; { ; ; movstrsi instruction pattern(s). ; block must be less than 16M (24 bits) in length (define_expand "movstrsi" [(set (match_operand:BLK 0 "general_operand" "") (match_operand:BLK 1 "general_operand" "")) (use (match_operand:SI 2 "general_operand" "")) (match_operand 3 "" "")] "" " { rtx op0, op1; op0 = XEXP (operands[0], 0); if (GET_CODE (op0) == REG || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG && GET_CODE (XEXP (op0, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op0, 1)) < 4096)) op0 = operands[0]; else op0 = replace_equiv_address (operands[0], copy_to_mode_reg (SImode, op0)); op1 = XEXP (operands[1], 0); if (GET_CODE (op1) == REG || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG && GET_CODE (XEXP (op1, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op1, 1)) < 4096)) op1 = operands[1]; else op1 = replace_equiv_address (operands[1], copy_to_mode_reg (SImode, op1)); if (GET_CODE (operands[2]) == CONST_INT && (unsigned) INTVAL (operands[2]) <= 256) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, op0, op1), gen_rtx_USE (VOIDmode, operands[2]; else { /* implementation provided by Richard Henderson */ rtx reg1 = gen_reg_rtx (DImode); rtx reg2 = gen_reg_rtx (DImode); rtx mem1 = operands[0]; rtx mem2 = operands[1]; rtx len = operands[2]; if (!CONSTANT_P (len)) len = force_reg (SImode, len); /* Load up the address+length pairs. */ emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), force_operand (XEXP (mem1, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), force_operand (XEXP (mem2, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); /* Copy! */ emit_insn (gen_movstrsi_1 (reg1, reg2)); } DONE; }") ; Move a block that is less than or equal to 256 bytes in length. (define_insn "" [(set (match_operand:BLK 0 "s_operand" "=S") (match_operand:BLK 1 "s_operand" "S")) (use (match_operand 2 "immediate_operand" "i"))] "((unsigned) INTVAL (operands[2]) <= 256)" "* { check_label_emit (); mvs_check_page (0, 6, 0); return \"MVC%O0(%c2,%R0),%1\"; }" [(set_attr "length" "6")] ) ; Move a block that is larger than 256 bytes in length. ; [(set (mem:BLK (subreg:SI (match_operand:DI 0 "register_operand" "+d") 0)) ;(mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0))) (define_insn "movstrsi_1" [(set (mem:BLK (match_operand:DI 0 "register_operand" "+d") ) (mem:BLK (match_operand:DI 1 "register_operand" "+d") )) (us
i370 - strange padding being generated for literals
Hi. On the i370 target of a slightly modified GCC 3.2.3, I am getting this strange padding: DC46X'00' I asked Dave Pitts about it, and he told me it is not related to the i370 machine definition and I should ask the group for advice instead. Note that one variable needs a padding of 46 and another variable needs a padding of 66, but for some reason only the "46" appears at all, and that appearance is completely redundant, and the code does not use it at all (which is why it causes no actual problem with the variable that needs 66 padding). Any insights? See code below. Thanks. Paul. void foo(void) { char buf[50] = "CDE"; char buf2[70] = "CDE"; bar(buf, buf2); return; } COPY PDPTOP CSECT * Program text area @@LC0EQU * DCC'CDE' DCX'0' DC46X'00' DS0F * X-func foo prologue FOO PDPPRLG CINDEX=0,FRAME=224,BASER=12,ENTRY=YES B @@FEN0 LTORG @@FEN0 EQU * DROP 12 BALR 12,0 USING *,12 @@PG0EQU * LR11,1 L 10,=A(@@PGT0) * Function foo code L 2,=A(@@LC0) * first buffer needs to copy the literal * then 46 filler MVC 96(4,13),0(2) LA6,100(,13) LA7,46(0,0) SLR 4,4 LR5,4 MVCL 6,4 * second bufer needs to copy the literal * then 66 filler MVC 152(4,13),0(2) LA6,156(,13) LA7,66(0,0) SLR 4,4 LR5,4 MVCL 6,4 * finished setting buffers, time for * irrelevant function call LA2,96(,13) ST2,88(13) LA2,152(,13) ST2,92(13) LA1,88(,13) L 15,=V(BAR) BALR 14,15 * Function foo epilogue PDPEPIL * Function foo literal pool DS0F LTORG * Function foo page table DS0F @@PGT0 EQU * DCA(@@PG0) END
gcc 3.4.6 asm charset error
GCC 3.4.6 natively handles different character sets for source and target. It actually works fine, writing source code in ASCII targeting an EBCDIC destination. However, __asm() doesn't seem to be working. As seen below, it is generating EBCDIC data in the ASCII assembler output. Those funny characters are in fact the EBCDIC code for "ABC" and "DEF". Anyone know how to fix this? Thanks. Paul. C:\scratch\bb99>type test.c extern int i; void foo(void) { i = 5; __asm("ABC"); __asm("DEF"); } C:\scratch\bb99>gccmvs-3_4_6-1_0 -S test.c C:\scratch\bb99>type test.s COPY PDPTOP CSECT * Program text area DS0F * X-func foo prologue FOO PDPPRLG CINDEX=0,FRAME=88,BASER=12,ENTRY=YES B FEN0 LTORG FEN0 EQU * DROP 12 BALR 12,0 USING *,12 PG0 EQU * LR11,1 L 10,=A(PGT0) * Function foo code L 2,=V(I) MVC 0(4,2),=F'5' ┴┬├ ─┼╞ * Function foo epilogue PDPEPIL * Function foo literal pool DS0F LTORG * Function foo page table DS0F PGT0 EQU * DCA(PG0) END C:\scratch\bb99>
Re: gcc 3.4.6 asm charset error
GCC 3.4.6 is the last version of GCC that supports the i370 target that I use. Last time I tried adding the i370 target from GCC 3.4.6 to GCC 4.x I got errors that I don't know how to fix. Actually GCC 3.4.6 also has errors which I don't know how to fix, so I normally use GCC 3.2.3. I hope one day someone with the required technical skills will volunteer to fix the remaining problems with GCC on MVS, and i370 will be a target once again in the latest GCC, but no-one has volunteered to clean it up for more than a decade. BFN. Paul. -Original Message- From: Segher Boessenkool Sent: Friday, September 23, 2016 6:21 AM To: Paul Edwards Cc: gcc@gcc.gnu.org Subject: Re: gcc 3.4.6 asm charset error On Thu, Sep 22, 2016 at 05:35:22PM +1000, Paul Edwards wrote: GCC 3.4.6 natively handles different character sets for source and target. It actually works fine, writing source code in ASCII targeting an EBCDIC destination. However, __asm() doesn't seem to be working. As seen below, it is generating EBCDIC data in the ASCII assembler output. Those funny characters are in fact the EBCDIC code for "ABC" and "DEF". Anyone know how to fix this? Does it work better with a GCC version that is less than ten years old? Segher
Re: i370 port
fig\i370\test>type onecomp.bat rem this should be run in a directory under config/i370 copy ..\..\..\testsuite\gcc.c-torture\execute\%1 cprog.c call mvsgccr cprog.c output.txt grep "EXECC CPROG RC= " output.txt if errorlevel 1 goto bad echo %1 passed >>results.txt goto exit :bad echo %1 failed >>results.txt :exit C:\devel\gcc\gcc\config\i370\test> C:\devel\gcc\gcc\config\i370\test>head dotests.bat del results.txt call onecomp 2112-1.c call onecomp 2113-1.c call onecomp 2121-1.c call onecomp 2205-1.c call onecomp 2217-1.c call onecomp 2223-1.c call onecomp 2224-1.c call onecomp 2225-1.c C:\devel\gcc\gcc\config\i370\test> -Original Message- From: Joseph S. Myers Sent: Saturday, June 6, 2009 1:02 AM To: Paul Edwards Cc: gcc@gcc.gnu.org Subject: Re: i370 port On Sat, 6 Jun 2009, Paul Edwards wrote: The port is to a pure C90 environment (ie not posix, not unix). It was a major effort to achieve that, and it has only just been completed to the point where the compiler recompiles itself with full optimization. The environment where it runs is not set up to run shell scripts or makes or test suites. It's set up to run JCL, and there's a stack of JCL card decks to allow GCC to compile, which would be good to have included in the i370 directory. You can test a cross compiler if you have some way of copying a test executable to the i370 system, running it and getting its output and exit status back (actually you don't need to be able to get the exit status since DejaGnu has wrappers to include it in the output if needed). There is no need for the target to be able to run shell scripts or makes. You would need to write your own DejaGnu board file that deals with copying to/from the i370 system and running programs there. The testsuite routinely runs for much more limited embedded systems (using appropriate board files). -- Joseph S. Myers jos...@codesourcery.com
i370 - negative indexes
Hi. On the i370 port of GCC 3.2.3, I am getting the following issue. This code: C:\scratch\bug>type bug.c const char *p; void foo(void) { printf("p-1 is %x\n", p[-1]); } generates: ... L 2,=F'-1' ... IC4,0(2,3) ie it is using a value of x’’ in R2 as an index. This works fine in AM24 and AM31 environments, but fails for AM64 where an address above 4 GiB is computed. Such code is very rare, so I would like to just have a rule that the index must always be a positive value, and for negative indexes like the above, different code is generated to do an actual subtract instead of trying to do everything via the index. Any idea how to achieve that? I can't see anywhere in i370.md where I can put some sort of constraint. Note that I am producing 32-bit modules, but setting them to AM64 so that they can use the full 4 GiB on certain environments (like MVS/380), instead of having a 2 GiB limit. Thanks. Paul. --- This email has been checked for viruses by AVG. http://www.avg.com
Re: i370 port
Hi Ulrich and group. The i370 port of GCC 3.4.6 is now complete and the result can be downloaded from http://gccmvs.sourceforge.net It can be built using configure/make, and there weren't that many changes that needed to be made to the code to get it to work. However, I have encountered a bug. I get bad code generated for this, because a non-s_operand is getting through: ; Move a block that is less than 256 bytes in length. (define_insn "" [(set (match_operand:BLK 0 "s_operand" "=m") (match_operand:BLK 1 "s_operand" "m")) (use (match_operand 2 "immediate_operand" "I"))] "((unsigned) INTVAL (operands[2]) < 256)" "* { check_label_emit (); mvs_check_page (0, 6, 0); return \"MVC %O0(%c2,%R0),%1\"; }" [(set_attr "length" "6")] ) Here is the bad code: L 9,=F'32880' MVC 9(10,13),0(2) That "9" in the MVC is supposed to be a constant from 0-4095. It can't fit the large value in so has used a register, but then tried to use that register in the instruction. It should have added R13 to R9 and used that as the base register (instead of the 13 you see) I was surprised that an instruction that is marked as s_operand was getting a seemingly non-s_operand given to it, so I added an "S" constraint: ; Move a block that is less than 256 bytes in length. (define_insn "" [(set (match_operand:BLK 0 "s_operand" "=S") (match_operand:BLK 1 "s_operand" "m")) That then gave an actual compiler error instead of generating bad code, which is a step forward: pdos.c: In function `pdosLoadExe': pdos.c:2703: error: unable to generate reloads for: (insn 38 37 41 0 (parallel [ (set (mem/s:BLK (plus:SI (reg/f:SI 13 13) (const_int 32880 [0x8070])) [27 srchprog+0 S10 A64]) (mem:BLK (reg/v/f:SI 2 2 [orig:27 prog ] [27]) [0 S10 A8])) (use (const_int 10 [0xa])) ]) 25 {*i370.md:1623} (insn_list 37 (nil)) (expr_list:REG_DEAD (reg/v/f:SI 2 2 [orig:27 prog ] [27]) (nil))) pdos.c:2703: internal compiler error: in find_reloads, at reload.c:3690 Please submit a full bug report, with preprocessed source if appropriate. See http://gccmvs.sourceforge.net> for instructions. But I am surprised that s_operand and "S" are producing different results. Regardless, I sort of tracked the problem down to this bit of the machine definition: ; ; movstrsi instruction pattern(s). ; block must be less than 16M (24 bits) in length (define_expand "movstrsi" [(set (match_operand:BLK 0 "general_operand" "") (match_operand:BLK 1 "general_operand" "")) (use (match_operand:SI 2 "general_operand" "")) (match_operand 3 "" "")] "" " { rtx op0, op1; op0 = XEXP (operands[0], 0); if (GET_CODE (op0) == REG || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG && GET_CODE (XEXP (op0, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op0, 1)) < 4096)) op0 = operands[0]; else op0 = replace_equiv_address (operands[0], copy_to_mode_reg (SImode, op0)); op1 = XEXP (operands[1], 0); if (GET_CODE (op1) == REG || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG && GET_CODE (XEXP (op1, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op1, 1)) < 4096)) op1 = operands[1]; else op1 = replace_equiv_address (operands[1], copy_to_mode_reg (SImode, op1)); if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 256) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, op0, op1), gen_rtx_USE (VOIDmode, operands[2]; So now I am basically wanting to stop this code from doing that emit_insn. I tested putting in a kludge to see if operands[2] was equal to 10 (the length in my test case), and bypassing the emit_insn. That forced it to use a more inefficient move instruction, but that's fine. So I need some way of getting op0 detected as "unsuitable for use in an MVC". I have put in debug and found that GET_CODE(op0) is equal to MEM. I have also found that GET_CODE(XEXP(op0, 0)) is a REG_P, whatever that means (I was just copying things I saw in the s_operand test). Here is the s_operand test for reference: /* Return 1 if OP is a valid S operand for an RS, SI or SS type instruction. OP is the current operation. MODE is the current operation mode. */ int s_operand (register rtx op, enum machine_mode mode) { extern int volatile_ok; register enum rtx_code code = GET_CODE (op); if (CONSTANT_ADDRESS_P (op)) return 1; if (mode == VOIDmode || GET_MODE (op) != mode) return 0; if (code == MEM) { register rtx x = XEXP (op, 0); if (!volatile_ok && op->volatil) return 0; if (REG_P (x) && REG_OK_FOR_BASE_P (x)) return 1; if (GET_CODE (x) == PLUS && REG_P (XEXP (x, 0)) && REG_OK_FOR_BASE_P (XEXP (x, 0)) && GET_CODE (XEXP (x, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (x, 1)) < 4096)
Re: i370 port
You'll need to mark your new constraint as EXTRA_MEMORY_CONSTRAINT so that reload knows what to do when an argument doesn't match. Thanks! That certainly produced an effect. Unfortunately it's not quite right, seemingly not loading R9 properly: LR9,13 AR9,13 MVC 0(10,9),0(2) And it had a knock-on effect too, producing bad code elsewhere: < SLR 2,2 < SLR 3,3 < ST2,128(13) < ST3,4+128(13) < ST2,136(13) < ST3,4+136(13) < ST2,144(13) < ST3,4+144(13) --- MVC 128(8,13),=F'0' MVC 136(8,13),=F'0' MVC 144(8,13),=F'0' But I guess that is another can of worms to investigate. BFN. Paul.
Re: i370 port
Hi Ulrich. I put in the following debug: op0 = find_replacement (&XEXP (in, 0)); op1 = find_replacement (&XEXP (in, 1)); /* Since constraint checking is strict, commutativity won't be checked, so we need to do that here to avoid spurious failure if the add instruction is two-address and the second operand of the add is the same as the reload reg, which is frequently the case. If the insn would be A = B + A, rearrange it so it will be A = A + B as constrain_operands expects. */ fprintf(stderr, "REGNO(out) is %d\n", REGNO(out)); fprintf(stderr, " REG in 1 is %d\n", REGNO(XEXP(in,1))); if (GET_CODE (XEXP (in, 1)) == REG && REGNO (out) == REGNO (XEXP (in, 1))) tem = op0, op0 = op1, op1 = tem; And it produced this output (for exactly the same code I showed you previously): C:\devel\pdos\s370>\devel\gcc\gcc\gccmvs -da -DUSE_MEMMGR -Os -DS390 -S -I . -I ../pdpclib pdos.c REGNO(out) is 3 REG in 1 is 32880 REGNO(out) is 2 REG in 1 is 32880 REGNO(out) is 2 REG in 1 is 32880 REGNO(out) is 2 REG in 1 is 112 REGNO(out) is 3 REG in 1 is 32880 REGNO(out) is 4 REG in 1 is 112 REGNO(out) is 2 REG in 1 is 112 which looks to me like it is not seeing a register, only a constant, so cannot perform a swap. Let me know if that is not the debugging required. Thanks. Paul. -Original Message- From: Ulrich Weigand Sent: Tuesday, August 16, 2011 11:25 PM To: Paul Edwards Cc: gcc@gcc.gnu.org Subject: Re: i370 port Paul Edwards wrote: >> Unfortunately it's not quite right, seemingly not loading R9 properly: >> >> LR9,13 >> AR9,13 >> MVC 0(10,9),0(2) > That's weird. What does the reload dump (.greg) say? I have trimmed the code down to a reasonably small size so that I could provide the .greg file (below) from the "-da" option. I don't know how to read it so I don't know if I've provided everything required. Here is the current problematic generated code: * Function pdosLoadExe code L 2,4(11) MVC 88(4,13),=A(LC0) ST2,92(13) LA1,88(,13) L 15,=V(PRINTF) BALR 14,15 LR3,13 <= probably wrong AR3,13 <= else this is wrong MVC 0(10,3),0(2) Reload decides on the following actions: Reloads for insn # 38 Reload 0: reload_in (SI) = (const_int 32880 [0x8070]) ADDR_REGS, RELOAD_FOR_INPUT_ADDRESS (opnum = 0) reload_in_reg: (const_int 32880 [0x8070]) reload_reg_rtx: (reg:SI 3 3) Reload 1: reload_in (SI) = (plus:SI (reg/f:SI 13 13) (const_int 32880 [0x8070])) ADDR_REGS, RELOAD_FOR_INPUT (opnum = 0) reload_in_reg: (plus:SI (reg/f:SI 13 13) (const_int 32880 [0x8070])) reload_reg_rtx: (reg:SI 3 3) That is, first: load the constant 32880 into register 3, and second: using that reloaded constant, compute the sum of register 13 plus 32880 and load the result also into register 3. Then, use that register for addressing. This leads to the following generated code: (insn 271 37 273 0 (set (reg:SI 3 3) (const_int 32880 [0x8070])) 15 {movsi} (nil) (nil)) Load constant into register 3. (insn 273 271 274 0 (set (reg:SI 3 3) (reg/f:SI 13 13)) 15 {movsi} (nil) (nil)) (insn 274 273 38 0 (set (reg:SI 3 3) (plus:SI (reg:SI 3 3) (reg:SI 3 3))) 41 {addsi3} (nil) (expr_list:REG_EQUIV (plus:SI (reg/f:SI 13 13) (reg:SI 3 3)) (nil))) Compute the sum. Note that this code is wrong. (insn 38 274 41 0 (parallel [ (set (mem/s:BLK (reg:SI 3 3) [6 srchprog+0 S10 A64]) (mem:BLK (reg/v/f:SI 2 2 [orig:27 prog ] [27]) [0 S10 A8])) (use (const_int 10 [0xa])) ]) 25 {*i370.md:1623} (insn_list 37 (nil)) (nil)) Use register 3 for adressing. The wrong code comes in when generating the sum (insns 273/274). I would have expected this to be a simple addsi3 instruction, along the lines of (set (reg:SI 3 3) (plus:SI (reg:SI 3 3) (reg:SI 13 13))) Note that the incoming pattern: (set (reg:SI 3 3) (plus:SI (reg:SI 13 13) (reg:SI 3 3))) cannot be immediately resolved, since addsi3 requires the first operand of the plus to match the result. However, this could have been fixed by just swapping the operands. Instead, the code attempts to create the match by reloading the first operand (reg 13) into the output (reg 3) -- this is bogus, since it thereby clobbers the *second* input operand, which happens to match the output. The code that generates these insns is in reload1.c:gen_reload /* We need to compute the sum of a register or a MEM and another register, constant, or MEM, and put it into the reload register. The best possible way of doing
Re: i370 port
Well done! That generated sensible code: L 15,=V(PRINTF) BALR 14,15 L 3,=F'32880' AR3,13 MVC 0(10,3),0(2) I still have the other knock-on effects from when I did this though: C:\devel\gcc\gcc\config\i370>cvs diff i370.h Index: i370.h === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.h,v retrieving revision 1.17 diff -r1.17 i370.h 599a600,602 #define EXTRA_MEMORY_CONSTRAINT(C, STR) \ ((C) == 'S') (like the 8 byte move from F'0'). I'll do my own investigation of that and report that later. BFN. Paul. -Original Message- From: Ulrich Weigand Sent: Thursday, August 18, 2011 11:14 PM To: Paul Edwards Cc: gcc@gcc.gnu.org Subject: Re: i370 port Paul Edwards wrote: Hi Ulrich. I put in the following debug: op0 = find_replacement (&XEXP (in, 0)); op1 = find_replacement (&XEXP (in, 1)); /* Since constraint checking is strict, commutativity won't be checked, so we need to do that here to avoid spurious failure if the add instruction is two-address and the second operand of the add is the same as the reload reg, which is frequently the case. If the insn would be A = B + A, rearrange it so it will be A = A + B as constrain_operands expects. */ fprintf(stderr, "REGNO(out) is %d\n", REGNO(out)); fprintf(stderr, " REG in 1 is %d\n", REGNO(XEXP(in,1))); if (GET_CODE (XEXP (in, 1)) == REG && REGNO (out) == REGNO (XEXP (in, 1))) tem = op0, op0 = op1, op1 = tem; And it produced this output (for exactly the same code I showed you previously): C:\devel\pdos\s370>\devel\gcc\gcc\gccmvs -da -DUSE_MEMMGR -Os -DS390 -S -I . -I ../pdpclib pdos.c REGNO(out) is 3 REG in 1 is 32880 REGNO(out) is 2 REG in 1 is 32880 REGNO(out) is 2 REG in 1 is 32880 REGNO(out) is 2 REG in 1 is 112 REGNO(out) is 3 REG in 1 is 32880 REGNO(out) is 4 REG in 1 is 112 REGNO(out) is 2 REG in 1 is 112 which looks to me like it is not seeing a register, only a constant, so cannot perform a swap. Oops, there's clearly a bug here. "in" at this point is the original expression that has not yet been reloaded, so its second operand will indeed be a constant, not a register. However, reload has already decided that this constant will end up being replaced by a register, and that is what the "find_replacement" call is checking. So at this point in the program, XEXP (in, 1) will be the constant, but op1 will be the register it is going to be replaced with. Unfortunately the test whether to swap looks at XEXP (in, 1) -- it really needs to look at op1 instead. Can you try changing the lines if (GET_CODE (XEXP (in, 1)) == REG && REGNO (out) == REGNO (XEXP (in, 1))) to if (GET_CODE (op1) == REG && REGNO (out) == REGNO (op1)) instead? Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE ulrich.weig...@de.ibm.com
Re: i370 port
(like the 8 byte move from F'0'). I'll do my own investigation of that and report that later. Ok, the bad MVC: MVC 112(8,13),=F'0' is being generated by the movdi instruction: ; ; movdi instruction pattern(s). ; (define_insn "" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,m,S") (match_operand:DI 1 "general_operand" "g,d,SF"))] ;; [(set (match_operand:DI 0 "r_or_s_operand" "=dS,m") ;;(match_operand:DI 1 "r_or_s_operand" "diS*fF,d*fF"))] "TARGET_CHAR_INSTRUCTIONS" "* { ... return \"MVC^I%O0(8,%R0),%1\"; }" which looks correct to me. The problem seems to be an =F'0' being treated as a DI operand. That extra memory constraint thing must be allowing this rogue value through that was normally not picked up. Any ideas? Thanks. Paul.
Re: i370 port
And here is the same debug info as last time ... #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "rtl.h" rtx foo (rtx addr, int size, int n_refs) { int offset = 0; switch (GET_CODE (addr)) { case PRE_INC: offset = (n_refs + 1) * size; break; case PRE_DEC: offset = -(n_refs + 1) * size; break; case POST_INC: offset = n_refs * size; break; } if (offset) addr = gen_rtx_PLUS (GET_MODE (addr), XEXP (addr, 0), GEN_INT (offset)); else addr = XEXP (addr, 0); return addr; } COPY PDPTOP CSECT * Program text area DS0F * X-func foo prologue FOO PDPPRLG CINDEX=0,FRAME=120,BASER=12,ENTRY=YES B FEN0 LTORG FEN0 EQU * DROP 12 BALR 12,0 USING *,12 PG0 EQU * LR11,1 L 10,=A(PGT0) * Function foo code MVC 112(8,13),=F'0' SLR 8,8 SLR 9,9 LR6,8 LR7,9 L 3,0(11) L 2,8(11) LH4,0(3) N 4,=XL4'' ST4,104(13) LA5,110(0,0) CLR 4,5 BEL3 BHL6 LA15,109(0,0) CLR 4,15 BEL4 B L7 L6 EQU * L 5,104(13) LA4,112(0,0) CLR 5,4 BEL5 B L7 L3 EQU * A 2,=F'1' L 15,4(11) ST15,116(13) L 4,112(13) L 5,4+112(13) MR4,2 ST4,112(13) ST5,4+112(13) LR2,5 B L2 L4 EQU * X 2,=F'-1' L 9,4(11) MR8,2 LR2,9 B L2 L5 EQU * L 7,4(11) MR6,2 LR2,7 L2 EQU * LTR 2,2 BEL7 MVC 88(4,13),=F'0' ST2,92(13) LA1,88(,13) L 15,=V(ZZZ@947) BALR 14,15 MVC 88(4,13),=F'88' SLR 5,5 IC5,2(3) ST5,92(13) MVC 96(4,13),4(3) ST15,100(13) LA1,88(,13) L 15,=V(ZZZ@957) BALR 14,15 LR3,15 B L8 L7 EQU * L 3,4(3) L8 EQU * LR15,3 * Function foo epilogue PDPEPIL * Function foo literal pool DS0F LTORG * Function foo page table DS0F PGT0 EQU * DCA(PG0) END ;; Function foo ;; 8 regs to allocate: 37 28 29 31 (2) 35 (2) 34 (2) 26 27 ;; 26 conflicts: 26 27 28 29 31 34 35 37 11 15 ;; 27 conflicts: 26 27 28 31 34 35 37 11 ;; 28 conflicts: 26 27 28 31 34 35 37 11 ;; 29 conflicts: 26 29 11 ;; 31 conflicts: 26 27 28 31 34 35 37 11 ;; 34 conflicts: 26 27 28 31 34 35 37 11 ;; 35 conflicts: 26 27 28 31 34 35 37 11 ;; 37 conflicts: 26 27 28 31 34 35 37 11 Spilling for insn 3. Spilling for insn 4. Spilling for insn 5. Spilling for insn 45. Spilling for insn 46. Using reg 15 for reload 0 Spilling for insn 48. Using reg 4 for reload 0 Spilling for insn 50. Using reg 4 for reload 0 Spilling for insn 55. Using reg 4 for reload 0 Spilling for insn 19. Spilling for insn 29. Spilling for insn 37. Spilling for insn 63. Spilling for insn 64. Spilling for insn 67. Spilling for insn 71. Using reg 2 for reload 0 Spilling for insn 72. Spilling for insn 73. Spilling for insn 80. Register 37 now on stack. Spilling for insn 3. Spilling for insn 4. Spilling for insn 5. Spilling for insn 45. Using reg 15 for reload 0 Spilling for insn 46. Using reg 15 for reload 1 Using reg 4 for reload 0 Spilling for insn 48. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 50. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 55. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 19. Spilling for insn 29. Spilling for insn 37. Spilling for insn 63. Spilling for insn 64. Spilling for insn 67. Spilling for insn 71. Using reg 2 for reload 0 Spilling for insn 72. Spilling for insn 73. Spilling for insn 80. Register 31 now on stack. Spilling for insn 113. Spilling for insn 3. Spilling for insn 4. Spilling for insn 5. Spilling for insn 45. Using reg 4 for reload 0 Spilling for insn 46. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 48. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 50. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 55. Using reg 4 for reload 1 Using reg 5 for reload 0 Spilling for insn 19. Using reg 4 for reload 0 Spilling for insn 20. Using reg 4 for reload 0 Spilling for insn 21. Spilling for insn 29. Spilling for insn 37. Spilling for insn 63. Spilling for insn 64. Spilling for insn 67. Spilling for insn 71. Using reg 2 for reload 0 Spilling for insn 72. Spilling for insn 73. Spilling for insn 80. Reloads for insn # 113 Reload 0: reload_out (DI) = (reg:DI 31 [ si
Re: i370 port
Adding this code: C:\devel\gcc\gcc\config\i370>cvs diff i370.md Index: i370.md === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.md,v retrieving revision 1.21 diff -r1.21 i370.md 845a846,851 if (operands[1] == const0_rtx) { CC_STATUS_INIT; mvs_check_page (0, 6, 8); return \"MVC %O0(8,%R0),=XL8'00'\"; } to the i370.md definition: ; ; movdi instruction pattern(s). ; (define_insn "" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,m,S") (match_operand:DI 1 "general_operand" "g,d,SF"))] ;; [(set (match_operand:DI 0 "r_or_s_operand" "=dS,m") ;;(match_operand:DI 1 "r_or_s_operand" "diS*fF,d*fF"))] "TARGET_CHAR_INSTRUCTIONS" "* { check_label_emit (); if (REG_P (operands[0])) { if (FP_REG_P (operands[1])) { mvs_check_page (0, 8, 0); return \"STD%1,\" CONVLO \"(,13)\;LM%0,%N0,\" CONVLO \"(13)\"; } if (REG_P (operands[1])) { mvs_check_page (0, 4, 0); return \"LR%0,%1\;LR%N0,%N1\"; } if (operands[1] == const0_rtx) { CC_STATUS_INIT; mvs_check_page (0, 4, 0); return \"SLR%0,%0\;SLR%N0,%N0\"; } if (GET_CODE (operands[1]) == CONST_INT && (unsigned) INTVAL (operands[1]) < 4096) { CC_STATUS_INIT; mvs_check_page (0, 6, 0); return \"SLR%0,%0\;LA%N0,%c1(0,0)\"; } if (GET_CODE (operands[1]) == CONST_INT) { CC_STATUS_SET (operands[0], operands[1]); mvs_check_page (0, 8, 0); return \"L%0,%1\;SRDA%0,32\"; } if (GET_CODE (operands[1]) == CONST_DOUBLE) { mvs_check_page (0, 6, 8); return \"LM%0,%N0,%1\"; } mvs_check_page (0, 4, 0); /*return \"LM%0,%N0,%1\";*/ return \"L%0,%1\;L%N0,4+%1\"; } else if (FP_REG_P (operands[1])) { mvs_check_page (0, 4, 0); return \"STD%1,%0\"; } else if (REG_P (operands[1])) { mvs_check_page (0, 4, 0); /*return \"STM%1,%N1,%0\"; */ return \"ST%1,%0\;ST%N1,4+%0\"; } if (operands[1] == const0_rtx) { CC_STATUS_INIT; mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),=XL8'00'\"; } mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),%1\"; }" [(set_attr "length" "8")] ) forces it to use XL8'00' instead of the default F'0' and that seems to work. Does that seem like a proper solution to you? Unfortunately there's still another problem I've noticed. I'll put that in another message after I've investigated it. BFN. Paul.
Re: i370 port
But sometimes r_or_s_operand is being used as a source, in which case, the constant is fine. But when it is used as a destination, it is not fine. What is the *simplest* way of changing the setup so that the code generation remains the same, but the warning is eliminated? Well, I guess you need to do two things: - Define the PREDICATE_CODES macro -- if this is undefined, genrecog will consider *any* target-defined predicate as potentially allowing non-lvalues, because it cannot know better. - Actually define two distinct predicates, one that allows non-lvalue and one that doesn't, and use them as appropriate. But wondering if there's something simpler and neater. Well, you could also simply ignore the warning -- nothing is going to go wrong because of it. Thanks for pointing me in the right direction Ulrich. Unfortunately just short of what would have been best for this situation. I defined the PREDICATE_CODES macro and put in the things I thought were appropriate: C:\devel\gcc\gcc\config\i370>cvs diff -r 1.33 -r 1.34 i370.h Index: i370.h === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.h,v retrieving revision 1.33 retrieving revision 1.34 diff -r1.33 -r1.34 200a201,204 #define PREDICATE_CODES \ {"r_or_s_operand", { REG, SUBREG, MEM, CONST_INT }}, \ {"s_operand", { MEM, CONST_INT }}, It had no effect on anything that I could see, but that was to be expected. I then had a closer look at the machine definitions and realised that some of them that were defined as r_or_s_operand could instead be nonimmediate_operand, which started eliminating warnings. So I proceeded down this track, eliminating things here and there, or in some cases, opening things up to be more general, with the hope that I would eventually have things so that the only r_or_s_operand I needed were ones that didn't require literals, so that I could (at the end), make this change: C:\devel\gcc\gcc\config\i370>cvs diff -r 1.34 -r 1.35 i370.h Index: i370.h === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.h,v retrieving revision 1.34 retrieving revision 1.35 diff -r1.34 -r1.35 202,203c202,203 < {"r_or_s_operand", { REG, SUBREG, MEM, CONST_INT }}, \ < {"s_operand", { MEM, CONST_INT }}, --- {"r_or_s_operand", { REG, SUBREG, MEM }}, \ {"s_operand", { MEM }}, and something similar in i370.c, to make constants invalid, so that I could eliminate the warnings. It took a month to do that, because I kept on being hit by presumed bugs, which started generating bad or unexpected code when I made a seemingly innocuous change. To make matters worse, sometimes I could only find out whether the code was good or not by running it on MVS, via the emulator, which means a 2 hour wait for a result. However, I did get it down to just a handful of warnings, which would be eliminated now that I could drop the CONST_INT. And I would check the generated code to see what I had missed when I took off the CONST_INT. Anyway, I took off the CONST_INT, and the warnings all disappeared, and the code didn't change! I then found out that even with old versions of the machine definition, I can have the warning removed by simply not defining CONST_INT in the PREDICATE_CODES, even though it is allowed when the function is called. ie it seems to have no effect on the code generation, but succeeds in eliminating the warning, and without needing to define an extra constraint for non-constant situations. So I've revamped the machine definition unnecessarily. Well, I did make things defined more consistently, and did make code generation improvements, but they're not major, and I wouldn't have done any of it if I knew I could have just defined a predicate that wasn't really going to be used. Oh well. At the end of the day, the warning has gone, the code is better and the machine definition is more correct. :-) I've also got 3.4.6 working to some extent. I have managed to build an single GCC executable, and if I call it with no parameters, it prints its usage (as designed). However, if I try to pass parameters it doesn't recognize them. It could be something to do with not having run the appropriate stuff through bison (or flex) on an EBCDIC platform. Normally I use this to get around that problem: C:\devel\gccnew\gcc>cvs diff -r release-3_4_6 c-parse.c Index: c-parse.c === RCS file: c:\cvsroot/gccnew/gcc/c-parse.c,v retrieving revision 1.1.1.1 retrieving revision 1.4 diff -r1.1.1.1 -r1.4 497a498,503 #if defined(__MVS__) || defined(__CMS__) #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? \ ((unsigned int) (YYX) < 256 ? yytranslate[_sch_ebcasc[YYX]] \ : yytranslate[YYX]) : YYUNDEFTOK) #else 499a506 #endif But perhaps the new gengtyp lex and yacc, although not used in the actual GCC executable,
Re: i370 port
I then found out that even with old versions of the machine definition, I can have the warning removed by simply not defining CONST_INT in the PREDICATE_CODES, even though it is allowed when the function is called. ie it seems to have no effect on the code generation, but succeeds in eliminating the warning, and without needing to define an extra constraint for non-constant situations. Actually PREDICATE_CODES does have to match the predicate definitions. If it does not, you can run into subtle bugs, as the code in genrecog.c that generates the finite state automaton matching an RTX pattern against the .md insn definitions *does* make use of PREDICATE_CODES; for example, it will assume that two predicates with disjoint sets of PREDICATE_CODES can never both match the same RTX. This may or may not lead to visible differences when compiling simple test cases, but I'd expect effects to be visible in more complex scenarios. Thanks Ulrich. When I went back to this I found that I had misdiagnosed - actually the r_or_s didn't allow constants after all. It was only const_rtx that it allowed. So the machine definition no longer has any warnings and all looks good. That's with 3.2.3. With 3.4.6 I have now managed to get an MVS load module, unoptimized (I already know that optimized doesn't work), to compile a hello world program successfully, although it abends at the end of that and I haven't investigated that yet. So the theoretical EBCDIC support is less theoretical now. I "needed" to change the parameter search algorithm to stop being binary search though. GCC 4 complained (on my Linux system) that I didn't have various things (gimp etc) installed, which means I would need that other software to be ported too, which is not a project I want to work on at the moment. However, at least it means that i have successfully merged all the GCCMVS changes to 3.2.3 in with the (last available) 3.4.6 development, which was a precursor to any GCC 4 port anyway. I'll see over time how GCC 3.4.6 pans out. Until then, back at GCC 3.2.3, I have a "need" to make the entry point 0 in my MVS modules. Currently I generate this: COPY PDPTOP CSECT * X-var bytes ENTRY BYTES * Program data area DS0F BYTESEQU * DCF'258' * Program text area LC0 EQU * DCC'bytes is %d' DCX'15' DCX'0' DS0F DCC'GCCMVS!!' EXTRN @@CRT0 ENTRY @@MAIN @@MAIN DS0H USING *,15 L 15,=V(@@CRT0) BR15 DROP 15 LTORG * X-func main prologue MAIN PDPPRLG CINDEX=0,FRAME=96,BASER=12,ENTRY=YES ... * Function main page table DS0F PGT0 EQU * DCA(PG0) END @@MAIN for a main program. In order to get the entry point to 0, I need to move that @@MAIN function to the top of the file. But I only really want that function if this is a main program. I have found somewhere where I can add some code to see if the function "main" is being compiled, and set a global variable. Unfortunately, the place that happens (c-decl) isn't called until after all the data has been written out! I looked at the documentation: http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gccint/Assembler-Format.html#Assembler%20Format but maybe I'm looking in the wrong place. Any ideas? And I have another question - where is the code for __asm__? Currently that is generating garbage for me: unsigned int bytes = 258; __asm__("? :"); int main(void) BYTESEQU * DCF'258' o...@z * Program text area when done in cross-compiler mode, and need to find out where the literal is being translated (or more likely - failing to be translated in the first instance). Any idea where that is? And final thing - the interest in the __asm__ comes from the hope that in the generated 370 assembler, it would be possible to have the C code interspersed to whatever extent possible. The plan was to basically somehow get every line of C code, e.g. "int main(void)" above, and automatically generate an: __asm__("int main void)"); although I'm not sure what to do about this: int main(void) __asm__("? :"); { which gives a syntax error. Any idea how to get the mixed C/assembler when I'm running with the "-S" option and don't have the luxury of calling the normal "as" which would normally handle that? Thanks. Paul.
Re: i370 port
This probably is not gimp (the graphics editor) but gmp (the multi-precision integer operation library) and mpfr (same for floating-point). To build any recent GCC you'll indeed need these two libraries. Fortunately, they're already available on s390(x) on Linux, and shouldn't really contain anything that is OS-specific, so porting those to MVS should hopefully be straightforward ... Ok, thanks Ulrich. Until then, back at GCC 3.2.3, I have a "need" to make the entry point 0 in my MVS modules. Currently I generate this: [snip] for a main program. In order to get the entry point to 0, I need to move that @@MAIN function to the top of the file. I don't think there is a reliable way to change the sequence of functions / objects in the output file. Sorry, my question may not have been clear. When I see main(), I generate the normal MAIN code, and I don't care where this goes. However, given that I now know that a main() exists somewhere in this source file, I need to change the ASM_FILE_START output. I expected that the assembler generation wouldn't happen until after the optimization was completed, and thus, by then, I would know whether this was a main. However, it seems to me it shouldn't really be necessary to treat "main" special. Usually, the "entry point" isn't really "main", but rather some function in crt0.o, which then in turn *calls* main after all startup processing has been done. That is roughly the case, yes. As crt0.o can be (and usually is) completely written in assembler, you can arrange for everything to be in the sequence that is required. (On the linker command line, crt0.o would be placed first, so if the entry point is the first thing in crt0.o it will then also be the first thing in the executable.) Yes, I can do that, but that means I need to have a linker command line! The way the MVS linker works, I can link my main program, (which obviously doesn't have crt0 in it), and, thanks to the "END" statement, I can specify an entry point. This means no complaint from the linker about a default (and wrong) entry point, and no need for any linker statements. It all automatically resolves. It all works really great! Except - I would ideally like to have an entry point of 0, instead of the typical "58" or whatever my static variables happen to be. (my main is normally at the top). And I have another question - where is the code for __asm__? Currently that is generating garbage for me: unsigned int bytes = 258; __asm__("? :"); int main(void) BYTESEQU * DCF'258' o...@z * Program text area when done in cross-compiler mode, and need to find out where the literal is being translated (or more likely - failing to be translated in the first instance). Any idea where that is? Hmm, this seems to be the bug fixed by Eric Christopher in 2004: http://gcc.gnu.org/ml/gcc-cvs/2004-02/msg01425.html Thanks again! That didn't seem to make it into 3.4.6. I was able to apply most of his stuff to 3.4.6, and I will see how far that gets me, before trying to find it in 3.2.3. Or maybe I'll skip it, since the problem doesn't occur on a pure EBCDIC system. :-) And final thing - the interest in the __asm__ comes from the hope that in the generated 370 assembler, it would be possible to have the C code interspersed to whatever extent possible. The plan was to basically somehow get every line of C code, e.g. "int main(void)" above, and automatically generate an: __asm__("int main void)"); As you note, this doesn't seem workable as the result wouldn't be syntactically valid ... which gives a syntax error. Any idea how to get the mixed C/assembler when I'm running with the "-S" option and don't have the luxury of calling the normal "as" which would normally handle that? There doesn't seem to be an easy way to do this from the compiler. At the time compiler output is generated, the original source code text isn't even kept any more; you'd have to go back and re-read the original source files using the line-number debug data, just as the assembler would ... Ok, well - I would be content with just the source line number appearing in the output assembler. Is this information available as each assembler line is output? Thanks. Paul.
Re: i370 port
That depends a bit on the compiler version and optimization level, but (in particular in the 3.x time frame) GCC may output assembler code on a function-by-function basis, without necessarily reading in the whole source file first. Ok, actually it doesn't matter if it doesn't work all the time. I'll always be compiling with -Os anyway, so it sounds like I'm in with a chance of the whole file being read first? If so, where is my first opportunity, in 3.2.3, to see if there's a "main" function in this file? > As crt0.o can be (and usually is) completely > written in assembler, you can arrange for everything to be in the > sequence > that is required. (On the linker command line, crt0.o would be placed > first, so if the entry point is the first thing in crt0.o it will then > also be the first thing in the executable.) Yes, I can do that, but that means I need to have a linker command line! The way the MVS linker works, I can link my main program, (which obviously doesn't have crt0 in it), and, thanks to the "END" statement, I can specify an entry point. This means no complaint from the linker about a default (and wrong) entry point, and no need for any linker statements. It all automatically resolves. I don't know exactly how your port handles this on MVS, but usually GCC itself will invoke the linker, and will itself prepare an appropriate command linker for the linker. GCC on MVS *only* outputs assembler. ie you always have to use the "-S" option. By doing so, it turns GCC into a pure text-processing application, which will thus work in any C90 environment. In current GCC, every insn contains "location" information pointing back to source code line (and column) numbers. However, in GCC 3.x I think this wasn't yet present, but you had to rely on line number notes interspersed with the insn stream. In any case, if you build with -g and use in addition the "debug assembler output" flag -dA the assembler output should contain human-readable comments containing line number information. The GCC assembler is never invoked. After getting the assembler output from the -S option, this is fed into IFOX00/IEV90/ASMA90. Regardless, if line number notes are interspersed in the stream, maybe whenever I write out an assembler instruction I will have access to those notes and can print out a comment. Thanks. Paul.
Re: i370 port
Thanks guys for your reply. As Paolo mentioned, the -dA flag is an option to the *compiler* that causes it to place additional information into its output stream (the assembler source code). [from Paolo] Only DWARF-2 output supports it currently, but if you want to use it say together with STABS, it is just a matter of modifying dbxout_source_line and add a single statement like this: if (flag_debug_asm) fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, filename, line); Ok, after a few false leads, I found something that produced a pleasing result. Fantastic I should say! With this mod: C:\devel\gcc\gcc>cvs diff debug.c Index: debug.c === RCS file: c:\cvsroot/gcc/gcc/debug.c,v retrieving revision 1.1.1.1 diff -r1.1.1.1 debug.c 20a21,31 #include "output.h" #include "flags.h" void fff (line, text) unsigned int line ATTRIBUTE_UNUSED; const char *text ATTRIBUTE_UNUSED; { if (flag_debug_asm) fprintf(asm_out_file, "fff %d %s\n", line, text); } 34c45 < debug_nothing_int_charstar, /* source_line */ --- fff /*debug_nothing_int_charstar*/, /* source_line */ and the -g -dA options I was able to get exactly what I needed: * Function main code fff 32 world.c * basic block 0 L 2,=V(X) L 2,0(2) LTR 2,2 BEL2 fff 34 world.c * basic block 1 MVC 88(4,13),=A(LC0) B L4 L2 EQU * * basic block 2 fff 38 world.c MVC 88(4,13),=A(LC1) L4 EQU * * basic block 3 LA1,88(,13) L 15,=V(PRINTF) BALR 14,15 fff 41 world.c SLR 15,15 * Function main epilogue But let me guess - I'm not allowed to modify debug.c and have to decide whether MVS is an sdb, xcoff, dbx, dwarf 1/2, or vms? > That depends a bit on the compiler version and optimization level, > but (in particular in the 3.x time frame) GCC may output assembler > code on a function-by-function basis, without necessarily reading > in the whole source file first. Ok, actually it doesn't matter if it doesn't work all the time. I'll always be compiling with -Os anyway, so it sounds like I'm in with a chance of the whole file being read first? If so, where is my first opportunity, in 3.2.3, to see if there's a "main" function in this file? Hmm, it seems 3.2.x would *always* operate on a function-by-function basis. The unit-at-a-time mode was only introduced with 3.4 (I don't recall if it was already present in 3.3). I don't think there is any way in 3.2.3 to check whether there is a "main" function in the file before it is processed ... Ok, I'll wait until 3.4.6 is working before attempting to get the entry point to 0 then. :-) > I don't know exactly how your port handles this on MVS, but usually > GCC itself will invoke the linker, and will itself prepare an > appropriate command linker for the linker. GCC on MVS *only* outputs assembler. ie you always have to use the "-S" option. By doing so, it turns GCC into a pure text-processing application, which will thus work in any C90 environment. Huh. So the user will always have to invoke the linker manually, and pass all the correct options (libraries etc.)? Correct. Very normal MVS. Where would we be without IEWL? What is the problem with having GCC itself invoke the linker, just like it does on other platforms? 1. That requires extensions to the C90 standard. The behaviour of system() is undefined, much less even the existence of fork() etc. 2. The attempt to add functionality to system() in MVS has made leaps and bounds, but has not reached the stage of being able to detect if the SYSPRINT DCB is already open so it knows not to reopen it, and close it, stuffing up the caller. 3. MVS compilers don't normally invoke the linker. That's always a separate step. GCCMVS is an MVS compiler also. It would be normal to generate object code though. But the compiler normally generates the object code, rather than invoking the assembler. In any case, the facility to allocate temporary datasets for HLASM and deciding what space parameters should be used etc etc has not yet been determined, and is unwieldy regardless, and the functionality doesn't exist yet anyway, and may be years away still, if it even makes sense. BFN. Paul.
Re: i370 port
GCC relies on the libiberty "pex" family of routines, which are much more narrow in scope, and have in fact been ported to several non-UNIX systems, including even MS-DOS. Providing a port of "pex" to MVS should be much easier that porting a full Unix "system" or "fork" feature. Ok. But I don't even have much of system() yet. B.t.w. if you cannot execute sub-tasks at all, how does the MVS GCC invoke the preprocessor (I think this was still a separate process in 3.2) and the core compiler (cc1) from the compiler driver? Do you even have a separate compiler driver? Sleight of hand. :-) #ifdef SINGLE_EXECUTABLE int ret_code = 0; #endif 2836a2853,2872 #ifdef SINGLE_EXECUTABLE { int cnt = 0; while (commands[i].argv[cnt] != NULL) { cnt++; } if (strcmp(string, "cpp0") == 0) { ret_code = cpp(cnt, commands[i].argv); if (ret_code != 0) break; } else if (strcmp(string, "cc1") == 0) { ret_code = toplev_main(cnt, commands[i].argv); if (ret_code != 0) break; } } #else 2850c2886 < --- #endif 2853a2890,2892 #ifdef SINGLE_EXECUTABLE return (ret_code); BTW, here's what I am going with: C:\devel\gcc\gcc>cvs diff -r release-3_2_3 debug.c Index: debug.c === RCS file: c:\cvsroot/gcc/gcc/debug.c,v retrieving revision 1.1.1.1 diff -r1.1.1.1 debug.c 20a21,35 #include "output.h" #include "flags.h" static void debug_source_line (line, text) unsigned int line ATTRIBUTE_UNUSED; const char *text ATTRIBUTE_UNUSED; { if (flag_debug_asm) { app_enable(); fprintf(asm_out_file, "%s %d %s\n", ASM_COMMENT_START, line, text); app_disable(); } } 34c49 < debug_nothing_int_charstar, /* source_line */ --- debug_source_line, /* source_line */ Thanks again for everyone's assistance. Just need to find out who's emitting this warning: C:\devel\gcc\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CONFIG _H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include -d A world.c -g world.c:0: warning: `-g': unknown or unsupported -g option and it'll be a wrap. :-) There will be some very happy people who are currently manually putting in __asm__ lines to get insight. :-) BFN. Paul.
Re: i370 port
Hmm, it seems 3.2.x would *always* operate on a function-by-function basis. The unit-at-a-time mode was only introduced with 3.4 (I don't recall if it was already present in 3.3). I don't think there is any way in 3.2.3 to check whether there is a "main" function in the file before it is processed ... Ulrich, this comment got me thinking. If global optimization is not being done, then less of the source file would need to be in memory at the same time. How much memory do you think is required to process the largest GCC 3.2.3 source file (ie when self-compiling)? My experience is that fold-const.c requires 20 MB of memory (not including the size of the executable) to compile with -Os. That's the biggest. Is that typical/expected? Because it just occurred to me that maybe the lack of a "normal" implementation of alloca() is causing memory to not be released, and it's taking more space than it needs to. Thanks. Paul.
Re: i370 port
> That depends a bit on the compiler version and optimization level, > but (in particular in the 3.x time frame) GCC may output assembler > code on a function-by-function basis, without necessarily reading > in the whole source file first. Ok, actually it doesn't matter if it doesn't work all the time. I'll always be compiling with -Os anyway, so it sounds like I'm in with a chance of the whole file being read first? If so, where is my first opportunity, in 3.2.3, to see if there's a "main" function in this file? Hmm, it seems 3.2.x would *always* operate on a function-by-function basis. The unit-at-a-time mode was only introduced with 3.4 (I don't recall if it was already present in 3.3). I don't think there is any way in 3.2.3 to check whether there is a "main" function in the file before it is processed ... Does that mean I could take advantage of this behaviour? Currently I have this change: /* Store in OUTPUT a string (made with alloca) containing an assembler-name for a local static variable named NAME. LABELNO is an integer which is different for each call. */ #ifdef TARGET_PDPMAC #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) ^I^I\ {^I^I^I^I^I^I^I^I^I\ (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10);^I^I^I\ sprintf ((OUTPUT), "__%d", (LABELNO));^I^I^I^I\ } to give the static functions unique names within the file. However, it has the unfortunate side-effect that this code: #if defined(TARGET_DIGNUS) || defined(TARGET_PDPMAC) #define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL)^I^I^I\ {^I^I^I^I^I^I^I^I^I\ if (strlen (NAME) + 1 > mvs_function_name_length)^I^I^I\ {^I^I^I^I^I^I^I^I^I\ if (mvs_function_name)^I^I^I^I^I^I\ ^Ifree (mvs_function_name);^I^I^I^I^I\ mvs_function_name = 0;^I^I^I^I^I^I\ }^I^I^I^I^I^I^I^I^I\ if (!mvs_function_name)^I^I^I^I^I^I\ {^I^I^I^I^I^I^I^I^I\ mvs_function_name_length = strlen (NAME) * 2 + 1;^I^I^I\ mvs_function_name = (char *) xmalloc (mvs_function_name_length);^I\ }^I^I^I^I^I^I^I^I^I\ strcpy (mvs_function_name, NAME);^I^I^I^I^I\ mvs_need_to_globalize = 1;^I^I^I^I^I^I\ } #endif static void i370_output_function_prologue (f, l) FILE *f; HOST_WIDE_INT l; { /* Don't print stack and args in PDPMAC as it makes the comment too long */ #ifdef TARGET_PDPMAC fprintf (f, "* %c-func %s prologue\n", mvs_need_entry ? 'X' : 'S', mvs_function_name); #else is producing this output: * S-func __0 prologue @@0 PDPPRLG CINDEX=1,FRAME=88,BASER=12,ENTRY=NO B FEN1 LTORG FEN1 EQU * DROP 12 BALR 12,0 USING *,12 PG1 EQU * LR11,1 L 10,=A(PGT1) * Function __0 code * 46 world.c SLR 15,15 * Function __0 epilogue PDPEPIL * Function __0 literal pool DS0F LTORG * Function __0 page table DS0F PGT1 EQU * DCA(PG1) for this function: static int aaa(void) { return (0); } ie the "aaa" is being completely lost, being replaced by __0 everywhere. Ideally the __0 would be aaa everywhere, with just the @@0 remaining generated. Indeed, I have just made this change: C:\devel\gcc\gcc>cd config\i370 C:\devel\gcc\gcc\config\i370>cvs diff cvs diff: Diffing . Index: i370.c === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.c,v retrieving revision 1.34 diff -r1.34 i370.c 84a85,87 /* original name of a static variable */ char origmvsstatic[150]; 1457c1460cvs diff -c i370.h Index: i370.h === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.h,v retrieving revision 1.35 diff -c -r1.35 i370.h *** i370.h 18 Jul 2009 08:56:33 - 1.35 --- i370.h 20 Aug 2009 10:40:35 - *** *** 57,62 --- 57,63 /* The source file module. */ extern char *mvs_module; + extern char origmvsstatic[]; /* Compile using char instructions (mvc, nc, oc, xc). On 4341 use this since these are more than twice as fast as
Re: i370 port
> Hmm, it seems 3.2.x would *always* operate on a function-by-function > basis. The unit-at-a-time mode was only introduced with 3.4 (I don't > recall if it was already present in 3.3). I don't think there is any > way in 3.2.3 to check whether there is a "main" function in the file > before it is processed ... Does that mean I could take advantage of this behaviour? I don't think this would be a good idea. You're right. With your new change, I was able to see the difference, and I can see that the static functions sometimes get numbers assigned in a different order (I think first one called), and in that case, with my method the name ends up wrong, but yours works. * S-func dump_new_line prologue @@3 PDPPRLG CINDEX=4,FRAME=104,BASER=12,ENTRY=NO * Function dump_new_line code * Function dump_new_line epilogue PDPEPIL * Function dump_new_line literal pool DS0F LTORG * Function dump_new_line page table DS0F * S-func dump_maybe_newline prologue ( your new technique) @@2 PDPPRLG CINDEX=5,FRAME=104,BASER=12,ENTRY=NO B FEN5 L 10,=A(PGT5) * Function dump_new_line code (!! wrong name) /* Store in OUTPUT a string (made with alloca) containing an assembler-name for a local static variable named NAME. LABELNO is an integer which is different for each call. */ #ifdef TARGET_PDPMAC #define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \ { \ (OUTPUT) = (char *) alloca (strlen ((NAME)) + 10); \ sprintf ((OUTPUT), "__%d", (LABELNO)); \ } How does this work? ASM_FORMAT_PRIVATE_NAME is not supposed to completely ignore the NAME argument, the function may well be called with the same LABELNO but different NAME strings, and this must not result in conflicting symbols ... I have compiled the entire GCC and not come up with any duplicate static function names, so I think the number is always unique. static void i370_output_function_prologue (f, l) FILE *f; HOST_WIDE_INT l; { /* Don't print stack and args in PDPMAC as it makes the comment too long */ #ifdef TARGET_PDPMAC fprintf (f, "* %c-func %s prologue\n", mvs_need_entry ? 'X' : 'S', mvs_function_name); #else At this point, you may refer to "current_function_decl" to retrieve information about the function currently being output. In particular, you can retrieve the original source-level name associated with the routine via DECL_NAME (current_function_decl). Thanks a lot! I couldn't use that directly, but this: c:\devel\gcc\gcc\config\i370>cvs diff -r 1.37 i370.c Index: i370.c === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.c,v retrieving revision 1.37 retrieving revision 1.38 diff -r1.37 -r1.38 1457c1457
Re: i370 port
> How does this work? ASM_FORMAT_PRIVATE_NAME is not supposed > to completely ignore the NAME argument, the function may well > be called with the same LABELNO but different NAME strings, > and this must not result in conflicting symbols ... I have compiled the entire GCC and not come up with any duplicate static function names, so I think the number is always unique. Hmm, I see that in the 3.2.x code base this is indeed true. However, in later compilers ASM_FORMAT_PRIVATE_NAME is used for other purposes by the middle-end, not just static function or variable names. You definitely can get number collisions in later compilers ... Well I've compiled and linked all of 3.4.6 without getting name clashes either. > At this point, you may refer to "current_function_decl" to > retrieve information about the function currently being output. > In particular, you can retrieve the original source-level name > associated with the routine via DECL_NAME (current_function_decl). Thanks a lot! I couldn't use that directly, but this: Why not? It was missing the IDENTIFIER_POINTER so getting a compile error. printf ("%s", IDENTIFIER_POINTER (DECL_NAME (current_function_decl))); should work fine ... Yes, I've adopted that, thanks. Anyway, I've finally packaged all those changes discussed on the list, and also creditted you in the documentation for your assistance in polishing the product off. Details in announcement below. BFN. Paul. Jujitsu are pleased to announce the release of the following software: GCC 3.2.3 MVS 7.5 - GCC C compiler for z/OS, MVS/380, MVS/370. Delivered in xmit format. GCC 3.2.3 CMS 7.5 - GCC C compiler for z/VM, VM/380, VM/370. Delivered in vmarc format. PDPCLIB 2.00 - C (C90-compliant) runtime library for MVS (all flavours), CMS (all flavours), Windows 32, MSDOS, OS/2, Linux (new with this release), PDOS. Provided in source form only, but also delivered as part of GCCMVS and GCCCMS. Hercules/380 3.06 v6.0 - Used to run MVS/380. It now does S/380 even if you specify S/370, so that Hercgui will work. Now has native support for ftp-rdw files (ie files that have been transferred from z/OS using ftp with the RDW option), so that you can quickly get your files restored to a V dataset. Windows executables provided. Unix users need to compile from source. You can find the products at: http://gccmvs.sourceforge.net http://pdos.sourceforge.net http://mvs380.sourceforge.net (respectively). Initial documentation can be found in gccmvs.txt, pdpclib.txt and README.S380 respectively. Any comments/questions please post over at: http://tech.groups.yahoo.com/group/hercules-os380 where our complaint department is in operation 24 hours a day, even during Ramadan - may Allah have mercy on our souls. BFN. Paul.
Re: i370 port
I understand current GCC supports various source and target character sets a lot better out of the box, so it may be EBCDIC isn't even an issue any more. If there are other problems related to MVS host I think the EBCDIC support is largely theoretical and not tested on any actual EBCDIC host (or target). cpplib knows the character set name UTF-EBCDIC, but whenever it does anything internally that involves the encoding of its internal character set it uses UTF-8 rules (which is not something valid to do with UTF-EBCDIC). Results are finally in. EBCDIC (or arbitrary character set) support was introduced in 3.4.6, and continues to be the same today, correct? I've just succeeded today in getting gcc 3.4.6 to self-compile on an EBCDIC host. :-) That's after a gcc 3.4.6 ascii to ebcdic cross-compile. It's fascinating to look back at what it took. Note that there are still some relatively minor cleanups I have yet to do, but it won't change much. Caveats: 1. The generated (from machine definition) files are still generated on the PC. 2. I am unable to do an optimized compile even as a cross-compile, I get an internal error in this function: gcse.c: static void compute_hash_table_work (struct hash_table *table) { ... if (!current_bb) /* +++ why are we getting NULL here? */ { printf("internal error in gcse\n"); exit(EXIT_FAILURE); } FOR_EACH_BB (current_bb) and indeed, I can't see anything that would initialize that current_bb, so it's not that surprising that it's NULL! 3. As with gcc 3.2.3, the compiler is still producing slightly different results on the PC vs mainframe, probably still because of floating point comparisons being done to select the next register to use or something like that. 4. There is one thing that doesn't have proper ASCII to EBCDIC translation being done - the __FUNCTION__ builtin. So here is the code generated on the PC: COPY PDPTOP CSECT * Program text area @@V1 EQU * DCX'78' DCX'31' DCX'32' DCX'33' DCX'0' LC0 EQU * DCC'%s %d %s' DCX'15' DCX'0' LC1 EQU * DCC'zatest.c' DCX'0' DS0F * X-func x123 prologue X123 PDPPRLG CINDEX=0,FRAME=104,BASER=12,ENTRY=YES B FEN0 LTORG FEN0 EQU * DROP 12 BALR 12,0 USING *,12 PG0 EQU * LR11,1 L 10,=A(PGT0) * Function x123 code MVC 88(4,13),=A(LC0) MVC 92(4,13),=A(LC1) MVC 96(4,13),=F'5' MVC 100(4,13),=A(@@V1) LA1,88(,13) L 15,=V(PRINTF) BALR 14,15 * Function x123 epilogue PDPEPIL * Function x123 literal pool DS0F LTORG * Function x123 page table DS0F PGT0 EQU * DCA(PG0) END for this source: #include void x123(void) { printf("%s %d %s\n", __FILE__, __LINE__, __FUNCTION__); } However, that anomaly is not integral to getting the compiler on the mainframe, and once on the mainframe, the problem goes away with the next pass. :-) I think the problem is this function: c-decl.c: c_make_fname_decl (tree id, int type_dep) needs to call cpp_interpret_string or something like that to get converted into EBCDIC. There's not that much mainline code that needs to be changed. You can see for youself here: http://rapidshare.com/files/277287822/gccnew-beta51.zip The file is 250k compressed containing diffs, but most of them are simply the generated files (which appear as new). Here are the real file changes: diff -c gccnew/gcc/builtins.c:1.1.1.1 gccnew/gcc/builtins.c:1.3 diff -c gccnew/gcc/c-common.c:1.1.1.1 gccnew/gcc/c-common.c:1.2 diff -c gccnew/gcc/c-incpath.c:1.1.1.1 gccnew/gcc/c-incpath.c:1.3 diff -c gccnew/gcc/c-opts.c:1.1.1.1 gccnew/gcc/c-opts.c:1.2 diff -c gccnew/gcc/c-parse.c:1.1.1.1 gccnew/gcc/c-parse.c:1.5 diff -c gccnew/gcc/c-pch.c:1.1.1.1 gccnew/gcc/c-pch.c:1.3 diff -c gccnew/gcc/cppcharset.c:1.1.1.1 gccnew/gcc/cppcharset.c:1.6 diff -c gccnew/gcc/cpperror.c:1.1.1.1 gccnew/gcc/cpperror.c:1.2 diff -c gccnew/gcc/cppfiles.c:1.1.1.1 gccnew/gcc/cppfiles.c:1.7 diff -c gccnew/gcc/cpplib.h:1.1.1.1 gccnew/gcc/cpplib.h:1.2 diff -c gccnew/gcc/cppmacro.c:1.1.1.1 gccnew/gcc/cppmacro.c:1.2 diff -c gccnew/gcc/cppspec.c:1.1.1.1 gccnew/gcc/cppspec.c:1.3 diff -c gccnew/gcc/gcc.c:1.1.1.1 gccnew/gcc/gcc.c:1.6 diff -c gccnew/gcc/gcc.h:1.1.1.1 gccnew/gcc/gcc.h:1.2 diff -c gccnew/gcc/gcov-io.c:1.1.1.1 gccnew/gcc/gcov-io.c:1.2 diff -c gccnew/gcc/gcov-io.h:1.1.1.1 gccnew/gcc/gcov-io.h:1.2 diff -c gccnew/gcc/gcse.c:1.1.1.1 gccnew/gcc/gcse.c:1.3 diff -c gccnew/gcc/hwint.h:1.1.1.1 gccnew/gcc/hwint.h:1.2 diff -c gccnew/gcc/longlong.h:1.1.1.1 gccnew/gcc/longlong.h:1.2 diff -c gccnew/gcc/opts.c:1.1.1.1 gccnew/gcc/opts.c:1.2 diff -c gccnew/gcc/opts.h:1.1.1.1 gccnew/gcc/opts.h:1.3 diff -c gccnew/gcc/opts.sh:1.1.1.1 gccnew/gcc/opts.sh:1.1.1.2 diff -c gccnew
Re: i370 port
2. I am unable to do an optimized compile even as a cross-compile, I get an internal error in this function: gcse.c: static void compute_hash_table_work (struct hash_table *table) { ... if (!current_bb) /* +++ why are we getting NULL here? */ It appears I have misdiagnosed this. The code will handle NULL already. Taking that out though, exposes this internal error: int i370_branch_dest (branch) rtx branch; { rtx dest = SET_SRC (PATTERN (branch)); int dest_uid; int dest_addr; /* first, compute the estimated address of the branch target */ if (GET_CODE (dest) == IF_THEN_ELSE) dest = XEXP (dest, 1); dest = XEXP (dest, 0); /* +++ why is this becoming NULL? */ if (!dest) { printf("internal error in branch dest\n"); exit (0); } which is obviously specific to the i370 port. This code works fine on 3.2.3 though, so any idea what 3.4.6 changed to stop this from working? Thanks. Paul. dest_uid = INSN_UID (dest); dest_addr = INSN_ADDRESSES (dest_uid); /* next, record the address of this insn as the true addr of first ref */ { label_node_t *lp; rtx label = JUMP_LABEL (branch); int labelno = CODE_LABEL_NUMBER (label); if (!label || CODE_LABEL != GET_CODE (label)) abort (); lp = mvs_get_label (labelno); if (-1 == lp -> first_ref_page) lp->first_ref_page = mvs_page_num; just_referenced_page = lp->label_page; } return dest_addr; }
Re: i370 port - in search of hooks
I'm making quite good progress with cleaning up the 3.4.6 i370 port. I've even got optimization working to some degree. Meanwhile, on a different machine (a Linux machine I program on on the way to/from work), I have managed to build 4.4.0, which means I have an environment to work on a more modern version of GCC. That modern version is what I would like to ask about today. Leaving aside the issue of the actual target, I'm more interested in the intrusive hooks I expect I will need (I won't know until I start doing the work, and I can't do that until I find out whether 4.4 is good enough - chicken and egg). Here is what I needed for 3.4.6: 1. Ability to build a standalone executable. Simply put, I need gcc to do a function call like this: #ifdef SINGLE_EXECUTABLE { int cnt = 0; while (commands[i].argv[cnt] != NULL) { cnt++; } if (strcmp(string, "cc1") == 0) { ret_code = toplev_main(cnt, commands[i].argv); if (ret_code != 0) break; } } #else Doesn't need to be exactly like that, but some sort of hook to be made available so that I can bypass system() or any variation of that. C90 doesn't guarantee that system() will do anything in particular. And my C environment indeed doesn't work too well if you try that. Can't have two programs opening and closing the same DDNAME. Can only have 100 characters worth of parameters too. 2. A completely different way of handling include files. After going through the normal remap process, I then want the following transformations: #include "fred.h" gets translated into an fopen("dd:include(fred)", "r") #include gets translated into an fopen("dd:sysincl(fred)", "r") None of this checking to see if something is a directory etc. There's no such call available in C90, nor my C library on MVS. The code above looks trivial enough, but when it's time to actually find where to put that, it's non-trivial. 3. There is some complicated parameter lookup facility - it does a binary search on the parameters. This requires a whole lot of infrastructure to be present to generate the code. Infrastructure which I don't have. I'd like a simple sequential search to be available as an option I can activate. 4. There are a whole lot of includes that don't exist, like sys/types.h, and I'd like them to be masked out like all other includes are done (even things that are part of C90 have masks!!!). 5. It'd be cool if some of the names could be unique in the first 8 characters (C90 guarantees 6 for externals, but I have the luxury of 8). I have a mostly non-intrusive way of remapping everything, but there are a few that I need to do intrusively, because I can't #define away something that is already #defined. Problem is compounded by the fact that I link together code that normally isn't linked together. Note that I don't need things like an assembler and linker linked in together - I just need the stuff required for the "-S" option to work. ie text file (ie C code) in, and text file (ie assembler code) out - a text processing program that should be (and in fact, has already been made that way) possible to do in pure C90. 6. It would be nice if all the non-C90 Posix functions were masked out, but so far I have been able to kludge around that without requiring a lot of intrusive changes. It would be good to get the worst of them out though. My questions are: 1. Are changes like the above likely to be accepted into the head version going forward? 2. If they are, what version should I work on to get that to happen? Ideally I'd like to work on a stable version, perhaps 4.4, and later have those changes merged onto the head. But I fear if I do that I will end up in the same position I am in now with 3.4.6, ie too many changes such that my patches are never actually relevant. But it's quite daunting to get this working at all. So I thought that what I might be able to do instead is get the hooks in place first. Not necessarily all at once. Possibly over the course of a year. Eventually all the hooks will exist, there will be a stable release cut containing all the hooks I need, and then I may be in with a chance of getting i370 working on that environment. That would also be done over the course of a year or whatever, as the GMP and MPFR need to be set up on MVS too (just having a S/390 port is not sufficient - I need S/370 HLASM). Hopefully at the end of that process, I'll have an i370 port that is done in a "standard" way so that updating to the latest GCC is fairly trivial *regardless* of whether the i370 port is included in GCC proper due to the yet more technical challenges that requires, another job for another year. :-) This is a parallel effort to my 3.4.6 work which is done on a different PC at a different time. 3.4.6 is mostly about getting it to run on real MVS. 4.4/x is simply to get a cross-compile to work for now. Thanks. Paul.
Re: i370 port
It was dropped from GCC 4 when there was supposedly no maintainer available. Actually, Dave Pitts and myself were both maintaining it at that time, but we were both still working on an old version of it (3.2). So gcc 3.4.6, circa 2004, was the last time it was included in the normal GCC distribution. (For reference, the port was removed in SVN revision 77216; before then it had had various largely mechanical changes as part of changes to multiple back ends or target-independent code, with r69086 as the last vaguely i370-only change but no changes appearing to come from someone specifically working and testing on i370 for some years before then. "svn log svn://gcc.gnu.org/svn/gcc/trunk/gcc/config/i...@77215" shows the history.) I just took a look to see if there was anything changed on the head that didn't make it into 3.4.6. Short answer: no. Long answer: C:\devel\gccoff>diff gccnew gcchead Only in gcchead: .svn diff gccnew/i370.h gcchead/i370.h 530,531c530 < #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT, N_NAMED_ARGS) \ < ((CUM) = 0) --- #define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) ((CUM) = 0) I just need to delete that N_NAMED_ARGS when upgrading. I'm sure that will be the least of my worries though. I'm more worried about things like the below. :-) Incidentally, 15 years of effort to get a hosted GCC compiler on real MVS (not USS) came to realization on Jan 11, 2004: http://osdir.com/ml/emulators.hercules390.mvs/2004-01/msg00031.html (although it wasn't released until March 2004 when it was good enough to self-compile.) The revision that deleted i370 was made on Feb 4th, 2004. How's that for timing? Incidentally, while it may look from this angle like the i370 port wasn't being worked on, it's actually had a huge amount of effort put into it. The activity has just been in different forums (like the one above). It wasn't just GCC though. A lot of infrastructure was required. E.g. even the assembler didn't support such a huge number of externals that was being generated by GCC, so first I hacked around that in GCC itself, mapping a whole lot of "unused" flags to be the same, and then reversed that out when someone came up with a modification to the assembler. Then we needed to switch from 24-bit mode to 31-bit mode to get the required memory for GCC to self-compile. Another huge enterprise. I would encourage going through all the changes made to the i370 port on GCC mainline, after 3.1/3.2 branched and before the port was removed, to see what should be merged into your version for mainline; ultimately it would be up to you how you get it updated for all the mechanical changes on mainline since 3.2, but those changes (see command above to get logs) may be a useful guide to how to do some of the updates. All the merging has already been done in the 3.4.6 effort. The only thing that I know of that is still "at large" is someone else who was working "offline" and made some changes. Specifically this: http://osdir.com/ml/emulators.hercules390.mvs/2004-01/msg8.html as I just discovered the same problem with both of these strict moves now that I too am using 3.4.6. The i370.md looks correct to me (this is the movstricthi one): ;(define_insn "" ; [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) ; (match_operand:HI 1 "general_operand" "dSi"))] ; "" ; "* ;{ ; check_label_emit (); ; if (REG_P (operands[1])) ;{ ; mvs_check_page (0, 8, 0); ; return \"STH %1,\" CONVLO \"(,13)\;ICM %0,3,\" CONVLO \"(13)\"; ;} ; else if (GET_CODE (operands[1]) == CONST_INT) ;{ ; mvs_check_page (0, 4, 2); ; return \"ICM %0,3,%H1\"; ;} ; mvs_check_page (0, 4, 0); ; return \"ICM %0,3,%1\"; ;}" ; [(set_attr "length" "8")] ;) but I have had to comment it out, because otherwise I get code like this generated: L691 EQU * SLR 2,2 IC2,0(8) LA5,92(0,0) CLR 2,5 BEL699 BHL702 ICM 5,3,=H'64' BEL696 ICM 5,3,=H'78' BEL694 B L701 ie the LA and CLR combination are what I would expect, but gcc 3.4.6 has decided to use an ICM to move a constant in, which seems an awful waste to me instead of using LA, but the real problem is that it hasn't generated a CLR afterwards (it needs to compare against register 2), so isn't taking a branch it should be. I didn't have this problem in 3.2.3, which has a virtually identical machine definition. But I'd be really surprised to find a serious compiler bug outside of the i370 code?! I assume I'm just looking in the wrong spot. But at least I'm making progress. :-) BFN. Paul.
Re: i370 port
Therefore, the i370_branch_dest routine needs to handle those as well. Probably something along the following lines: if (GET_CODE (dest) == IF_THEN_ELSE) { if (GET_CODE (XEXP (dest, 1) == LABEL_REF) dest = XEXP (dest, 1); else dest = XEXP (dest, 2); } gcc_assert (GET_CODE (dest) == LABEL_REF); dest = XEXP (dest, 0); Hi Ulrich. Thanks for the reply. I didn't use gcc_assert because I didn't see it defined anywhere, but the rest of the fix worked fine. I have now reached the stage where I can (*) self-compile with optimization on (**). It takes 6 hours (***). :-) (*) I had to disable the MH (multiply halfword) instruction in order to get it to go through unfortunately. See below (+). (**) Except that c-common is being compiled with it off, because of a bug in the emulator I think, rather than GCC. (***) It would be closer to 4 hours if I didn't have to do two passes on the mainframe. I can't do that though until I can verify the integrity of the generated code. And I can't do that until I can get a fully optimized compile done, because otherwise the register selection changes slightly on PC vs mainframe causing slight differences in the one file being compiled without optimization, that prevents an automatic compare. (+) Can you spot anything wrong with this? Here is the error I get: C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include cppexp.c cppexp.c: In function `ZZZ_1148': cppexp.c:980: error: unable to generate reloads for: (insn 15 14 19 0 (set (reg:SI 4 4 [32]) (mult:SI (reg:SI 4 4 [30]) (const_int -858993459 [0xcccd]))) 52 {*i370.md:2585} (insn_list 12 (nil)) (expr_list:REG_DEAD (reg:SI 4 4 [30]) (nil))) cppexp.c:980: internal compiler error: in find_reloads, at reload.c:3690 Please submit a full bug report, with preprocessed source if appropriate. See http://gccmvs.sourceforge.net> for instructions. I can bypass this error by commenting out the MH pattern, and the code that would normally invoke it. Note that I didn't write that "XXX trouble" stuff, and I don't know if it is still relevant. ; ; mulsi3 instruction pattern(s). ; (define_expand "mulsi3" [(set (match_operand:SI 0 "general_operand" "") (mult:SI (match_operand:SI 1 "general_operand" "") (match_operand:SI 2 "general_operand" "")))] "" " { /*if (GET_CODE (operands[1]) == CONST_INT && REG_P (operands[0]) && CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'K')) { emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_MULT (SImode, operands[2], operands[1]))); } else if (GET_CODE (operands[2]) == CONST_INT && REG_P (operands[0]) && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')) { emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_MULT (SImode, operands[1], operands[2]))); } else */ { rtx r = gen_reg_rtx (DImode); /* XXX trouble. Below we generate some rtx's that model what * is really supposed to happen with multiply on the 370/390 * hardware, and that is all well & good. However, during optimization * it can happen that the two operands are exchanged (after all, * multiplication is commutitive), in which case the doubleword * ends up in memory and everything is hosed. The gen_reg_rtx * should have kept it in a reg ... We hack around this * below, in the M/MR isntruction pattern, and constrain it to * \"di\" instead of \"g\". But this still ends up with lots & lots of * movement between registers & memory and is an awful waste. * Dunno how to untwist it elegantly; but it seems to work for now. */ if (GET_CODE (operands[1]) == CONST_INT) { emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)), operands[1])); emit_insn (gen_rtx_SET (VOIDmode, r, gen_rtx_MULT (DImode, r, operands[2]))); } else { emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode)), operands[2])); emit_insn (gen_rtx_SET (VOIDmode, r, gen_rtx_MULT (DImode, r, operands[1]))); } emit_insn (gen_rtx_SET (VOIDmode, operands[0], gen_rtx_SUBREG (SImode, r, GET_MODE_SIZE (SImode; } DONE; }") ;(define_insn "" ; [(set (match_operand:SI 0 "register_operand" "=d") ; (mult:SI (match_operand:SI 1 "register_operand" "0") ;(match_operand:SI 2 "immediate_operand" "K")))] ; "" ; "* ;{ ; check_label_emit (); ; mvs_check_page (0, 4, 0); ; return \"MH %0,%H2\"; ;}" ; [(set_attr "length" "4")] ;) ; See mulsi3 comment above
Re: i370 port
Hi Ulrich. Good news is that I have now gotten GCC 3.4.6 to recompile itself with full optimization on. The compilation time on the (emulated) mainframe is only 2.5 hours as only a single pass is required. GCC 3.4.6 requires 49 MB to recompile c-common! I assume with GCC 3.4.6 it is doing global optimization or something. It was only 20 MB under 3.2.3. Anyway, I'm still continuing the cleanup, but now have a strong fallback position. Basically I won't introduce any machine definition change that causes the self-compile to fail. ;(define_insn "" ; [(set (match_operand:SI 0 "register_operand" "=d") ; (mult:SI (match_operand:SI 1 "register_operand" "0") ;(match_operand:SI 2 "immediate_operand" "K")))] ; "" ; "* ;{ ; check_label_emit (); ; mvs_check_page (0, 4, 0); ; return \"MH %0,%H2\"; ;}" ; [(set_attr "length" "4")] ;) The combination of predicates and constraints on this insn is broken. Before reload, the predicate "immediate_operand" explicitly allows *any* SImode immediate value. However, during reload, the "K" constraint accepts only a subset of values. Is there a way to give a predicate that just says "look at the constraint"? It seems a bit overkill to add a new predicate for this one instruction. As there is no other alternative, No other alternative for this same pattern, right? There was an alternative - the pattern that I explictly asked it to use, since I'd already done the K check in advance. and the insn supports neither memory nor register operands, this is impossible for reload to fix up. Hmmm. I was wondering whether I could put a memory operand there, if that means it can fix it up regardless. But that would give it the idea that it can put a fullword there, when a halfword operand is required, right? In addition, I don't quite understand how this pattern works in the first place; MH requires a memory operand, but this pattern seems to output an immediate value as operand. Is there some magic going on in your assembler? %H2 is ... ;; Special formats used for outputting 370 instructions. ;; ;; %H -- Print a signed 16-bit constant. in the i370.md documentation which can be seen here: http://gcc.gnu.org/viewcvs/trunk/gcc/config/i370/i370.md?revision=71850&view=markup&pathrev=77215 (there's not a lot of technical changes since then, mainly because no-one knew how to make them). If you indeed want to output immediate values here, you should As opposed to wanting what? All I want is the MH instruction to be available for use, so that when someone writes x = x * 5, it doesn't have to organize a register pair. probably define a new *predicate* that constrains the set of allowed values even before reload. Ok, that should be straightforward if that's the best solution. In the s390 port, we're instead modelling the MH instruction with a memory operand (this still allows the generic parts of GCC to push immediate operands into memory, if they are in range for an HImode operand): (define_insn "*mulsi3_sign" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R")) (match_operand:SI 1 "register_operand" "0")))] "" "mh\t%0,%2" [(set_attr "op_type" "RX") (set_attr "type" "imul")]) I tried a lot of variations to try to get this to fit into the i370 scheme, but didn't have any luck. e.g. I managed to make this: (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "g")) (match_operand:SI 1 "register_operand" "0")))] "" "* { check_label_emit (); mvs_check_page (0, 4, 0); return \"MH^I%0,%2\"; }" [(set_attr "length" "4")] ) produce: C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include cfgloopanal.c cfgloopanal.c: In function `average_num_loop_insns': cfgloopanal.c:1379: error: unrecognizable insn: (insn 68 67 71 7 (set (reg:SI 45) (mult:SI (reg:SI 44 [ .frequency ]) (const_int 1 [0x2710]))) -1 (insn_list 67 (nil)) (expr_list:REG_DEAD (reg:SI 44 [ .frequency ]) (nil))) This also seems broken. A MULT:DI must have two DImode operands, it cannot have one DImode and one SImode operand. Also, it is in fact incorrect that it takes the full DImode first operand; rather, it only uses the low 32-bit of its first operand as input. Ok. In the s390 port we're modelling the real behavior of the instruction using two explicit SIGN_EXTEND codes: (define_insn "mulsidi3" [(set (match_operand:DI 0 "register_operand" "=d,d") (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0,0")) (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,R"] Ok. That certainly looks better. Well, the point of optimization
Re: i370 port
> The combination of predicates and constraints on this insn is broken. > > Before reload, the predicate "immediate_operand" explicitly allows > *any* SImode immediate value. However, during reload, the "K" > constraint accepts only a subset of values. Is there a way to give a predicate that just says "look at the constraint"? Not that I'm aware of. This below was what I was hoping for ... It seems a bit overkill to add a new predicate for this one instruction. As an alternative to the operand predicate, you might also add an extra check to the insn condition. For example, something along the following lines should work: (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "const_int_operand" "K")))] "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" My eyes lit up when I saw that! However, it produced a compiler error when I tried it. But undeterred, I tried this: (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") ^I(mult:SI (match_operand:SI 1 "register_operand" "0") ^I^I (match_operand:SI 2 "immediate_operand" "K")))] "(GET_CODE (operands[2]) == CONST_INT && REG_P (operands[0]) && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" "* { check_label_emit (); mvs_check_page (0, 4, 0); return \"MH^I%0,%H2\"; }" [(set_attr "length" "4")] ) And it worked (verified by self-compile)! And I relaxed the constraint on the "M" instruction as well. Those old warnings are apparently irrelevant now. Thank you sir. :-) My point was that the MH instruction on an instruction set architecture level *does not accept* an immediate operand, but only a memory operand: MH R1,D2(X2,B2) [RX] (There is a MULTIPLY HALFWORD IMMEDIATE (MHI) instruction as well, but I'm assuming you don't want to use it in the i370 port as that instruction was added later on.) Oh, I understand now. So the usual way of using MH to multiply by an immediate value is to place the constant into memory, typically some form of literal pool. But I see nothing in the i370 port that would actually do that; instead, you seem to simply output the immediate value itself into the assembler source. Right, with an "=". If this works, it seems that the assembler will under the covers manage a literal pool. I was simply wondering if this is indeed what you're relying on ... Yes indeed. And we go to a lot of effort to maintain the length of that literal pool, so we know when we need to break out into a new page. That's what this does: mvs_check_page (0, 4, 0); Although, as usual, it's broken. Needs to be (0, 4, 2) for the 4-byte instruction followed by the 2 bytes it will use from the literal pool. (In the s390 port, the compiler will always manage literal pools completely on its own and does never rely on any assembler magic in that area.) I see. That explains one of the difficulties of trying to get s390 instruction definitions and use them on i370. People keep asking why I don't "just" use the s390 ones. If only life were that simple. :-) Well, in this case someone has to push the constant into a literal pool. You can either do this at expand time by calling force_const_mem, or else you have to change the predicate to also accept immediates before reload (then reload will do the force_const_mem for you). (Note that if you in fact do not manage a literal pool in the compiler today but rely on the assembler, as discussed above, this whole approach may be difficult.) That's putting it mildly. :-) Anyway, with that out of the way, I'll take a look at the next one. There's only one bug remaining that I know of, and 3 workarounds that I would like to reverse out and fix properly. BFN. Paul.
Re: i370 port
> As an alternative to the operand predicate, you might also add > an extra check to the insn condition. For example, something > along the following lines should work: > > (define_insn "" > [(set (match_operand:SI 0 "register_operand" "=d") > (mult:SI (match_operand:SI 1 "register_operand" "0") > (match_operand:SI 2 "const_int_operand" "K")))] > "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" My eyes lit up when I saw that! However, it produced a compiler error when I tried it. But undeterred, I tried this: Sorry. I just copied the last line into the existing pattern, didn't notice that you'd changed the predicate too. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (mult:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "K")))] "(GET_CODE (operands[2]) == CONST_INT && REG_P (operands[0]) && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" Huh. Instead of adding an explicit CONST_INT check, my approach above used a const_int_operand predicate (instead of immediate_operand). That should have had the exact same effect ... I'm not sure why the REG_P check on the other operand would be necessary at this point. I just copied that from the existing condition too. Once I realised that I could put a check in advance, I just copied the check across basically. I'd seen that before, it just hadn't sunk in that I could use it for this situation. I will try out your original suggestion again properly. :-) And it worked (verified by self-compile)! And I relaxed the constraint on the "M" instruction as well. Those old warnings are apparently irrelevant now. Thank you sir. :-) OK, that's good to know. Indeed. And as I mentioned, there's just one real bug that I know of left. I can bypass the bug in the GCC code that I am compiling, by forcing a function call. C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include varasm.c varasm.c: In function `force_const_mem': varasm.c:3021: internal compiler error: in instantiate_virtual_regs_lossage, at function.c:3765 Please submit a full bug report, with preprocessed source if appropriate. See http://gccmvs.sourceforge.net> for instructions. This is the code that is triggering off that bug: force_const_mem (enum machine_mode mode, rtx x) { int hash; struct constant_descriptor_rtx *desc; ... if (compare_constant_rtx (mode, x, desc)) static int compare_constant_rtx (enum machine_mode mode, rtx x, ^I^I struct constant_descriptor_rtx *desc) { struct rtx_const value; decode_rtx_const (mode, x, &value); /* Compare constant contents. */ #if defined(XTARGET_MVS) /* +++ seems we have a machine definition problem */ return (memcmp) (&value, &desc->value, sizeof (struct rtx_const)) == 0; #else return memcmp (&value, &desc->value, sizeof (struct rtx_const)) == 0; #endif } You can see how I normally work around this problem by forcing a function call. If I do that force, then I get this code generated: L445 EQU * LTR 3,3 BEL442 MVC 88(4,13),0(11) MVC 92(4,13),4(11) LA2,560(,13) ST2,96(13) LA1,88(,13) L 15,=A(@@F17) BALR 14,15 ST2,88(13) LR2,3 A 2,=F'8' ST2,92(13) MVC 96(4,13),=F'196' LA1,88(,13) L 15,=V(MEMCMP) BALR 14,15 LTR 15,15 which is bizarre. It seems to be comparing two values that are 8 bytes apart, for a length of 196. Can't imagine that doing anything useful. It's almost certainly an i370 port bug, but I haven't had any bright ideas on how to fix that yet. :-) BFN. Paul.
Re: i370 port
That's a bit hard to diagnose without some further information ... What insn it is failing on? (To find out, use a debugger, or maybe add a "debug_rtx (insn)" statement before the abort in instantiate_virtual_regs_lossage)? I did the latter. C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include varasm.c (insn 117 429 118 7 (parallel [ (set (reg:SI 64) (compare:SI (mem/s:BLK (plus:SI (reg/f:SI 21 virtual-stack-vars) (const_int 456 [0x1c8])) [232 value+0 S196 A64]) (mem:BLK (plus:SI (reg/v/f:SI 61 [ desc ]) (const_int 8 [0x8])) [0 A8]))) (use (const_int 196 [0xc4])) ]) -1 (nil) (nil)) varasm.c: In function `force_const_mem': varasm.c:3021: internal compiler error: in instantiate_virtual_regs_lossage, at function.c:3767 Please submit a full bug report, with preprocessed source if appropriate. See http://gccmvs.sourceforge.net> for instructions. Which would seem to correspond to this: ; Compare a block that is less than 256 bytes in length. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") ^I(compare:SI (match_operand:BLK 1 "s_operand" "m") ^I^I (match_operand:BLK 2 "s_operand" "m"))) (use (match_operand:QI 3 "immediate_operand" "I"))] "((unsigned) INTVAL (operands[3]) < 256)" "* { check_label_emit (); mvs_check_page (0, 22, 0); return \"CLC^I%O1(%c3,%R1),%2\;BH^I*+12\;BL^I*+6\;SLR^I%0,%0\;LNR^I%0,%0\"; }" [(set_attr "length" "22")] ) This is conceivably another effect of the same bug, but again it's hard to say. You'd have to look at the generated RTX and see how it changes over the various optimization stages (use -da to generate RTX dumps after each stage). Ok, I'll see if I can see something. Probably easier for me to play around with the md though. BFN. Paul.
Re: i370 port
C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include varasm.c (insn 117 429 118 7 (parallel [ (set (reg:SI 64) (compare:SI (mem/s:BLK (plus:SI (reg/f:SI 21 virtual-stack-vars) (const_int 456 [0x1c8])) [232 value+0 S196 A64]) (mem:BLK (plus:SI (reg/v/f:SI 61 [ desc ]) (const_int 8 [0x8])) [0 A8]))) (use (const_int 196 [0xc4])) ]) -1 (nil) (nil)) varasm.c: In function `force_const_mem': varasm.c:3021: internal compiler error: in instantiate_virtual_regs_lossage, at function.c:3767 OK, so what goes on here is that GCC attempts to replace the "virtual" register 21 (virtual-stack-vars) with some real register, that is frame pointer + STARTING_FRAME_OFFSET. It seems for the i370 port, this should resolve to register 13 + STACK_POINTER_OFFSET + current_function_outgoing_args_size Overall, the middle-end would therefore replace "reg 21 + 456" with "reg 13 + X", where X is constant computed from 456 + STACK_POINTER_OFFSET + current_function_outgoing_args_size. It will then re-process the insn pattern constraints to verify that the resulting insn is still valid. At this stage, it appears we're running into the above error. I'm not quite sure why this would be case, this will require some further debugging why the insn was not recognized ... Ok, I spent today trying to solve this problem. Although I didn't succeed in solving it properly, I did at least find a workaround for the one instance. I found that in the failing circumstance, neither of the two things being compared fell into the "force copy" situation. I don't know whether that is right or wrong, but at least I can detect whether a "force copy" was done. If no force copy was done, I stop doing the short CLC and let it do the CLCL instead. See below where I have introduced the "copy" variable. Unfortunately it affects other things, ie good CLCs have been converted into CLCL also, which is a shame. However, it may at least mean the compiler doesn't have a bug as far as the end user is concerned, ie it generates valid code. I have a theory that if both displacements in the S-type (ie register plus displacement) address are non-zero, that something fails. So the next thing I will do is see if I can detect just that situation, and stop it going into the CLC. Some of these md constructs are beginning to make more sense. :-) BFN. Paul. ; ; cmpmemsi instruction pattern(s). ; (define_expand "cmpmemsi" [(set (match_operand:SI 0 "general_operand" "") (compare (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) (use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 4 "" ""))] "" " { rtx op1, op2; int copy = 0; op1 = XEXP (operands[1], 0); if (GET_CODE (op1) == REG || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG && GET_CODE (XEXP (op1, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op1, 1)) < 4096)) { op1 = operands[1]; } else { op1 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op1)); copy = 1; } op2 = XEXP (operands[2], 0); if (GET_CODE (op2) == REG || (GET_CODE (op2) == PLUS && GET_CODE (XEXP (op2, 0)) == REG && GET_CODE (XEXP (op2, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op2, 1)) < 4096)) { op2 = operands[2]; } else { op2 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op2)); copy = 1; } /* so long as at least one operand was copied, this seems safe */ if (copy && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256) { emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, operands[0], gen_rtx_COMPARE (SImode, op1, op2)), /* was VOIDmode */ gen_rtx_USE (VOIDmode, operands[3]; } else { /* implementation suggested by Richard Henderson */ rtx reg1 = gen_reg_rtx (DImode); rtx reg2 = gen_reg_rtx (DImode); rtx result = operands[0]; rtx mem1 = operands[1]; rtx mem2 = operands[2]; rtx len = operands[3]; if (!CONSTANT_P (len)) len = force_reg (SImode, len); /* Load up the address+length pairs. */ emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), force_operand (XEXP (mem1, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), force_operand (XEXP (mem2, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); /* Compare! */ emit_insn (gen_cmpmemsi_1 (result, reg1, reg2));
Re: i370 port
I have a theory that if both displacements in the S-type (ie register plus displacement) address are non-zero, that something fails. So the next thing I will do is see if I can detect just that situation, and stop it going into the CLC. I now have that detection in place, and done a self-compile, and all is looking great. No idea if that is producing a technically correct compiler or not though (ie whether my workaround correctly bypasses all circumstances). So that leaves 2 more workarounds which I would like to reverse out. I'll spend some time on them next. BFN. Paul. ; ; cmpmemsi instruction pattern(s). ; (define_expand "cmpmemsi" [(set (match_operand:SI 0 "general_operand" "") (compare (match_operand:BLK 1 "general_operand" "") (match_operand:BLK 2 "general_operand" ""))) (use (match_operand:SI 3 "general_operand" "")) (use (match_operand:SI 4 "" ""))] "" " { rtx op1, op2; int iv1 = 0; int iv2 = 0; op1 = XEXP (operands[1], 0); if (GET_CODE (op1) == REG || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG && GET_CODE (XEXP (op1, 1)) == CONST_INT && (unsigned) (iv1 = INTVAL (XEXP (op1, 1))) < 4096)) { op1 = operands[1]; } else { op1 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op1)); } op2 = XEXP (operands[2], 0); if (GET_CODE (op2) == REG || (GET_CODE (op2) == PLUS && GET_CODE (XEXP (op2, 0)) == REG && GET_CODE (XEXP (op2, 1)) == CONST_INT && (unsigned) (iv2 = INTVAL (XEXP (op2, 1))) < 4096)) { op2 = operands[2]; } else { op2 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op2)); } /* one circumstance has been found where this short comparison causes an internal error. Could be related to the fact that both displacements were non-zero, which is unusual. So check for that */ if (((iv1 == 0) || (iv2 == 0)) && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256) { emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, operands[0], gen_rtx_COMPARE (SImode, op1, op2)), /* was VOIDmode */ gen_rtx_USE (VOIDmode, operands[3]; } else { /* implementation suggested by Richard Henderson */ rtx reg1 = gen_reg_rtx (DImode); rtx reg2 = gen_reg_rtx (DImode); rtx result = operands[0]; rtx mem1 = operands[1]; rtx mem2 = operands[2]; rtx len = operands[3]; if (!CONSTANT_P (len)) len = force_reg (SImode, len); /* Load up the address+length pairs. */ emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), force_operand (XEXP (mem1, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), force_operand (XEXP (mem2, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); /* Compare! */ emit_insn (gen_cmpmemsi_1 (result, reg1, reg2)); } DONE; }") ; Compare a block that is less than 256 bytes in length. (define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (compare:SI (match_operand:BLK 1 "s_operand" "m") (match_operand:BLK 2 "s_operand" "m"))) (use (match_operand:QI 3 "immediate_operand" "I"))] "((unsigned) INTVAL (operands[3]) < 256)" "* { check_label_emit (); mvs_check_page (0, 22, 0); return \"CLC %O1(%c3,%R1),%2\;BH *+12\;BL *+6\;SLR %0,%0\;LNR %0,%0\"; }" [(set_attr "length" "22")] ) ; Compare a block that is larger than 255 bytes in length. ;(mem:BLK (subreg:SI (match_operand:DI 1 "register_operand" "+d") 0)) ;(mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "+d") 0 (define_insn "cmpmemsi_1" [(set (match_operand:SI 0 "register_operand" "+d") (compare:SI (mem:BLK (match_operand:DI 1 "register_operand" "+d") ) (mem:BLK (match_operand:DI 2 "register_operand" "+d") ))) (use (match_dup 1)) (use (match_dup 2)) (clobber (match_dup 1)) (clobber (match_dup 2))] "" "* { check_label_emit (); mvs_check_page (0, 18, 0); return \"LA %0,1(0,0)\;CLCL %1,%2\;BH *+12\;BL *+6\;SLR %0,%0\;LNR %0,%0\"; }" [(set_attr "length" "18")] )
Re: i370 port
Ulrich, here's one of the workarounds I mentioned. The other one is pretty similar to this one as well. After my investigation, I've come to the conclusion that this never worked, and was not noticed before, because the optimizer mustn't have ever used it before. As such, it's appropriate to simply comment it out (which was my "workaround"). However, before I do so, do you think this is close to being correct? I already made one correction, to put in that XL1 rather than doing a fullword (which was always zero obviously). (define_insn "movstrictqi" [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d")) (match_operand:QI 1 "general_operand" "g"))] "" "* { check_label_emit (); if (REG_P (operands[1])) { mvs_check_page (0, 8, 0); return \"STC^I%1,\" CONVLO \"(,13)\;IC^I%0,\" CONVLO \"(,13)\"; } mvs_check_page (0, 4, 0); return \"IC^I%0,=XL1'%X1'\"; }" [(set_attr "length" "8")] ) The trouble is that when the instruction is active, things like this happen: C:\devel\gccnew\gcc>diff -c6 old\alias.s new\alias.s | head -50 *** old\alias.s Tue Sep 22 09:37:45 2009 --- new\alias.s Fri Sep 25 16:38:31 2009 *** *** 277,290 L26 EQU * N 2,=XL4'00FF' LA3,242(0,0) CR2,3 BEL30 BHL45 ! LA3,241(0,0) ! CLR 2,3 BEL28 B L44 L45 EQU * LA3,243(0,0) CLR 2,3 BEL37 --- 277,289 L26 EQU * N 2,=XL4'00FF' LA3,242(0,0) CR2,3 BEL30 BHL45 ! IC3,=XL1'F1' BEL28 B L44 L45 EQU * LA3,243(0,0) CLR 2,3 BEL37 Which I can clearly see is different. Specifically, the IC by itself is fine, although I would have preferred to see the LA instruction there, but for some reason it is dropping the CLR. That makes it technically incorrect. I checked the S/370 reference summary, and IC doesn't set the condition code, and nor does the instruction pattern mention condition codes anywhere. Normally I would be suspicious of the rest of the compiler, but in this case, I know that the compiler is stable and the i370 target is dubious. :-) After resolution of this one way or another, I think it's in a good enough state for version 1.0 and will start on the preparations for all that. BFN. Paul.
i370 port - constructing compile script
What is the best way to go from this: Makefile: C_AND_OBJC_OBJS = attribs.o c-errors.o c-lex.o c-pragma.o c-decl.o c-typeck.o \ c-convert.o c-aux-info.o c-common.o c-opts.o c-format.o c-semantics.o \ C_OBJS = c-lang.o stub-objc.o $(C_AND_OBJC_OBJS) OBJS-common = \ ^Iinsn-attrtab.o \ ^Iinsn-automata.o \ ^Iinsn-emit.o \ ^Iinsn-extract.o \ to: call stdcomp alias.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp alloc-pool.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp attribs.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp bb-reorder.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp bitmap.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp bt-load.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp builtins.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp caller-save.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp calls.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp c-aux-info.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp c-common.c %1 %2 %3 %4 %5 %6 %7 %8 %9 and then finally to: //ALIASEXEC ST2CMP,MEMBER=ALIAS //al...@po EXEC ST2CMP,member=al...@po //ATTRIBS EXEC ST2CMP,MEMBER=ATTRIBS //b...@reord EXEC ST2CMP,member...@reord //BITMAP EXEC ST2CMP,MEMBER=BITMAP //b...@load EXEC ST2CMP,member...@load //BUILTINS EXEC ST2CMP,MEMBER=BUILTINS //cal...@s EXEC ST2CMP,member=cal...@s //CALLSEXEC ST2CMP,MEMBER=CALLS //c...@aux@IN EXEC ST2CMP,membe...@aux@IN //c...@common EXEC ST2CMP,membe...@common I am happy to construct all of this on a Unix system with the various tools (m4 etc) available. But from the Unix system, I need to be able to generate the above very simple compile script, which is a precursor to creating very simple JCL steps (trust me, you don't want to see what ST2CMP looks like). Note that the JCL has the filenames truncated to 8 characters, listed twice, uppercased, and '-' and '_' converted to '@'. I assume I need a C program to do such a conversion. I'm happy to write that C program. But what's the best way to work with the existing infrastructure when writing and running that C program? One idea I had was to have a target that listed all the variables, and then just had an "echo" as the rule to make the ".o" from ".c", and then I could just go "make" to get all the object files listed out, and then I run a separate C program to convert that into the various scripts. Note that the objective is to basically get a list (in the above format) of all necessary C source in order to be able to compile (to assembler, not .o) C programs. I will be building a single executable, ie combining the C front end and i370 back end into a single executable. I know that it is possible, because I already have it working (on 3.4.6). Now the objective is to do it properly. :-) Also note that I'm not 100% sure what variables to use to get the minimum required source, although I would guess GCC_OBJS, C_OBJS plus the individual files listed in ALL_HOST_OBJS. This would be something that would be good to have an explicit variable for - the minimum C files required in the process of converting C to assembler (even though in normal configurations, those C files reside in different executables). So I would like to define such a variable prior to doing the above. Thanks. Paul. P.S. Here are the (intrusive) changes I have had to make so far to get (maybe 3/4 of) GCC 4.4 to compile on a C90-only platform: Index: gcc/system.h === RCS file: /cvsroot/gcc4/gcc/system.h,v retrieving revision 1.1.1.1 diff -r1.1.1.1 system.h 180a181 #ifdef HAVE_SYS_TYPES_H 181a183 #endif Index: include/sort.h === RCS file: /cvsroot/gcc4/include/sort.h,v retrieving revision 1.1.1.1 diff -r1.1.1.1 sort.h 24a25 #ifdef HAVE_SYS_TYPES_H 25a27 #endif Index: libcpp/include/cpplib.h === RCS file: /cvsroot/gcc4/libcpp/include/cpplib.h,v retrieving revision 1.1.1.1 diff -r1.1.1.1 cpplib.h 26a27 #ifdef HAVE_SYS_TYPES_H 27a29,30 #endif 542,543c545,546 < ino_t ino; < dev_t dev; --- /* ino_t ino; */ /* dev_t dev; */ Index: libiberty/xmemdup.c === RCS file: /cvsroot/gcc4/libiberty/xmemdup.c,v retrieving revision 1.1.1.1 diff -r1.1.1.1 xmemdup.c 23a24 #ifdef HAVE_SYS_TYPES_H 24a26 #endif Index: libiberty/xstrdup.c === RCS file: /cvsroot/gcc4/libiberty/xstrdup.c,v retrieving revision 1.1.1.1 diff -r1.1.1.1 xstrdup.c 18a19 #ifdef HAVE_SYS_TYPES_H 19a21 #endif ie very little. Not sure what the proper way to deal with that ino_t and dev_t is, but in the past I've simply created my own typedefs: typedef int ino_t; typedef int dev_t; and included them in config.h But I'll deal with that after I've got a comprehensive list of source files.
Re: i370 port - constructing compile script
What is the best way to go from this: Makefile: The easy way to convert a Makefile to a shell script is "make -n". That will print out all of the commands that make would run. From there it's a Mere Matter of Programming to have perl (or whatever) edit that down into your JCL scripts. Hi Richard. Thanks for your reply. 1. That would include a lot of irrelevant commands - compiles and links of the generator files interspersed with what I actually need to go into the stage 1 executable on the target machine. Maybe a variable STAGE1_OBJS would be suitable? 2. If the normal way to do things is to parse the make -n output with perl etc, that's fine, I'll do it that way. I was just wondering if the proper way was to incorporate the logic into a Makefile rule and get that rule repeatedly executed rather than just having a simple "echo". It seems to me that having a generic rule to execute an external script would be neater??? BTW, I remember your name from the i370 md. Why were you interested in i370 at the time (probably many years ago)? Or was someone else just asking a public question and you answered it (like now)? BFN. Paul. else { /* implementation suggested by Richard Henderson */ rtx reg1 = gen_reg_rtx (DImode); rtx reg2 = gen_reg_rtx (DImode); rtx result = operands[0]; rtx mem1 = operands[1]; rtx mem2 = operands[2]; rtx len = operands[3]; if (!CONSTANT_P (len)) len = force_reg (SImode, len); /* Load up the address+length pairs. */ emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), force_operand (XEXP (mem1, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), force_operand (XEXP (mem2, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), /* Compare! */ emit_insn (gen_cmpmemsi_1 (result, reg1, reg2)); } DONE; }")
Re: i370 port - constructing compile script
> 2. If the normal way to do things is to parse the make -n output > with perl etc, that's fine, I'll do it that way. I was just wondering > if the proper way was to incorporate the logic into a Makefile > rule and get that rule repeatedly executed rather than just > having a simple "echo". It seems to me that having a generic > rule to execute an external script would be neater??? I'm not sure what you are suggesting here, but I do know that it wouldn't make sense for us to change the gcc Makefile to use a rule which executes an external script. I didn't mean use by default. The "normal way to do things" is to use GNU make. I think you are the first person trying to build gcc without it. It's also the first native MVS port. Anyway, since then I had another idea. I should be able to achieve the same thing by just changing the C compiler to be "echo" or the external script replacement. Then all I need is a consolidated stage 1 target. But today I spent my time fighting a different battle. I tried to get configure to use my provided minimal (ie all of C90, but no extensions) header files, using the --with-root option and --with-build-root. But it seemed to ignore those and use the ones on my Linux box, insisting that sys/types existed etc. Maybe I need to change my INCLUDE_PATH or something instead. Not the first - BSDs have been known to import GCC sources into their repositories and write their own build system using BSD make. No doubt this is a lot of work that needs repeating for each new version imported - that's the price you pay if you don't want to use the normal GCC build system. (And GCC didn't always require GNU make - but the BSDs replacing the build system are a much closer analogy here than ordinary builds of old versions with other make implementations before GNU make was required.) Yeah, make isn't available (environment variables aren't available in batch either), and even if it was, that's not what people want. People want SMP/E in fact. But I don't know SMP/E. I only know JCL, which is the normal (and much much simpler) rival for SMP. I don't think that doing a glorified "make -n" is a radical change to the existing methodology. Nor is a make target that just lists all the stage 1 object files. I think it would be a neat addition (even if it remains a patch forever). BFN. Paul.
Re: i370 port - constructing compile script
I am happy to construct all of this on a Unix system with the various tools (m4 etc) available. But from the Unix system, I need to be able to generate the above very simple compile script, which is a precursor to creating very simple JCL steps (trust me, you don't want to see what ST2CMP looks like). Note that the JCL has the filenames truncated to 8 characters, listed twice, uppercased, and '-' and '_' converted to '@'. Have you considered the obvious solution: Don't do that? i.e. use a cross compiler from a sane system. If you really want to a native compiler than I still suggest building it as a canadian cross. That's what this is. Or at least, replace ST2CMP with ST1CMP and it is the Canadian Cross. ST1CMP will run the assemblies using HLASM. Almost identical JCL will run a compile, then an assemble with HLASM. My guess is that getting gcc hosted in a bizarre environment is much easier than getting Not so bizarre when so many of the Fortune 500 use it. the gcc build system working. Trying to bootstrap gcc there seems like a lot of pain for no real benefit. The effort is mostly in the Canadian Cross. The changes to get it to bootstrap from that point are relatively small. The extra things required are: 1. header.gcc to remap includes. 2. scripts to rename includes. 3. 20 lines of JCL in the stage 2 procs, to do compiles. Here's the first of those from 3.4.6, so you can see the scope of the work: builtin-attrs.def builtina.h builtin-types.def builtint.h builtins.def builtind.h c-common.def ccommond.h diagnostic.def diagndef.h machmode.def machmodd.h params.def paramsd.h predict.def predictd.h rtl.def rtld.h stab.def stabd.h timevar.def timevard.h tree.def treed.h insn-constants.h i-constants.h langhooks-def.h langhdef.h hosthooks-def.h hosthdef.h gt-dwarf2asm.h gt-dwasm.h gcov-io.c gcovioc.h It's now very rare to have a problem on the MVS EBCDIC host that doesn't also occur on a Unix ASCII cross-compiler. So for that extra bit of work, mainframers are able to modify the C compiler on their native platform instead of having to mess around with a Unix system they know nothing about. Part of open source is making the source available and usable on the native environment, I think. Otherwise, the job of providing a free, open source C compiler on the mainframe hasn't really been done, I think. And I was dreaming of that way back in 1987 when I had a 3270 terminal plus a mainframe. Although admittedly I only wanted to use it, not build it. But the easier it is for a mainframer to access the code, the more likely it is that they will be inspired to add a PL/S or Cobol front-end to it. BFN. Paul.
Re: i370 port - constructing compile script
the gcc build system working. Trying to bootstrap gcc there seems like a lot of pain for no real benefit. The effort is mostly in the Canadian Cross. The changes to get it to bootstrap from that point are relatively small. I think you are underestimating the work involved. ? Note that I have *already* ported both GCC 3.2.3 and GCC 3.4.6 such that they bootstrap on MVS, in a totally non-Unix environment, with nothing more than a C90 compiler (with zero (0) extensions). The trouble is that in the process of doing that (ie mainly for the Canadian Cross part), I had to: 1. Construct the config.h/auto-host by hand (having the stack direction go the wrong way was a lot of fun for sure). 2. Got the list of files to compile by hand. 3. Constructed the compile JCL by hand. I believe all of these things can be integrated into the existing build process on Unix with minimal fuss if you know where to put it. At the time I was doing the original porting, I didn't even have Unix, so it was easier to do it by hand. But now I'm interested in neat, minimal integration. With appropriate workarounds, GCC is very close to C90 already. Many years ago now, when Steve Chamberlain started porting the GNU tools to bootstrap on Windows, he realized that the best approach was to write (what is now known as) cygwin. It may sound crazy now, but bringing the Unix environment to yours is doable, and it has many ancillary benefits. Adding POSIX to MVS 3.8j is certainly a worthwhile project. However, I consider bashing GCC into C90-shape to be a worthwhile project too. For whenever you're on a non-Posix system, not just MVS. E.g. DOS/VS, or CMS, or MUSIC/SP, or TPF, or MVT, or MFT, or some of the others I have heard mentioned. :-) I'm really only interested in DOS/VS, CMS, MUSIC/SP. Maybe TPF as well. But bringing POSIX to them is a separate exercise to writing the 1000 lines (literally) of assembler that is required to get them to work. GCC 3.4.6 is 850,000 lines of (generated) assembler code. But the way things are structured, it only requires 1000 lines for each of those different targets (to do I/O). MVS and CMS are already done. MUSIC/SP is half done (the person doing the port died). DOS/VS is not done, although a couple of people started an attempt. Adding POSIX to all those environments may be done at some point in the future, but no-one has even started, and everyone wants native support regardless. Can you imagine if GCC was running on Unix with some sort of emulated-MVS I/O? You'd rip out that nonsense and replace it with native POSIX in an instant. CMS actually supports emulated MVS I/O too, and indeed, that's what the first port was. But someone has already spent the effort to replace it with native CMS I/O, which gets around various restrictions. I think that we have now reached the point where two quite different cultures meet. :-) People have been freaking out a bit on the MVS side too. :-) BFN. Paul.
Re: i370 port - constructing compile script
But from the Unix system, I need to be able to generate the above very simple compile script, which is a precursor to creating very simple JCL steps (trust me, you don't want to see what ST2CMP looks like). Note that the JCL has the filenames truncated to 8 characters, listed twice, uppercased, and '-' and '_' converted to '@'. Why are you not making use of z/OS Unis System Services? GNU Make and other GNU tools are available and already built for z/OS. USS is not available for free, or even for a price on MVS 3.8j, and it is not native MVS, it is an expensive overhead. It's a bit like asking "why don't you use a JCL emulator instead of make on Unix?". :-) You know, even as a batch job with JCL, people then said to me that reading the C source from a file instead of "standard input" (ie stdin, ie //SYSIN DD) is really weird, and so I had to make a pretty small mod to GCC to allow "-" as the filename, so that the JCL at least looks like a normal MVS compiler. Perhaps because he is a hacker in the good ol' sense of the word ? Mjam, MVS, JCL, the possibility of COBOL, perhaps even PL/1 ... Both Cobol and PL/1 front-ends are already supported to some extent ... http://www.opencobol.org/ http://pl1gcc.sourceforge.net/ although we're not really at the stage of even attempting to get that onto native MVS. Actually, PL/1 basically requires GCC 4.x, which is my main interest in upgrading 3.4.6 to 4.x. :-) Someone else said he would like to see PL/S, and maybe if PL/1 was available, the super-secret PL/S language would start to be made available. But it all rests on getting the HLASM-generator working on a more modern GCC. :-) And C90 is the lingua franca. [ Over a quarter of century ago I worked at the computer center of the Dutch Postal Service. One of my colleagues managed the IBM system group. He had an assistant to write the JCL jobs he needed for him. ] Maybe for old times sake you'd like to load up: http://mvs380.sourceforge.net It comes with GCC so you can now do what you always wanted to do back then. :-) And of course, all perfectly usable on z/OS too. Natively. :-) 850,000 lines of assembler. Like wow, man. I wonder what GCC 4.4 will clock in as? 3.2.3 was 700,000, so we're probably up to a million lines of pure 370 assembler. :-) BFN. Paul.
Re: i370 port - constructing compile script
I tried again but I'm not making much progress. Maybe I need to go further than Canada, let's say Alaska. 1. First I need to use my current build machine, Linux, to first of all convert the i370.md into insn*.c files, then generate an xgcc. The xgcc would be capable of producing i370 code so long as I use the "-S" option. It doesn't really matter how this xgcc was created (ie using non-C90 stuff like fork available on my build machine). 2. It is now (at the Alaskan stage) that I need a different sort of config.h/auto-host.h that excludes things like fork. I can present my i370 include files here, that only include C90 functions. It is at this stage that I need it to invoke xgcc (still on the build machine), but it will be with the -S option, so there will be no .o files (although I could perhaps fake that via a scipt to keep "make" happy) and no executable built. The "fake" script could generate JCL at the same time. The C90 library (for MVS) also needs to be cross-compiled here. 3. Then I need to assemble all the assembler on real i370 (MVS). It is at this point that a real host (ie on i370 MVS) xgcc is built. 4. Then I can use that xgcc (on MVS) to compile arbitary C programs. Technically I could have had a requirement for this i370-mvs host compiler to produce say sparc target code. All of the above ignores the bootstrap on MVS, which I know is easy to add on later. To fit into the standard Canadian Cross 3-step model, I need to either collapse steps 2 and 3 into 1 theoretical step, executed across 2 platforms (compile on one, assemble on another), or I need to omit step 4, and say that I cannot target any platform other than the host. Which is fine by me anyway. If combining steps 2 and 3, we could ignore the fact that step 3 happens at all, and assume that there is a theoretical machine that directly executes assembler code. I suspect that it will only take 20 lines or similar of intrusive Makefile/shell script changes to shoe-horn my way into the existing gcc methodology. All I need to do is force it to use my C90 headers at the right spot, so that it stops thinking that I have fork etc, and stop it trying to build an executable. Can someone tell me where to put those 20 lines? I have been playing around with something like this: ./configure --host=i370-mvspdp --enable-languages=c --with-local-prefix=/devel/pdos/pdpclib but haven't been getting very far. I have one more option, and in fact, maybe it's even a preference. The C90-only library (PDPCLIB) I have on MVS is also on Linux, and gives me advance warning of problems about to happen on MVS. As such, I could force the build machine to use this C90 library to build the first xgcc. Then the config file etc would be correct for the next step. Mostly correct, anyway. It would probably get the stack direction wrong instead of leaving it unknown. What suggestions for a configure command that would come closest to what I want? Note that with the above host I had to copy "ar" to "i370-mvspdp-ar" to get it to the stage of building the xgcc. Note - prior to this latest exercise, in order to get some initial feedback, I had been manually constructing the auto-host and using my manually-created compile script to compile. But that's a pretty horrible life, when I'm pretty sure that a judiciously-placed 20 lines of code and some nifty config parameters for host and target will automate the thing. Any suggestions that don't involve "forget about MVS - no-one even knows how to spell MVS these days"? Thanks. Paul.
Re: i370 port - constructing compile script
Hi Ian, thanks for your reply. 1. First I need to use my current build machine, Linux, to first of all convert the i370.md into insn*.c files, then generate an xgcc. The xgcc would be capable of producing i370 code so long as I use the "-S" option. It doesn't really matter how this xgcc was created (ie using non-C90 stuff like fork available on my build machine). 2. It is now (at the Alaskan stage) that I need a different sort of config.h/auto-host.h that excludes things like fork. I can present my i370 include files here, that only include C90 functions. It is at this stage that I need it to invoke xgcc (still on the build machine), but it will be with the -S option, so there will be no .o files (although I could perhaps fake that via a scipt to keep "make" happy) and no executable built. The "fake" script could generate JCL at the same time. The C90 library (for MVS) also needs to be cross-compiled here. 3. Then I need to assemble all the assembler on real i370 (MVS). It is at this point that a real host (ie on i370 MVS) xgcc is built. 4. Then I can use that xgcc (on MVS) to compile arbitary C programs. Technically I could have had a requirement for this i370-mvs host compiler to produce say sparc target code. What most people do is: * Configure gcc as a cross-compiler. So this would not be considered a Canadian Cross after all, and with configure I only change the target, not the host? * Write a cross-assembler and cross-linker. Sure, and that's what I'm trying to avoid. I have a perfectly working assembler and linker on MVS already. It's been working for several decades. * Copy header files and libraries from the host (MVS). That's fine. And use the --with-root option of configure to get them used? Now you have a complete cross-toolchain running on a supported host which can produce executables which run on MVS. It's a can of worms just trying to copy MVS load modules. There's meta-data in 2 different places and it needs to be packaged. * Use that cross-toolchain to build a version of gcc which runs on MVS. At this step you port gcc to work on MVS. * Run that gcc on MVS. (Note that you mention fork, but as you probably know the gcc code never actually calls fork. It calls the pexecute routines in libiberty. Those routines have been ported to several different hosts, including MS-DOS. If you port them to MVS, then you don't have to worry about fork.) I spent several minutes going through the config.h looking at the "detected" functions to find a good example. Maybe I should I have getrlimit or getrusage or fputs_unlocked instead. To fit into the standard Canadian Cross 3-step model, I need to either collapse steps 2 and 3 into 1 theoretical step, executed across 2 platforms (compile on one, assemble on another), Right, people normally do this by using a cross-assembler and cross-linker. Ok. I suspect that it will only take 20 lines or similar of intrusive Makefile/shell script changes to shoe-horn my way into the existing gcc methodology. All I need to do is force it to use my C90 headers at the right spot, so that it stops thinking that I have fork etc, and stop it trying to build an executable. Can someone tell me where to put those 20 lines? One way to shoe-horn those lines in would be to make your cross-assembler and cross-linker actually be shell scripts. Ok, that's no problem. They would copy the files to MVS, run the real assembler and linker, and copy the output back. I might theoretically be able to do such a thing, but that's not what I'm after. I'm just after 200+ assembler files to be produced so that I can zip them up and take them to a real MVS site or whatever to get compiled. It looks like someone just wrote a C compiler in 370 assembler, which is now all natural MVS (the objective of the exercise). That would be more than 20 lines, but it seems doable to me. Actually, that would be 0 lines of intrusive code (ie changing GCC itself). But I don't understand the bit about C90 headers. gcc doesn't need fork, but it does need a way to execute other programs. No, I use intrusive code to convert the pexecute call into a static call to cc1 (effectively - I actually intercept it within gcc itself, see below). And that is why I need a Makefile target that includes all the object code. Because I compile the 450,000 lines of C code into 850,000 lines of assembler code to produce a 3.4 MB gcc load module for MVS. Those figures are from gcc 3.4.6. BFN. Paul. *** *** 2610,2615 --- 2623,2631 static int execute (void) { + #ifdef SINGLE_EXECUTABLE + int ret_code = 0; + #endif int i; int n_commands; /* # of command. */ char *string; *** *** 2756,2761 --- 2772,2792 char *errmsg_fmt, *errmsg_arg; const char *string = commands[i].argv[0]; + #ifdef SINGLE_EXECUTABLE + { + int cnt = 0; + + while (commands[i].argv[cnt] !=
Re: i370 port - constructing compile script
* Configure gcc as a cross-compiler. So this would not be considered a Canadian Cross after all, and with configure I only change the target, not the host? The end result is a Canadian Cross, but the first step in a typical build of a Canadian Cross is a cross-compiler. Ok. * Write a cross-assembler and cross-linker. Sure, and that's what I'm trying to avoid. I have a perfectly working assembler and linker on MVS already. It's been working for several decades. There are many advantages of a cross-assembler and cross-linker, but, whatever. One of them is not "you can leverage into all the existing work of the existing-and-working-fine IFOX00 and IEWL". * Copy header files and libraries from the host (MVS). That's fine. And use the --with-root option of configure to get them used? --with-sysroot, yes. I have been trying combinations of --prefix and --with-sysroot, and --with-build-sysroot, but it is still insisting that I have an fputs_unlocked etc, despite pointing all those things to a directory that has no such thing in it, and just has my C90 headers. (Note that you mention fork, but as you probably know the gcc code never actually calls fork. It calls the pexecute routines in libiberty. Those routines have been ported to several different hosts, including MS-DOS. If you port them to MVS, then you don't have to worry about fork.) I spent several minutes going through the config.h looking at the "detected" functions to find a good example. Maybe I should I have getrlimit or getrusage or fputs_unlocked instead. fputs_unlocked is only used for systems which provide it. On systems which don't, gcc uses fputs. Similarly, getrlimit and getrusage are entirely optional. They are used if available, otherwise not. Right. I'm having trouble getting it to ignore the ones that are installed on the build system, and to switch to the directory given with --with-sysroot. Also, for the long term, it would be better to distinguish the headers that I use on the build system, to the headers used when cross-compiling. As I mentioned, I happen to be in a position where I can use the same ones on MVS, on Linux (and some other platforms too), so I can get away with forcing it to the C90 headers immediately. I've been discussing this under the assumption that you want to contribute your port back to gcc. If you don't, then I think I will step out. You can pursue whatever path you like. I do want it to be in the mainline gcc. But the requirements for reversing the 2004 deletion of the i370 target (which can be done with two svn commands) are too onerous to be met for likely years. I personally think it's strange that we had an i370 target that didn't meet those requirements from 1993 to 2004, but now it isn't, regardless of the fact that it now works better than ever before (not suprising after more than 5 years of effort by multiple people). But there's not much I can do about that. Way back In 1998 I was talking to someone from GCC (not ecgs) about getting some mods in to support MVS (I wasn't aware of other MVS activity on the ecgs side). The computer with the conversation was stolen, so I don't know who that was. Whoever it was, I think they had plans to rewrite the i370.md themselves (but that obviously didn't happen). My changes were all outside that. Basically I needed those small mods to create a single executable plus some other minor mods (similar to what I posted here recently). I don't recall if any of it was accepted or not (I just gave the patches, and no longer have those to see if they got in). I know the single-executable mods didn't get in, because I know what to look for, and it isn't there. There's not much I can do about the non-acceptance of the mods, but the one thing I can do is keep my modification footprint low. That's why I believe that 20 lines somewhere in the configuration scripts are probably enough to get what I want, without upsetting the existing structure. Maybe eventually those 20 lines will be accepted as a non-default option, but that is beyond my control. But regardless of whether it is accepted or not, I want to be able to demonstrate it working first. Where "working" doesn't mean "write my own cross-assembler and cross-linker and change MVS to be posix instead of MVS and get the entire test suite working", but rather "work the same way that gccmvs 3.2.3 works (ie bootstrapping works), except get the JCL and auto-host to be automatically generated instead of manually constructed for each release". It takes several days of effort to manually construct those files and debug the problems with them, when I suspect that with the right config command-line and a little bit of intrusive code, plus some external support scripts (that are no skin off anyone's nose), the whole thing can be automated. Anyway, I'll keep plugging away. I resorted to renaming /usr/include, but that triggered off other problems. I suspect
Re: i370 port - constructing compile script
* Copy header files and libraries from the host (MVS). That's fine. And use the --with-root option of configure to get them used? --with-sysroot, yes. I have been trying combinations of --prefix and --with-sysroot, and --with-build-sysroot, but it is still insisting that I have an fputs_unlocked etc, despite pointing all those things to a directory that has no such thing in it, and just has my C90 headers. The --with-sysroot option tells gcc where to find header files and libraries for the target. The --with-build-sysroot option tells gcc where to find header files and libraries for the target while building gcc itself. But that's the first step in what I'm doing, isn't it? fputs_unlocked is called by gcc itself, not by target code; As such, I am in a position where I can point it to my C90 libraries. I have everything I need to create the xgcc as a single executable on Linux that produces i370 assembler. That's what I already have with gcc 3.4.6. With 3.4.6, I have a script called "compile", which looks like this: call stdcomp alias.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp alloc-pool.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp attribs.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp bb-reorder.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp bitmap.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcomp bt-load.c %1 %2 %3 %4 %5 %6 %7 %8 %9 ... gcc -s -nostdlib -o gccmvs.exe *.o ../../pdos/pdpclib/pdpwin32.a -lkernel32 The Windows version is simpler, but I have the equivalent for Linux. I call it gccmvs instead of xgcc. That's my cross-compiler. That was sort of hand-constructed (I actually selected stuff from the output of a normal make on Linux, skipping stuff that was used to produce the generator files (genrecog etc). I believe that a simple script like above can be *generated* with a few lines of changes to an appropriate makefile. That's why I mentioned before that I'm after a makefile target that only lists the object code that would go into a stage 1 executable. therefore, what matters for whether fputs_unlocked is supported is the host header files and libraries, not the target header files and libraries. So using --with-sysroot is never going to affect whether gcc itself uses fputs_unlocked. Well even with --with-build-sysroot I don't seem to be able to steer it away from my system's header files. But this is a more minor aspect to what I'm interested in. I think I'll just rename my system header files and copy in the C90 headers. The case where that should work if you configure gcc using --with-sysroot to point to C90 headers and libraries, and you use that gcc to build another gcc. That is, configure gcc as a cross-compiler to a system which happens to be very similar to the host system, and then use that cross-compiler to build a new compiler, in what is effectively a same-system Canadian Cross. The second gcc should not use fputs_unlocked in that case. This comment has me confused. I already have gcc 4.4 installed as a native compiler. I am now trying to build on Linux, to produce a Linux-to-i370 cross-compiler. Therefore the first thing I want to do is build a cross-compiler, right? Or does the build process want to force me to compile gcc 4.4 as a native compiler *again*? I was expecting it to just use what I already have, which coincidentally happens to be gcc 4.4. Can I skip that step then? I (used to) sometimes use a different compiler, such as Watcom or Borland, on Windows, in order to build the windows-to-i370 cross. Similarly, getrlimit and getrusage are entirely optional. They are used if available, otherwise not. Right. I'm having trouble getting it to ignore the ones that are installed on the build system, and to switch to the directory given with --with-sysroot. When talking about this kind of thing, you have to distinguish the build system and the host system. The header files on the build system are irrelevant. The header files on the host system are what matter. Normally the build system and the host system are the same, but this is not true when building with a cross-compiler. In my case, I intend to run the cross-compiler on Linux to make sure it works. On Linux I also want to generate the compile script, and to generate the JCL. Once I have all those things (on the best system for gcc tools), I then want to package it all up and move to Windows. There I will run the compile script (shown above), and make sure that it also produces a single executable. I will use gcc 3.4.4 for that task, because it comes by default with Cygwin. I may choose to use Borland etc instead, but unlikely. At this stage I will be confident that I have a single C90-compliant executable, and the challenge becomes whether I can reproduce that on MVS. So I run a slightly different script, compmvs, which looks like this: call stdcompm alias.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcompm alloc-pool.c %1 %2 %3 %4 %5 %6 %7 %8 %9 call stdcompm attribs.c %1 %2 %3 %4 %5 %6 %
Re: i370 port - constructing compile script
In step 3, configure will use the A->B cross-compiler (from step 2) to do the trial compiles. This compiler, if built correctly, will use host *B* header files and libraries from its sysroot, and thus configure will detect properties of system *B* (which again is correct, as in step 3, "host" == B). From the symptoms you describe, it would appear that you're picking up bad configure results in step 3. Depending on what exactly you do, this might be either because you don't actually re-run configure but attempt to use the configure results from step 2 (that certainly cannot work), or else your step 2 cross-compiler was itself built incorrectly in some form so it doesn't properly pick up headers from its sysroot, or else the headers in the sysroot are simply incorrect ... You should investigate the various log files left by configure to figure out what's going on. Thanks for the explanation Ulrich. I was previously under the impression (my interpretation of the documentation) that I just needed to do one configure, and it would do both of the steps you mentioned. Note that one problem might be that your step 2 cross-compiler cannot actually link executables as it is missing the cross-linker required to do so. I *think* the core GCC (C-only) configure process should be able to handle this, but I might be mistaken here. Would you be able to give me the two suggested configure commands so that I can find out the answer to the above, one way or another? Perhaps if that bit fails I will need to replace the cross-compiler and cross-linker with normal gcc during the configure process, and only give it access to some C90 libraries. It so happens that I have a full suite of those, but even if I didn't, I could create a dummy printf etc so that it would at least link. Or does the configure process attempt to run the executables as well? No mind - as I said, I have the full suite for a configure to work. But it won't be able to correctly determine the stack direction if it does that. So that is the sort of thing I would need some intrusive code (out of my 20 lines quota!) to force it to 0 (unknown stack direction). Thanks. Paul.
Re: i370 port - constructing compile script
.../configure --target=i370-mvs --prefix=... --with-sysroot=... \ --enable-languages=c Thanks Ulrich. That's very different from the concept I had of how the build process was meant to work. Ignoring the cross stuff, if this is all you need I would suggest calling make in the right way to generate this script. We'll use a fake "compiler" for making cc1 which does nothing else than appending its command line to your compile script. Hence, create a script collect-stuff.sh with this content: snip -- #!/bin/sh echo stdcomp ${1+"$@"} >> /tmp/compile snap -- Now we'll call make so that it only tries to make cc1 with this compiler to collect the commands: % cd gcc % make CC=collect-stuff.sh cc1 Thanks Michael. That's exactly the sort of thing I was after. Just one thing - I'll need more than cc1. I need the files that normally go into gcc as well. So a combination of those two sets of source, so that I can get a single standalone executable. So I'll need to create a new Makefile target that's a bit bigger than cc1. But cc1 will come close. Also, I decided that I'd better go back to gcc 3.4.6 in order to do this experimentation, because at least with that I know that at the end of the day, there's no compiler issue, so if it doesn't work, the fault must lie withe the build process. I can't say that about 4.4, because I already know a normally built cross-compiler on 4.4 with a resuscitated i370 will build, but has a runtime error which wasn't immediately obvious (ie gdb didn't point to something wrong). After 3.4.6 is working, I'll hopefully have an easier time with 4.4. Anyway, I'll try it out tomorrow etc, and report back the results. BFN. Paul.
Re: i370 port - constructing compile script
Would you be able to give me the two suggested configure commands so that I can find out the answer to the above, one way or another? For step 2 (building the cross-compiler), you'd need something along the lines of .../configure --target=i370-mvs --prefix=... --with-sysroot=... \ --enable-languages=c where prefix points to the directory where the cross-compiler should be installed, and sysroot points to the directory where the MVS libraries and header are installed. I tried to action this today. But first I tried to get the normal make process working, ie without the --prefix and --with-sysroot above, and just using defaults. I had some surprising success, but also one failure. The failure (on 3.4.6, but not on 3.2.3) is that after the successful build, when I do an xgcc -S, it produces the assembler file, and then hangs. I traced this to gcc.c which was in a loop doing this: pid = pwait (commands[i].pid, &status, 0); getting a return of 0 all the time, while the process (cc1) that it is waiting on is showing up as being . Not sure what that is about. I have gcc 3.2.3 working without that problem, so I'll spend some time comparing how the two pexecutes work differently. Of course I don't have system-related problems like this on MVS, because I have a single executable and a simple function call. :-) In the meantime, I have a question. You said above that I have to point sysroot to the MVS libraries and headers. What libraries? And why, at the point of building a cross-compiler, do I need any of those things? The normal way I build a cross-compiler I just do the above configure without prefix or with-sysroot, and it builds an xgcc executable as expected, using the Linux headers, as expected. I would certainly like an option to force it to use my C90-only Linux headers and my C90-only libraries, but that should be strictly optional, and if I did do that, I would expect to see configure saying things like "no you don't have fork, or getrusage, or sys/types" etc etc. I think I am still failing to understand some major aspect of the build process. BFN. Paul.
Re: i370 port - constructing compile script
The failure (on 3.4.6, but not on 3.2.3) is that after the successful build, when I do an xgcc -S, it produces the assembler file, and then hangs. I traced this to gcc.c which was in a loop doing this: pid = pwait (commands[i].pid, &status, 0); getting a return of 0 all the time, while the process (cc1) that it is waiting on is showing up as being . Not sure what that is about. I have gcc 3.2.3 working without that problem, so I'll spend some time comparing how the two pexecutes work differently. Huh. I've never seen this before. Is this with your patches to generate a "single executable" or without? My patches are applied, but shouldn't be activated, because I haven't defined SINGLE_EXECUTABLE. I could try taking it back to raw 3.4.6 though and see if that has the same problem. For the cross-compiler, you shouldn't need any of the MVS host-specific patches ... My target is new basically. It's closest to mvsdignus, which was used as a starting point, but it has evolved. :-) In the meantime, I have a question. You said above that I have to point sysroot to the MVS libraries and headers. What libraries? And why, at the point of building a cross-compiler, do I need any of those things? The normal way I build a cross-compiler I just do the above configure without prefix or with-sysroot, and it builds an xgcc executable as expected, using the Linux headers, as expected. I would certainly like an option to force it to use my C90-only Linux headers and my C90-only libraries, but that should be strictly optional, and if I did do that, I would expect to see configure saying things like "no you don't have fork, or getrusage, or sys/types" etc etc. I think I am still failing to understand some major aspect of the build process. Maybe the confusion is about what "sysroot" for a cross-compiler means. The libraries and headers in the sysroot are *not* used to build the compiler itself. You need to specify the sysroot location at build time of the compiler only so that this location can be compiled into the gcc/cc1 binaries. Once you later *use* the resulting cross-compiler, this cross-compiler will refer to the sysroot location for standard headers and libraries. That is to say, if you build a cross-compiler with --prefix=/home/gccmvs/cross --sysroot=/home/gccmvs/sysroot --target=i370-mvs the result of the build process ("make" and then "make install") will be a cross-compiler in /home/gccmvs/cross/bin/i370-mvs-gcc (and additional files in /home/gccmvs/cross/lib/gcc/...). Ok, that's a new concept to me. Thanks. Note that the build process of the compiler itself will refer to the host's default headers in /usr/include and libraries in /usr/lib. However, once you *run* this i370-mvs-gcc, and it processes a source file using #include , the compiler will search the directory /home/gccmvs/sysroot/include for the stdio.h header file, and it will invoke the cross-linker passing /home/gccmvs/sysroot/lib as the location to search for standard libraries like libc. (Note that the names of such standard libraries, if any, are defined by the MVS target definitions, in particular the setting of target macros like LIB_SPEC in your target header files in config/i370/*.h.) I don't seem to have that variable defined. Not surprising since there's no include or lib directories like that on MVS. It is important to get this cross-compiler working correctly, i.e. refering to the proper headers and libraries, because in the next step, when you configure and build the native compiler, you'll be using the cross-compiler, and what headers it uses will determine which host features are detected by configure ... I see. Anyway, I'll start with raw 3.4.6 and move forward from there. The good thing about doing it that way is that I know the end result is actually achievable. Gone are the dark days of the 3.2 port where I was doing a lot of work, and had no idea whether at the end of all that work it would all be wasted, because the compiler wouldn't run natively due to some ASCII-specific bug beyond my ability to fix or work around. :-) BFN. Paul.
Re: i370 port - constructing compile script
> Huh. I've never seen this before. Is this with your patches to > generate a "single executable" or without? My patches are applied, but shouldn't be activated, because I haven't defined SINGLE_EXECUTABLE. I could try taking it back to raw 3.4.6 though and see if that has the same problem. Might be interesting ... Things are never that simple. :-) My target isn't in raw 3.4.6, so I had to use a different target (dignus), which worked! But dignus no longer worked with my changes. So had to get dignus working again before I could compare. I tried other shortcuts, but wasn't successful. After getting dignus working again I was able to start narrowing it down. For some reason gdb doesn't seem to be working as expected, so had to do without it. In the end, one line, long forgotten, in my target config file: #define pwait(a,b,c) (0) was what was responsible. :-) Most of my Posix replacement functions are in a separate unixio.h, which would normally be ignored in a configure/real unix environment. Not sure why this one ended up there. Anyway, after that interlude, I can finally move on to the original challenge! BFN. Paul.
Re: i370 port - constructing compile script
.../configure --target=i370-mvs --prefix=... --with-sysroot=... \ --enable-languages=c where prefix points to the directory where the cross-compiler should be installed, and sysroot points to the directory where the MVS libraries and header are installed. Ok, I used ../configure --target=i370-mvspdp --prefix=/devel/mvscross --with-sysroot=/devel/mvshead --enable-languages=c plus make and make install then I went to mvscross/bin and renamed i370-mvspdp-gcc to i370-mvspdp-xxx and replaced it with a script that does: i370-mvspdp-xxx -S $* For step 3 (cross-building a native compiler), you'd need something along the lines of .../configure --build=i686-linux --host=i370-mvs --target=i370-mvs \ --prefix=... --with-build-sysroot=... --enable-languages=c ./configure --build-i686-linux --host=i370-mvspdp --target=i370-mvspdp --prefix=/devel/mvshost --with-build-sysroot=/devel/mvshead --enable-languages=c I wasn't sure if that --with-build-sysroot was right - pointing to the same headers, but couldn't think of anything else to do with it! This configure run will then use the i370-mvs-gcc cross-compiler you built in step 2 in order to detect MVS host properties. Ok, it (3.4.6 I am using) got as far as: checking size of void *... configure: error: cannot determine a size of void * make: *** [configure-gcc] Error 1 I haven't had a chance to investigate what it's trying to do there, to see if I can devise a workaround. I know that it seems to try to compile with "-g" all the time which gives a warning about it not being supported, but I don't think warnings produce bad return codes like that. BFN. Paul.
Re: i370 port - constructing compile script
../configure --target=i370-mvspdp --prefix=/devel/mvscross --with-sysroot=/devel/mvshead --enable-languages=c plus make and make install then I went to mvscross/bin and renamed i370-mvspdp-gcc to i370-mvspdp-xxx and replaced it with a script that does: i370-mvspdp-xxx -S $* Maybe a more generic way to work around the missing assembler and linker would be to provide dummy scripts i370-mvspdp-as I created one of them, but as far as I can tell it didn't pick it up. and i370-mvspdp-ld, where the "assembler" would simply copy the assembler source input as text to the "object" file output, and the "linker" would collect all input files into a tar file (or some other archive) as "executable" output ... Sounds good. This would allow usual build processes (including "make") to proceed as expected. Yes. The compiler error output found in the config.log file should hopefully point to the problem ... Well, below are some of the changes I made today to get it to go past the various errors. Probably the most interesting was this one: ! #define BIG_ENDIAN 1 ! #define LITTLE_ENDIAN 2 ! #define BYTE_ORDER 1 I don't have a sys/param.h and so I just stuck those in somewhere that it seemed to be looking for, so that it didn't come up and say that it couldn't determine the endian order. It seemed to try very hard to stick in sys/types.h and sys/time.h and I'm not sure how well I got around that. It also seemed to execute /bin/as at one point instead of my dummy cross-assembler. I'll try to figure out what the logic is tomorrow. Note - all this is on 3.4.6. BFN. Paul. Index: configure === RCS file: /cvsroot/gccnew/gcc/configure,v retrieving revision 1.1.1.1 retrieving revision 1.8 diff -c -r1.1.1.1 -r1.8 *** configure 9 Jul 2009 00:25:05 - 1.1.1.1 --- configure 20 Oct 2009 12:39:48 - 1.8 *** *** 2463,2470 /* end confdefs.h. */ #include #include ! #include ! #include /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); --- 2463,2470 /* end confdefs.h. */ #include #include ! /*#include ! #include */ /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); *** *** 3377,3383 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! #include int --- 3377,3383 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! /*#include */ int *** *** 3448,3454 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! #include int --- 3448,3454 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! /*#include */ int *** *** 3519,3525 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! #include int --- 3519,3525 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! /*#include */ int *** *** 3590,3596 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! #include int --- 3590,3596 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! /*#include */ int *** *** 3662,3668 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! #include int --- 3662,3668 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! /*#include */ int *** *** 3735,3741 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! #include int --- 3735,3741 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" ! /*#include */ int *** *** 5656,5662 if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF ! #define TIME_WITH_SYS_TIME 1 _ACEOF fi --- 5656,5662 if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF ! /*#define TIME_WITH_SYS_TIME 1*/ _ACEOF fi *** *** 6150,6157 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ ! #include ! #include int main () { --- 6150,6160 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ ! /*#include ! #include */ ! #define BIG_ENDIAN 1 ! #define LITTLE_ENDIAN 2 ! #define BYTE_ORDER 1 int main () { *** *** 6192,6199 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ ! #include ! #include int main () { --- 6195,6205 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ ! /*#include ! #include */ ! #define BIG_ENDIAN 1 ! #define LITTLE_ENDIAN 2 ! #define BYT
Re: i370 port - constructing compile script
Hi Ulrich. I've had considerable success in this process. I've now reached the point where I seem to have a correctly generated config.h in libiberty and correct auto-host.h in gcc, which is one of the aims in order to get an eventual link on MVS. However, it meant that I could look at the auto-host.h and see what it had come up with. It correctly figured out that I didn't have a raft of header files, but still thought I had lots of functions like fork() and getrusage(). I suspect that is because my fake compiler is compiling with the "-S' option and returning success when it's after a link failure. OK. I thought with the fake as and ld scripts, you should no longer need a "fake compiler" script? I haven't got to the stage of playing around with that yet. But even so, you're right that the "fake linker" will not actually check whether symbols are present in your library ... I had an idea - maybe I can have warnings switched on for functions without prototypes, and then my dummy compiler trap the output and do a "wc" and if there's an unexpectedly high number of lines, then it can exit with failure. Or simply use -Werror when doing test compiles in configure. Turns out that -Werror-implicit-function-declaration wasn't sufficient. Because "configure" dutifully goes and inserts its own declaration for the non-existant functions! However, more intrusive code: + #if !defined(__MVS__) char $ac_func (); + #else + #include + #include + #include + #include + #include + #include + #endif got past that problem, such that I could get the config file I needed. I needed to put in the standard includes, otherwise it thought that I didn't even have memcmp! Any suggestion on how to make this less intrusive? Or perhaps is it logical to have a generic "trap at compile time instead of link time" configure option for other environments also? Maybe we could have two variables, a BEFORE_AC_FUNC and AFTER_AC_FUNC which are defined in all those tests, and can be set to open comment and close comment + includes to achieve the above effect. Or maybe I should simply pass over the configure script doing that substitution, since the string to search for is unique and consistent, ie grep "^char \$ac_func" configure char $ac_func (); /* The GNU C library define to always fail with ENO something starting with #if defined (__stub_$ac_fun choke me #else char (*f) () = $ac_func; I was thinking that maybe what I should do is in the fake linker, see what the output executable is. If the output executable is a conftest, then do a scan of the VCONs (external references) in the assembler making sure they are all C90. But that seems to be the wrong approach to me. If there's going to be a list of C90 functions and variables it should probably be in configure.ac I think. Speaking of which. When I was putting in the intrusive code, I saw things like newlib and Vxworks which had explicit mention and explicit settings for various things. Perhaps I should be doing something like that too rather than faking things to get them through? That would lower the barrier for an arbitrary and possibly complicated target with no extensions. However, let's stay on the current track, so that e.g. this could be used to target mvsdignus, which probably does have various extensions, and they may wish to make use of them in their MVS build. Thus, it needs to go through the detection process. Assuming that detection process has worked, and the config.h file is correctly set, then I run into the next problem. A stack of C files in libiberty failed to compile, because they have extensions in them. E.g. make-temp-file.c calls access(). I've never noticed them before because I've never included them in my links, because they are not required on MVS. Even totally unrelated things like pex-unix.c are being compiled. So what is the best way of switching the source code to compile? It is at this stage that I wish to create a single executable, so would want the fake linker to do a tar or zip. (or simply an echo, I'm flexible on that). So those failing files would presumably be omitted from that anyway? Or are they normally unconditionally compiled and linked? Finally, even with this in place, the build process stopped at the next roadblock. The file "genmodes.c" couldn't be compiled. I was surprised to see that it was being compiled with i370-mvspdp-gcc. The genmodes "needs" to be run on Unix still. It's only the source code that IT generates that needs to be cross-compiled. Regardless, genmodes.c didn't compile because auto-build.h correctly detected that my Unix system has etc, but my own header files don't have that, so a cross compile doesn't work. How does that normally work when cross-compiling a host? BTW, I really like the idea of the fake linker zipping up all the generated assembler as it goes through, which is ultimately what I need to send up to MVS. The JCL can be generated from "unzip -v" a
Re: i370 port - constructing compile script
Hi Ulrich. I'll try out some of those things. I have some initial comments. Hmmm, the access() use probably needs to be guarded by a configure check. Or else you might provide a MVS-specific implementation of "access" (if that is possible), and compile it into libiberty by providing an EXTRA_OFILES setting in a host makefile fragment; Probably too many of them. Just like open() etc in GCC main. I'll see what can be faked up, now that I know those object files are basically mandatory. in 3.4 these are set in config.table: case "${host}" in rs6000-ibm-aix3.1 | rs6000-ibm-aix) frag=mh-aix ;; *-*-cxux7*) frag=mh-cxux7 ;; *-*-freebsd2.1.*) frag=mh-fbsd21 ;; *-*-freebsd2.2.[012]) frag=mh-fbsd21 ;; i370-*-opened*) frag=mh-openedition ;; i[34567]86-*-windows*)frag=mh-windows ;; esac As to the pex-unix.c, you certainly should provide a MVS-specific version of the PEX callbacks. They are selected in configure.ac: # Figure out which version of pexecute to use. case "${host}" in *-*-mingw* | *-*-winnt*) pexecute=pex-win32.o ;; *-*-msdosdjgpp*) pexecute=pex-djgpp.o ;; *-*-msdos*)pexecute=pex-msdos.o ;; *-*-os2-emx*) pexecute=pex-os2.o;; *) pexecute=pex-unix.o ;; esac Ok, thanks. Your MVS version might be just a dummy that always fails. Ok. Even better would be a version that actually works; in this case all the "single-exectuable" hacks would become superfluous. Having a single executable, especially in my environment where only assembler code is ever generated, has its own merits even if a working system() can be done in the future. Note that e.g. pex-msdos.c implements the required callbacks solely in terms of the C99 "system" routine. If you at least have this facility available on MVS, you might be able to just use the msdos version? I don't have a working system that can execute another C program yet. Note that C90 leaves the behaviour of system() as "implementation defined". Well, on my system, I can do a system() to call some simple programs that clear the screen. In one environment on my system, anyway. :-) Finally, even with this in place, the build process stopped at the next roadblock. The file "genmodes.c" couldn't be compiled. I was surprised to see that it was being compiled with i370-mvspdp-gcc. The genmodes "needs" to be run on Unix still. It's only the source code that IT generates that needs to be cross-compiled. If this happens, then something went very wrong during configure. Did you make sure to use the proper build / host / target flags? In particular, the --build= configure argument must be present and refer to the build architecture. This is used to determine which architecture to build the generator programs for. Yes, I have all 3 specified, with --build of i686-linux. Now that I know that the generator files are meant to be built with the i686 gcc, I'll try to find out where it's picking that up from. BFN. Paul.
Re: i370 port - constructing compile script
As to the pex-unix.c, you certainly should provide a MVS-specific version of the PEX callbacks. They are selected in configure.ac: # Figure out which version of pexecute to use. case "${host}" in *-*-mingw* | *-*-winnt*) pexecute=pex-win32.o ;; *-*-msdosdjgpp*) pexecute=pex-djgpp.o ;; *-*-msdos*)pexecute=pex-msdos.o ;; *-*-os2-emx*) pexecute=pex-os2.o;; *) pexecute=pex-unix.o ;; esac Your MVS version might be just a dummy that always fails. Even better would be a version that actually works; in this case all the "single-exectuable" hacks would become superfluous. Note that e.g. pex-msdos.c implements the required callbacks solely in terms of the C99 "system" routine. If you at least have this facility available on MVS, you might be able to just use the msdos version? I tried using the MSDOS version and it had non-C90 compile errors. But provding a dummy pex-mvs is fine. Finally, even with this in place, the build process stopped at the next roadblock. The file "genmodes.c" couldn't be compiled. I was surprised to see that it was being compiled with i370-mvspdp-gcc. The genmodes "needs" to be run on Unix still. It's only the source code that IT generates that needs to be cross-compiled. If this happens, then something went very wrong during configure. Did you make sure to use the proper build / host / target flags? In particular, the --build= configure argument must be present and refer to the build architecture. This is used to determine which architecture to build the generator programs for. Ok, perhaps this error was because when I hit errors in intl, which I've never used before, I just went to the gcc directory and did a make. Regardless, I added a stack of touch xxx.o in the intl directory after the failure of the first make, which allowed me to do a second make, and then it was satisfied with the intl directory and moved on to the gcc directory, where it did in fact invoke the correct gcc rather than the cross-compiler. The next thing I hit was that genmodes didn't compile because there were conflicts between the strsignal function in the Linux include files and the system.h. Looking at the system.h, it was including things in because it thought that the prototypes didn't exist. Which would have been true for the cross-compiler, but isn't true for a native gcc. How are those two different things meant to be reconciled? Thanks. Paul.
Re: i370 port - constructing compile script
If you use --disable-nls on the configure line, the intl directory should be skipped ... Ok, that's working. The next thing I hit was that genmodes didn't compile because there were conflicts between the strsignal function in the Linux include files and the system.h. Looking at the system.h, it was including things in because it thought that the prototypes didn't exist. Which would have been true for the cross-compiler, but isn't true for a native gcc. How are those two different things meant to be reconciled? Before including "system.h", generator files include "bconfig.h" where core compiler files include "config.h". The former then in turn includes "auto-build.h", while the latter includes "auto-host.h". And this much is fine. These contain the configure results for the --build= and --host= systems, respectively. However, the auto-build.h is not detecting the all the includes etc. So while auto-host.h has a #define HAVE_DECL_CALLOC 1, the auto-build.h has it as 0. There's nothing in config.log showing a CALLOC of 0. So where can I find out what's setting this? All this should work automatically if you use the proper configure options, so something odd must be going on ... Yeah, I've probably changed something when making all the additions to get my new target and that is now interfering. Something similar to that dummy pwait. Now I've got to find it and reverse it (or mask it out). Are you running the top-level configure? (If you run a subdirectory configure, e.g. the one in gcc/, directly, things may not work correctly.) Yes I am. One other thing I did - I compiled the cross-compiler, and installed it. Then I wiped out the directory and extracted a fresh version and did the configure for building the host. I thought that would make things clean. But maybe the previous build had the correct auto-build.h that I need, and without it I get some sort of dummy auto-build.h? BFN. Paul.
Re: i370 port - constructing compile script
This means that if your GCC source tree resides in a directory, say, ~/gcc-src you should *not* run ./configure while in ~/gcc-src. Instead, you should create a second, empty directory ~/gcc-build (which is not a subdirectory of ~/gcc-src), and run ../gcc-src/configure ... while in ~/gcc-build. Ok, I tried that, and it still didn't fix the problem. Not only that, after I fixed the problem (below), I ended up getting an error that way. input.h not found or something like that. So I went back to the source tree build, and made quite a lot of progress. First of all, the problem was obvious in hindsight. I had commented out a whole lot of stuff in configure in order to stop things from being auto-detected. However, that was interfering with the configure for the build environment!!! So I put #if !defined(__MVS__) around everything that I was commenting out, and I was able to get past genmodes and on to the next error. The next error was that it was trying to use ino_t in a header file, which doesn't exist. The way I got around this using my own procedure was to create a unixio.h which has the various Posix stuff in it. E.g. I have an open() that calls fopen(). ino_t is one of the typedefs there. Anyway, I put a #include "unixio.h" into config.h and got past that problem. I don't think that was the right thing to do though, because that is a generated file. What should I have done instead? A #include of "config/i370/mvspdp.h" got around the next problem, and I think I need to do more investigation as to why that was needed. Then finally I ran into an internal compiler error which I haven't seen before. One of the gcc options must have triggered something off. Perhaps it was -Wwrite-strings, or maybe the -O2 (I normally use -Os for a completely unrelated reason). Either way, I need to find out how to switch off those flags. I'll also try to fix the compiler internal error in i370.md. BFN. Paul.
Re: i370 port - constructing compile script
I've been having fantastic success building gcc. I have got it to iterate through the entire build (as far as I can tell) now. Then finally I ran into an internal compiler error which I haven't seen before. One of the gcc options must have triggered something off. Perhaps it was -Wwrite-strings, or maybe the -O2 (I normally use -Os for a completely unrelated reason). Either way, I need to find out how to switch off those flags. I'll also try to fix the compiler internal error in i370.md. This problem was due to the build being done with 64-bit long long enabled - something i370.md can't cope with. I forced it off with these two things: configure: main () { ! long long int i; ; return 0; } --- 3196,3202 int main () { ! zlong long int i; hwint.h: #if !defined HAVE_LONG_LONG ! # if GCC_VERSION >= 3000 && !PUREISO && defined(WANT64) # define HAVE_LONG_LONG 1 # define SIZEOF_LONG_LONG 8 Now at the end of the build, I can save the output, and do a grep "^i370-mvspdp-gcc" to get all the source files that need to be compiled. I could attempt to use the .o files (that are really .s) directly, but that's not something I really need. The auto-host.h looks fine, plus I have the generated files. I still need to clean up the scripts further (the below is a work in progress), and I need to write the programs that will generate the compile JCL and then try it out! Part of the cleanup will hopefully get around the multiple make failures ... + make + cp gcc/config/i370/dummy_config.h gcc/config.h + make + cp gcc/config/i370/i370-mvspdp-gcc2 ../mvscross/bin/i370-mvspdp-gcc + make :-) BFN. Paul. Index: gccnew/gcc/configure diff -c gccnew/gcc/configure:1.1.1.1 gccnew/gcc/configure:1.12 *** gccnew/gcc/configure:1.1.1.1 Thu Jul 9 10:25:05 2009 --- gccnew/gcc/configure Fri Oct 30 12:34:44 2009 *** *** 2463,2470 --- 2463,2472 /* end confdefs.h. */ #include #include + #if !defined(__MVS__) #include #include + #endif /* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ struct buf { int x; }; FILE * (*rcsopen) (struct buf *, struct stat *, int); *** *** 3194,3200 int main () { ! long long int i; ; return 0; } --- 3196,3202 int main () { ! zlong long int i; ; return 0; } *** *** 3377,3383 --- 3379,3387 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif int *** *** 3448,3454 --- 3452,3460 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif int *** *** 3519,3525 --- 3525,3533 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif int *** *** 3590,3596 --- 3598,3606 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif int *** *** 3662,3668 --- 3672,3680 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif int *** *** 3735,3741 --- 3747,3755 cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif int *** *** 5656,5662 --- 5670,5678 if test $ac_cv_header_time = yes; then cat >>confdefs.h <<\_ACEOF + #if !defined(__MVS__) #define TIME_WITH_SYS_TIME 1 + #endif _ACEOF fi *** *** 6150,6157 --- 6166,6180 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ + #if !defined(__MVS__) #include #include + #endif + #if defined(__MVS__) + #define BIG_ENDIAN 1 + #define LITTLE_ENDIAN 2 + #define BYTE_ORDER 1 + #endif int main () { *** *** 6192,6199 --- 6215,6229 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ + #if !defined(__MVS__) #include #include + #endif + #if defined(__MVS__) + #define BIG_ENDIAN 1 + #define LITTLE_ENDIAN 2 + #define BYTE_ORDER 1 + #endif int main () { *** *** 6731,6738 --- 6761,6770 cat confdefs.h >>conftest.$ac_ext cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ + #if !defined(__MVS__) #include #include + #endif int main () { *** *** 6851,6857 --- 6883,6891 #endif /* We use char because int might match the return type of a gcc2 builtin and then its argument prototype would still apply. */ + #if !defined(__MVS__) char $ac_func (); + #endif /* The GNU C library defines this for functions which it implements to always fail with ENOSYS. Some functions are actually named something starting with __ and the normal name is an alias. */ *** *** 7051,7057 --- 7085,7093
Re: i370 port
C:\devel\gccnew\gcc>gccmvs -DUSE_MEMMGR -Os -S -ansi -pedantic-errors -DHAVE_CON FIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../include varasm.c (insn 117 429 118 7 (parallel [ (set (reg:SI 64) (compare:SI (mem/s:BLK (plus:SI (reg/f:SI 21 virtual-stack-vars) (const_int 456 [0x1c8])) [232 value+0 S196 A64]) (mem:BLK (plus:SI (reg/v/f:SI 61 [ desc ]) (const_int 8 [0x8])) [0 A8]))) (use (const_int 196 [0xc4])) ]) -1 (nil) (nil)) varasm.c: In function `force_const_mem': varasm.c:3021: internal compiler error: in instantiate_virtual_regs_lossage, at function.c:3767 OK, so what goes on here is that GCC attempts to replace the "virtual" register 21 (virtual-stack-vars) with some real register, that is frame pointer + STARTING_FRAME_OFFSET. It seems for the i370 port, this should resolve to register 13 + STACK_POINTER_OFFSET + current_function_outgoing_args_size Overall, the middle-end would therefore replace "reg 21 + 456" with "reg 13 + X", where X is constant computed from 456 + STACK_POINTER_OFFSET + current_function_outgoing_args_size. It will then re-process the insn pattern constraints to verify that the resulting insn is still valid. At this stage, it appears we're running into the above error. I'm not quite sure why this would be case, this will require some further debugging why the insn was not recognized ... This mystery is finally solved. The previous workaround I had in place failed when I tried to do an unoptimized compile of varasm.c. I found this out when I tried speeding up the experimental configure/make process. However, since it was occurring with unoptimized compiles, I thought it would be easier to track down, and indeed, I found out that the memcmp was only failing for values 128 and above. 127 was working fine. That made me suspect a signed char vs unsigned char problem. And it's the "QI" below that was causing the grief ... *** 699,711 { op2 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op2)); } ! ! /* one circumstance has been found where this short comparison ! causes an internal error. Could be related to the fact that ! both displacements were non-zero, which is unusual. So check ! for that */ ! if (((iv1 == 0) || (iv2 == 0)) && ! GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) < 256) { emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, operands[0], --- 697,705 { op2 = gen_rtx_MEM (BLKmode, copy_to_mode_reg (SImode, op2)); } ! ! if (GET_CODE (operands[3]) == CONST_INT ! && (unsigned)INTVAL (operands[3]) < 256) { emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, operands[0], *** *** 747,753 [(set (match_operand:SI 0 "register_operand" "=d") (compare:SI (match_operand:BLK 1 "s_operand" "m") (match_operand:BLK 2 "s_operand" "m"))) !(use (match_operand:QI 3 "immediate_operand" "I"))] "((unsigned) INTVAL (operands[3]) < 256)" "* { --- 741,747 [(set (match_operand:SI 0 "register_operand" "=d") (compare:SI (match_operand:BLK 1 "s_operand" "m") (match_operand:BLK 2 "s_operand" "m"))) !(use (match_operand:SI 3 "immediate_operand" "I"))] "((unsigned) INTVAL (operands[3]) < 256)" "* { The QI must be a signed char, and thus rejecting any value greater than 127. As you can see, I changed it to SI, which, with the constraints and tests in place, should be fine. Just to be sure, I did a before and after comparison of the generated assembler for all of GCC (3.4.6) and it all checked out fine. :-) BFN. Paul.
Re: i370 port
Still making great progress. The process is being simplified. I have a question. I need to remap long names to short, and I wish to use #defines to do this as it is portable. So I have a whole lot of: #define align_functions ZZZ_1 #define align_functions_log ZZZ_2 etc and I have put them all into an mshort.h for convenience. Now all code needs to be exposed to this. ie libiberty and gcc. To fit in with the new style of building, I basically want to update ansidecl.h to do a: #ifdef PUREISO #include "mshort.h" #endif Does that seem reasonable? Actually I also need to #include "unixio.h" to include various types that must be present, st_ino or whatever too. I may have other miscellaneous defines as well. I'm still in the process of unwinding all the hacks I put in years ago. :-) Thanks. Paul.
Re: i370 port
Now all code needs to be exposed to this. ie libiberty and gcc. To fit in with the new style of building, I basically want to update ansidecl.h to do a: #ifdef PUREISO #include "mshort.h" #endif Does that seem reasonable? The ISO C99 standard requires that an identifier have 31 significant initial characters, so PUREISO does not seem like the right name here. Ok. I was under the impression that C99 was rarely fully implemented, and far from universal, thus pretty irrelevant. Based on your suggested #define's, your system seems even more restrictive than ISO C99 requires. I vaguely recall that ISO C90 requires 6 significant initial characters, so something like Yep, externals need to be unique in the first 6 characters, and with case ignored. My system requires 8, and ignores case. PURE_ISO_C90 might be right here. Ok. I can see that ansidecl.h is a tempting place to put this, but I don't think it is correct. ansidecl.h is used by many different programs, including the GNU binutils and gdb. Ok, but it's a non-default option, so would have no effect on those. Changes that are specific to gcc should be in gcc, probably in gcc/system.h. Changes specific to libiberty should be in libiberty, probably in include/libiberty.h. I can give it a go, but I'm not sure they kick in early enough. I even had to move the ansidecl in cplus-dem.c up to get it to take effect soon enough. But in principle, separating the remaps for libiberty and gcc into two different files sounds like the correct thing to be doing, so I'll see if I can get that to work. Needs a bit more infrastructure to be written though. :-) BFN. Paul.
Re: i370 port
I can see that ansidecl.h is a tempting place to put this, but I don't think it is correct. ansidecl.h is used by many different programs, including the GNU binutils and gdb. Changes that are specific to gcc should be in gcc, probably in gcc/system.h. Changes specific to libiberty should be in libiberty, probably in include/libiberty.h. Another "where" question. The i370 port can't cope with 64-bit integers. The below bit keeps on defining it. So I created a WANT64 which obviously is never going to be set. I've just updated config/i370/mvspdp.h to define USE_C_ALLOCA because the i370 also doesn't have this builtin. I was wondering if I could define another variable, USE_ONLY32, to achieve the same thing for the 64-bit integers. PUREISO (I'll change it to C90 later when everything is working) is not always going to be true for the pdp port. By default, someone extracting the modified 3.4.6 code will in fact get a non-C90 build and it will have the traditional separate gcc, cc1 etc modules. So I can't use that. So - is USE_ONLY32 the way to go or is there another method? Thanks. Paul. C:\devel\gccnew\gcc>cvs diff -c hwint.h Index: hwint.h === RCS file: c:\cvsroot/gccnew/gcc/hwint.h,v retrieving revision 1.2 diff -c -r1.2 hwint.h *** hwint.h 24 Apr 2009 14:27:58 - 1.2 --- hwint.h 10 Nov 2009 13:38:16 - *** *** 22,28 but they're all cross-compile-only.) Just in case, force a constraint violation if that assumption is incorrect. */ #if !defined HAVE_LONG_LONG ! # if GCC_VERSION >= 3000 && !PUREISO # define HAVE_LONG_LONG 1 # define SIZEOF_LONG_LONG 8 extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1]; --- 22,28 but they're all cross-compile-only.) Just in case, force a constraint violation if that assumption is incorrect. */ #if !defined HAVE_LONG_LONG ! # if GCC_VERSION >= 3000 && !PUREISO && defined(WANT64) # define HAVE_LONG_LONG 1 # define SIZEOF_LONG_LONG 8 extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1];
Re: i370 port
There are a couple of places where I need to do something different if I'm running on an EBCDIC host (e.g. MVS, CMS, MUSIC, VSE). So in mvspdp.h I have put: /* If running on MVS, need some EBCDIC-related differences */ #if defined(__MVS__) || defined(__CMS__) #define HOST_EBCDIC 1 #endif and c-parse.c: #ifdef HOST_EBCDIC #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? \ ((unsigned int) (YYX) < 256 ? yytranslate[_sch_ebcasc[YYX]] \ : yytranslate[YYX]) : YYUNDEFTOK) #else #define YYTRANSLATE(YYX) ^I^I^I^I^I^I\ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) #endif and opts.c: #ifdef HOST_EBCDIC static size_t find_opt (const char *input, int lang_mask) { /* sequential search */ Is that a reasonable way to do it? I think I should probably make the opts.c into a PUREISO so that the sequential search is always used (ie work on an arbitrary C90 platform, not necessarily ASCII or EBCDIC). But the c-parse one is definitely a translation that will only work on EBCDIC. That is useful so that I don't need to have a working bison. Similarly, the opts.c change doesn't require a working shell! I think I would stop right there. Why can't the i370 port support 64-bit integers? Plenty of 32-bit hosts support them. It got an internal error. I don't have the skills to get that to work, but I do have the skills to bypass it one way or another (and I demonstrated what I am doing now, but I know that that intrusive code will break everything else, so want to back it out, without losing the functionality that I want). That said, these days gcc always defines __SIZEOF_LONG_LONG__. It would be perfectly reasonable for hwint.h to test that. Maybe something along the lines of #if !defined HAVE_LONG_LONG # if GCC_VERSION >= 3000 # ifdef __SIZEOF_LONG_LONG__ #define HAVE_LONG_LONG 1 #define SIZEOF_LONGLONG __SIZEOF_LONG_LONG__ # else # define HAVE_LONG_LONG 1 # define SIZEOF_LONG_LONG 8 These both switch long_long on. I want to switch it off (which it was already). extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1]; # endif # endif #endif So would defining a new option be a reasonable solution for any target that wants to limit code generation for whatever reason? Thanks. Paul.
Re: i370 port - constructing compile script
Well, I have good news to report. The restructuring was a success. That means with those 30-odd changes to the configure scripts, I was able to get an auto-host.h built that allowed me to take the generated source and compile it with my own scripts as per normal. There's still a stack more work to do of course, such as reversing out the ansidecl.h change, which is pretty horrible: #ifdef PUREISO #include "../gcc/unixio.h" #include "../gcc/config/i370/mvspdp.h" #endif I needed to put in the relative path to allow compilation. However, now I would like to know: 1. I think my unixio.h, which has a stack of POSIX functions that need to be there (mkdir, pwait, open, fileno etc), needs to be considered "honorary ansi" (after all, so much code assumes that they exist) and get included in ansidecl, with unixio.h living in include, and unixio.c living in libiberty. Does that sound reasonable? 2. A 3rd EBCDIC port has recently been achieved - MUSIC/SP. As part of doing that port I ran into an old problem - IFOX's 399 external limitation. On MVS and CMS we had people who knew how to modify IFOX. On MUSIC, we don't. I have a code workaround: #define flag_test_coverage gflags[0] #define flag_branch_probabilities gflags[1] #define flag_reorder_blocks gflags[2] #define flag_reorder_functions gflags[3] #define flag_rename_registers gflags[4] #define flag_force_mem gflags[5] #define flag_force_addr gflags[6] #define flag_defer_pop gflags[7] #define flag_float_store gflags[8] #define flag_strength_reduce gflags[9] etc What would be really good is if flags.h and toplev.c had a consecutive block of flags, so that even if my few lines of intrusive code aren't accepted, it's at least easy for me to mask out an entire block. At the moment I have to look for a few largish chunks of flags to mask out. I'm not sure how many I need to mask out in total. I'll be experimenting with that in the coming days on one computer, while on the other computer I will be getting the compile scripts auto-generated from the file list. I haven't tried linking with the auto-generated file list yet. I know that it is a bit different from my list (by something like 10 files), but haven't yet determined if it is functional anyway. I'll come back to making the configure changes more streamlined after the rest of the stuff is working. BTW, with MUSIC/SP done, VSE is the only currently-used EBCDIC programming environment without a GCC port, and in fact, probably the only computer system (definition: has assembler, has editor, has programmers who use that editor, commercially-used) in existence without a free C compiler (and thus, to me, preventing C from being a truly universal language for computers). And there's only about 1000 lines of assembler in the way of that happening. Unfortunately it's the same 1000 lines we've been waiting for several years for. :-) But I will be concentrating on making the MUSIC/SP port look nicer first. If I can get DYNALLOC working for output datasets, it should be fine. Otherwise, the workaround for that problem is pretty horrible. :-) Anyway, thanks guys for your help. I'll post the code after I've cleaned it up further. BFN. Paul.
Re: i370 port - constructing compile script
* Paul Edwards wrote on Thu, Nov 12, 2009 at 03:02:59PM CET: Well, I have good news to report. The restructuring was a success. That means with those 30-odd changes to the configure scripts, I was able to get an auto-host.h built that allowed me to take the generated source and compile it with my own scripts as per normal. It would be a good idea if you took the extra mile and reported all these changes to the bug-autoconf mailing list, so it could be fixed for good there. I was under the impression that the root cause was a problem with configure.ac in gcc rather than autoconf. However, I took a look at that file, and I can only see a couple of references to sys/types.h, none of which look the same as the sort of thing I needed to change. /* end confdefs.h. */ #include #include + #if !defined(__MVS__) #include #include + #endif cat >>conftest.$ac_ext <<_ACEOF /* end confdefs.h. */ #include "confdefs.h" + #if !defined(__MVS__) #include + #endif Furthermore, it would be really good if we could get Autoconf to build and run on your system, so you could run its test suite there. That would provide much better coverage of all the issues that would need fixing, and allow us to fix them once in the macros, instead of having you do this repeatedly in every configure script. I am running on a Linux box! The thing I am doing that is unusual is two things: 1. Only providing C90 headers when cross-building a host. That means that things like sys/types are failing. 2. No linking is done, because I don't have a cross-linker. As far as I can tell, peculiarity number 2 has not caused the need for any changes, with the possible exception of ones like this: + #if !defined(__MVS__) #include #include + #endif + #if defined(__MVS__) + #define BIG_ENDIAN 1 + #define LITTLE_ENDIAN 2 + #define BYTE_ORDER 1 + #endif I'm not sure what that one was all about, and I'm not sure the result of it is even used. Note that peculiarity 2 ideally requires prototypes for all functions, so there were a couple of other changes made to the gcc 3.4.6 code, such as this one: #ifdef HAVE_SYS_RESOURCE_H #include #endif ! #if defined (HAVE_DECL_GETRUSAGE) && !HAVE_DECL_GETRUSAGE extern int getrusage (int, struct rusage *); #endif --- 86,100 #include "prefix.h" #include "gcc.h" #include "flags.h" #ifdef HAVE_SYS_RESOURCE_H #include #endif ! #if defined (HAVE_GETRUSAGE) && !HAVE_DECL_GETRUSAGE extern int getrusage (int, struct rusage *); #endif Anyway, all of this should be reproducible building any ASCII target on any ASCII machine, just by using a C90 set of head files and a dummy compile script like this: C:\devel\gccnew\gcc\config\i370>type i370-mvspdp-gcc echo $* >>/tmp/build.txt i370-mvspdp-xxx -Werror-implicit-function-declaration -DPUREISO -S -I /devel/mvshead/usr/include $* Note the '-S' which could be '-c' instead and the -W. However, Autoconf requires Perl and GNU M4 (and some shell environment as well as a make program), so I'm not sure whether it is possible to get to this point. Those are all available on the build machine, even though, out of those, only m4 is available on the host. :-) BFN. Paul.
Re: i370 port - constructing compile script
Ok, now I have some results from the auto-compile-script-generation. I got it to work, but it required some manual corrections. First of all, I got link errors, because sched-ebb etc were trying to call various functions, but those functions were not being compiled in because INSN_SCHEDULING was not defined (that's my quick analysis, anyway). So I just grepped those files out of the "source list". Next, a stack of libiberty files were not compiled - strcasecmp, vasprintf, asprintf, getpagesize, strdup. I don't know why this would be the case, because e.g. HAVE_STRCASECMP is not defined. Anyway, I added them to the source list manually, and with a script, awk and m4, I was able to produce my traditional compile script (which is a stepping stone for doing the same thing on MVS). Oh, one other change I made - I normally define PREFIX in a common header file. However, this caused a conflict between prefix.c and regex.c which both try to use this keyword. It would be good if this define was made unique within the source base. I realise there are different ways around this, but it would still be good to be unique. For now I just updated prefix.c to use "" as a default prefix if none is provided. That's neater than any immediate alternative I can think of. But anyway, the short story is that things are looking great, and it is looking like I have managed to slot into the existing build process with fairly minimal intrusive code, which bodes well for a future GCC 4 port attempt. :-) The remaining work I know of doesn't require any more intrusive code. BFN. Paul.
Re: i370 port - constructing compile script
Next, a stack of libiberty files were not compiled - strcasecmp, vasprintf, asprintf, getpagesize, strdup. I don't know why this would be the case, because e.g. HAVE_STRCASECMP is not defined. Anyway, I added them to the source list manually, and with a script, awk and m4, I was able to produce my traditional compile script (which is a stepping stone for doing the same thing on MVS). The libiberty configure process attempts to detect which functions need to be built via link tests by default. As you don't have a cross-linker, something may be going wrong here. As an alternative, you can hard-code which functions to use in libiberty's configure.ac. The thing is, I already know it has detected that I don't have strcasecmp. That's why it doesn't have HAVE_STRCASECMP defined in the config.h. You are right that I don't have a linker, but the compile with error-on-no-prototype is working fine - I can see the result in config.h. Oh, one other change I made - I normally define PREFIX in a common header file. However, this caused a conflict between prefix.c and regex.c which both try to use this keyword. It would be good if this define was made unique within the source base. I realise there are different ways around this, but it would still be good to be unique. For now I just updated prefix.c to use "" as a default prefix if none is provided. That's neater than any immediate alternative I can think of. Why would you define this by hand? The usual make process will define PREFIX while building prefix.c, using the appropriate value determined at configure time ... Because when my assemble and compile jobs start running on MVS, I would first of all need to put in a special define for that in the compile step for prefix - the only exception in fact. Secondly, I am running close to the 100-character limit of the PARM statement already, with the things I was forced to add: //ST2CMP PROC GCCPREF='GCC',MEMBER='', // PDPPREF='PDPCLIB', // COS1='-Os -S -ansi -pedantic-errors -remap -DHAVE_CONFIG_H', // COS2='-DIN_GCC -DPUREISO -o dd:out -' Having another define, just to define an empty string, seems very ugly indeed, even assuming it comes in under 100 characters. By the way - that previous discussion we had about the potential for the MVS version to one day be able to do a system(). Even if it works for MVS eventually, which it probably will, it won't work for MUSIC/SP in batch. It's tragic, because I wanted to use exactly that to issue a "/file" for dynamic file allocation similar to how the CMS port does. I only have one other option - maybe the DYNALLOC call will work under MUSIC/SP, which would be nicer than doing a "/file" anyway. I will be trying that in the days ahead, but regardless, I need gcc to be a single executable on that environment if I want to run in batch. And yes, I want to run my compiles in batch! :-) BFN. Paul.
Re: i370 port - constructing compile script
Well, the configure process should result in the variable LIBOBJS in the generated libiberty Makefile to be set to list of objects containing implementations of replacement system routines. So if you do not have HAVE_STRCASECMP in config.h, you should have been getting strcasecmp.o in LIBOBJS ... And indeed, I sort of am. LIBOBJS includes a strcasecmp.s$U.s That suffix is certainly strange-looking though. I checked in config.log and I can see that it automatically detected that my "object code" has a ".s" extension, which is basically correct given that I forced the "-S" option. All of the LIBOBJS are like that. In addition, there's another problem - it has included strncmp in the list. I had a look and it appears that it attempts to actually run the program to see if strncmp works. That's not going to work in a cross-compile environment though. So maybe it assumes the worst. I've taken a look at the Makefile to try to find out what is happening. It seems that there are REQUIRED_OFILES which include things like safe-ctype and that has to have a ".o" extension. Give that those are hardcoded and forced to ".o", why isn't LIBOBJS done the same way? Anyway, I decided to change this: else LIBOBJS="$LIBOBJS $ac_func.$ac_objext" fi code you showed earlier to be hardcoded to .o. And then I changed ac_libobjs to stop putting that $U in there as well, and I finally got my strcasecmp. Note that I also seem to be getting strerror. It's on the list of "required files", even though it isn't required or wanted. configure correctly detected that I already had strerror. I manually excluded that from my list of files and now things are looking good again - including strcasecmp being automatically selected in the build process. :-) Hopefully it won't be too much longer before I have the stage 1 JCL being automatically generated so that I can verify the new files to be compiled actually work on MVS. :-) BFN. Paul.
Re: i370 port - constructing compile script
LIBOBJS includes a strcasecmp.s$U.s That suffix is certainly strange-looking though. I checked in config.log and I can see that it automatically detected that my "object code" has a ".s" extension, which is basically correct given that I forced the "-S" option. Why do you pass -S in the compiler script? configure sort of expects that neither -S nor -c are passed automatically. The only thing the compiler is capable of doing is generating assembler code. Just getting that to work has been a 20 year effort. So what I have done is get the compiler to fail on any missing prototype. I think perhaps we need to have a generic gcc or autoconfigure option called "config by prototype". MVS is just one instance where you might wish to do it this way. Other ports in their infancy may not have working cross-assemblers and linkers either. It worked out quite well. that strncmp does not work. It uses the cache variable ac_cv_func_strncmp_works, which you can set if you need to override the decision, e.g.: ac_cv_func_strncmp_works=yes export ac_cv_func_strncmp_works Ok, thanks, I've added that, and can confirm that it did the trick. A more permanent solution would be to set this correctly based upon $host in libiberty/configure.ac and regenerate libiberty/configure with autoconf. Ok, that's what a lot of this exercise is about - finding out what needs to be changed in the long term in GCC 4 if MVS is to be supported. And then I changed ac_libobjs to stop putting that $U in there as well, and I finally got my strcasecmp. Why does that $U hurt you? It should get expanded to nothing later on. (It is a remainder from some ansi2knr scheme.) Ok, I put it back in, and indeed, it does work. I must have been confused by an unrelated failure. Note that I also seem to be getting strerror. It's on the list of "required files", even though it isn't required or wanted. configure correctly detected that I already had strerror. I manually excluded that from my list of files and now things are looking good again - including strcasecmp being automatically selected in the build process. :-) Again, rather than hacking the generated configure script, I think you should start modifying the input files, configure.ac in this case, for permanent solutions to your build issues. As above, that is certainly on the cards. However, I'm trying to flesh out the issues that exist before seeing if we can get agreement for changes in GCC 4. E.g. what do you think of the generic "configure by prototype rather than link" facility? Personally I'd like a "configure by standard" option, where autoconfigure knows what to do based on me just telling it that the compiler is C90 (or C99 as another option) compliant, so that I don't even need to provide headers. But I think the header file option is also useful, so both should be selectable. Even if you're only changing a few lines, doing it each time you want to build a different GCC version is an unnecessary burden. Man, I really wish that was even 1% of the issues that needed to be sorted out going from GCC 3.4.6 to GCC 4.x. :-) I'd be happy to do it for the rest of my life. :-) While the amount of intrusive code is relatively small, it's still quite widespread. ie more than 80 files. And that's just the intrusive code. There's all the separate port files that need to be taken care of. :-) There's a good reason it took 20 years to get to this point. :-) BFN. Paul.
Re: i370 port - finally building
I have wonderful news to report. I am finally able to build GCC 3.4.6 for MVS using the normal build process. There is still a lot of extra i370-specific utilities to e.g. generate compile JCL, but these are completely separate scripts so not intrusive at all. Here's all the changes I have made to 3.4.6, including the extra i370 stuff, and including the generated files like insn-*.c. http://rapidshare.com/files/307362433/gccnew-beta72.zip And here's the file of more interest - much smaller: http://rapidshare.com/files/307366004/gcc-change.zip that contains just the changes to common files. There are 78 files in total that have been changed. Almost all of the changes are quite small. I am now in a strong position to do 2 things: 1. Experiment with changes to the build procedure, because I can easily check that the whole thing still works (it takes 2 hours to do an end-to-end test, so I see the results in the morning etc). 2. Replicate the same thing on GCC 4. I'll work on number 1 first, as I haven't put the external name remapping into the suggested place yet. And I haven't incorporated that (external) remap-generation into the build process either. Hopefully by the time I've finished that, someone can suggest precisely what autoconfigure changes would be best for (2), thinking especially of a config-by-prototype option. BFN. Paul.
Re: i370 port - constructing compile script
Ok, I've now reached a new milestone - the mshort.h which redefines all the long names into ZZZ_123 etc is now automatically generated as part of the build process. The libiberty and gcc aren't split yet, but I'll probably defer that to gcc 4, and see if I can simply reproduce what I have with 3.4.6 first. But there are some things I want to change in the 3.4.6 before starting that. There are some files that are being automatically generated as part of the build process, which I would like to stop. gcov-iov creates a gcov-iov.h which has a version number which changes when I change MVS versions. So I am thinking of updating gcov-iov.c so that when the target is MVS, it generates a more fixed format. Or maybe as part of the build process I can just put in a #define GCOV_VERSION 0 Not sure if it's actually being used for anything in my environment. gengtype-yacc.c & .h gets created with my new version of bison. I just want to use the one that came with 3.4.6 instead of having it regenerated. Do I need to hide my bison to stop that from happening? configargs.h I will just overwrite with something simple as part of the build process. gencheck.h is being generated as an empty file, which doesn't work well on some environments. I want it to at least have a comment saying "/* empty file */". I can put that in as part of the build script too. Basically I'm looking for consistent source that won't change with my build environment. The raw "MVS source" can then be taken to another environment to be compiled. Thanks. Paul.
Re: i370 port - constructing compile script
gcov-iov creates a gcov-iov.h which has a version number which changes when I change MVS versions. So I am thinking of updating gcov-iov.c so that when the target is MVS, it generates a more fixed format. I don't see how the generated number depends on the MVS version ... It is supposed to depend solely on the *GCC* version string of the compiler currently being built. Mostly yes. However, it still grabs the full version string, which includes the text "MVS 0.X" (which I added, to identify the sub-version of 3.4.6 on MVS (note that for 3.2.3 I am up to MVS 7.6 there's been so much activity). And basically I don't want that GCOV header file to change between MVS releases. Anyway, in the build scripts (ie outside the normal configure/make process, so no-one needs to see it) I just overwrite the header, and I didn't notice any ill-effect. gengtype-yacc.c & .h gets created with my new version of bison. I just want to use the one that came with 3.4.6 instead of having it regenerated. Do I need to hide my bison to stop that from happening? Well, it's just a make step -- the files will get rebuilt if and only if the gengtype-yacc.y file is more recent than the gengtype-yacc.c and .h files. In the default 3.4.6 tarball this is not the case. Did you somehow modify file timestamps while unpacking / copying the files? Yes, I imported everything into CVS and that presumably changed all the timestamps. I wasn't aware of that. Anyway, I got around that problem by making dummy changes to the .c and .h and then reversing them out. So that is fixed now, thanks. gencheck.h is being generated as an empty file, which doesn't work well on some environments. I want it to at least have a comment saying "/* empty file */". I can put that in as part of the build script too. Well, adding a comment should be trivial at the place in the Makefile.in where gencheck.h is generated (s-gencheck). Ok, I decided it was better to keep it outside the common files. In any case, more recent GCC versions no longer refer to this file at all. And I don't even need to revisit that decision for GCC 4 it seems. :-) So I've basically finished doing what I wanted for 3.4.6 now. I'm not going to spend time doing niceties like putting the generated files generation onto MVS so that mainframe users can upgrade the machine definition without needing a non-MVS machine. I have that nicety already for 3.2.3 and I may look into it again for 4.x. There's still one last thing for 3.4.6, although it's not really 3.4.6, I'm doing it for 3.2.3, but will have to incorporate that change into 3.4.6. And that thing is the MUSIC/SP port. I have managed to get dynamic allocation to work, which changes the whole look of the port, so I'm working through that, which I expect will take a couple of weeks. So that will be 3 nicely-working EBCDIC platforms. 4 if you count USS, but I don't use or test that, so don't know whether it works there currently. I should be starting the GCC 4 port in a matter of days, while using my Unix machine. Thanks everyone for helping get it to this point. BFN. Paul.
Re: i370 port - 3.4.6 to 4.4 upgrade attempt
Ok, now that 3.4.6 is fully working, I made a start on the 4.4 port. 4.4 appears to have invalidated a lot of 3.4.6 things. Below are all the changes I needed to make just to get an xgcc executable built. I didn't really know what most of it was about, but the purpose was just to scope the changes. Any changes that need to be done to 4.4 I can now refer to how it was accomplished in 3.4.6. So, given the scope below, can someone please explain what 4.4 changes are affecting me and what I need to do to overcome them? Note that I have never had to do the machine changes myself - in the past I simply waiting for Dave Pitts to do the upgrade to the new version, and then with a working 370 code generator I would make all the changes necessary for MVS. This time I don't have a working code generator. With these changes to force an executable, I can go: xgcc --version and it works, but when I attempt a compile (with -S), I get an internal error in builtin line 0, which is presumably completely meaningless because I haven't actually done the work yet. Thanks. Paul. Index: gcc4/config.sub diff -c gcc4/config.sub:1.3 gcc4/config.sub:1.4 *** gcc4/config.sub:1.3 Mon Nov 23 12:58:07 2009 --- gcc4/config.sub Mon Nov 23 22:47:08 2009 *** *** 940,945 --- 940,948 rtpc | rtpc-*) basic_machine=romp-ibm ;; + i370 | i370-*) + basic_machine=i370-ibm + ;; s390 | s390-*) basic_machine=s390-ibm ;; Index: gcc4/gcc/config.gcc diff -c gcc4/gcc/config.gcc:1.3 gcc4/gcc/config.gcc:1.4 *** gcc4/gcc/config.gcc:1.3 Mon Nov 23 12:58:07 2009 --- gcc4/gcc/config.gcc Mon Nov 23 22:46:56 2009 *** *** 358,363 --- 358,366 cpu_type=spu need_64bit_hwint=yes ;; + i370*-*-*) + cpu_type=i370 + ;; s390*-*-*) cpu_type=s390 need_64bit_hwint=yes *** *** 1964,1969 --- 1967,1984 thread_file='aix' extra_headers=altivec.h ;; + i370-*-mvspdp) + xm_defines='POSIX' # 'FATAL_EXIT_CODE=12' + xm_file="i370/xm-mvs.h" + tm_file="i370/mvspdp.h i370/i370.h" + tmake_file="i370/t-mvs i370/t-i370" + c_target_objs="i370-c.o" + cxx_target_objs="i370-c.o" + ;; + s390-*-linux*) + tm_file="s390/s390.h dbxelf.h elfos.h svr4.h linux.h s390/linux.h" + tmake_file="${tmake_file} t-dfprules s390/t-crtstuff s390/t-linux" + ;; s390-*-linux*) tm_file="s390/s390.h dbxelf.h elfos.h svr4.h linux.h s390/linux.h" tmake_file="${tmake_file} t-dfprules s390/t-crtstuff s390/t-linux" Index: gcc4/gcc/config/i370/i370-c.c diff -c gcc4/gcc/config/i370/i370-c.c:1.5 gcc4/gcc/config/i370/i370-c.c:1.6 *** gcc4/gcc/config/i370/i370-c.c:1.5 Mon Nov 23 22:17:42 2009 --- gcc4/gcc/config/i370/i370-c.c Mon Nov 23 22:46:22 2009 *** *** 34,40 #ifdef TARGET_HLASM ! #define BAD(msgid) do { warning (msgid); return; } while (0) /* #pragma map (name, alias) - In this implementation both name and alias are required to be --- 34,43 #ifdef TARGET_HLASM ! #define BAD(msgid) do { warning (0, msgid); return; } while (0) ! ! /* +++ c_lex has gone. however, we don't use it for anything important anyway */ ! #define c_lex(a) /* #pragma map (name, alias) - In this implementation both name and alias are required to be *** *** 42,52 anyone clarify? */ void ! i370_pr_map (pfile) ! cpp_reader *pfile ATTRIBUTE_UNUSED; { tree name, alias, x; if (c_lex (&x) != CPP_OPEN_PAREN) BAD ("missing '(' after '#pragma map' - ignored"); --- 45,55 anyone clarify? */ void ! i370_pr_map (cpp_reader *pfile ATTRIBUTE_UNUSED) { tree name, alias, x; + #if 0 if (c_lex (&x) != CPP_OPEN_PAREN) BAD ("missing '(' after '#pragma map' - ignored"); *** *** 63,70 BAD ("missing ')' for '#pragma map' - ignored"); if (c_lex (&x) != CPP_EOF) ! warning ("junk at end of '#pragma map'"); ! mvs_add_alias (IDENTIFIER_POINTER (name), TREE_STRING_POINTER (alias), 1); } --- 66,73 BAD ("missing ')' for '#pragma map' - ignored"); if (c_lex (&x) != CPP_EOF) ! warning (0, "junk at end of '#pragma map'"); ! #endif mvs_add_alias (IDENTIFIER_POINTER (name), TREE_STRING_POINTER (alias), 1); } *** *** 74,84 anyone clarify? */ void ! i370_pr_linkage (pfile) ! cpp_reader *pfile ATTRIBUTE_UNUSED; { tree name, mode, x; if (c_lex (&x) != CPP_OPEN_PAREN) BAD ("missing '(' after '#pragma linkage' - ignored"); --- 77,87 anyone clarify? */ void ! i370_pr_linkage (cpp_reader *pfile ATTRIBUTE_UNUSED) { tree name, mode, x; + #if 0 if (c_lex (&x) != CPP_OPEN_PAREN) BAD ("missing '(' after '#pragma linkage' - ignored"); *** *** 95,102 BAD ("missing ')' for '#pragma linkage' - ignored"); if (c_lex (&x) != CPP_EOF) ! warning ("junk at end of '#pragma linkage'"); ! } /* #pragma checkout (mode) - --- 98,105 BAD ("missing ')' for '#pragma linkage' - ignored");
Re: i370 port - 3.4.6 to 4.4 upgrade attempt
I can see one significant change: the GCC middle-end now no longer supports base-16 floating point at all. The old i370 port was the only user of this feature, and some time after the port was removed, the middle-end support was removed as well in order to simplify floating-point handling code. Hmmm. Well I don't know anything about floating point. Thanks very much for all your comments. I will see what difference that makes. Note that I'd expect that with the above obvious issues fixed, you may well run into additional problems in moving the port forward ... At some point, it will be necessary to be able to debug the back-end and resolve problems. Ok, well what I did in the original (3.2) port was to ANSIfy it and then use different debuggers (Borland, Watcom) on my Windows box. I'll see what I can come up with this time. Overall, I still think that adding HLASM support to the s390 back-end would probably be a simpler task ... Well in that case, maybe now is the time to be doing exactly that. I could make 3.4.6 the last of the i370 ports. Can you tell me what is required to convert s390, which has a very alien assembler output, into hlasm? And that brings me to another question. The i370 hlasm port uses tabs in every instruction to separate the instruction and operand. This is not valid in hlasm. In order to get around this, I ended up doing a #define for putc etc to channel everything through my own routine which converted those tabs into an appropriate number of spaces. I suspect there's a neater way to do things, but I never stumbled across that in my travels. Thanks. Paul.
i370 port - music/sp - possible generic gcc problem
I think I have found a bug in gcc, that still exists in gcc 4.4 I found the problem on 3.2.3 though. While MVS and VM have basically been working fine, when I did the port to MUSIC/SP I started getting strange compilation failures. Initializing the stack to NULs made the problem go away, but I persisted, and instead initialized the stack to x'01' to try to get consistent failures. Even with that, and the malloced memory initialized to consistent garbage, I still didn't get the desired consistency in failures. But it was consistent enough that I could just run it 6 times and see if there were any failures. Anyway, I tracked down the particular malloc() which gave changed behaviour depending on whether the malloc() did a memory initialization to NULs or not. It's this one (showing 3.2.3): C:\devel\gcc\gcc>cvs diff -l -c15 cvs diff: Diffing . Index: ggc-page.c === RCS file: c:\cvsroot/gcc/gcc/ggc-page.c,v retrieving revision 1.1.1.1 diff -c -1 -5 -r1.1.1.1 ggc-page.c *** ggc-page.c 15 Feb 2006 10:22:25 - 1.1.1.1 --- ggc-page.c 28 Nov 2009 14:13:41 - *** *** 640,670 #ifdef USING_MALLOC_PAGE_GROUPS else { /* Allocate a large block of memory and serve out the aligned pages therein. This results in much less memory wastage than the traditional implementation of valloc. */ char *allocation, *a, *enda; size_t alloc_size, head_slop, tail_slop; int multiple_pages = (entry_size == G.pagesize); if (multiple_pages) alloc_size = GGC_QUIRE_SIZE * G.pagesize; else alloc_size = entry_size + G.pagesize - 1; ! allocation = xmalloc (alloc_size); page = (char *) (((size_t) allocation + G.pagesize - 1) & -G.pagesize); head_slop = page - allocation; if (multiple_pages) tail_slop = ((size_t) allocation + alloc_size) & (G.pagesize - 1); else tail_slop = alloc_size - entry_size - head_slop; enda = allocation + alloc_size - tail_slop; /* We allocated N pages, which are likely not aligned, leaving us with N-1 usable pages. We plan to place the page_group structure somewhere in the slop. */ if (head_slop >= sizeof (page_group)) group = (page_group *)page - 1; else --- 640,670 #ifdef USING_MALLOC_PAGE_GROUPS else { /* Allocate a large block of memory and serve out the aligned pages therein. This results in much less memory wastage than the traditional implementation of valloc. */ char *allocation, *a, *enda; size_t alloc_size, head_slop, tail_slop; int multiple_pages = (entry_size == G.pagesize); if (multiple_pages) alloc_size = GGC_QUIRE_SIZE * G.pagesize; else alloc_size = entry_size + G.pagesize - 1; ! allocation = xcalloc (1, alloc_size); page = (char *) (((size_t) allocation + G.pagesize - 1) & -G.pagesize); head_slop = page - allocation; if (multiple_pages) tail_slop = ((size_t) allocation + alloc_size) & (G.pagesize - 1); else tail_slop = alloc_size - entry_size - head_slop; enda = allocation + alloc_size - tail_slop; /* We allocated N pages, which are likely not aligned, leaving us with N-1 usable pages. We plan to place the page_group structure somewhere in the slop. */ if (head_slop >= sizeof (page_group)) group = (page_group *)page - 1; else I suspect that it has stayed hidden for so long because most people probably have this mmap_anon: /* Define if mmap can get us zeroed pages using MAP_ANON(YMOUS). */ #undef HAVE_MMAP_ANON #ifdef HAVE_MMAP_ANON # undef HAVE_MMAP_DEV_ZERO # include # ifndef MAP_FAILED # define MAP_FAILED -1 # endif # if !defined (MAP_ANONYMOUS) && defined (MAP_ANON) # define MAP_ANONYMOUS MAP_ANON # endif # define USING_MMAP #endif #ifndef USING_MMAP #define USING_MALLOC_PAGE_GROUPS #endif Seems pretty clear that zeroed pages are required. Looking at the code above and below this block, it uses xcalloc instead. It will take a couple of days to confirm that this is the last presumed bug affecting the MUSIC/SP port. In the meantime, can someone confirm that this code is wrong, and that xcalloc is definitely required? I had a look at the gcc4 code, and it is calling XNEWVEC which is also using xmalloc instead of xcalloc, so I presume it is still a problem today, under the right circumstances. It took about a week to track this one down. :-) One problem I have had for years, even on the MVS port, is that I need to use -Os to get the exact same register selection on the PC as the mainframe. -O0 and -O2 get slightly different register allocations, although all versions of the code are correct. If I'm lucky, this fix may make that problem go away, but as I said, it'll take a couple of days before the results are
Re: i370 port - music/sp - possible generic gcc problem
Anyway, I tracked down the particular malloc() which gave changed behaviour depending on whether the malloc() did a memory initialization to NULs or not. Well, GC hands out non-zeroed memory - the callers are responsible for initializing it. So the fix below is not a fix but papering over an issue elswhere. Hi Richard. If GC does that, then how come there is all this effort to do mmap testing to see if it has the facility to zero memory, and why is the surrounding code (in GCC 4.4's alloc_page()) calling XCNEWVEC instead of XNEWVEC? Thanks. Paul.
Re: i370 port - music/sp - possible generic gcc problem
If GC does that, then how come there is all this effort to do mmap testing to see if it has the facility to zero memory, and I can't see what you are refering to. I obviously misinterpreted that then. why is the surrounding code (in GCC 4.4's alloc_page()) calling XCNEWVEC instead of XNEWVEC? That's the page table entries, not the data itself. There wouldn't be the need for ggc_alloc_cleared if ggc_alloc would already zero pages. Ok, based on this, I traced it back further: rtx gen_rtx_fmt_e0 (code, mode, arg0) RTX_CODE code; enum machine_mode mode; rtx arg0; { rtx rt; rt = ggc_alloc_rtx (2); memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion)); rtx gen_rtx_MEM (mode, addr) enum machine_mode mode; rtx addr; { rtx rt = gen_rtx_raw_MEM (mode, addr); /* This field is not cleared by the mere allocation of the rtx, so we clear it here. */ MEM_ATTRS (rt) = 0; return rt; } void init_caller_save () { ... for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++) if (HARD_REGNO_MODE_OK (i, mode)) { rtx mem = gen_rtx_MEM (mode, address); And indeed, this code - caller_save, shows up as one of the symptoms. One of the symptoms is that where it is meant to be saving a register prior to a function call, it instead generates a completely stupid instruction - and that stupid instruction happens to be the first instruction listed in i370.md. Right at the moment the symptom is: /ID SAVE-JOB-123456 @BLD000 /SYS REGION=,XREGION=64M /FILE SYSPRINT PRT OSRECFM(F) OSLRECL(256) /FILE SYSIN N(MATH.C) SHR /FILE O N(MATH.S) NEW RECFM(V) SP(1000) /FILE SYSINCL PDS(*.H) /FILE INCLUDE PDS(*.H) /PARM -Os -S -DUSE_MEMMGR -DMUSIC -o dd:o - /LOAD XMON : In function `acos': :137: Internal compiler error in ?, at :724 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html> for instructions. compiling something from my C runtime library. But I basically get different behaviour depending on what I initialize uninitialized memory to. Any ideas on what to look for now? I can probably isolate which bit of the malloc()ed memory is being referenced before initialization. But finding out who is doing the reference could be tricky. I might be able to trace it from a different approach, getting more information about that internal error, now that I know where some of the involved memory is. I'll get that converted into a PC filename first. BFN. Paul.
Re: i370 port - music/sp - possible generic gcc problem
: In function `acos': :137: Internal compiler error in ?, at :724 Please submit a full bug report, with preprocessed source if appropriate. See http://gcc.gnu.org/bugs.html> for instructions. I might be able to trace it from a different approach, getting more information about that internal error, now that I know where some of the involved memory is. I'll get that converted into a PC filename first. 6 hours of compilation later, I was unsuccessful in getting the proper filename displayed. As far as I can tell, it's aborting but not displaying any output. ie randomly displaying the above message. However, not to worry, since there's only one line 724 with an abort() in it, and it's this bit of code: static int insert_save (chain, before_p, regno, to_save, save_mode) struct insn_chain *chain; int before_p; int regno; HARD_REG_SET *to_save; enum machine_mode *save_mode; { int i; unsigned int k; rtx pat = NULL_RTX; int code; unsigned int numregs = 0; struct insn_chain *new; rtx mem; /* A common failure mode if register status is not correct in the RTL is for this routine to be called with a REGNO we didn't expect to save. That will cause us to write an insn with a (nil) SET_DEST or SET_SRC. Instead of doing so and causing a crash later, check for this common case and abort here instead. This will remove one step in debugging such problems. */ if (regno_save_mem[regno][1] == 0) abort (); which is in the same file as the init_caller_save() function that allocated the memory in the first place. One fortunate thing is that this source file is under 1000 lines long so hopefully amenable to debugging. BFN. Paul.
Re: i370 port - music/sp - possible generic gcc problem
Latest information - Ok, based on this, I traced it back further: rtx gen_rtx_fmt_e0 (code, mode, arg0) RTX_CODE code; enum machine_mode mode; rtx arg0; { rtx rt; rt = ggc_alloc_rtx (2); memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion)); The request for 2 (I guess, rtx's) results in a malloc for 65536 bytes, so presumably each rtx is 32k. It appears that only the single byte at offset 47072 needs to be initialized to some appropriate value (I found that x'08' and x'81' also work, and I am still experimenting on that) in order to circumvent the problem of garbage code generation. rtx gen_rtx_MEM (mode, addr) enum machine_mode mode; rtx addr; { rtx rt = gen_rtx_raw_MEM (mode, addr); /* This field is not cleared by the mere allocation of the rtx, so we clear it here. */ MEM_ATTRS (rt) = 0; return rt; } I wonder if another field like the above also needs to be initialized? Or maybe the same field, but it needs to be for the second rtx? I will try to see if I can map that offset onto a meaningful variable. BFN. Paul.
Re: i370 port
I think I would stop right there. Why can't the i370 port support 64-bit integers? Plenty of 32-bit hosts support them. It got an internal error. I don't have the skills to get that to work, but I do have the skills to bypass it one way or another (and I demonstrated what I am doing now, but I know that that intrusive code will break everything else, so want to back it out, without losing the functionality that I want). A failure in your target is not a reason to change target-independent code. Well I found out what was causing this - the adddi3 definition. Commenting that out allowed the target to be built the normal way. However, when doing the host build, I wanted everything done by the (ansi) book so that I end up with code that can be compiled with a C90 compiler, be it IBM's C/370 or Borland C++. I found that I could achieve that by making my dummy cross-compile script introduce the -ansi -pedantic-errors options. However, that triggered off some more changes to configure like this ... Index: gccnew/libiberty/configure diff -c gccnew/libiberty/configure:1.1.1.3 gccnew/libiberty/configure:1.25 *** gccnew/libiberty/configure:1.1.1.3^ISun Nov 15 19:41:46 2009 --- gccnew/libiberty/configure^IWed Dec 2 17:18:07 2009 *** *** 4190,4196 #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else ! char (*f) () = $ac_func; #endif #ifdef __cplusplus } --- 4190,4196 #if defined (__stub_$ac_func) || defined (__stub___$ac_func) choke me #else ! char (*f) () = (char (*)())$ac_func; #endif #ifdef __cplusplus } *** *** 4199,4205 int main () { ! return f != $ac_func; ; return 0; } --- 4199,4205 int main () { ! return f != (char (*)())$ac_func; ; return 0; } I still haven't found the wild pointer in my GCC 3.2.3 port that gets masked with xcalloc. It's a tough one because the problem keeps on disappearing whenever I try to introduce debug info and I haven't found a technique yet. So I'm working on 3.2.3, 3.4.6 and 4.4 at any particular time. :-) BFN. Paul..
Re: i370 port - 3.4.6 to 4.4 upgrade attempt
Well I have good news to report. I applied most of your recommended changes, but it still crashed, still at the same spot: :0: internal compiler error: Segmentation fault However, I managed to track it down to some floating point stuff in the i370 code, and got rid of that, and now I can compile a "hello, world" program! The changes to 4.4.0 required to do that can be found here: http://rapidshare.com/files/317504205/gcc4-alpha6.zip I can see one significant change: the GCC middle-end now no longer supports base-16 floating point at all. The old i370 port was the only user of this feature, and some time after the port was removed, the middle-end support was removed as well in order to simplify floating-point handling code. The s390 port uses IEEE float instead of hex float throughout, so it is not affected by this change. I found that if I didn't define anything for this at all, it still worked. I'm not sure when the lack of "hex float" will actually start affecting me. I got it to generate code like: LD 0,=D'5.599...e+0' which will only require minor modifications to be acceptable to HLASM. And in fact, that's basically the same code that was being generated with GCC 3.4.6 anyway. In the meantime, I'll see how much of gcc 4.4 can be self-compiled. BFN. Paul.
i370 port
Hello GCC maintainers. There used to be an i370 target for GCC. It was written in 1989, and put into GCC 2.5 in 1993. It has always been semi-working, but never good enough to actually use. It was dropped from GCC 4 when there was supposedly no maintainer available. Actually, Dave Pitts and myself were both maintaining it at that time, but we were both still working on an old version of it (3.2). So gcc 3.4.6, circa 2004, was the last time it was included in the normal GCC distribution. We were both maintaining it, and continue to maintain it, because MVS doesn't have any alternate free C compiler available. As of yesterday, after years of work, an i370 version was released that is now fully working. The code generator has no known bugs that would stop it from being C90-compliant, and GCC can fully regenerate itself, with full optimization. You can see it here: http://gccmvs.sourceforge.net It's based on GCC 3.2.3. There is also a free i370 emulator (Hercules) and a free i370-based operating system (MVS/380) that enables the compiler to be fully tested and fully regenerate itself on its native environment. Not only that, but there is an effort underway to allow this free environment to be made available on the internet so that Unix users can do an MVS build (takes around 4 hours if done properly - ie 3 stage, full optimization, on an emulated machine), from the safety of their Unix box. Both of those products are also under active development by a community of mainframe enthusiasts. In addition, that code has been ported to GCC 3.4.6, which is now working as a cross-compiler at least. It's still some months away from working natively though. It takes a lot of effort to convert the Posix-expecting GCC compiler into C90 compliance. This has been done though, in a way that has minimal code changes to the GCC mainline. There is a lot of other activity (e.g. availability of REXX, PL/1, Cobol) that rests on the C compiler being available. So, my question is - what is required to get the i370 port reinstated into the GCC mainline? Yes, I'm aware that there is an S/390 port, but it isn't EBCDIC, isn't HLASM, isn't 370, isn't C90, isn't MVS. It may well be possible to change all those things, and I suspect that in a few years from now I may be sending another message asking what I need to do to get all my changes to the s390 target into the s390 target. At that time, I suspect there will be a lot of objection to "polluting" the s390 target with all those "unnecessary" things. So, here's hoping that the i370 port can end up where it was originally intended to end up, and that all the effort that was spent in the GCC mainline to get rid of the ASCII assumptions can now be put to good use. BFN. Paul.
Re: i370 port
We were both maintaining it, and continue to maintain it, because MVS doesn't have any alternate free C compiler available. To merge back into FSF GCC, the people who have made changes that would be merged back will need to have copyright assignments on file at the FSF (and disclaimers from any relevant employers). I don't have a current copy of the assignments list (my very old copy does show assignments from David G. Pitts with an employer disclaimer dating from 1993). There's only 3 people who have made changes. Dave Pitts, Linas Vepstas and myself. Dave you already have apparently. Linas's code is largely already merged - just his last set of changes didn't get put in. That leaves me. I work as a contractor and I'd probably be sacked if I tried to either bring in or attempt to maintain gcc. All my work was done at home. So, my question is - what is required to get the i370 port reinstated into the GCC mainline? The basic requirements for a resurrected port are the same as for a new port; it needs to be assigned to the FSF, to pass the normal technical review, and the SC needs to approve someone as a maintainer of the port (there may be a bottleneck with the last stage, since there are currently at least three new ports pending approval). It is a very good idea if you can run the testsuite for the port and will be posting results to gcc-testresults regularly. The port is to a pure C90 environment (ie not posix, not unix). It was a major effort to achieve that, and it has only just been completed to the point where the compiler recompiles itself with full optimization. The environment where it runs is not set up to run shell scripts or makes or test suites. It's set up to run JCL, and there's a stack of JCL card decks to allow GCC to compile, which would be good to have included in the i370 directory. It's difficult enough just to get GCC to know to open dd:include(xxx) for an include of "xxx.h" and dd:sysincl(xxx) for an include of . That logic was revamped in gcc 3.4.6 so I haven't put it in yet. It'll probably be months before I do that, because I can't test it until it gets up onto the mainframe. And once again, in preparation for that, I need to make it a pure C90 application. So that is where I spend my effort. Note that the i370 port used to be in GCC even though it was riddled with bugs. It took literally years to get rid of them. I would have thought that GCC recompiling itself was a damn good start for inclusion, irrespective of any test suites (assuming those test suites are even C90 code - as they would need to be to work). I would encourage going through all the changes made to the i370 port on GCC mainline, after 3.1/3.2 branched and before the port was removed, to see what should be merged into your version for mainline; ultimately it would be up to you how you get it updated for all the mechanical changes on mainline since 3.2, but those changes (see command above to get logs) may be a useful guide to how to do some of the updates. I have already merged the changes made from 3.2.3 to 3.4.6 into my code, and have a diff against 3.4.6 available already. ie, that covers all known code changes. But it only works as a cross-compiler at the moment. It's probably a few months away from being native. BFN. Paul.
Re: i370 port
The port is to a pure C90 environment (ie not posix, not unix). It was a major effort to achieve that, and it has only just been completed to the point where the compiler recompiles itself with full optimization. The environment where it runs is not set up to run shell scripts or makes or test suites. It's set up to run JCL, and there's a stack of JCL card decks to allow GCC to compile, which would be good to have included in the i370 directory. You can test a cross compiler if you have some way of copying a test executable to the i370 system It doesn't build executables either. Only the "-S" option is used. With that restriction, GCC merely reads a bunch of text files and writes a text file, and thus is amenable to being a pure C90 application. That's how it manages to work at all. running it and getting its output and exit status back (actually you don't need to be able to get the exit status since DejaGnu has wrappers to include it in the output if needed). It so happens that MVS/380 has the ability to be run in batch, and extracting the exit code won't be a problem either. Note however that I normally do all my GCC work in Windows, and the batch running etc is done with batch files. There is no need for the target to be able to run shell scripts or makes. You would need to write your own DejaGnu board file that deals with copying to/from the i370 system and running programs there. The testsuite routinely runs for much more limited embedded systems (using appropriate board files). I have a large backlog of work to do with the i370 port already, starting with getting gcc 3.4.6 running natively. Isn't that a more productive thing to do? Even after 3.4.6 is done, so that every scrap of code is available, then there's version 4 to do! BFN. Paul.
Re: i370 port
Wow, what a lot of responses. Last time I tried making contact, I didn't get a single response! In addition, that code has been ported to GCC 3.4.6, which is now working as a cross-compiler at least. It's still some months away from working natively though. It takes a lot of effort to convert the Posix-expecting GCC compiler into C90 compliance. This has been done though, in a way that has minimal code changes to the GCC mainline. You're referring to building GCC for a non-Posix *host*, right? Yep. I assume those changes are not (primarily) in the back-end, but throughout GCC common code? Yes. Or rather, they would be, if it weren't for sleight-of-hand to minimize that. I dummied up all the Posix calls to point back to C90 functions. Please take a look at the actual changes to GCC. There's not a lot: Here's the exact file: https://sourceforge.net/project/downloading.php?group_id=195127&filename=gccmvs-3_2_3-7_0.zip&a=50206324 Most of the size is generated code from the md, or other new files, and not changes to GCC proper. However, in fact, GCC is turned on its head. It's a single executable. C90 doesn't guarantee, and the host doesn't support, the ability to do a fork() and exec(). Yes, I'm aware that there is an S/390 port, but it isn't EBCDIC, isn't HLASM, isn't 370, isn't C90, isn't MVS. It may well be possible to change all those things, and I suspect that in a few years from now I may be sending another message asking what I need to do to get all my changes to the s390 target into the s390 target. At that time, I suspect there will be a lot of objection to "polluting" the s390 target with all those "unnecessary" things. Actually, I would really like to see the s390 target optionally support the MVS ABI and HLASM assembler format, so I wouldn't have any objection to patches that add these features ... Great. I understand current GCC supports various source and target character sets a lot better out of the box, so it may be EBCDIC isn't even an issue any more. It looks that way from what I've seen of 3.4.6 so far. However, I won't know for sure until it's on the host and self-generating. If there are other problems related to MVS host support, I suppose those would need to be fixed in common code anyway, no matter whether the s390 or i370 back-ends are used. Well, I would like to see that - I don't know why there are all those calls to open() instead of fopen() etc in the first place, but I don't see that happening. The only point in your list I'm sceptical about is 370 architecture support -- I don't quite see why this is still useful today (the s390 port does require at a minimum a S/390 G2 with the branch relative instructions ... but those have been around for nearly 15 years). The last free MVS was MVS 3.8j which runs on the S/370 architecture. If you want to write MVS software, for free, your only option is to pick that up. It doesn't run on S/390 hardware. However. :-) That's where MVS/380 comes in. http://mvs380.sourceforge.net So yes, we can sort of cope with S/390 instructions. It's just not as widely supported as the proper S/370 (emulated) machine. Or rather, I think we can. It's into unchartered territory what restrictions S/380 actually has in its current form. It's known that it's enough to run 31-bit GCC using 20 MB of memory though. Which again, is a damn good start. BFN. Paul.
Re: i370 port
I understand current GCC supports various source and target character sets a lot better out of the box, so it may be EBCDIC isn't even an issue any more. If there are other problems related to MVS host I think the EBCDIC support is largely theoretical and not tested on any actual EBCDIC host (or target). cpplib knows the character set name UTF-EBCDIC, but whenever it does anything internally that involves the encoding of its internal character set it uses UTF-8 rules (which is not something valid to do with UTF-EBCDIC). From the hercules-os380 files section, here's the relevant change to 3.4.6 to stop it being theoretical: Index: gccnew/gcc/cppcharset.c diff -c gccnew/gcc/cppcharset.c:1.1.1.1 gccnew/gcc/cppcharset.c:1.6 *** gccnew/gcc/cppcharset.c:1.1.1.1 Wed Apr 15 16:26:16 2009 --- gccnew/gcc/cppcharset.c Wed May 13 11:07:08 2009 *** *** 23,28 --- 23,30 #include "cpplib.h" #include "cpphash.h" #include "cppucnid.h" + #include "coretypes.h" + #include "tm.h" /* Character set handling for C-family languages. *** *** 529,534 --- 531,561 return conversion_loop (one_utf32_to_utf8, cd, from, flen, to); } + #ifdef MAP_OUTCHAR + /* convert ASCII to EBCDIC */ + static bool + convert_asc_ebc (iconv_t cd ATTRIBUTE_UNUSED, + const uchar *from, size_t flen, struct _cpp_strbuf *to) + { + size_t x; + int c; + + if (to->len + flen > to->asize) + { + to->asize = to->len + flen; + to->text = xrealloc (to->text, to->asize); + } + for (x = 0; x < flen; x++) + { + c = from[x]; + c = MAP_OUTCHAR(c); + to->text[to->len + x] = c; + } + to->len += flen; + return true; + } + #endif + /* Identity conversion, used when we have no alternative. */ static bool convert_no_conversion (iconv_t cd ATTRIBUTE_UNUSED, *** *** 606,611 --- 633,641 { "UTF-32BE/UTF-8", convert_utf32_utf8, (iconv_t)1 }, { "UTF-16LE/UTF-8", convert_utf16_utf8, (iconv_t)0 }, { "UTF-16BE/UTF-8", convert_utf16_utf8, (iconv_t)1 }, + #if defined(TARGET_EBCDIC) + { "UTF-8/UTF-EBCDIC", convert_asc_ebc, (iconv_t)0 }, + #endif }; /* Subroutine of cpp_init_iconv: initialize and return a *** *** 683,688 --- 713,722 bool be = CPP_OPTION (pfile, bytes_big_endian); + #if defined(TARGET_EBCDIC) + ncset = "UTF-EBCDIC"; + wcset = "UTF-EBCDIC"; + #else if (CPP_OPTION (pfile, wchar_precision) >= 32) default_wcset = be ? "UTF-32BE" : "UTF-32LE"; else if (CPP_OPTION (pfile, wchar_precision) >= 16) *** *** 696,701 --- 730,736 ncset = SOURCE_CHARSET; if (!wcset) wcset = default_wcset; + #endif pfile->narrow_cset_desc = init_iconv_desc (pfile, ncset, SOURCE_CHARSET); pfile->wide_cset_desc = init_iconv_desc (pfile, wcset, SOURCE_CHARSET); The generated code appears to be fine from visual inspection. BFN. Paul.
Re: i370 port
I understand current GCC supports various source and target character sets a lot better out of the box, so it may be EBCDIC isn't even an issue any more. It looks that way from what I've seen of 3.4.6 so far. However, I won't know for sure until it's on the host and self-generating. Why are you migrating to 3.4.6 now, instead of to a current version? If you want to include this in mainline some day, then eventually it has to be caught up - and 3.4.6 is older than it may appear from the release date, since it branched off of mainline five years ago. A lot has changed since then. 3.4.6 made some revamps to the i370 port (compared to 3.2.3), and I need to make sure those changes have been digested, and no code has been lost, so that I can pick up the final i370 port and move it. It's less daunting to get 3.4.6 working first. At least there the target actually exists and does obstensibly appear to work! Migrating from 3.4.6 to 4.x is not going to be made any bigger a deal. It's not like someone else is making incompatible changes to the i370 port at the same time as me! BFN. Paul.
Re: i370 port
3.4.6 made some revamps to the i370 port (compared to 3.2.3), and I need to make sure those changes have been digested, and no code has been lost, so that I can pick up the final i370 port and move it. But there were probably also (mechanical) changes to the port between when 3.4 branched (long before 3.4.6 was released) and when the port was removed from trunk - that's why the last revision before it was removed from trunk may be a better starting point. Ok, I understand now. So there were some changes, that would nominally have made it to GCC 4, but were in fact never officially released, because it was dropped before release. So, prior to starting a GCC 4 port (ie the changes may not be desirable for the GCC 3.4.6 port I am currently working on), I need to get GCC 3.4 as a base, GCC 3.4.6 as one derivative, and SVN 77215, then do a 3-way diff/merge to obtain the "nominal GCC 4" changes. Or perhaps not. I don't want the 3.4.6 changes at that point, since anything of value will be covered by SVN 77215. So I need to use GCC 3.4.6 as the base, my personal version as one derivative, SVN 77215 as the second derivative, and feed that into the 3-way diff. Ok, I'll do that when I'm in a position to do the GCC 4 port attempt. I'm still months away from completing the GCC 3.4.6 port, and there are other MVS-related projects that are more important than what is basically a transparent 3.2.3 to 4 upgrade that will only start being useful when it enables something else to happen (such as the PL/1 front-end). So I'll be working on that stable 3.4.6 before taking my chances with what is basically an axed beta (SVN 77215), with still no indication of whether even a perfectly working self-compiling i370 target will be accepted unless the testsuite is working first (and even if it was working, that still may not be enough - as the next hoop may be an s390 merge - and a requirement to switch from 370 to 390). BFN. Paul.
Re: i370 port
Why are you migrating to 3.4.6 now, instead of to a current version? If you want to include this in mainline some day, then eventually it has to be caught up - and 3.4.6 is older than it may appear from the release date, since it branched off of mainline five years ago. A lot has changed since then. A question about those changes. One of the things that I experienced when porting 3.2.3 to MVS was that GCC was sensitive to the exact floating point representation. Register selection was different depending on those slight differences. Below is what documentation I have for it. Dave Edwards, who wrote another S/370 emulator, was the one who discovered that. Does anyone know if that was changed somewhere along the line? BFN. Paul. 17. The assembler code generated by gccmvs when run on the PC is slightly different (even when the same parameters are used for code generation) from that when run on the mainframe, if -O2 is used instead of -Os. But functionally equivalent. This non-deterministic nature of the compiler is disconcerting. It seems to not always allocate registers consistently. This has been traced to floating point code in predict.c and local-alloc.c which is sensitive to the very small changes in floating point representation. This should be changed to include deltas when comparing floating point values. Here's an example of what's happening: *** c-lex.s Mon Jan 14 20:48:35 2008 --- temp.dat Mon Jan 14 21:14:04 2008 *** *** 1328,1335 SLR 15,15 STC 15,0(3,4) SLR 6,6 - LR9,6 LR8,6 L 2,192(13) CLR 2,5 BNL L303 --- 1328,1335 SLR 15,15 STC 15,0(3,4) SLR 6,6 LR8,6 + LR9,6 L 2,192(13) CLR 2,5 BNL L303
Re: i370 port
Hi guys. The last class of warning I have from the machine definition is this: ./config/i370/i370.md:784: warning: destination operand 0 allows non-lvalue which is because I have used r_or_s_operand like this: ; ; movdi instruction pattern(s). ; (define_insn "" [(set (match_operand:DI 0 "r_or_s_operand" "=dm,dS") (match_operand:DI 1 "r_or_s_operand" "dm*fF,i"))] "TARGET_CHAR_INSTRUCTIONS" "* { check_label_emit (); if (REG_P (operands[0])) and I believe what is happening is that r_or_s_operand allows a constant. But sometimes r_or_s_operand is being used as a source, in which case, the constant is fine. But when it is used as a destination, it is not fine. What is the *simplest* way of changing the setup so that the code generation remains the same, but the warning is eliminated? Note that this is 3.2.3 and I'm not wanting to restructure the whole thing to be the same as s390.md. I am thinking I can define something like r_or_s_lval_operand which would be the same as r_or_s_operand except not allow constants. But wondering if there's something simpler and neater. Thanks. Paul.
Re: i370 port - status
So the fix below is not a fix but papering over an issue elswhere. Ok, this problem nearly killed me. It took months of effort to try to isolate the fault, delving into unfamiliar code, trying to get something that could be reliably reproduced. I did finally succeed in getting an executable that reliably crashed on the 3rd identical run. However, when I attempted to debug at a level above, ie in the emulator, the bug would disappear also. My working hypothesis now is that it is a bug in the Hercules emulator to do with paging. Which means I am at the mercy of the operating system as to when it pages. That operating system is MUSIC/SP, and it doesn't come with source code, and I'm not really familiar with it anyway, and the author is dead (a couple of years ago). I did succeed in finding a configuration option to stop the huge amount of paging in MUSIC/SP. That then allowed my compiles to go through cleanly, so I am now able to get GCC to reproduce itself under MUSIC/SP. The underlying presumed paging bug in either Hercules or MUSIC/SP I decided to just package up and leave for another day, as neither thing was my main or even important focus. Closer to my main focus - after getting GCC working on MUSIC/SP, the final real ("real" = "commercially used operating system, which people use to develop code, and which doesn't have a free C compiler already") target that I knew of that remained was DOS/VS (z/VSE). In April 2010 I finally got this last environment to have a hosted C compiler that was good enough to compile a "hello world". The C runtime library is only bare bones, so it can't handle #include yet, only reading from stdin, but that's enough to get the right code for a "hello world" to be generated. Getting GCC on that environment found a bug in the DOS/VS operating system, and other limitations, but these problems were worked around. As we speak, Michel et al over here: http://tech.groups.yahoo.com/group/H390-DOSVS/ is battling to try to get the DOS/VS environment to process a PARM string (in a way compatible with z/VSE). Previously the parameter was kludged to read it from stdin. The old DOS/VS doesn't have parameters basically. Then the rest of the library can be dealt with (reading from private source statement libraries is the main thing). Meanwhile, I have released GCC 3.2.3 MVS 8.0, which can be found here: http://gccmvs.sourceforge.net which includes a much nicer MVS environment (with default DCB information) for GCC et al. It also includes the afore mentioned MUSIC/SP and DOS/VS ports, even if the latter is bare-bones. Perhaps a link to that site could be put here: http://gcc.gnu.org/extensions.html So in the short term, the sort of things I am likely to be involved in are: 1. MVS source code management (10 million lines of code). 2. Improve VSE/380 port. 3. GCC 3.4.6 upgrade (from 3.2.3). Although I managed to get 3.4.6 working on MVS many months ago, I haven't formally released that port because I was trying to get the potentially last 3.2.3 out the door. But that happened a couple of days ago. So now, as long as I can bring all 4 environments along, I should be able to upgrade. GCC 3.4.6 has the advantage that the Unix build tools are able to generate all the required files for MVS etc. Before I used to handcraft them. I could probably backport that to 3.2.3 but haven't tried, as my plan was to go forward. One problem with going foward though is that I will lose the ability to generate the generated files from i370.md. The reason for that is that one of the generator programs opens lots of files by name, and those names are not appropriate for MVS usage. I can probably work around that, but rather than spending the effort doing that, I was planning on revisiting that in GCC 4, and in the meantime, just do that part of the build on Unix instead. If people truly need a self-contained MVS (EBCDIC) C compiler, then 3.2.3 will always be available. Hopefully I'll have more positive news on GCC on the EBCDIC platfoms in the months ahead. :-) Thanks to everyone who helped in getting it so far already. BFN. Paul. - Original Message - From: "Richard Guenther" To: "Paul Edwards" Cc: Sent: Sunday, November 29, 2009 2:02 AM Subject: Re: i370 port - music/sp - possible generic gcc problem On Sat, Nov 28, 2009 at 4:13 PM, Paul Edwards wrote: I think I have found a bug in gcc, that still exists in gcc 4.4 I found the problem on 3.2.3 though. While MVS and VM have basically been working fine, when I did the port to MUSIC/SP I started getting strange compilation failures. Initializing the stack to NULs made the problem go away, but I persisted, and instead initialized the stack to x'01' to try to get consistent failures. Even with that, and the malloced memory initialized to consistent garbage, I still didn't get the
Re: i370 port
Hello all. I have previously succeeded in getting configure to work for gcc 3.4.6. Unfortunately gcc 3.4.6 is too buggy to use and needs to wait for Dave Pitts or someone to fix. gcc 3.2.3 has no known bugs for the i370 target, but it has not been done using "configure". I am now trying to get gcc 3.2.3 to build via configure using the same technique I used for gcc 3.4.6. Some differences I found so far are as follows: I needed to define the size of short etc which I didn't need to do with 3.4.6: export ac_cv_func_strncmp_works=yes export ac_cv_c_bigendian=yes export ac_cv_c_compile_endian=big-endian export ac_cv_sizeof_short=2 export ac_cv_sizeof_int=4 export ac_cv_sizeof_long=4 export ac_cv_c_float_format='IBM 370 hex' And "make", after this configure: ./configure --build=x86_64-unknown-linux-gnu --host=i370-mvspdp --target=i370-mvspdp --prefix=/devel/mvshost --enable-languages=c --disable-nls is failing here: make[2]: Leaving directory `/home/users/k/ke/kerravon86/devel/gcc/x86_64-unknown -linux-gnu/libiberty' rm -f *~ Makefile config.status xhost-mkfrag TAGS multilib.out rm -f config.log rmdir testsuite 2>/dev/null make[1]: [distclean] Error 1 (ignored) make[1]: Leaving directory `/home/users/k/ke/kerravon86/devel/gcc/x86_64-unknown -linux-gnu/libiberty' loading cache ../config.cache configure: error: can not find install-sh or install.sh in ./.. ././.. make: *** [configure-build-libiberty] Error 1 The file in question seems to exist: ~/devel/gcc>find . -name install-sh ./boehm-gc/install-sh ./install-sh ./fastjar/install-sh ~/devel/gcc>find . -name install.sh ~/devel/gcc> and is executable. Any suggestions? Thanks. Paul.
Re: i370 port
Let me ask a different question. On GCC 3.2.3, does this sequence look correct: ./configure --target=i370-mvspdp --prefix=~/devel/mvscross --with-sysroot=~/devel/mvshead --enable-languages=c make make install ./configure --build=x86_64-unknown-linux-gnu --host=i370-mvspdp --target=i370-mvspdp --prefix=~/devel/mvshost --enable-languages=c --disable-nls make The first bit is working well - it is creating a cross-compiler. But the second bit is not working well, on gcc 3.2.3 at least. The sequence worked fine on gcc 3.4.6. Thanks. Paul.
Re: i370 port
Hi Ulrich. I'm getting back to this after a long hiatus. I have reviewed the 'W' code in PRINT_OPERAND: else if (CODE == 'W') { /* hand-built sign-extension of signed 32-bit to 64-bit */ mvs_page_lit += 8; if (0 <= INTVAL (XV)) { fprintf (FILE, "=XL8'"); } else { fprintf (FILE, "=XL8'"); } fprintf (FILE, "%08X'", INTVAL (XV)); } and it looks to me like it is already correct. If movdi is given a const_int as a parameter, then sign-extending to 64-bit is exactly what needs to happen, isn't it? I'm only expecting to compile programs as 32-bit, so I'm not expecting more than 32-bit integers. The IFOX assembler won't do more than that. In case that's the issue. But regardless I don't know how to make this code: mvs_check_page (0, 6, 8); return \"MVC^I%O0(8,%R0),%1\"; make use of that 'W' operand. Do I change that %1 to %W1 perhaps? I'll give that a try tomorrow. Thanks. Paul. -Original Message- From: Ulrich Weigand Sent: Monday, August 22, 2011 10:22 PM To: Paul Edwards Cc: gcc@gcc.gnu.org Subject: Re: i370 port Paul Edwards wrote: if (operands[1] == const0_rtx) { CC_STATUS_INIT; mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),=XL8'00'\"; } mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),%1\"; }" [(set_attr "length" "8")] ) forces it to use XL8'00' instead of the default F'0' and that seems to work. Does that seem like a proper solution to you? Well, there isn't really anything special about const0_rtx. *Any* CONST_INT that shows up as second operand to the movdi pattern must be emitted into an 8 byte literal at this point. You can do that inline; but the more usual way would be to define an operand print format that encodes the fact that a 64-bit operand is requested. In fact, looking at the i370.h PRINT_OPERAND, there already seems to be such a format: 'W'. (Maybe not quite; since 'W' sign-extends a 32-bit operand to 64-bit. But since 'W' doesn't seem to be used anyway, maybe this can be changed.) Bye, Ulrich -- Dr. Ulrich Weigand GNU Toolchain for Linux on System z and Cell BE ulrich.weig...@de.ibm.com
Re: i370 port
t;show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i686-pc-cygwin"... (gdb) run Starting program: /cygdrive/c/devel/gcc/gcc/gccmvs.exe -DUSE_MEMMGR -Os -S -DHAV E_CONFIG_H -DIN_GCC -DPUREISO -I ../../pdos/pdpclib -I . -I config/i370 -I ../in clude alias.c Error: dll starting at 0x76901000 not found. Error: dll starting at 0x761f1000 not found. Error: dll starting at 0x76901000 not found. Error: dll starting at 0x765f1000 not found. Loaded symbols for /cygdrive/c/Windows/system32/ntdll.dll Loaded symbols for /cygdrive/c/Windows/syswow64/kernel32.dll Loaded symbols for /cygdrive/c/Windows/syswow64/KernelBase.dll Program received signal SIGSEGV, Segmentation fault. 0x005fca41 in discover_flags_reg () at regmove.c:174 174 if (GET_CODE (tmp) == SET) (gdb) where #0 0x005fca41 in discover_flags_reg () at regmove.c:174 #1 0x005fdfd7 in regmove_optimize (f=0x1aaecc0, nregs=29, regmove_dump_file=0x0) at regmove.c:1056 #2 0x0064d6bc in rest_of_handle_regmove (decl=0x177a000, insns=0x1aaecc0) at toplev.c:2438 #3 0x0064f1af in ZZZ_1833 (decl=0x177a000) at toplev.c:3412 #4 0x00656061 in tree_rest_of_compilation (fndecl=0x177a000, nested_p=false) at tree-optimize.c:168 #5 0x0043e6ec in c_expand_body_1 (fndecl=0x177a000, nested_p=0) at c-decl.c:6190 #6 0x0043e835 in ZZZ_331 (fndecl=0x177a000) at c-decl.c:6222 #7 0x00487dee in cgraph_expand_function (node=0x177ec3c) at cgraphunit.c:538 #8 0x00489e7e in cgraph_expand_all_functions () at cgraphunit.c:1542 #9 0x0048a046 in cgraph_optimize () at cgraphunit.c:1607 #10 0x00447d75 in ZZZ_345 () at c-objc-common.c:240 #11 0x0044664b in ZZZ_708 () at c-lang.c:185 #12 0x0044947f in ZZZ_318 (set_yydebug=0) at c-opts.c:1270 #13 0x0064cd88 in compile_file () at toplev.c:1848 #14 0x00650f5a in do_compile () at toplev.c:4695 #15 0x00650ff5 in toplev_main (argc=26, argv=0xcc583c) at toplev.c:4735 #16 0x0054df47 in execute () at gcc.c:2785 #17 0x00551c59 in do_spec ( spec=0x6a997c "%{E|M|MM:%(trad_capable_cpp) %(cpp_options) %(cpp_debug_optio ns)} %{!E:%{!M:%{!MM: %{traditional|ftraditional:%eGNU C no longer supports -tra ditional without -E} %{save-temps|traditional-cpp|no-integr"...) at gcc.c:4265 #18 0x00556a1b in main (argc=16, argv=0x6e6920) at gcc.c:6437 (gdb) /* Determine if the pattern generated by add_optab has a clobber, such as might be issued for a flags hard register. To make the code elsewhere simpler, we handle cc0 in this same framework. Return the register if one was discovered. Return NULL_RTX if if no flags were found. Return pc_rtx if we got confused. */ static rtx discover_flags_reg (void) { rtx tmp; tmp = gen_rtx_REG (word_mode, 1); tmp = gen_add3_insn (tmp, tmp, GEN_INT (2)); /* If we get something that isn't a simple set, or a [(set ..) (clobber ..)], this whole function will go wrong. */ if (GET_CODE (tmp) == SET) I tried commenting out different plus:SI rules, but that also met with a crash in the main compiler. So I don't know which plus:SI is causing the problem, and it seems very strange that the extra memory constraint triggers off the problem. Any ideas? Thanks. Paul. -Original Message- From: Paul Edwards Sent: Thursday, April 05, 2012 11:31 PM To: Ulrich Weigand Cc: gcc@gcc.gnu.org Subject: Re: i370 port Hi Ulrich. I'm getting back to this after a long hiatus. I have reviewed the 'W' code in PRINT_OPERAND: else if (CODE == 'W') { /* hand-built sign-extension of signed 32-bit to 64-bit */ mvs_page_lit += 8; if (0 <= INTVAL (XV)) { fprintf (FILE, "=XL8'"); } else { fprintf (FILE, "=XL8'"); } fprintf (FILE, "%08X'", INTVAL (XV)); } and it looks to me like it is already correct. If movdi is given a const_int as a parameter, then sign-extending to 64-bit is exactly what needs to happen, isn't it? I'm only expecting to compile programs as 32-bit, so I'm not expecting more than 32-bit integers. The IFOX assembler won't do more than that. In case that's the issue. But regardless I don't know how to make this code: mvs_check_page (0, 6, 8); return \"MVC^I%O0(8,%R0),%1\"; make use of that 'W' operand. Do I change that %1 to %W1 perhaps? I'll give that a try tomorrow. Thanks. Paul. -Original Message- From: Ulrich Weigand Sent: Monday, August 22, 2011 10:22 PM To: Paul Edwards Cc: gcc@gcc.gnu.org Subject: Re: i370 port Paul Edwards wrote: if (operands[1] == const0_rtx) { CC_STATUS_INIT; mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),=XL8'00'\"; } mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),%1\"; }" [(set_attr "length" "8")] ) forces it to
Re: i370 port
I've managed to isolate the problem to a small test program. Any suggestions on how to debug this? Thanks. Paul. C:\devel\gcc\gcc>type bug27.c /* This program demonstrates a bug in a modification to GCC 3.4.6 */ /* It generates the below error when compiled with -O2 */ #if 0 bug27.c: In function `foo': bug27.c:28: error: unrecognizable insn: (insn 116 34 35 2 (set (reg:SI 5 5) (plus:SI (plus:SI (reg:SI 2 2 [orig:54 i ] [54]) (reg/f:SI 13 13)) (const_int 104 [0x68]))) -1 (nil) (nil)) bug27.c:28: internal compiler error: in ZZZ_680, at recog.c:2083 #endif void foo(int c) { int x[3]; int y[3]; int i; for (i = 0; i < 2; i++) { if (c == 1) x[i] &= y[i]; else if (c == 2) x[i] |= y[i]; } return; } C:\devel\gcc\gcc> -Original Message----- From: Paul Edwards Sent: Friday, April 06, 2012 3:50 PM To: Ulrich Weigand Cc: gcc@gcc.gnu.org Subject: Re: i370 port I have made this change: C:\devel\gcc\gcc\config\i370>cvs diff -c -r 1.23 i370.md Index: i370.md === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.md,v retrieving revision 1.23 retrieving revision 1.24 diff -c -r1.23 -r1.24 *** i370.md 6 Apr 2012 03:57:08 - 1.23 --- i370.md 6 Apr 2012 04:03:21 - 1.24 *** *** 843,848 --- 843,853 /*return \"STM %1,%N1,%0\"; */ return \"ST %1,%0\;ST %N1,4+%0\"; } + if (GET_CODE (operands[1]) == CONST_INT) + { + mvs_check_page (0, 6, 8); + return \"MVC%O0(8,%R0),%W1\"; + } mvs_check_page (0, 6, 8); return \"MVC%O0(8,%R0),%1\"; }" C:\devel\gcc\gcc\config\i370> And it has had a good effect: diff old/cpplib.s new/cpplib.s 1670c1670 < MVC 120(8,13),=F'0' --- MVC 120(8,13),=XL8'' 1796c1796 < MVC 120(8,13),=F'0' --- MVC 120(8,13),=XL8'' However, I'm still stuck. Because when I make this change: C:\devel\gcc\gcc\config\i370>cvs diff -r 1.17 i370.h Index: i370.h === RCS file: c:\cvsroot/gcc/gcc/config/i370/i370.h,v retrieving revision 1.17 retrieving revision 1.18 diff -r1.17 -r1.18 599a600,602 #define EXTRA_MEMORY_CONSTRAINT(C, STR) \ ((C) == 'S') It triggers off a problem with plus:SI C:\devel\gcc\gcc>stdcompm global.c C:\devel\gcc\gcc>gccmvs -DUSE_MEMMGR -Os -S -DHAVE_CONFIG_H -DIN_GCC -DPUREISO - I ../../pdos/pdpclib -I . -I config/i370 -I ../include global.c global.c: In function `find_reg': global.c:1325: error: unrecognizable insn: (insn 2432 130 131 12 (set (reg:SI 15 15) (plus:SI (plus:SI (reg:SI 4 4 [orig:82 allocno ] [82]) (reg:SI 3 3 [87])) (const_int 44 [0x2c]))) -1 (nil) (nil)) global.c:1325: internal compiler error: in ZZZ_680, at recog.c:2083 Please submit a full bug report, with preprocessed source if appropriate. See http://gccmvs.sourceforge.net> for instructions. C:\devel\gcc\gcc> Seems to be a problem when adding very small const_ints (in the above case, 44) that can fit into a LA. I tried to isolate which plus:SI rule was causing the problem by commenting out these: ; ; addsi3 instruction pattern(s). ; ; The following insn is used when it is known that operand one is an address, ; frame, stack or argument pointer, and operand two is a constant that is ; small enough to fit in the displacement field. ; Notice that we can't allow the frame pointer to used as a normal register ; because of this insn. ; ;(define_insn "" ; [(set (match_operand:SI 0 "register_operand" "=d") ;^I(plus:SI (match_operand:SI 1 "general_operand" "%a") ;^I^I (match_operand:SI 2 "immediate_operand" "J")))] ; "((REGNO (operands[1]) == FRAME_POINTER_REGNUM || REGNO (operands[1]) == ARG$ ; "* ;{ ; check_label_emit (); ; CC_STATUS_INIT; /* add assumes CC but LA doesn't set CC */ ; mvs_check_page (0, 4, 0); ; return \"LA^I%0,%c2(,%1)\"; ;}" ; [(set_attr "length" "4")] ;) ;; The CC status bits for the arithmetic instructions are handled ;; in the NOTICE_UPDATE_CC macro (yeah???) and so they do not need ;; to be set below. They only need to be invalidated if *not* set ;; (e.g. by BCTR) ... yeah I think that's right ... ;; ;(define_insn "addsi3" ; [(set (match_operand:SI 0 "nonimmediate_operand" "=d") ;^I(plus:SI (match_operand:SI 1 "general_operand" "%0") ;^I^I (match_operand:SI 2 "general_operand" "g")))] ; "" ; "* ;{ ; check_label_emit (); ; if (REG_P (operands[2])) ;{ ; mvs_check_
Re: i370 port
Ah, yes. The problem is that reload assumes any valid address can be loaded into a register with a single instruction, and it will thus simply generate such instructions unconditionally -- and if the target then doesn't actually provide such a pattern, it will fail with "unrecognizable insn". Hi Ulrich. Thanks for your reply. This approach seems to be quite complicated. What do you think about the option of NOT adding this (which triggers off errors I hadn't seen before): #define EXTRA_MEMORY_CONSTRAINT(C, STR) \ ((C) == 'S') and instead making a change similar to what I have already put in under "hack" below? Is that legitimate? ; ; movstrsi instruction pattern(s). ; block must be less than 16M (24 bits) in length (define_expand "movstrsi" [(set (match_operand:BLK 0 "general_operand" "") (match_operand:BLK 1 "general_operand" "")) (use (match_operand:SI 2 "general_operand" "")) (match_operand 3 "" "")] "" " { rtx op0, op1; op0 = XEXP (operands[0], 0); if (GET_CODE (op0) == REG || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG && GET_CODE (XEXP (op0, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op0, 1)) < 4096)) op0 = operands[0]; else op0 = replace_equiv_address (operands[0], copy_to_mode_reg (SImode, op0)); op1 = XEXP (operands[1], 0); if (GET_CODE (op1) == REG || (GET_CODE (op1) == PLUS && GET_CODE (XEXP (op1, 0)) == REG && GET_CODE (XEXP (op1, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op1, 1)) < 4096)) op1 = operands[1]; else op1 = replace_equiv_address (operands[1], copy_to_mode_reg (SImode, op1)); /* first line is a hack - if target address involves two registers, we can't use an MVC, even if the length to move is less than 256, because MVC takes an S parameter. I'm unsure of the best way to distinguish a two-register target. */ if (!((GET_CODE(op0) == MEM) && REG_P(XEXP(op0,0))) && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 256) emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, gen_rtx_SET (VOIDmode, op0, op1), gen_rtx_USE (VOIDmode, operands[2]; else { /* implementation provided by Richard Henderson */ rtx reg1 = gen_reg_rtx (DImode); rtx reg2 = gen_reg_rtx (DImode); rtx mem1 = operands[0]; rtx mem2 = operands[1]; rtx len = operands[2]; if (!CONSTANT_P (len)) len = force_reg (SImode, len); /* Load up the address+length pairs. */ emit_insn (gen_rtx_CLOBBER (VOIDmode, reg1)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, 0), force_operand (XEXP (mem1, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg1, GET_MODE_SIZE (SImode)), len); emit_insn (gen_rtx_CLOBBER (VOIDmode, reg2)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, 0), force_operand (XEXP (mem2, 0), NULL_RTX)); emit_move_insn (gen_rtx_SUBREG (SImode, reg2, GET_MODE_SIZE (SImode)), len); /* Copy! */ emit_insn (gen_movstrsi_1 (reg1, reg2)); } DONE; }") Thanks. Paul.
Re: i370 port
Hi Ulrich. A further question. I put some debugging on here: op0 = XEXP (operands[0], 0); if (GET_CODE (op0) == REG || (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 0)) == REG && GET_CODE (XEXP (op0, 1)) == CONST_INT && (unsigned) INTVAL (XEXP (op0, 1)) < 4096)) { op0 = operands[0]; fprintf(stderr, \"used as-is\n\"); } else { op0 = replace_equiv_address (operands[0], copy_to_mode_reg (SImode, op0)); fprintf(stderr, \"replaced\n\"); } And I found out that op0 is already being "replaced". Shouldn't this replacement eliminate the index register and just have a base register, so that I don't need the hack further down? Thanks. Paul.
old archives from 1998
Hello. During the GCC 2.7.2/2.8.1 timeframe I sent emails to this list (or some similar list) with patches. I have found evidence of the patches being applied: http://hg.sourceforge.jp/view/cbc/GCC/file/ec4cbc2ac877/gcc/FSFChangeLog 527 Sun Oct 4 08:37:36 1998 Paul Edwards 528 529 * configure.in (AC_CHECK_HEADERS): Add sys/types.h and sys/stat.h. 530 * gcc.c (sys/types.h, sys/stat.h): Only include if exist. 531 * cccp.c, toplev.c: Likewise. But those entries do not appear in the Changelog of GCC 3.4.6, even though it goes back to 1991. I suspect it might have been due to ECGS. So my question is - is there a non-ECGS archive of some sort that would allow me to find out who modified gcc.c with that change documented above (I didn't have write access to the repository) and is there a list that my circa 1998 messages would be on so that I can find out who I was communicating with at the time? My emails from the time were lost due to a stolen computer. Thanks. Paul.