ram@nucsrl.UUCP (01/17/87)
I have a problem in using the C compiler and VAX assembler in our local 4.3BSD(VAX) site. I have a program which has a huge(>900lines) case statement. /* Whoever said that programmers(pro) don't use case/switch */ The assembler chokes on (>32K long) long branches. Apparently there is a flag "-J" for such purposes (in the assembler) which does not seem to work. The man page for "as" lists under Bugs --------------- BUGS -J should be eliminated; the assembler should automatically choose among byte, word and long branches. _______________ That does not seem to work either. The ouput of the C compiler was ___________________________ Assembler: "/tmp/ctm088343", line 2565: brw: Branch too far(50148b): try -J flag "/tmp/ctm088343", line 2823: brw: Branch too far(48806b): try -J flag "/tmp/ctm088343", line 2922: brw: Branch too far(48313b): try -J flag "/tmp/ctm088343", line 12658: Case will branch too far "/tmp/ctm088343", line 12659: Case will branch too far "/tmp/ctm088343", line 12664: Case will branch too far __________________________ and the ouput of a seperate assembly had the same error message(predictably). Assembler: "prolog.s", line 13337: Case will branch too far "prolog.s", line 13338: Case will branch too far "prolog.s", line 13339: Case will branch too far "prolog.s", line 13340: Case will branch too far This piece of code did compile in a Gould machine but not on the Vax (Code is portable). Could somebody explain and help me solve this problem. Renu Raman ...ihnp4!nucsrl!ram Northwestern Univ. Comp. Sci. Lab. Evanston IL 60201
ark@alice.UUCP (01/19/87)
In article <3950006@nucsrl.UUCP>, ram@nucsrl.UUCP writes: > > I have a problem in using the C compiler and VAX assembler in our local > 4.3BSD(VAX) site. I have a program which has a huge(>900lines) case statement. > > /* Whoever said that programmers(pro) don't use case/switch */ > > The assembler chokes on (>32K long) long branches. Apparently > there is a flag "-J" for such purposes (in the assembler) > which does not seem to work. The trouble is that a case statement does not generate jump instructions on the VAX. Instead it generates a CASE instruction. This instruction also comes in three flavors: byte, word, and longword offsets. It would not be enough for the assembler to translate the CASEW the compiler probably generates into a CASEL: the jump table must be translated from words to longwords too. Portable solutions? I suppose the best bet is to make the switch statement smaller. One way to do this might be to replace some of the bigger cases by jumps to code outside the switch statement itself. Ick.
chris@mimsy.UUCP (01/19/87)
In article <3950006@nucsrl.UUCP> ram@nucsrl.UUCP (Raman Renu) writes: >... using the C compiler and VAX assembler in our local 4.3BSD(VAX) site. >I have a program which has a huge(>900lines) case statement. >The assembler chokes on (>32K long) long branches. This may seem a nit, but no, the assembler chokes on >32K *word* branches. This is an important distinction. The pseudo-ops `jbr' expand into one of `brb' or `brw', but not `jmp'. The Vax does not have a long branch instruction, just a long jump instruction (the difference is that one takes an offset, the other an address). >Apparently there is a flag "-J" for such purposes (in the assembler) >which does not seem to work. Indeed, it does work. Look more closely at the error messages! >The ouput of the C compiler was (To be technical, these errors are from the assembler.) >Assembler: >"/tmp/ctm088343", line 2565: brw: Branch too far(50148b): try -J flag >"/tmp/ctm088343", line 2823: brw: Branch too far(48806b): try -J flag >"/tmp/ctm088343", line 2922: brw: Branch too far(48313b): try -J flag >"/tmp/ctm088343", line 12658: Case will branch too far >"/tmp/ctm088343", line 12659: Case will branch too far >"/tmp/ctm088343", line 12664: Case will branch too far Three are `branch too far, try -J'. Three are something else. >and the ouput of a seperate assembly [with -J] had the same error >message(predictably). No, not the same! >Assembler: >"prolog.s", line 13337: Case will branch too far >"prolog.s", line 13338: Case will branch too far >"prolog.s", line 13339: Case will branch too far >"prolog.s", line 13340: Case will branch too far All three `branch too far, try -J's are gone. There is one new `case will branch too far' message (because the code got bigger). The problem is that the Vax `case' instruction has only a word offset for its branches. If you look at the result of compiling a switch statement, you can see this yourself: f() { extern int sw; switch (sw) { #define CASE(n) case n: f/**/n(); break /* kludge; no ## yet */ CASE(0); CASE(1); CASE(2); CASE(3); CASE(4); CASE(5); CASE(6); CASE(7); } } The switch compiles as: casel r0,$0,$7 # note that this is a `long' case L35: .word L19-L35 # For case 0, branch to L19, .word L21-L35 # and so on. .word L23-L35 # Note that these are only word .word L25-L35 # offsets; no long offsets are .word L27-L35 # available. .word L29-L35 .word L31-L35 .word L33-L35 There is nothing the assembler can do at this point. You have several alternatives: alter the compiler to produce a series of if/else tests (preferably via a -J flag); edit the assembly to be a series of if/else tests; or restructure your C code, splitting up the switch statement or making the cases shorter. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690) UUCP: seismo!mimsy!chris ARPA/CSNet: chris@mimsy.umd.edu
herndon@umn-cs.UUCP (01/19/87)
I've had this problem a few times. Try invoking the optimizer on your file. The optimizer gets the assembly code before the assembler does, recognizes that the branch is inappropriate (or something, anyway) and generates an appropriate branch. The only problem is that the optimizer adds significant time to the compilation process. Robert Herndon ...!ihnp4!umn-cs!herndon herndon@umn-cs.ARPA
ram@nucsrl.UUCP (Raman Renu) (01/19/87)
I have a problem in using the C compiler and VAX assembler in our local 4.3BSD(VAX) site. I have a program which has a huge(>900lines) switch statement. /* Whoever said that programmers(pro) don't use case/switch */ The assembler chokes on (>32K long) long branches. Apparently there is a flag "-J" for such purposes (in the assembler) which does not seem to work. The man page for "as" lists under Bugs --------------- BUGS -J should be eliminated; the assembler should automatically choose among byte, word and long branches. _______________ That does not seem to work either. The ouput of the C compiler was ___________________________ Assembler: "/tmp/ctm088343", line 2565: brw: Branch too far(50148b): try -J flag "/tmp/ctm088343", line 2823: brw: Branch too far(48806b): try -J flag "/tmp/ctm088343", line 2922: brw: Branch too far(48313b): try -J flag "/tmp/ctm088343", line 12658: Case will branch too far "/tmp/ctm088343", line 12659: Case will branch too far "/tmp/ctm088343", line 12664: Case will branch too far __________________________ and the ouput of a seperate assembly had the same error message(predictably). Assembler: "prolog.s", line 13337: Case will branch too far "prolog.s", line 13338: Case will branch too far "prolog.s", line 13339: Case will branch too far "prolog.s", line 13340: Case will branch too far This piece of code did compile in a Gould machine but not on the Vax (Code is portable). Could somebody explain and help me solve this problem. Renu Raman ...ihnp4!nucsrl!ram Northwestern Univ. Comp. Sci. Lab. Evanston IL 60201
firth@sei.cmu.edu (Robert Firth) (01/20/87)
In article <6552@alice.uUCp> ark@alice.UUCP writes: >In article <3950006@nucsrl.UUCP>, ram@nucsrl.UUCP writes: >> >> I have a problem in using the C compiler and VAX assembler in our local >> 4.3BSD(VAX) site. I have a program which has a huge(>900lines) case statement. >> >> /* Whoever said that programmers(pro) don't use case/switch */ >> >> The assembler chokes on (>32K long) long branches. Apparently >> there is a flag "-J" for such purposes (in the assembler) >> which does not seem to work. > >The trouble is that a case statement does not generate jump instructions >on the VAX. Instead it generates a CASE instruction. This instruction >also comes in three flavors: byte, word, and longword offsets. It would >not be enough for the assembler to translate the CASEW the compiler >probably generates into a CASEL: the jump table must be translated from >words to longwords too. Sorry, the B/W/L forms refer to the size of the INDEX into the case statement. The displacements are always encoded as 16-bit relative offests. >Portable solutions? I suppose the best bet is to make the switch statement >smaller. One way to do this might be to replace some of the bigger cases >by jumps to code outside the switch statement itself. Ick. Replace the code in the case arms by routine calls. A monolithic chunk of code more than 32k bytes long might even be improved by this change.
amos@instable.UUCP (Amos Shapir) (01/20/87)
A portable kludge solution to the problem: the VAX BSD compiler generates 'casel' instructions only for switches in which the value range is dense, i.e. there are a lot of used values between the highest and lowest case values (I think the criterion is (hi-lo)/nused>=1/3 ). Otherwise, it generates a set of if's, creating in effect a binary search tree. If you add a dummy case with a value that is way out of the range, if's should be created instead of a casel. After that, if the branches are still too long, just do 'sed s/brw/jmp/' on the assembly file. -- Amos Shapir National Semiconductor (Israel) 6 Maskit st. P.O.B. 3007, Herzlia 46104, Israel (011-972) 52-522261 amos%nsta@nsc 34.48'E 32.10'N
donn@utah-cs.UUCP (Donn Seeley) (01/20/87)
Renu Raman asks what one must do in order to compile a huge switch statement on a VAX using the 4.3 BSD PCC. The real answer, as has been suggested by Robert Firth, is to use structured coding techniques to avoid creating monstrous Fortran-style functions. Sometimes one must contend with mechanically generated C code, however, and in such cases it can be useful to know about hacks to squeeze such awful code through the compiler. As Robert Firth says, the VAX CASEx instructions are limited to 16-bit branch offsets; it's this restriction which produces the assembler warning 'Case will branch too far'. (Other VAX instructions which have unexpectedly limited displacement sizes include ACBx, AOBxxx and SOBxxx...) It is possible to force the VAX 4.3 BSD PCC to produce actual tests and jumps instead of a CASEL, however. Unfortunately this is not conditioned on a compiler flag, so the technique qualifies as a hack. The compiler will use a 'heap' switch if there are more than 8 case labels and the difference between the greatest and the least case labels is greater than three times the number of labels (this controls the density of the CASEL branch table). A typical switch uses low-numbered case labels; if you throw in a 'case 0x7fffffff:' with the default label, this should force the compiler to use a 'heap' switch instead of a CASEL switch. A 'heap' switch is a jumble of tests and branches; if these are assembled with the -J flag, they will be able to span a distance of greater than 32 Kb. Robert Herndon suggested that the peephole optimizer can 'fix' huge switch statements. The peephole optimizer won't replace CASEL switches, but it will sometimes rearrange code so that a switch will squeeze inside the range. I don't know if the peephole optimizer will handle most 'typical' huge switches, but I was able to cook up an example just now which was beyond its capacity, so it's not a panacea. People can produce Fortran regardless of the actual coding language, Donn Seeley University of Utah CS Dept donn@cs.utah.edu 40 46' 6"N 111 50' 34"W (801) 581-5668 utah-cs!donn
tps@sdchem.UUCP (Tom Stockfisch) (01/21/87)
In article <53900001@umn-cs.UUCP> herndon@umn-cs.UUCP (Robert Herndon) writes: >I've had this problem a few times. Try invoking the optimizer >on your file. The optimizer gets the assembly code before the >assembler does, recognizes that the branch is inappropriate >(or something, anyway) and generates an appropriate branch. Are you sure your optimizer isn't just optimizing away enough instructions to make the switch no longer span >64K bytes? I had the optimizer on a vax 4.2BSD system save me this way once. By the way, I don't think a huge switch is necessarily indicative of a poorly structured program. The switch could be the result of preprocessor replacement or be generated by another program such as yacc. In the program I wrote where I ran into this trouble my longest function consisted of 40 source code lines, and all the others were less than 20. The whole source file was ~250 lines (including copious comments), yet "cc" generated a ".s" file of 1.2 megabytes. || Tom Stockfisch, UCSD Chemistry tps%chem@sdcsvax.UCSD
herndon@umn-cs.UUCP (01/23/87)
The code in question appears to the York Prolog interpreter. I had exactly the same problem with the interpreter and found that turning on the optimizer fixed the problem. I did not actually examine the assembler code produced. I often ran into strange problems with the BSD 4.2 C compiler and didn't really have time to putz around trying to fix the compiler. As I recall, the York interpreter itself had some problems. Variable lookup was very slow (linear search; not even a hashing scheme) and the initialization time was long (that I fixed by 'checkpointing' the interpreter after initialization and constructing an executable binary image of the initialized interpreter). The code appeared to be otherwise well written in strict ISO pascal. We later got Cprolog -- York is now (virtually) unused. It is much faster, has better debugging features, ... Robert Herndon ...!ihnp4!umn-cs!herndon herndon@umn-cs.ARPA Dept. of Computer Science, Univ. of Minnesota, 136 Lind Hall, 207 Church St. SE Minneapolis, MN 55455
jsdy@hadron.UUCP (02/05/87)
In article <3950007@nucsrl.UUCP> ram@nucsrl.UUCP (Raman Renu) writes: > I have a problem in using the C compiler and VAX assembler in our local >4.3BSD(VAX) site. I have a program which has a huge(>900lines) switch >statement. >The assembler chokes on (>32K long) long branches. We had this problem on an Altos [29]86, 8086 Xenix machine. Never thought that I'd see it on a Vax! The compiler should correctly interpret this. However, the only portable solution we could figure out that was (relatively) quick and easy was to translate the case into if/else if/else if/ ... Speaking of which, I'd like to promote the use of the form: if (...) { ... } else if (...) { ... } else if (...) { ... ... } instead of indenting each successive "if". Where appropriate only, of course. This is advocated in one of the early C Style books. -- Joe Yao hadron!jsdy@seismo.{CSS.GOV,ARPA,UUCP} jsdy@hadron.COM (not yet domainised)
tropp@cthce.UUCP (02/10/87)
In article <449@hadron.UUCP> jsdy@hadron.UUCP (Joseph S. D. Yao) writes: |In article <3950007@nucsrl.UUCP> ram@nucsrl.UUCP (Raman Renu) writes: || I have a problem in using the C compiler and VAX assembler in our local ||4.3BSD(VAX) site. I have a program which has a huge(>900lines) switch ||statement. ||The assembler chokes on (>32K long) long branches. | |Speaking of which, I'd like to promote the use of the form: | if (...) { | ... | } else if (...) { | ... | } else if (...) { | ... ... | } From 4.2BSD(VAX) as man page: -J Use long branches to resolve jumps when byte- displacement branches are insufficient. This must be used when a compiler-generated assembly contains branches of more than 32k bytes.