1 /** 2 * Code generation 5 3 * 4 * Handles finding out which blocks need a function prolog / epilog attached 5 * 6 * Compiler implementation of the 7 * $(LINK2 https://www.dlang.org, D programming language). 8 * 9 * Copyright: Copyright (C) 1995-1998 by Symantec 10 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 11 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 12 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 13 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/cod5.d, backend/cod5.d) 14 */ 15 module dmd.backend.cod5; 16 17 import core.stdc.stdio; 18 import core.stdc.string; 19 import core.stdc.time; 20 import dmd.backend.cc; 21 import dmd.backend.el; 22 import dmd.backend.oper; 23 import dmd.backend.code; 24 import dmd.backend.global; 25 import dmd.backend.type; 26 27 import dmd.backend.cdef; 28 import dmd.backend.dlist; 29 import dmd.backend.ty; 30 31 nothrow: 32 @safe: 33 34 35 /******************************************************** 36 * Determine which blocks get the function prolog and epilog 37 * attached to them. 38 */ 39 40 @trusted 41 void cod5_prol_epi() 42 { 43 static if(1) 44 { 45 cod5_noprol(); 46 } 47 else 48 { 49 tym_t tym; 50 tym_t tyf; 51 block *b; 52 block *bp; 53 int nepis; 54 55 tyf = funcsym_p.ty(); 56 tym = tybasic(tyf); 57 58 if (!(config.flags4 & CFG4optimized) || 59 anyiasm || 60 Alloca.size || 61 usednteh || 62 calledFinally || 63 tyf & (mTYnaked | mTYloadds) || 64 tym == TYifunc || 65 tym == TYmfunc || // can't yet handle ECX passed as parameter 66 tym == TYjfunc || // can't yet handle EAX passed as parameter 67 config.flags & (CFGalwaysframe | CFGtrace) || 68 // config.fulltypes || 69 (config.wflags & WFwindows && tyfarfunc(tym)) || 70 need_prolog(startblock) 71 ) 72 { // First block gets the prolog, all return blocks 73 // get the epilog. 74 //printf("not even a candidate\n"); 75 cod5_noprol(); 76 return; 77 } 78 79 // Turn on BFLoutsideprolog for all blocks outside the ones needing the prolog. 80 81 for (b = startblock; b; b = b.Bnext) 82 b.Bflags &= ~BFLoutsideprolog; // start with them all off 83 84 pe_add(startblock); 85 86 // Look for only one block (bp) that will hold the prolog 87 bp = null; 88 nepis = 0; 89 for (b = startblock; b; b = b.Bnext) 90 { int mark; 91 92 if (b.Bflags & BFLoutsideprolog) 93 continue; 94 95 // If all predecessors are marked 96 mark = 0; 97 assert(b.Bpred); 98 foreach (bl; ListRange(b.Bpred)) 99 { 100 if (list_block(bl).Bflags & BFLoutsideprolog) 101 { 102 if (mark == 2) 103 goto L1; 104 mark = 1; 105 } 106 else 107 { 108 if (mark == 1) 109 goto L1; 110 mark = 2; 111 } 112 } 113 if (mark == 1) 114 { 115 if (bp) // if already have one 116 goto L1; 117 bp = b; 118 } 119 120 // See if b is an epilog 121 mark = 0; 122 foreach (bl; ListRange(b.Bsucc)) 123 { 124 if (list_block(bl).Bflags & BFLoutsideprolog) 125 { 126 if (mark == 2) 127 goto L1; 128 mark = 1; 129 } 130 else 131 { 132 if (mark == 1) 133 goto L1; 134 mark = 2; 135 } 136 } 137 if (mark == 1 || b.BC == BCret || b.BC == BCretexp) 138 { b.Bflags |= BFLepilog; 139 nepis++; 140 if (nepis > 1 && config.flags4 & CFG4space) 141 goto L1; 142 } 143 } 144 if (bp) 145 { bp.Bflags |= BFLprolog; 146 //printf("=============== prolog opt\n"); 147 } 148 } 149 } 150 151 /********************************************** 152 * No prolog/epilog optimization. 153 */ 154 155 @trusted 156 void cod5_noprol() 157 { 158 block *b; 159 160 //printf("no prolog optimization\n"); 161 startblock.Bflags |= BFLprolog; 162 for (b = startblock; b; b = b.Bnext) 163 { 164 b.Bflags &= ~BFLoutsideprolog; 165 switch (b.BC) 166 { case BCret: 167 case BCretexp: 168 b.Bflags |= BFLepilog; 169 break; 170 default: 171 b.Bflags &= ~BFLepilog; 172 } 173 } 174 } 175 176 /********************************************* 177 * Add block b, and its successors, to those blocks outside those requiring 178 * the function prolog. 179 */ 180 181 private void pe_add(block *b) 182 { 183 if (b.Bflags & BFLoutsideprolog || 184 need_prolog(b)) 185 return; 186 187 b.Bflags |= BFLoutsideprolog; 188 foreach (bl; ListRange(b.Bsucc)) 189 pe_add(list_block(bl)); 190 } 191 192 /********************************************** 193 * Determine if block needs the function prolog to be set up. 194 */ 195 196 @trusted 197 private int need_prolog(block *b) 198 { 199 if (b.Bregcon.used & fregsaved) 200 goto Lneed; 201 202 // If block referenced a param in 16 bit code 203 if (!I32 && b.Bflags & BFLrefparam) 204 goto Lneed; 205 206 // If block referenced a stack local 207 if (b.Bflags & BFLreflocal) 208 goto Lneed; 209 210 return 0; 211 212 Lneed: 213 return 1; 214 }