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-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/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     NFLaecp   = 0x10,  // AE or CP or VBE expression
57     NFLdelcse = 0x40,  // this is not the generating CSE
58     NFLtouns  = 0x80,  // relational operator was changed from signed to unsigned
59 }
60 
61 /******************************************
62  * Elems:
63  *      Elems are the basic tree element. They can be either
64  *      terminal elems (leaves), unary elems (left subtree exists)
65  *      or binary elems (left and right subtrees exist).
66  */
67 
68 struct elem
69 {
70     debug ushort      id;
71     enum IDelem = 0x4C45;   // 'EL'
72 
73     version (OSX) // workaround https://issues.dlang.org/show_bug.cgi?id=16466
74         align(16) eve EV; // variants for each type of elem
75     else
76         eve EV;           // variants for each type of elem
77 
78     ubyte Eoper;        // operator (OPxxxx)
79     ubyte Ecount;       // # of parents of this elem - 1,
80                         // always 0 until CSE elimination is done
81     eflags_t Eflags;
82 
83     union
84     {
85         // PARSER
86         struct
87         {
88             version (SCPP)
89                 Symbol* Emember;       // if PEFmember, this is the member
90             version (HTOD)
91                 Symbol* Emember;       // if PEFmember, this is the member
92             pef_flags_t PEFflags;
93         }
94 
95         // OPTIMIZER
96         struct
97         {
98             tym_t Ety;         // data type (TYxxxx)
99             uint Eexp;         // index into expnod[]
100             uint Edef;         // index into expdef[]
101 
102             // These flags are all temporary markers, used once and then
103             // thrown away.
104             nflags_t Nflags;   // NFLxxx
105 
106             // MARS
107             ubyte Ejty;        // original Mars type
108         }
109 
110         // CODGEN
111         struct
112         {
113             // Ety2: Must be in same position as Ety!
114             tym_t Ety2;        // data type (TYxxxx)
115             ubyte Ecomsub;     // number of remaining references to
116                                // this common subexp (used to determine
117                                // first, intermediate, and last references
118                                // to a CSE)
119         }
120     }
121 
122     type *ET;            // pointer to type of elem if TYstruct | TYarray
123     Srcpos Esrcpos;      // source file position
124 }
125 
126 void elem_debug(const elem* e)
127 {
128     debug assert(e.id == e.IDelem);
129 }
130 
131 version (MARS)
132     tym_t typemask(const elem* e) { return e.Ety; }
133 else
134     tym_t typemask(const elem* e) { return PARSER ? e.ET.Tty : e.Ety; }
135 
136 FL el_fl(const elem* e) { return cast(FL)e.EV.Vsym.Sfl; }
137 
138 //#define Eoffset         EV.sp.Voffset
139 //#define Esymnum         EV.sp.Vsymnum
140 
141 inout(elem)* list_elem(inout list_t list) { return cast(inout(elem)*)list_ptr(list); }
142 
143 void list_setelem(list_t list, void* ptr) { list.ptr = cast(elem *)ptr; }
144 
145 //#define cnst(e) ((e)->Eoper == OPconst) /* Determine if elem is a constant */
146 //#define E1        EV.eop.Eleft          /* left child                   */
147 //#define E2        EV.eop.Eright         /* right child                  */
148 //#define Erd       EV.sp.spu.Erd         // reaching definition
149 
150 void el_init();
151 void el_reset();
152 void el_term();
153 elem *el_calloc();
154 void el_free(elem *);
155 elem *el_combine(elem *,elem *);
156 elem *el_param(elem *,elem *);
157 elem *el_params(elem *, ...);
158 elem *el_params(void **args, int length);
159 elem *el_combines(void **args, int length);
160 int el_nparams(const elem *e);
161 void el_paramArray(elem ***parray, elem *e);
162 elem *el_pair(tym_t, elem *, elem *);
163 void el_copy(elem *, const elem *);
164 elem *el_alloctmp(tym_t);
165 elem *el_selecte1(elem *);
166 elem *el_selecte2(elem *);
167 elem *el_copytree(elem *);
168 void  el_replace_sym(elem *e,const Symbol *s1,Symbol *s2);
169 elem *el_scancommas(elem *);
170 int el_countCommas(const(elem)*);
171 bool el_sideeffect(const elem *);
172 int el_depends(const(elem)* ea, const elem *eb);
173 targ_llong el_tolongt(elem *);
174 targ_llong el_tolong(elem *);
175 bool el_allbits(const elem*, int);
176 bool el_signx32(const elem *);
177 targ_ldouble el_toldouble(elem *);
178 void el_toconst(elem *);
179 elem *el_same(elem **);
180 elem *el_copytotmp(elem **);
181 bool el_match(const elem *, const elem *);
182 bool el_match2(const elem *, const elem *);
183 bool el_match3(const elem *, const elem *);
184 bool el_match4(const elem *, const elem *);
185 bool el_match5(const elem *, const elem *);
186 int el_appears(const(elem)* e, const Symbol *s);
187 Symbol *el_basesym(elem *e);
188 bool el_anydef(const elem *ed, const(elem)* e);
189 elem* el_bint(OPER, type*,elem*, elem*);
190 elem* el_unat(OPER, type*, elem*);
191 elem* el_bin(OPER, tym_t, elem*, elem*);
192 elem* el_una(OPER, tym_t, elem*);
193 extern(C) elem *el_longt(type *,targ_llong);
194 elem *el_settype(elem *,type *);
195 elem *el_typesize(type *);
196 elem *el_ptr_offset(Symbol *s,targ_size_t offset);
197 void el_replacesym(elem *,const Symbol *,Symbol *);
198 elem *el_nelems(type *);
199 
200 extern (C) elem *el_long(tym_t,targ_llong);
201 
202 bool ERTOL(const elem *);
203 bool el_returns(const(elem) *);
204 //elem *el_dctor(elem *e,void *decl);
205 //elem *el_ddtor(elem *e,void *decl);
206 elem *el_ctor_dtor(elem *ec, elem *ed, elem **pedtor);
207 elem *el_ctor(elem *ector,elem *e,Symbol *sdtor);
208 elem *el_dtor(elem *edtor,elem *e);
209 elem *el_zero(type *t);
210 elem *el_const(tym_t, eve *);
211 elem *el_test(tym_t, eve *);
212 elem ** el_parent(elem *,elem **);
213 
214 //#ifdef DEBUG
215 //void el_check(const(elem)*);
216 //#else
217 //#define el_check(e)     ((void)0)
218 //#endif
219 
220 elem *el_convfloat(elem *);
221 elem *el_convstring(elem *);
222 elem *el_convert(elem *e);
223 bool el_isdependent(elem *);
224 uint el_alignsize(elem *);
225 
226 size_t el_opN(const elem *e, OPER op);
227 void el_opArray(elem ***parray, elem *e, OPER op);
228 void el_opFree(elem *e, OPER op);
229 extern (C) elem *el_opCombine(elem **args, size_t length, OPER op, tym_t ty);
230 
231 void elem_print(const elem *, int nestlevel = 0);
232 void elem_print_const(const elem *);
233 void el_hydrate(elem **);
234 void el_dehydrate(elem **);
235 
236 // elpicpie.d
237 elem *el_var(Symbol *);
238 elem *el_ptr(Symbol *);
239