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