/dev/dmd2/src/dmd/backend/evalu8.c
C | 2000 lines | 1839 code | 83 blank | 78 comment | 237 complexity | ec4bfde454a2b034625191f6c2a29a2c MD5 | raw file
Possible License(s): AGPL-1.0, LGPL-2.1, ISC
Large files files are truncated, but you can click here to view the full file
- // Copyright (C) 1985-1998 by Symantec
- // Copyright (C) 2000-2011 by Digital Mars
- // All Rights Reserved
- // http://www.digitalmars.com
- // Written by Walter Bright
- /*
- * This source file is made available for personal use
- * only. The license is in /dmd/src/dmd/backendlicense.txt
- * or /dm/src/dmd/backendlicense.txt
- * For any other uses, please contact Digital Mars.
- */
-
- #if !SPP
-
- #include <math.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <float.h>
- #include <time.h>
-
- #if !defined(__OpenBSD__)
- // Mysteriously missing from OpenBSD
- #include <fenv.h>
- #endif
-
- #if __DMC__
- #include <fp.h>
- #endif
-
- #if __FreeBSD__ || __OpenBSD__
- #define fmodl fmod
- #endif
-
- #include "cc.h"
- #include "oper.h" /* OPxxxx definitions */
- #include "global.h"
- #include "el.h"
- #include "type.h"
-
- #if SCPP
- #include "parser.h"
- #include "cpp.h"
- #endif
-
- static char __file__[] = __FILE__; /* for tassert.h */
- #include "tassert.h"
-
- extern void error(const char *filename, unsigned linnum, const char *format, ...);
-
- #if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
- int _status87()
- {
- return fetestexcept(FE_ALL_EXCEPT);
- }
-
- void _clear87()
- {
- feclearexcept(FE_ALL_EXCEPT);
- }
- #endif
-
- CEXTERN elem * evalu8(elem *);
-
- /* When this !=0, we do constant folding on floating point constants
- * even if they raise overflow, underflow, invalid, etc. exceptions.
- */
-
- static int ignore_exceptions;
-
- /* When this is !=0, we try to fold out OPsizeof expressions.
- */
-
- static int resolve_sizeof;
-
- /************************************
- * Helper to do % for long doubles.
- */
-
- #if __DMC__
- long double _modulo(long double x, long double y)
- { short sw;
-
- __asm
- {
- fld tbyte ptr y
- fld tbyte ptr x // ST = x, ST1 = y
- FM1: // We don't use fprem1 because for some inexplicable
- // reason we get -5 when we do _modulo(15, 10)
- fprem // ST = ST % ST1
- fstsw word ptr sw
- fwait
- mov AH,byte ptr sw+1 // get msb of status word in AH
- sahf // transfer to flags
- jp FM1 // continue till ST < ST1
- fstp ST(1) // leave remainder on stack
- }
- }
- #endif
-
- /**********************
- * Return boolean result of constant elem.
- */
-
- HINT boolres(elem *e)
- { int b;
-
- //printf("boolres()\n");
- //elem_print(e);
- elem_debug(e);
- // assert((_status87() & 0x3800) == 0);
- switch (e->Eoper)
- {
- case OPrelconst:
- case OPstring:
- return TRUE;
-
- #if SCPP
- case OPvar:
- assert(CPP && PARSER);
- el_toconst(e);
- assert(e->Eoper == OPconst);
- #endif
- case OPconst:
- switch (tybasic(typemask(e)))
- { case TYchar:
- case TYuchar:
- case TYschar:
- case TYchar16:
- case TYshort:
- case TYushort:
- case TYint:
- case TYuint:
- case TYbool:
- case TYwchar_t:
- case TYenum:
- case TYmemptr:
- case TYlong:
- case TYulong:
- case TYdchar:
- case TYllong:
- case TYullong:
- #if TX86
- #if JHANDLE
- case TYjhandle:
- #endif
- //case TYnullptr:
- case TYnptr:
- case TYsptr:
- case TYcptr:
- case TYhptr:
- #endif
- case TYfptr:
- case TYvptr:
- b = el_tolong(e) != 0;
- break;
- case TYfloat:
- case TYifloat:
- case TYdouble:
- case TYidouble:
- case TYdouble_alias:
- case TYildouble:
- case TYldouble:
- { targ_ldouble ld = el_toldouble(e);
-
- if (isnan((double)ld))
- b = 1;
- else
- b = (ld != 0);
- break;
- }
- case TYcfloat:
- if (isnan(e->EV.Vcfloat.re) || isnan(e->EV.Vcfloat.im))
- b = 1;
- else
- b = e->EV.Vcfloat.re != 0 || e->EV.Vcfloat.im != 0;
- break;
- case TYcdouble:
- if (isnan(e->EV.Vcdouble.re) || isnan(e->EV.Vcdouble.im))
- b = 1;
- else
- b = e->EV.Vcdouble.re != 0 || e->EV.Vcdouble.im != 0;
- break;
- case TYcldouble:
- if (isnan(e->EV.Vcldouble.re) || isnan(e->EV.Vcldouble.im))
- b = 1;
- else
- b = e->EV.Vcldouble.re != 0 || e->EV.Vcldouble.im != 0;
- break;
- case TYstruct: // happens on syntax error of (struct x)0
- #if SCPP
- assert(errcnt);
- #else
- assert(0);
- #endif
- case TYvoid: /* happens if we get syntax errors or
- on RHS of && || expressions */
- b = 0;
- break;
-
- case TYcent:
- case TYucent:
- b = e->EV.Vcent.lsw || e->EV.Vcent.msw;
- break;
-
- default:
- #ifdef DEBUG
- WRTYxx(typemask(e));
- #endif
- assert(0);
- }
- break;
- default:
- assert(0);
- }
- return b;
- }
-
- /***************************
- * Return TRUE if expression will always evaluate to TRUE.
- */
-
- HINT iftrue(elem *e)
- {
- while (1)
- {
- assert(e);
- elem_debug(e);
- switch (e->Eoper)
- { case OPcomma:
- case OPinfo:
- e = e->E2;
- break;
- case OPrelconst:
- case OPconst:
- case OPstring:
- return boolres(e);
- default:
- return FALSE;
- }
- }
- }
-
- /***************************
- * Return TRUE if expression will always evaluate to FALSE.
- */
-
- HINT iffalse(elem *e)
- {
- while (1)
- { assert(e);
- elem_debug(e);
- switch (e->Eoper)
- { case OPcomma:
- case OPinfo:
- e = e->E2;
- break;
- case OPconst:
- return !boolres(e);
- //case OPstring:
- //case OPrelconst:
- default:
- return FALSE;
- }
- }
- }
-
- /******************************
- * Constant fold expression tree.
- * Calculate &symbol and &*e1 if we can.
- */
-
- #if SCPP
-
- elem *poptelem2(elem *e)
- {
- // Same as poptelem(), but we ignore floating point exceptions
- ignore_exceptions++;
- e = poptelem(e);
- ignore_exceptions--;
- return e;
- }
-
- elem *poptelem3(elem *e)
- {
- resolve_sizeof++;
- e = poptelem(e);
- resolve_sizeof--;
- return e;
- }
-
- elem *poptelem4(elem *e)
- {
- resolve_sizeof++;
- ignore_exceptions++;
- e = poptelem(e);
- ignore_exceptions--;
- resolve_sizeof--;
- return e;
- }
-
- elem *poptelem(elem *e)
- {
- elem *e1,*e2;
- unsigned op;
-
- //dbg_printf("poptelem(e = %p)\n", e); elem_print(e);
- #ifdef DEBUG
- assert(PARSER);
- assert(e && e->ET);
-
- if (controlc_saw)
- exit(1);
- // static int xxx; if (++xxx == 1000) *(char *)0 = 0;
- #endif
- elem_debug(e);
- type_debug(e->ET);
-
- op = e->Eoper;
-
- #ifdef DEBUG
- if (OTunary(op))
- assert(!e->E2 || op == OPinfo);
- #endif
-
- switch (op)
- {
- case OPvar:
- if (CPP && e->EV.sp.Vsym->Sflags & SFLvalue)
- el_toconst(e);
- break;
-
- case OPsizeof:
- if (resolve_sizeof)
- {
- e->Eoper = OPconst;
- e->EV.Vlong = type_size(e->EV.sp.Vsym->Stype);
- }
- break;
-
- case OPconst:
- case OPrelconst:
- case OPstring:
- break;
-
- case OPaddr:
- e1 = e->E1;
- if (e1->Eoper == OPvar)
- goto L3;
- e->E1 = e1 = poptelem(e1);
- if (e1->Eoper == OPind) /* if &*exp */
- { type *t;
-
- L6:
- t = e->ET;
- e1->E1 = cast(e1->E1,t);
- e = selecte1(selecte1(e,t),t);
- }
- else if (e1->Eoper == OPvar)
- { /* convert &var to relconst */
- L3:
- e = selecte1(e,e->ET);
- e->Eoper = OPrelconst;
- #if 1
- // If this is an address of a function template,
- // try to expand the template if it's got an explicit
- // parameter list.
- if (e->PEFflags & PEFtemplate_id)
- { symbol *s;
-
- s = e->EV.sp.Vsym;
- s = cpp_lookformatch(s, NULL, NULL,NULL,NULL,NULL,
- e->EV.sp.spu.Vtal, 1|8, NULL, NULL);
- if (s)
- {
- e->EV.sp.Vsym = s;
- param_free(&e->EV.sp.spu.Vtal);
- e->PEFflags &= ~PEFtemplate_id;
- type_settype(&e->ET, newpointer(s->Stype));
- }
- }
- #endif
- }
- break;
- case OPind:
- e->E1 = e1 = poptelem(e->E1);
- #if TX86
- if (e1->Eoper == OPrelconst)
- { /* convert *(&var) to var */
-
- e = selecte1(e,e->ET);
- e->Eoper = OPvar;
- }
- #else
- if (e1->Eoper == OPrelconst)
- {
- unsigned to_sz = tysize(tym_conv(e->ET));
- unsigned frm_sz = tysize(tym_conv(e1->ET));
-
- if (tyfunc(tybasic(e->ET->Tty)))
- to_sz = LONGSIZE;
- else if (tybasic(e->ET->Tty) == TYstruct || tybasic(e->ET->Tty) == TYarray)
- {
- to_sz = LONGSIZE;
- e1->ET = e->ET;
- }
- if(to_sz == frm_sz)
- { /* convert *(&var) to var */
- doit:
- e = selecte1(e,e->ET);
- e->Eoper = OPvar;
- }
- else /* handle the most common cases for now */
- { unsigned offset = e1->Eoffset;
- switch(to_sz)
- {
- case SHORTSIZE:
- if (frm_sz == LONGSIZE && (offset%LONGSIZE) == SHORTSIZE)
- goto doit;
- break;
- case CHARSIZE:
- if (frm_sz == LONGSIZE &&
- offset%(LONGSIZE-CHARSIZE) == CHARSIZE)
- goto doit;
- if (frm_sz == SHORTSIZE && offset&1)
- goto doit;
- break;
- }
- }
- }
- #endif
- break;
- #if TX86
- case OPptrlptr:
- e->E1 = e1 = poptelem(e->E1);
- // If casting a non-NULL constant pointer
- if (e1->Eoper == OPconst && el_tolong(e1) != 0)
- break;
- goto L5;
- case OPoffset:
- e->E1 = e1 = poptelem(e->E1);
- if (e1->Eoper == OPptrlptr)
- goto L6;
- goto L5;
- #endif
- case OPlngsht:
- e->E1 = e1 = poptelem(e->E1);
- L5:
- if (e1->Eoper == OPrelconst || e1->Eoper == OPstring)
- e = selecte1(e,e->ET);
- else
- goto eval;
- break;
- case OPandand:
- e->E1 = e1 = poptelem(e->E1);
- if (iffalse(e1))
- goto L2;
- else
- goto def;
- case OPoror:
- e->E1 = e1 = poptelem(e->E1);
- if (iftrue(e1))
- {
- L2: el_free(e->E2);
- e->E2 = NULL;
- e->Eoper = OPbool;
- e = poptelem(e);
- }
- else
- goto def;
- break;
- case OPcond:
- e->E1 = e1 = poptelem(e->E1);
- if (e1->Eoper == OPconst)
- {
- e2 = e->E2;
- type_free(e->ET);
- if (boolres(e1))
- { el_copy(e,e2->E1);
- e2->E1->Eoper = OPunde;
- e2->E1->ET = NULL;
- e2->E1->E1 = NULL;
- e2->E1->E2 = NULL;
- el_free(e2->E1);
- e2->E1 = NULL;
- }
- else
- { el_copy(e,e2->E2);
- e2->E2->Eoper = OPunde;
- e2->E2->ET = NULL;
- e2->E2->E1 = NULL;
- e2->E2->E2 = NULL;
- el_free(e2->E2);
- e2->E2 = NULL;
- }
- el_free(e2);
- el_free(e1);
- e = poptelem(e);
- }
- else
- goto def;
- break;
- case OPadd:
- e->E1 = e1 = poptelem(e->E1);
- e->E2 = e2 = poptelem(e->E2);
- if (e1->Eoper == OPconst)
- { /* swap leaves */
- e->E1 = e2;
- e2 = e->E2 = e1;
- e1 = e->E1;
- }
- goto L4;
- case OPmin:
- e->E1 = e1 = poptelem(e->E1);
- e->E2 = e2 = poptelem(e->E2);
- L4:
- if (e1->Eoper == OPrelconst || e1->Eoper == OPstring)
- {
- if (e2->Eoper == OPconst)
- { targ_int i = e2->EV.Vint;
-
- #if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
- if (i && e1->EV.sp.Vsym->Sfl == FLgot)
- break;
- #endif
- if (e->Eoper == OPmin)
- i = -i;
- e1->EV.sp.Voffset += i;
- e = selecte1(e,e->ET);
- break;
- }
- }
- goto eval;
- default:
- if (OTleaf(op))
- goto ret;
- e->E1 = poptelem(e->E1);
- def:
- if (OTbinary(op)) // if binary node
- {
- e->E2 = poptelem(e->E2);
- }
- eval:
- e = evalu8(e);
- break;
- }
- ret:
- return e;
- }
-
- /********************
- * Select E1 leaf of e, and give it type t.
- */
-
- elem *selecte1(elem *e,type *t)
- { elem *e1;
-
- elem_debug(e);
- assert(EOP(e));
- e1 = e->E1;
- el_settype(e1,t);
- e->E1 = NULL;
- el_free(e);
- return e1;
- }
-
- #endif
-
- /******************************
- * Evaluate a node with only constants as leaves.
- * Return with the result.
- */
-
- elem * evalu8(elem *e)
- { elem *e1,*e2;
- tym_t tym,tym2,uns;
- unsigned op;
- targ_int i1,i2;
- int i;
- targ_llong l1,l2;
- targ_ldouble d1,d2;
- elem esave;
-
- // assert((_status87() & 0x3800) == 0);
- assert(e && EOP(e));
- op = e->Eoper;
- elem_debug(e);
- e1 = e->E1;
-
- //printf("evalu8(): "); elem_print(e);
- elem_debug(e1);
- if (e1->Eoper == OPconst)
- {
- tym2 = 0;
- e2 = NULL;
- if (EBIN(e))
- { e2 = e->E2;
- elem_debug(e2);
- if (e2->Eoper == OPconst)
- {
- i2 = l2 = el_tolong(e2);
- d2 = el_toldouble(e2);
- }
- else
- return e;
- tym2 = tybasic(typemask(e2));
- }
- else
- {
- tym2 = 0;
- e2 = NULL;
- i2 = 0; // not used, but static analyzer complains
- l2 = 0; // "
- d2 = 0; // "
- }
- i1 = l1 = el_tolong(e1);
- d1 = el_toldouble(e1);
- tym = tybasic(typemask(e1)); /* type of op is type of left child */
-
- #if TX86 && SCPP
- // Huge pointers are always evaluated at runtime
- if (tym == TYhptr && (l1 != 0 || l2 != 0))
- return e;
- #endif
- esave = *e;
- #if !__OpenBSD__
- _clear87();
- #endif
- }
- else
- return e;
-
- /* if left or right leaf is unsigned, this is an unsigned operation */
- uns = tyuns(tym) | tyuns(tym2);
-
- /*elem_print(e);*/
- /*dbg_printf("x%lx ",l1); WROP(op); dbg_printf("x%lx = ",l2);*/
- #if 0
- if (0 && e2)
- {
- dbg_printf("d1 = %Lg, d2 = %Lg, op = %d, OPne = %d, tym = x%lx\n",d1,d2,op,OPne,tym);
- dbg_printf("tym1 = x%lx, tym2 = x%lx, e2 = %g\n",tym,tym2,e2->EV.Vdouble);
-
- union eve u;
- dbg_printf("d1 = x%16llx\n", (u.Vldouble = d1, u.Vullong));
- dbg_printf("d2 = x%16llx\n", (u.Vldouble = d2, u.Vullong));
- }
- #endif
- i = 0;
- switch (op)
- {
- case OPadd:
- switch (tym)
- {
- case TYfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vfloat = e1->EV.Vfloat + e2->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vcfloat.re = e1->EV.Vfloat;
- e->EV.Vcfloat.im = e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = e1->EV.Vfloat + e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = 0 + e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYdouble:
- case TYdouble_alias:
- switch (tym2)
- {
- case TYdouble:
- case TYdouble_alias:
- e->EV.Vdouble = e1->EV.Vdouble + e2->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vcdouble.re = e1->EV.Vdouble;
- e->EV.Vcdouble.im = e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = e1->EV.Vdouble + e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = 0 + e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vldouble = d1 + d2;
- break;
- case TYildouble:
- e->EV.Vcldouble.re = d1;
- e->EV.Vcldouble.im = d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = d1 + e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = 0 + e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYifloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vcfloat.re = e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vfloat = e1->EV.Vfloat + e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = 0 + e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vfloat + e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYidouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vcdouble.re = e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vdouble = e1->EV.Vdouble + e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = 0 + e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vdouble + e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYildouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vcldouble.re = d2;
- e->EV.Vcldouble.im = d1;
- break;
- case TYildouble:
- e->EV.Vldouble = d1 + d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = 0 + e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = d1 + e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYcfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re + e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im;
- break;
- case TYifloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im + e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re + e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im + e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYcdouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re + e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im;
- break;
- case TYidouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im + e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re + e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im + e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYcldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re + d2;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im;
- break;
- case TYildouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im + d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re + e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im + e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
-
- default:
- #if TX86
- if (intsize == 2)
- { if (tyfv(tym))
- e->EV.Vlong = (l1 & 0xFFFF0000) |
- (targ_ushort) ((targ_ushort) l1 + i2);
- else if (tyfv(tym2))
- e->EV.Vlong = (l2 & 0xFFFF0000) |
- (targ_ushort) (i1 + (targ_ushort) l2);
- else if (tyintegral(tym) || typtr(tym))
- e->EV.Vllong = l1 + l2;
- else
- assert(0);
- }
- else
- #endif
- if (tyintegral(tym) || typtr(tym))
- e->EV.Vllong = l1 + l2;
- else
- assert(0);
- break;
- }
- break;
-
- case OPmin:
- switch (tym)
- {
- case TYfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vfloat = e1->EV.Vfloat - e2->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vcfloat.re = e1->EV.Vfloat;
- e->EV.Vcfloat.im = -e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = e1->EV.Vfloat - e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = 0 - e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYdouble:
- case TYdouble_alias:
- switch (tym2)
- {
- case TYdouble:
- case TYdouble_alias:
- e->EV.Vdouble = e1->EV.Vdouble - e2->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vcdouble.re = e1->EV.Vdouble;
- e->EV.Vcdouble.im = -e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = e1->EV.Vdouble - e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = 0 - e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vldouble = d1 - d2;
- break;
- case TYildouble:
- e->EV.Vcldouble.re = d1;
- e->EV.Vcldouble.im = -d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = d1 - e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = 0 - e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYifloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vcfloat.re = -e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vfloat = e1->EV.Vfloat - e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = 0 - e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vfloat - e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYidouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vcdouble.re = -e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vdouble = e1->EV.Vdouble - e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = 0 - e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vdouble - e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYildouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vcldouble.re = -d2;
- e->EV.Vcldouble.im = d1;
- break;
- case TYildouble:
- e->EV.Vldouble = d1 - d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = 0 - e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = d1 - e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYcfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re - e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im;
- break;
- case TYifloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im - e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re - e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im - e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYcdouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re - e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im;
- break;
- case TYidouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im - e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re - e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im - e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYcldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re - d2;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im;
- break;
- case TYildouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im - d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re - e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im - e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
-
- default:
- #if TX86
- if (intsize == 2 &&
- tyfv(tym) && tysize[tym2] == 2)
- e->EV.Vllong = (l1 & 0xFFFF0000) |
- (targ_ushort) ((targ_ushort) l1 - i2);
- else
- #endif
- if (tyintegral(tym) || typtr(tym))
- e->EV.Vllong = l1 - l2;
- else
- assert(0);
- break;
- }
- break;
- case OPmul:
- if (tyintegral(tym) || typtr(tym))
- e->EV.Vllong = l1 * l2;
- else
- { switch (tym)
- {
- case TYfloat:
- switch (tym2)
- {
- case TYfloat:
- case TYifloat:
- e->EV.Vfloat = e1->EV.Vfloat * e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = e1->EV.Vfloat * e2->EV.Vcfloat.re;
- e->EV.Vcfloat.im = e1->EV.Vfloat * e2->EV.Vcfloat.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYdouble:
- case TYdouble_alias:
- switch (tym2)
- {
- case TYdouble:
- case TYdouble_alias:
- case TYidouble:
- e->EV.Vdouble = e1->EV.Vdouble * e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = e1->EV.Vdouble * e2->EV.Vcdouble.re;
- e->EV.Vcdouble.im = e1->EV.Vdouble * e2->EV.Vcdouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYldouble:
- switch (tym2)
- {
- case TYldouble:
- case TYildouble:
- e->EV.Vldouble = d1 * d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = d1 * e2->EV.Vcldouble.re;
- e->EV.Vcldouble.im = d1 * e2->EV.Vcldouble.im;
- break;
- default:
- assert(0);
- }
- break;
- case TYifloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vfloat = e1->EV.Vfloat * e2->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vfloat = -e1->EV.Vfloat * e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = -e1->EV.Vfloat * e2->EV.Vcfloat.im;
- e->EV.Vcfloat.im = e1->EV.Vfloat * e2->EV.Vcfloat.re;
- break;
- default:
- assert(0);
- }
- break;
- case TYidouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vdouble = e1->EV.Vdouble * e2->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vdouble = -e1->EV.Vdouble * e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = -e1->EV.Vdouble * e2->EV.Vcdouble.im;
- e->EV.Vcdouble.im = e1->EV.Vdouble * e2->EV.Vcdouble.re;
- break;
- default:
- assert(0);
- }
- break;
- case TYildouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vldouble = d1 * d2;
- break;
- case TYildouble:
- e->EV.Vldouble = -d1 * d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = -d1 * e2->EV.Vcldouble.im;
- e->EV.Vcldouble.im = d1 * e2->EV.Vcldouble.re;
- break;
- default:
- assert(0);
- }
- break;
- case TYcfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re * e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im * e2->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vcfloat.re = -e1->EV.Vcfloat.im * e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.re * e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat = Complex_f::mul(e1->EV.Vcfloat, e2->EV.Vcfloat);
- break;
- default:
- assert(0);
- }
- break;
- case TYcdouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re * e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im * e2->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vcdouble.re = -e1->EV.Vcdouble.im * e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.re * e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble = Complex_d::mul(e1->EV.Vcdouble, e2->EV.Vcdouble);
- break;
- default:
- assert(0);
- }
- break;
- case TYcldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re * d2;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im * d2;
- break;
- case TYildouble:
- e->EV.Vcldouble.re = -e1->EV.Vcldouble.im * d2;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.re * d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble = Complex_ld::mul(e1->EV.Vcldouble, e2->EV.Vcldouble);
- break;
- default:
- assert(0);
- }
- break;
- default:
- #ifdef DEBUG
- dbg_printf("tym = x%x\n",tym);
- elem_print(e);
- #endif
- assert(0);
- }
- }
- break;
- case OPdiv:
- if (!boolres(e2)) // divide by 0
- {
- #if SCPP
- if (!tyfloating(tym))
- #endif
- goto div0;
- }
- if (uns)
- e->EV.Vullong = ((targ_ullong) l1) / ((targ_ullong) l2);
- else
- { switch (tym)
- {
- case TYfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vfloat = e1->EV.Vfloat / e2->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vfloat = -e1->EV.Vfloat / e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = d1;
- e->EV.Vcfloat.im = 0;
- e->EV.Vcfloat = Complex_f::div(e->EV.Vcfloat, e2->EV.Vcfloat);
- break;
- default:
- assert(0);
- }
- break;
- case TYdouble:
- case TYdouble_alias:
- switch (tym2)
- {
- case TYdouble:
- case TYdouble_alias:
- e->EV.Vdouble = e1->EV.Vdouble / e2->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vdouble = -e1->EV.Vdouble / e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = d1;
- e->EV.Vcdouble.im = 0;
- e->EV.Vcdouble = Complex_d::div(e->EV.Vcdouble, e2->EV.Vcdouble);
- break;
- default:
- assert(0);
- }
- break;
- case TYldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vldouble = d1 / d2;
- break;
- case TYildouble:
- e->EV.Vldouble = -d1 / d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = d1;
- e->EV.Vcldouble.im = 0;
- e->EV.Vcldouble = Complex_ld::div(e->EV.Vcldouble, e2->EV.Vcldouble);
- break;
- default:
- assert(0);
- }
- break;
- case TYifloat:
- switch (tym2)
- {
- case TYfloat:
- case TYifloat:
- e->EV.Vfloat = e1->EV.Vfloat / e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat.re = 0;
- e->EV.Vcfloat.im = e1->EV.Vfloat;
- e->EV.Vcfloat = Complex_f::div(e->EV.Vcfloat, e2->EV.Vcfloat);
- break;
- default:
- assert(0);
- }
- break;
- case TYidouble:
- switch (tym2)
- {
- case TYdouble:
- case TYidouble:
- e->EV.Vdouble = e1->EV.Vdouble / e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble.re = 0;
- e->EV.Vcdouble.im = e1->EV.Vdouble;
- e->EV.Vcdouble = Complex_d::div(e->EV.Vcdouble, e2->EV.Vcdouble);
- break;
- default:
- assert(0);
- }
- break;
- case TYildouble:
- switch (tym2)
- {
- case TYldouble:
- case TYildouble:
- e->EV.Vldouble = d1 / d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble.re = 0;
- e->EV.Vcldouble.im = d1;
- e->EV.Vcldouble = Complex_ld::div(e->EV.Vcldouble, e2->EV.Vcldouble);
- break;
- default:
- assert(0);
- }
- break;
- case TYcfloat:
- switch (tym2)
- {
- case TYfloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.re / e2->EV.Vfloat;
- e->EV.Vcfloat.im = e1->EV.Vcfloat.im / e2->EV.Vfloat;
- break;
- case TYifloat:
- e->EV.Vcfloat.re = e1->EV.Vcfloat.im / e2->EV.Vfloat;
- e->EV.Vcfloat.im = -e1->EV.Vcfloat.re / e2->EV.Vfloat;
- break;
- case TYcfloat:
- e->EV.Vcfloat = Complex_f::div(e1->EV.Vcfloat, e2->EV.Vcfloat);
- break;
- default:
- assert(0);
- }
- break;
- case TYcdouble:
- switch (tym2)
- {
- case TYdouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.re / e2->EV.Vdouble;
- e->EV.Vcdouble.im = e1->EV.Vcdouble.im / e2->EV.Vdouble;
- break;
- case TYidouble:
- e->EV.Vcdouble.re = e1->EV.Vcdouble.im / e2->EV.Vdouble;
- e->EV.Vcdouble.im = -e1->EV.Vcdouble.re / e2->EV.Vdouble;
- break;
- case TYcdouble:
- e->EV.Vcdouble = Complex_d::div(e1->EV.Vcdouble, e2->EV.Vcdouble);
- break;
- default:
- assert(0);
- }
- break;
- case TYcldouble:
- switch (tym2)
- {
- case TYldouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.re / d2;
- e->EV.Vcldouble.im = e1->EV.Vcldouble.im / d2;
- break;
- case TYildouble:
- e->EV.Vcldouble.re = e1->EV.Vcldouble.im / d2;
- e->EV.Vcldouble.im = -e1->EV.Vcldouble.re / d2;
- break;
- case TYcldouble:
- e->EV.Vcldouble = Complex_ld::div(e1->EV.Vcldouble, e2->EV.Vcldouble);
- break;
- default:
- assert(0);
- }
- break;
- default:
- e->EV.Vllong = l1 / l2;
- break;
- }
- }
- break;
- case OPmod:
- if (!boolres(e2))
- {
- div0:
- #if SCPP
- synerr(EM_divby0);
- #else // MARS
- //error(e->Esrcpos.Sfilename, e->Esrcpos.Slinnum, "divide by zero");
- #endif
- break;
- }
- if (uns)
- e->EV.Vullong = ((targ_ullong) l1) % ((targ_ullong) l2);
- else
- {
- // BUG: what do we do for imaginary, complex?
- switch (tym)
- { case TYdouble:
- case TYidouble:
- case TYdouble_alias:
- e->EV.Vdouble = fmod(e1->EV.Vdouble,e2->EV.Vdouble);
- break;
- case TYfloat:
- case TYifloat:
- e->EV.Vfloat = fmodf(e1->EV.Vfloat,e2->EV.Vfloat);
- break;
- case TYldouble:
- case TYildouble:
- #if __DMC__
- e->EV.Vldouble = _modulo(d1, d2);
- #else
- e->EV.Vldouble = fmodl(d1, d2);
- #endif
- break;
- case TYcfloat:
- switch (tym2)
- {
- case TYfloat:
- case TYifloat:
- e->EV.Vcfloat.re = fmodf(e1->EV.Vcfloat.re, e2->EV.Vfloat);
- e->EV.Vcfloat.im = fmodf(e1->EV.Vcfloat.im, e2->EV.Vfloat);
- break;
- default:
- assert(0);
- }
- break;
- case TYcdouble:
- switch (tym2)
- {
- case TYdouble:
- case TYidouble:
- e->EV…
Large files files are truncated, but you can click here to view the full file