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