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