1756Speter /* Copyright (c) 1979 Regents of the University of California */ 2756Speter 3*9137Smckusick static char sccsid[] = "@(#)lab.c 1.16 11/12/82"; 4756Speter 5756Speter #include "whoami.h" 6756Speter #include "0.h" 7756Speter #include "tree.h" 8756Speter #include "opcode.h" 9756Speter #include "objfmt.h" 10756Speter #ifdef PC 11756Speter # include "pc.h" 12756Speter # include "pcops.h" 13756Speter #endif PC 14756Speter 15756Speter /* 16756Speter * Label enters the definitions 17756Speter * of the label declaration part 18756Speter * into the namelist. 19756Speter */ 20756Speter label(r, l) 21756Speter int *r, l; 22756Speter { 237951Speter static bool label_order = FALSE; 247951Speter static bool label_seen = FALSE; 253366Speter #ifdef PC 263366Speter char extname[ BUFSIZ ]; 273366Speter #endif PC 28756Speter #ifndef PI0 29756Speter register *ll; 30756Speter register struct nl *p, *lp; 31756Speter 32756Speter lp = NIL; 33756Speter #else 34756Speter send(REVLAB, r); 35756Speter #endif 36756Speter if ( ! progseen ) { 37756Speter level1(); 38756Speter } 39756Speter line = l; 40756Speter #ifndef PI1 41835Speter if (parts[ cbn ] & (CPRT|TPRT|VPRT|RPRT)){ 42835Speter if ( opt( 's' ) ) { 43756Speter standard(); 447951Speter error("Label declarations should precede const, type, var and routine declarations"); 45835Speter } else { 467951Speter if ( !label_order ) { 477951Speter label_order = TRUE; 487951Speter warning(); 497951Speter error("Label declarations should precede const, type, var and routine declarations"); 507951Speter } 51835Speter } 52756Speter } 53835Speter if (parts[ cbn ] & LPRT) { 54835Speter if ( opt( 's' ) ) { 55756Speter standard(); 567951Speter error("All labels should be declared in one label part"); 57835Speter } else { 587951Speter if ( !label_seen ) { 597951Speter label_seen = TRUE; 607951Speter warning(); 617951Speter error("All labels should be declared in one label part"); 627951Speter } 63835Speter } 64756Speter } 65835Speter parts[ cbn ] |= LPRT; 66756Speter #endif 67756Speter #ifndef PI0 68756Speter for (ll = r; ll != NIL; ll = ll[2]) { 69756Speter l = getlab(); 70756Speter p = enter(defnl(ll[1], LABEL, 0, l)); 71756Speter /* 72756Speter * Get the label for the eventual target 73756Speter */ 74756Speter p->value[1] = getlab(); 75756Speter p->chain = lp; 76756Speter p->nl_flags |= (NFORWD|NMOD); 77756Speter p->value[NL_GOLEV] = NOTYET; 787919Smckusick p->value[NL_ENTLOC] = l; 79756Speter lp = p; 80756Speter # ifdef OBJ 81756Speter /* 82756Speter * This operator is between 83756Speter * the bodies of two procedures 84756Speter * and provides a target for 85756Speter * gotos for this label via TRA. 86756Speter */ 87756Speter putlab(l); 883074Smckusic put(2, O_GOTO | cbn<<8, (long)p->value[1]); 89756Speter # endif OBJ 90756Speter # ifdef PC 91756Speter /* 92756Speter * labels have to be .globl otherwise /lib/c2 may 93756Speter * throw them away if they aren't used in the function 94756Speter * which defines them. 95756Speter */ 964880Speter extlabname( extname , p -> symbol , cbn ); 973366Speter putprintf( " .globl %s" , 0 , extname ); 983366Speter if ( cbn == 1 ) { 993366Speter stabglabel( extname , line ); 100756Speter } 101756Speter # endif PC 102756Speter } 103756Speter gotos[cbn] = lp; 104756Speter # ifdef PTREE 105756Speter { 106756Speter pPointer Labels = LabelDCopy( r ); 107756Speter 108756Speter pDEF( PorFHeader[ nesting ] ).PorFLabels = Labels; 109756Speter } 110756Speter # endif PTREE 111756Speter #endif 112756Speter } 113756Speter 114756Speter #ifndef PI0 115756Speter /* 116756Speter * Gotoop is called when 117756Speter * we get a statement "goto label" 118756Speter * and generates the needed tra. 119756Speter */ 120756Speter gotoop(s) 121756Speter char *s; 122756Speter { 123756Speter register struct nl *p; 1243366Speter #ifdef PC 1253366Speter char extname[ BUFSIZ ]; 1263366Speter #endif PC 127756Speter 128756Speter gocnt++; 129756Speter p = lookup(s); 130756Speter if (p == NIL) 131756Speter return (NIL); 132756Speter # ifdef OBJ 1337919Smckusick put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 134756Speter # endif OBJ 135756Speter # ifdef PC 1369127Smckusick if ( cbn == bn ) { 137756Speter /* 1389127Smckusick * local goto. 1399127Smckusick */ 1409127Smckusick extlabname( extname , p -> symbol , bn ); 141*9137Smckusick /* 142*9137Smckusick * this is a jmp because it's a jump to a label that 143*9137Smckusick * has been declared global. Although this branch is 144*9137Smckusick * within this module the assembler will complain that 145*9137Smckusick * the destination is a global symbol. The complaint 146*9137Smckusick * arises because the assembler doesn't change jbr's 147*9137Smckusick * into jmp's and consequently may cause a branch 148*9137Smckusick * displacement overflow when the module is subsequently 149*9137Smckusick * linked into the rest of the program. 150*9137Smckusick */ 151*9137Smckusick putprintf( " jmp %s" , 0 , extname ); 1529127Smckusick } else { 1539127Smckusick /* 1549127Smckusick * Non-local goto. 1559127Smckusick * 1569120Smckusick * Close all active files between top of stack and 1579120Smckusick * frame at the destination level. Then call longjmp 1589120Smckusick * to unwind the stack to the destination level. 1599127Smckusick * 1609127Smckusick * For nested routines the end is calculated as: 1619127Smckusick * __disply[ bn ] . ap + sizeof( local frame ) 1629127Smckusick * The size of the local frame is dumped out by 1639127Smckusick * the second pass as an assembler constant. 1649127Smckusick * The main routine may not be compiled in this 1659127Smckusick * module, so its size may not be available. 1669127Smckusick * However all of its variables will be globally 1679127Smckusick * declared, so only the known runtime temporaries 1689127Smckusick * will be in its stack frame. 169756Speter */ 1709127Smckusick parts[ bn ] |= NONLOCALGOTO; 171756Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1729120Smckusick , "_PCLOSE" ); 1739120Smckusick if ( bn > 1 ) { 1749120Smckusick p = lookup( enclosing[ bn - 1 ] ); 1759120Smckusick sprintf( extname, "LF%d+%d", p -> value[ NL_ENTLOC ] 1769120Smckusick , sizeof( int ) ); 1779120Smckusick p = lookup(s); 1789127Smckusick putLV( extname , bn , 0 , NNLOCAL , P2PTR | P2CHAR ); 1799120Smckusick } else { 1809127Smckusick putLV( 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR , 1819127Smckusick P2PTR | P2CHAR ); 1829120Smckusick } 183756Speter putop( P2CALL , P2INT ); 184756Speter putdot( filename , line ); 1859120Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1869120Smckusick , "_longjmp" ); 1879120Smckusick putLV( 0 , bn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 1889120Smckusick extlabname( extname , p -> symbol , bn ); 1899120Smckusick putLV( extname , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); 1909120Smckusick putop( P2LISTOP , P2INT ); 1919120Smckusick putop( P2CALL , P2INT ); 1929120Smckusick putdot( filename , line ); 193756Speter } 194756Speter # endif PC 195756Speter if (bn == cbn) 196756Speter if (p->nl_flags & NFORWD) { 197756Speter if (p->value[NL_GOLEV] == NOTYET) { 198756Speter p->value[NL_GOLEV] = level; 199756Speter p->value[NL_GOLINE] = line; 200756Speter } 201756Speter } else 202756Speter if (p->value[NL_GOLEV] == DEAD) { 203756Speter recovered(); 204756Speter error("Goto %s is into a structured statement", p->symbol); 205756Speter } 206756Speter } 207756Speter 208756Speter /* 209756Speter * Labeled is called when a label 210756Speter * definition is encountered, and 211756Speter * marks that it has been found and 212756Speter * patches the associated GOTO generated 213756Speter * by gotoop. 214756Speter */ 215756Speter labeled(s) 216756Speter char *s; 217756Speter { 218756Speter register struct nl *p; 2193366Speter #ifdef PC 2203366Speter char extname[ BUFSIZ ]; 2213366Speter #endif PC 222756Speter 223756Speter p = lookup(s); 224756Speter if (p == NIL) 225756Speter return (NIL); 226756Speter if (bn != cbn) { 227756Speter error("Label %s not defined in correct block", s); 228756Speter return; 229756Speter } 230756Speter if ((p->nl_flags & NFORWD) == 0) { 231756Speter error("Label %s redefined", s); 232756Speter return; 233756Speter } 234756Speter p->nl_flags &= ~NFORWD; 235756Speter # ifdef OBJ 2367919Smckusick patch4(p->value[NL_ENTLOC]); 237756Speter # endif OBJ 238756Speter # ifdef PC 2394880Speter extlabname( extname , p -> symbol , bn ); 2403366Speter putprintf( "%s:" , 0 , extname ); 241756Speter # endif PC 242756Speter if (p->value[NL_GOLEV] != NOTYET) 243756Speter if (p->value[NL_GOLEV] < level) { 244756Speter recovered(); 245756Speter error("Goto %s from line %d is into a structured statement", s, p->value[NL_GOLINE]); 246756Speter } 247756Speter p->value[NL_GOLEV] = level; 248756Speter } 249756Speter #endif 2504880Speter 2514880Speter #ifdef PC 2524880Speter /* 2534880Speter * construct the long name of a label based on it's static nesting. 2544880Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 2554880Speter */ 2564880Speter extlabname( buffer , name , level ) 2574880Speter char buffer[]; 2584880Speter char *name; 2594880Speter int level; 2604880Speter { 2614880Speter char *starthere; 2624880Speter int i; 2634880Speter 2644880Speter starthere = &buffer[0]; 2654880Speter for ( i = 1 ; i < level ; i++ ) { 2664880Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 2674880Speter starthere += strlen( enclosing[ i ] ) + 1; 2684880Speter } 2694880Speter sprintf( starthere , EXTFORMAT , "" ); 2704880Speter starthere += 1; 2714880Speter sprintf( starthere , LABELFORMAT , name ); 2724880Speter starthere += strlen( name ) + 1; 2734880Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 2744880Speter panic( "extlabname" ); 2754880Speter } 2764880Speter } 2774880Speter #endif PC 278