1756Speter /* Copyright (c) 1979 Regents of the University of California */ 2756Speter 3*14733Sthien #ifndef lint 4*14733Sthien static char sccsid[] = "@(#)lab.c 1.18 08/19/83"; 5*14733Sthien #endif 6756Speter 7756Speter #include "whoami.h" 8756Speter #include "0.h" 9756Speter #include "tree.h" 10756Speter #include "opcode.h" 11756Speter #include "objfmt.h" 12756Speter #ifdef PC 13756Speter # include "pc.h" 14756Speter # include "pcops.h" 15756Speter #endif PC 16*14733Sthien #include "tree_ty.h" 17756Speter 18756Speter /* 19756Speter * Label enters the definitions 20756Speter * of the label declaration part 21756Speter * into the namelist. 22756Speter */ 23756Speter label(r, l) 24*14733Sthien struct tnode *r; 25*14733Sthien int l; 26756Speter { 277951Speter static bool label_order = FALSE; 287951Speter static bool label_seen = FALSE; 293366Speter #ifdef PC 303366Speter char extname[ BUFSIZ ]; 313366Speter #endif PC 32756Speter #ifndef PI0 33*14733Sthien register struct tnode *ll; 34756Speter register struct nl *p, *lp; 35756Speter 36756Speter lp = NIL; 37756Speter #else 38756Speter send(REVLAB, r); 39756Speter #endif 40756Speter if ( ! progseen ) { 41756Speter level1(); 42756Speter } 43756Speter line = l; 44756Speter #ifndef PI1 45835Speter if (parts[ cbn ] & (CPRT|TPRT|VPRT|RPRT)){ 46835Speter if ( opt( 's' ) ) { 47756Speter standard(); 487951Speter error("Label declarations should precede const, type, var and routine declarations"); 49835Speter } else { 507951Speter if ( !label_order ) { 517951Speter label_order = TRUE; 527951Speter warning(); 537951Speter error("Label declarations should precede const, type, var and routine declarations"); 547951Speter } 55835Speter } 56756Speter } 57835Speter if (parts[ cbn ] & LPRT) { 58835Speter if ( opt( 's' ) ) { 59756Speter standard(); 607951Speter error("All labels should be declared in one label part"); 61835Speter } else { 627951Speter if ( !label_seen ) { 637951Speter label_seen = TRUE; 647951Speter warning(); 657951Speter error("All labels should be declared in one label part"); 667951Speter } 67835Speter } 68756Speter } 69835Speter parts[ cbn ] |= LPRT; 70756Speter #endif 71756Speter #ifndef PI0 72*14733Sthien for (ll = r; ll != TR_NIL; ll = ll->list_node.next) { 73*14733Sthien l = (int) getlab(); 74*14733Sthien p = enter(defnl((char *) ll->list_node.list, LABEL, NLNIL, 75*14733Sthien (int) l)); 76756Speter /* 77756Speter * Get the label for the eventual target 78756Speter */ 79*14733Sthien p->value[1] = (int) getlab(); 80756Speter p->chain = lp; 81756Speter p->nl_flags |= (NFORWD|NMOD); 82756Speter p->value[NL_GOLEV] = NOTYET; 837919Smckusick p->value[NL_ENTLOC] = l; 84756Speter lp = p; 85756Speter # ifdef OBJ 86756Speter /* 87756Speter * This operator is between 88756Speter * the bodies of two procedures 89756Speter * and provides a target for 90756Speter * gotos for this label via TRA. 91756Speter */ 92*14733Sthien (void) putlab((char *) l); 93*14733Sthien (void) put(2, O_GOTO | cbn<<8, (long)p->value[1]); 94756Speter # endif OBJ 95756Speter # ifdef PC 96756Speter /* 97756Speter * labels have to be .globl otherwise /lib/c2 may 98756Speter * throw them away if they aren't used in the function 99756Speter * which defines them. 100756Speter */ 1014880Speter extlabname( extname , p -> symbol , cbn ); 102*14733Sthien putprintf(" .globl %s", 0, (int) extname); 1033366Speter if ( cbn == 1 ) { 1043366Speter stabglabel( extname , line ); 105756Speter } 106756Speter # endif PC 107756Speter } 108756Speter gotos[cbn] = lp; 109756Speter # ifdef PTREE 110756Speter { 111756Speter pPointer Labels = LabelDCopy( r ); 112756Speter 113756Speter pDEF( PorFHeader[ nesting ] ).PorFLabels = Labels; 114756Speter } 115756Speter # endif PTREE 116756Speter #endif 117756Speter } 118756Speter 119756Speter #ifndef PI0 120756Speter /* 121756Speter * Gotoop is called when 122756Speter * we get a statement "goto label" 123756Speter * and generates the needed tra. 124756Speter */ 125756Speter gotoop(s) 126756Speter char *s; 127756Speter { 128756Speter register struct nl *p; 1293366Speter #ifdef PC 1303366Speter char extname[ BUFSIZ ]; 1313366Speter #endif PC 132756Speter 133756Speter gocnt++; 134756Speter p = lookup(s); 135756Speter if (p == NIL) 136*14733Sthien return; 137756Speter # ifdef OBJ 138*14733Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 139756Speter # endif OBJ 140756Speter # ifdef PC 1419127Smckusick if ( cbn == bn ) { 142756Speter /* 1439127Smckusick * local goto. 1449127Smckusick */ 1459127Smckusick extlabname( extname , p -> symbol , bn ); 1469137Smckusick /* 14710655Speter * this is a funny jump because it's to a label that 14810655Speter * has been declared global. 14910655Speter * Although this branch is within this module 15010655Speter * the assembler will complain that the destination 15110655Speter * is a global symbol. 15210655Speter * The complaint arises because the assembler 15310655Speter * doesn't change relative jumps into absolute jumps. 15410655Speter * and this may cause a branch displacement overflow 15510655Speter * when the module is subsequently linked with 15610655Speter * the rest of the program. 1579137Smckusick */ 15810655Speter # ifdef vax 159*14733Sthien putprintf(" jmp %s", 0, (int) extname); 16010655Speter # endif vax 16110655Speter # ifdef mc68000 162*14733Sthien putprintf(" jra %s", 0, (int) extname); 16310655Speter # endif mc68000 1649127Smckusick } else { 1659127Smckusick /* 1669127Smckusick * Non-local goto. 1679127Smckusick * 1689120Smckusick * Close all active files between top of stack and 1699120Smckusick * frame at the destination level. Then call longjmp 1709120Smckusick * to unwind the stack to the destination level. 1719127Smckusick * 17210655Speter * For nested routines the end of the frame 17310655Speter * is calculated as: 17410655Speter * __disply[bn].fp + sizeof(local frame) 17510655Speter * (adjusted by (sizeof int) to get just past the end). 1769127Smckusick * The size of the local frame is dumped out by 1779127Smckusick * the second pass as an assembler constant. 1789127Smckusick * The main routine may not be compiled in this 1799127Smckusick * module, so its size may not be available. 1809127Smckusick * However all of its variables will be globally 1819127Smckusick * declared, so only the known runtime temporaries 1829127Smckusick * will be in its stack frame. 183756Speter */ 1849127Smckusick parts[ bn ] |= NONLOCALGOTO; 185756Speter putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 1869120Smckusick , "_PCLOSE" ); 1879120Smckusick if ( bn > 1 ) { 1889120Smckusick p = lookup( enclosing[ bn - 1 ] ); 18910655Speter sprintf( extname, "%s%d+%d", 19010655Speter FRAME_SIZE_LABEL, p -> value[NL_ENTLOC], sizeof(int)); 1919120Smckusick p = lookup(s); 1929127Smckusick putLV( extname , bn , 0 , NNLOCAL , P2PTR | P2CHAR ); 1939120Smckusick } else { 194*14733Sthien putLV((char *) 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR , 1959127Smckusick P2PTR | P2CHAR ); 1969120Smckusick } 197756Speter putop( P2CALL , P2INT ); 198756Speter putdot( filename , line ); 1999120Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 2009120Smckusick , "_longjmp" ); 201*14733Sthien putLV((char *) 0 , bn , GOTOENVOFFSET , NLOCAL , P2PTR|P2STRTY ); 2029120Smckusick extlabname( extname , p -> symbol , bn ); 2039120Smckusick putLV( extname , 0 , 0 , NGLOBAL , P2PTR|P2STRTY ); 2049120Smckusick putop( P2LISTOP , P2INT ); 2059120Smckusick putop( P2CALL , P2INT ); 2069120Smckusick putdot( filename , line ); 207756Speter } 208756Speter # endif PC 209756Speter if (bn == cbn) 210756Speter if (p->nl_flags & NFORWD) { 211756Speter if (p->value[NL_GOLEV] == NOTYET) { 212756Speter p->value[NL_GOLEV] = level; 213756Speter p->value[NL_GOLINE] = line; 214756Speter } 215756Speter } else 216756Speter if (p->value[NL_GOLEV] == DEAD) { 217756Speter recovered(); 218756Speter error("Goto %s is into a structured statement", p->symbol); 219756Speter } 220756Speter } 221756Speter 222756Speter /* 223756Speter * Labeled is called when a label 224756Speter * definition is encountered, and 225756Speter * marks that it has been found and 226756Speter * patches the associated GOTO generated 227756Speter * by gotoop. 228756Speter */ 229756Speter labeled(s) 230756Speter char *s; 231756Speter { 232756Speter register struct nl *p; 2333366Speter #ifdef PC 2343366Speter char extname[ BUFSIZ ]; 2353366Speter #endif PC 236756Speter 237756Speter p = lookup(s); 238756Speter if (p == NIL) 239*14733Sthien return; 240756Speter if (bn != cbn) { 241756Speter error("Label %s not defined in correct block", s); 242756Speter return; 243756Speter } 244756Speter if ((p->nl_flags & NFORWD) == 0) { 245756Speter error("Label %s redefined", s); 246756Speter return; 247756Speter } 248756Speter p->nl_flags &= ~NFORWD; 249756Speter # ifdef OBJ 250*14733Sthien patch4((PTR_DCL) p->value[NL_ENTLOC]); 251756Speter # endif OBJ 252756Speter # ifdef PC 2534880Speter extlabname( extname , p -> symbol , bn ); 254*14733Sthien putprintf( "%s:" , 0 , (int) extname ); 255756Speter # endif PC 256756Speter if (p->value[NL_GOLEV] != NOTYET) 257756Speter if (p->value[NL_GOLEV] < level) { 258756Speter recovered(); 259*14733Sthien error("Goto %s from line %d is into a structured statement", s, (char *) p->value[NL_GOLINE]); 260756Speter } 261756Speter p->value[NL_GOLEV] = level; 262756Speter } 263756Speter #endif 2644880Speter 2654880Speter #ifdef PC 2664880Speter /* 2674880Speter * construct the long name of a label based on it's static nesting. 2684880Speter * into a caller-supplied buffer (that should be about BUFSIZ big). 2694880Speter */ 2704880Speter extlabname( buffer , name , level ) 2714880Speter char buffer[]; 2724880Speter char *name; 2734880Speter int level; 2744880Speter { 2754880Speter char *starthere; 2764880Speter int i; 2774880Speter 2784880Speter starthere = &buffer[0]; 2794880Speter for ( i = 1 ; i < level ; i++ ) { 2804880Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 2814880Speter starthere += strlen( enclosing[ i ] ) + 1; 2824880Speter } 2834880Speter sprintf( starthere , EXTFORMAT , "" ); 2844880Speter starthere += 1; 2854880Speter sprintf( starthere , LABELFORMAT , name ); 2864880Speter starthere += strlen( name ) + 1; 2874880Speter if ( starthere >= &buffer[ BUFSIZ ] ) { 2884880Speter panic( "extlabname" ); 2894880Speter } 2904880Speter } 2914880Speter #endif PC 292