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-2016 by Digital Mars, All Rights Reserved
7  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
8  * License:     backendlicense.txt
9  * Source:      $(DMDSRC backend/_oper.d)
10  */
11 
12 module ddmd.backend.oper;
13 
14 extern (C++):
15 @nogc:
16 nothrow:
17 
18 alias int OPER;
19 enum
20 {
21         OPunde,                 // place holder for undefined operator
22 
23         OPadd,
24         OPmin,
25         OPmul,
26         OPdiv,
27         OPmod,
28         OPshr,                  // unsigned right shift
29         OPshl,
30         OPand,
31         OPxor,
32         OPor,
33         OPashr,                 // signed right shift
34         OPnot,
35         OPbool,                 // "booleanize"
36         OPcom,
37         OPcond,
38         OPcomma,
39         OPoror,
40         OPandand,
41         OPbit,                  // ref to bit field
42         OPind,                  // *E
43         OPaddr,                 // &E
44         OPneg,                  // unary -
45         OPuadd,                 // unary +
46         OPvoid,                 // where casting to void is not a no-op
47         OPabs,                  // absolute value
48         OPrndtol,               // round to short, long, long long (inline 8087 only)
49         OPrint,                 // round to int
50 
51         OPsqrt,                 // square root
52         OPsin,                  // sine
53         OPcos,                  // cosine
54         OPscale,                // ldexp
55         OPyl2x,                 // y * log2(x)
56         OPyl2xp1,               // y * log2(x + 1)
57         OPcmpxchg,              // cmpxchg
58 
59         OPstrlen,               // strlen()
60         OPstrcpy,               // strcpy()
61         OPstrcat,               // strcat()
62         OPstrcmp,               // strcmp()
63         OPmemcpy,
64         OPmemcmp,
65         OPmemset,
66         OPsetjmp,               // setjmp()
67 
68         OPremquo,               // / and % in one operation
69 
70         OPbsf,                  // bit scan forward
71         OPbsr,                  // bit scan reverse
72         OPbt,                   // bit test
73         OPbtc,                  // bit test and complement
74         OPbtr,                  // bit test and reset
75         OPbts,                  // bit test and set
76         OPbswap,                // swap bytes
77         OProl,                  // rotate left
78         OPror,                  // rotate right
79         OPbtst,                 // bit test
80         OPpopcnt,               // count of number of bits set to 1
81 
82         OPstreq,                // structure assignment
83 
84         OPnegass,               // x = -x
85         OPpostinc,              // x++
86         OPpostdec,              // x--
87 
88         OPeq,
89         OPaddass,
90         OPminass,
91         OPmulass,
92         OPdivass,
93         OPmodass,
94         OPshrass,
95         OPshlass,
96         OPandass,
97         OPxorass,
98         OPorass,
99 
100         OPashrass,
101 
102         // relational operators (in same order as corresponding tokens)
103         RELOPMIN,
104         OPle = RELOPMIN,
105         OPgt,
106         OPlt,
107         OPge,
108         OPeqeq,
109         OPne,
110 
111         OPunord,        // !<>=
112         OPlg,           // <>
113         OPleg,          // <>=
114         OPule,          // !>
115         OPul,           // !>=
116         OPuge,          // !<
117         OPug,           // !<=
118         OPue,           // !<>
119         OPngt,
120         OPnge,
121         OPnlt,
122         OPnle,
123         OPord,
124         OPnlg,
125         OPnleg,
126         OPnule,
127         OPnul,
128         OPnuge,
129         OPnug,
130         RELOPMAX,
131         OPnue = RELOPMAX,
132 
133 //**************** End of relational operators *****************
134 
135 /*      8,16,32,64      integral type of unspecified sign
136         s,u             signed/unsigned
137         f,d,ld          float/double/long double
138         np,fp,vp,f16p   near pointer/far pointer/handle pointer/far16 pointer
139         cvp             const handle pointer
140 */
141 
142         CNVOPMIN,
143         OPb_8 = CNVOPMIN,   // convert bit to byte
144         OPd_s32,
145         OPs32_d,
146         OPd_s16,
147         OPs16_d,
148         OPd_u16,
149         OPu16_d,
150         OPd_u32,
151         OPu32_d,
152         OPd_s64,
153         OPs64_d,
154         OPd_u64,
155         OPu64_d,
156         OPd_f,
157         OPf_d,
158         OPs16_32,       // short to long
159         OPu16_32,       // unsigned short to long
160         OP32_16,        // long to short
161         OPu8_16,        // unsigned char to short
162         OPs8_16,        // signed char to short
163         OP16_8,         // short to 8 bits
164         OPu32_64,       // unsigned long to long long
165         OPs32_64,       // long to long long
166         OP64_32,        // long long to long
167         OPu64_128,
168         OPs64_128,
169         OP128_64,
170 
171         // segmented
172         OPvp_fp,
173         OPcvp_fp,       // const handle * => far *
174         OPoffset,       // get offset of far pointer
175         OPnp_fp,        // convert near pointer to far
176         OPnp_f16p,      // from 0:32 to 16:16
177         OPf16p_np,      // from 16:16 to 0:32
178 
179         OPld_d,
180         OPd_ld,
181         CNVOPMAX,
182         OPld_u64 = CNVOPMAX,
183 
184 //**************** End of conversion operators *****************
185 
186         OPc_r,          // complex to real
187         OPc_i,          // complex to imaginary
188         OPmsw,          // top 32 bits of 64 bit word (32 bit code gen)
189                         // top 16 bits of 32 bit word (16 bit code gen)
190 
191         OPparam,                // function parameter separator
192         OPcall,                 // binary function call
193         OPucall,                // unary function call
194         OPcallns,               // binary function call, no side effects
195         OPucallns,              // unary function call, no side effects
196 
197         OPsizeof,               // for forward-ref'd structs
198         OPstrctor,              // call ctor on struct param
199         OPstrthis,              // 'this' pointer for OPstrctor
200         OPstrpar,               // structure func param
201         OPconst,                // constant
202         OPrelconst,             // constant that contains an address
203         OPvar,                  // variable
204         OPreg,                  // register (used in inline asm operand expressions)
205         OPcolon,                // : as in ?:
206         OPcolon2,               // alternate version with different EH semantics
207         OPstring,               // address of string
208         OPnullptr,              // null pointer
209         OPasm,                  // in-line assembly code
210         OPinfo,                 // attach info (used to attach ctor/dtor
211                                 // info for exception handling)
212         OPhalt,                 // insert HLT instruction
213         OPctor,
214         OPdtor,
215         OPmark,
216         OPdctor,                // D constructor
217         OPddtor,                // D destructor
218 
219         OPpair,                 // build register pair, E1 is lsb, E2 = msb
220         OPrpair,                // build reversed register pair, E1 is msb, E2 = lsb
221         OPframeptr,             // load pointer to base of frame
222         OPgot,                  // load pointer to global offset table
223         OPvector,               // SIMD vector operations
224         OPvecsto,               // SIMD vector store operations
225 
226         OPinp,                  // input from I/O port
227         OPoutp,                 // output to I/O port
228 
229         // C++ operators
230         OPnew,                  // operator new
231         OPanew,                 // operator new[]
232         OPdelete,               // operator delete
233         OPadelete,              // operator delete[]
234         OPbrack,                // [] subscript
235         OParrow,                // for -> overloading
236         OParrowstar,            // for ->* overloading
237         OPpreinc,               // ++x overloading
238         OPpredec,               // --x overloading
239 
240         OPva_start,             // va_start intrinsic (dmd)
241 
242         OPMAX                   // 1 past last operator
243 }
244 
245 /* Convert from token to assignment operator    */
246 //int asgtoktoop(int tok) { return tok + OPeq - TKeq; }
247 
248 
249 /************************************
250  * Determine things about relational operators.
251  */
252 
253 //OPER rel_toktoop(int tk) { return tk - TKle + RELOPMIN; }
254 
255 extern __gshared ubyte[RELOPMAX - RELOPMIN + 1]
256         _rel_not,
257         _rel_swap,
258         _rel_integral,
259         _rel_exception,
260         _rel_unord;
261 
262 int rel_not(int op)       { return _rel_not      [op - RELOPMIN]; }
263 int rel_swap(int op)      { return _rel_swap     [op - RELOPMIN]; }
264 int rel_integral(int op)  { return _rel_integral [op - RELOPMIN]; }
265 int rel_exception(int op) { return _rel_exception[op - RELOPMIN]; }
266 int rel_unord(int op)     { return _rel_unord    [op - RELOPMIN]; }
267 
268 /****************************************
269  * Conversion operators.
270  * Convert from conversion operator to conversion index
271  * parallel array invconvtab[] in cgelem.c)
272  */
273 int convidx(OPER op) { return op - CNVOPMIN; }
274 
275 
276 /**********************************
277  * Various types of operators:
278  *      OTbinary        binary
279  *      OTunary         unary
280  *      OTleaf          leaf
281  *      OTcommut        commutative (e1 op e2) == (e2 op e1)
282  *                      (assoc == !=)
283  *      OTassoc         associative (e1 op (e2 op e3)) == ((e1 op e2) op e3)
284  *                      (also commutative)
285  *      OTassign        assignment = op= i++ i-- i=-i str=
286  *      OTpost          post inc or post dec operator
287  *      OTeop0e         if (e op 0) => e
288  *      OTeop00         if (e op 0) => 0
289  *      OTeop1e         if (e op 1) => e
290  *      OTsideff        there are side effects to the operator (assign call
291  *                      post ?: && ||)
292  *      OTconv          type conversion operator that could appear on lhs of
293  *                      assignment operator
294  *      OTlogical       logical operator (result is 0 or 1)
295  *      OTwid           high order bits of operation are irrelevant
296  *      OTopeq          an op= operator
297  *      OTop            an operator that has a corresponding op=
298  *      OTcall          function call
299  *      OTrtol          operators that evaluate right subtree first then left
300  *      OTrel           == != < <= > >= operators
301  *      OTrel2          < <= > >= operators
302  *      OTdef           definition operator (assign call post asm)
303  *      OTae            potential common subexpression operator
304  *      OTboolnop       operation is a nop if boolean result is desired
305  */
306 
307 // Workaround 2.066.x bug by resolving the TYMAX value before using it as dimension.
308 static if (__VERSION__ <= 2066):
309     private enum computeEnumValue = OPMAX;
310 
311 extern __gshared ubyte[OPMAX] optab1;
312 extern __gshared ubyte[OPMAX] optab2;
313 extern __gshared ubyte[OPMAX] optab3;
314 extern __gshared ubyte[OPMAX] opcost;
315 
316 /* optab1[]     */      /* Use byte arrays to avoid index scaling       */
317 enum
318 {
319     _OTbinary       = 1,
320     _OTunary        = 2,
321     _OTcommut       = 4,
322     _OTassoc        = 8,
323     _OTsideff       = 0x10,
324     _OTeop0e        = 0x20,
325     _OTeop00        = 0x40,
326     _OTeop1e        = 0x80,
327 }
328 
329 /* optab2[]     */
330 enum
331 {
332     _OTlogical      = 1,
333     _OTwid          = 2,
334     _OTcall         = 4,
335     _OTrtol         = 8,
336     _OTassign       = 0x10,
337     _OTdef          = 0x20,
338     _OTae           = 0x40,
339 }
340 
341 // optab3[]
342 enum
343 {
344     _OTboolnop      = 1,
345 }
346 
347 ubyte OTbinary(int op)    { return optab1[op] & _OTbinary; }
348 ubyte OTunary(int op)     { return optab1[op] & _OTunary; }
349 bool  OTleaf(int op)      { return !(optab1[op] & (_OTunary|_OTbinary)); }
350 ubyte OTcommut(int op)    { return optab1[op] & _OTcommut; }
351 ubyte OTassoc(int op)     { return optab1[op] & _OTassoc; }
352 ubyte OTassign(int op)    { return optab2[op]&_OTassign; }
353 bool  OTpost(int op)      { return op == OPpostinc || op == OPpostdec; }
354 ubyte OTeop0e(int op)     { return optab1[op] & _OTeop0e; }
355 ubyte OTeop00(int op)     { return optab1[op] & _OTeop00; }
356 ubyte OTeop1e(int op)     { return optab1[op] & _OTeop1e; }
357 ubyte OTsideff(int op)    { return optab1[op] & _OTsideff; }
358 bool  OTconv(int op)      { return op >= CNVOPMIN && op <= CNVOPMAX; }
359 ubyte OTlogical(int op)   { return optab2[op] & _OTlogical; }
360 ubyte OTwid(int op)       { return optab2[op] & _OTwid; }
361 bool  OTopeq(int op)      { return op >= OPaddass && op <= OPashrass; }
362 bool  OTop(int op)        { return op >= OPadd && op <= OPor; }
363 ubyte OTcall(int op)      { return optab2[op] & _OTcall; }
364 ubyte OTrtol(int op)      { return optab2[op] & _OTrtol; }
365 bool  OTrel(int op)       { return op >= OPle && op <= OPnue; }
366 bool  OTrel2(int op)      { return op >= OPle && op <= OPge; }
367 ubyte OTdef(int op)       { return optab2[op] & _OTdef; }
368 ubyte OTae(int op)        { return optab2[op] & _OTae; }
369 ubyte OTboolnop(int op)   { return optab3[op] & _OTboolnop; }
370 bool  OTcalldef(int op)   { return OTcall(op) || op == OPstrcpy || op == OPstrcat || op == OPmemcpy; }
371 
372 /* Convert op= to op    */
373 int opeqtoop(int opx)   { return opx - OPaddass + OPadd; }
374 
375 /* Convert op to op=    */
376 int optoopeq(int opx)   { return opx - OPadd + OPaddass; }
377 
378 /***************************
379  * Determine properties of an elem.
380  * EBIN         binary node?
381  * EUNA         unary node?
382  * EOP          operator node (unary or binary)?
383  * ERTOL        right to left evaluation (left to right is default)
384  * Eunambig     unambiguous definition elem?
385  */
386 
387 //#define EBIN(e) (OTbinary((e)->Eoper))
388 //#define EUNA(e) (OTunary((e)->Eoper))
389 
390 /* ERTOL(e) is moved to el.c    */
391 
392 //#define Elvalue(e)      ((e)->E1)
393 //#define Eunambig(e)     (OTassign((e)->Eoper) && (e)->E1->Eoper == OPvar)
394 
395 //#define EOP(e)  (!OTleaf((e)->Eoper))
396