1 /*
2 * Copyright (c) 2015-2018, NVIDIA CORPORATION. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18 /**
19 \file
20 \brief Functions for dealing with lexical scopes and the lifetimes
21 of scoped variables.
22
23
24 A lexical scope is represented by an ST_BLOCK symbol table entry. The
25 scope's ENCLFUNC field points to either the enclosing scope or the
26 containing function. Scopes have two pairs of start/end labels:
27
28 STARTLAB / ENDLAB: These labels are only inserted when generating debug
29 info. The are tagged as volatile so they won't be removed, and they can be
30 used to generate complete DWARF lexical scope information.
31
32 BEGINSCOPELAB / ENDSCOPELAB: These labels are inserted in-stream as ilts
33 with an IL_LABEL instruction. The corresponding ST_LABEL symbol table
34 entries are tagged with the corresponding BEGINSCOPE / ENDSCOPE flags, and
35 the ENCLFUNC field points back to the ST_BLOCK entry.
36
37 Every local variable has a scope indicated by its ENCLFUNC field. Variables
38 with function scope point to the function's symbol table entry instead of an
39 ST_BLOCK entry.
40 */
41
42 #include "scope.h"
43 #include "error.h"
44 #include "global.h"
45 #include "ilm.h"
46 #include "ilmtp.h"
47 #include "ili.h"
48 #include "go.h"
49 #include "scope.h"
50 #include "flang/ADT/hash.h"
51 #include "symfun.h"
52
53 /* For addlabel(). */
54 #include "semant.h"
55
56 #define VALIDSYM(sptr) ((sptr) > NOSYM && (sptr) < stb.stg_avail)
57
58 /**
59 \brief Is sptr a symbol table entry that can be the root of a scope
60 tree? For C, this is functions. For Fortran, this includes entries
61 and procedures.
62 */
63 static bool
is_scope_root(SPTR sptr)64 is_scope_root(SPTR sptr)
65 {
66 switch (STYPEG(sptr)) {
67 case ST_PROC:
68 case ST_ENTRY:
69 return true;
70 default:
71 return false;
72 }
73 }
74
75 /**
76 \brief Return true if the scope 'outer' contains the scope 'inner'.
77
78 Both outer and inner must be valid ST_BLOCK or ST_FUNC symbol table
79 entries.
80 */
81 bool
scope_contains(SPTR outer,SPTR inner)82 scope_contains(SPTR outer, SPTR inner)
83 {
84 ICHECK(VALIDSYM(outer) &&
85 (is_scope_root(outer) || STYPEG(outer) == ST_BLOCK));
86 ICHECK(VALIDSYM(inner) &&
87 (is_scope_root(inner) || STYPEG(inner) == ST_BLOCK));
88
89 while (STYPEG(inner) == ST_BLOCK) {
90 if (inner == outer)
91 return true;
92 inner = ENCLFUNCG(inner);
93 }
94
95 return inner == outer;
96 }
97
98 /**
99 \brief Return true if label_sptr is a scope label.
100 */
101 bool
is_scope_label(int label_sptr)102 is_scope_label(int label_sptr)
103 {
104 if (!VALIDSYM(label_sptr) || STYPEG(label_sptr) != ST_LABEL)
105 return false;
106
107 return BEGINSCOPEG(label_sptr) || ENDSCOPEG(label_sptr);
108 }
109
110 /**
111 \brief Check if ilix is an IL_LABEL instruction referring to a
112 scope label.
113 */
114 bool
is_scope_label_ili(int ilix)115 is_scope_label_ili(int ilix)
116 {
117 return ILI_OPC(ilix) == IL_LABEL && is_scope_label(ILI_OPND(ilix, 1));
118 }
119
120 /**
121 \brief Check if the bihx basic block contains nothing but scope
122 labels (or is empty).
123 */
124 bool
is_scope_labels_only_bih(int bihx)125 is_scope_labels_only_bih(int bihx)
126 {
127 int iltx;
128
129 for (iltx = BIH_ILTFIRST(bihx); iltx; iltx = ILT_NEXT(iltx)) {
130 if (!is_scope_label_ili(ILT_ILIP(iltx)))
131 return false;
132 }
133 return true;
134 }
135
136 /**
137 \brief Verify the integrity of an ST_BLOCK symbol table entry and
138 its associated labels.
139 */
140 static void
verify_block(int block_sptr)141 verify_block(int block_sptr)
142 {
143 int lab;
144
145 ICHECK(VALIDSYM(block_sptr));
146 ICHECK(STYPEG(block_sptr) == ST_BLOCK);
147
148 /* STARTLAB and ENDLAB are not required to be present. */
149 if (STARTLABG(block_sptr)) {
150 lab = STARTLABG(block_sptr);
151 ICHECK(VALIDSYM(lab));
152 ICHECK(STYPEG(lab) == ST_LABEL);
153 ICHECK(ENCLFUNCG(lab) == block_sptr);
154
155 /* These flags should go on the BEGINSCOPELAB / ENDSCOPELAB
156 labels, not here. */
157 ICHECK(!BEGINSCOPEG(lab));
158 ICHECK(!ENDSCOPEG(lab));
159 /* FIXME: Check ILIBLK. */
160 }
161
162 if (ENDLABG(block_sptr)) {
163 lab = ENDLABG(block_sptr);
164 ICHECK(VALIDSYM(lab));
165 ICHECK(STYPEG(lab) == ST_LABEL);
166 ICHECK(ENCLFUNCG(lab) == block_sptr);
167 ICHECK(!BEGINSCOPEG(lab));
168 ICHECK(!ENDSCOPEG(lab));
169 /* FIXME: Check ILIBLK. */
170 }
171
172 /* All blocks should have delineating labels. */
173 lab = BEGINSCOPELABG(block_sptr);
174 ICHECK(VALIDSYM(lab));
175 ICHECK(STYPEG(lab) == ST_LABEL);
176 ICHECK(ENCLFUNCG(lab) == block_sptr);
177 ICHECK(BEGINSCOPEG(lab));
178 ICHECK(!ENDSCOPEG(lab));
179 /* FIXME: Check ILIBLK. */
180
181 lab = ENDSCOPELABG(block_sptr);
182 ICHECK(VALIDSYM(lab));
183 ICHECK(STYPEG(lab) == ST_LABEL);
184 ICHECK(ENCLFUNCG(lab) == block_sptr);
185 ICHECK(!BEGINSCOPEG(lab));
186 ICHECK(ENDSCOPEG(lab));
187 /* FIXME: Check ILIBLK. */
188 }
189
190 static bool
is_local_variable(int sptr)191 is_local_variable(int sptr)
192 {
193 switch (STYPEG(sptr)) {
194 case ST_PLIST:
195 case ST_VAR:
196 case ST_ARRAY:
197 case ST_STRUCT:
198 case ST_UNION:
199 switch (SCG(sptr)) {
200 case SC_LOCAL:
201 /* Somebody who understands Fortran should probably revisit this
202 and check DINITG, SAVEG etc. */
203 return true;
204 /* Ignore SC_DUMMY. It's going to have function scope anyway. */
205 default:
206 return false;
207 }
208 default:
209 return false;
210 }
211 }
212
213 /**
214 \brief Collect the set of locals referenced by the ILI tree starting at ilix.
215
216 Loads and stores to local variables are always going to use an ACON
217 to compute the address, so just find all the symbols referenced by
218 ACONs.
219 */
220 static void
collect_referenced_locals(hashset_t symbs,int ilix)221 collect_referenced_locals(hashset_t symbs, int ilix)
222 {
223 ILI_OP opc = ILI_OPC(ilix);
224
225 if (opc == IL_ACON) {
226 /* ACON opnd 1 is an ST_CONST sptr with DT_CPTR type. */
227 int sptr = CONVAL1G(ILI_OPND(ilix, 1));
228 if (sptr && is_local_variable(sptr))
229 hashset_replace(symbs, INT2HKEY(sptr));
230 } else {
231 int i;
232 for (i = IL_OPRS(opc); i > 0; i--)
233 if (IL_ISLINK(opc, i))
234 collect_referenced_locals(symbs, ILI_OPND(ilix, i));
235 }
236 }
237
238 /* Info about a single open scope. */
239 struct scope_info {
240 /* ST_BLOCK for scope, or ST_FUNC/ST_PROC/ST_ENTRY for the function-level
241 scope. */
242 SPTR block;
243 /* The IL_LABEL ilt that closes this scope. */
244 int closing_ilt;
245 };
246
247 /* A stack of open scopes. */
248 struct scope_stack {
249 /* scope[0..curr] are in use. */
250 int curr;
251 /* scope[0..outer] are perfectly nested. */
252 int outer;
253 /* Allocated entries in scope. */
254 int allocated;
255 struct scope_info *scope;
256 /* scope[outer].block from before closed scopes were popped. */
257 SPTR prev_top;
258 };
259
260 /**
261 \brief Initialize a scope stack with func as the outermost scope.
262 */
263 static void
init_scope_stack(struct scope_stack * ss,SPTR func)264 init_scope_stack(struct scope_stack *ss, SPTR func)
265 {
266 ss->curr = ss->outer = 0;
267 ss->allocated = 100;
268 NEW(ss->scope, struct scope_info, ss->allocated);
269 memset(&ss->scope[0], 0, sizeof(ss->scope[0]));
270 ss->scope[0].block = func;
271 ss->prev_top = SPTR_NULL;
272 }
273
274 static void
push_block(struct scope_stack * ss,SPTR block)275 push_block(struct scope_stack *ss, SPTR block)
276 {
277 ++ss->curr;
278 NEED(ss->curr + 1, ss->scope, struct scope_info, ss->allocated,
279 ss->allocated + 100);
280 memset(&ss->scope[ss->curr], 0, sizeof(ss->scope[0]));
281 ss->scope[ss->curr].block = block;
282 dbgprintf(" Pushing scope %d (%s) at level %d: enclfunc=%d (%s)\n", block,
283 SYMNAME(block), ss->curr, ENCLFUNCG(block),
284 SYMNAME(ENCLFUNCG(block)));
285 }
286
287 static void
pop_block(struct scope_stack * ss)288 pop_block(struct scope_stack *ss)
289 {
290 dbgprintf(" Popping scope %d (%s) at level %d\n", ss->scope[ss->curr].block,
291 SYMNAME(ss->scope[ss->curr].block), ss->curr);
292 ICHECK(ss->curr > 0);
293 if (--ss->curr < ss->outer)
294 ss->outer = ss->curr;
295 }
296
297 /**
298 \brief Check labels opening scopes in bih, and collect all symbols
299 referenced in this block.
300
301 Add opened scopes to ss.
302 */
303 static void
verify_beginscopes(int bih,hashset_t locals,struct scope_stack * ss)304 verify_beginscopes(int bih, hashset_t locals, struct scope_stack *ss)
305 {
306 int ilt;
307
308 /* All of the scopes pushed in this block must be sub-scopes of the
309 current top. */
310 SPTR outer_scope = ss->scope[ss->curr].block;
311
312 for (ilt = BIH_ILTFIRST(bih); ilt; ilt = ILT_NEXT(ilt)) {
313 int ilix = ILT_ILIP(ilt);
314 SPTR lab, blk;
315
316 if (ILI_OPC(ilix) != IL_LABEL) {
317 collect_referenced_locals(locals, ilix);
318 continue;
319 }
320
321 /* This is an IL_LABEL ilt. */
322 lab = ILI_SymOPND(ilix, 1);
323 ICHECK(VALIDSYM(lab) && STYPEG(lab) == ST_LABEL);
324 if (!BEGINSCOPEG(lab))
325 continue;
326
327 /* This is a scope-opening label. */
328 blk = ENCLFUNCG(lab);
329 verify_block(blk);
330 ICHECK(BEGINSCOPELABG(blk) == lab);
331
332 /* If multiple scopes are pushed in the same BIH, we'll allow any
333 order. They all have to be proper sub-scopes of outer_scope,
334 though. */
335 push_block(ss, blk);
336 ICHECK((blk != outer_scope) && "Can't open the same scope twice");
337 ICHECK(scope_contains(outer_scope, blk) &&
338 "New scope is not properly nested");
339 }
340 }
341
342 /**
343 \brief Verify a local that was referenced in the current function.
344
345 This function conforms to the prototype expected by hashset_iterate.
346 */
347 static void
verify_local(hash_key_t key,void * context)348 verify_local(hash_key_t key, void *context)
349 {
350 int sptr = HKEY2INT(key);
351 struct scope_stack *ss = (struct scope_stack *)context;
352 SPTR encl = ENCLFUNCG(sptr);
353 int i;
354
355 /* The Fortran frontend doesn't bother setting ENCLFUNC on local
356 variables. Fortran doesn't have scopes anyway, except through
357 inlining. */
358 if (!encl)
359 return;
360
361 /* Compiler-created scalar temporaries don't always have associated
362 scopes. They will be treated as function-scope. */
363 if (!encl && CCSYMG(sptr)) {
364 dbgprintf(" Referenced local compiler-created temporary with no "
365 "scope: %d (%s)\n",
366 sptr, SYMNAME(sptr));
367 return;
368 }
369
370 dbgprintf(" Referenced local %d (%s) from scope %d. At block %d level "
371 "%d-%d, prev %d.\n",
372 sptr, SYMNAME(sptr), encl, ss->scope[ss->curr].block, ss->outer,
373 ss->curr, ss->prev_top);
374 ICHECK(VALIDSYM(encl) && "Local variable does not have a valid scope");
375
376 /* Now verify that the 'encl' scope is accessible in one of the
377 active scopes in the current block.
378
379 It is possible that multiple non-overlapping scopes were pushed
380 and popped in the current basic block. When that happens, these
381 scopes will appear on the scope stack from ss->outer to
382 ss->curr. These scopes are pushed even though they are not
383 nested. They will be popped again by verify_endscopes().
384
385 We are satisfied if encl contains any scope from this set. */
386 for (i = ss->outer; i <= ss->curr; i++) {
387 if (scope_contains(encl, ss->scope[i].block))
388 return;
389 }
390
391 /* Finally, it is also possible that encl overlaps one of the scopes
392 that ended in the current block. ss->prev_top records the
393 innermost active scope on entry to the block. The assertion here
394 covers the above scope containment checks too. */
395 ICHECK(scope_contains(encl, ss->prev_top) &&
396 "Local variable referenced by code outside its scope");
397 }
398
399 /**
400 \brief Process all the scope closing labels in bih.
401
402 Pop the closed scopes off the stack.
403 */
404 static void
verify_endscopes(int bih,struct scope_stack * ss)405 verify_endscopes(int bih, struct scope_stack *ss)
406 {
407 int ilt, i;
408 int ilix;
409 int lab, blk;
410 bool closed_last_opened;
411
412 for (ilt = BIH_ILTFIRST(bih); ilt; ilt = ILT_NEXT(ilt)) {
413 ilix = ILT_ILIP(ilt);
414 if (ILI_OPC(ilix) != IL_LABEL)
415 continue;
416 lab = ILI_OPND(ilix, 1);
417 if (!ENDSCOPEG(lab))
418 continue;
419
420 /* This is a scope-closing label. */
421 blk = ENCLFUNCG(lab);
422 verify_block(blk);
423 ICHECK(ENDSCOPELABG(blk) == lab);
424
425 /* Find the scope that is being closed. It doesn't have to be the
426 topmost one. */
427 for (i = ss->curr; i > 0; i--) {
428 if (ss->scope[i].block == blk) {
429 /* We can't have duplicate labels closing the same scope. */
430 ICHECK(ss->scope[i].closing_ilt == 0);
431 ss->scope[i].closing_ilt = ilt;
432 break;
433 }
434 }
435 }
436
437 /* Pop all the closed scopes. */
438 while (ss->scope[ss->curr].closing_ilt != 0)
439 pop_block(ss);
440 }
441
442 /**
443 \brief Verify all of the locals referenced in the current function
444 and check the scope labels.
445 */
446 static void
verify_all_blocks(void)447 verify_all_blocks(void)
448 {
449 hashset_t locals = hashset_alloc(hash_functions_direct);
450 struct scope_stack ss = {-1, 0, 0, 0};
451 int bih;
452
453 dbgprintf("\nVerifying scopes\n");
454 init_scope_stack(&ss, GBL_CURRFUNC);
455
456 /* Visit basic blocks in program order. */
457 for (bih = gbl.entbih; bih; bih = BIH_NEXT(bih)) {
458 int i, j;
459
460 ss.prev_top = ss.scope[ss.curr].block;
461 dbgprintf("block:%d in scope %d (%s)\n", bih, ss.prev_top,
462 SYMNAME(ss.prev_top));
463
464 /* First get rid of any open scopes that are closed in this block. */
465 verify_endscopes(bih, &ss);
466
467 /* Check labels opening scopes, collect all symbols referenced. */
468 hashset_clear(locals);
469 verify_beginscopes(bih, locals, &ss);
470
471 /* The scope stack is now as deep as it gets in bih. Check that
472 all referenced locals belong to a pushed scope block. */
473 hashset_iterate(locals, verify_local, &ss);
474
475 /* Check labels closing scopes again. This takes care of scopes
476 that were opened and closed in the same block. */
477 verify_endscopes(bih, &ss);
478
479 /* Check that new open scope are perfectly nested with respect to
480 other open scopes. */
481 for (i = ss.curr; i > ss.outer; i--) {
482 if (ss.scope[i].closing_ilt == 0) {
483 for (j = i - 1; j > ss.outer; j--)
484 if (ss.scope[j].closing_ilt == 0)
485 break;
486 ICHECK(ENCLFUNCG(ss.scope[i].block) == ss.scope[j].block);
487 }
488 }
489 ss.outer = ss.curr;
490 }
491
492 FREE(ss.scope);
493 hashset_free(locals);
494 }
495
496 /**
497 \brief Verify the integrity of data structures relating to variable
498 scopes in the current function. Terminate compilation with a fatal
499 error if anything is inconsistent.
500 */
501 void
scope_verify(void)502 scope_verify(void)
503 {
504 #if DEBUG
505 if (XBIT_USE_SCOPE_LABELS) {
506 verify_all_blocks();
507 }
508 #endif
509 }
510
511 /**
512 \brief Insert a begin-scope label ILM for the scope blksym which
513 much be an ST_BLOCK symbol table entry.
514
515 \return the new ST_LABEL symbol table entry.
516 */
517 int
insert_begin_scope_label(int block_sptr)518 insert_begin_scope_label(int block_sptr)
519 {
520 int lab;
521
522 ICHECK(VALIDSYM(block_sptr) && STYPEG(block_sptr) == ST_BLOCK);
523 ICHECK(BEGINSCOPELABG(block_sptr) == 0 && "Scope already has a begin label.");
524
525 if (!XBIT_USE_SCOPE_LABELS)
526 return 0;
527
528 lab = getlab();
529 BEGINSCOPEP(lab, 1);
530 ENCLFUNCP(lab, block_sptr);
531 BEGINSCOPELABP(block_sptr, lab);
532 addlabel(lab);
533
534 return lab;
535 }
536
537 /**
538 \brief Insert an end-scope label ILM for the scope blksym which
539 much be an ST_BLOCK symbol table entry.
540
541 \return the new ST_LABEL symbol table entry.
542 */
543 int
insert_end_scope_label(int block_sptr)544 insert_end_scope_label(int block_sptr)
545 {
546 int lab;
547
548 ICHECK(VALIDSYM(block_sptr) && STYPEG(block_sptr) == ST_BLOCK);
549 ICHECK(ENDSCOPELABG(block_sptr) == 0 && "Scope already has an end label.");
550
551 if (!XBIT_USE_SCOPE_LABELS)
552 return 0;
553
554 lab = getlab();
555 ENDSCOPEP(lab, 1);
556 ENCLFUNCP(lab, block_sptr);
557 ENDSCOPELABP(block_sptr, lab);
558 addlabel(lab);
559
560 return lab;
561 }
562
563 /*
564 * Scope tracking.
565 *
566 * During inlining, as we're scanning the current function ILMs top to bottom,
567 * call track_scope_label(label_sptr) whenever an IM_LABEL is seen in order to
568 * keep track of the current scope.
569 *
570 * The global variable current_scope points to the currently open scope.
571 */
572 int current_scope = 0;
573
574 /**
575 \brief Reset scope tracking, start from the outer function scope.
576 */
577 void
track_scope_reset()578 track_scope_reset()
579 {
580 current_scope = GBL_CURRFUNC;
581 dbgprintf("Scope: Reset to current function %d:%s\n", current_scope,
582 SYMNAME(current_scope));
583 }
584
585 /**
586 \brief Update curent_scope after scanning over an IM_LABEL ilmx.
587 The label sptr is the first and only ILM operand on IM_LABEL.
588 */
589 void
track_scope_label(int label)590 track_scope_label(int label)
591 {
592 assert(STYPEG(label) == ST_LABEL, "track_scope_label: Bogus label", label,
593 ERR_Severe);
594
595 /* If scope labels are not being inserted, it is impossible to keep
596 track of the current scope. */
597 if (!XBIT_USE_SCOPE_LABELS)
598 return;
599
600 /* Non-scope labels are simply ignored. */
601 if (!BEGINSCOPEG(label) && !ENDSCOPEG(label))
602 return;
603
604 /* Labels left over after cancel_lexical_block() are also ignored. */
605 if (!ENCLFUNCG(label))
606 return;
607
608 if (BEGINSCOPEG(label)) {
609 dbgprintf("Scope: Enter scope %d:%s from %d:%s. Parent %d:%s.\n",
610 ENCLFUNCG(label), SYMNAME(ENCLFUNCG(label)), current_scope,
611 SYMNAME(current_scope), ENCLFUNCG(ENCLFUNCG(label)),
612 SYMNAME(ENCLFUNCG(ENCLFUNCG(label))));
613 current_scope = ENCLFUNCG(label);
614 /* A label can't refer to a function scope. */
615 assert(STYPEG(current_scope) == ST_BLOCK,
616 "track_scope_label: Scope label does not refer to an ST_BLOCK",
617 label, ERR_Severe);
618 }
619
620 if (ENDSCOPEG(label)) {
621 dbgprintf("Scope: Leave scope %d:%s from %d:%s. Parent %d:%s.\n",
622 ENCLFUNCG(label), SYMNAME(ENCLFUNCG(label)), current_scope,
623 SYMNAME(current_scope), ENCLFUNCG(ENCLFUNCG(label)),
624 SYMNAME(ENCLFUNCG(ENCLFUNCG(label))));
625 /* This is the scope that's ending: */
626 current_scope = ENCLFUNCG(label);
627 assert(STYPEG(current_scope) == ST_BLOCK,
628 "track_scope_label: Scope label does not refer to an ST_BLOCK",
629 label, ERR_Severe);
630 /* This is the active scope after leaving the current scope: */
631 current_scope = ENCLFUNCG(current_scope);
632 }
633
634 if (!flg.inliner || XBIT(117, 0x10000)) {
635 assert(current_scope == GBL_CURRFUNC || STYPEG(current_scope) == ST_BLOCK,
636 "track_scope_label: Invalid scope label", label, ERR_Severe);
637 }
638 }
639
640 /**
641 \brief Find all the scope labels in the current ILM block and pass
642 them to track_scope_label. This is used for blocks that don't
643 contain any calls.
644
645 This function is looking at numilms ILMs in the ilmb.ilm_base
646 array. We don't have any ILM_* macros defined to access that area.
647
648 Compare find_bpar() in inliner.c
649 */
650 void
find_scope_labels(int numilms)651 find_scope_labels(int numilms)
652 {
653 int ilmx, len;
654
655 if (!XBIT_USE_SCOPE_LABELS)
656 return;
657
658 for (ilmx = BOS_SIZE; ilmx < numilms; ilmx += len) {
659 int opc = ilmb.ilm_base[ilmx];
660 if (opc == IM_LABEL) {
661 int label = ilmb.ilm_base[ilmx + 1];
662 track_scope_label(label);
663 }
664
665 len = ilms[opc].oprs + 1; /* length for opcode and fixed operands */
666 if (IM_VAR(opc))
667 len += ilmb.ilm_base[ilmx + 1]; /* include the variable opnds */
668 }
669 }
670
671 /*
672 * Inliner support.
673 *
674 * The functions and global variables below are used by the C and Fortran
675 * inliners.
676 */
677
678 int new_callee_scope = 0;
679
680 /* Stack of simultaneously open callee scopes.
681 *
682 * This stack contains scopes whose begin label has been inserted, and whose
683 * end label has yet to be inserted.
684 *
685 * The stack top is equal to new_callee_scope only after calling
686 * begin_inlined_scope().
687 */
688 static int *open_callee_scope = NULL;
689 static int open_callee_scope_count = 0;
690 static int open_callee_scope_capacity = 0;
691
692 /* Check if new_callee_scope is at the top of the open_callee_scope stack.
693 *
694 * This is false when new_callee_scope is 0 or when it hasn't been pushed yet
695 * by begin_inlined_scope().
696 */
697 #define NEW_CALLEE_SCOPE_IS_STACK_TOP \
698 (open_callee_scope_count > 0 && \
699 new_callee_scope == open_callee_scope[open_callee_scope_count - 1])
700
701 /**
702 \brief The original function scope of the callee being inlined is
703 represented as a new ST_BLOCK scope, stored in new_callee_scope.
704
705 Call create_inlined_scope() to create new_callee_scope as a subscope of the
706 currently tracked scope. Then call begin_inlined_scope() and
707 end_inlined_scope() to insert the begin/end labels.
708 */
709 void
create_inlined_scope(int callee_sptr)710 create_inlined_scope(int callee_sptr)
711 {
712 if (!XBIT_USE_SCOPE_LABELS) {
713 /* Without scope labels, we don't know the scope containing the
714 call site. Conservatively map scope to the entire function
715 scope. */
716 new_callee_scope = GBL_CURRFUNC;
717 return;
718 }
719
720 if (!flg.inliner || XBIT(117, 0x10000)) {
721 assert(current_scope, "create_inlined_scope: No current scope?", 0,
722 ERR_Severe);
723 }
724
725 /* An existing callee scope should have been saved or cancelled. */
726 if (new_callee_scope) {
727 assert(NEW_CALLEE_SCOPE_IS_STACK_TOP,
728 "create_inlined_scope: Previous callee scope wasn't saved",
729 new_callee_scope, ERR_Fatal);
730 }
731
732 NEWSYM(new_callee_scope);
733 STYPEP(new_callee_scope, ST_BLOCK);
734 NMPTRP(new_callee_scope, NMPTRG(callee_sptr));
735 SCOPEP(new_callee_scope, 1);
736 ENCLFUNCP(new_callee_scope, current_scope);
737
738 dbgprintf("Scope: Create %d:%s for inlining %d:%s.\n", new_callee_scope,
739 SYMNAME(new_callee_scope), callee_sptr, SYMNAME(callee_sptr));
740 }
741
742 /**
743 \brief Immediately before inlining a function, create a new
744 ST_BLOCK to represent the callee's function scope in the current
745 function.
746
747 Insert an IM_LABEL ILM to open the new scope, update the
748 new_callee_scope and current_scope variables to refer to the newly
749 created scope.
750 */
751 void
begin_inlined_scope(int func_sptr)752 begin_inlined_scope(int func_sptr)
753 {
754 int label;
755
756 if (!XBIT_USE_SCOPE_LABELS)
757 return;
758
759 /* Make a new scope unless create_inlined_scope() has already been called.
760 * Don't attempt to reuse an open scope that has already been pushed. */
761 if (!new_callee_scope || NEW_CALLEE_SCOPE_IS_STACK_TOP)
762 create_inlined_scope(func_sptr);
763
764 assert(new_callee_scope && STYPEG(new_callee_scope) == ST_BLOCK,
765 "begin_inlined_scope: No inlined scope was created", new_callee_scope,
766 ERR_Severe);
767
768 /* Push scope onto the stack of open callee scopes. */
769 NEED(open_callee_scope_count + 1, open_callee_scope, int,
770 open_callee_scope_capacity, open_callee_scope_capacity + 16);
771 open_callee_scope[open_callee_scope_count++] = new_callee_scope;
772
773 /* Create begin label here, end label in end_inlined_scope(). */
774 label = insert_begin_scope_label(new_callee_scope);
775 dbgprintf("Scope: Label %d:%s created, nest=%d.\n", label, SYMNAME(label),
776 open_callee_scope_count);
777
778 track_scope_label(label);
779 }
780
781 /**
782 \brief After inlining a function, emit a scope-ending label.
783 */
784 void
end_inlined_scope(void)785 end_inlined_scope(void)
786 {
787 int label;
788
789 if (!XBIT_USE_SCOPE_LABELS)
790 return;
791
792 assert(new_callee_scope && STYPEG(new_callee_scope) == ST_BLOCK,
793 "end_inlined_scope: Not currently in an inlined scope",
794 new_callee_scope, ERR_Severe);
795
796 label = insert_end_scope_label(new_callee_scope);
797 dbgprintf("Scope: Label %d:%s created, next=%d.\n", label, SYMNAME(label),
798 open_callee_scope_count);
799
800 /* Pop this scope off the stack. Make new_callee_scope refer to the
801 * previous open callee scope. */
802 assert(NEW_CALLEE_SCOPE_IS_STACK_TOP,
803 "end_inlined_scope: Scope stack corrupted", new_callee_scope,
804 ERR_Fatal);
805 if (--open_callee_scope_count)
806 new_callee_scope = open_callee_scope[open_callee_scope_count - 1];
807 else
808 new_callee_scope = 0;
809
810 track_scope_label(label);
811 }
812
813 /**
814 \brief End currently open callee scopes until
815 open_callee_scope_count is new_open_count.
816 */
817 void
end_inlined_scopes(int new_open_count)818 end_inlined_scopes(int new_open_count)
819 {
820 while (open_callee_scope_count > new_open_count) {
821 new_callee_scope = open_callee_scope[open_callee_scope_count - 1];
822 end_inlined_scope();
823 }
824 }
825
826 /**
827 \brief If create_inlined_scope() was called, but the inlining was
828 abandoned before any labels were inserted, call
829 cancel_inlined_scope() to clean up.
830 */
831 void
cancel_inlined_scope(void)832 cancel_inlined_scope(void)
833 {
834 if (!XBIT_USE_SCOPE_LABELS)
835 return;
836
837 if (!new_callee_scope)
838 return;
839
840 /* If the begin label was already inserted, this scope can't be cancelled. */
841 if (NEW_CALLEE_SCOPE_IS_STACK_TOP)
842 return;
843
844 /* Go back to the scope we came from before calling
845 * begin_inlined_scope(). */
846 current_scope = ENCLFUNCG(new_callee_scope);
847 dbgprintf("Scope: Reverted to %d:%s scope.\n", current_scope,
848 SYMNAME(current_scope));
849
850 /* Restore the old stack top into new_callee_scope. */
851 if (open_callee_scope_count)
852 new_callee_scope = open_callee_scope[open_callee_scope_count - 1];
853 else
854 new_callee_scope = 0;
855 }
856
857 void
reset_new_callee_scope()858 reset_new_callee_scope()
859 {
860 new_callee_scope = 0;
861 }
862
863 /**
864 \brief Remove any scope labels from all blocks. This is done as a
865 workaround until all the phases of the compiler accept (or ignore)
866 scope labels.
867 */
868 void
remove_scope_labels(void)869 remove_scope_labels(void)
870 {
871 int bihx, iltx, nextiltx;
872 for (bihx = gbl.entbih; 1; bihx = BIH_NEXT(bihx)) {
873 rdilts(bihx);
874 for (iltx = BIH_ILTFIRST(bihx); iltx; iltx = nextiltx) {
875 nextiltx = ILT_NEXT(iltx);
876 if (is_scope_label_ili(ILT_ILIP(iltx)))
877 delilt(iltx);
878 }
879 wrilts(bihx);
880 if (BIH_LAST(bihx))
881 break;
882 }
883 } /* remove_scope_labels */
884