1 /** 2 * Compiler implementation of the 3 * $(LINK2 http://www.dlang.org, D programming language). 4 * 5 * Copyright: Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved 6 * Authors: $(LINK2 http://www.digitalmars.com, Walter Bright) 7 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 8 * Source: $(DMDSRC _irstate.d) 9 */ 10 11 module ddmd.irstate; 12 13 import ddmd.arraytypes; 14 import ddmd.backend.type; 15 import ddmd.dmodule; 16 import ddmd.dsymbol; 17 import ddmd.func; 18 import ddmd.identifier; 19 import ddmd.statement; 20 import ddmd.globals; 21 import ddmd.mtype; 22 23 import ddmd.backend.cc; 24 import ddmd.backend.el; 25 26 extern (C++) struct Label; 27 28 /*********************************************************** 29 */ 30 struct IRState 31 { 32 IRState* prev; 33 Statement statement; 34 Module m; // module 35 Dsymbol symbol; 36 Identifier ident; 37 Symbol* shidden; // hidden parameter to function 38 Symbol* sthis; // 'this' parameter to function (member and nested) 39 Symbol* sclosure; // pointer to closure instance 40 Blockx* blx; 41 Dsymbols* deferToObj; // array of Dsymbol's to run toObjFile(bool multiobj) on later 42 elem* ehidden; // transmit hidden pointer to CallExp::toElem() 43 Symbol* startaddress; 44 VarDeclarations* varsInScope; // variables that are in scope that will need destruction later 45 Label*[void*]* labels; // table of labels used/declared in function 46 47 block* breakBlock; 48 block* contBlock; 49 block* switchBlock; 50 block* defaultBlock; 51 block* finallyBlock; 52 53 extern (D) this(IRState* irs, Statement s) 54 { 55 prev = irs; 56 statement = s; 57 if (irs) 58 { 59 m = irs.m; 60 shidden = irs.shidden; 61 sclosure = irs.sclosure; 62 sthis = irs.sthis; 63 blx = irs.blx; 64 deferToObj = irs.deferToObj; 65 varsInScope = irs.varsInScope; 66 labels = irs.labels; 67 } 68 } 69 70 extern (D) this(IRState* irs, Dsymbol s) 71 { 72 prev = irs; 73 symbol = s; 74 if (irs) 75 { 76 m = irs.m; 77 shidden = irs.shidden; 78 sclosure = irs.sclosure; 79 sthis = irs.sthis; 80 blx = irs.blx; 81 deferToObj = irs.deferToObj; 82 varsInScope = irs.varsInScope; 83 labels = irs.labels; 84 } 85 } 86 87 extern (D) this(Module m, Dsymbol s) 88 { 89 this.m = m; 90 symbol = s; 91 } 92 93 /**** 94 * Access labels AA from C++ code. 95 * Params: 96 * s = key 97 * Returns: 98 * pointer to value if it's there, null if not 99 */ 100 extern (C++) Label** lookupLabel(Statement s) 101 { 102 return cast(void*)s in *labels; 103 } 104 105 /**** 106 * Access labels AA from C++ code. 107 * Params: 108 * s = key 109 * label = value 110 */ 111 extern (C++) void insertLabel(Statement s, Label* label) 112 { 113 (*labels)[cast(void*)s] = label; 114 } 115 116 extern (C++) block* getBreakBlock(Identifier ident) 117 { 118 IRState* bc; 119 if (ident) 120 { 121 Statement related = null; 122 block* ret = null; 123 for (bc = &this; bc; bc = bc.prev) 124 { 125 // The label for a breakBlock may actually be some levels up (e.g. 126 // on a try/finally wrapping a loop). We'll see if this breakBlock 127 // is the one to return once we reach that outer statement (which 128 // in many cases will be this same statement). 129 if (bc.breakBlock) 130 { 131 related = bc.statement.getRelatedLabeled(); 132 ret = bc.breakBlock; 133 } 134 if (bc.statement == related && bc.prev.ident == ident) 135 return ret; 136 } 137 } 138 else 139 { 140 for (bc = &this; bc; bc = bc.prev) 141 { 142 if (bc.breakBlock) 143 return bc.breakBlock; 144 } 145 } 146 return null; 147 } 148 149 extern (C++) block* getContBlock(Identifier ident) 150 { 151 IRState* bc; 152 if (ident) 153 { 154 block* ret = null; 155 for (bc = &this; bc; bc = bc.prev) 156 { 157 // The label for a contBlock may actually be some levels up (e.g. 158 // on a try/finally wrapping a loop). We'll see if this contBlock 159 // is the one to return once we reach that outer statement (which 160 // in many cases will be this same statement). 161 if (bc.contBlock) 162 { 163 ret = bc.contBlock; 164 } 165 if (bc.prev && bc.prev.ident == ident) 166 return ret; 167 } 168 } 169 else 170 { 171 for (bc = &this; bc; bc = bc.prev) 172 { 173 if (bc.contBlock) 174 return bc.contBlock; 175 } 176 } 177 return null; 178 } 179 180 extern (C++) block* getSwitchBlock() 181 { 182 IRState* bc; 183 for (bc = &this; bc; bc = bc.prev) 184 { 185 if (bc.switchBlock) 186 return bc.switchBlock; 187 } 188 return null; 189 } 190 191 extern (C++) block* getDefaultBlock() 192 { 193 IRState* bc; 194 for (bc = &this; bc; bc = bc.prev) 195 { 196 if (bc.defaultBlock) 197 return bc.defaultBlock; 198 } 199 return null; 200 } 201 202 extern (C++) block* getFinallyBlock() 203 { 204 IRState* bc; 205 for (bc = &this; bc; bc = bc.prev) 206 { 207 if (bc.finallyBlock) 208 return bc.finallyBlock; 209 } 210 return null; 211 } 212 213 extern (C++) FuncDeclaration getFunc() 214 { 215 IRState* bc; 216 for (bc = &this; bc.prev; bc = bc.prev) 217 { 218 } 219 return cast(FuncDeclaration)bc.symbol; 220 } 221 222 /********************** 223 * Returns true if do array bounds checking for the current function 224 */ 225 extern (C++) bool arrayBoundsCheck() 226 { 227 bool result; 228 switch (global.params.useArrayBounds) 229 { 230 case BOUNDSCHECKoff: 231 result = false; 232 break; 233 case BOUNDSCHECKon: 234 result = true; 235 break; 236 case BOUNDSCHECKsafeonly: 237 { 238 result = false; 239 FuncDeclaration fd = getFunc(); 240 if (fd) 241 { 242 Type t = fd.type; 243 if (t.ty == Tfunction && (cast(TypeFunction)t).trust == TRUSTsafe) 244 result = true; 245 } 246 break; 247 } 248 default: 249 assert(0); 250 } 251 return result; 252 } 253 }