1 /** 2 * Expression trees (intermediate representation) 3 * 4 * Compiler implementation of the 5 * $(LINK2 https://www.dlang.org, D programming language). 6 * 7 * Copyright: Copyright (C) 1985-1998 by Symantec 8 * Copyright (C) 2000-2023 by The D Language Foundation, All Rights Reserved 9 * Authors: $(LINK2 https://www.digitalmars.com, Walter Bright) 10 * License: $(LINK2 https://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) 11 * Source: $(LINK2 https://github.com/dlang/dmd/blob/master/src/dmd/backend/el.d, backend/el.d) 12 */ 13 14 module dmd.backend.el; 15 16 // Online documentation: https://dlang.org/phobos/dmd_backend_el.html 17 18 import dmd.backend.cdef; 19 import dmd.backend.cc; 20 import dmd.backend.global; 21 import dmd.backend.oper; 22 import dmd.backend.type; 23 24 import dmd.backend.cc : Symbol; 25 26 import dmd.backend.dlist; 27 28 extern (C++): 29 @nogc: 30 nothrow: 31 @safe: 32 33 /* Routines to handle elems. */ 34 35 alias eflags_t = ubyte; 36 enum 37 { 38 EFLAGS_variadic = 1, // variadic function call 39 } 40 41 alias pef_flags_t = uint; 42 enum 43 { 44 PEFnotlvalue = 1, // although elem may look like 45 // an lvalue, it isn't 46 PEFtemplate_id = 0x10, // symbol is a template-id 47 PEFparentheses = 0x20, // expression was within () 48 PEFaddrmem = 0x40, // address of member 49 PEFdependent = 0x80, // value-dependent 50 PEFmember = 0x100, // was a class member access 51 } 52 53 alias nflags_t = ubyte; 54 enum 55 { 56 NFLli = 1, // loop invariant 57 NFLnogoal = 2, // evaluate elem for side effects only 58 NFLassign = 8, // unambiguous assignment elem 59 NFLdelcse = 0x40, // this is not the generating CSE 60 NFLtouns = 0x80, // relational operator was changed from signed to unsigned 61 } 62 63 /****************************************** 64 * Elems: 65 * Elems are the basic tree element. They can be either 66 * terminal elems (leaves), unary elems (left subtree exists) 67 * or binary elems (left and right subtrees exist). 68 */ 69 70 struct elem 71 { 72 debug ushort id; 73 enum IDelem = 0x4C45; // 'EL' 74 75 version (OSX) // workaround https://issues.dlang.org/show_bug.cgi?id=16466 76 align(16) eve EV; // variants for each type of elem 77 else 78 eve EV; // variants for each type of elem 79 80 ubyte Eoper; // operator (OPxxxx) 81 ubyte Ecount; // # of parents of this elem - 1, 82 // always 0 until CSE elimination is done 83 eflags_t Eflags; 84 85 union 86 { 87 // PARSER 88 struct 89 { 90 version (SCPP) 91 Symbol* Emember; // if PEFmember, this is the member 92 version (HTOD) 93 Symbol* Emember; // if PEFmember, this is the member 94 pef_flags_t PEFflags; 95 } 96 97 // OPTIMIZER 98 struct 99 { 100 tym_t Ety; // data type (TYxxxx) 101 uint Eexp; // index into expnod[] 102 uint Edef; // index into expdef[] 103 104 // These flags are all temporary markers, used once and then 105 // thrown away. 106 nflags_t Nflags; // NFLxxx 107 108 // MARS 109 ubyte Ejty; // original Mars type 110 } 111 112 // CODGEN 113 struct 114 { 115 // Ety2: Must be in same position as Ety! 116 tym_t Ety2; // data type (TYxxxx) 117 ubyte Ecomsub; // number of remaining references to 118 // this common subexp (used to determine 119 // first, intermediate, and last references 120 // to a CSE) 121 } 122 } 123 124 type *ET; // pointer to type of elem if TYstruct | TYarray 125 Srcpos Esrcpos; // source file position 126 } 127 128 void elem_debug(const elem* e) 129 { 130 debug assert(e.id == e.IDelem); 131 } 132 133 @trusted tym_t typemask(const elem* e) 134 { 135 version (MARS) 136 return e.Ety; 137 else 138 return PARSER ? e.ET.Tty : e.Ety; 139 } 140 141 @trusted 142 FL el_fl(const elem* e) { return cast(FL)e.EV.Vsym.Sfl; } 143 144 //#define Eoffset EV.sp.Voffset 145 //#define Esymnum EV.sp.Vsymnum 146 147 @trusted 148 inout(elem)* list_elem(inout list_t list) { return cast(inout(elem)*)list_ptr(list); } 149 150 @trusted 151 void list_setelem(list_t list, void* ptr) { list.ptr = cast(elem *)ptr; } 152 153 //#define cnst(e) ((e)->Eoper == OPconst) /* Determine if elem is a constant */ 154 //#define E1 EV.eop.Eleft /* left child */ 155 //#define E2 EV.eop.Eright /* right child */ 156 //#define Erd EV.sp.spu.Erd // reaching definition 157 158 void el_init(); 159 void el_reset(); 160 void el_term(); 161 elem *el_calloc(); 162 void el_free(elem *); 163 elem *el_combine(elem *,elem *); 164 elem *el_param(elem *,elem *); 165 elem *el_params(elem *, ...); 166 elem *el_params(void **args, int length); 167 elem *el_combines(void **args, int length); 168 int el_nparams(const elem *e); 169 void el_paramArray(elem ***parray, elem *e); 170 elem *el_pair(tym_t, elem *, elem *); 171 void el_copy(elem *, const elem *); 172 elem *el_alloctmp(tym_t); 173 elem *el_selecte1(elem *); 174 elem *el_selecte2(elem *); 175 elem *el_copytree(elem *); 176 void el_replace_sym(elem *e,const Symbol *s1,Symbol *s2); 177 elem *el_scancommas(elem *); 178 int el_countCommas(const(elem)*); 179 bool el_sideeffect(const elem *); 180 int el_depends(const(elem)* ea, const elem *eb); 181 targ_llong el_tolongt(elem *); 182 targ_llong el_tolong(elem *); 183 bool el_allbits(const elem*, int); 184 bool el_signx32(const elem *); 185 targ_ldouble el_toldouble(elem *); 186 void el_toconst(elem *); 187 elem *el_same(elem **); 188 elem *el_copytotmp(elem **); 189 bool el_match(const elem *, const elem *); 190 bool el_match2(const elem *, const elem *); 191 bool el_match3(const elem *, const elem *); 192 bool el_match4(const elem *, const elem *); 193 bool el_match5(const elem *, const elem *); 194 int el_appears(const(elem)* e, const Symbol *s); 195 Symbol *el_basesym(elem *e); 196 bool el_anydef(const elem *ed, const(elem)* e); 197 elem* el_bint(OPER, type*,elem*, elem*); 198 elem* el_unat(OPER, type*, elem*); 199 elem* el_bin(OPER, tym_t, elem*, elem*); 200 elem* el_una(OPER, tym_t, elem*); 201 extern(C) elem *el_longt(type *,targ_llong); 202 elem *el_settype(elem *,type *); 203 elem *el_typesize(type *); 204 elem *el_ptr_offset(Symbol *s,targ_size_t offset); 205 void el_replacesym(elem *,const Symbol *,Symbol *); 206 elem *el_nelems(type *); 207 208 extern (C) elem *el_long(tym_t,targ_llong); 209 extern (C) elem* el_vectorConst(tym_t ty, ulong val); 210 211 bool ERTOL(const elem *); 212 bool el_returns(const(elem) *); 213 //elem *el_dctor(elem *e,void *decl); 214 //elem *el_ddtor(elem *e,void *decl); 215 elem *el_ctor_dtor(elem *ec, elem *ed, elem **pedtor); 216 elem *el_ctor(elem *ector,elem *e,Symbol *sdtor); 217 elem *el_dtor(elem *edtor,elem *e); 218 elem *el_zero(type *t); 219 elem *el_const(tym_t, eve *); 220 elem *el_test(tym_t, eve *); 221 elem ** el_parent(elem *,elem **); 222 223 //#ifdef DEBUG 224 //void el_check(const(elem)*); 225 //#else 226 //#define el_check(e) ((void)0) 227 //#endif 228 229 elem *el_convfloat(elem *); 230 elem *el_convstring(elem *); 231 elem *el_convert(elem *e); 232 bool el_isdependent(elem *); 233 uint el_alignsize(elem *); 234 235 size_t el_opN(const elem *e, OPER op); 236 void el_opArray(elem ***parray, elem *e, OPER op); 237 void el_opFree(elem *e, OPER op); 238 extern (C) elem *el_opCombine(elem **args, size_t length, OPER op, tym_t ty); 239 240 void elem_print(const elem *, int nestlevel = 0); 241 void elem_print_const(const elem *); 242 void el_hydrate(elem **); 243 void el_dehydrate(elem **); 244 245 // elpicpie.d 246 elem *el_var(Symbol *); 247 elem *el_ptr(Symbol *);