1756Speter /* Copyright (c) 1979 Regents of the University of California */ 2756Speter 3*10655Speter static char sccsid[] = "@(#)lab.c 1.17 02/01/83"; 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 ); 97*10655Speter 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 ); 1419137Smckusick /* 142*10655Speter * this is a funny jump because it's to a label that 143*10655Speter * has been declared global. 144*10655Speter * Although this branch is within this module 145*10655Speter * the assembler will complain that the destination 146*10655Speter * is a global symbol. 147*10655Speter * The complaint arises because the assembler 148*10655Speter * doesn't change relative jumps into absolute jumps. 149*10655Speter * and this may cause a branch displacement overflow 150*10655Speter * when the module is subsequently linked with 151*10655Speter * the rest of the program. 1529137Smckusick */ 153*10655Speter # ifdef vax 154*10655Speter putprintf(" jmp %s", 0, extname); 155*10655Speter # endif vax 156*10655Speter # ifdef mc68000 157*10655Speter putprintf(" jra %s", 0, extname); 158*10655Speter # endif mc68000 1599127Smckusick } else { 1609127Smckusick /* 1619127Smckusick * Non-local goto. 1629127Smckusick * 1639120Smckusick * Close all active files between top of stack and 1649120Smckusick * frame at the destination level. Then call longjmp 1659120Smckusick * to unwind the stack to the destination level. 1669127Smckusick * 167*10655Speter * For nested routines the end of the frame 168*10655Speter * is calculated as: 169*10655Speter * __disply[bn].fp + sizeof(local frame) 170*10655Speter * (adjusted by (sizeof int) to get just past the end). 1719127Smckusick * The size of the local frame is dumped out by 1729127Smckusick * the second pass as an assembler constant. 1739127Smckusick * The main routine may not be compiled in this 1749127Smckusick * module, so its size may not be available. 1759127Smckusick * However all of its variables will be globally 1769127Smckusick * declared, so only the known runtime temporaries 1779127Smckusick * will be in its stack frame. 178756Speter */ 1799127Smckusick parts[ bn ] |= NONLOCALGOTO; 180756Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1819120Smckusick , "_PCLOSE" ); 1829120Smckusick if ( bn > 1 ) { 1839120Smckusick p = lookup( enclosing[ bn - 1 ] ); 184*10655Speter sprintf( extname, "%s%d+%d", 185*10655Speter FRAME_SIZE_LABEL, p -> value[NL_ENTLOC], sizeof(int)); 1869120Smckusick p = lookup(s); 1879127Smckusick putLV( extname , bn , 0 , NNLOCAL , P2PTR | P2CHAR ); 1889120Smckusick } else { 1899127Smckusick putLV( 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR , 1909127Smckusick P2PTR | P2CHAR ); 1919120Smckusick } 192756Speter putop( P2CALL , P2INT ); 193756Speter putdot( filename , line ); 1949120Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1959120Smckusick , "_longjmp" ); 1969120Smckusick putLV( 0 , bn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 1979120Smckusick extlabname( extname , p -> symbol , bn ); 1989120Smckusick putLV( extname , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); 1999120Smckusick putop( P2LISTOP , P2INT ); 2009120Smckusick putop( P2CALL , P2INT ); 2019120Smckusick putdot( filename , line ); 202756Speter } 203756Speter # endif PC 204756Speter if (bn == cbn) 205756Speter if (p->nl_flags & NFORWD) { 206756Speter if (p->value[NL_GOLEV] == NOTYET) { 207756Speter p->value[NL_GOLEV] = level; 208756Speter p->value[NL_GOLINE] = line; 209756Speter } 210756Speter } else 211756Speter if (p->value[NL_GOLEV] == DEAD) { 212756Speter recovered(); 213756Speter error("Goto %s is into a structured statement", p->symbol); 214756Speter } 215756Speter } 216756Speter 217756Speter /* 218756Speter * Labeled is called when a label 219756Speter * definition is encountered, and 220756Speter * marks that it has been found and 221756Speter * patches the associated GOTO generated 222756Speter * by gotoop. 223756Speter */ 224756Speter labeled(s) 225756Speter char *s; 226756Speter { 227756Speter register struct nl *p; 2283366Speter #ifdef PC 2293366Speter char extname[ BUFSIZ ]; 2303366Speter #endif PC 231756Speter 232756Speter p = lookup(s); 233756Speter if (p == NIL) 234756Speter return (NIL); 235756Speter if (bn != cbn) { 236756Speter error("Label %s not defined in correct block", s); 237756Speter return; 238756Speter } 239756Speter if ((p->nl_flags & NFORWD) == 0) { 240756Speter error("Label %s redefined", s); 241756Speter return; 242756Speter } 243756Speter p->nl_flags &= ~NFORWD; 244756Speter # ifdef OBJ 2457919Smckusick patch4(p->value[NL_ENTLOC]); 246756Speter # endif OBJ 247756Speter # ifdef PC 2484880Speter extlabname( extname , p -> symbol , bn ); 2493366Speter putprintf( "%s:" , 0 , extname ); 250756Speter # endif PC 251756Speter if (p->value[NL_GOLEV] != NOTYET) 252756Speter if (p->value[NL_GOLEV] < level) { 253756Speter recovered(); 254756Speter error("Goto %s from line %d is into a structured statement", s, p->value[NL_GOLINE]); 255756Speter } 256756Speter p->value[NL_GOLEV] = level; 257756Speter } 258756Speter #endif 2594880Speter 2604880Speter #ifdef PC 2614880Speter /* 2624880Speter * construct the long name of a label based on it's static nesting. 2634880Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 2644880Speter */ 2654880Speter extlabname( buffer , name , level ) 2664880Speter char buffer[]; 2674880Speter char *name; 2684880Speter int level; 2694880Speter { 2704880Speter char *starthere; 2714880Speter int i; 2724880Speter 2734880Speter starthere = &buffer[0]; 2744880Speter for ( i = 1 ; i < level ; i++ ) { 2754880Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 2764880Speter starthere += strlen( enclosing[ i ] ) + 1; 2774880Speter } 2784880Speter sprintf( starthere , EXTFORMAT , "" ); 2794880Speter starthere += 1; 2804880Speter sprintf( starthere , LABELFORMAT , name ); 2814880Speter starthere += strlen( name ) + 1; 2824880Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 2834880Speter panic( "extlabname" ); 2844880Speter } 2854880Speter } 2864880Speter #endif PC 287