148116Sbostic /*-
2*62213Sbostic * Copyright (c) 1980, 1993
3*62213Sbostic * The Regents of the University of California. All rights reserved.
448116Sbostic *
548116Sbostic * %sccs.include.redist.c%
622172Sdist */
7756Speter
814733Sthien #ifndef lint
9*62213Sbostic static char sccsid[] = "@(#)lab.c 8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11756Speter
12756Speter #include "whoami.h"
13756Speter #include "0.h"
14756Speter #include "tree.h"
15756Speter #include "opcode.h"
16756Speter #include "objfmt.h"
17756Speter #ifdef PC
18756Speter # include "pc.h"
1918460Sralph # include <pcc.h>
20756Speter #endif PC
2114733Sthien #include "tree_ty.h"
22756Speter
23756Speter /*
24756Speter * Label enters the definitions
25756Speter * of the label declaration part
26756Speter * into the namelist.
27756Speter */
28756Speter label(r, l)
2914733Sthien struct tnode *r;
3014733Sthien int l;
31756Speter {
327951Speter static bool label_order = FALSE;
337951Speter static bool label_seen = FALSE;
343366Speter #ifdef PC
353366Speter char extname[ BUFSIZ ];
363366Speter #endif PC
37756Speter #ifndef PI0
3814733Sthien register struct tnode *ll;
39756Speter register struct nl *p, *lp;
40756Speter
41756Speter lp = NIL;
42756Speter #else
43756Speter send(REVLAB, r);
44756Speter #endif
45756Speter if ( ! progseen ) {
46756Speter level1();
47756Speter }
48756Speter line = l;
49756Speter #ifndef PI1
50835Speter if (parts[ cbn ] & (CPRT|TPRT|VPRT|RPRT)){
51835Speter if ( opt( 's' ) ) {
52756Speter standard();
537951Speter error("Label declarations should precede const, type, var and routine declarations");
54835Speter } else {
557951Speter if ( !label_order ) {
567951Speter label_order = TRUE;
577951Speter warning();
587951Speter error("Label declarations should precede const, type, var and routine declarations");
597951Speter }
60835Speter }
61756Speter }
62835Speter if (parts[ cbn ] & LPRT) {
63835Speter if ( opt( 's' ) ) {
64756Speter standard();
657951Speter error("All labels should be declared in one label part");
66835Speter } else {
677951Speter if ( !label_seen ) {
687951Speter label_seen = TRUE;
697951Speter warning();
707951Speter error("All labels should be declared in one label part");
717951Speter }
72835Speter }
73756Speter }
74835Speter parts[ cbn ] |= LPRT;
75756Speter #endif
76756Speter #ifndef PI0
7714733Sthien for (ll = r; ll != TR_NIL; ll = ll->list_node.next) {
7814733Sthien l = (int) getlab();
7914733Sthien p = enter(defnl((char *) ll->list_node.list, LABEL, NLNIL,
8014733Sthien (int) l));
81756Speter /*
82756Speter * Get the label for the eventual target
83756Speter */
8414733Sthien p->value[1] = (int) getlab();
85756Speter p->chain = lp;
86756Speter p->nl_flags |= (NFORWD|NMOD);
87756Speter p->value[NL_GOLEV] = NOTYET;
887919Smckusick p->value[NL_ENTLOC] = l;
89756Speter lp = p;
90756Speter # ifdef OBJ
91756Speter /*
92756Speter * This operator is between
93756Speter * the bodies of two procedures
94756Speter * and provides a target for
95756Speter * gotos for this label via TRA.
96756Speter */
9714733Sthien (void) putlab((char *) l);
9814733Sthien (void) put(2, O_GOTO | cbn<<8, (long)p->value[1]);
99756Speter # endif OBJ
100756Speter # ifdef PC
101756Speter /*
102756Speter * labels have to be .globl otherwise /lib/c2 may
103756Speter * throw them away if they aren't used in the function
104756Speter * which defines them.
105756Speter */
1064880Speter extlabname( extname , p -> symbol , cbn );
10714733Sthien putprintf(" .globl %s", 0, (int) extname);
1083366Speter if ( cbn == 1 ) {
1093366Speter stabglabel( extname , line );
110756Speter }
111756Speter # endif PC
112756Speter }
113756Speter gotos[cbn] = lp;
114756Speter # ifdef PTREE
115756Speter {
116756Speter pPointer Labels = LabelDCopy( r );
117756Speter
118756Speter pDEF( PorFHeader[ nesting ] ).PorFLabels = Labels;
119756Speter }
120756Speter # endif PTREE
121756Speter #endif
122756Speter }
123756Speter
124756Speter #ifndef PI0
125756Speter /*
126756Speter * Gotoop is called when
127756Speter * we get a statement "goto label"
128756Speter * and generates the needed tra.
129756Speter */
gotoop(s)130756Speter gotoop(s)
131756Speter char *s;
132756Speter {
133756Speter register struct nl *p;
1343366Speter #ifdef PC
1353366Speter char extname[ BUFSIZ ];
1363366Speter #endif PC
137756Speter
138756Speter gocnt++;
139756Speter p = lookup(s);
140756Speter if (p == NIL)
14114733Sthien return;
142756Speter # ifdef OBJ
14314733Sthien (void) put(2, O_TRA4, (long)p->value[NL_ENTLOC]);
144756Speter # endif OBJ
145756Speter # ifdef PC
1469127Smckusick if ( cbn == bn ) {
147756Speter /*
1489127Smckusick * local goto.
1499127Smckusick */
1509127Smckusick extlabname( extname , p -> symbol , bn );
1519137Smckusick /*
15210655Speter * this is a funny jump because it's to a label that
15310655Speter * has been declared global.
15410655Speter * Although this branch is within this module
15510655Speter * the assembler will complain that the destination
15610655Speter * is a global symbol.
15710655Speter * The complaint arises because the assembler
15810655Speter * doesn't change relative jumps into absolute jumps.
15910655Speter * and this may cause a branch displacement overflow
16010655Speter * when the module is subsequently linked with
16110655Speter * the rest of the program.
1629137Smckusick */
16330031Smckusick # if defined(vax) || defined(tahoe)
16414733Sthien putprintf(" jmp %s", 0, (int) extname);
16530031Smckusick # endif vax || tahoe
16610655Speter # ifdef mc68000
16714733Sthien putprintf(" jra %s", 0, (int) extname);
16810655Speter # endif mc68000
1699127Smckusick } else {
1709127Smckusick /*
1719127Smckusick * Non-local goto.
1729127Smckusick *
1739120Smckusick * Close all active files between top of stack and
1749120Smckusick * frame at the destination level. Then call longjmp
1759120Smckusick * to unwind the stack to the destination level.
1769127Smckusick *
17710655Speter * For nested routines the end of the frame
17810655Speter * is calculated as:
17910655Speter * __disply[bn].fp + sizeof(local frame)
18010655Speter * (adjusted by (sizeof int) to get just past the end).
1819127Smckusick * The size of the local frame is dumped out by
1829127Smckusick * the second pass as an assembler constant.
1839127Smckusick * The main routine may not be compiled in this
1849127Smckusick * module, so its size may not be available.
1859127Smckusick * However all of its variables will be globally
1869127Smckusick * declared, so only the known runtime temporaries
1879127Smckusick * will be in its stack frame.
188756Speter */
1899127Smckusick parts[ bn ] |= NONLOCALGOTO;
19018460Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
1919120Smckusick , "_PCLOSE" );
1929120Smckusick if ( bn > 1 ) {
1939120Smckusick p = lookup( enclosing[ bn - 1 ] );
19410655Speter sprintf( extname, "%s%d+%d",
19510655Speter FRAME_SIZE_LABEL, p -> value[NL_ENTLOC], sizeof(int));
1969120Smckusick p = lookup(s);
19718460Sralph putLV( extname , bn , 0 , NNLOCAL , PCCTM_PTR | PCCT_CHAR );
1989120Smckusick } else {
19914733Sthien putLV((char *) 0 , bn , -( DPOFF1 + sizeof( int ) ) , LOCALVAR ,
20018460Sralph PCCTM_PTR | PCCT_CHAR );
2019120Smckusick }
20218460Sralph putop( PCC_CALL , PCCT_INT );
203756Speter putdot( filename , line );
20418460Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
2059120Smckusick , "_longjmp" );
20618460Sralph putLV((char *) 0 , bn , GOTOENVOFFSET , NLOCAL , PCCTM_PTR|PCCT_STRTY );
2079120Smckusick extlabname( extname , p -> symbol , bn );
20818460Sralph putLV( extname , 0 , 0 , NGLOBAL , PCCTM_PTR|PCCT_STRTY );
20918460Sralph putop( PCC_CM , PCCT_INT );
21018460Sralph putop( PCC_CALL , PCCT_INT );
2119120Smckusick putdot( filename , line );
212756Speter }
213756Speter # endif PC
214756Speter if (bn == cbn)
215756Speter if (p->nl_flags & NFORWD) {
216756Speter if (p->value[NL_GOLEV] == NOTYET) {
217756Speter p->value[NL_GOLEV] = level;
218756Speter p->value[NL_GOLINE] = line;
219756Speter }
220756Speter } else
221756Speter if (p->value[NL_GOLEV] == DEAD) {
222756Speter recovered();
223756Speter error("Goto %s is into a structured statement", p->symbol);
224756Speter }
225756Speter }
226756Speter
227756Speter /*
228756Speter * Labeled is called when a label
229756Speter * definition is encountered, and
230756Speter * marks that it has been found and
231756Speter * patches the associated GOTO generated
232756Speter * by gotoop.
233756Speter */
labeled(s)234756Speter labeled(s)
235756Speter char *s;
236756Speter {
237756Speter register struct nl *p;
2383366Speter #ifdef PC
2393366Speter char extname[ BUFSIZ ];
2403366Speter #endif PC
241756Speter
242756Speter p = lookup(s);
243756Speter if (p == NIL)
24414733Sthien return;
245756Speter if (bn != cbn) {
246756Speter error("Label %s not defined in correct block", s);
247756Speter return;
248756Speter }
249756Speter if ((p->nl_flags & NFORWD) == 0) {
250756Speter error("Label %s redefined", s);
251756Speter return;
252756Speter }
253756Speter p->nl_flags &= ~NFORWD;
254756Speter # ifdef OBJ
25514733Sthien patch4((PTR_DCL) p->value[NL_ENTLOC]);
256756Speter # endif OBJ
257756Speter # ifdef PC
2584880Speter extlabname( extname , p -> symbol , bn );
25914733Sthien putprintf( "%s:" , 0 , (int) extname );
260756Speter # endif PC
261756Speter if (p->value[NL_GOLEV] != NOTYET)
262756Speter if (p->value[NL_GOLEV] < level) {
263756Speter recovered();
26414733Sthien error("Goto %s from line %d is into a structured statement", s, (char *) p->value[NL_GOLINE]);
265756Speter }
266756Speter p->value[NL_GOLEV] = level;
267756Speter }
268756Speter #endif
2694880Speter
2704880Speter #ifdef PC
2714880Speter /*
2724880Speter * construct the long name of a label based on it's static nesting.
2734880Speter * into a caller-supplied buffer (that should be about BUFSIZ big).
2744880Speter */
extlabname(buffer,name,level)2754880Speter extlabname( buffer , name , level )
2764880Speter char buffer[];
2774880Speter char *name;
2784880Speter int level;
2794880Speter {
2804880Speter char *starthere;
2814880Speter int i;
2824880Speter
2834880Speter starthere = &buffer[0];
2844880Speter for ( i = 1 ; i < level ; i++ ) {
2854880Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] );
2864880Speter starthere += strlen( enclosing[ i ] ) + 1;
2874880Speter }
2884880Speter sprintf( starthere , EXTFORMAT , "" );
2894880Speter starthere += 1;
2904880Speter sprintf( starthere , LABELFORMAT , name );
2914880Speter starthere += strlen( name ) + 1;
2924880Speter if ( starthere >= &buffer[ BUFSIZ ] ) {
2934880Speter panic( "extlabname" );
2944880Speter }
2954880Speter }
2964880Speter #endif PC
297