# HG changeset patch # User Robert Clipsham # Date 1243879329 -3600 # Node ID ff707c518ad7fff2f1b0b83e44220ddc48ce546e # Parent f35a9a77d2567640a29c882684fc90a2a0066b3f Removed unused files to allow for a pull. diff -r f35a9a77d256 -r ff707c518ad7 dmd2/array.c --- a/dmd2/array.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include -#include - -#if _MSC_VER || __MINGW32__ -#include -#endif - -#if IN_GCC -#include "gdc_alloca.h" -#endif - -#if _WIN32 -#include -#endif - -#ifndef _WIN32 -#include -#include -#include -#include -#include -#include -#endif - -#include "port.h" -#include "root.h" -#include "dchar.h" -#include "mem.h" - - -/********************************* Array ****************************/ - -Array::Array() -{ - data = NULL; - dim = 0; - allocdim = 0; -} - -Array::~Array() -{ - mem.free(data); -} - -void Array::mark() -{ unsigned u; - - mem.mark(data); - for (u = 0; u < dim; u++) - mem.mark(data[u]); // BUG: what if arrays of Object's? -} - -void Array::reserve(unsigned nentries) -{ - //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); - if (allocdim - dim < nentries) - { - allocdim = dim + nentries; - data = (void **)mem.realloc(data, allocdim * sizeof(*data)); - } -} - -void Array::setDim(unsigned newdim) -{ - if (dim < newdim) - { - reserve(newdim - dim); - } - dim = newdim; -} - -void Array::fixDim() -{ - if (dim != allocdim) - { data = (void **)mem.realloc(data, dim * sizeof(*data)); - allocdim = dim; - } -} - -void Array::push(void *ptr) -{ - reserve(1); - data[dim++] = ptr; -} - -void *Array::pop() -{ - return data[--dim]; -} - -void Array::shift(void *ptr) -{ - reserve(1); - memmove(data + 1, data, dim * sizeof(*data)); - data[0] = ptr; - dim++; -} - -void Array::insert(unsigned index, void *ptr) -{ - reserve(1); - memmove(data + index + 1, data + index, (dim - index) * sizeof(*data)); - data[index] = ptr; - dim++; -} - - -void Array::insert(unsigned index, Array *a) -{ - if (a) - { unsigned d; - - d = a->dim; - reserve(d); - if (dim != index) - memmove(data + index + d, data + index, (dim - index) * sizeof(*data)); - memcpy(data + index, a->data, d * sizeof(*data)); - dim += d; - } -} - - -/*********************************** - * Append array a to this array. - */ - -void Array::append(Array *a) -{ - insert(dim, a); -} - -void Array::remove(unsigned i) -{ - memmove(data + i, data + i + 1, (dim - i) * sizeof(data[0])); - dim--; -} - -char *Array::toChars() -{ - unsigned len; - unsigned u; - char **buf; - char *str; - char *p; - - buf = (char **)alloca(dim * sizeof(char *)); - len = 2; - for (u = 0; u < dim; u++) - { - buf[u] = ((Object *)data[u])->toChars(); - len += strlen(buf[u]) + 1; - } - str = (char *)mem.malloc(len); - - str[0] = '['; - p = str + 1; - for (u = 0; u < dim; u++) - { - if (u) - *p++ = ','; - len = strlen(buf[u]); - memcpy(p,buf[u],len); - p += len; - } - *p++ = ']'; - *p = 0; - return str; -} - -void Array::zero() -{ - memset(data,0,dim * sizeof(data[0])); -} - -void *Array::tos() -{ - return dim ? data[dim - 1] : NULL; -} - -int -#if _WIN32 - __cdecl -#endif - Array_sort_compare(const void *x, const void *y) -{ - Object *ox = *(Object **)x; - Object *oy = *(Object **)y; - - return ox->compare(oy); -} - -void Array::sort() -{ - if (dim) - { - qsort(data, dim, sizeof(Object *), Array_sort_compare); - } -} - -Array *Array::copy() -{ - Array *a = new Array(); - - a->setDim(dim); - memcpy(a->data, data, dim * sizeof(void *)); - return a; -} - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/dchar.c --- a/dmd2/dchar.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,482 +0,0 @@ - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include -#include - -#include "dchar.h" -#include "mem.h" - -#if M_UNICODE - -// Converts a char string to Unicode - -dchar *Dchar::dup(char *p) -{ - dchar *s; - size_t len; - - if (!p) - return NULL; - len = strlen(p); - s = (dchar *)mem.malloc((len + 1) * sizeof(dchar)); - for (unsigned i = 0; i < len; i++) - { - s[i] = (dchar)(p[i] & 0xFF); - } - s[len] = 0; - return s; -} - -dchar *Dchar::memchr(dchar *p, int c, int count) -{ - int u; - - for (u = 0; u < count; u++) - { - if (p[u] == c) - return p + u; - } - return NULL; -} - -#if _WIN32 && __DMC__ -__declspec(naked) -unsigned Dchar::calcHash(const dchar *str, unsigned len) -{ - __asm - { - mov ECX,4[ESP] - mov EDX,8[ESP] - xor EAX,EAX - test EDX,EDX - je L92 - -LC8: cmp EDX,1 - je L98 - cmp EDX,2 - je LAE - - add EAX,[ECX] -// imul EAX,EAX,025h - lea EAX,[EAX][EAX*8] - add ECX,4 - sub EDX,2 - jmp LC8 - -L98: mov DX,[ECX] - and EDX,0FFFFh - add EAX,EDX - ret - -LAE: add EAX,[ECX] -L92: ret - } -} -#else -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - unsigned hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(const uint16_t *)str; - return hash; - - case 2: - hash += *(const uint32_t *)str; - return hash; - - default: - hash += *(const uint32_t *)str; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} -#endif - -hash_t Dchar::icalcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash += *(const uint16_t *)str | 0x20; - return hash; - - case 2: - hash += *(const uint32_t *)str | 0x200020; - return hash; - - default: - hash += *(const uint32_t *)str | 0x200020; - hash *= 37; - str += 2; - len -= 2; - break; - } - } -} - -#elif MCBS - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; - hash += *(const uint16_t *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(const uint32_t *)str; - str += 4; - len -= 4; - break; - } - } -} - -#elif UTF8 - -// Specification is: http://anubis.dkuug.dk/JTC1/SC2/WG2/docs/n1335 - -char Dchar::mblen[256] = -{ - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, - 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, - 4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1, -}; - -dchar *Dchar::dec(dchar *pstart, dchar *p) -{ - while ((p[-1] & 0xC0) == 0x80) - p--; - return p; -} - -int Dchar::get(dchar *p) -{ - unsigned c; - unsigned char *q = (unsigned char *)p; - - c = q[0]; - switch (mblen[c]) - { - case 2: - c = ((c - 0xC0) << 6) | - (q[1] - 0x80); - break; - - case 3: - c = ((c - 0xE0) << 12) | - ((q[1] - 0x80) << 6) | - (q[2] - 0x80); - break; - - case 4: - c = ((c - 0xF0) << 18) | - ((q[1] - 0x80) << 12) | - ((q[2] - 0x80) << 6) | - (q[3] - 0x80); - break; - - case 5: - c = ((c - 0xF8) << 24) | - ((q[1] - 0x80) << 18) | - ((q[2] - 0x80) << 12) | - ((q[3] - 0x80) << 6) | - (q[4] - 0x80); - break; - - case 6: - c = ((c - 0xFC) << 30) | - ((q[1] - 0x80) << 24) | - ((q[2] - 0x80) << 18) | - ((q[3] - 0x80) << 12) | - ((q[4] - 0x80) << 6) | - (q[5] - 0x80); - break; - } - return c; -} - -dchar *Dchar::put(dchar *p, unsigned c) -{ - if (c <= 0x7F) - { - *p++ = c; - } - else if (c <= 0x7FF) - { - p[0] = 0xC0 + (c >> 6); - p[1] = 0x80 + (c & 0x3F); - p += 2; - } - else if (c <= 0xFFFF) - { - p[0] = 0xE0 + (c >> 12); - p[1] = 0x80 + ((c >> 6) & 0x3F); - p[2] = 0x80 + (c & 0x3F); - p += 3; - } - else if (c <= 0x1FFFFF) - { - p[0] = 0xF0 + (c >> 18); - p[1] = 0x80 + ((c >> 12) & 0x3F); - p[2] = 0x80 + ((c >> 6) & 0x3F); - p[3] = 0x80 + (c & 0x3F); - p += 4; - } - else if (c <= 0x3FFFFFF) - { - p[0] = 0xF8 + (c >> 24); - p[1] = 0x80 + ((c >> 18) & 0x3F); - p[2] = 0x80 + ((c >> 12) & 0x3F); - p[3] = 0x80 + ((c >> 6) & 0x3F); - p[4] = 0x80 + (c & 0x3F); - p += 5; - } - else if (c <= 0x7FFFFFFF) - { - p[0] = 0xFC + (c >> 30); - p[1] = 0x80 + ((c >> 24) & 0x3F); - p[2] = 0x80 + ((c >> 18) & 0x3F); - p[3] = 0x80 + ((c >> 12) & 0x3F); - p[4] = 0x80 + ((c >> 6) & 0x3F); - p[5] = 0x80 + (c & 0x3F); - p += 6; - } - else - assert(0); // not a UCS-4 character - return p; -} - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; -#if __I86__ - hash += *(const uint16_t *)str; -#else - hash += str[0] * 256 + str[1]; -#endif - return hash; - - case 3: - hash *= 37; -#if __I86__ - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; -#else - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif - return hash; - - default: - hash *= 37; -#if __I86__ - hash += *(const uint32_t *)str; -#else - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif - - str += 4; - len -= 4; - break; - } - } -} - -#else // ascii - -hash_t Dchar::calcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str; - return hash; - - case 2: - hash *= 37; -#if __I86__ - hash += *(const uint16_t *)str; -#else - hash += str[0] * 256 + str[1]; -#endif - return hash; - - case 3: - hash *= 37; -#if __I86__ - hash += (*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]; -#else - hash += (str[0] * 256 + str[1]) * 256 + str[2]; -#endif - return hash; - - default: - hash *= 37; -#if __I86__ - hash += *(const uint32_t *)str; -#else - hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3]; -#endif - str += 4; - len -= 4; - break; - } - } -} - -hash_t Dchar::icalcHash(const dchar *str, size_t len) -{ - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(const uint8_t *)str | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(const uint16_t *)str | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(const uint16_t *)str << 8) + - ((const uint8_t *)str)[2]) | 0x202020; - return hash; - - default: - hash *= 37; - hash += *(const uint32_t *)str | 0x20202020; - str += 4; - len -= 4; - break; - } - } -} - -#endif - -#if 0 -#include - -void main() -{ - // Print out values to hardcode into Dchar::mblen[] - int c; - int s; - - for (c = 0; c < 256; c++) - { - s = 1; - if (c >= 0xC0 && c <= 0xDF) - s = 2; - if (c >= 0xE0 && c <= 0xEF) - s = 3; - if (c >= 0xF0 && c <= 0xF7) - s = 4; - if (c >= 0xF8 && c <= 0xFB) - s = 5; - if (c >= 0xFC && c <= 0xFD) - s = 6; - - printf("%d", s); - if ((c & 15) == 15) - printf(",\n"); - else - printf(","); - } -} -#endif diff -r f35a9a77d256 -r ff707c518ad7 dmd2/dchar.h --- a/dmd2/dchar.h Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#ifndef DCHAR_H -#define DCHAR_H - -#if __GNUC__ && !_WIN32 -#include "gnuc.h" -#endif - -#if _MSC_VER - // Disable useless warnings about unreferenced functions - #pragma warning (disable : 4514) -#endif - -//#include "root.h" -typedef size_t hash_t; - -#undef TEXT - -// NOTE: All functions accepting pointer arguments must not be NULL - -#if M_UNICODE - -#include -#include - -typedef wchar_t dchar; -#define TEXT(x) L##x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { (void)pstart; return p - 1; } - static int len(const dchar *p) { return wcslen(p); } - static dchar get(dchar *p) { return *p; } - static dchar getprev(dchar *pstart, dchar *p) { (void)pstart; return p[-1]; } - static dchar *put(dchar *p, dchar c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) - { -#if __DMC__ - if (!*s1 && !*s2) // wcscmp is broken - return 0; -#endif - return wcscmp(s1, s2); -#if 0 - return (*s1 == *s2) - ? wcscmp(s1, s2) - : ((int)*s1 - (int)*s2); -#endif - } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars * sizeof(dchar)); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return iswalpha(c); } - static int isUpper(dchar c) { return iswupper(c); } - static int isLower(dchar c) { return iswlower(c); } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? towlower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? towupper(c) : c; } - static dchar *dup(dchar *p) { return ::_wcsdup(p); } // BUG: out of memory? - static dchar *dup(char *p); - static dchar *chr(dchar *p, unsigned c) { return wcschr(p, (dchar)c); } - static dchar *rchr(dchar *p, unsigned c) { return wcsrchr(p, (dchar)c); } - static dchar *memchr(dchar *p, int c, int count); - static dchar *cpy(dchar *s1, dchar *s2) { return wcscpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return wcsstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return wcsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::wcsnicmp(s1, s2, nchars); } - static hash_t icalcHash(const dchar *str, size_t len); -}; - -#elif MCBS - -#include -#include - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax MB_LEN_MAX - -#elif UTF8 - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 6 - -struct Dchar -{ - static char mblen[256]; - - static dchar *inc(dchar *p) { return p + mblen[*p & 0xFF]; } - static dchar *dec(dchar *pstart, dchar *p); - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p); - static int getprev(dchar *pstart, dchar *p) - { return *dec(pstart, p) & 0xFF; } - static dchar *put(dchar *p, unsigned c); - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } - static int isAlpha(dchar c) { return c <= 0x7F ? isalpha(c) : 0; } - static int isUpper(dchar c) { return c <= 0x7F ? isupper(c) : 0; } - static int isLower(dchar c) { return c <= 0x7F ? islower(c) : 0; } - static int isLocaleUpper(dchar c) { return isUpper(c); } - static int isLocaleLower(dchar c) { return isLower(c); } - static int toLower(dchar c) { return isUpper(c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return isLower(c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions - static int icmp(dchar *s1, dchar *s2) { return _mbsicmp(s1, s2); } - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::_mbsnicmp(s1, s2, nchars); } -}; - -#else - -#include - -#ifndef GCC_SAFE_DMD -#include -#endif - -typedef char dchar; -#define TEXT(x) x - -#define Dchar_mbmax 1 - -struct Dchar -{ - static dchar *inc(dchar *p) { return p + 1; } - static dchar *dec(dchar *pstart, dchar *p) { return p - 1; } - static int len(const dchar *p) { return strlen(p); } - static int get(dchar *p) { return *p & 0xFF; } - static int getprev(dchar *pstart, dchar *p) { return p[-1] & 0xFF; } - static dchar *put(dchar *p, unsigned c) { *p = c; return p + 1; } - static int cmp(dchar *s1, dchar *s2) { return strcmp(s1, s2); } - static int memcmp(const dchar *s1, const dchar *s2, int nchars) { return ::memcmp(s1, s2, nchars); } - static int isDigit(dchar c) { return '0' <= c && c <= '9'; } -#ifndef GCC_SAFE_DMD - static int isAlpha(dchar c) { return isalpha(c); } - static int isUpper(dchar c) { return isupper(c); } - static int isLower(dchar c) { return islower(c); } - static int isLocaleUpper(dchar c) { return isupper(c); } - static int isLocaleLower(dchar c) { return islower(c); } - static int toLower(dchar c) { return isupper(c) ? tolower(c) : c; } - static int toLower(dchar *p) { return toLower(*p); } - static int toUpper(dchar c) { return islower(c) ? toupper(c) : c; } - static dchar *dup(dchar *p) { return ::strdup(p); } // BUG: out of memory? -#endif - static dchar *chr(dchar *p, int c) { return strchr(p, c); } - static dchar *rchr(dchar *p, int c) { return strrchr(p, c); } - static dchar *memchr(dchar *p, int c, int count) - { return (dchar *)::memchr(p, c, count); } - static dchar *cpy(dchar *s1, dchar *s2) { return strcpy(s1, s2); } - static dchar *str(dchar *s1, dchar *s2) { return strstr(s1, s2); } - static hash_t calcHash(const dchar *str, size_t len); - - // Case insensitive versions -#ifdef __GNUC__ - static int icmp(dchar *s1, dchar *s2) { return strcasecmp(s1, s2); } -#else - static int icmp(dchar *s1, dchar *s2) { return stricmp(s1, s2); } -#endif - static int memicmp(const dchar *s1, const dchar *s2, int nchars) { return ::memicmp(s1, s2, nchars); } - static hash_t icalcHash(const dchar *str, size_t len); -}; - -#endif -#endif - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/e2ir.c.nolink --- a/dmd2/e2ir.c.nolink Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4679 +0,0 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include - -#include "lexer.h" -#include "expression.h" -#include "mtype.h" -#include "dsymbol.h" -#include "declaration.h" -#include "enum.h" -#include "aggregate.h" -#include "attrib.h" -#include "module.h" -#include "init.h" -#include "template.h" - -#if _WIN32 -#include "..\tk\mem.h" // for mem_malloc -#elif linux -#include "../tk/mem.h" // for mem_malloc -#endif - -#include "cc.h" -#include "el.h" -#include "oper.h" -#include "global.h" -#include "code.h" -#include "type.h" -#include "dt.h" -#include "irstate.h" -#include "id.h" -#include "type.h" -#include "toir.h" - -static char __file__[] = __FILE__; /* for tassert.h */ -#include "tassert.h" - - -elem *addressElem(elem *e, Type *t); -elem *array_toPtr(Type *t, elem *e); -elem *bit_assign(enum OPER op, elem *eb, elem *ei, elem *ev, int result); -elem *bit_read(elem *eb, elem *ei, int result); -elem *exp2_copytotemp(elem *e); - -#define el_setLoc(e,loc) ((e)->Esrcpos.Sfilename = (loc).filename, \ - (e)->Esrcpos.Slinnum = (loc).linnum) - -/************************************ - * Call a function. - */ - -elem *callfunc(Loc loc, - IRState *irs, - int directcall, // 1: don't do virtual call - Type *tret, // return type - elem *ec, // evaluates to function address - Type *ectype, // original type of ec - FuncDeclaration *fd, // if !=NULL, this is the function being called - Type *t, // TypeDelegate or TypeFunction for this function - elem *ehidden, // if !=NULL, this is the 'hidden' argument - Array *arguments) -{ - elem *ep; - elem *e; - elem *ethis = NULL; - elem *eside = NULL; - int i; - tym_t ty; - tym_t tyret; - enum RET retmethod; - int reverse; - TypeFunction *tf; - int op; - -#if 0 - printf("callfunc(directcall = %d, tret = '%s', ec = %p, fd = %p)\n", - directcall, tret->toChars(), ec, fd); - printf("ec: "); elem_print(ec); - if (fd) - printf("fd = '%s'\n", fd->toChars()); -#endif - - t = t->toBasetype(); - if (t->ty == Tdelegate) - { - // A delegate consists of: - // { Object *this; Function *funcptr; } - assert(!fd); - assert(t->nextOf()->ty == Tfunction); - tf = (TypeFunction *)(t->nextOf()); - ethis = ec; - ec = el_same(ðis); - ethis = el_una(OP64_32, TYnptr, ethis); // get this - ec = array_toPtr(t, ec); // get funcptr - ec = el_una(OPind, tf->totym(), ec); - } - else - { assert(t->ty == Tfunction); - tf = (TypeFunction *)(t); - } - retmethod = tf->retStyle(); - ty = ec->Ety; - if (fd) - ty = fd->toSymbol()->Stype->Tty; - reverse = tyrevfunc(ty); - ep = NULL; - if (arguments) - { - // j=1 if _arguments[] is first argument - int j = (tf->linkage == LINKd && tf->varargs == 1); - - for (i = 0; i < arguments->dim ; i++) - { Expression *arg; - elem *ea; - - arg = (Expression *)arguments->data[i]; - //printf("\targ[%d]: %s\n", i, arg->toChars()); - - size_t nparams = Argument::dim(tf->parameters); - if (i - j < nparams && i >= j) - { - Argument *p = Argument::getNth(tf->parameters, i - j); - - if (p->storageClass & (STCout | STCref)) - { - // Convert argument to a pointer, - // use AddrExp::toElem() - Expression *ae = arg->addressOf(NULL); - ea = ae->toElem(irs); - goto L1; - } - } - ea = arg->toElem(irs); - L1: - if (ea->Ety == TYstruct) - { - ea = el_una(OPstrpar, TYstruct, ea); - ea->Enumbytes = ea->E1->Enumbytes; - assert(ea->Enumbytes); - } - if (reverse) - ep = el_param(ep,ea); - else - ep = el_param(ea,ep); - } - } - - if (retmethod == RETstack) - { - if (!ehidden) - { // Don't have one, so create one - type *t; - - if (tf->next->toBasetype()->ty == Tstruct) - t = tf->next->toCtype(); - else - t = type_fake(tf->next->totym()); - Symbol *stmp = symbol_genauto(t); - ehidden = el_ptr(stmp); - } - if (ep) - { -#if 0 // BUG: implement - if (reverse && type_mangle(tfunc) == mTYman_cpp) - ep = el_param(ehidden,ep); - else -#endif - ep = el_param(ep,ehidden); - } - else - ep = ehidden; - ehidden = NULL; - } - assert(ehidden == NULL); - - if (fd && fd->isMember2()) - { - InterfaceDeclaration *intd; - Symbol *sfunc; - AggregateDeclaration *ad; - - ad = fd->isThis(); - if (ad) - { - ethis = ec; - if (ad->handle->ty == Tpointer && tybasic(ec->Ety) != TYnptr) - { - ethis = addressElem(ec, ectype); - } - } - else - { - // Evaluate ec for side effects - eside = ec; - } - sfunc = fd->toSymbol(); - - if (!fd->isVirtual() || - directcall || // BUG: fix - fd->isFinal() - ) - { - // make static call - ec = el_var(sfunc); - } - else - { - // make virtual call - elem *ev; - unsigned vindex; - - assert(ethis); - ev = el_same(ðis); - ev = el_una(OPind, TYnptr, ev); - vindex = fd->vtblIndex; - - // Build *(ev + vindex * 4) - ec = el_bin(OPadd,TYnptr,ev,el_long(TYint, vindex * 4)); - ec = el_una(OPind,TYnptr,ec); - ec = el_una(OPind,tybasic(sfunc->Stype->Tty),ec); - } - } - else if (fd && fd->isNested()) - { - assert(!ethis); - ethis = getEthis(0, irs, fd); - - } - - ep = el_param(ep, ethis); - - tyret = tret->totym(); - - // Look for intrinsic functions - if (ec->Eoper == OPvar && (op = intrinsic_op(ec->EV.sp.Vsym->Sident)) != -1) - { - el_free(ec); - if (OTbinary(op)) - { - ep->Eoper = op; - ep->Ety = tyret; - e = ep; - if (op == OPscale) - { elem *et; - - et = e->E1; - e->E1 = el_una(OPs32_d, TYdouble, e->E2); - e->E1 = el_una(OPd_ld, TYldouble, e->E1); - e->E2 = et; - e->Ety = tyret; - } - } - else - e = el_una(op,tyret,ep); - } - else if (ep) - e = el_bin(OPcall,tyret,ec,ep); - else - e = el_una(OPucall,tyret,ec); - - if (retmethod == RETstack) - { - e->Ety = TYnptr; - e = el_una(OPind, tyret, e); - } - -#if DMDV2 - if (tf->isref) - { - e->Ety = TYnptr; - e = el_una(OPind, tyret, e); - } -#endif - - if (tybasic(tyret) == TYstruct) - { - e->Enumbytes = tret->size(); - } - e = el_combine(eside, e); - return e; -} - -/******************************************* - * Take address of an elem. - */ - -elem *addressElem(elem *e, Type *t) -{ - elem **pe; - - //printf("addressElem()\n"); - - for (pe = &e; (*pe)->Eoper == OPcomma; pe = &(*pe)->E2) - ; - if ((*pe)->Eoper != OPvar && (*pe)->Eoper != OPind) - { Symbol *stmp; - elem *eeq; - elem *e = *pe; - type *tx; - - // Convert to ((tmp=e),tmp) - TY ty; - if (t && ((ty = t->toBasetype()->ty) == Tstruct || ty == Tsarray)) - tx = t->toCtype(); - else - tx = type_fake(e->Ety); - stmp = symbol_genauto(tx); - eeq = el_bin(OPeq,e->Ety,el_var(stmp),e); - if (e->Ety == TYstruct) - { - eeq->Eoper = OPstreq; - eeq->Enumbytes = e->Enumbytes; - } - else if (e->Ety == TYarray) - { - eeq->Eoper = OPstreq; - eeq->Ejty = eeq->Ety = TYstruct; - eeq->Enumbytes = t->size(); - } - *pe = el_bin(OPcomma,e->Ety,eeq,el_var(stmp)); - } - e = el_una(OPaddr,TYnptr,e); - return e; -} - -/***************************************** - * Convert array to a pointer to the data. - */ - -elem *array_toPtr(Type *t, elem *e) -{ - //printf("array_toPtr()\n"); - //elem_print(e); - t = t->toBasetype(); - switch (t->ty) - { - case Tpointer: - break; - - case Tarray: - case Tdelegate: - if (e->Eoper == OPcomma) - { - e->Ety = TYnptr; - e->E2 = array_toPtr(t, e->E2); - } - else if (e->Eoper == OPpair) - { - e->Eoper = OPcomma; - e->Ety = TYnptr; - } - else - { -#if 1 - e = el_una(OPmsw, TYnptr, e); -#else - e = el_una(OPaddr, TYnptr, e); - e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4)); - e = el_una(OPind, TYnptr, e); -#endif - } - break; - - case Tsarray: - e = el_una(OPaddr, TYnptr, e); - break; - - default: - t->print(); - assert(0); - } - return e; -} - -/***************************************** - * Convert array to a dynamic array. - */ - -elem *array_toDarray(Type *t, elem *e) -{ - unsigned dim; - elem *ef = NULL; - elem *ex; - - //printf("array_toDarray(t = %s)\n", t->toChars()); - //elem_print(e); - t = t->toBasetype(); - switch (t->ty) - { - case Tarray: - break; - - case Tsarray: - e = el_una(OPaddr, TYnptr, e); - dim = ((TypeSArray *)t)->dim->toInteger(); - e = el_pair(TYullong, el_long(TYint, dim), e); - break; - - default: - L1: - switch (e->Eoper) - { - case OPconst: - { - size_t len = tysize[tybasic(e->Ety)]; - elem *es = el_calloc(); - es->Eoper = OPstring; - - // Match MEM_PH_FREE for OPstring in ztc\el.c - es->EV.ss.Vstring = (char *)mem_malloc(len); - memcpy(es->EV.ss.Vstring, &e->EV, len); - - es->EV.ss.Vstrlen = len; - es->Ety = TYnptr; - e = es; - break; - } - - case OPvar: - e = el_una(OPaddr, TYnptr, e); - break; - - case OPcomma: - ef = el_combine(ef, e->E1); - ex = e; - e = e->E2; - ex->E1 = NULL; - ex->E2 = NULL; - el_free(ex); - goto L1; - - case OPind: - ex = e; - e = e->E1; - ex->E1 = NULL; - ex->E2 = NULL; - el_free(ex); - break; - - default: - { - // Copy expression to a variable and take the - // address of that variable. - Symbol *stmp; - tym_t ty = tybasic(e->Ety); - - if (ty == TYstruct) - { - if (e->Enumbytes == 4) - ty = TYint; - else if (e->Enumbytes == 8) - ty = TYllong; - } - e->Ety = ty; - stmp = symbol_genauto(type_fake(ty)); - e = el_bin(OPeq, e->Ety, el_var(stmp), e); - e = el_bin(OPcomma, TYnptr, e, el_una(OPaddr, TYnptr, el_var(stmp))); - break; - } - } - dim = 1; - e = el_pair(TYullong, el_long(TYint, dim), e); - break; - } - return el_combine(ef, e); -} - -/***************************************** - * Evaluate elem and convert to dynamic array. - */ - -elem *eval_Darray(IRState *irs, Expression *e) -{ - elem *ex; - - ex = e->toElem(irs); - return array_toDarray(e->type, ex); -} - -/************************************ - */ - -elem *sarray_toDarray(Loc loc, Type *tfrom, Type *tto, elem *e) -{ - //printf("sarray_toDarray()\n"); - //elem_print(e); - - elem *elen; - unsigned dim = ((TypeSArray *)tfrom)->dim->toInteger(); - - if (tto) - { - unsigned fsize = tfrom->nextOf()->size(); - unsigned tsize = tto->nextOf()->size(); - - if ((dim * fsize) % tsize != 0) - { - Lerr: - error(loc, "cannot cast %s to %s since sizes don't line up", tfrom->toChars(), tto->toChars()); - } - dim = (dim * fsize) / tsize; - } - L1: - elen = el_long(TYint, dim); - e = el_una(OPaddr, TYnptr, e); - e = el_pair(TYullong, elen, e); - return e; -} - -/******************************************* - * Set an array pointed to by eptr to evalue: - * eptr[0..edim] = evalue; - * Input: - * eptr where to write the data to - * evalue value to write - * edim number of times to write evalue to eptr[] - * tb type of evalue - */ - -elem *setArray(elem *eptr, elem *edim, Type *tb, elem *evalue, IRState *irs, int op) -{ int r; - elem *e; - int sz = tb->size(); - - if (tb->ty == Tfloat80 || tb->ty == Timaginary80) - r = RTLSYM_MEMSET80; - else if (tb->ty == Tcomplex80) - r = RTLSYM_MEMSET160; - else if (tb->ty == Tcomplex64) - r = RTLSYM_MEMSET128; - else - { - switch (sz) - { - case 1: r = RTLSYM_MEMSET8; break; - case 2: r = RTLSYM_MEMSET16; break; - case 4: r = RTLSYM_MEMSET32; break; - case 8: r = RTLSYM_MEMSET64; break; - default: r = RTLSYM_MEMSETN; break; - } - - /* Determine if we need to do postblit - */ - if (op != TOKblit) - { - Type *t = tb; - while (t->ty == Tsarray) - t = t->nextOf()->toBasetype(); - if (t->ty == Tstruct) - { StructDeclaration *sd = ((TypeStruct *)t)->sym; - if (sd->postblit) - { /* Need to do postblit. - * void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti); - */ - r = (op == TOKconstruct) ? RTLSYM_ARRAYSETCTOR : RTLSYM_ARRAYSETASSIGN; - evalue = el_una(OPaddr, TYnptr, evalue); - Expression *ti = tb->getTypeInfo(NULL); - elem *eti = ti->toElem(irs); - e = el_params(eti, edim, evalue, eptr, NULL); - e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); - return e; - } - } - } - - if (r == RTLSYM_MEMSETN) - { - // void *_memsetn(void *p, void *value, int dim, int sizelem) - evalue = el_una(OPaddr, TYnptr, evalue); - elem *esz = el_long(TYint, sz); - e = el_params(esz, edim, evalue, eptr, NULL); - e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); - return e; - } - } - if (sz > 1 && sz <= 8 && - evalue->Eoper == OPconst && el_allbits(evalue, 0)) - { - r = RTLSYM_MEMSET8; - edim = el_bin(OPmul, TYuint, edim, el_long(TYuint, sz)); - } - - if (evalue->Ety == TYstruct) - { - evalue = el_una(OPstrpar, TYstruct, evalue); - evalue->Enumbytes = evalue->E1->Enumbytes; - assert(evalue->Enumbytes); - } - - // Be careful about parameter side effect ordering - if (r == RTLSYM_MEMSET8) - { - e = el_param(edim, evalue); - e = el_bin(OPmemset,TYnptr,eptr,e); - } - else - { - e = el_params(edim, evalue, eptr, NULL); - e = el_bin(OPcall,TYnptr,el_var(rtlsym[r]),e); - } - return e; -} - -/*************************************** - */ - -elem *Expression::toElem(IRState *irs) -{ - print(); - assert(0); - return NULL; -} - -/************************************ - */ - -elem *SymbolExp::toElem(IRState *irs) -{ Symbol *s; - elem *e; - tym_t tym; - Type *tb = (op == TOKsymoff) ? var->type->toBasetype() : type->toBasetype(); - int offset = (op == TOKsymoff) ? ((SymOffExp*)this)->offset : 0; - FuncDeclaration *fd; - VarDeclaration *v = var->isVarDeclaration(); - - //printf("SymbolExp::toElem('%s') %p\n", toChars(), this); - //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null"); - if (op == TOKvar && var->needThis()) - { - error("need 'this' to access member %s", toChars()); - return el_long(TYint, 0); - } - s = var->toSymbol(); - fd = NULL; - if (var->toParent2()) - fd = var->toParent2()->isFuncDeclaration(); - - int nrvo = 0; - if (fd && fd->nrvo_can && fd->nrvo_var == var) - { - s = fd->shidden; - nrvo = 1; - } - - if (s->Sclass == SCauto || s->Sclass == SCparameter) - { - if (fd && fd != irs->getFunc()) - { // 'var' is a variable in an enclosing function. - elem *ethis; - int soffset; - - ethis = getEthis(loc, irs, fd); - ethis = el_una(OPaddr, TYnptr, ethis); - - if (v && v->offset) - soffset = v->offset; - else - { - soffset = s->Soffset; - /* If fd is a non-static member function of a class or struct, - * then ethis isn't the frame pointer. - * ethis is the 'this' pointer to the class/struct instance. - * We must offset it. - */ - if (fd->vthis) - { - soffset -= fd->vthis->toSymbol()->Soffset; - } - //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset); - } - - if (!nrvo) - soffset += offset; - - e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset)); - if (op == TOKvar) - e = el_una(OPind, TYnptr, e); - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - e = el_una(OPind, s->ty(), e); - else if (op == TOKsymoff && nrvo) - { e = el_una(OPind, TYnptr, e); - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } - goto L1; - } - } - - /* If var is a member of a closure - */ - if (v && v->offset) - { assert(irs->sclosure); - e = el_var(irs->sclosure); - e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset)); - if (op == TOKvar) - { e = el_una(OPind, type->totym(), e); - if (tybasic(e->Ety) == TYstruct) - e->Enumbytes = type->size(); - el_setLoc(e, loc); - } - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - { e->Ety = TYnptr; - e = el_una(OPind, s->ty(), e); - } - else if (op == TOKsymoff && nrvo) - { e = el_una(OPind, TYnptr, e); - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } - else if (op == TOKsymoff) - { - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } - goto L1; - } - - if (s->Sclass == SCauto && s->Ssymnum == -1) - { - //printf("\tadding symbol\n"); - symbol_add(s); - } - - if (var->isImportedSymbol()) - { - assert(op == TOKvar); - e = el_var(var->toImport()); - e = el_una(OPind,s->ty(),e); - } - else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - { // Static arrays are really passed as pointers to the array - // Out parameters are really references - e = el_var(s); - e->Ety = TYnptr; - if (op == TOKvar) - e = el_una(OPind, s->ty(), e); - else if (offset) - e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset)); - } - else if (op == TOKvar) - e = el_var(s); - else - { e = nrvo ? el_var(s) : el_ptr(s); - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } -L1: - if (op == TOKvar) - { - if (nrvo) - { - e->Ety = TYnptr; - e = el_una(OPind, 0, e); - } - if (tb->ty == Tfunction) - { - tym = s->Stype->Tty; - } - else - tym = type->totym(); - e->Ejty = e->Ety = tym; - if (tybasic(tym) == TYstruct) - { - e->Enumbytes = type->size(); - } - else if (tybasic(tym) == TYarray) - { - e->Ejty = e->Ety = TYstruct; - e->Enumbytes = type->size(); - } - } - el_setLoc(e,loc); - return e; -} - -#if 0 -elem *VarExp::toElem(IRState *irs) -{ Symbol *s; - elem *e; - tym_t tym; - Type *tb = type->toBasetype(); - FuncDeclaration *fd; - VarDeclaration *v = var->isVarDeclaration(); - - //printf("VarExp::toElem('%s') %p\n", toChars(), this); - //printf("\tparent = '%s'\n", var->parent ? var->parent->toChars() : "null"); - if (var->needThis()) - { - error("need 'this' to access member %s", toChars()); - return el_long(TYint, 0); - } - s = var->toSymbol(); - fd = NULL; - if (var->toParent2()) - fd = var->toParent2()->isFuncDeclaration(); - - int nrvo = 0; - if (fd && fd->nrvo_can && fd->nrvo_var == var) - { - s = fd->shidden; - nrvo = 1; - } - - if (s->Sclass == SCauto || s->Sclass == SCparameter) - { - if (fd && fd != irs->getFunc()) - { // 'var' is a variable in an enclosing function. - elem *ethis; - int soffset; - - ethis = getEthis(loc, irs, fd); - ethis = el_una(OPaddr, TYnptr, ethis); - - if (v && v->offset) - soffset = v->offset; - else - { - soffset = s->Soffset; - /* If fd is a non-static member function of a class or struct, - * then ethis isn't the frame pointer. - * ethis is the 'this' pointer to the class/struct instance. - * We must offset it. - */ - if (fd->vthis) - { - soffset -= fd->vthis->toSymbol()->Soffset; - } - //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset); - } - - ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset)); - e = el_una(OPind, 0, ethis); - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - goto L2; - goto L1; - } - } - - /* If var is a member of a closure - */ - if (v && v->offset) - { assert(irs->sclosure); - e = el_var(irs->sclosure); - e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset)); - e = el_una(OPind, type->totym(), e); - if (tybasic(e->Ety) == TYstruct) - e->Enumbytes = type->size(); - el_setLoc(e, loc); - - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - goto L2; - goto L1; - } - - if (s->Sclass == SCauto && s->Ssymnum == -1) - { - //printf("\tadding symbol\n"); - symbol_add(s); - } - - if (var->isImportedSymbol()) - { - e = el_var(var->toImport()); - e = el_una(OPind,s->ty(),e); - } - else if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - { // Static arrays are really passed as pointers to the array - // Out parameters are really references - e = el_var(s); -L2: - e->Ety = TYnptr; - e = el_una(OPind, s->ty(), e); - } - else - e = el_var(s); -L1: - if (nrvo) - { - e->Ety = TYnptr; - e = el_una(OPind, 0, e); - } - if (tb->ty == Tfunction) - { - tym = s->Stype->Tty; - } - else - tym = type->totym(); - e->Ejty = e->Ety = tym; - if (tybasic(tym) == TYstruct) - { - e->Enumbytes = type->size(); - } - else if (tybasic(tym) == TYarray) - { - e->Ejty = e->Ety = TYstruct; - e->Enumbytes = type->size(); - } - el_setLoc(e,loc); - return e; -} -#endif - -#if 0 -elem *SymOffExp::toElem(IRState *irs) -{ Symbol *s; - elem *e; - Type *tb = var->type->toBasetype(); - VarDeclaration *v = var->isVarDeclaration(); - FuncDeclaration *fd = NULL; - if (var->toParent2()) - fd = var->toParent2()->isFuncDeclaration(); - - //printf("SymOffExp::toElem(): %s\n", toChars()); - s = var->toSymbol(); - - int nrvo = 0; - if (fd && fd->nrvo_can && fd->nrvo_var == var) - { s = fd->shidden; - nrvo = 1; - } - - if (s->Sclass == SCauto && s->Ssymnum == -1) - symbol_add(s); - assert(!var->isImportedSymbol()); - - // This code closely parallels that in VarExp::toElem() - if (s->Sclass == SCauto || s->Sclass == SCparameter) - { - if (fd && fd != irs->getFunc()) - { // 'var' is a variable in an enclosing function. - elem *ethis; - int soffset; - - ethis = getEthis(loc, irs, fd); - ethis = el_una(OPaddr, TYnptr, ethis); - - if (v && v->offset) - soffset = v->offset; - else - { - soffset = s->Soffset; - /* If fd is a non-static member function of a class or struct, - * then ethis isn't the frame pointer. - * ethis is the 'this' pointer to the class/struct instance. - * We must offset it. - */ - if (fd->vthis) - { - soffset -= fd->vthis->toSymbol()->Soffset; - } - //printf("\tSoffset = x%x, sthis->Soffset = x%x\n", s->Soffset, irs->sthis->Soffset); - } - - if (!nrvo) - soffset += offset; - e = el_bin(OPadd, TYnptr, ethis, el_long(TYnptr, soffset)); - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - e = el_una(OPind, s->ty(), e); - else if (nrvo) - { e = el_una(OPind, TYnptr, e); - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } - goto L1; - } - } - - /* If var is a member of a closure - */ - if (v && v->offset) - { assert(irs->sclosure); - e = el_var(irs->sclosure); - e = el_bin(OPadd, TYnptr, e, el_long(TYint, v->offset)); - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - e = el_una(OPind, s->ty(), e); - else if (nrvo) - { e = el_una(OPind, TYnptr, e); - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } - goto L1; - } - - if ((var->isParameter() && tb->ty == Tsarray) || var->isOut() || var->isRef()) - { // Static arrays are really passed as pointers to the array - // Out parameters are really references - e = el_var(s); - e->Ety = TYnptr; - if (offset) - e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset)); - } - else - { e = nrvo ? el_var(s) : el_ptr(s); - e = el_bin(OPadd, e->Ety, e, el_long(TYint, offset)); - } - -L1: - el_setLoc(e,loc); - return e; -} -#endif - -/************************************** - */ - -elem *FuncExp::toElem(IRState *irs) -{ - elem *e; - Symbol *s; - - //printf("FuncExp::toElem() %s\n", toChars()); - s = fd->toSymbol(); - e = el_ptr(s); - if (fd->isNested()) - { - elem *ethis = getEthis(loc, irs, fd); - e = el_pair(TYullong, ethis, e); - } - - irs->deferToObj->push(fd); - el_setLoc(e,loc); - return e; -} - -/************************************** - */ - -elem *Dsymbol_toElem(Dsymbol *s, IRState *irs) -{ - elem *e = NULL; - Symbol *sp; - AttribDeclaration *ad; - VarDeclaration *vd; - ClassDeclaration *cd; - StructDeclaration *sd; - FuncDeclaration *fd; - TemplateMixin *tm; - TupleDeclaration *td; - TypedefDeclaration *tyd; - - //printf("Dsymbol_toElem() %s\n", s->toChars()); - ad = s->isAttribDeclaration(); - if (ad) - { - Array *decl = ad->include(NULL, NULL); - if (decl && decl->dim) - { - for (size_t i = 0; i < decl->dim; i++) - { - s = (Dsymbol *)decl->data[i]; - e = el_combine(e, Dsymbol_toElem(s, irs)); - } - } - } - else if ((vd = s->isVarDeclaration()) != NULL) - { - s = s->toAlias(); - if (s != vd) - return Dsymbol_toElem(s, irs); - if (vd->isStatic() || vd->storage_class & STCextern) - vd->toObjFile(0); - else - { - sp = s->toSymbol(); - symbol_add(sp); - //printf("\tadding symbol '%s'\n", sp->Sident); - if (vd->init) - { - ExpInitializer *ie; - - ie = vd->init->isExpInitializer(); - if (ie) - e = ie->exp->toElem(irs); - } - } - } - else if ((cd = s->isClassDeclaration()) != NULL) - { - irs->deferToObj->push(s); - } - else if ((sd = s->isStructDeclaration()) != NULL) - { - irs->deferToObj->push(sd); - } - else if ((fd = s->isFuncDeclaration()) != NULL) - { - //printf("function %s\n", fd->toChars()); - irs->deferToObj->push(fd); - } - else if ((tm = s->isTemplateMixin()) != NULL) - { - //printf("%s\n", tm->toChars()); - if (tm->members) - { - for (size_t i = 0; i < tm->members->dim; i++) - { - Dsymbol *sm = (Dsymbol *)tm->members->data[i]; - e = el_combine(e, Dsymbol_toElem(sm, irs)); - } - } - } - else if ((td = s->isTupleDeclaration()) != NULL) - { - for (size_t i = 0; i < td->objects->dim; i++) - { Object *o = (Object *)td->objects->data[i]; - if (o->dyncast() == DYNCAST_EXPRESSION) - { Expression *eo = (Expression *)o; - if (eo->op == TOKdsymbol) - { DsymbolExp *se = (DsymbolExp *)eo; - e = el_combine(e, Dsymbol_toElem(se->s, irs)); - } - } - } - } - else if ((tyd = s->isTypedefDeclaration()) != NULL) - { - irs->deferToObj->push(tyd); - } - return e; -} - -elem *DeclarationExp::toElem(IRState *irs) -{ elem *e; - - //printf("DeclarationExp::toElem() %s\n", toChars()); - e = Dsymbol_toElem(declaration, irs); - return e; -} - -/*************************************** - */ - -elem *ThisExp::toElem(IRState *irs) -{ elem *ethis; - FuncDeclaration *fd; - - //printf("ThisExp::toElem()\n"); - assert(irs->sthis); - - if (var) - { - assert(var->parent); - fd = var->toParent2()->isFuncDeclaration(); - assert(fd); - ethis = getEthis(loc, irs, fd); - } - else - ethis = el_var(irs->sthis); - - el_setLoc(ethis,loc); - return ethis; -} - -/*************************************** - */ - -elem *IntegerExp::toElem(IRState *irs) -{ elem *e; - - e = el_long(type->totym(), value); - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *RealExp::toElem(IRState *irs) -{ union eve c; - tym_t ty; - - //printf("RealExp::toElem(%p)\n", this); - memset(&c, 0, sizeof(c)); - ty = type->toBasetype()->totym(); - switch (ty) - { - case TYfloat: - case TYifloat: - c.Vfloat = value; - break; - - case TYdouble: - case TYidouble: - c.Vdouble = value; - break; - - case TYldouble: - case TYildouble: - c.Vldouble = value; - break; - - default: - print(); - type->print(); - type->toBasetype()->print(); - printf("ty = %d, tym = %x\n", type->ty, ty); - assert(0); - } - return el_const(ty, &c); -} - - -/*************************************** - */ - -elem *ComplexExp::toElem(IRState *irs) -{ union eve c; - tym_t ty; - real_t re; - real_t im; - - re = creall(value); - im = cimagl(value); - - memset(&c, 0, sizeof(c)); - ty = type->totym(); - switch (ty) - { - case TYcfloat: - c.Vcfloat.re = (float) re; - c.Vcfloat.im = (float) im; - break; - - case TYcdouble: - c.Vcdouble.re = (double) re; - c.Vcdouble.im = (double) im; - break; - - case TYcldouble: - c.Vcldouble.re = re; - c.Vcldouble.im = im; - break; - - default: - assert(0); - } - return el_const(ty, &c); -} - -/*************************************** - */ - -elem *NullExp::toElem(IRState *irs) -{ - return el_long(type->totym(), 0); -} - -/*************************************** - */ - -struct StringTab -{ - Module *m; // module we're generating code for - Symbol *si; - void *string; - size_t sz; - size_t len; -}; - -#define STSIZE 16 -StringTab stringTab[STSIZE]; -size_t stidx; - -static Symbol *assertexp_sfilename = NULL; -static char *assertexp_name = NULL; -static Module *assertexp_mn = NULL; - -void clearStringTab() -{ - //printf("clearStringTab()\n"); - memset(stringTab, 0, sizeof(stringTab)); - stidx = 0; - - assertexp_sfilename = NULL; - assertexp_name = NULL; - assertexp_mn = NULL; -} - -elem *StringExp::toElem(IRState *irs) -{ - elem *e; - Type *tb= type->toBasetype(); - - -#if 0 - printf("StringExp::toElem() %s, type = %s\n", toChars(), type->toChars()); -#endif - - if (tb->ty == Tarray) - { - Symbol *si; - dt_t *dt; - StringTab *st; - -#if 0 - printf("irs->m = %p\n", irs->m); - printf(" m = %s\n", irs->m->toChars()); - printf(" len = %d\n", len); - printf(" sz = %d\n", sz); -#endif - for (size_t i = 0; i < STSIZE; i++) - { - st = &stringTab[(stidx + i) % STSIZE]; - //if (!st->m) continue; - //printf(" st.m = %s\n", st->m->toChars()); - //printf(" st.len = %d\n", st->len); - //printf(" st.sz = %d\n", st->sz); - if (st->m == irs->m && - st->si && - st->len == len && - st->sz == sz && - memcmp(st->string, string, sz * len) == 0) - { - //printf("use cached value\n"); - si = st->si; // use cached value - goto L1; - } - } - - stidx = (stidx + 1) % STSIZE; - st = &stringTab[stidx]; - - dt = NULL; - toDt(&dt); - - si = symbol_generate(SCstatic,type_fake(TYdarray)); - si->Sdt = dt; - si->Sfl = FLdata; -#if ELFOBJ // Burton - si->Sseg = CDATA; -#endif - outdata(si); - - st->m = irs->m; - st->si = si; - st->string = string; - st->len = len; - st->sz = sz; - L1: - e = el_var(si); - } - else if (tb->ty == Tsarray) - { - Symbol *si; - dt_t *dt = NULL; - - toDt(&dt); - dtnzeros(&dt, sz); // leave terminating 0 - - si = symbol_generate(SCstatic,type_allocn(TYarray, tschar)); - si->Sdt = dt; - si->Sfl = FLdata; - -#if ELFOBJ // Burton - si->Sseg = CDATA; -#endif - outdata(si); - - e = el_var(si); - } - else if (tb->ty == Tpointer) - { - e = el_calloc(); - e->Eoper = OPstring; -#if 1 - // Match MEM_PH_FREE for OPstring in ztc\el.c - e->EV.ss.Vstring = (char *)mem_malloc((len + 1) * sz); - memcpy(e->EV.ss.Vstring, string, (len + 1) * sz); -#else - e->EV.ss.Vstring = (char *)string; -#endif - e->EV.ss.Vstrlen = (len + 1) * sz; - e->Ety = TYnptr; - } - else - { - printf("type is %s\n", type->toChars()); - assert(0); - } - el_setLoc(e,loc); - return e; -} - -elem *NewExp::toElem(IRState *irs) -{ elem *e; - Type *t; - Type *ectype; - - //printf("NewExp::toElem() %s\n", toChars()); - t = type->toBasetype(); - //printf("\ttype = %s\n", t->toChars()); - //if (member) - //printf("\tmember = %s\n", member->toChars()); - if (t->ty == Tclass) - { - Symbol *csym; - - t = newtype->toBasetype(); - assert(t->ty == Tclass); - TypeClass *tclass = (TypeClass *)(t); - ClassDeclaration *cd = tclass->sym; - - /* Things to do: - * 1) ex: call allocator - * 2) ey: set vthis for nested classes - * 3) ez: call constructor - */ - - elem *ex = NULL; - elem *ey = NULL; - elem *ez = NULL; - - if (allocator || onstack) - { elem *ei; - Symbol *si; - - if (onstack) - { - /* Create an instance of the class on the stack, - * and call it stmp. - * Set ex to be the &stmp. - */ - Symbol *s = symbol_calloc(tclass->sym->toChars()); - s->Sclass = SCstruct; - s->Sstruct = struct_calloc(); - s->Sstruct->Sflags |= 0; - s->Sstruct->Salignsize = tclass->sym->alignsize; - s->Sstruct->Sstructalign = tclass->sym->structalign; - s->Sstruct->Sstructsize = tclass->sym->structsize; - - ::type *tc = type_alloc(TYstruct); - tc->Ttag = (Classsym *)s; // structure tag name - tc->Tcount++; - s->Stype = tc; - - Symbol *stmp = symbol_genauto(tc); - ex = el_ptr(stmp); - } - else - { - ex = el_var(allocator->toSymbol()); - ex = callfunc(loc, irs, 1, type, ex, allocator->type, - allocator, allocator->type, NULL, newargs); - } - - si = tclass->sym->toInitializer(); - ei = el_var(si); - - if (cd->isNested()) - { - ey = el_same(&ex); - ez = el_copytree(ey); - } - else if (member) - ez = el_same(&ex); - - ex = el_una(OPind, TYstruct, ex); - ex = el_bin(OPstreq, TYnptr, ex, ei); - ex->Enumbytes = cd->size(loc); - ex = el_una(OPaddr, TYnptr, ex); - ectype = tclass; - } - else - { - csym = cd->toSymbol(); - ex = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_NEWCLASS]),el_ptr(csym)); - ectype = NULL; - - if (cd->isNested()) - { - ey = el_same(&ex); - ez = el_copytree(ey); - } - else if (member) - ez = el_same(&ex); -//elem_print(ex); -//elem_print(ey); -//elem_print(ez); - } - - if (thisexp) - { ClassDeclaration *cdthis = thisexp->type->isClassHandle(); - assert(cdthis); - //printf("cd = %s\n", cd->toChars()); - //printf("cdthis = %s\n", cdthis->toChars()); - assert(cd->isNested()); - int offset = 0; - Dsymbol *cdp = cd->toParent2(); // class we're nested in - elem *ethis; - -//printf("member = %p\n", member); -//printf("cdp = %s\n", cdp->toChars()); -//printf("cdthis = %s\n", cdthis->toChars()); - if (cdp != cdthis) - { int i = cdp->isClassDeclaration()->isBaseOf(cdthis, &offset); - assert(i); - } - ethis = thisexp->toElem(irs); - if (offset) - ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, offset)); - - ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset)); - ey = el_una(OPind, TYnptr, ey); - ey = el_bin(OPeq, TYnptr, ey, ethis); - -//printf("ex: "); elem_print(ex); -//printf("ey: "); elem_print(ey); -//printf("ez: "); elem_print(ez); - } - else if (cd->isNested()) - { /* Initialize cd->vthis: - * *(ey + cd.vthis.offset) = this; - */ - elem *ethis; - FuncDeclaration *thisfd = irs->getFunc(); - int offset = 0; - Dsymbol *cdp = cd->toParent2(); // class/func we're nested in - - if (cdp == thisfd) - { /* Class we're new'ing is a local class in this function: - * void thisfd() { class cd { } } - */ - if (irs->sclosure) - ethis = el_var(irs->sclosure); - else if (irs->sthis) - { -#if DMDV2 - if (thisfd->closureVars.dim) -#else - if (thisfd->nestedFrameRef) -#endif - ethis = el_ptr(irs->sthis); - else - ethis = el_var(irs->sthis); - } - else - { - ethis = el_long(TYnptr, 0); -#if DMDV2 - if (thisfd->closureVars.dim) -#else - if (thisfd->nestedFrameRef) -#endif - ethis->Eoper = OPframeptr; - } - } - else if (thisfd->vthis && - (cdp == thisfd->toParent2() || - (cdp->isClassDeclaration() && - cdp->isClassDeclaration()->isBaseOf(thisfd->toParent2()->isClassDeclaration(), &offset) - ) - ) - ) - { /* Class we're new'ing is at the same level as thisfd - */ - assert(offset == 0); // BUG: should handle this case - ethis = el_var(irs->sthis); - } - else - { - ethis = getEthis(loc, irs, cd->toParent2()); - ethis = el_una(OPaddr, TYnptr, ethis); - } - - ey = el_bin(OPadd, TYnptr, ey, el_long(TYint, cd->vthis->offset)); - ey = el_una(OPind, TYnptr, ey); - ey = el_bin(OPeq, TYnptr, ey, ethis); - - } - - if (member) - // Call constructor - ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments); - - e = el_combine(ex, ey); - e = el_combine(e, ez); - } - else if (t->ty == Tpointer && t->nextOf()->toBasetype()->ty == Tstruct) - { - Symbol *csym; - - t = newtype->toBasetype(); - assert(t->ty == Tstruct); - TypeStruct *tclass = (TypeStruct *)(t); - StructDeclaration *cd = tclass->sym; - - /* Things to do: - * 1) ex: call allocator - * 2) ey: set vthis for nested classes - * 3) ez: call constructor - */ - - elem *ex = NULL; - elem *ey = NULL; - elem *ez = NULL; - - if (allocator) - { elem *ei; - Symbol *si; - - ex = el_var(allocator->toSymbol()); - ex = callfunc(loc, irs, 1, type, ex, allocator->type, - allocator, allocator->type, NULL, newargs); - - si = tclass->sym->toInitializer(); - ei = el_var(si); - - if (member) - ez = el_same(&ex); - else - { /* Statically intialize with default initializer - */ - ex = el_una(OPind, TYstruct, ex); - ex = el_bin(OPstreq, TYnptr, ex, ei); - ex->Enumbytes = cd->size(loc); - ex = el_una(OPaddr, TYnptr, ex); - } - ectype = tclass; - } - else - { - d_uns64 elemsize = cd->size(loc); - - // call _d_newarrayT(ti, 1) - e = el_long(TYsize_t, 1); - e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); - - int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; - e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); - - // The new functions return an array, so convert to a pointer - // ex -> (unsigned)(e >> 32) - e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); - ex = el_una(OP64_32, TYnptr, e); - - ectype = NULL; - - if (member) - ez = el_same(&ex); -//elem_print(ex); -//elem_print(ey); -//elem_print(ez); - } - - if (member) - // Call constructor - ez = callfunc(loc, irs, 1, type, ez, ectype, member, member->type, NULL, arguments); - - e = el_combine(ex, ey); - e = el_combine(e, ez); - } - else if (t->ty == Tarray) - { - TypeDArray *tda = (TypeDArray *)(t); - - assert(arguments && arguments->dim >= 1); - if (arguments->dim == 1) - { // Single dimension array allocations - Expression *arg = (Expression *)arguments->data[0]; // gives array length - e = arg->toElem(irs); - d_uns64 elemsize = tda->next->size(); - - // call _d_newT(ti, arg) - e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); - int rtl = tda->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; - e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); - } - else - { // Multidimensional array allocations - e = el_long(TYint, arguments->dim); - for (size_t i = 0; i < arguments->dim; i++) - { - Expression *arg = (Expression *)arguments->data[i]; // gives array length - e = el_param(arg->toElem(irs), e); - assert(t->ty == Tarray); - t = t->nextOf(); - assert(t); - } - - e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); - - int rtl = t->isZeroInit() ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT; - e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); - } - } - else if (t->ty == Tpointer) - { - TypePointer *tp = (TypePointer *)t; - d_uns64 elemsize = tp->next->size(); - Expression *di = tp->next->defaultInit(); - d_uns64 disize = di->type->size(); - - // call _d_newarrayT(ti, 1) - e = el_long(TYsize_t, 1); - e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); - - int rtl = tp->next->isZeroInit() ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT; - e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e); - - // The new functions return an array, so convert to a pointer - // e -> (unsigned)(e >> 32) - e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32)); - e = el_una(OP64_32, t->totym(), e); - } - else - { - assert(0); - } - - el_setLoc(e,loc); - return e; -} - -//////////////////////////// Unary /////////////////////////////// - -/*************************************** - */ - -elem *NegExp::toElem(IRState *irs) -{ - elem *e = el_una(OPneg, type->totym(), e1->toElem(irs)); - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *ComExp::toElem(IRState *irs) -{ elem *e; - - elem *e1 = this->e1->toElem(irs); - tym_t ty = type->totym(); - if (this->e1->type->toBasetype()->ty == Tbool) - e = el_bin(OPxor, ty, e1, el_long(ty, 1)); - else - e = el_una(OPcom,ty,e1); - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *NotExp::toElem(IRState *irs) -{ - elem *e = el_una(OPnot, type->totym(), e1->toElem(irs)); - el_setLoc(e,loc); - return e; -} - - -/*************************************** - */ - -elem *HaltExp::toElem(IRState *irs) -{ elem *e; - - e = el_calloc(); - e->Ety = TYvoid; - e->Eoper = OPhalt; - el_setLoc(e,loc); - return e; -} - -/******************************************** - */ - -elem *AssertExp::toElem(IRState *irs) -{ elem *e; - elem *ea; - Type *t1 = e1->type->toBasetype(); - - //printf("AssertExp::toElem() %s\n", toChars()); - if (global.params.useAssert) - { - e = e1->toElem(irs); - - InvariantDeclaration *inv = (InvariantDeclaration *)(void *)1; - - // If e1 is a class object, call the class invariant on it - if (global.params.useInvariants && t1->ty == Tclass && - !((TypeClass *)t1)->sym->isInterfaceDeclaration()) - { -#if TARGET_LINUX - e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e); -#else - e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e); -#endif - } - // If e1 is a struct object, call the struct invariant on it - else if (global.params.useInvariants && - t1->ty == Tpointer && - t1->nextOf()->ty == Tstruct && - (inv = ((TypeStruct *)t1->nextOf())->sym->inv) != NULL) - { - e = callfunc(loc, irs, 1, inv->type->nextOf(), e, e1->type, inv, inv->type, NULL, NULL); - } - else - { - // Construct: (e1 || ModuleAssert(line)) - Symbol *sassert; - Module *m = irs->blx->module; - char *mname = m->srcfile->toChars(); - - //printf("filename = '%s'\n", loc.filename); - //printf("module = '%s'\n", m->srcfile->toChars()); - - /* If the source file name has changed, probably due - * to a #line directive. - */ - if (loc.filename && (msg || strcmp(loc.filename, mname) != 0)) - { elem *efilename; - - /* Cache values. - */ - //static Symbol *assertexp_sfilename = NULL; - //static char *assertexp_name = NULL; - //static Module *assertexp_mn = NULL; - - if (!assertexp_sfilename || strcmp(loc.filename, assertexp_name) != 0 || assertexp_mn != m) - { - dt_t *dt = NULL; - char *id; - int len; - - id = loc.filename; - len = strlen(id); - dtdword(&dt, len); - dtabytes(&dt,TYnptr, 0, len + 1, id); - - assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray)); - assertexp_sfilename->Sdt = dt; - assertexp_sfilename->Sfl = FLdata; -#if ELFOBJ - assertexp_sfilename->Sseg = CDATA; -#endif - outdata(assertexp_sfilename); - - assertexp_mn = m; - assertexp_name = id; - } - - efilename = el_var(assertexp_sfilename); - - if (msg) - { elem *emsg = msg->toElem(irs); - ea = el_var(rtlsym[RTLSYM_DASSERT_MSG]); - ea = el_bin(OPcall, TYvoid, ea, el_params(el_long(TYint, loc.linnum), efilename, emsg, NULL)); - } - else - { - ea = el_var(rtlsym[RTLSYM_DASSERT]); - ea = el_bin(OPcall, TYvoid, ea, el_param(el_long(TYint, loc.linnum), efilename)); - } - } - else - { - sassert = m->toModuleAssert(); - ea = el_bin(OPcall,TYvoid,el_var(sassert), - el_long(TYint, loc.linnum)); - } - e = el_bin(OPoror,TYvoid,e,ea); - } - } - else - { // BUG: should replace assert(0); with a HLT instruction - e = el_long(TYint, 0); - } - el_setLoc(e,loc); - return e; -} - -elem *PostExp::toElem(IRState *irs) -{ elem *e; - elem *einc; - - e = e1->toElem(irs); - einc = e2->toElem(irs); - e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec, - e->Ety,e,einc); - el_setLoc(e,loc); - return e; -} - -//////////////////////////// Binary /////////////////////////////// - -/******************************************** - */ - -elem *BinExp::toElemBin(IRState *irs,int op) -{ - //printf("toElemBin() '%s'\n", toChars()); - - tym_t tym = type->totym(); - - elem *el = e1->toElem(irs); - elem *er = e2->toElem(irs); - elem *e = el_bin(op,tym,el,er); - el_setLoc(e,loc); - return e; -} - - -/*************************************** - */ - -elem *AddExp::toElem(IRState *irs) -{ elem *e; - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) - ) - { - error("Array operation %s not implemented", toChars()); - } - else - e = toElemBin(irs,OPadd); - return e; -} - -/*************************************** - */ - -elem *MinExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPmin); -} - -/*************************************** - */ - -elem *CatExp::toElem(IRState *irs) -{ elem *e; - -#if 0 - printf("CatExp::toElem()\n"); - print(); -#endif - - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - Type *tn; - -#if 0 - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) - ) -#endif - - Type *ta = tb1->nextOf() ? e1->type : e2->type; - tn = tb1->nextOf() ? tb1->nextOf() : tb2->nextOf(); - { - if (e1->op == TOKcat) - { - elem *ep; - CatExp *ce = this; - int n = 2; - - ep = eval_Darray(irs, ce->e2); - do - { - n++; - ce = (CatExp *)ce->e1; - ep = el_param(ep, eval_Darray(irs, ce->e2)); - } while (ce->e1->op == TOKcat); - ep = el_param(ep, eval_Darray(irs, ce->e1)); -#if 1 - ep = el_params( - ep, - el_long(TYint, n), - ta->getTypeInfo(NULL)->toElem(irs), - NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep); -#else - ep = el_params( - ep, - el_long(TYint, n), - el_long(TYint, tn->size()), - NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep); -#endif - } - else - { - elem *e1; - elem *e2; - elem *ep; - - e1 = eval_Darray(irs, this->e1); - e2 = eval_Darray(irs, this->e2); -#if 1 - ep = el_params(e2, e1, ta->getTypeInfo(NULL)->toElem(irs), NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep); -#else - ep = el_params(el_long(TYint, tn->size()), e2, e1, NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep); -#endif - } - el_setLoc(e,loc); - } -#if 0 - else if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - e2->type->equals(tb1->next)) - { - error("array cat with element not implemented"); - e = el_long(TYint, 0); - } - else - assert(0); -#endif - return e; -} - -/*************************************** - */ - -elem *MulExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPmul); -} - -/************************************ - */ - -elem *DivExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPdiv); -} - -/*************************************** - */ - -elem *ModExp::toElem(IRState *irs) -{ - elem *e; - elem *e1; - elem *e2; - tym_t tym; - - tym = type->totym(); - - e1 = this->e1->toElem(irs); - e2 = this->e2->toElem(irs); - -#if 0 // Now inlined - if (this->e1->type->isfloating()) - { elem *ep; - - switch (this->e1->type->ty) - { - case Tfloat32: - case Timaginary32: - e1 = el_una(OPf_d, TYdouble, e1); - e2 = el_una(OPf_d, TYdouble, e2); - case Tfloat64: - case Timaginary64: - e1 = el_una(OPd_ld, TYldouble, e1); - e2 = el_una(OPd_ld, TYldouble, e2); - break; - case Tfloat80: - case Timaginary80: - break; - default: - assert(0); - break; - } - ep = el_param(e2,e1); - e = el_bin(OPcall,tym,el_var(rtlsym[RTLSYM_MODULO]),ep); - } - else -#endif - e = el_bin(OPmod,tym,e1,e2); - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *CmpExp::toElem(IRState *irs) -{ - elem *e; - enum OPER eop; - Type *t1 = e1->type->toBasetype(); - Type *t2 = e2->type->toBasetype(); - - switch (op) - { - case TOKlt: eop = OPlt; break; - case TOKgt: eop = OPgt; break; - case TOKle: eop = OPle; break; - case TOKge: eop = OPge; break; - case TOKequal: eop = OPeqeq; break; - case TOKnotequal: eop = OPne; break; - - // NCEG floating point compares - case TOKunord: eop = OPunord; break; - case TOKlg: eop = OPlg; break; - case TOKleg: eop = OPleg; break; - case TOKule: eop = OPule; break; - case TOKul: eop = OPul; break; - case TOKuge: eop = OPuge; break; - case TOKug: eop = OPug; break; - case TOKue: eop = OPue; break; - default: - dump(0); - assert(0); - } - if (!t1->isfloating()) - { - // Convert from floating point compare to equivalent - // integral compare - eop = (enum OPER)rel_integral(eop); - } - if ((int)eop > 1 && t1->ty == Tclass && t2->ty == Tclass) - { -#if 1 - assert(0); -#else - elem *ec1; - elem *ec2; - - ec1 = e1->toElem(irs); - ec2 = e2->toElem(irs); - e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_CMP]),el_param(ec1, ec2)); - e = el_bin(eop, TYint, e, el_long(TYint, 0)); -#endif - } - else if ((int)eop > 1 && - (t1->ty == Tarray || t1->ty == Tsarray) && - (t2->ty == Tarray || t2->ty == Tsarray)) - { - elem *ea1; - elem *ea2; - elem *ep; - Type *telement = t1->nextOf()->toBasetype(); - int rtlfunc; - - ea1 = e1->toElem(irs); - ea1 = array_toDarray(t1, ea1); - ea2 = e2->toElem(irs); - ea2 = array_toDarray(t2, ea2); - -#if 1 - ep = el_params(telement->arrayOf()->getInternalTypeInfo(NULL)->toElem(irs), - ea2, ea1, NULL); - rtlfunc = RTLSYM_ARRAYCMP2; -#else - ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL); - rtlfunc = RTLSYM_ARRAYCMP; -#endif - e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); - e = el_bin(eop, TYint, e, el_long(TYint, 0)); - el_setLoc(e,loc); - } - else - { - if ((int)eop <= 1) - { - /* The result is determinate, create: - * (e1 , e2) , eop - */ - e = toElemBin(irs,OPcomma); - e = el_bin(OPcomma,e->Ety,e,el_long(e->Ety,(int)eop)); - } - else - e = toElemBin(irs,eop); - } - return e; -} - -elem *EqualExp::toElem(IRState *irs) -{ - //printf("EqualExp::toElem() %s\n", toChars()); - - elem *e; - enum OPER eop; - Type *t1 = e1->type->toBasetype(); - Type *t2 = e2->type->toBasetype(); - - switch (op) - { - case TOKequal: eop = OPeqeq; break; - case TOKnotequal: eop = OPne; break; - default: - dump(0); - assert(0); - } - - //printf("EqualExp::toElem()\n"); - if (t1->ty == Tstruct) - { // Do bit compare of struct's - elem *es1; - elem *es2; - elem *ecount; - - es1 = e1->toElem(irs); - es2 = e2->toElem(irs); -#if 1 - es1 = addressElem(es1, t1); - es2 = addressElem(es2, t2); -#else - es1 = el_una(OPaddr, TYnptr, es1); - es2 = el_una(OPaddr, TYnptr, es2); -#endif - e = el_param(es1, es2); - ecount = el_long(TYint, t1->size()); - e = el_bin(OPmemcmp, TYint, e, ecount); - e = el_bin(eop, TYint, e, el_long(TYint, 0)); - el_setLoc(e,loc); - } -#if 0 - else if (t1->ty == Tclass && t2->ty == Tclass) - { - elem *ec1; - elem *ec2; - - ec1 = e1->toElem(irs); - ec2 = e2->toElem(irs); - e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2)); - } -#endif - else if ((t1->ty == Tarray || t1->ty == Tsarray) && - (t2->ty == Tarray || t2->ty == Tsarray)) - { - elem *ea1; - elem *ea2; - elem *ep; - Type *telement = t1->nextOf()->toBasetype(); - int rtlfunc; - - ea1 = e1->toElem(irs); - ea1 = array_toDarray(t1, ea1); - ea2 = e2->toElem(irs); - ea2 = array_toDarray(t2, ea2); - -#if 1 - ep = el_params(telement->arrayOf()->getInternalTypeInfo(NULL)->toElem(irs), - ea2, ea1, NULL); - rtlfunc = RTLSYM_ARRAYEQ2; -#else - ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL); - rtlfunc = RTLSYM_ARRAYEQ; -#endif - e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); - if (op == TOKnotequal) - e = el_bin(OPxor, TYint, e, el_long(TYint, 1)); - el_setLoc(e,loc); - } - else - e = toElemBin(irs, eop); - return e; -} - -elem *IdentityExp::toElem(IRState *irs) -{ - elem *e; - enum OPER eop; - Type *t1 = e1->type->toBasetype(); - Type *t2 = e2->type->toBasetype(); - - switch (op) - { - case TOKidentity: eop = OPeqeq; break; - case TOKnotidentity: eop = OPne; break; - default: - dump(0); - assert(0); - } - - //printf("IdentityExp::toElem() %s\n", toChars()); - - if (t1->ty == Tstruct) - { // Do bit compare of struct's - elem *es1; - elem *es2; - elem *ecount; - - es1 = e1->toElem(irs); - es1 = addressElem(es1, e1->type); - //es1 = el_una(OPaddr, TYnptr, es1); - es2 = e2->toElem(irs); - es2 = addressElem(es2, e2->type); - //es2 = el_una(OPaddr, TYnptr, es2); - e = el_param(es1, es2); - ecount = el_long(TYint, t1->size()); - e = el_bin(OPmemcmp, TYint, e, ecount); - e = el_bin(eop, TYint, e, el_long(TYint, 0)); - el_setLoc(e,loc); - } - else if ((t1->ty == Tarray || t1->ty == Tsarray) && - (t2->ty == Tarray || t2->ty == Tsarray)) - { - elem *ea1; - elem *ea2; - - ea1 = e1->toElem(irs); - ea1 = array_toDarray(t1, ea1); - ea2 = e2->toElem(irs); - ea2 = array_toDarray(t2, ea2); - - e = el_bin(eop, type->totym(), ea1, ea2); - el_setLoc(e,loc); - } - else - e = toElemBin(irs, eop); - - return e; -} - - -/*************************************** - */ - -elem *InExp::toElem(IRState *irs) -{ elem *e; - elem *key = e1->toElem(irs); - elem *aa = e2->toElem(irs); - elem *ep; - elem *keyti; - TypeAArray *taa = (TypeAArray *)e2->type->toBasetype(); - - - // set to: - // aaIn(aa, keyti, key); - - if (key->Ety == TYstruct) - { - key = el_una(OPstrpar, TYstruct, key); - key->Enumbytes = key->E1->Enumbytes; - assert(key->Enumbytes); - } - - Symbol *s = taa->aaGetSymbol("In", 0); - keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs); - ep = el_params(key, keyti, aa, NULL); - e = el_bin(OPcall, type->totym(), el_var(s), ep); - - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *RemoveExp::toElem(IRState *irs) -{ elem *e; - Type *tb = e1->type->toBasetype(); - assert(tb->ty == Taarray); - TypeAArray *taa = (TypeAArray *)tb; - elem *ea = e1->toElem(irs); - elem *ekey = e2->toElem(irs); - elem *ep; - elem *keyti; - - if (ekey->Ety == TYstruct) - { - ekey = el_una(OPstrpar, TYstruct, ekey); - ekey->Enumbytes = ekey->E1->Enumbytes; - assert(ekey->Enumbytes); - } - - Symbol *s = taa->aaGetSymbol("Del", 0); - keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs); - ep = el_params(ekey, keyti, ea, NULL); - e = el_bin(OPcall, TYnptr, el_var(s), ep); - - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *AssignExp::toElem(IRState *irs) -{ elem *e; - IndexExp *ae; - int r; - Type *t1b; - - //printf("AssignExp::toElem('%s')\n", toChars()); - t1b = e1->type->toBasetype(); - - // Look for array.length = n - if (e1->op == TOKarraylength) - { - // Generate: - // _d_arraysetlength(e2, sizeelem, &ale->e1); - - ArrayLengthExp *ale = (ArrayLengthExp *)e1; - elem *p1; - elem *p2; - elem *p3; - elem *ep; - Type *t1; - - p1 = e2->toElem(irs); - p3 = ale->e1->toElem(irs); - p3 = addressElem(p3, NULL); - t1 = ale->e1->type->toBasetype(); - -#if 1 - // call _d_arraysetlengthT(ti, e2, &ale->e1); - p2 = t1->getTypeInfo(NULL)->toElem(irs); - ep = el_params(p3, p1, p2, NULL); // c function - r = t1->nextOf()->isZeroInit() ? RTLSYM_ARRAYSETLENGTHT : RTLSYM_ARRAYSETLENGTHIT; -#else - if (t1->next->isZeroInit()) - { p2 = t1->getTypeInfo(NULL)->toElem(irs); - ep = el_params(p3, p1, p2, NULL); // c function - r = RTLSYM_ARRAYSETLENGTHT; - } - else - { - p2 = el_long(TYint, t1->next->size()); - ep = el_params(p3, p2, p1, NULL); // c function - Expression *init = t1->next->defaultInit(); - ep = el_param(el_long(TYint, init->type->size()), ep); - elem *ei = init->toElem(irs); - ep = el_param(ei, ep); - r = RTLSYM_ARRAYSETLENGTH3; - } -#endif - - e = el_bin(OPcall, type->totym(), el_var(rtlsym[r]), ep); - el_setLoc(e, loc); - return e; - } - - // Look for array[]=n - if (e1->op == TOKslice) - { - SliceExp *are = (SliceExp *)(e1); - Type *t1 = t1b; - Type *t2 = e2->type->toBasetype(); - - // which we do if the 'next' types match - if (ismemset) - { // Do a memset for array[]=v - //printf("Lpair %s\n", toChars()); - SliceExp *are = (SliceExp *)e1; - elem *elwr; - elem *eupr; - elem *n1; - elem *evalue; - elem *enbytes; - elem *elength; - elem *einit; - integer_t value; - Type *ta = are->e1->type->toBasetype(); - Type *tb = ta->nextOf()->toBasetype(); - int sz = tb->size(); - tym_t tym = type->totym(); - - n1 = are->e1->toElem(irs); - elwr = are->lwr ? are->lwr->toElem(irs) : NULL; - eupr = are->upr ? are->upr->toElem(irs) : NULL; - - elem *n1x = n1; - - // Look for array[]=n - if (ta->ty == Tsarray) - { - TypeSArray *ts; - - ts = (TypeSArray *) ta; - n1 = array_toPtr(ta, n1); - enbytes = ts->dim->toElem(irs); - n1x = n1; - n1 = el_same(&n1x); - einit = resolveLengthVar(are->lengthVar, &n1, ta); - } - else if (ta->ty == Tarray) - { - n1 = el_same(&n1x); - einit = resolveLengthVar(are->lengthVar, &n1, ta); - enbytes = el_copytree(n1); - n1 = array_toPtr(ta, n1); - enbytes = el_una(OP64_32, TYint, enbytes); - } - else if (ta->ty == Tpointer) - { - n1 = el_same(&n1x); - enbytes = el_long(TYint, -1); // largest possible index - einit = NULL; - } - - // Enforce order of evaluation of n1[elwr..eupr] as n1,elwr,eupr - elem *elwrx = elwr; - if (elwr) elwr = el_same(&elwrx); - elem *euprx = eupr; - if (eupr) eupr = el_same(&euprx); - -#if 0 - printf("sz = %d\n", sz); - printf("n1x\n"); - elem_print(n1x); - printf("einit\n"); - elem_print(einit); - printf("elwrx\n"); - elem_print(elwrx); - printf("euprx\n"); - elem_print(euprx); - printf("n1\n"); - elem_print(n1); - printf("elwr\n"); - elem_print(elwr); - printf("eupr\n"); - elem_print(eupr); - printf("enbytes\n"); - elem_print(enbytes); -#endif - einit = el_combine(n1x, einit); - einit = el_combine(einit, elwrx); - einit = el_combine(einit, euprx); - - evalue = this->e2->toElem(irs); - -#if 0 - printf("n1\n"); - elem_print(n1); - printf("enbytes\n"); - elem_print(enbytes); -#endif - - if (global.params.useArrayBounds && eupr && ta->ty != Tpointer) - { - elem *c1; - elem *c2; - elem *ea; - elem *eb; - elem *enbytesx; - - assert(elwr); - enbytesx = enbytes; - enbytes = el_same(&enbytesx); - c1 = el_bin(OPle, TYint, el_copytree(eupr), enbytesx); - c2 = el_bin(OPle, TYint, el_copytree(elwr), el_copytree(eupr)); - c1 = el_bin(OPandand, TYint, c1, c2); - - // Construct: (c1 || ModuleArray(line)) - Symbol *sassert; - - sassert = irs->blx->module->toModuleArray(); - ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum)); - eb = el_bin(OPoror,TYvoid,c1,ea); - einit = el_combine(einit, eb); - } - - if (elwr) - { elem *elwr2; - - el_free(enbytes); - elwr2 = el_copytree(elwr); - elwr2 = el_bin(OPmul, TYint, elwr2, el_long(TYint, sz)); - n1 = el_bin(OPadd, TYnptr, n1, elwr2); - enbytes = el_bin(OPmin, TYint, eupr, elwr); - elength = el_copytree(enbytes); - } - else - elength = el_copytree(enbytes); - e = setArray(n1, enbytes, tb, evalue, irs, op); - Lpair: - e = el_pair(TYullong, elength, e); - Lret2: - e = el_combine(einit, e); - //elem_print(e); - goto Lret; - } -#if 0 - else if (e2->op == TOKadd || e2->op == TOKmin) - { - /* It's ea[] = eb[] +- ec[] - */ - BinExp *e2a = (BinExp *)e2; - Type *t = e2->type->toBasetype()->nextOf()->toBasetype(); - if (t->ty != Tfloat32 && t->ty != Tfloat64 && t->ty != Tfloat80) - { - e2->error("array add/min for %s not supported", t->toChars()); - return el_long(TYint, 0); - } - elem *ea = e1->toElem(irs); - ea = array_toDarray(e1->type, ea); - elem *eb = e2a->e1->toElem(irs); - eb = array_toDarray(e2a->e1->type, eb); - elem *ec = e2a->e2->toElem(irs); - ec = array_toDarray(e2a->e2->type, ec); - - int rtl = RTLSYM_ARRAYASSADDFLOAT; - if (t->ty == Tfloat64) - rtl = RTLSYM_ARRAYASSADDDOUBLE; - else if (t->ty == Tfloat80) - rtl = RTLSYM_ARRAYASSADDREAL; - if (e2->op == TOKmin) - { - rtl = RTLSYM_ARRAYASSMINFLOAT; - if (t->ty == Tfloat64) - rtl = RTLSYM_ARRAYASSMINDOUBLE; - else if (t->ty == Tfloat80) - rtl = RTLSYM_ARRAYASSMINREAL; - } - - /* Set parameters so the order of evaluation is eb, ec, ea - */ - elem *ep = el_params(eb, ec, ea, NULL); - e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep); - goto Lret; - } -#endif - else - { - /* It's array1[]=array2[] - * which is a memcpy - */ - elem *eto; - elem *efrom; - elem *esize; - elem *ep; - - eto = e1->toElem(irs); - efrom = e2->toElem(irs); - - unsigned size = t1->nextOf()->size(); - esize = el_long(TYint, size); - - /* Determine if we need to do postblit - */ - int postblit = 0; - Type *t = t1; - do - t = t->nextOf()->toBasetype(); - while (t->ty == Tsarray); - if (t->ty == Tstruct) - { StructDeclaration *sd = ((TypeStruct *)t)->sym; - if (sd->postblit) - postblit = 1; - } - - assert(e2->type->ty != Tpointer); - - if (!postblit && !global.params.useArrayBounds) - { elem *epto; - elem *epfr; - elem *elen; - elem *ex; - - ex = el_same(&eto); - - // Determine if elen is a constant - if (eto->Eoper == OPpair && - eto->E1->Eoper == OPconst) - { - elen = el_copytree(eto->E1); - } - else - { - // It's not a constant, so pull it from the dynamic array - elen = el_una(OP64_32, TYint, el_copytree(ex)); - } - - esize = el_bin(OPmul, TYint, elen, esize); - epto = array_toPtr(e1->type, ex); - epfr = array_toPtr(e2->type, efrom); - e = el_bin(OPmemcpy, TYnptr, epto, el_param(epfr, esize)); - e = el_pair(eto->Ety, el_copytree(elen), e); - e = el_combine(eto, e); - } -#if DMDV2 - else if (postblit && op != TOKblit) - { - /* Generate: - * _d_arrayassign(ti, efrom, eto) - * or: - * _d_arrayctor(ti, efrom, eto) - */ - el_free(esize); - Expression *ti = t1->nextOf()->toBasetype()->getTypeInfo(NULL); - ep = el_params(eto, efrom, ti->toElem(irs), NULL); - int rtl = (op == TOKconstruct) ? RTLSYM_ARRAYCTOR : RTLSYM_ARRAYASSIGN; - e = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep); - } -#endif - else - { - // Generate: - // _d_arraycopy(eto, efrom, esize) - - ep = el_params(eto, efrom, esize, NULL); - e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCOPY]), ep); - } - el_setLoc(e, loc); - return e; - } - } - - if (e1->op == TOKindex) - { - elem *eb; - elem *ei; - elem *ev; - TY ty; - Type *ta; - - ae = (IndexExp *)(e1); - ta = ae->e1->type->toBasetype(); - ty = ta->ty; - } -#if 1 - /* This will work if we can distinguish an assignment from - * an initialization of the lvalue. It'll work if the latter. - * If the former, because of aliasing of the return value with - * function arguments, it'll fail. - */ - if (op == TOKconstruct && e2->op == TOKcall) - { CallExp *ce = (CallExp *)e2; - - TypeFunction *tf = (TypeFunction *)ce->e1->type->toBasetype(); - if (tf->ty == Tfunction && tf->retStyle() == RETstack) - { - elem *ehidden = e1->toElem(irs); - ehidden = el_una(OPaddr, TYnptr, ehidden); - assert(!irs->ehidden); - irs->ehidden = ehidden; - e = e2->toElem(irs); - goto Lret; - } - } -#endif - if (t1b->ty == Tstruct) - { - if (e2->op == TOKint64) - { /* Implement: - * (struct = 0) - * with: - * memset(&struct, 0, struct.sizeof) - */ - elem *el = e1->toElem(irs); - elem *enbytes = el_long(TYint, e1->type->size()); - elem *evalue = el_long(TYint, 0); - - el = el_una(OPaddr, TYnptr, el); - e = el_param(enbytes, evalue); - e = el_bin(OPmemset,TYnptr,el,e); - el_setLoc(e, loc); - //e = el_una(OPind, TYstruct, e); - } - else - { - elem *e1; - elem *e2; - tym_t tym; - - //printf("toElemBin() '%s'\n", toChars()); - - tym = type->totym(); - - e1 = this->e1->toElem(irs); - elem *ex = e1; - if (e1->Eoper == OPind) - ex = e1->E1; - if (this->e2->op == TOKstructliteral && - ex->Eoper == OPvar && ex->EV.sp.Voffset == 0) - { StructLiteralExp *se = (StructLiteralExp *)this->e2; - - Symbol *symSave = se->sym; - size_t soffsetSave = se->soffset; - int fillHolesSave = se->fillHoles; - - se->sym = ex->EV.sp.Vsym; - se->soffset = 0; - se->fillHoles = (op == TOKconstruct || op == TOKblit) ? 1 : 0; - - el_free(e1); - e = this->e2->toElem(irs); - - se->sym = symSave; - se->soffset = soffsetSave; - se->fillHoles = fillHolesSave; - } - else - { - e2 = this->e2->toElem(irs); - e = el_bin(OPstreq,tym,e1,e2); - e->Enumbytes = this->e1->type->size(); - } - goto Lret; - } - } - else - e = toElemBin(irs,OPeq); - return e; - - Lret: - el_setLoc(e,loc); - return e; -} - -/*************************************** - */ - -elem *AddAssignExp::toElem(IRState *irs) -{ - //printf("AddAssignExp::toElem() %s\n", toChars()); - elem *e; - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if ((tb1->ty == Tarray || tb1->ty == Tsarray) && - (tb2->ty == Tarray || tb2->ty == Tsarray) - ) - { - error("Array operations not implemented"); - } - else - e = toElemBin(irs,OPaddass); - return e; -} - - -/*************************************** - */ - -elem *MinAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPminass); -} - -/*************************************** - */ - -elem *CatAssignExp::toElem(IRState *irs) -{ - //printf("CatAssignExp::toElem('%s')\n", toChars()); - elem *e; - Type *tb1 = e1->type->toBasetype(); - Type *tb2 = e2->type->toBasetype(); - - if (tb1->ty == Tarray || tb2->ty == Tsarray) - { elem *e1; - elem *e2; - elem *ep; - - e1 = this->e1->toElem(irs); - e1 = el_una(OPaddr, TYnptr, e1); - - e2 = this->e2->toElem(irs); - if (e2->Ety == TYstruct) - { - e2 = el_una(OPstrpar, TYstruct, e2); - e2->Enumbytes = e2->E1->Enumbytes; - assert(e2->Enumbytes); - } - - Type *tb1n = tb1->nextOf()->toBasetype(); - if ((tb2->ty == Tarray || tb2->ty == Tsarray) && - tb1n->equals(tb2->nextOf()->toBasetype())) - { // Append array -#if 1 - ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep); -#else - ep = el_params(el_long(TYint, tb1n->size()), e2, e1, NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep); -#endif - } - else - { // Append element -#if 1 - ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep); -#else - ep = el_params(e2, el_long(TYint, tb1n->size()), e1, NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep); -#endif - } - el_setLoc(e,loc); - } - else - assert(0); - return e; -} - - -/*************************************** - */ - -elem *DivAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPdivass); -} - - -/*************************************** - */ - -elem *ModAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPmodass); -} - - -/*************************************** - */ - -elem *MulAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPmulass); -} - - -/*************************************** - */ - -elem *ShlAssignExp::toElem(IRState *irs) -{ elem *e; - - e = toElemBin(irs,OPshlass); - return e; -} - - -/*************************************** - */ - -elem *ShrAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPshrass); -} - - -/*************************************** - */ - -elem *UshrAssignExp::toElem(IRState *irs) -{ - elem *eleft = e1->toElem(irs); - eleft->Ety = touns(eleft->Ety); - elem *eright = e2->toElem(irs); - elem *e = el_bin(OPshrass, type->totym(), eleft, eright); - el_setLoc(e, loc); - return e; -} - - -/*************************************** - */ - -elem *AndAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPandass); -} - - -/*************************************** - */ - -elem *OrAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPorass); -} - - -/*************************************** - */ - -elem *XorAssignExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPxorass); -} - - -/*************************************** - */ - -elem *AndAndExp::toElem(IRState *irs) -{ - elem *e = toElemBin(irs,OPandand); - if (global.params.cov && e2->loc.linnum) - e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2); - return e; -} - - -/*************************************** - */ - -elem *OrOrExp::toElem(IRState *irs) -{ - elem *e = toElemBin(irs,OPoror); - if (global.params.cov && e2->loc.linnum) - e->E2 = el_combine(incUsageElem(irs, e2->loc), e->E2); - return e; -} - - -/*************************************** - */ - -elem *XorExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPxor); -} - - -/*************************************** - */ - -elem *AndExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPand); -} - - -/*************************************** - */ - -elem *OrExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPor); -} - - -/*************************************** - */ - -elem *ShlExp::toElem(IRState *irs) -{ - return toElemBin(irs, OPshl); -} - - -/*************************************** - */ - -elem *ShrExp::toElem(IRState *irs) -{ - return toElemBin(irs,OPshr); -} - - -/*************************************** - */ - -elem *UshrExp::toElem(IRState *irs) -{ - elem *eleft = e1->toElem(irs); - eleft->Ety = touns(eleft->Ety); - elem *eright = e2->toElem(irs); - elem *e = el_bin(OPshr, type->totym(), eleft, eright); - el_setLoc(e, loc); - return e; -} - -/**************************************** - */ - -elem *CommaExp::toElem(IRState *irs) -{ - assert(e1 && e2); - elem *eleft = e1->toElem(irs); - elem *eright = e2->toElem(irs); - elem *e = el_combine(eleft, eright); - if (e) - el_setLoc(e, loc); - return e; -} - - -/*************************************** - */ - -elem *CondExp::toElem(IRState *irs) -{ elem *eleft; - elem *eright; - - elem *ec = econd->toElem(irs); - - eleft = e1->toElem(irs); - tym_t ty = eleft->Ety; - if (global.params.cov && e1->loc.linnum) - eleft = el_combine(incUsageElem(irs, e1->loc), eleft); - - eright = e2->toElem(irs); - if (global.params.cov && e2->loc.linnum) - eright = el_combine(incUsageElem(irs, e2->loc), eright); - - elem *e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright)); - if (tybasic(ty) == TYstruct) - e->Enumbytes = e1->type->size(); - el_setLoc(e, loc); - return e; -} - - -/*************************************** - */ - -elem *TypeDotIdExp::toElem(IRState *irs) -{ - print(); - assert(0); - return NULL; -} - -elem *TypeExp::toElem(IRState *irs) -{ -#ifdef DEBUG - printf("TypeExp::toElem()\n"); -#endif - error("type %s is not an expression", toChars()); - return el_long(TYint, 0); -} - -elem *ScopeExp::toElem(IRState *irs) -{ - error("%s is not an expression", sds->toChars()); - return el_long(TYint, 0); -} - -elem *DotVarExp::toElem(IRState *irs) -{ - // *(&e + offset) - - //printf("DotVarExp::toElem('%s')\n", toChars()); - - VarDeclaration *v = var->isVarDeclaration(); - if (!v) - { - error("%s is not a field", var->toChars()); - } - - elem *e = e1->toElem(irs); - Type *tb1 = e1->type->toBasetype(); - if (tb1->ty != Tclass && tb1->ty != Tpointer) - e = el_una(OPaddr, TYnptr, e); - e = el_bin(OPadd, TYnptr, e, el_long(TYint, v ? v->offset : 0)); - e = el_una(OPind, type->totym(), e); - if (tybasic(e->Ety) == TYstruct) - { - e->Enumbytes = type->size(); - } - el_setLoc(e,loc); - return e; -} - -elem *DelegateExp::toElem(IRState *irs) -{ - elem *e; - elem *ethis; - elem *ep; - Symbol *sfunc; - int directcall = 0; - - //printf("DelegateExp::toElem() '%s'\n", toChars()); - sfunc = func->toSymbol(); - if (func->isNested()) - { - ep = el_ptr(sfunc); - ethis = getEthis(loc, irs, func); - } - else - { - ethis = e1->toElem(irs); - if (e1->type->ty != Tclass && e1->type->ty != Tpointer) - ethis = el_una(OPaddr, TYnptr, ethis); - - if (e1->op == TOKsuper) - directcall = 1; - - if (!func->isThis()) - error("delegates are only for non-static functions"); - - if (!func->isVirtual() || - directcall || - func->isFinal()) - { - ep = el_ptr(sfunc); - } - else - { - // Get pointer to function out of virtual table - unsigned vindex; - - assert(ethis); - ep = el_same(ðis); - ep = el_una(OPind, TYnptr, ep); - vindex = func->vtblIndex; - - // Build *(ep + vindex * 4) - ep = el_bin(OPadd,TYnptr,ep,el_long(TYint, vindex * 4)); - ep = el_una(OPind,TYnptr,ep); - } - -// if (func->tintro) -// func->error(loc, "cannot form delegate due to covariant return type"); - } - if (ethis->Eoper == OPcomma) - { - ethis->E2 = el_pair(TYullong, ethis->E2, ep); - ethis->Ety = TYullong; - e = ethis; - } - else - e = el_pair(TYullong, ethis, ep); - el_setLoc(e,loc); - return e; -} - -elem *DotTypeExp::toElem(IRState *irs) -{ - // Just a pass-thru to e1 - elem *e; - - //printf("DotTypeExp::toElem() %s\n", toChars()); - e = e1->toElem(irs); - el_setLoc(e,loc); - return e; -} - -elem *CallExp::toElem(IRState *irs) -{ - //printf("CallExp::toElem('%s')\n", toChars()); - assert(e1->type); - elem *ec; - int directcall; - FuncDeclaration *fd; - Type *t1 = e1->type->toBasetype(); - Type *ectype = t1; - - elem *ehidden = irs->ehidden; - irs->ehidden = NULL; - - directcall = 0; - fd = NULL; - if (e1->op == TOKdotvar && t1->ty != Tdelegate) - { DotVarExp *dve = (DotVarExp *)e1; - - fd = dve->var->isFuncDeclaration(); - Expression *ex = dve->e1; - while (1) - { - switch (ex->op) - { - case TOKsuper: // super.member() calls directly - case TOKdottype: // type.member() calls directly - directcall = 1; - break; - - case TOKcast: - ex = ((CastExp *)ex)->e1; - continue; - - default: - //ex->dump(0); - break; - } - break; - } - ec = dve->e1->toElem(irs); - ectype = dve->e1->type->toBasetype(); - } - else if (e1->op == TOKvar) - { - fd = ((VarExp *)e1)->var->isFuncDeclaration(); - - if (fd && fd->ident == Id::alloca && - !fd->fbody && fd->linkage == LINKc && - arguments && arguments->dim == 1) - { Expression *arg = (Expression *)arguments->data[0]; - arg = arg->optimize(WANTvalue); - if (arg->isConst() && arg->type->isintegral()) - { integer_t sz = arg->toInteger(); - if (sz > 0 && sz < 0x40000) - { - // It's an alloca(sz) of a fixed amount. - // Replace with an array allocated on the stack - // of the same size: char[sz] tmp; - - Symbol *stmp; - ::type *t; - - assert(!ehidden); - t = type_allocn(TYarray, tschar); - t->Tdim = sz; - stmp = symbol_genauto(t); - ec = el_ptr(stmp); - el_setLoc(ec,loc); - return ec; - } - } - } - - ec = e1->toElem(irs); - } - else - { - ec = e1->toElem(irs); - } - ec = callfunc(loc, irs, directcall, type, ec, ectype, fd, t1, ehidden, arguments); - el_setLoc(ec,loc); - return ec; -} - -elem *AddrExp::toElem(IRState *irs) -{ elem *e; - elem **pe; - - //printf("AddrExp::toElem('%s')\n", toChars()); - - e = e1->toElem(irs); - e = addressElem(e, e1->type); -L2: - e->Ety = type->totym(); - el_setLoc(e,loc); - return e; -} - -elem *PtrExp::toElem(IRState *irs) -{ elem *e; - - //printf("PtrExp::toElem() %s\n", toChars()); - e = e1->toElem(irs); - e = el_una(OPind,type->totym(),e); - if (tybasic(e->Ety) == TYstruct) - { - e->Enumbytes = type->size(); - } - el_setLoc(e,loc); - return e; -} - -elem *BoolExp::toElem(IRState *irs) -{ elem *e1; - - e1 = this->e1->toElem(irs); - return el_una(OPbool,type->totym(),e1); -} - -elem *DeleteExp::toElem(IRState *irs) -{ elem *e; - int rtl; - Type *tb; - - //printf("DeleteExp::toElem()\n"); - if (e1->op == TOKindex) - { - IndexExp *ae = (IndexExp *)(e1); - tb = ae->e1->type->toBasetype(); - if (tb->ty == Taarray) - { - TypeAArray *taa = (TypeAArray *)tb; - elem *ea = ae->e1->toElem(irs); - elem *ekey = ae->e2->toElem(irs); - elem *ep; - elem *keyti; - - if (ekey->Ety == TYstruct) - { - ekey = el_una(OPstrpar, TYstruct, ekey); - ekey->Enumbytes = ekey->E1->Enumbytes; - assert(ekey->Enumbytes); - } - - Symbol *s = taa->aaGetSymbol("Del", 0); - keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs); - ep = el_params(ekey, keyti, ea, NULL); - e = el_bin(OPcall, TYnptr, el_var(s), ep); - goto Lret; - } - } - //e1->type->print(); - e = e1->toElem(irs); - tb = e1->type->toBasetype(); - switch (tb->ty) - { - case Tarray: - { e = addressElem(e, e1->type); - rtl = RTLSYM_DELARRAYT; - - /* See if we need to run destructors on the array contents - */ - elem *et = NULL; - Type *tv = tb->nextOf()->toBasetype(); - while (tv->ty == Tsarray) - { TypeSArray *ta = (TypeSArray *)tv; - tv = tv->nextOf()->toBasetype(); - } - if (tv->ty == Tstruct) - { TypeStruct *ts = (TypeStruct *)tv; - StructDeclaration *sd = ts->sym; - if (sd->dtor) - et = tb->nextOf()->getTypeInfo(NULL)->toElem(irs); - } - if (!et) // if no destructors needed - et = el_long(TYnptr, 0); // pass null for TypeInfo - e = el_params(et, e, NULL); - // call _d_delarray_t(e, et); - e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e); - goto Lret; - } - case Tclass: - if (e1->op == TOKvar) - { VarExp *ve = (VarExp *)e1; - if (ve->var->isVarDeclaration() && - ve->var->isVarDeclaration()->onstack) - { - rtl = RTLSYM_CALLFINALIZER; - if (tb->isClassHandle()->isInterfaceDeclaration()) - rtl = RTLSYM_CALLINTERFACEFINALIZER; - break; - } - } - e = addressElem(e, e1->type); - rtl = RTLSYM_DELCLASS; - if (tb->isClassHandle()->isInterfaceDeclaration()) - rtl = RTLSYM_DELINTERFACE; - break; - - case Tpointer: - e = addressElem(e, e1->type); - rtl = RTLSYM_DELMEMORY; - break; - - default: - assert(0); - break; - } - e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e); - - Lret: - el_setLoc(e,loc); - return e; -} - -elem *CastExp::toElem(IRState *irs) -{ elem *e; - TY fty; - TY tty; - tym_t ftym; - tym_t ttym; - enum OPER eop; - Type *t; - Type *tfrom; - -#if 0 - printf("CastExp::toElem()\n"); - print(); - printf("\tfrom: %s\n", e1->type->toChars()); - printf("\tto : %s\n", to->toChars()); -#endif - - e = e1->toElem(irs); - tfrom = e1->type->toBasetype(); - t = to->toBasetype(); // skip over typedef's - if (t->equals(tfrom)) - goto Lret; - - fty = tfrom->ty; - //printf("fty = %d\n", fty); - tty = t->ty; - - if (tty == Tpointer && fty == Tarray -#if 0 - && (t->next->ty == Tvoid || t->next->equals(e1->type->next)) -#endif - ) - { - if (e->Eoper == OPvar) - { - // e1 -> *(&e1 + 4) - e = el_una(OPaddr, TYnptr, e); - e = el_bin(OPadd, TYnptr, e, el_long(TYint, 4)); - e = el_una(OPind,t->totym(),e); - } - else - { - // e1 -> (unsigned)(e1 >> 32) - e = el_bin(OPshr, TYullong, e, el_long(TYint, 32)); - e = el_una(OP64_32, t->totym(), e); - } - goto Lret; - } - - if (tty == Tpointer && fty == Tsarray -#if 0 - && (t->next->ty == Tvoid || t->next->equals(e1->type->next)) -#endif - ) - { - // e1 -> &e1 - e = el_una(OPaddr, TYnptr, e); - goto Lret; - } - - // Convert from static array to dynamic array - if (tty == Tarray && fty == Tsarray) - { - e = sarray_toDarray(loc, tfrom, t, e); - goto Lret; - } - - // Convert from dynamic array to dynamic array - if (tty == Tarray && fty == Tarray) - { - unsigned fsize = tfrom->nextOf()->size(); - unsigned tsize = t->nextOf()->size(); - - if (fsize != tsize) - { - elem *ep; - - ep = el_params(e, el_long(TYint, fsize), el_long(TYint, tsize), NULL); - e = el_bin(OPcall, type->totym(), el_var(rtlsym[RTLSYM_ARRAYCAST]), ep); - } - goto Lret; - } - - // Casting from base class to derived class requires a runtime check - if (fty == Tclass && tty == Tclass) - { - // Casting from derived class to base class is a no-op - ClassDeclaration *cdfrom; - ClassDeclaration *cdto; - int offset; - int rtl = RTLSYM_DYNAMIC_CAST; - - cdfrom = e1->type->isClassHandle(); - cdto = t->isClassHandle(); - if (cdfrom->isInterfaceDeclaration()) - { - rtl = RTLSYM_INTERFACE_CAST; - if (cdfrom->isCPPinterface()) - { - if (cdto->isCPPinterface()) - { - /* Casting from a C++ interface to a C++ interface - * is always a 'paint' operation - */ - goto Lret; // no-op - } - - /* Casting from a C++ interface to a class - * always results in null because there is no runtime - * information available to do it. - * - * Casting from a C++ interface to a non-C++ interface - * always results in null because there's no way one - * can be derived from the other. - */ - e = el_bin(OPcomma, TYnptr, e, el_long(TYnptr, 0)); - goto Lret; - } - } - if (cdto->isBaseOf(cdfrom, &offset) && offset != OFFSET_RUNTIME) - { - /* The offset from cdfrom=>cdto is known at compile time. - */ - - //printf("offset = %d\n", offset); - if (offset) - { /* Rewrite cast as (e ? e + offset : null) - */ - elem *etmp; - elem *ex; - - if (e1->op == TOKthis) - { // Assume 'this' is never null, so skip null check - e = el_bin(OPadd, TYnptr, e, el_long(TYint, offset)); - } - else - { - etmp = el_same(&e); - ex = el_bin(OPadd, TYnptr, etmp, el_long(TYint, offset)); - ex = el_bin(OPcolon, TYnptr, ex, el_long(TYnptr, 0)); - e = el_bin(OPcond, TYnptr, e, ex); - } - } - goto Lret; // no-op - } - - /* The offset from cdfrom=>cdto can only be determined at runtime. - */ - elem *ep; - - ep = el_param(el_ptr(cdto->toSymbol()), e); - e = el_bin(OPcall, TYnptr, el_var(rtlsym[rtl]), ep); - goto Lret; - } - - ftym = e->Ety; - ttym = t->totym(); - if (ftym == ttym) - goto Lret; - - switch (tty) - { - case Tpointer: - if (fty == Tdelegate) - goto Lpaint; - tty = Tuns32; - break; - - case Tchar: tty = Tuns8; break; - case Twchar: tty = Tuns16; break; - case Tdchar: tty = Tuns32; break; - case Tvoid: goto Lpaint; - - case Tbool: - { - // Construct e?true:false - elem *eq; - - e = el_una(OPbool, ttym, e); - goto Lret; - } - } - - switch (fty) - { - case Tpointer: fty = Tuns32; break; - case Tchar: fty = Tuns8; break; - case Twchar: fty = Tuns16; break; - case Tdchar: fty = Tuns32; break; - } - - #define X(fty, tty) ((fty) * TMAX + (tty)) -Lagain: - switch (X(fty,tty)) - { -#if 0 - case X(Tbit,Tint8): - case X(Tbit,Tuns8): - goto Lpaint; - case X(Tbit,Tint16): - case X(Tbit,Tuns16): - case X(Tbit,Tint32): - case X(Tbit,Tuns32): eop = OPu8_16; goto Leop; - case X(Tbit,Tint64): - case X(Tbit,Tuns64): - case X(Tbit,Tfloat32): - case X(Tbit,Tfloat64): - case X(Tbit,Tfloat80): - case X(Tbit,Tcomplex32): - case X(Tbit,Tcomplex64): - case X(Tbit,Tcomplex80): - e = el_una(OPu8_16, TYuint, e); - fty = Tuns32; - goto Lagain; - case X(Tbit,Timaginary32): - case X(Tbit,Timaginary64): - case X(Tbit,Timaginary80): goto Lzero; -#endif - /* ============================= */ - - case X(Tbool,Tint8): - case X(Tbool,Tuns8): - goto Lpaint; - case X(Tbool,Tint16): - case X(Tbool,Tuns16): - case X(Tbool,Tint32): - case X(Tbool,Tuns32): eop = OPu8_16; goto Leop; - case X(Tbool,Tint64): - case X(Tbool,Tuns64): - case X(Tbool,Tfloat32): - case X(Tbool,Tfloat64): - case X(Tbool,Tfloat80): - case X(Tbool,Tcomplex32): - case X(Tbool,Tcomplex64): - case X(Tbool,Tcomplex80): - e = el_una(OPu8_16, TYuint, e); - fty = Tuns32; - goto Lagain; - case X(Tbool,Timaginary32): - case X(Tbool,Timaginary64): - case X(Tbool,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tint8,Tuns8): goto Lpaint; - case X(Tint8,Tint16): - case X(Tint8,Tuns16): - case X(Tint8,Tint32): - case X(Tint8,Tuns32): eop = OPs8_16; goto Leop; - case X(Tint8,Tint64): - case X(Tint8,Tuns64): - case X(Tint8,Tfloat32): - case X(Tint8,Tfloat64): - case X(Tint8,Tfloat80): - case X(Tint8,Tcomplex32): - case X(Tint8,Tcomplex64): - case X(Tint8,Tcomplex80): - e = el_una(OPs8_16, TYint, e); - fty = Tint32; - goto Lagain; - case X(Tint8,Timaginary32): - case X(Tint8,Timaginary64): - case X(Tint8,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tuns8,Tint8): goto Lpaint; - case X(Tuns8,Tint16): - case X(Tuns8,Tuns16): - case X(Tuns8,Tint32): - case X(Tuns8,Tuns32): eop = OPu8_16; goto Leop; - case X(Tuns8,Tint64): - case X(Tuns8,Tuns64): - case X(Tuns8,Tfloat32): - case X(Tuns8,Tfloat64): - case X(Tuns8,Tfloat80): - case X(Tuns8,Tcomplex32): - case X(Tuns8,Tcomplex64): - case X(Tuns8,Tcomplex80): - e = el_una(OPu8_16, TYuint, e); - fty = Tuns32; - goto Lagain; - case X(Tuns8,Timaginary32): - case X(Tuns8,Timaginary64): - case X(Tuns8,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tint16,Tint8): - case X(Tint16,Tuns8): eop = OP16_8; goto Leop; - case X(Tint16,Tuns16): goto Lpaint; - case X(Tint16,Tint32): - case X(Tint16,Tuns32): eop = OPs16_32; goto Leop; - case X(Tint16,Tint64): - case X(Tint16,Tuns64): e = el_una(OPs16_32, TYint, e); - fty = Tint32; - goto Lagain; - case X(Tint16,Tfloat32): - case X(Tint16,Tfloat64): - case X(Tint16,Tfloat80): - case X(Tint16,Tcomplex32): - case X(Tint16,Tcomplex64): - case X(Tint16,Tcomplex80): - e = el_una(OPs16_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tint16,Timaginary32): - case X(Tint16,Timaginary64): - case X(Tint16,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tuns16,Tint8): - case X(Tuns16,Tuns8): eop = OP16_8; goto Leop; - case X(Tuns16,Tint16): goto Lpaint; - case X(Tuns16,Tint32): - case X(Tuns16,Tuns32): eop = OPu16_32; goto Leop; - case X(Tuns16,Tint64): - case X(Tuns16,Tuns64): - case X(Tuns16,Tfloat64): - case X(Tuns16,Tfloat32): - case X(Tuns16,Tfloat80): - case X(Tuns16,Tcomplex32): - case X(Tuns16,Tcomplex64): - case X(Tuns16,Tcomplex80): - e = el_una(OPu16_32, TYuint, e); - fty = Tuns32; - goto Lagain; - case X(Tuns16,Timaginary32): - case X(Tuns16,Timaginary64): - case X(Tuns16,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tint32,Tint8): - case X(Tint32,Tuns8): e = el_una(OP32_16, TYshort, e); - fty = Tint16; - goto Lagain; - case X(Tint32,Tint16): - case X(Tint32,Tuns16): eop = OP32_16; goto Leop; - case X(Tint32,Tuns32): goto Lpaint; - case X(Tint32,Tint64): - case X(Tint32,Tuns64): eop = OPs32_64; goto Leop; - case X(Tint32,Tfloat32): - case X(Tint32,Tfloat64): - case X(Tint32,Tfloat80): - case X(Tint32,Tcomplex32): - case X(Tint32,Tcomplex64): - case X(Tint32,Tcomplex80): - e = el_una(OPs32_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tint32,Timaginary32): - case X(Tint32,Timaginary64): - case X(Tint32,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tuns32,Tint8): - case X(Tuns32,Tuns8): e = el_una(OP32_16, TYshort, e); - fty = Tuns16; - goto Lagain; - case X(Tuns32,Tint16): - case X(Tuns32,Tuns16): eop = OP32_16; goto Leop; - case X(Tuns32,Tint32): goto Lpaint; - case X(Tuns32,Tint64): - case X(Tuns32,Tuns64): eop = OPu32_64; goto Leop; - case X(Tuns32,Tfloat32): - case X(Tuns32,Tfloat64): - case X(Tuns32,Tfloat80): - case X(Tuns32,Tcomplex32): - case X(Tuns32,Tcomplex64): - case X(Tuns32,Tcomplex80): - e = el_una(OPu32_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tuns32,Timaginary32): - case X(Tuns32,Timaginary64): - case X(Tuns32,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tint64,Tint8): - case X(Tint64,Tuns8): - case X(Tint64,Tint16): - case X(Tint64,Tuns16): e = el_una(OP64_32, TYint, e); - fty = Tint32; - goto Lagain; - case X(Tint64,Tint32): - case X(Tint64,Tuns32): eop = OP64_32; goto Leop; - case X(Tint64,Tuns64): goto Lpaint; - case X(Tint64,Tfloat32): - case X(Tint64,Tfloat64): - case X(Tint64,Tfloat80): - case X(Tint64,Tcomplex32): - case X(Tint64,Tcomplex64): - case X(Tint64,Tcomplex80): - e = el_una(OPs64_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tint64,Timaginary32): - case X(Tint64,Timaginary64): - case X(Tint64,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tuns64,Tint8): - case X(Tuns64,Tuns8): - case X(Tuns64,Tint16): - case X(Tuns64,Tuns16): e = el_una(OP64_32, TYint, e); - fty = Tint32; - goto Lagain; - case X(Tuns64,Tint32): - case X(Tuns64,Tuns32): eop = OP64_32; goto Leop; - case X(Tuns64,Tint64): goto Lpaint; - case X(Tuns64,Tfloat32): - case X(Tuns64,Tfloat64): - case X(Tuns64,Tfloat80): - case X(Tuns64,Tcomplex32): - case X(Tuns64,Tcomplex64): - case X(Tuns64,Tcomplex80): - e = el_una(OPu64_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tuns64,Timaginary32): - case X(Tuns64,Timaginary64): - case X(Tuns64,Timaginary80): goto Lzero; - - /* ============================= */ - - case X(Tfloat32,Tint8): - case X(Tfloat32,Tuns8): - case X(Tfloat32,Tint16): - case X(Tfloat32,Tuns16): - case X(Tfloat32,Tint32): - case X(Tfloat32,Tuns32): - case X(Tfloat32,Tint64): - case X(Tfloat32,Tuns64): - case X(Tfloat32,Tfloat80): e = el_una(OPf_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tfloat32,Tfloat64): eop = OPf_d; goto Leop; - case X(Tfloat32,Timaginary32): goto Lzero; - case X(Tfloat32,Timaginary64): goto Lzero; - case X(Tfloat32,Timaginary80): goto Lzero; - case X(Tfloat32,Tcomplex32): - case X(Tfloat32,Tcomplex64): - case X(Tfloat32,Tcomplex80): - e = el_bin(OPadd,TYcfloat,el_long(TYifloat,0),e); - fty = Tcomplex32; - goto Lagain; - - /* ============================= */ - - case X(Tfloat64,Tint8): - case X(Tfloat64,Tuns8): e = el_una(OPd_s16, TYshort, e); - fty = Tint16; - goto Lagain; - case X(Tfloat64,Tint16): eop = OPd_s16; goto Leop; - case X(Tfloat64,Tuns16): eop = OPd_u16; goto Leop; - case X(Tfloat64,Tint32): eop = OPd_s32; goto Leop; - case X(Tfloat64,Tuns32): eop = OPd_u32; goto Leop; - case X(Tfloat64,Tint64): eop = OPd_s64; goto Leop; - case X(Tfloat64,Tuns64): eop = OPd_u64; goto Leop; - case X(Tfloat64,Tfloat32): eop = OPd_f; goto Leop; - case X(Tfloat64,Tfloat80): eop = OPd_ld; goto Leop; - case X(Tfloat64,Timaginary32): goto Lzero; - case X(Tfloat64,Timaginary64): goto Lzero; - case X(Tfloat64,Timaginary80): goto Lzero; - case X(Tfloat64,Tcomplex32): - case X(Tfloat64,Tcomplex64): - case X(Tfloat64,Tcomplex80): - e = el_bin(OPadd,TYcfloat,el_long(TYidouble,0),e); - fty = Tcomplex64; - goto Lagain; - - /* ============================= */ - - case X(Tfloat80,Tint8): - case X(Tfloat80,Tuns8): - case X(Tfloat80,Tint16): - case X(Tfloat80,Tuns16): - case X(Tfloat80,Tint32): - case X(Tfloat80,Tuns32): - case X(Tfloat80,Tint64): - case X(Tfloat80,Tuns64): - case X(Tfloat80,Tfloat32): e = el_una(OPld_d, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tfloat80,Tfloat64): eop = OPld_d; goto Leop; - case X(Tfloat80,Timaginary32): goto Lzero; - case X(Tfloat80,Timaginary64): goto Lzero; - case X(Tfloat80,Timaginary80): goto Lzero; - case X(Tfloat80,Tcomplex32): - case X(Tfloat80,Tcomplex64): - case X(Tfloat80,Tcomplex80): - e = el_bin(OPadd,TYcldouble,e,el_long(TYildouble,0)); - fty = Tcomplex80; - goto Lagain; - - /* ============================= */ - - case X(Timaginary32,Tint8): - case X(Timaginary32,Tuns8): - case X(Timaginary32,Tint16): - case X(Timaginary32,Tuns16): - case X(Timaginary32,Tint32): - case X(Timaginary32,Tuns32): - case X(Timaginary32,Tint64): - case X(Timaginary32,Tuns64): - case X(Timaginary32,Tfloat32): - case X(Timaginary32,Tfloat64): - case X(Timaginary32,Tfloat80): goto Lzero; - case X(Timaginary32,Timaginary64): eop = OPf_d; goto Leop; - case X(Timaginary32,Timaginary80): - e = el_una(OPf_d, TYidouble, e); - fty = Timaginary64; - goto Lagain; - case X(Timaginary32,Tcomplex32): - case X(Timaginary32,Tcomplex64): - case X(Timaginary32,Tcomplex80): - e = el_bin(OPadd,TYcfloat,el_long(TYfloat,0),e); - fty = Tcomplex32; - goto Lagain; - - /* ============================= */ - - case X(Timaginary64,Tint8): - case X(Timaginary64,Tuns8): - case X(Timaginary64,Tint16): - case X(Timaginary64,Tuns16): - case X(Timaginary64,Tint32): - case X(Timaginary64,Tuns32): - case X(Timaginary64,Tint64): - case X(Timaginary64,Tuns64): - case X(Timaginary64,Tfloat32): - case X(Timaginary64,Tfloat64): - case X(Timaginary64,Tfloat80): goto Lzero; - case X(Timaginary64,Timaginary32): eop = OPd_f; goto Leop; - case X(Timaginary64,Timaginary80): eop = OPd_ld; goto Leop; - case X(Timaginary64,Tcomplex32): - case X(Timaginary64,Tcomplex64): - case X(Timaginary64,Tcomplex80): - e = el_bin(OPadd,TYcdouble,el_long(TYdouble,0),e); - fty = Tcomplex64; - goto Lagain; - - /* ============================= */ - - case X(Timaginary80,Tint8): - case X(Timaginary80,Tuns8): - case X(Timaginary80,Tint16): - case X(Timaginary80,Tuns16): - case X(Timaginary80,Tint32): - case X(Timaginary80,Tuns32): - case X(Timaginary80,Tint64): - case X(Timaginary80,Tuns64): - case X(Timaginary80,Tfloat32): - case X(Timaginary80,Tfloat64): - case X(Timaginary80,Tfloat80): goto Lzero; - case X(Timaginary80,Timaginary32): e = el_una(OPf_d, TYidouble, e); - fty = Timaginary64; - goto Lagain; - case X(Timaginary80,Timaginary64): eop = OPld_d; goto Leop; - case X(Timaginary80,Tcomplex32): - case X(Timaginary80,Tcomplex64): - case X(Timaginary80,Tcomplex80): - e = el_bin(OPadd,TYcldouble,el_long(TYldouble,0),e); - fty = Tcomplex80; - goto Lagain; - - /* ============================= */ - - case X(Tcomplex32,Tint8): - case X(Tcomplex32,Tuns8): - case X(Tcomplex32,Tint16): - case X(Tcomplex32,Tuns16): - case X(Tcomplex32,Tint32): - case X(Tcomplex32,Tuns32): - case X(Tcomplex32,Tint64): - case X(Tcomplex32,Tuns64): - case X(Tcomplex32,Tfloat32): - case X(Tcomplex32,Tfloat64): - case X(Tcomplex32,Tfloat80): - e = el_una(OPc_r, TYfloat, e); - fty = Tfloat32; - goto Lagain; - case X(Tcomplex32,Timaginary32): - case X(Tcomplex32,Timaginary64): - case X(Tcomplex32,Timaginary80): - e = el_una(OPc_i, TYifloat, e); - fty = Timaginary32; - goto Lagain; - case X(Tcomplex32,Tcomplex64): - case X(Tcomplex32,Tcomplex80): - e = el_una(OPf_d, TYcdouble, e); - fty = Tcomplex64; - goto Lagain; - - /* ============================= */ - - case X(Tcomplex64,Tint8): - case X(Tcomplex64,Tuns8): - case X(Tcomplex64,Tint16): - case X(Tcomplex64,Tuns16): - case X(Tcomplex64,Tint32): - case X(Tcomplex64,Tuns32): - case X(Tcomplex64,Tint64): - case X(Tcomplex64,Tuns64): - case X(Tcomplex64,Tfloat32): - case X(Tcomplex64,Tfloat64): - case X(Tcomplex64,Tfloat80): - e = el_una(OPc_r, TYdouble, e); - fty = Tfloat64; - goto Lagain; - case X(Tcomplex64,Timaginary32): - case X(Tcomplex64,Timaginary64): - case X(Tcomplex64,Timaginary80): - e = el_una(OPc_i, TYidouble, e); - fty = Timaginary64; - goto Lagain; - case X(Tcomplex64,Tcomplex32): eop = OPd_f; goto Leop; - case X(Tcomplex64,Tcomplex80): eop = OPd_ld; goto Leop; - - /* ============================= */ - - case X(Tcomplex80,Tint8): - case X(Tcomplex80,Tuns8): - case X(Tcomplex80,Tint16): - case X(Tcomplex80,Tuns16): - case X(Tcomplex80,Tint32): - case X(Tcomplex80,Tuns32): - case X(Tcomplex80,Tint64): - case X(Tcomplex80,Tuns64): - case X(Tcomplex80,Tfloat32): - case X(Tcomplex80,Tfloat64): - case X(Tcomplex80,Tfloat80): - e = el_una(OPc_r, TYldouble, e); - fty = Tfloat80; - goto Lagain; - case X(Tcomplex80,Timaginary32): - case X(Tcomplex80,Timaginary64): - case X(Tcomplex80,Timaginary80): - e = el_una(OPc_i, TYildouble, e); - fty = Timaginary80; - goto Lagain; - case X(Tcomplex80,Tcomplex32): - case X(Tcomplex80,Tcomplex64): - e = el_una(OPld_d, TYcdouble, e); - fty = Tcomplex64; - goto Lagain; - - /* ============================= */ - - default: - if (fty == tty) - goto Lpaint; - //dump(0); - //printf("fty = %d, tty = %d\n", fty, tty); - error("e2ir: cannot cast from %s to %s", e1->type->toChars(), t->toChars()); - goto Lzero; - - Lzero: - e = el_long(ttym, 0); - break; - - Lpaint: - e->Ety = ttym; - break; - - Leop: - e = el_una(eop, ttym, e); - break; - } -Lret: - // Adjust for any type paints - t = type->toBasetype(); - e->Ety = t->totym(); - - el_setLoc(e,loc); - return e; -} - -elem *ArrayLengthExp::toElem(IRState *irs) -{ - elem *e = e1->toElem(irs); - e = el_una(OP64_32, type->totym(), e); - el_setLoc(e,loc); - return e; -} - -elem *SliceExp::toElem(IRState *irs) -{ elem *e; - Type *t1; - - //printf("SliceExp::toElem()\n"); - t1 = e1->type->toBasetype(); - e = e1->toElem(irs); - if (lwr) - { elem *elwr; - elem *elwr2; - elem *eupr; - elem *eptr; - elem *einit; - int sz; - - einit = resolveLengthVar(lengthVar, &e, t1); - - sz = t1->nextOf()->size(); - - elwr = lwr->toElem(irs); - eupr = upr->toElem(irs); - - elwr2 = el_same(&elwr); - - // Create an array reference where: - // length is (upr - lwr) - // pointer is (ptr + lwr*sz) - // Combine as (length pair ptr) - - if (global.params.useArrayBounds) - { - // Checks (unsigned compares): - // upr <= array.length - // lwr <= upr - - elem *c1; - elem *c2; - elem *ea; - elem *eb; - elem *eupr2; - elem *elength; - - if (t1->ty == Tpointer) - { - // Just do lwr <= upr check - - eupr2 = el_same(&eupr); - eupr2->Ety = TYuint; // make sure unsigned comparison - c1 = el_bin(OPle, TYint, elwr2, eupr2); - c1 = el_combine(eupr, c1); - goto L2; - } - else if (t1->ty == Tsarray) - { TypeSArray *tsa = (TypeSArray *)t1; - integer_t length = tsa->dim->toInteger(); - - elength = el_long(TYuint, length); - goto L1; - } - else if (t1->ty == Tarray) - { - if (lengthVar) - elength = el_var(lengthVar->toSymbol()); - else - { - elength = e; - e = el_same(&elength); - elength = el_una(OP64_32, TYuint, elength); - } - L1: - eupr2 = el_same(&eupr); - c1 = el_bin(OPle, TYint, eupr, elength); - eupr2->Ety = TYuint; // make sure unsigned comparison - c2 = el_bin(OPle, TYint, elwr2, eupr2); - c1 = el_bin(OPandand, TYint, c1, c2); // (c1 && c2) - - L2: - // Construct: (c1 || ModuleArray(line)) - Symbol *sassert; - - sassert = irs->blx->module->toModuleArray(); - ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum)); - eb = el_bin(OPoror,TYvoid,c1,ea); - elwr = el_combine(elwr, eb); - - elwr2 = el_copytree(elwr2); - eupr = el_copytree(eupr2); - } - } - - eptr = array_toPtr(e1->type, e); - - elem *elength = el_bin(OPmin, TYint, eupr, elwr2); - eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz))); - - e = el_pair(TYullong, elength, eptr); - e = el_combine(elwr, e); - e = el_combine(einit, e); - } - else if (t1->ty == Tsarray) - { - e = sarray_toDarray(loc, t1, NULL, e); - } - el_setLoc(e,loc); - return e; -} - -elem *IndexExp::toElem(IRState *irs) -{ elem *e; - elem *n1 = e1->toElem(irs); - elem *n2; - elem *eb = NULL; - Type *t1; - - //printf("IndexExp::toElem() %s\n", toChars()); - t1 = e1->type->toBasetype(); - if (t1->ty == Taarray) - { - // set to: - // *aaGet(aa, keyti, valuesize, index); - - TypeAArray *taa = (TypeAArray *)t1; - elem *keyti; - elem *ep; - int vsize = taa->next->size(); - elem *valuesize; - Symbol *s; - - // n2 becomes the index, also known as the key - n2 = e2->toElem(irs); - if (n2->Ety == TYstruct || n2->Ety == TYarray) - { - n2 = el_una(OPstrpar, TYstruct, n2); - n2->Enumbytes = n2->E1->Enumbytes; - //printf("numbytes = %d\n", n2->Enumbytes); - assert(n2->Enumbytes); - } - valuesize = el_long(TYuint, vsize); // BUG: should be TYsize_t - //printf("valuesize: "); elem_print(valuesize); - if (modifiable) - { - n1 = el_una(OPaddr, TYnptr, n1); - s = taa->aaGetSymbol("Get", 1); - } - else - { - s = taa->aaGetSymbol("GetRvalue", 1); - } - //printf("taa->index = %s\n", taa->index->toChars()); - keyti = taa->index->getInternalTypeInfo(NULL)->toElem(irs); - //keyti = taa->index->getTypeInfo(NULL)->toElem(irs); - //printf("keyti:\n"); - //elem_print(keyti); - ep = el_params(n2, valuesize, keyti, n1, NULL); - e = el_bin(OPcall, TYnptr, el_var(s), ep); - if (global.params.useArrayBounds) - { - elem *n; - elem *ea; - - n = el_same(&e); - - // Construct: ((e || ModuleAssert(line)),n) - Symbol *sassert; - - sassert = irs->blx->module->toModuleArray(); - ea = el_bin(OPcall,TYvoid,el_var(sassert), - el_long(TYint, loc.linnum)); - e = el_bin(OPoror,TYvoid,e,ea); - e = el_bin(OPcomma, TYnptr, e, n); - } - e = el_una(OPind, type->totym(), e); - if (tybasic(e->Ety) == TYstruct) - e->Enumbytes = type->size(); - } - else - { elem *einit; - - einit = resolveLengthVar(lengthVar, &n1, t1); - n2 = e2->toElem(irs); - - if (global.params.useArrayBounds) - { - elem *elength; - elem *n2x; - elem *ea; - - if (t1->ty == Tsarray) - { TypeSArray *tsa = (TypeSArray *)t1; - integer_t length = tsa->dim->toInteger(); - - elength = el_long(TYuint, length); - goto L1; - } - else if (t1->ty == Tarray) - { - elength = n1; - n1 = el_same(&elength); - elength = el_una(OP64_32, TYuint, elength); - L1: - n2x = n2; - n2 = el_same(&n2x); - n2x = el_bin(OPlt, TYint, n2x, elength); - - // Construct: (n2x || ModuleAssert(line)) - Symbol *sassert; - - sassert = irs->blx->module->toModuleArray(); - ea = el_bin(OPcall,TYvoid,el_var(sassert), - el_long(TYint, loc.linnum)); - eb = el_bin(OPoror,TYvoid,n2x,ea); - } - } - - n1 = array_toPtr(t1, n1); - - { elem *escale; - - escale = el_long(TYint, t1->nextOf()->size()); - n2 = el_bin(OPmul, TYint, n2, escale); - e = el_bin(OPadd, TYnptr, n1, n2); - e = el_una(OPind, type->totym(), e); - if (tybasic(e->Ety) == TYstruct || tybasic(e->Ety) == TYarray) - { e->Ety = TYstruct; - e->Enumbytes = type->size(); - } - } - - eb = el_combine(einit, eb); - e = el_combine(eb, e); - } - el_setLoc(e,loc); - return e; -} - - -elem *TupleExp::toElem(IRState *irs) -{ elem *e = NULL; - - //printf("TupleExp::toElem() %s\n", toChars()); - for (size_t i = 0; i < exps->dim; i++) - { Expression *el = (Expression *)exps->data[i]; - elem *ep = el->toElem(irs); - - e = el_combine(e, ep); - } - return e; -} - - -elem *ArrayLiteralExp::toElem(IRState *irs) -{ elem *e; - size_t dim; - - //printf("ArrayLiteralExp::toElem() %s\n", toChars()); - if (elements) - { - dim = elements->dim; - e = el_long(TYint, dim); - for (size_t i = 0; i < dim; i++) - { Expression *el = (Expression *)elements->data[i]; - elem *ep = el->toElem(irs); - - if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) - { - ep = el_una(OPstrpar, TYstruct, ep); - ep->Enumbytes = el->type->size(); - } - e = el_param(ep, e); - } - } - else - { dim = 0; - e = el_long(TYint, 0); - } - Type *tb = type->toBasetype(); -#if 1 - e = el_param(e, type->getTypeInfo(NULL)->toElem(irs)); - - // call _d_arrayliteralT(ti, dim, ...) - e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e); -#else - e = el_param(e, el_long(TYint, tb->next->size())); - - // call _d_arrayliteral(size, dim, ...) - e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e); -#endif - if (tb->ty == Tarray) - { - e = el_pair(TYullong, el_long(TYint, dim), e); - } - else if (tb->ty == Tpointer) - { - } - else - { - e = el_una(OPind,TYstruct,e); - e->Enumbytes = type->size(); - } - - el_setLoc(e,loc); - return e; -} - - -elem *AssocArrayLiteralExp::toElem(IRState *irs) -{ elem *e; - size_t dim; - - //printf("AssocArrayLiteralExp::toElem() %s\n", toChars()); - dim = keys->dim; - e = el_long(TYint, dim); - for (size_t i = 0; i < dim; i++) - { Expression *el = (Expression *)keys->data[i]; - - for (int j = 0; j < 2; j++) - { - elem *ep = el->toElem(irs); - - if (tybasic(ep->Ety) == TYstruct || tybasic(ep->Ety) == TYarray) - { - ep = el_una(OPstrpar, TYstruct, ep); - ep->Enumbytes = el->type->size(); - } -//printf("[%d] %s\n", i, el->toChars()); -//elem_print(ep); - e = el_param(ep, e); - el = (Expression *)values->data[i]; - } - } - - Type *t = type->toBasetype()->mutableOf(); - assert(t->ty == Taarray); - TypeAArray *ta = (TypeAArray *)t; - - /* Unfortunately, the hash function for Aa (array of chars) is custom and - * different from Axa and Aya, which get the generic hash function. - * So, rewrite the type of the AArray so that if it's key type - * is an array of const or invariant, make it an array of mutable. - */ - Type *tkey = ta->index->toBasetype(); - if (tkey->ty == Tarray) - { - tkey = tkey->nextOf()->mutableOf()->arrayOf(); - tkey = tkey->semantic(0, NULL); - ta = new TypeAArray(ta->nextOf(), tkey); - ta = (TypeAArray *)ta->merge(); - } - - e = el_param(e, ta->getTypeInfo(NULL)->toElem(irs)); - - // call _d_assocarrayliteralT(ti, dim, ...) - e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e); - - el_setLoc(e,loc); - return e; -} - - -/******************************************* - * Generate elem to zero fill contents of Symbol stmp - * from *poffset..offset2. - * May store anywhere from 0..maxoff, as this function - * tries to use aligned int stores whereever possible. - * Update *poffset to end of initialized hole; *poffset will be >= offset2. - */ - -elem *fillHole(Symbol *stmp, size_t *poffset, size_t offset2, size_t maxoff) -{ elem *e = NULL; - int basealign = 1; - - while (*poffset < offset2) - { tym_t ty; - elem *e1; - - if (tybasic(stmp->Stype->Tty) == TYnptr) - e1 = el_var(stmp); - else - e1 = el_ptr(stmp); - if (basealign) - *poffset &= ~3; - basealign = 1; - size_t sz = maxoff - *poffset; - switch (sz) - { case 1: ty = TYchar; break; - case 2: ty = TYshort; break; - case 3: - ty = TYshort; - basealign = 0; - break; - default: - ty = TYlong; - break; - } - e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset)); - e1 = el_una(OPind, ty, e1); - e1 = el_bin(OPeq, ty, e1, el_long(ty, 0)); - e = el_combine(e, e1); - *poffset += tysize[ty]; - } - return e; -} - -elem *StructLiteralExp::toElem(IRState *irs) -{ elem *e; - size_t dim; - - //printf("StructLiteralExp::toElem() %s\n", toChars()); - - // struct symbol to initialize with the literal - Symbol *stmp = sym ? sym : symbol_genauto(sd->type->toCtype()); - - e = NULL; - - if (fillHoles) - { - /* Initialize all alignment 'holes' to zero. - * Do before initializing fields, as the hole filling process - * can spill over into the fields. - */ - size_t offset = 0; - for (size_t i = 0; i < sd->fields.dim; i++) - { - Dsymbol *s = (Dsymbol *)sd->fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v); - - e = el_combine(e, fillHole(stmp, &offset, v->offset, sd->structsize)); - size_t vend = v->offset + v->type->size(); - if (offset < vend) - offset = vend; - } - e = el_combine(e, fillHole(stmp, &offset, sd->structsize, sd->structsize)); - } - - if (elements) - { - dim = elements->dim; - assert(dim <= sd->fields.dim); - for (size_t i = 0; i < dim; i++) - { Expression *el = (Expression *)elements->data[i]; - if (!el) - continue; - - Dsymbol *s = (Dsymbol *)sd->fields.data[i]; - VarDeclaration *v = s->isVarDeclaration(); - assert(v); - - elem *e1; - if (tybasic(stmp->Stype->Tty) == TYnptr) - { e1 = el_var(stmp); - e1->EV.sp.Voffset = soffset; - } - else - { e1 = el_ptr(stmp); - if (soffset) - e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); - } - e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v->offset)); - elem *ec = e1; // pointer to destination - - elem *ep = el->toElem(irs); - - Type *t1b = v->type->toBasetype(); - Type *t2b = el->type->toBasetype(); - if (t1b->ty == Tsarray) - { - if (t2b->implicitConvTo(t1b)) - { -#if DMDV2 - // Determine if postblit is needed - int postblit = 0; - Type *t = t1b; - do - { - t = t->nextOf()->toBasetype(); - } while (t->ty == Tsarray); - if (t->ty == Tstruct) - { StructDeclaration *sd = ((TypeStruct *)t)->sym; - if (sd->postblit) - postblit = 1; - } - - if (postblit) - { - /* Generate: - * _d_arrayctor(ti, From: ep, To: e1) - */ - Expression *ti = t1b->nextOf()->toBasetype()->getTypeInfo(NULL); - elem *esize = el_long(TYsize_t, ((TypeSArray *)t1b)->dim->toInteger()); - e1 = el_pair(TYdarray, esize, e1); - ep = el_pair(TYdarray, el_copytree(esize), array_toPtr(el->type, ep)); - ep = el_params(e1, ep, ti->toElem(irs), NULL); - int rtl = RTLSYM_ARRAYCTOR; - e1 = el_bin(OPcall, type->totym(), el_var(rtlsym[rtl]), ep); - } - else -#endif - { - elem *esize = el_long(TYsize_t, t1b->size()); - ep = array_toPtr(el->type, ep); - e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize)); - } - } - else - { - elem *edim = el_long(TYsize_t, t1b->size() / t2b->size()); - e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct); - } - } - else - { - tym_t ty = v->type->totym(); - e1 = el_una(OPind, ty, e1); - if (ty == TYstruct) - e1->Enumbytes = v->type->size(); - e1 = el_bin(OPeq, ty, e1, ep); - if (ty == TYstruct) - { e1->Eoper = OPstreq; - e1->Enumbytes = v->type->size(); - } -#if DMDV2 - /* Call postBlit() on e1 - */ - Type *tb = v->type->toBasetype(); - if (tb->ty == Tstruct) - { StructDeclaration *sd = ((TypeStruct *)tb)->sym; - if (sd->postblit) - { FuncDeclaration *fd = sd->postblit; - ec = el_copytree(ec); - ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL); - e1 = el_bin(OPcomma, ec->Ety, e1, ec); - } - } -#endif - } - e = el_combine(e, e1); - } - } - - elem *ev = el_var(stmp); - ev->Enumbytes = sd->structsize; - e = el_combine(e, ev); - el_setLoc(e,loc); - return e; -} diff -r f35a9a77d256 -r ff707c518ad7 dmd2/gnuc.c --- a/dmd2/gnuc.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ - -// Put functions in here missing from gnu C - -#include "gnuc.h" - -int memicmp(const char *s1, const char *s2, int n) -{ - int result = 0; - - for (int i = 0; i < n; i++) - { char c1 = s1[i]; - char c2 = s2[i]; - - result = c1 - c2; - if (result) - { - if ('A' <= c1 && c1 <= 'Z') - c1 += 'a' - 'A'; - if ('A' <= c2 && c2 <= 'Z') - c2 += 'a' - 'A'; - result = c1 - c2; - if (result) - break; - } - } - return result; -} - -int stricmp(const char *s1, const char *s2) -{ - int result = 0; - - for (;;) - { char c1 = *s1; - char c2 = *s2; - - result = c1 - c2; - if (result) - { - if ('A' <= c1 && c1 <= 'Z') - c1 += 'a' - 'A'; - if ('A' <= c2 && c2 <= 'Z') - c2 += 'a' - 'A'; - result = c1 - c2; - if (result) - break; - } - if (!c1) - break; - s1++; - s2++; - } - return result; -} - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/gnuc.h --- a/dmd2/gnuc.h Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,8 +0,0 @@ - -#ifndef _GNUC_H -#define _GNUC_H 1 - -int memicmp(const char *s1, const char *s2, int n); -int stricmp(const char *s1, const char *s2); - -#endif diff -r f35a9a77d256 -r ff707c518ad7 dmd2/link.c.nolink --- a/dmd2/link.c.nolink Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,505 +0,0 @@ - -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include -#include -#include -#include - -#if _WIN32 -#include -#endif - -#if linux -#include -#include -#include -#endif - -#include "root.h" - -#include "mars.h" - -#include "mem.h" - -int executecmd(char *cmd, char *args, int useenv); -int executearg0(char *cmd, char *args); - -/**************************************** - * Write filename to cmdbuf, quoting if necessary. - */ - -void writeFilename(OutBuffer *buf, char *filename, size_t len) -{ - /* Loop and see if we need to quote - */ - for (size_t i = 0; i < len; i++) - { char c = filename[i]; - - if (isalnum(c) || c == '_') - continue; - - /* Need to quote - */ - buf->writeByte('"'); - buf->write(filename, len); - buf->writeByte('"'); - return; - } - - /* No quoting necessary - */ - buf->write(filename, len); -} - -void writeFilename(OutBuffer *buf, char *filename) -{ - writeFilename(buf, filename, strlen(filename)); -} - -/***************************** - * Run the linker. Return status of execution. - */ - -int runLINK() -{ -#if _WIN32 - char *p; - int i; - int status; - OutBuffer cmdbuf; - - global.params.libfiles->push((void *) "user32"); - global.params.libfiles->push((void *) "kernel32"); - - for (i = 0; i < global.params.objfiles->dim; i++) - { - if (i) - cmdbuf.writeByte('+'); - p = (char *)global.params.objfiles->data[i]; - char *ext = FileName::ext(p); - if (ext) - // Write name sans extension - writeFilename(&cmdbuf, p, ext - p - 1); - else - writeFilename(&cmdbuf, p); - } - cmdbuf.writeByte(','); - if (global.params.exefile) - writeFilename(&cmdbuf, global.params.exefile); - else - { /* Generate exe file name from first obj name. - * No need to add it to cmdbuf because the linker will default to it. - */ - char *n = (char *)global.params.objfiles->data[0]; - n = FileName::name(n); - FileName *fn = FileName::forceExt(n, "exe"); - global.params.exefile = fn->toChars(); - } - - // Make sure path to exe file exists - { char *p = FileName::path(global.params.exefile); - FileName::ensurePathExists(p); - mem.free(p); - } - - cmdbuf.writeByte(','); - if (global.params.run) - cmdbuf.writestring("nul"); -// if (mapfile) -// cmdbuf.writestring(output); - cmdbuf.writeByte(','); - - for (i = 0; i < global.params.libfiles->dim; i++) - { - if (i) - cmdbuf.writeByte('+'); - writeFilename(&cmdbuf, (char *) global.params.libfiles->data[i]); - } - - if (global.params.deffile) - { - cmdbuf.writeByte(','); - writeFilename(&cmdbuf, global.params.deffile); - } - - /* Eliminate unnecessary trailing commas */ - while (1) - { i = cmdbuf.offset; - if (!i || cmdbuf.data[i - 1] != ',') - break; - cmdbuf.offset--; - } - - if (global.params.resfile) - { - cmdbuf.writestring("/RC:"); - writeFilename(&cmdbuf, global.params.resfile); - } - -#if 0 - if (mapfile) - cmdbuf.writestring("/m"); - if (debuginfo) - cmdbuf.writestring("/li"); - if (codeview) - { - cmdbuf.writestring("/co"); - if (codeview3) - cmdbuf.writestring(":3"); - } -#else - if (global.params.symdebug) - cmdbuf.writestring("/co"); -#endif - - cmdbuf.writestring("/noi"); - for (i = 0; i < global.params.linkswitches->dim; i++) - { - cmdbuf.writestring((char *) global.params.linkswitches->data[i]); - } - cmdbuf.writeByte(';'); - - p = cmdbuf.toChars(); - - FileName *lnkfilename = NULL; - size_t plen = strlen(p); - if (plen > 7000) - { - lnkfilename = FileName::forceExt(global.params.exefile, "lnk"); - File flnk(lnkfilename); - flnk.setbuffer(p, plen); - flnk.ref = 1; - if (flnk.write()) - error("error writing file %s", lnkfilename); - if (lnkfilename->len() < plen) - sprintf(p, "@%s", lnkfilename->toChars()); - } - - char *linkcmd = getenv("LINKCMD"); - if (!linkcmd) - linkcmd = "link"; - status = executecmd(linkcmd, p, 1); - if (lnkfilename) - { - remove(lnkfilename->toChars()); - delete lnkfilename; - } - return status; -#elif linux - pid_t childpid; - int i; - int status; - - // Build argv[] - Array argv; - - const char *cc = getenv("CC"); - if (!cc) - cc = "gcc"; - argv.push((void *)cc); - argv.insert(1, global.params.objfiles); - - // None of that a.out stuff. Use explicit exe file name, or - // generate one from name of first source file. - argv.push((void *)"-o"); - if (global.params.exefile) - { - argv.push(global.params.exefile); - } - else - { // Generate exe file name from first obj name - char *n = (char *)global.params.objfiles->data[0]; - char *e; - char *ex; - - n = FileName::name(n); - e = FileName::ext(n); - if (e) - { - e--; // back up over '.' - ex = (char *)mem.malloc(e - n + 1); - memcpy(ex, n, e - n); - ex[e - n] = 0; - } - else - ex = (char *)"a.out"; // no extension, so give up - argv.push(ex); - global.params.exefile = ex; - } - - // Make sure path to exe file exists - { char *p = FileName::path(global.params.exefile); - FileName::ensurePathExists(p); - mem.free(p); - } - - argv.insert(argv.dim, global.params.libfiles); - - if (global.params.symdebug) - argv.push((void *)"-g"); - - argv.push((void *)"-m32"); - - if (0 && global.params.exefile) - { - /* This switch enables what is known as 'smart linking' - * in the Windows world, where unreferenced sections - * are removed from the executable. It eliminates unreferenced - * functions, essentially making a 'library' out of a module. - * Although it is documented to work with ld version 2.13, - * in practice it does not, but just seems to be ignored. - * Thomas Kuehne has verified that it works with ld 2.16.1. - * BUG: disabled because it causes exception handling to fail - */ - argv.push((void *)"-Xlinker"); - argv.push((void *)"--gc-sections"); - } - - for (i = 0; i < global.params.linkswitches->dim; i++) - { char *p = (char *)global.params.linkswitches->data[i]; - if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l')) - // Don't need -Xlinker if switch starts with -l - argv.push((void *)"-Xlinker"); - argv.push((void *) p); - } - - /* Standard libraries must go after user specified libraries - * passed with -l. - */ - const char *libname = (global.params.symdebug) - ? global.params.debuglibname - : global.params.defaultlibname; - char *buf = (char *)malloc(2 + strlen(libname) + 1); - strcpy(buf, "-l"); - strcpy(buf + 2, libname); - argv.push((void *)buf); // turns into /usr/lib/libphobos2.a - - argv.push((void *)"-ldruntime"); - argv.push((void *)"-lpthread"); - argv.push((void *)"-lm"); - - if (!global.params.quiet || global.params.verbose) - { - // Print it - for (i = 0; i < argv.dim; i++) - printf("%s ", (char *)argv.data[i]); - printf("\n"); - fflush(stdout); - } - - argv.push(NULL); - childpid = fork(); - if (childpid == 0) - { - execvp((char *)argv.data[0], (char **)argv.data); - perror((char *)argv.data[0]); // failed to execute - return -1; - } - - waitpid(childpid, &status, 0); - - status=WEXITSTATUS(status); - if (status) - printf("--- errorlevel %d\n", status); - return status; -#else - printf ("Linking is not yet supported for this version of DMD.\n"); - return -1; -#endif -} - -/********************************** - * Delete generated EXE file. - */ - -void deleteExeFile() -{ - if (global.params.exefile) - { - //printf("deleteExeFile() %s\n", global.params.exefile); - remove(global.params.exefile); - } -} - -/****************************** - * Execute a rule. Return the status. - * cmd program to run - * args arguments to cmd, as a string - * useenv if cmd knows about _CMDLINE environment variable - */ - -#if _WIN32 -int executecmd(char *cmd, char *args, int useenv) -{ - int status; - char *buff; - size_t len; - - if (!global.params.quiet || global.params.verbose) - { - printf("%s %s\n", cmd, args); - fflush(stdout); - } - - if ((len = strlen(args)) > 255) - { char *q; - static char envname[] = "@_CMDLINE"; - - envname[0] = '@'; - switch (useenv) - { case 0: goto L1; - case 2: envname[0] = '%'; break; - } - q = (char *) alloca(sizeof(envname) + len + 1); - sprintf(q,"%s=%s", envname + 1, args); - status = putenv(q); - if (status == 0) - args = envname; - else - { - L1: - error("command line length of %d is too long",len); - } - } - - status = executearg0(cmd,args); -#if _WIN32 - if (status == -1) - status = spawnlp(0,cmd,cmd,args,NULL); -#endif -// if (global.params.verbose) -// printf("\n"); - if (status) - { - if (status == -1) - printf("Can't run '%s', check PATH\n", cmd); - else - printf("--- errorlevel %d\n", status); - } - return status; -} -#endif - -/************************************** - * Attempt to find command to execute by first looking in the directory - * where DMD was run from. - * Returns: - * -1 did not find command there - * !=-1 exit status from command - */ - -#if _WIN32 -int executearg0(char *cmd, char *args) -{ - char *file; - char *argv0 = global.params.argv0; - - //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args); - - // If cmd is fully qualified, we don't do this - if (FileName::absolute(cmd)) - return -1; - - file = FileName::replaceName(argv0, cmd); - - //printf("spawning '%s'\n",file); -#if _WIN32 - return spawnl(0,file,file,args,NULL); -#elif linux - char *full; - int cmdl = strlen(cmd); - - full = (char*) mem.malloc(cmdl + strlen(args) + 2); - if (full == NULL) - return 1; - strcpy(full, cmd); - full [cmdl] = ' '; - strcpy(full + cmdl + 1, args); - - int result = system(full); - - mem.free(full); - return result; -#else - assert(0); -#endif -} -#endif - -/*************************************** - * Run the compiled program. - * Return exit status. - */ - -int runProgram() -{ - //printf("runProgram()\n"); - if (global.params.verbose) - { - printf("%s", global.params.exefile); - for (size_t i = 0; i < global.params.runargs_length; i++) - printf(" %s", (char *)global.params.runargs[i]); - printf("\n"); - } - - // Build argv[] - Array argv; - - argv.push((void *)global.params.exefile); - for (size_t i = 0; i < global.params.runargs_length; i++) - { char *a = global.params.runargs[i]; - -#if _WIN32 - // BUG: what about " appearing in the string? - if (strchr(a, ' ')) - { char *b = (char *)mem.malloc(3 + strlen(a)); - sprintf(b, "\"%s\"", a); - a = b; - } -#endif - argv.push((void *)a); - } - argv.push(NULL); - -#if _WIN32 - char *ex = FileName::name(global.params.exefile); - if (ex == global.params.exefile) - ex = FileName::combine(".", ex); - else - ex = global.params.exefile; - return spawnv(0,ex,(char **)argv.data); -#elif linux - pid_t childpid; - int status; - - childpid = fork(); - if (childpid == 0) - { - const char *fn = (const char *)argv.data[0]; - if (!FileName::absolute(fn)) - { // Make it "./fn" - fn = FileName::combine(".", fn); - } - execv(fn, (char **)argv.data); - perror(fn); // failed to execute - return -1; - } - - waitpid(childpid, &status, 0); - - status = WEXITSTATUS(status); - return status; -#else - assert(0); -#endif -} diff -r f35a9a77d256 -r ff707c518ad7 dmd2/lstring.c --- a/dmd2/lstring.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -// lstring.c - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include - -#include "dchar.h" -#include "mem.h" -#include "lstring.h" - -#ifdef _MSC_VER // prevent compiler internal crash -Lstring Lstring::zero; -#else -Lstring Lstring::zero = LSTRING_EMPTY(); -#endif - -Lstring *Lstring::ctor(const dchar *p, unsigned length) -{ - Lstring *s; - - s = alloc(length); - memcpy(s->string, p, length * sizeof(dchar)); - return s; -} - -Lstring *Lstring::alloc(unsigned length) -{ - Lstring *s; - - s = (Lstring *)mem.malloc(size(length)); - s->length = length; - s->string[length] = 0; - return s; -} - -Lstring *Lstring::append(const Lstring *s) -{ - Lstring *t; - - if (!s->length) - return this; - t = alloc(length + s->length); - memcpy(t->string, string, length * sizeof(dchar)); - memcpy(t->string + length, s->string, s->length * sizeof(dchar)); - return t; -} - -Lstring *Lstring::substring(int start, int end) -{ - Lstring *t; - - if (start == end) - return &zero; - t = alloc(end - start); - memcpy(t->string, string + start, (end - start) * sizeof(dchar)); - return t; -} diff -r f35a9a77d256 -r ff707c518ad7 dmd2/lstring.h --- a/dmd2/lstring.h Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ - -// lstring.h -// length-prefixed strings - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef LSTRING_H -#define LSTRING_H 1 - -#include "dchar.h" - -struct Lstring -{ - unsigned length; - - // Disable warning about nonstandard extension - #pragma warning (disable : 4200) - dchar string[]; - - static Lstring zero; // 0 length string - - // No constructors because we want to be able to statically - // initialize Lstring's, and Lstrings are of variable size. - - #if M_UNICODE - #define LSTRING(p,length) { length, L##p } - #else - #define LSTRING(p,length) { length, p } - #endif - -#if __GNUC__ - #define LSTRING_EMPTY() { 0 } -#else - #define LSTRING_EMPTY() LSTRING("", 0) -#endif - - static Lstring *ctor(const dchar *p) { return ctor(p, Dchar::len(p)); } - static Lstring *ctor(const dchar *p, unsigned length); - static unsigned size(unsigned length) { return sizeof(Lstring) + (length + 1) * sizeof(dchar); } - static Lstring *alloc(unsigned length); - Lstring *clone(); - - unsigned len() { return length; } - - dchar *toDchars() { return string; } - - hash_t hash() { return Dchar::calcHash(string, length); } - hash_t ihash() { return Dchar::icalcHash(string, length); } - - static int cmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memcmp(s1->string, s2->string, s1->length); - } - - static int icmp(const Lstring *s1, const Lstring *s2) - { - int c = s2->length - s1->length; - return c ? c : Dchar::memicmp(s1->string, s2->string, s1->length); - } - - Lstring *append(const Lstring *s); - Lstring *substring(int start, int end); -}; - -#endif diff -r f35a9a77d256 -r ff707c518ad7 dmd2/man.c --- a/dmd2/man.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ - -// Compiler implementation of the D programming language -// Copyright (c) 2008-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include - -#if _WIN32 - -#include - -#pragma comment(lib,"shell32.lib") - -void browse(const char *url) -{ - ShellExecute(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL); -} - -#endif - -#if linux || __APPLE__ - -#include -#include -#include - -void browse(const char *url) -{ - pid_t childpid; - const char *args[3]; - - const char *browser = getenv("BROWSER"); - if (browser) - browser = strdup(browser); - else - browser = "firefox"; - - args[0] = browser; - args[1] = url; - args[2] = NULL; - - childpid = fork(); - if (childpid == 0) - { - execvp(args[0], (char**)args); - perror(args[0]); // failed to execute - return; - } -} - -#endif - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/port.h --- a/dmd2/port.h Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +0,0 @@ - -// Copyright (c) 1999-2002 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com - -#ifndef PORT_H -#define PORT_H - -// Portable wrapper around compiler/system specific things. -// The idea is to minimize #ifdef's in the app code. - -#ifndef TYPEDEFS -#define TYPEDEFS - -#include - -#if _MSC_VER -typedef __int64 longlong; -typedef unsigned __int64 ulonglong; -#else -typedef long long longlong; -typedef unsigned long long ulonglong; -#endif - -#endif - -typedef double d_time; - -struct Port -{ - static double nan; - static double infinity; - static double dbl_max; - static double dbl_min; - -#if __GNUC__ - // These conflict with macros in math.h, should rename them - #undef isnan - #undef isfinite - #undef isinfinity - #undef signbit -#endif - static int isNan(double); - static int isFinite(double); - static int isInfinity(double); - static int Signbit(double); - - static double floor(double); - static double pow(double x, double y); - - static ulonglong strtoull(const char *p, char **pend, int base); - - static char *ull_to_string(char *buffer, ulonglong ull); - static wchar_t *ull_to_string(wchar_t *buffer, ulonglong ull); - - // Convert ulonglong to double - static double ull_to_double(ulonglong ull); - - // Get locale-dependent list separator - static char *list_separator(); - static wchar_t *wlist_separator(); -}; - -#endif diff -r f35a9a77d256 -r ff707c518ad7 dmd2/root.c --- a/dmd2/root.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1903 +0,0 @@ - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#include -#include -#include -#include -#include -#include - -#if _MSC_VER ||__MINGW32__ -#include -#include -#endif - -#if _WIN32 -#include -#include -#endif - -#if POSIX -#include -#include -#include -#include -#include -#include -#endif - -#include "port.h" -#include "root.h" -#include "dchar.h" -#include "mem.h" -#include "mars.h" - -#if 0 //__SC__ //def DEBUG -extern "C" void __cdecl _assert(void *e, void *f, unsigned line) -{ - printf("Assert('%s','%s',%d)\n",e,f,line); - fflush(stdout); - *(char *)0 = 0; -} -#endif - - -/************************************* - * Convert wchar string to ascii string. - */ - -char *wchar2ascii(wchar_t *us) -{ - return wchar2ascii(us, wcslen(us)); -} - -char *wchar2ascii(wchar_t *us, unsigned len) -{ - unsigned i; - char *p; - - p = (char *)mem.malloc(len + 1); - for (i = 0; i <= len; i++) - p[i] = (char) us[i]; - return p; -} - -int wcharIsAscii(wchar_t *us) -{ - return wcharIsAscii(us, wcslen(us)); -} - -int wcharIsAscii(wchar_t *us, unsigned len) -{ - unsigned i; - - for (i = 0; i <= len; i++) - { - if (us[i] & ~0xFF) // if high bits set - return 0; // it's not ascii - } - return 1; -} - - -/*********************************** - * Compare length-prefixed strings (bstr). - */ - -int bstrcmp(unsigned char *b1, unsigned char *b2) -{ - return (*b1 == *b2 && memcmp(b1 + 1, b2 + 1, *b2) == 0) ? 0 : 1; -} - -/*************************************** - * Convert bstr into a malloc'd string. - */ - -char *bstr2str(unsigned char *b) -{ - char *s; - unsigned len; - - len = *b; - s = (char *) mem.malloc(len + 1); - s[len] = 0; - return (char *)memcpy(s,b + 1,len); -} - -/************************************** - * Print error message and exit. - */ - -void error(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Error: "); - vprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); - - exit(EXIT_FAILURE); -} - -#if M_UNICODE -void error(const dchar *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Error: "); - vwprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); - - exit(EXIT_FAILURE); -} -#endif - -void error_mem() -{ - error("out of memory"); -} - -/************************************** - * Print warning message. - */ - -void warning(const char *format, ...) -{ - va_list ap; - - va_start(ap, format); - printf("Warning: "); - vprintf(format, ap); - va_end( ap ); - printf("\n"); - fflush(stdout); -} - -/****************************** Object ********************************/ - -int Object::equals(Object *o) -{ - return o == this; -} - -hash_t Object::hashCode() -{ - return (hash_t) this; -} - -int Object::compare(Object *obj) -{ - return this - obj; -} - -void Object::print() -{ - printf("%s %p\n", toChars(), this); -} - -char *Object::toChars() -{ - return (char *)"Object"; -} - -dchar *Object::toDchars() -{ -#if M_UNICODE - return L"Object"; -#else - return toChars(); -#endif -} - -int Object::dyncast() -{ - return 0; -} - -void Object::toBuffer(OutBuffer *b) -{ - b->writestring("Object"); -} - -void Object::mark() -{ -} - -/****************************** String ********************************/ - -String::String(char *str, int ref) -{ - this->str = ref ? str : mem.strdup(str); - this->ref = ref; -} - -String::~String() -{ - mem.free(str); -} - -void String::mark() -{ - mem.mark(str); -} - -hash_t String::calcHash(const char *str, size_t len) -{ - hash_t hash = 0; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(uint8_t *)str; - return hash; - - case 2: - hash *= 37; - hash += *(uint16_t *)str; - return hash; - - case 3: - hash *= 37; - hash += (*(uint16_t *)str << 8) + - ((uint8_t *)str)[2]; - return hash; - - default: - hash *= 37; - hash += *(uint32_t *)str; - str += 4; - len -= 4; - break; - } - } -} - -hash_t String::calcHash(const char *str) -{ - return calcHash(str, strlen(str)); -} - -hash_t String::hashCode() -{ - return calcHash(str, strlen(str)); -} - -unsigned String::len() -{ - return strlen(str); -} - -int String::equals(Object *obj) -{ - return strcmp(str,((String *)obj)->str) == 0; -} - -int String::compare(Object *obj) -{ - return strcmp(str,((String *)obj)->str); -} - -char *String::toChars() -{ - return str; -} - -void String::print() -{ - printf("String '%s'\n",str); -} - - -/****************************** FileName ********************************/ - -FileName::FileName(char *str, int ref) - : String(str,ref) -{ -} - -char *FileName::combine(const char *path, const char *name) -{ char *f; - size_t pathlen; - size_t namelen; - - if (!path || !*path) - return (char *)name; - pathlen = strlen(path); - namelen = strlen(name); - f = (char *)mem.malloc(pathlen + 1 + namelen + 1); - memcpy(f, path, pathlen); - - if ( - path[pathlen - 1] != '/' -#if _WIN32 - && path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' -#endif - ) - { f[pathlen] = '/'; - pathlen++; - } - - memcpy(f + pathlen, name, namelen + 1); - return f; -} - -FileName::FileName(char *path, char *name) - : String(combine(path,name),1) -{ -} - -// Split a path into an Array of paths -Array *FileName::splitPath(const char *path) -{ - char c = 0; // unnecessary initializer is for VC /W4 - const char *p; - OutBuffer buf; - Array *array; - - array = new Array(); - if (path) - { - p = path; - do - { char instring = 0; - - while (isspace(*p)) // skip leading whitespace - p++; - buf.reserve(strlen(p) + 1); // guess size of path - for (; ; p++) - { - c = *p; - switch (c) - { - case '"': - instring ^= 1; // toggle inside/outside of string - continue; - -#if _WIN32 - case ';': -#endif -#if POSIX - case ':': -#endif - p++; - break; // note that ; cannot appear as part - // of a path, quotes won't protect it - - case 0x1A: // ^Z means end of file - case 0: - break; - - case '\r': - continue; // ignore carriage returns - -#if POSIX - case '~': - buf.writestring(getenv("HOME")); - continue; -#endif - - case ' ': - case '\t': // tabs in filenames? - if (!instring) // if not in string - break; // treat as end of path - default: - buf.writeByte(c); - continue; - } - break; - } - if (buf.offset) // if path is not empty - { - buf.writeByte(0); // to asciiz - array->push(buf.extractData()); - } - } while (c); - } - return array; -} - -hash_t FileName::hashCode() -{ -#if _WIN32 - // We need a different hashCode because it must be case-insensitive - size_t len = strlen(str); - hash_t hash = 0; - unsigned char *s = (unsigned char *)str; - - for (;;) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 37; - hash += *(uint8_t *)s | 0x20; - return hash; - - case 2: - hash *= 37; - hash += *(uint16_t *)s | 0x2020; - return hash; - - case 3: - hash *= 37; - hash += ((*(uint16_t *)s << 8) + - ((uint8_t *)s)[2]) | 0x202020; - break; - - default: - hash *= 37; - hash += *(uint32_t *)s | 0x20202020; - s += 4; - len -= 4; - break; - } - } -#else - // darwin HFS is case insensitive, though... - return String::hashCode(); -#endif -} - -int FileName::compare(Object *obj) -{ -#if _WIN32 - return stricmp(str,((FileName *)obj)->str); -#else - return String::compare(obj); -#endif -} - -int FileName::equals(Object *obj) -{ -#if _WIN32 - return stricmp(str,((FileName *)obj)->str) == 0; -#else - return String::equals(obj); -#endif -} - -/************************************ - * Return !=0 if absolute path name. - */ - -int FileName::absolute(const char *name) -{ - return -#if _WIN32 - (*name == '\\') || - (*name == '/') || - (*name && name[1] == ':') || -#endif - (*name == '/'); -} - -/******************************** - * Return filename extension (read-only). - * Points past '.' of extension. - * If there isn't one, return NULL. - */ - -char *FileName::ext(const char *str) -{ - char *e; - size_t len = strlen(str); - - e = (char *)str + len; - for (;;) - { - switch (*e) - { case '.': - return e + 1; - - case '/': - break; - -#if _WIN32 - case '\\': - case ':': - break; -#endif - default: - if (e == str) - break; - e--; - continue; - } - return NULL; - } -} - -char *FileName::ext() -{ - return ext(str); -} - -/******************************** - * Return mem.malloc'd filename with extension removed. - */ - -char *FileName::removeExt(const char *str) -{ - const char *e = ext(str); - if (e) - { size_t len = (e - str) - 1; - char *n = (char *)mem.malloc(len + 1); - memcpy(n, str, len); - n[len] = 0; - return n; - } - return mem.strdup(str); -} - -/******************************** - * Return filename name excluding path (read-only). - */ - -char *FileName::name(const char *str) -{ - char *e; - size_t len = strlen(str); - - e = (char *)str + len; - for (;;) - { - switch (*e) - { - - case '/': - return e + 1; - -#if _WIN32 - case '\\': - case ':': - return e + 1; -#endif - default: - if (e == str) - break; - e--; - continue; - } - return e; - } -} - -char *FileName::name() -{ - return name(str); -} - -/************************************** - * Return path portion of str. - * Path will does not include trailing path separator. - */ - -char *FileName::path(const char *str) -{ - char *n = name(str); - char *path; - size_t pathlen; - - if (n > str) - { - - if (n[-1] == '/') - n--; - -#if _WIN32 - if (n[-1] == '\\') - n--; -#endif - } - pathlen = n - str; - path = (char *)mem.malloc(pathlen + 1); - memcpy(path, str, pathlen); - path[pathlen] = 0; - return path; -} - -/************************************** - * Replace filename portion of path. - */ - -char *FileName::replaceName(char *path, char *name) -{ char *f; - char *n; - size_t pathlen; - size_t namelen; - - if (absolute(name)) - return name; - - n = FileName::name(path); - if (n == path) - return name; - pathlen = n - path; - namelen = strlen(name); - f = (char *)mem.malloc(pathlen + 1 + namelen + 1); - memcpy(f, path, pathlen); - - if ( - path[pathlen - 1] != '/' -#if _WIN32 - && path[pathlen - 1] != '\\' && path[pathlen - 1] != ':' -#endif - ) - { f[pathlen] = '/'; - pathlen++; - } - - memcpy(f + pathlen, name, namelen + 1); - return f; -} - -/*************************** - */ - -FileName *FileName::defaultExt(const char *name, const char *ext) -{ - char *e; - char *s; - size_t len; - size_t extlen; - - e = FileName::ext(name); - if (e) // if already has an extension - return new FileName((char *)name, 0); - - len = strlen(name); - extlen = strlen(ext); - s = (char *)alloca(len + 1 + extlen + 1); - memcpy(s,name,len); - s[len] = '.'; - memcpy(s + len + 1, ext, extlen + 1); - return new FileName(s, 0); -} - -/*************************** - */ - -FileName *FileName::forceExt(const char *name, const char *ext) -{ - char *e; - char *s; - size_t len; - size_t extlen; - - e = FileName::ext(name); - if (e) // if already has an extension - { - len = e - name; - extlen = strlen(ext); - - s = (char *)alloca(len + extlen + 1); - memcpy(s,name,len); - memcpy(s + len, ext, extlen + 1); - return new FileName(s, 0); - } - else - return defaultExt(name, ext); // doesn't have one -} - -/****************************** - * Return !=0 if extensions match. - */ - -int FileName::equalsExt(const char *ext) -{ const char *e; - - e = FileName::ext(); - if (!e && !ext) - return 1; - if (!e || !ext) - return 0; -#if POSIX - return strcmp(e,ext) == 0; -#endif -#if _WIN32 - return stricmp(e,ext) == 0; -#endif -} - -/************************************* - * Copy file from this to to. - */ - -void FileName::CopyTo(FileName *to) -{ - File file(this); - -#if _WIN32 - file.touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); // keep same file time -#endif -#if POSIX - file.touchtime = mem.malloc(sizeof(struct stat)); // keep same file time -#endif - file.readv(); - file.name = to; - file.writev(); -} - -/************************************* - * Search Path for file. - * Input: - * cwd if !=0, search current directory before searching path - */ - -char *FileName::searchPath(Array *path, const char *name, int cwd) -{ - if (absolute(name)) - { - return exists(name) ? (char *)name : NULL; - } - if (cwd) - { - if (exists(name)) - return (char *)name; - } - if (path) - { unsigned i; - - for (i = 0; i < path->dim; i++) - { - char *p = (char *)path->data[i]; - char *n = combine(p, name); - - if (exists(n)) - return n; - } - } - return NULL; -} - -int FileName::exists(const char *name) -{ -#if POSIX - struct stat st; - - if (stat(name, &st) < 0) - return 0; - if (S_ISDIR(st.st_mode)) - return 2; - return 1; -#endif -#if _WIN32 - DWORD dw; - int result; - - dw = GetFileAttributesA(name); - if (dw == -1L) - result = 0; - else if (dw & FILE_ATTRIBUTE_DIRECTORY) - result = 2; - else - result = 1; - return result; -#endif -} - -void FileName::ensurePathExists(const char *path) -{ - //printf("FileName::ensurePathExists(%s)\n", path ? path : ""); - if (path && *path) - { - if (!exists(path)) - { - char *p = FileName::path(path); - if (*p) - { -#if _WIN32 - size_t len = strlen(p); - if (len > 2 && p[-1] == ':') - { mem.free(p); - return; - } -#endif - ensurePathExists(p); - mem.free(p); - } -#if _WIN32 - if (path[strlen(path) - 1] != '\\') -#endif -#if POSIX - if (path[strlen(path) - 1] != '\\') -#endif - { - //printf("mkdir(%s)\n", path); -#if _WIN32 - if (mkdir(path)) -#endif -#if POSIX - if (mkdir(path, 0777)) -#endif - error("cannot create directory %s", path); - } - } - } -} - -/****************************** File ********************************/ - -File::File(FileName *n) -{ - ref = 0; - buffer = NULL; - len = 0; - touchtime = NULL; - name = n; -} - -File::File(char *n) -{ - ref = 0; - buffer = NULL; - len = 0; - touchtime = NULL; - name = new FileName(n, 0); -} - -File::~File() -{ - if (buffer) - { - if (ref == 0) - mem.free(buffer); -#if _WIN32 - else if (ref == 2) - UnmapViewOfFile(buffer); -#endif - } - if (touchtime) - mem.free(touchtime); -} - -void File::mark() -{ - mem.mark(buffer); - mem.mark(touchtime); - mem.mark(name); -} - -/************************************* - */ - -int File::read() -{ -#if POSIX - off_t size; - ssize_t numread; - int fd; - struct stat buf; - int result = 0; - char *name; - - name = this->name->toChars(); - //printf("File::read('%s')\n",name); - fd = open(name, O_RDONLY); - if (fd == -1) - { result = errno; - //printf("\topen error, errno = %d\n",errno); - goto err1; - } - - if (!ref) - mem.free(buffer); - ref = 0; // we own the buffer now - - //printf("\tfile opened\n"); - if (fstat(fd, &buf)) - { - printf("\tfstat error, errno = %d\n",errno); - goto err2; - } - size = buf.st_size; - buffer = (unsigned char *) mem.malloc(size + 2); - if (!buffer) - { - printf("\tmalloc error, errno = %d\n",errno); - goto err2; - } - - numread = ::read(fd, buffer, size); - if (numread != size) - { - printf("\tread error, errno = %d\n",errno); - goto err2; - } - - if (touchtime) - memcpy(touchtime, &buf, sizeof(buf)); - - if (close(fd) == -1) - { - printf("\tclose error, errno = %d\n",errno); - goto err; - } - - len = size; - - // Always store a wchar ^Z past end of buffer so scanner has a sentinel - buffer[size] = 0; // ^Z is obsolete, use 0 - buffer[size + 1] = 0; - return 0; - -err2: - close(fd); -err: - mem.free(buffer); - buffer = NULL; - len = 0; - -err1: - result = 1; - return result; -#endif -#if _WIN32 - DWORD size; - DWORD numread; - HANDLE h; - int result = 0; - char *name; - - name = this->name->toChars(); - h = CreateFileA(name,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,0); - if (h == INVALID_HANDLE_VALUE) - goto err1; - - if (!ref) - mem.free(buffer); - ref = 0; - - size = GetFileSize(h,NULL); - buffer = (unsigned char *) mem.malloc(size + 2); - if (!buffer) - goto err2; - - if (ReadFile(h,buffer,size,&numread,NULL) != TRUE) - goto err2; - - if (numread != size) - goto err2; - - if (touchtime) - { - if (!GetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime)) - goto err2; - } - - if (!CloseHandle(h)) - goto err; - - len = size; - - // Always store a wchar ^Z past end of buffer so scanner has a sentinel - buffer[size] = 0; // ^Z is obsolete, use 0 - buffer[size + 1] = 0; - return 0; - -err2: - CloseHandle(h); -err: - mem.free(buffer); - buffer = NULL; - len = 0; - -err1: - result = 1; - return result; -#endif -} - -/***************************** - * Read a file with memory mapped file I/O. - */ - -int File::mmread() -{ -#if POSIX - return read(); -#endif -#if _WIN32 - HANDLE hFile; - HANDLE hFileMap; - DWORD size; - char *name; - - name = this->name->toChars(); - hFile = CreateFile(name, GENERIC_READ, - FILE_SHARE_READ, NULL, - OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - if (hFile == INVALID_HANDLE_VALUE) - goto Lerr; - size = GetFileSize(hFile, NULL); - //printf(" file created, size %d\n", size); - - hFileMap = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,size,NULL); - if (CloseHandle(hFile) != TRUE) - goto Lerr; - - if (hFileMap == NULL) - goto Lerr; - - //printf(" mapping created\n"); - - if (!ref) - mem.free(buffer); - ref = 2; - buffer = (unsigned char *)MapViewOfFileEx(hFileMap, FILE_MAP_READ,0,0,size,NULL); - if (CloseHandle(hFileMap) != TRUE) - goto Lerr; - if (buffer == NULL) // mapping view failed - goto Lerr; - - len = size; - //printf(" buffer = %p\n", buffer); - - return 0; - -Lerr: - return GetLastError(); // failure -#endif -} - -/********************************************* - * Write a file. - * Returns: - * 0 success - */ - -int File::write() -{ -#if POSIX - int fd; - ssize_t numwritten; - char *name; - - name = this->name->toChars(); - fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644); - if (fd == -1) - goto err; - - numwritten = ::write(fd, buffer, len); - if (len != numwritten) - goto err2; - - if (close(fd) == -1) - goto err; - - if (touchtime) - { struct utimbuf ubuf; - - ubuf.actime = ((struct stat *)touchtime)->st_atime; - ubuf.modtime = ((struct stat *)touchtime)->st_mtime; - if (utime(name, &ubuf)) - goto err; - } - return 0; - -err2: - close(fd); - ::remove(name); -err: - return 1; -#endif -#if _WIN32 - HANDLE h; - DWORD numwritten; - char *name; - - name = this->name->toChars(); - h = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); - if (h == INVALID_HANDLE_VALUE) - goto err; - - if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) - goto err2; - - if (len != numwritten) - goto err2; - - if (touchtime) { - SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); - } - if (!CloseHandle(h)) - goto err; - return 0; - -err2: - CloseHandle(h); - DeleteFileA(name); -err: - return 1; -#endif -} - -/********************************************* - * Append to a file. - * Returns: - * 0 success - */ - -int File::append() -{ -#if POSIX - return 1; -#endif -#if _WIN32 - HANDLE h; - DWORD numwritten; - char *name; - - name = this->name->toChars(); - h = CreateFileA(name,GENERIC_WRITE,0,NULL,OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,NULL); - if (h == INVALID_HANDLE_VALUE) - goto err; - -#if 1 - SetFilePointer(h, 0, NULL, FILE_END); -#else // INVALID_SET_FILE_POINTER doesn't seem to have a definition - if (SetFilePointer(h, 0, NULL, FILE_END) == INVALID_SET_FILE_POINTER) - goto err; -#endif - - if (WriteFile(h,buffer,len,&numwritten,NULL) != TRUE) - goto err2; - - if (len != numwritten) - goto err2; - - if (touchtime) { - SetFileTime(h, NULL, NULL, &((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime); - } - if (!CloseHandle(h)) - goto err; - return 0; - -err2: - CloseHandle(h); -err: - return 1; -#endif -} - -/************************************** - */ - -void File::readv() -{ - if (read()) - error("Error reading file '%s'\n",name->toChars()); -} - -/************************************** - */ - -void File::mmreadv() -{ - if (mmread()) - readv(); -} - -void File::writev() -{ - if (write()) - error("Error writing file '%s'\n",name->toChars()); -} - -void File::appendv() -{ - if (write()) - error("Error appending to file '%s'\n",name->toChars()); -} - -/******************************************* - * Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - -int File::exists() -{ -#if POSIX - return 0; -#endif -#if _WIN32 - DWORD dw; - int result; - char *name; - - name = this->name->toChars(); - if (touchtime) - dw = ((WIN32_FIND_DATAA *)touchtime)->dwFileAttributes; - else - dw = GetFileAttributesA(name); - if (dw == -1L) - result = 0; - else if (dw & FILE_ATTRIBUTE_DIRECTORY) - result = 2; - else - result = 1; - return result; -#endif -} - -void File::remove() -{ -#if POSIX - ::remove(this->name->toChars()); -#endif -#if _WIN32 - DeleteFileA(this->name->toChars()); -#endif -} - -Array *File::match(char *n) -{ - return match(new FileName(n, 0)); -} - -Array *File::match(FileName *n) -{ -#if POSIX - return NULL; -#endif -#if _WIN32 - HANDLE h; - WIN32_FIND_DATAA fileinfo; - Array *a; - char *c; - char *name; - - a = new Array(); - c = n->toChars(); - name = n->name(); - h = FindFirstFileA(c,&fileinfo); - if (h != INVALID_HANDLE_VALUE) - { - do - { - // Glue path together with name - char *fn; - File *f; - - fn = (char *)mem.malloc(name - c + strlen(fileinfo.cFileName) + 1); - memcpy(fn, c, name - c); - strcpy(fn + (name - c), fileinfo.cFileName); - f = new File(fn); - f->touchtime = mem.malloc(sizeof(WIN32_FIND_DATAA)); - memcpy(f->touchtime, &fileinfo, sizeof(fileinfo)); - a->push(f); - } while (FindNextFileA(h,&fileinfo) != FALSE); - FindClose(h); - } - return a; -#endif -} - -int File::compareTime(File *f) -{ -#if POSIX - return 0; -#endif -#if _WIN32 - if (!touchtime) - stat(); - if (!f->touchtime) - f->stat(); - return CompareFileTime(&((WIN32_FIND_DATAA *)touchtime)->ftLastWriteTime, &((WIN32_FIND_DATAA *)f->touchtime)->ftLastWriteTime); -#endif -} - -void File::stat() -{ -#if POSIX - if (!touchtime) - { - touchtime = mem.calloc(1, sizeof(struct stat)); - } -#endif -#if _WIN32 - HANDLE h; - - if (!touchtime) - { - touchtime = mem.calloc(1, sizeof(WIN32_FIND_DATAA)); - } - h = FindFirstFileA(name->toChars(),(WIN32_FIND_DATAA *)touchtime); - if (h != INVALID_HANDLE_VALUE) - { - FindClose(h); - } -#endif -} - -void File::checkoffset(size_t offset, size_t nbytes) -{ - if (offset > len || offset + nbytes > len) - error("Corrupt file '%s': offset x%"PRIxSIZE" off end of file",toChars(),offset); -} - -char *File::toChars() -{ - return name->toChars(); -} - - -/************************* OutBuffer *************************/ - -OutBuffer::OutBuffer() -{ - data = NULL; - offset = 0; - size = 0; -} - -OutBuffer::~OutBuffer() -{ - mem.free(data); -} - -void *OutBuffer::extractData() -{ - void *p; - - p = (void *)data; - data = NULL; - offset = 0; - size = 0; - return p; -} - -void OutBuffer::mark() -{ - mem.mark(data); -} - -void OutBuffer::reserve(unsigned nbytes) -{ - //printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); - if (size - offset < nbytes) - { -#if defined (__x86_64__) - size = (offset + nbytes) * 2+2; -#else - size = (offset + nbytes) * 2; -#endif - data = (unsigned char *)mem.realloc(data, size); - } -} - -void OutBuffer::reset() -{ - offset = 0; -} - -void OutBuffer::setsize(unsigned size) -{ - offset = size; -} - -void OutBuffer::write(const void *data, unsigned nbytes) -{ - reserve(nbytes); - memcpy(this->data + offset, data, nbytes); - offset += nbytes; -} - -void OutBuffer::writebstring(unsigned char *string) -{ - write(string,*string + 1); -} - -void OutBuffer::writestring(const char *string) -{ - write(string,strlen(string)); -} - -void OutBuffer::writedstring(const char *string) -{ -#if M_UNICODE - for (; *string; string++) - { - writedchar(*string); - } -#else - write(string,strlen(string)); -#endif -} - -void OutBuffer::writedstring(const wchar_t *string) -{ -#if M_UNICODE - write(string,wcslen(string) * sizeof(wchar_t)); -#else - for (; *string; string++) - { - writedchar(*string); - } -#endif -} - -void OutBuffer::prependstring(const char *string) -{ unsigned len; - - len = strlen(string); - reserve(len); - memmove(data + len, data, offset); - memcpy(data, string, len); - offset += len; -} - -void OutBuffer::writenl() -{ -#if _WIN32 -#if M_UNICODE - write4(0x000A000D); // newline is CR,LF on Microsoft OS's -#else - writeword(0x0A0D); // newline is CR,LF on Microsoft OS's -#endif -#else -#if M_UNICODE - writeword('\n'); -#else - writeByte('\n'); -#endif -#endif -} - -void OutBuffer::writeByte(unsigned b) -{ - reserve(1); - this->data[offset] = (unsigned char)b; - offset++; -} - -void OutBuffer::writeUTF8(unsigned b) -{ - reserve(6); - if (b <= 0x7F) - { - this->data[offset] = (unsigned char)b; - offset++; - } - else if (b <= 0x7FF) - { - this->data[offset + 0] = (unsigned char)((b >> 6) | 0xC0); - this->data[offset + 1] = (unsigned char)((b & 0x3F) | 0x80); - offset += 2; - } - else if (b <= 0xFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 12) | 0xE0); - this->data[offset + 1] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)((b & 0x3F) | 0x80); - offset += 3; - } - else if (b <= 0x1FFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 18) | 0xF0); - this->data[offset + 1] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 3] = (unsigned char)((b & 0x3F) | 0x80); - offset += 4; - } - else if (b <= 0x3FFFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 24) | 0xF8); - this->data[offset + 1] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); - this->data[offset + 3] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 4] = (unsigned char)((b & 0x3F) | 0x80); - offset += 5; - } - else if (b <= 0x7FFFFFFF) - { - this->data[offset + 0] = (unsigned char)((b >> 30) | 0xFC); - this->data[offset + 1] = (unsigned char)(((b >> 24) & 0x3F) | 0x80); - this->data[offset + 2] = (unsigned char)(((b >> 18) & 0x3F) | 0x80); - this->data[offset + 3] = (unsigned char)(((b >> 12) & 0x3F) | 0x80); - this->data[offset + 4] = (unsigned char)(((b >> 6) & 0x3F) | 0x80); - this->data[offset + 5] = (unsigned char)((b & 0x3F) | 0x80); - offset += 6; - } - else - assert(0); -} - -void OutBuffer::writedchar(unsigned b) -{ - reserve(Dchar_mbmax * sizeof(dchar)); - offset = (unsigned char *)Dchar::put((dchar *)(this->data + offset), (dchar)b) - - this->data; -} - -void OutBuffer::prependbyte(unsigned b) -{ - reserve(1); - memmove(data + 1, data, offset); - data[0] = (unsigned char)b; - offset++; -} - -void OutBuffer::writeword(unsigned w) -{ - reserve(2); - *(unsigned short *)(this->data + offset) = (unsigned short)w; - offset += 2; -} - -void OutBuffer::writeUTF16(unsigned w) -{ - reserve(4); - if (w <= 0xFFFF) - { - *(unsigned short *)(this->data + offset) = (unsigned short)w; - offset += 2; - } - else if (w <= 0x10FFFF) - { - *(unsigned short *)(this->data + offset) = (unsigned short)((w >> 10) + 0xD7C0); - *(unsigned short *)(this->data + offset + 2) = (unsigned short)((w & 0x3FF) | 0xDC00); - offset += 4; - } - else - assert(0); -} - -void OutBuffer::write4(unsigned w) -{ - reserve(4); - *(unsigned long *)(this->data + offset) = w; - offset += 4; -} - -void OutBuffer::write(OutBuffer *buf) -{ - if (buf) - { reserve(buf->offset); - memcpy(data + offset, buf->data, buf->offset); - offset += buf->offset; - } -} - -void OutBuffer::write(Object *obj) -{ - if (obj) - { - writestring(obj->toChars()); - } -} - -void OutBuffer::fill0(unsigned nbytes) -{ - reserve(nbytes); - memset(data + offset,0,nbytes); - offset += nbytes; -} - -void OutBuffer::align(unsigned size) -{ unsigned nbytes; - - nbytes = ((offset + size - 1) & ~(size - 1)) - offset; - fill0(nbytes); -} - - -//////////////////////////////////////////////////////////////// -// The compiler shipped with Visual Studio 2005 (and possible -// other versions) does not support C99 printf format specfiers -// such as %z and %j -#if _MSC_VER || __MINGW32__ -using std::string; -using std::wstring; - -template -inline void -search_and_replace(S& str, const S& what, const S& replacement) -{ - assert(!what.empty()); - size_t pos = str.find(what); - while (pos != S::npos) - { - str.replace(pos, what.size(), replacement); - pos = str.find(what, pos + replacement.size()); - } -} -#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) \ - S tmp = f; \ - search_and_replace(fmt, S("%z"), S("%l")); \ - search_and_replace(fmt, S("%j"), S("%i")); \ - f = tmp.c_str(); -#else -#define WORKAROUND_C99_SPECIFIERS_BUG(S,tmp,f) -#endif - -void OutBuffer::vprintf(const char *format, va_list args) -{ - char buffer[128]; - char *p; - unsigned psize; - int count; - - WORKAROUND_C99_SPECIFIERS_BUG(string, fmt, format); - - p = buffer; - psize = sizeof(buffer); - for (;;) - { -#if _WIN32 - count = _vsnprintf(p,psize,format,args); - if (count != -1) - break; - psize *= 2; -#elif POSIX - va_list va; - va_copy(va, args); -/* - The functions vprintf(), vfprintf(), vsprintf(), vsnprintf() - are equivalent to the functions printf(), fprintf(), sprintf(), - snprintf(), respectively, except that they are called with a - va_list instead of a variable number of arguments. These - functions do not call the va_end macro. Consequently, the value - of ap is undefined after the call. The application should call - va_end(ap) itself afterwards. - */ - count = vsnprintf(p,psize,format,va); - va_end(va); - if (count == -1) - psize *= 2; - else if (count >= psize) - psize = count + 1; - else - break; -#endif - p = (char *) alloca(psize); // buffer too small, try again with larger size - } - write(p,count); -} - -#if M_UNICODE -void OutBuffer::vprintf(const wchar_t *format, va_list args) -{ - dchar buffer[128]; - dchar *p; - unsigned psize; - int count; - - WORKAROUND_C99_SPECIFIERS_BUG(wstring, fmt, format); - - p = buffer; - psize = sizeof(buffer) / sizeof(buffer[0]); - for (;;) - { -#if _WIN32 - count = _vsnwprintf(p,psize,format,args); - if (count != -1) - break; - psize *= 2; -#endif -#if POSIX - va_list va; - va_copy(va, args); - count = vsnwprintf(p,psize,format,va); - va_end(va); - - if (count == -1) - psize *= 2; - else if (count >= psize) - psize = count + 1; - else - break; -#endif - p = (dchar *) alloca(psize * 2); // buffer too small, try again with larger size - } - write(p,count * 2); -} -#endif - -void OutBuffer::printf(const char *format, ...) -{ - va_list ap; - va_start(ap, format); - vprintf(format,ap); - va_end(ap); -} - -#if M_UNICODE -void OutBuffer::printf(const wchar_t *format, ...) -{ - va_list ap; - va_start(ap, format); - vprintf(format,ap); - va_end(ap); -} -#endif - -void OutBuffer::bracket(char left, char right) -{ - reserve(2); - memmove(data + 1, data, offset); - data[0] = left; - data[offset + 1] = right; - offset += 2; -} - -/****************** - * Insert left at i, and right at j. - * Return index just past right. - */ - -unsigned OutBuffer::bracket(unsigned i, const char *left, unsigned j, const char *right) -{ - size_t leftlen = strlen(left); - size_t rightlen = strlen(right); - reserve(leftlen + rightlen); - insert(i, left, leftlen); - insert(j + leftlen, right, rightlen); - return j + leftlen + rightlen; -} - -void OutBuffer::spread(unsigned offset, unsigned nbytes) -{ - reserve(nbytes); - memmove(data + offset + nbytes, data + offset, - this->offset - offset); - this->offset += nbytes; -} - -/**************************************** - * Returns: offset + nbytes - */ - -unsigned OutBuffer::insert(unsigned offset, const void *p, unsigned nbytes) -{ - spread(offset, nbytes); - memmove(data + offset, p, nbytes); - return offset + nbytes; -} - -void OutBuffer::remove(unsigned offset, unsigned nbytes) -{ - memmove(data + offset, data + offset + nbytes, this->offset - (offset + nbytes)); - this->offset -= nbytes; -} - -char *OutBuffer::toChars() -{ - writeByte(0); - return (char *)data; -} - -/********************************* Bits ****************************/ - -Bits::Bits() -{ - data = NULL; - bitdim = 0; - allocdim = 0; -} - -Bits::~Bits() -{ - mem.free(data); -} - -void Bits::mark() -{ - mem.mark(data); -} - -void Bits::resize(unsigned bitdim) -{ - unsigned allocdim; - unsigned mask; - - allocdim = (bitdim + 31) / 32; - data = (unsigned *)mem.realloc(data, allocdim * sizeof(data[0])); - if (this->allocdim < allocdim) - memset(data + this->allocdim, 0, (allocdim - this->allocdim) * sizeof(data[0])); - - // Clear other bits in last word - mask = (1 << (bitdim & 31)) - 1; - if (mask) - data[allocdim - 1] &= ~mask; - - this->bitdim = bitdim; - this->allocdim = allocdim; -} - -void Bits::set(unsigned bitnum) -{ - data[bitnum / 32] |= 1 << (bitnum & 31); -} - -void Bits::clear(unsigned bitnum) -{ - data[bitnum / 32] &= ~(1 << (bitnum & 31)); -} - -int Bits::test(unsigned bitnum) -{ - return data[bitnum / 32] & (1 << (bitnum & 31)); -} - -void Bits::set() -{ unsigned mask; - - memset(data, ~0, allocdim * sizeof(data[0])); - - // Clear other bits in last word - mask = (1 << (bitdim & 31)) - 1; - if (mask) - data[allocdim - 1] &= mask; -} - -void Bits::clear() -{ - memset(data, 0, allocdim * sizeof(data[0])); -} - -void Bits::copy(Bits *from) -{ - assert(bitdim == from->bitdim); - memcpy(data, from->data, allocdim * sizeof(data[0])); -} - -Bits *Bits::clone() -{ - Bits *b; - - b = new Bits(); - b->resize(bitdim); - b->copy(this); - return b; -} - -void Bits::sub(Bits *b) -{ - unsigned u; - - for (u = 0; u < allocdim; u++) - data[u] &= ~b->data[u]; -} - - - - - - - - - - - - - - - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/root.h --- a/dmd2/root.h Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,356 +0,0 @@ - - -// Copyright (c) 1999-2006 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - -#ifndef ROOT_H -#define ROOT_H - -#include -#include - -#if __DMC__ -#pragma once -#endif - -typedef size_t hash_t; - -#include "dchar.h" - -char *wchar2ascii(wchar_t *); -int wcharIsAscii(wchar_t *); -char *wchar2ascii(wchar_t *, unsigned len); -int wcharIsAscii(wchar_t *, unsigned len); - -int bstrcmp(unsigned char *s1, unsigned char *s2); -char *bstr2str(unsigned char *b); -void error(const char *format, ...); -void error(const wchar_t *format, ...); -void warning(const char *format, ...); - -#ifndef TYPEDEFS -#define TYPEDEFS - -#if _MSC_VER -#include // for alloca -// According to VC 8.0 docs, long double is the same as double -#define strtold strtod -#define strtof strtod -#define isnan _isnan - -typedef __int64 longlong; -typedef unsigned __int64 ulonglong; -#else -typedef long long longlong; -typedef unsigned long long ulonglong; -#endif - -#endif - -longlong randomx(); - -/* - * Root of our class library. - */ - -struct OutBuffer; -struct Array; - -struct Object -{ - Object() { } - virtual ~Object() { } - - virtual int equals(Object *o); - - /** - * Returns a hash code, useful for things like building hash tables of Objects. - */ - virtual hash_t hashCode(); - - /** - * Return <0, ==0, or >0 if this is less than, equal to, or greater than obj. - * Useful for sorting Objects. - */ - virtual int compare(Object *obj); - - /** - * Pretty-print an Object. Useful for debugging the old-fashioned way. - */ - virtual void print(); - - virtual char *toChars(); - virtual dchar *toDchars(); - virtual void toBuffer(OutBuffer *buf); - - /** - * Used as a replacement for dynamic_cast. Returns a unique number - * defined by the library user. For Object, the return value is 0. - */ - virtual int dyncast(); - - /** - * Marks pointers for garbage collector by calling mem.mark() for all pointers into heap. - */ - /*virtual*/ // not used, disable for now - void mark(); -}; - -struct String : Object -{ - int ref; // != 0 if this is a reference to someone else's string - char *str; // the string itself - - String(char *str, int ref = 1); - - ~String(); - - static hash_t calcHash(const char *str, size_t len); - static hash_t calcHash(const char *str); - hash_t hashCode(); - unsigned len(); - int equals(Object *obj); - int compare(Object *obj); - char *toChars(); - void print(); - void mark(); -}; - -struct FileName : String -{ - FileName(char *str, int ref); - FileName(char *path, char *name); - hash_t hashCode(); - int equals(Object *obj); - int compare(Object *obj); - static int absolute(const char *name); - static char *ext(const char *); - char *ext(); - static char *removeExt(const char *str); - static char *name(const char *); - char *name(); - static char *path(const char *); - static char *replaceName(char *path, char *name); - - static char *combine(const char *path, const char *name); - static Array *splitPath(const char *path); - static FileName *defaultExt(const char *name, const char *ext); - static FileName *forceExt(const char *name, const char *ext); - int equalsExt(const char *ext); - - void CopyTo(FileName *to); - static char *searchPath(Array *path, const char *name, int cwd); - static int exists(const char *name); - static void ensurePathExists(const char *path); -}; - -struct File : Object -{ - int ref; // != 0 if this is a reference to someone else's buffer - unsigned char *buffer; // data for our file - unsigned len; // amount of data in buffer[] - void *touchtime; // system time to use for file - - FileName *name; // name of our file - - File(char *); - File(FileName *); - ~File(); - - void mark(); - - char *toChars(); - - /* Read file, return !=0 if error - */ - - int read(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void readv(); - - /* Read file, return !=0 if error - */ - - int mmread(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void mmreadv(); - - /* Write file, return !=0 if error - */ - - int write(); - - /* Write file, either succeed or fail - * with error message & exit. - */ - - void writev(); - - /* Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - - /* Append to file, return !=0 if error - */ - - int append(); - - /* Append to file, either succeed or fail - * with error message & exit. - */ - - void appendv(); - - /* Return !=0 if file exists. - * 0: file doesn't exist - * 1: normal file - * 2: directory - */ - - int exists(); - - /* Given wildcard filespec, return an array of - * matching File's. - */ - - static Array *match(char *); - static Array *match(FileName *); - - // Compare file times. - // Return <0 this < f - // =0 this == f - // >0 this > f - int compareTime(File *f); - - // Read system file statistics - void stat(); - - /* Set buffer - */ - - void setbuffer(void *buffer, unsigned len) - { - this->buffer = (unsigned char *)buffer; - this->len = len; - } - - void checkoffset(size_t offset, size_t nbytes); - - void remove(); // delete file -}; - -struct OutBuffer : Object -{ - unsigned char *data; - unsigned offset; - unsigned size; - - OutBuffer(); - ~OutBuffer(); - void *extractData(); - void mark(); - - void reserve(unsigned nbytes); - void setsize(unsigned size); - void reset(); - void write(const void *data, unsigned nbytes); - void writebstring(unsigned char *string); - void writestring(const char *string); - void writedstring(const char *string); - void writedstring(const wchar_t *string); - void prependstring(const char *string); - void writenl(); // write newline - void writeByte(unsigned b); - void writebyte(unsigned b) { writeByte(b); } - void writeUTF8(unsigned b); - void writedchar(unsigned b); - void prependbyte(unsigned b); - void writeword(unsigned w); - void writeUTF16(unsigned w); - void write4(unsigned w); - void write(OutBuffer *buf); - void write(Object *obj); - void fill0(unsigned nbytes); - void align(unsigned size); - void vprintf(const char *format, va_list args); - void printf(const char *format, ...); -#if M_UNICODE - void vprintf(const unsigned short *format, va_list args); - void printf(const unsigned short *format, ...); -#endif - void bracket(char left, char right); - unsigned bracket(unsigned i, const char *left, unsigned j, const char *right); - void spread(unsigned offset, unsigned nbytes); - unsigned insert(unsigned offset, const void *data, unsigned nbytes); - void remove(unsigned offset, unsigned nbytes); - char *toChars(); - char *extractString(); -}; - -struct Array : Object -{ - unsigned dim; - unsigned allocdim; - void **data; - - Array(); - ~Array(); - void mark(); - char *toChars(); - - void reserve(unsigned nentries); - void setDim(unsigned newdim); - void fixDim(); - void push(void *ptr); - void *pop(); - void shift(void *ptr); - void insert(unsigned index, void *ptr); - void insert(unsigned index, Array *a); - void append(Array *a); - void remove(unsigned i); - void zero(); - void *tos(); - void sort(); - Array *copy(); -}; - -struct Bits : Object -{ - unsigned bitdim; - unsigned allocdim; - unsigned *data; - - Bits(); - ~Bits(); - void mark(); - - void resize(unsigned bitdim); - - void set(unsigned bitnum); - void clear(unsigned bitnum); - int test(unsigned bitnum); - - void set(); - void clear(); - void copy(Bits *from); - Bits *clone(); - - void sub(Bits *b); -}; - -#endif diff -r f35a9a77d256 -r ff707c518ad7 dmd2/root/rmem.c --- a/dmd2/root/rmem.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ - -/* Copyright (c) 2000 Digital Mars */ -/* All Rights Reserved */ - -#include -#include -#include - -#if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 -#include "../root/rmem.h" -#else -#include "rmem.h" -#endif - -/* This implementation of the storage allocator uses the standard C allocation package. - */ - -Mem mem; - -void Mem::init() -{ -} - -char *Mem::strdup(const char *s) -{ - char *p; - - if (s) - { - p = ::strdup(s); - if (p) - return p; - error(); - } - return NULL; -} - -void *Mem::malloc(size_t size) -{ void *p; - - if (!size) - p = NULL; - else - { - p = ::malloc(size); - if (!p) - error(); - } - return p; -} - -void *Mem::calloc(size_t size, size_t n) -{ void *p; - - if (!size || !n) - p = NULL; - else - { - p = ::calloc(size, n); - if (!p) - error(); - } - return p; -} - -void *Mem::realloc(void *p, size_t size) -{ - if (!size) - { if (p) - { ::free(p); - p = NULL; - } - } - else if (!p) - { - p = ::malloc(size); - if (!p) - error(); - } - else - { - p = ::realloc(p, size); - if (!p) - error(); - } - return p; -} - -void Mem::free(void *p) -{ - if (p) - ::free(p); -} - -void *Mem::mallocdup(void *o, size_t size) -{ void *p; - - if (!size) - p = NULL; - else - { - p = ::malloc(size); - if (!p) - error(); - else - memcpy(p,o,size); - } - return p; -} - -void Mem::error() -{ - printf("Error: out of memory\n"); - exit(EXIT_FAILURE); -} - -void Mem::fullcollect() -{ -} - -void Mem::mark(void *pointer) -{ - (void) pointer; // necessary for VC /W4 -} - -/* =================================================== */ - -void * operator new(size_t m_size) -{ - void *p = malloc(m_size); - if (p) - return p; - printf("Error: out of memory\n"); - exit(EXIT_FAILURE); - return p; -} - -void operator delete(void *p) -{ - free(p); -} - - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/stringtable.c --- a/dmd2/stringtable.c Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ - -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#include -#include -#include - -#include "root.h" -#include "mem.h" -#include "dchar.h" -#include "lstring.h" -#include "stringtable.h" - -StringTable::StringTable(unsigned size) -{ - table = (void **)mem.calloc(size, sizeof(void *)); - tabledim = size; - count = 0; -} - -StringTable::~StringTable() -{ - unsigned i; - - // Zero out dangling pointers to help garbage collector. - // Should zero out StringEntry's too. - for (i = 0; i < count; i++) - table[i] = NULL; - - mem.free(table); - table = NULL; -} - -struct StringEntry -{ - StringEntry *left; - StringEntry *right; - hash_t hash; - - StringValue value; - - static StringEntry *alloc(const dchar *s, unsigned len); -}; - -StringEntry *StringEntry::alloc(const dchar *s, unsigned len) -{ - StringEntry *se; - - se = (StringEntry *) mem.calloc(1,sizeof(StringEntry) - sizeof(Lstring) + Lstring::size(len)); - se->value.lstring.length = len; - se->hash = Dchar::calcHash(s,len); - memcpy(se->value.lstring.string, s, len * sizeof(dchar)); - return se; -} - -void **StringTable::search(const dchar *s, unsigned len) -{ - hash_t hash; - unsigned u; - int cmp; - StringEntry **se; - - //printf("StringTable::search(%p,%d)\n",s,len); - hash = Dchar::calcHash(s,len); - u = hash % tabledim; - se = (StringEntry **)&table[u]; - //printf("\thash = %d, u = %d\n",hash,u); - while (*se) - { - cmp = (*se)->hash - hash; - if (cmp == 0) - { - cmp = (*se)->value.lstring.len() - len; - if (cmp == 0) - { - cmp = Dchar::memcmp(s,(*se)->value.lstring.toDchars(),len); - if (cmp == 0) - break; - } - } - if (cmp < 0) - se = &(*se)->left; - else - se = &(*se)->right; - } - //printf("\treturn %p, %p\n",se, (*se)); - return (void **)se; -} - -StringValue *StringTable::lookup(const dchar *s, unsigned len) -{ StringEntry *se; - - se = *(StringEntry **)search(s,len); - if (se) - return &se->value; - else - return NULL; -} - -StringValue *StringTable::update(const dchar *s, unsigned len) -{ StringEntry **pse; - StringEntry *se; - - pse = (StringEntry **)search(s,len); - se = *pse; - if (!se) // not in table: so create new entry - { - se = StringEntry::alloc(s, len); - *pse = se; - } - return &se->value; -} - -StringValue *StringTable::insert(const dchar *s, unsigned len) -{ StringEntry **pse; - StringEntry *se; - - pse = (StringEntry **)search(s,len); - se = *pse; - if (se) - return NULL; // error: already in table - else - { - se = StringEntry::alloc(s, len); - *pse = se; - } - return &se->value; -} - - - - diff -r f35a9a77d256 -r ff707c518ad7 dmd2/stringtable.h --- a/dmd2/stringtable.h Mon Jun 01 18:58:21 2009 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -// Copyright (c) 1999-2008 by Digital Mars -// All Rights Reserved -// written by Walter Bright -// http://www.digitalmars.com -// License for redistribution is by either the Artistic License -// in artistic.txt, or the GNU General Public License in gnu.txt. -// See the included readme.txt for details. - - -#ifndef STRINGTABLE_H -#define STRINGTABLE_H - -#if __SC__ -#pragma once -#endif - -#include "root.h" -#include "dchar.h" -#include "lstring.h" - -struct StringValue -{ - union - { int intvalue; - void *ptrvalue; - dchar *string; - }; - Lstring lstring; -}; - -struct StringTable : Object -{ - void **table; - unsigned count; - unsigned tabledim; - - StringTable(unsigned size = 37); - ~StringTable(); - - StringValue *lookup(const dchar *s, unsigned len); - StringValue *insert(const dchar *s, unsigned len); - StringValue *update(const dchar *s, unsigned len); - -private: - void **search(const dchar *s, unsigned len); -}; - -#endif