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 *);