1: /* 2: * Copyright (c) 1980 Regents of the University of California. 3: * All rights reserved. The Berkeley software License Agreement 4: * specifies the terms and conditions for redistribution. 5: */ 6: 7: #ifndef lint 8: static char sccsid[] = "@(#)lab.c 5.1 (Berkeley) 6/5/85"; 9: #endif not lint 10: 11: #include "whoami.h" 12: #include "0.h" 13: #include "tree.h" 14: #include "opcode.h" 15: #include "objfmt.h" 16: #ifdef PC 17: # include "pc.h" 18: # include <pcc.h> 19: #endif PC 20: #include "tree_ty.h" 21: 22: /* 23: * Label enters the definitions 24: * of the label declaration part 25: * into the namelist. 26: */ 27: label(r, l) 28: struct tnode *r; 29: int l; 30: { 31: static bool label_order = FALSE; 32: static bool label_seen = FALSE; 33: #ifdef PC 34: char extname[ BUFSIZ ]; 35: #endif PC 36: #ifndef PI0 37: register struct tnode *ll; 38: register struct nl *p, *lp; 39: 40: lp = NIL; 41: #else 42: send(REVLAB, r); 43: #endif 44: if ( ! progseen ) { 45: level1(); 46: } 47: line = l; 48: #ifndef PI1 49: if (parts[ cbn ] & (CPRT|TPRT|VPRT|RPRT)){ 50: if ( opt( 's' ) ) { 51: standard(); 52: error("Label declarations should precede const, type, var and routine declarations"); 53: } else { 54: if ( !label_order ) { 55: label_order = TRUE; 56: warning(); 57: error("Label declarations should precede const, type, var and routine declarations"); 58: } 59: } 60: } 61: if (parts[ cbn ] & LPRT) { 62: if ( opt( 's' ) ) { 63: standard(); 64: error("All labels should be declared in one label part"); 65: } else { 66: if ( !label_seen ) { 67: label_seen = TRUE; 68: warning(); 69: error("All labels should be declared in one label part"); 70: } 71: } 72: } 73: parts[ cbn ] |= LPRT; 74: #endif 75: #ifndef PI0 76: for (ll = r; ll != TR_NIL; ll = ll->list_node.next) { 77: l = (int) getlab(); 78: p = enter(defnl((char *) ll->list_node.list, LABEL, NLNIL, 79: (int) l)); 80: /* 81: * Get the label for the eventual target 82: */ 83: p->value[1] = (int) getlab(); 84: p->chain = lp; 85: p->nl_flags |= (NFORWD|NMOD); 86: p->value[NL_GOLEV] = NOTYET; 87: p->value[NL_ENTLOC] = l; 88: lp = p; 89: # ifdef OBJ 90: /* 91: * This operator is between 92: * the bodies of two procedures 93: * and provides a target for 94: * gotos for this label via TRA. 95: */ 96: (void) putlab((char *) l); 97: (void) put(2, O_GOTO | cbn<<8, (long)p->value[1]); 98: # endif OBJ 99: # ifdef PC 100: /* 101: * labels have to be .globl otherwise /lib/c2 may 102: * throw them away if they aren't used in the function 103: * which defines them. 104: */ 105: extlabname( extname , p -> symbol , cbn ); 106: putprintf(" .globl %s", 0, (int) extname); 107: if ( cbn == 1 ) { 108: stabglabel( extname , line ); 109: } 110: # endif PC 111: } 112: gotos[cbn] = lp; 113: # ifdef PTREE 114: { 115: pPointer Labels = LabelDCopy( r ); 116: 117: pDEF( PorFHeader[ nesting ] ).PorFLabels = Labels; 118: } 119: # endif PTREE 120: #endif 121: } 122: 123: #ifndef PI0 124: /* 125: * Gotoop is called when 126: * we get a statement "goto label" 127: * and generates the needed tra. 128: */ 129: gotoop(s) 130: char *s; 131: { 132: register struct nl *p; 133: #ifdef PC 134: char extname[ BUFSIZ ]; 135: #endif PC 136: 137: gocnt++; 138: p = lookup(s); 139: if (p == NIL) 140: return; 141: # ifdef OBJ 142: (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]); 143: # endif OBJ 144: # ifdef PC 145: if ( cbn == bn ) { 146: /* 147: * local goto. 148: */ 149: extlabname( extname , p -> symbol , bn ); 150: /* 151: * this is a funny jump because it's to a label that 152: * has been declared global. 153: * Although this branch is within this module 154: * the assembler will complain that the destination 155: * is a global symbol. 156: * The complaint arises because the assembler 157: * doesn't change relative jumps into absolute jumps. 158: * and this may cause a branch displacement overflow 159: * when the module is subsequently linked with 160: * the rest of the program. 161: */ 162: # ifdef vax 163: putprintf(" jmp %s", 0, (int) extname); 164: # endif vax 165: # ifdef mc68000 166: putprintf(" jra %s", 0, (int) extname); 167: # endif mc68000 168: } else { 169: /* 170: * Non-local goto. 171: * 172: * Close all active files between top of stack and 173: * frame at the destination level. Then call longjmp 174: * to unwind the stack to the destination level. 175: * 176: * For nested routines the end of the frame 177: * is calculated as: 178: * __disply[bn].fp + sizeof(local frame) 179: * (adjusted by (sizeof int) to get just past the end). 180: * The size of the local frame is dumped out by 181: * the second pass as an assembler constant. 182: * The main routine may not be compiled in this 183: * module, so its size may not be available. 184: * However all of its variables will be globally 185: * declared, so only the known runtime temporaries 186: * will be in its stack frame. 187: */ 188: parts[ bn ] |= NONLOCALGOTO; 189: putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 190: , "_PCLOSE" ); 191: if ( bn > 1 ) { 192: p = lookup( enclosing[ bn - 1 ] ); 193: sprintf( extname, "%s%d+%d", 194: FRAME_SIZE_LABEL, p -> value[NL_ENTLOC], sizeof(int)); 195: p = lookup(s); 196: putLV( extname , bn , 0 , NNLOCAL , PCCTM_PTR | PCCT_CHAR ); 197: } else { 198: putLV((char *) 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR , 199: PCCTM_PTR | PCCT_CHAR ); 200: } 201: putop( PCC_CALL , PCCT_INT ); 202: putdot( filename , line ); 203: putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 204: , "_longjmp" ); 205: putLV((char *) 0 , bn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY ); 206: extlabname( extname , p -> symbol , bn ); 207: putLV( extname , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY ); 208: putop( PCC_CM , PCCT_INT ); 209: putop( PCC_CALL , PCCT_INT ); 210: putdot( filename , line ); 211: } 212: # endif PC 213: if (bn == cbn) 214: if (p->nl_flags & NFORWD) { 215: if (p->value[NL_GOLEV] == NOTYET) { 216: p->value[NL_GOLEV] = level; 217: p->value[NL_GOLINE] = line; 218: } 219: } else 220: if (p->value[NL_GOLEV] == DEAD) { 221: recovered(); 222: error("Goto %s is into a structured statement", p->symbol); 223: } 224: } 225: 226: /* 227: * Labeled is called when a label 228: * definition is encountered, and 229: * marks that it has been found and 230: * patches the associated GOTO generated 231: * by gotoop. 232: */ 233: labeled(s) 234: char *s; 235: { 236: register struct nl *p; 237: #ifdef PC 238: char extname[ BUFSIZ ]; 239: #endif PC 240: 241: p = lookup(s); 242: if (p == NIL) 243: return; 244: if (bn != cbn) { 245: error("Label %s not defined in correct block", s); 246: return; 247: } 248: if ((p->nl_flags & NFORWD) == 0) { 249: error("Label %s redefined", s); 250: return; 251: } 252: p->nl_flags &= ~NFORWD; 253: # ifdef OBJ 254: patch4((PTR_DCL) p->value[NL_ENTLOC]); 255: # endif OBJ 256: # ifdef PC 257: extlabname( extname , p -> symbol , bn ); 258: putprintf( "%s:" , 0 , (int) extname ); 259: # endif PC 260: if (p->value[NL_GOLEV] != NOTYET) 261: if (p->value[NL_GOLEV] < level) { 262: recovered(); 263: error("Goto %s from line %d is into a structured statement", s, (char *) p->value[NL_GOLINE]); 264: } 265: p->value[NL_GOLEV] = level; 266: } 267: #endif 268: 269: #ifdef PC 270: /* 271: * construct the long name of a label based on it's static nesting. 272: * into a caller-supplied buffer (that should be about BUFSIZ big). 273: */ 274: extlabname( buffer , name , level ) 275: char buffer[]; 276: char *name; 277: int level; 278: { 279: char *starthere; 280: int i; 281: 282: starthere = &buffer[0]; 283: for ( i = 1 ; i < level ; i++ ) { 284: sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 285: starthere += strlen( enclosing[ i ] ) + 1; 286: } 287: sprintf( starthere , EXTFORMAT , "" ); 288: starthere += 1; 289: sprintf( starthere , LABELFORMAT , name ); 290: starthere += strlen( name ) + 1; 291: if ( starthere >= &buffer[ BUFSIZ ] ) { 292: panic( "extlabname" ); 293: } 294: } 295: #endif PC