|
|
1.1 root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.