1756Speter /* Copyright (c) 1979 Regents of the University of California */ 2756Speter 3*9127Smckusick static char sccsid[] = "@(#)lab.c 1.15 11/11/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 136*9127Smckusick if ( cbn == bn ) { 137756Speter /* 138*9127Smckusick * local goto. 139*9127Smckusick */ 140*9127Smckusick extlabname( extname , p -> symbol , bn ); 141*9127Smckusick putprintf( " jbr %s" , 0 , extname ); 142*9127Smckusick } else { 143*9127Smckusick /* 144*9127Smckusick * Non-local goto. 145*9127Smckusick * 1469120Smckusick * Close all active files between top of stack and 1479120Smckusick * frame at the destination level. Then call longjmp 1489120Smckusick * to unwind the stack to the destination level. 149*9127Smckusick * 150*9127Smckusick * For nested routines the end is calculated as: 151*9127Smckusick * __disply[ bn ] . ap + sizeof( local frame ) 152*9127Smckusick * The size of the local frame is dumped out by 153*9127Smckusick * the second pass as an assembler constant. 154*9127Smckusick * The main routine may not be compiled in this 155*9127Smckusick * module, so its size may not be available. 156*9127Smckusick * However all of its variables will be globally 157*9127Smckusick * declared, so only the known runtime temporaries 158*9127Smckusick * will be in its stack frame. 159756Speter */ 160*9127Smckusick parts[ bn ] |= NONLOCALGOTO; 161756Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1629120Smckusick , "_PCLOSE" ); 1639120Smckusick if ( bn > 1 ) { 1649120Smckusick p = lookup( enclosing[ bn - 1 ] ); 1659120Smckusick sprintf( extname, "LF%d+%d", p -> value[ NL_ENTLOC ] 1669120Smckusick , sizeof( int ) ); 1679120Smckusick p = lookup(s); 168*9127Smckusick putLV( extname , bn , 0 , NNLOCAL , P2PTR | P2CHAR ); 1699120Smckusick } else { 170*9127Smckusick putLV( 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR , 171*9127Smckusick P2PTR | P2CHAR ); 1729120Smckusick } 173756Speter putop( P2CALL , P2INT ); 174756Speter putdot( filename , line ); 1759120Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1769120Smckusick , "_longjmp" ); 1779120Smckusick putLV( 0 , bn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 1789120Smckusick extlabname( extname , p -> symbol , bn ); 1799120Smckusick putLV( extname , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); 1809120Smckusick putop( P2LISTOP , P2INT ); 1819120Smckusick putop( P2CALL , P2INT ); 1829120Smckusick putdot( filename , line ); 183756Speter } 184756Speter # endif PC 185756Speter if (bn == cbn) 186756Speter if (p->nl_flags & NFORWD) { 187756Speter if (p->value[NL_GOLEV] == NOTYET) { 188756Speter p->value[NL_GOLEV] = level; 189756Speter p->value[NL_GOLINE] = line; 190756Speter } 191756Speter } else 192756Speter if (p->value[NL_GOLEV] == DEAD) { 193756Speter recovered(); 194756Speter error("Goto %s is into a structured statement", p->symbol); 195756Speter } 196756Speter } 197756Speter 198756Speter /* 199756Speter * Labeled is called when a label 200756Speter * definition is encountered, and 201756Speter * marks that it has been found and 202756Speter * patches the associated GOTO generated 203756Speter * by gotoop. 204756Speter */ 205756Speter labeled(s) 206756Speter char *s; 207756Speter { 208756Speter register struct nl *p; 2093366Speter #ifdef PC 2103366Speter char extname[ BUFSIZ ]; 2113366Speter #endif PC 212756Speter 213756Speter p = lookup(s); 214756Speter if (p == NIL) 215756Speter return (NIL); 216756Speter if (bn != cbn) { 217756Speter error("Label %s not defined in correct block", s); 218756Speter return; 219756Speter } 220756Speter if ((p->nl_flags & NFORWD) == 0) { 221756Speter error("Label %s redefined", s); 222756Speter return; 223756Speter } 224756Speter p->nl_flags &= ~NFORWD; 225756Speter # ifdef OBJ 2267919Smckusick patch4(p->value[NL_ENTLOC]); 227756Speter # endif OBJ 228756Speter # ifdef PC 2294880Speter extlabname( extname , p -> symbol , bn ); 2303366Speter putprintf( "%s:" , 0 , extname ); 231756Speter # endif PC 232756Speter if (p->value[NL_GOLEV] != NOTYET) 233756Speter if (p->value[NL_GOLEV] < level) { 234756Speter recovered(); 235756Speter error("Goto %s from line %d is into a structured statement", s, p->value[NL_GOLINE]); 236756Speter } 237756Speter p->value[NL_GOLEV] = level; 238756Speter } 239756Speter #endif 2404880Speter 2414880Speter #ifdef PC 2424880Speter /* 2434880Speter * construct the long name of a label based on it's static nesting. 2444880Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 2454880Speter */ 2464880Speter extlabname( buffer , name , level ) 2474880Speter char buffer[]; 2484880Speter char *name; 2494880Speter int level; 2504880Speter { 2514880Speter char *starthere; 2524880Speter int i; 2534880Speter 2544880Speter starthere = &buffer[0]; 2554880Speter for ( i = 1 ; i < level ; i++ ) { 2564880Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 2574880Speter starthere += strlen( enclosing[ i ] ) + 1; 2584880Speter } 2594880Speter sprintf( starthere , EXTFORMAT , "" ); 2604880Speter starthere += 1; 2614880Speter sprintf( starthere , LABELFORMAT , name ); 2624880Speter starthere += strlen( name ) + 1; 2634880Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 2644880Speter panic( "extlabname" ); 2654880Speter } 2664880Speter } 2674880Speter #endif PC 268