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