rendered paste bodyIndex: d/phobos/std/loader.d
===================================================================
--- d/phobos/std/loader.d (Revision 199)
+++ d/phobos/std/loader.d (Arbeitskopie)
@@ -858,8 +858,16 @@
this(uint errcode)
{
+ version (linux)
+ {
+ char[80] buf = void;
+ super(std.string.toString(strerror_r(errcode, buf.ptr, buf.length)).dup);
+ }
+ else
+ {
super(std.string.toString(strerror(errcode)).dup);
}
+ }
}
/// This class represents an executable image
Index: d/phobos/std/process.d
===================================================================
--- d/phobos/std/process.d (Revision 199)
+++ d/phobos/std/process.d (Arbeitskopie)
@@ -146,7 +146,11 @@
Lerror:
retval = getErrno;
- throw new Exception("Cannot spawn " ~ toString(pathname) ~ "; " ~ toString(strerror(retval)) ~ " [errno " ~ toString(retval) ~ "]");
+ char[80] buf = void;
+ throw new Exception(
+ "Cannot spawn " ~ toString(pathname) ~ "; "
+ ~ toString(strerror_r(retval, buf.ptr, buf.length))
+ ~ " [errno " ~ toString(retval) ~ "]");
} // _spawnvp
private
{
Index: d/phobos/std/stdio.d
===================================================================
--- d/phobos/std/stdio.d (Revision 199)
+++ d/phobos/std/stdio.d (Arbeitskopie)
@@ -104,7 +104,15 @@
}
this(uint errno)
- { char* s = strerror(errno);
+ {
+ version (linux)
+ { char[80] buf = void;
+ auto s = std.string.strerror_r(errno, buf.ptr, buf.length);
+ }
+ else
+ {
+ auto s = std.string.strerror(errno);
+ }
super(std.string.toString(s).dup);
}
Index: d/phobos/std/system.d
===================================================================
--- d/phobos/std/system.d (Revision 199)
+++ d/phobos/std/system.d (Arbeitskopie)
@@ -1,3 +1,4 @@
+// Written in the D programming language
/**
* Information about the target operating system, environment, and CPU
@@ -63,7 +64,7 @@
RedHatLinux,
}
- /// Byte order endiannes
+ /// Byte order endianness
enum Endian
{
@@ -73,7 +74,7 @@
version(LittleEndian)
{
- /// Native system endiannes
+ /// Native system endianness
Endian endian = Endian.LittleEndian;
}
else
Index: d/phobos/std/math.d
===================================================================
--- d/phobos/std/math.d (Revision 199)
+++ d/phobos/std/math.d (Arbeitskopie)
@@ -83,7 +83,7 @@
{
this(string msg)
{
- super(msg ~ "not implemented");
+ super(msg ~ " not implemented");
}
}
@@ -372,18 +372,18 @@
/***************
* Calculates the arc tangent of y / x,
- * returning a value ranging from -$(PI)/2 to $(PI)/2.
+ * returning a value ranging from -$(PI) to $(PI).
*
* $(TABLE_SV
* $(TR $(TH y) $(TH x) $(TH atan(y, x)))
* $(TR $(TD $(NAN)) $(TD anything) $(TD $(NAN)) )
* $(TR $(TD anything) $(TD $(NAN)) $(TD $(NAN)) )
* $(TR $(TD $(PLUSMN)0.0) $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) )
- * $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) )
+ * $(TR $(TD $(PLUSMN)0.0) $(TD +0.0) $(TD $(PLUSMN)0.0) )
* $(TR $(TD $(PLUSMN)0.0) $(TD $(LT)0.0) $(TD $(PLUSMN)$(PI)))
* $(TR $(TD $(PLUSMN)0.0) $(TD -0.0) $(TD $(PLUSMN)$(PI)))
* $(TR $(TD $(GT)0.0) $(TD $(PLUSMN)0.0) $(TD $(PI)/2) )
- * $(TR $(TD $(LT)0.0) $(TD $(PLUSMN)0.0) $(TD $(PI)/2))
+ * $(TR $(TD $(LT)0.0) $(TD $(PLUSMN)0.0) $(TD -$(PI)/2) )
* $(TR $(TD $(GT)0.0) $(TD $(INFIN)) $(TD $(PLUSMN)0.0) )
* $(TR $(TD $(PLUSMN)$(INFIN)) $(TD anything) $(TD $(PLUSMN)$(PI)/2))
* $(TR $(TD $(GT)0.0) $(TD -$(INFIN)) $(TD $(PLUSMN)$(PI)) )
@@ -906,6 +906,8 @@
* $(TR $(TD $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) )
* $(TR $(TD $(PLUSMN)0.0) $(TD $(PLUSMN)0.0) )
* )
+ *
+ * Note: Not supported on windows
*/
real scalbn(real x, int n)
{
@@ -1181,6 +1183,8 @@
/***************************************
* Rounds x to the nearest integer value, using the current rounding
* mode.
+ *
+ * Note: Not supported on windows
*/
long lrint(real x)
{
@@ -1234,6 +1238,8 @@
*
* If the fractional part of x is exactly 0.5, the return value is rounded
* away from zero.
+ *
+ * Note: Not supported on windows
*/
long lround(real x)
{
@@ -1287,6 +1293,8 @@
* $(TR $(TD anything) $(TD $(PLUSMN)0.0) $(TD $(NAN)) $(TD ?) $(TD yes))
* $(TR $(TD != $(PLUSMN)$(INFIN)) $(TD $(PLUSMN)$(INFIN)) $(TD x) $(TD ?) $(TD no))
* )
+ *
+ * Note: remquo not supported on windows
*/
real remainder(real x, real y) { return std.c.math.remainderl(x, y); }
@@ -1498,6 +1506,8 @@
* the function result is infinite. The FE_INEXACT and FE_UNDERFLOW
* exceptions will be raised if the function value is subnormal, and x is
* not equal to y.
+ *
+ * Note: real nextafter(real, real) not supported on windows
*/
real nextafter(real x, real y)
{
Index: d/phobos/std/stream.d
===================================================================
--- d/phobos/std/stream.d (Revision 199)
+++ d/phobos/std/stream.d (Arbeitskopie)
@@ -2130,7 +2130,7 @@
}
/// creates file in requested mode
- void create(char[] filename, FileMode mode = FileMode.Out) {
+ void create(char[] filename, FileMode mode = FileMode.OutNew) {
File sf = cast(File)s;
sf.create(filename,mode);
resetSource();
Index: d/phobos/std/c/string.d
===================================================================
--- d/phobos/std/c/string.d (Revision 199)
+++ d/phobos/std/c/string.d (Arbeitskopie)
@@ -68,3 +68,9 @@
{
int memicmp(char* s1, char* s2, size_t n); ///
}
+
+version (linux)
+{
+ char* strerror_r(int errnum, char* buf, size_t buflen); ///
+}
+
Index: d/phobos/std/c/windows/winsock.d
===================================================================
--- d/phobos/std/c/windows/winsock.d (Revision 199)
+++ d/phobos/std/c/windows/winsock.d (Arbeitskopie)
@@ -381,6 +381,7 @@
MSG_OOB = 0x1,
MSG_PEEK = 0x2,
MSG_DONTROUTE = 0x4,
+ MSG_NOSIGNAL = 0x0, /// not supported on win32, would be 0x4000 if it was
}
Index: d/phobos/std/c/windows/windows.d
===================================================================
--- d/phobos/std/c/windows/windows.d (Revision 199)
+++ d/phobos/std/c/windows/windows.d (Arbeitskopie)
@@ -250,8 +250,11 @@
FILE_VOLUME_IS_COMPRESSED = 0x00008000,
}
-const DWORD MAILSLOT_NO_MESSAGE = cast(DWORD)-1;
-const DWORD MAILSLOT_WAIT_FOREVER = cast(DWORD)-1;
+enum
+{
+ MAILSLOT_NO_MESSAGE = cast(DWORD)-1,
+ MAILSLOT_WAIT_FOREVER = cast(DWORD)-1,
+}
enum : uint
{
@@ -275,9 +278,13 @@
}
const HANDLE INVALID_HANDLE_VALUE = cast(HANDLE)-1;
-const DWORD INVALID_SET_FILE_POINTER = cast(DWORD)-1;
-const DWORD INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF;
+enum : DWORD
+{
+ INVALID_SET_FILE_POINTER = cast(DWORD)-1,
+ INVALID_FILE_SIZE = cast(DWORD)0xFFFFFFFF,
+}
+
struct OVERLAPPED {
DWORD Internal;
DWORD InternalHigh;
@@ -326,6 +333,13 @@
wchar cAlternateFileName[ 14 ];
}
+enum
+{
+ STD_INPUT_HANDLE = cast(DWORD)-10,
+ STD_OUTPUT_HANDLE = cast(DWORD)-11,
+ STD_ERROR_HANDLE = cast(DWORD)-12,
+}
+
export
{
BOOL SetCurrentDirectoryA(LPCSTR lpPathName);
@@ -428,8 +442,11 @@
// Key creation/open disposition
//
-const int REG_CREATED_NEW_KEY = 0x00000001; // New Registry Key created
-const int REG_OPENED_EXISTING_KEY = 0x00000002; // Existing Key opened
+enum : int
+{
+ REG_CREATED_NEW_KEY = 0x00000001, // New Registry Key created
+ REG_OPENED_EXISTING_KEY = 0x00000002, // Existing Key opened
+}
//
@@ -1102,6 +1119,7 @@
export HANDLE GetCurrentThread();
export BOOL GetProcessTimes(HANDLE hProcess, LPFILETIME lpCreationTime, LPFILETIME lpExitTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime);
export HANDLE GetCurrentProcess();
+export DWORD GetCurrentProcessId();
export BOOL DuplicateHandle (HANDLE sourceProcess, HANDLE sourceThread,
HANDLE targetProcessHandle, HANDLE *targetHandle, DWORD access,
BOOL inheritHandle, DWORD options);
@@ -2083,11 +2101,15 @@
COLOR_BTNHILIGHT = COLOR_BTNHIGHLIGHT,
}
-const int CW_USEDEFAULT = cast(int)0x80000000;
+enum : int
+{
+ CW_USEDEFAULT = cast(int)0x80000000
+}
+
/*
* Special value for CreateWindow, et al.
*/
-const HWND HWND_DESKTOP = (cast(HWND)0);
+const HWND HWND_DESKTOP = cast(HWND)0;
export ATOM RegisterClassA(WNDCLASSA *lpWndClass);
@@ -2713,10 +2735,328 @@
export int wsprintfA(LPSTR, LPCSTR, ...);
export int wsprintfW(LPWSTR, LPCWSTR, ...);
-const uint INFINITE = uint.max;
-const uint WAIT_OBJECT_0 = 0;
+enum : uint
+{
+ INFINITE = uint.max,
+ WAIT_OBJECT_0 = 0,
+}
export HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, LONG lMaximumCount, LPCTSTR lpName);
export HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTR lpName);
export BOOL ReleaseSemaphore(HANDLE hSemaphore, LONG lReleaseCount, LPLONG lpPreviousCount);
+
+struct COORD {
+ SHORT X;
+ SHORT Y;
}
+alias COORD *PCOORD;
+
+struct SMALL_RECT {
+ SHORT Left;
+ SHORT Top;
+ SHORT Right;
+ SHORT Bottom;
+}
+alias SMALL_RECT *PSMALL_RECT;
+
+struct KEY_EVENT_RECORD {
+ BOOL bKeyDown;
+ WORD wRepeatCount;
+ WORD wVirtualKeyCode;
+ WORD wVirtualScanCode;
+ union {
+ WCHAR UnicodeChar;
+ CHAR AsciiChar;
+ }
+ DWORD dwControlKeyState;
+}
+alias KEY_EVENT_RECORD *PKEY_EVENT_RECORD;
+
+//
+// ControlKeyState flags
+//
+
+enum
+{
+ RIGHT_ALT_PRESSED = 0x0001, // the right alt key is pressed.
+ LEFT_ALT_PRESSED = 0x0002, // the left alt key is pressed.
+ RIGHT_CTRL_PRESSED = 0x0004, // the right ctrl key is pressed.
+ LEFT_CTRL_PRESSED = 0x0008, // the left ctrl key is pressed.
+ SHIFT_PRESSED = 0x0010, // the shift key is pressed.
+ NUMLOCK_ON = 0x0020, // the numlock light is on.
+ SCROLLLOCK_ON = 0x0040, // the scrolllock light is on.
+ CAPSLOCK_ON = 0x0080, // the capslock light is on.
+ ENHANCED_KEY = 0x0100, // the key is enhanced.
+}
+
+struct MOUSE_EVENT_RECORD {
+ COORD dwMousePosition;
+ DWORD dwButtonState;
+ DWORD dwControlKeyState;
+ DWORD dwEventFlags;
+}
+alias MOUSE_EVENT_RECORD *PMOUSE_EVENT_RECORD;
+
+//
+// ButtonState flags
+//
+enum
+{
+ FROM_LEFT_1ST_BUTTON_PRESSED = 0x0001,
+ RIGHTMOST_BUTTON_PRESSED = 0x0002,
+ FROM_LEFT_2ND_BUTTON_PRESSED = 0x0004,
+ FROM_LEFT_3RD_BUTTON_PRESSED = 0x0008,
+ FROM_LEFT_4TH_BUTTON_PRESSED = 0x0010,
+}
+
+//
+// EventFlags
+//
+
+enum
+{
+ MOUSE_MOVED = 0x0001,
+ DOUBLE_CLICK = 0x0002,
+}
+
+struct WINDOW_BUFFER_SIZE_RECORD {
+ COORD dwSize;
+}
+alias WINDOW_BUFFER_SIZE_RECORD *PWINDOW_BUFFER_SIZE_RECORD;
+
+struct MENU_EVENT_RECORD {
+ UINT dwCommandId;
+}
+alias MENU_EVENT_RECORD *PMENU_EVENT_RECORD;
+
+struct FOCUS_EVENT_RECORD {
+ BOOL bSetFocus;
+}
+alias FOCUS_EVENT_RECORD *PFOCUS_EVENT_RECORD;
+
+struct INPUT_RECORD {
+ WORD EventType;
+ union {
+ KEY_EVENT_RECORD KeyEvent;
+ MOUSE_EVENT_RECORD MouseEvent;
+ WINDOW_BUFFER_SIZE_RECORD WindowBufferSizeEvent;
+ MENU_EVENT_RECORD MenuEvent;
+ FOCUS_EVENT_RECORD FocusEvent;
+ }
+}
+alias INPUT_RECORD *PINPUT_RECORD;
+
+//
+// EventType flags:
+//
+
+enum
+{
+ KEY_EVENT = 0x0001, // Event contains key event record
+ MOUSE_EVENT = 0x0002, // Event contains mouse event record
+ WINDOW_BUFFER_SIZE_EVENT = 0x0004, // Event contains window change event record
+ MENU_EVENT = 0x0008, // Event contains menu event record
+ FOCUS_EVENT = 0x0010, // event contains focus change
+}
+
+struct CHAR_INFO {
+ union {
+ WCHAR UnicodeChar;
+ CHAR AsciiChar;
+ }
+ WORD Attributes;
+}
+alias CHAR_INFO *PCHAR_INFO;
+
+//
+// Attributes flags:
+//
+
+enum
+{
+ FOREGROUND_BLUE = 0x0001, // text color contains blue.
+ FOREGROUND_GREEN = 0x0002, // text color contains green.
+ FOREGROUND_RED = 0x0004, // text color contains red.
+ FOREGROUND_INTENSITY = 0x0008, // text color is intensified.
+ BACKGROUND_BLUE = 0x0010, // background color contains blue.
+ BACKGROUND_GREEN = 0x0020, // background color contains green.
+ BACKGROUND_RED = 0x0040, // background color contains red.
+ BACKGROUND_INTENSITY = 0x0080, // background color is intensified.
+}
+
+struct CONSOLE_SCREEN_BUFFER_INFO {
+ COORD dwSize;
+ COORD dwCursorPosition;
+ WORD wAttributes;
+ SMALL_RECT srWindow;
+ COORD dwMaximumWindowSize;
+}
+alias CONSOLE_SCREEN_BUFFER_INFO *PCONSOLE_SCREEN_BUFFER_INFO;
+
+struct CONSOLE_CURSOR_INFO {
+ DWORD dwSize;
+ BOOL bVisible;
+}
+alias CONSOLE_CURSOR_INFO *PCONSOLE_CURSOR_INFO;
+
+enum
+{
+ ENABLE_PROCESSED_INPUT = 0x0001,
+ ENABLE_LINE_INPUT = 0x0002,
+ ENABLE_ECHO_INPUT = 0x0004,
+ ENABLE_WINDOW_INPUT = 0x0008,
+ ENABLE_MOUSE_INPUT = 0x0010,
+}
+
+enum
+{
+ ENABLE_PROCESSED_OUTPUT = 0x0001,
+ ENABLE_WRAP_AT_EOL_OUTPUT = 0x0002,
+}
+
+BOOL PeekConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL PeekConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL ReadConsoleInputA(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL ReadConsoleInputW(HANDLE hConsoleInput, PINPUT_RECORD lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsRead);
+BOOL WriteConsoleInputA(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten);
+BOOL WriteConsoleInputW(HANDLE hConsoleInput, INPUT_RECORD *lpBuffer, DWORD nLength, LPDWORD lpNumberOfEventsWritten);
+BOOL ReadConsoleOutputA(HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion);
+BOOL ReadConsoleOutputW(HANDLE hConsoleOutput, PCHAR_INFO lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpReadRegion);
+BOOL WriteConsoleOutputA(HANDLE hConsoleOutput, CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion);
+BOOL WriteConsoleOutputW(HANDLE hConsoleOutput, CHAR_INFO *lpBuffer, COORD dwBufferSize, COORD dwBufferCoord, PSMALL_RECT lpWriteRegion);
+BOOL ReadConsoleOutputCharacterA(HANDLE hConsoleOutput, LPSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead);
+BOOL ReadConsoleOutputCharacterW(HANDLE hConsoleOutput, LPWSTR lpCharacter, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfCharsRead);
+BOOL ReadConsoleOutputAttribute(HANDLE hConsoleOutput, LPWORD lpAttribute, DWORD nLength, COORD dwReadCoord, LPDWORD lpNumberOfAttrsRead);
+BOOL WriteConsoleOutputCharacterA(HANDLE hConsoleOutput, LPCSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL WriteConsoleOutputCharacterW(HANDLE hConsoleOutput, LPCWSTR lpCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL WriteConsoleOutputAttribute(HANDLE hConsoleOutput, WORD *lpAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten);
+BOOL FillConsoleOutputCharacterA(HANDLE hConsoleOutput, CHAR cCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL FillConsoleOutputCharacterW(HANDLE hConsoleOutput, WCHAR cCharacter, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfCharsWritten);
+BOOL FillConsoleOutputAttribute(HANDLE hConsoleOutput, WORD wAttribute, DWORD nLength, COORD dwWriteCoord, LPDWORD lpNumberOfAttrsWritten);
+BOOL GetConsoleMode(HANDLE hConsoleHandle, LPDWORD lpMode);
+BOOL GetNumberOfConsoleInputEvents(HANDLE hConsoleInput, LPDWORD lpNumberOfEvents);
+BOOL GetConsoleScreenBufferInfo(HANDLE hConsoleOutput, PCONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
+COORD GetLargestConsoleWindowSize( HANDLE hConsoleOutput);
+BOOL GetConsoleCursorInfo(HANDLE hConsoleOutput, PCONSOLE_CURSOR_INFO lpConsoleCursorInfo);
+BOOL GetNumberOfConsoleMouseButtons( LPDWORD lpNumberOfMouseButtons);
+BOOL SetConsoleMode(HANDLE hConsoleHandle, DWORD dwMode);
+BOOL SetConsoleActiveScreenBuffer(HANDLE hConsoleOutput);
+BOOL FlushConsoleInputBuffer(HANDLE hConsoleInput);
+BOOL SetConsoleScreenBufferSize(HANDLE hConsoleOutput, COORD dwSize);
+BOOL SetConsoleCursorPosition(HANDLE hConsoleOutput, COORD dwCursorPosition);
+BOOL SetConsoleCursorInfo(HANDLE hConsoleOutput, CONSOLE_CURSOR_INFO *lpConsoleCursorInfo);
+BOOL ScrollConsoleScreenBufferA(HANDLE hConsoleOutput, SMALL_RECT *lpScrollRectangle, SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, CHAR_INFO *lpFill);
+BOOL ScrollConsoleScreenBufferW(HANDLE hConsoleOutput, SMALL_RECT *lpScrollRectangle, SMALL_RECT *lpClipRectangle, COORD dwDestinationOrigin, CHAR_INFO *lpFill);
+BOOL SetConsoleWindowInfo(HANDLE hConsoleOutput, BOOL bAbsolute, SMALL_RECT *lpConsoleWindow);
+BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);
+alias BOOL(*PHANDLER_ROUTINE)(DWORD CtrlType);
+BOOL SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, BOOL Add);
+BOOL GenerateConsoleCtrlEvent( DWORD dwCtrlEvent, DWORD dwProcessGroupId);
+BOOL AllocConsole();
+BOOL FreeConsole();
+DWORD GetConsoleTitleA(LPSTR lpConsoleTitle, DWORD nSize);
+DWORD GetConsoleTitleW(LPWSTR lpConsoleTitle, DWORD nSize);
+BOOL SetConsoleTitleA(LPCSTR lpConsoleTitle);
+BOOL SetConsoleTitleW(LPCWSTR lpConsoleTitle);
+BOOL ReadConsoleA(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved);
+BOOL ReadConsoleW(HANDLE hConsoleInput, LPVOID lpBuffer, DWORD nNumberOfCharsToRead, LPDWORD lpNumberOfCharsRead, LPVOID lpReserved);
+BOOL WriteConsoleA(HANDLE hConsoleOutput, void *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
+BOOL WriteConsoleW(HANDLE hConsoleOutput, void *lpBuffer, DWORD nNumberOfCharsToWrite, LPDWORD lpNumberOfCharsWritten, LPVOID lpReserved);
+HANDLE CreateConsoleScreenBuffer(DWORD dwDesiredAccess, DWORD dwShareMode, SECURITY_ATTRIBUTES *lpSecurityAttributes, DWORD dwFlags, LPVOID lpScreenBufferData);
+UINT GetConsoleCP();
+BOOL SetConsoleCP( UINT wCodePageID);
+UINT GetConsoleOutputCP();
+BOOL SetConsoleOutputCP(UINT wCodePageID);
+
+enum : int
+{
+ CONSOLE_TEXTMODE_BUFFER = 1,
+}
+
+enum
+{
+ SM_CXSCREEN = 0,
+ SM_CYSCREEN = 1,
+ SM_CXVSCROLL = 2,
+ SM_CYHSCROLL = 3,
+ SM_CYCAPTION = 4,
+ SM_CXBORDER = 5,
+ SM_CYBORDER = 6,
+ SM_CXDLGFRAME = 7,
+ SM_CYDLGFRAME = 8,
+ SM_CYVTHUMB = 9,
+ SM_CXHTHUMB = 10,
+ SM_CXICON = 11,
+ SM_CYICON = 12,
+ SM_CXCURSOR = 13,
+ SM_CYCURSOR = 14,
+ SM_CYMENU = 15,
+ SM_CXFULLSCREEN = 16,
+ SM_CYFULLSCREEN = 17,
+ SM_CYKANJIWINDOW = 18,
+ SM_MOUSEPRESENT = 19,
+ SM_CYVSCROLL = 20,
+ SM_CXHSCROLL = 21,
+ SM_DEBUG = 22,
+ SM_SWAPBUTTON = 23,
+ SM_RESERVED1 = 24,
+ SM_RESERVED2 = 25,
+ SM_RESERVED3 = 26,
+ SM_RESERVED4 = 27,
+ SM_CXMIN = 28,
+ SM_CYMIN = 29,
+ SM_CXSIZE = 30,
+ SM_CYSIZE = 31,
+ SM_CXFRAME = 32,
+ SM_CYFRAME = 33,
+ SM_CXMINTRACK = 34,
+ SM_CYMINTRACK = 35,
+ SM_CXDOUBLECLK = 36,
+ SM_CYDOUBLECLK = 37,
+ SM_CXICONSPACING = 38,
+ SM_CYICONSPACING = 39,
+ SM_MENUDROPALIGNMENT = 40,
+ SM_PENWINDOWS = 41,
+ SM_DBCSENABLED = 42,
+ SM_CMOUSEBUTTONS = 43,
+
+
+ SM_CXFIXEDFRAME = SM_CXDLGFRAME,
+ SM_CYFIXEDFRAME = SM_CYDLGFRAME,
+ SM_CXSIZEFRAME = SM_CXFRAME,
+ SM_CYSIZEFRAME = SM_CYFRAME,
+
+ SM_SECURE = 44,
+ SM_CXEDGE = 45,
+ SM_CYEDGE = 46,
+ SM_CXMINSPACING = 47,
+ SM_CYMINSPACING = 48,
+ SM_CXSMICON = 49,
+ SM_CYSMICON = 50,
+ SM_CYSMCAPTION = 51,
+ SM_CXSMSIZE = 52,
+ SM_CYSMSIZE = 53,
+ SM_CXMENUSIZE = 54,
+ SM_CYMENUSIZE = 55,
+ SM_ARRANGE = 56,
+ SM_CXMINIMIZED = 57,
+ SM_CYMINIMIZED = 58,
+ SM_CXMAXTRACK = 59,
+ SM_CYMAXTRACK = 60,
+ SM_CXMAXIMIZED = 61,
+ SM_CYMAXIMIZED = 62,
+ SM_NETWORK = 63,
+ SM_CLEANBOOT = 67,
+ SM_CXDRAG = 68,
+ SM_CYDRAG = 69,
+ SM_SHOWSOUNDS = 70,
+ SM_CXMENUCHECK = 71,
+ SM_CYMENUCHECK = 72,
+ SM_SLOWMACHINE = 73,
+ SM_MIDEASTENABLED = 74,
+ SM_CMETRICS = 75,
+}
+
+int GetSystemMetrics(int nIndex);
+
+}
Index: d/phobos/std/c/linux/socket.d
===================================================================
--- d/phobos/std/c/linux/socket.d (Revision 199)
+++ d/phobos/std/c/linux/socket.d (Arbeitskopie)
@@ -235,6 +235,7 @@
MSG_OOB = 0x1,
MSG_PEEK = 0x2,
MSG_DONTROUTE = 0x4,
+ MSG_NOSIGNAL = 0x4000,
}
Index: d/phobos/std/c/stdlib.d
===================================================================
--- d/phobos/std/c/stdlib.d (Revision 199)
+++ d/phobos/std/c/stdlib.d (Arbeitskopie)
@@ -1,6 +1,7 @@
/**
* C's <stdlib.h>
- * Authors: Walter Bright, Digital Mars, www.digitalmars.com
+ * D Programming Language runtime library
+ * Authors: Walter Bright, Digital Mars, http://www.digitalmars.com
* License: Public Domain
* Macros:
* WIKI=Phobos/StdCStdlib
Index: d/phobos/std/zlib.d
===================================================================
--- d/phobos/std/zlib.d (Revision 199)
+++ d/phobos/std/zlib.d (Arbeitskopie)
@@ -20,7 +20,7 @@
//debug=zlib; // uncomment to turn on debugging printf's
-private import etc.c.zlib, std.stdint, std.gc;
+private import etc.c.zlib, std.stdint;
// Values for 'mode'
@@ -117,13 +117,13 @@
body
{
int err;
- void[] destbuf;
+ ubyte[] destbuf;
Culong_t destlen;
destlen = srcbuf.length + ((srcbuf.length + 1023) / 1024) + 12;
- destbuf = new void[destlen];
+ destbuf = new ubyte[destlen];
std.gc.hasNoPointers(destbuf.ptr);
- err = etc.c.zlib.compress2(cast(ubyte *)destbuf, &destlen, cast(ubyte *)srcbuf, srcbuf.length, level);
+ err = etc.c.zlib.compress2(destbuf.ptr, &destlen, cast(ubyte *)srcbuf, srcbuf.length, level);
if (err)
{ delete destbuf;
throw new ZlibException(err);
@@ -153,7 +153,7 @@
void[] uncompress(void[] srcbuf, size_t destlen = 0u, int winbits = 15)
{
int err;
- void[] destbuf;
+ ubyte[] destbuf;
if (!destlen)
destlen = srcbuf.length * 2 + 1;
@@ -162,13 +162,12 @@
{
etc.c.zlib.z_stream zs;
- destbuf = new void[destlen];
- std.gc.hasNoPointers(destbuf.ptr);
+ destbuf = new ubyte[destlen];
zs.next_in = cast(ubyte*) srcbuf;
zs.avail_in = srcbuf.length;
- zs.next_out = cast(ubyte*)destbuf;
+ zs.next_out = destbuf.ptr;
zs.avail_out = destlen;
err = etc.c.zlib.inflateInit2(&zs, winbits);
@@ -291,7 +290,7 @@
*/
void[] compress(void[] buf)
{ int err;
- void[] destbuf;
+ ubyte[] destbuf;
if (buf.length == 0)
return null;
@@ -304,9 +303,8 @@
inited = 1;
}
- destbuf = new void[zs.avail_in + buf.length];
- std.gc.hasNoPointers(destbuf.ptr);
- zs.next_out = cast(ubyte*) destbuf.ptr;
+ destbuf = new ubyte[zs.avail_in + buf.length];
+ zs.next_out = destbuf.ptr;
zs.avail_out = destbuf.length;
if (zs.avail_in)
@@ -455,7 +453,7 @@
}
body
{ int err;
- void[] destbuf;
+ ubyte[] destbuf;
if (buf.length == 0)
return null;
@@ -470,9 +468,8 @@
if (!destbufsize)
destbufsize = buf.length * 2;
- destbuf = new void[zs.avail_in * 2 + destbufsize];
- std.gc.hasNoPointers(destbuf.ptr);
- zs.next_out = cast(ubyte*) destbuf;
+ destbuf = new ubyte[zs.avail_in * 2 + destbufsize];
+ zs.next_out = destbuf.ptr;
zs.avail_out = destbuf.length;
if (zs.avail_in)
@@ -506,8 +503,8 @@
}
body
{
- void[] extra;
- void[] destbuf;
+ ubyte[] extra;
+ ubyte[] destbuf;
int err;
done = 1;
@@ -515,9 +512,8 @@
return null;
L1:
- destbuf = new void[zs.avail_in * 2 + 100];
- std.gc.hasNoPointers(destbuf.ptr);
- zs.next_out = cast(ubyte*) destbuf;
+ destbuf = new ubyte[zs.avail_in * 2 + 100];
+ zs.next_out = destbuf.ptr;
zs.avail_out = destbuf.length;
err = etc.c.zlib.inflate(&zs, Z_NO_FLUSH);
@@ -533,7 +529,7 @@
err = Z_BUF_ERROR;
error(err);
}
- destbuf = cast(void[])((cast(ubyte*)destbuf)[0 .. zs.next_out - cast(ubyte*)destbuf]);
+ destbuf = destbuf.ptr[0 .. zs.next_out - destbuf.ptr];
err = etc.c.zlib.inflateEnd(&zs);
inited = 0;
if (err)
Index: d/phobos/std/conv.d
===================================================================
--- d/phobos/std/conv.d (Revision 199)
+++ d/phobos/std/conv.d (Arbeitskopie)
@@ -1,4 +1,3 @@
-
// Written in the D programming language.
/*
@@ -944,6 +943,11 @@
// nan
f = toFloat("nan");
assert(toString(f) == toString(float.nan));
+
+ bool ok = false;
+ try toFloat("\x00");
+ catch (ConvError e) ok = true;
+ assert(ok);
}
/*******************************************************
@@ -1013,6 +1017,11 @@
d = toDouble("nan");
assert(toString(d) == toString(double.nan));
//assert(cast(real)d == cast(real)double.nan);
+
+ bool ok = false;
+ try toDouble("\x00");
+ catch (ConvError e) ok = true;
+ assert(ok);
}
/*******************************************************
@@ -1086,6 +1095,11 @@
r = toReal(toString(real.nan));
assert(toString(r) == toString(real.nan));
//assert(r == real.nan);
+
+ bool ok = false;
+ try toReal("\x00");
+ catch (ConvError e) ok = true;
+ assert(ok);
}
version (none)
Index: d/phobos/std/thread.d
===================================================================
--- d/phobos/std/thread.d (Revision 199)
+++ d/phobos/std/thread.d (Arbeitskopie)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2002-2006 by Digital Mars, www.digitalmars.com
+ * Copyright (C) 2002-2007 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
@@ -40,6 +40,8 @@
module std.thread;
+import std.c.stdio;
+
//debug=thread;
/* ================================ Win32 ================================= */
@@ -56,6 +58,8 @@
stdfp start_addr, void* arglist, uint initflag,
thread_id* thrdaddr);
+private const uint WAIT_TIMEOUT = 258;
+
/**
* The type of the thread handle used by the operating system.
* For Windows, it is equivalent to a HANDLE from windows.d.
@@ -69,7 +73,7 @@
*/
class ThreadError : Error
{
- this(char[] s)
+ this(string s)
{
super("Thread error: " ~ s);
}
@@ -110,6 +114,17 @@
}
/**
+ * Destructor
+ *
+ * If the thread hasn't been joined yet, detach it.
+ */
+ ~this()
+ {
+ if (state != TS.FINISHED)
+ CloseHandle(hdl);
+ }
+
+ /**
* The handle to this thread assigned by the operating system. This is set
* to thread_id.init if the thread hasn't been started yet.
*/
@@ -123,11 +138,11 @@
*/
void start()
{
+ synchronized (Thread.classinfo)
+ {
if (state != TS.INITIAL)
error("already started");
- synchronized (threadLock)
- {
for (int i = 0; 1; i++)
{
if (i == allThreads.length)
@@ -141,17 +156,19 @@
}
}
nthreads++;
- }
state = TS.RUNNING;
hdl = _beginthreadex(null, cast(uint)stacksize, &threadstart, cast(void*)this, 0, &id);
if (hdl == cast(thread_hdl)0)
- { state = TS.TERMINATED;
+ {
allThreads[idx] = null;
+ nthreads--;
+ state = TS.FINISHED;
idx = -1;
error("failed to start");
}
}
+ }
/**
* Entry point for a thread. If not overridden, it calls the function
@@ -176,12 +193,15 @@
*/
void wait()
{
- if (this is getThis())
+ if (isSelf)
error("wait on self");
- if (state == TS.RUNNING)
+ if (state != TS.FINISHED)
{ DWORD dw;
dw = WaitForSingleObject(hdl, 0xFFFFFFFF);
+ state = TS.FINISHED;
+ CloseHandle(hdl);
+ hdl = null;
}
}
@@ -193,12 +213,18 @@
*/
void wait(uint milliseconds)
{
- if (this is getThis())
+ if (isSelf)
error("wait on self");
- if (state == TS.RUNNING)
+ if (state != TS.FINISHED)
{ DWORD dw;
dw = WaitForSingleObject(hdl, milliseconds);
+ if (dw != WAIT_TIMEOUT)
+ {
+ state = TS.FINISHED;
+ CloseHandle(hdl);
+ hdl = null;
+ }
}
}
@@ -209,7 +235,8 @@
{
INITIAL, /// The thread hasn't been started yet.
RUNNING, /// The thread is running or paused.
- TERMINATED /// The thread has ended.
+ TERMINATED, /// The thread has ended.
+ FINISHED /// The thread has been cleaned up
}
/**
@@ -228,7 +255,8 @@
INCREASE, /// Increase thread priority
DECREASE, /// Decrease thread priority
IDLE, /// Assign thread low priority
- CRITICAL /// Assign thread high priority
+ CRITICAL, /// Assign thread high priority
+ NORMAL
}
/**
@@ -253,6 +281,9 @@
case PRIORITY.CRITICAL:
nPriority = THREAD_PRIORITY_TIME_CRITICAL;
break;
+ case PRIORITY.NORMAL:
+ nPriority = THREAD_PRIORITY_NORMAL;
+ break;
default:
assert(0);
}
@@ -276,13 +307,8 @@
*/
static Thread getThis()
{
- thread_id id;
- Thread result;
-
//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
- synchronized (threadLock)
- {
- id = GetCurrentThreadId();
+ thread_id id = GetCurrentThreadId();
for (int i = 0; i < allThreadsDim; i++)
{
Thread t = allThreads[i];
@@ -291,10 +317,8 @@
return t;
}
}
- }
printf("didn't find it\n");
- assert(result);
- return result;
+ assert(0);
}
/**
@@ -302,7 +326,7 @@
*/
static Thread[] getAll()
{
- return allThreads[0 .. allThreadsDim];
+ synchronized (Thread.classinfo) return allThreads[0 .. allThreadsDim];
}
/**
@@ -328,38 +352,42 @@
*/
static void pauseAll()
{
+ synchronized (Thread.classinfo)
+ {
if (nthreads > 1)
{
- Thread tthis = getThis();
+ thread_id thisid = GetCurrentThreadId();
for (int i = 0; i < allThreadsDim; i++)
- { Thread t;
-
- t = allThreads[i];
- if (t && t !is tthis && t.state == TS.RUNNING)
+ {
+ Thread t = allThreads[i];
+ if (t && t.id != thisid && t.state == TS.RUNNING)
t.pause();
}
}
}
+ }
/**
* Resume execution of all paused threads.
*/
static void resumeAll()
{
+ synchronized (Thread.classinfo)
+ {
if (nthreads > 1)
{
- Thread tthis = getThis();
+ thread_id thisid = GetCurrentThreadId();
for (int i = 0; i < allThreadsDim; i++)
- { Thread t;
-
- t = allThreads[i];
- if (t && t !is tthis && t.state == TS.RUNNING)
+ {
+ Thread t = allThreads[i];
+ if (t && t.id != thisid && t.state == TS.RUNNING)
t.resume();
}
}
}
+ }
/**
* Give up the remainder of this thread's time slice.
@@ -377,7 +405,6 @@
private:
static uint allThreadsDim;
- static Object threadLock;
static Thread[0x400] allThreads; // length matches value in C runtime
TS state;
@@ -390,7 +417,7 @@
int delegate() dg;
- void error(char[] msg)
+ void error(string msg)
{
throw new ThreadError(msg);
}
@@ -413,16 +440,18 @@
}
catch (Object o)
{
- printf("Error: ");
- o.print();
+ fprintf(stderr, "Error: %.*s\n", o.toString());
result = 1;
}
debug (thread) printf("Ending thread %d\n", t.idx);
+ synchronized (Thread.classinfo)
+ {
+ allThreads[t.idx] = null;
+ nthreads--;
t.state = TS.TERMINATED;
- allThreads[t.idx] = null;
t.idx = -1;
- nthreads--;
+ }
return result;
}
@@ -433,8 +462,6 @@
public static void thread_init()
{
- threadLock = new Object();
-
Thread t = new Thread();
t.state = TS.RUNNING;
@@ -536,7 +563,7 @@
class ThreadError : Error
{
- this(char[] s)
+ this(string s)
{
super("Thread error: " ~ s);
}
@@ -568,6 +595,8 @@
{
pthread_cond_destroy(&waitCond);
pthread_mutex_destroy(&waitMtx);
+ if (state != TS.FINISHED)
+ pthread_detach(id);
}
pthread_t id;
@@ -579,7 +608,7 @@
if (state != TS.INITIAL)
error("already started");
- synchronized (threadLock)
+ synchronized (Thread.classinfo)
{
for (int i = 0; 1; i++)
{
@@ -596,14 +625,13 @@
nthreads++;
state = TS.RUNNING;
- int result;
//printf("creating thread x%x\n", this);
//result = pthread_create(&id, null, &threadstart, this);
// Create with thread attributes to allow non-default stack size - Dave Fladebo
- result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this);
+ int result = pthread_create(&id, &threadAttrs, &threadstart, cast(void*)this);
if (result)
- { state = TS.TERMINATED;
- allThreads[idx] = null;
+ { state = TS.FINISHED;
+ synchronized (Thread.classinfo) allThreads[idx] = null;
idx = -1;
error("failed to start"); // BUG: should report errno
}
@@ -622,25 +650,15 @@
void wait()
{
- if (this is getThis())
+ if (isSelf)
error("wait on self");
- /* Sean Kelly writes:
- * Change to:
- * if (state != TS.INITIAL)
- * Because it is not only legal to call pthread_join on a thread that
- * has run and finished, but calling pthread_join or pthread_detach is
- * required for the thread resources to be released. However, it is
- * illegal to call pthread_join more than once, and I believe it is also
- * illegal to detach a thread that has already been joined, so 'id'
- * should probably be cleared after join/detach is called, and this
- * value tested along with 'state' before performing thread ops.
- */
- if (state == TS.RUNNING)
- { int result;
+ if (state != TS.FINISHED)
+ {
void *value;
- result = pthread_join(id, &value);
+ int result = pthread_join(id, &value);
+ state = TS.FINISHED;
if (result)
error("failed to wait");
}
@@ -649,9 +667,9 @@
void wait(uint milliseconds)
{
// Implemented for POSIX systems by Dave Fladebo
- if (this is getThis())
+ if (isSelf)
error("wait on self");
- if (state == TS.RUNNING)
+ if (state != TS.FINISHED)
{
timespec ts;
timeval tv;
@@ -683,9 +701,12 @@
pthread_setcanceltype(oldtype, null);
state = TS.TERMINATED;
+ synchronized (Thread.classinfo)
+ {
allThreads[idx] = null;
idx = -1;
nthreads--;
+ }
pthread_mutex_unlock(&waitMtx);
}
@@ -699,9 +720,10 @@
enum TS
{
- INITIAL,
- RUNNING,
- TERMINATED
+ INITIAL, // created
+ RUNNING, // running
+ TERMINATED, // execution finished
+ FINISHED // pthread_join()'ed
}
TS getState()
@@ -751,13 +773,8 @@
static Thread getThis()
{
- pthread_t id;
- Thread result;
-
//printf("getThis(), allThreadsDim = %d\n", allThreadsDim);
- //synchronized (threadLock)
- {
- id = pthread_self();
+ pthread_t id = pthread_self();
//printf("id = %d\n", id);
for (int i = 0; i < allThreadsDim; i++)
{
@@ -768,15 +785,13 @@
return t;
}
}
- }
printf("didn't find it\n");
- assert(result);
- return result;
+ assert(null);
}
static Thread[] getAll()
{
- return allThreads[0 .. allThreadsDim];
+ synchronized (Thread.classinfo) return allThreads[0 .. allThreadsDim];
}
void pause()
@@ -789,10 +804,9 @@
error("cannot pause");
}
else
- { int result;
+ {
- result = pthread_kill(id, SIGUSR1);
- if (result)
+ if (pthread_kill(id, SIGUSR1))
error("cannot pause");
else
flagSuspend.wait(); // wait for acknowledgement
@@ -812,10 +826,8 @@
error("cannot pause");
}
else
- { int result;
-
- result = pthread_kill(id, SIGUSR2);
- if (result)
+ {
+ if (pthread_kill(id, SIGUSR2))
error("cannot resume");
}
}
@@ -825,24 +837,21 @@
static void pauseAll()
{
+ synchronized(Thread.classinfo)
+ {
version (GNU_pthread_suspend)
{
if (nthreads > 1)
{
- Thread tthis = getThis();
-
- synchronized (threadLock)
- {
+ pthread_t thisid = pthread_self();
for (int i = 0; i < allThreadsDim; i++)
- { Thread t;
+ {
- t = allThreads[i];
- if (t && t !is tthis && t.state == TS.RUNNING)
+ Thread t = allThreads[i];
+ if (t && !pthread_equal(thisid, t.id) && t.state == TS.RUNNING)
t.pause();
}
-
- }
}
}
else
@@ -850,54 +859,50 @@
if (nthreads > 1)
{
- Thread tthis = getThis();
+ pthread_t thisid = pthread_self();
int npause = 0;
- synchronized (threadLock)
+ for (int i = 0; i < allThreadsDim; i++)
{
-
- for (int i = 0; i < allThreadsDim; i++)
- { Thread t;
- t = allThreads[i];
- if (t && t !is tthis && t.state == TS.RUNNING)
- { int result;
-
- result = pthread_kill(t.id, SIGUSR1);
- if (result)
+ Thread t = allThreads[i];
+ if (t && !pthread_equal(thisid, t.id) && t.state == TS.RUNNING)
+ {
+ if (pthread_kill(t.id, SIGUSR1))
getThis().error("cannot pause");
else
npause++; // count of paused threads
}
}
- }
-
// Wait for each paused thread to acknowledge
while (npause--)
{
flagSuspend.wait();
}
}
-
}
+ }
}
static void resumeAll()
{
+ synchronized (Thread.classinfo)
+ {
if (nthreads > 1)
{
- Thread tthis = getThis();
+ pthread_t thisid = pthread_self();
for (int i = 0; i < allThreadsDim; i++)
- { Thread t;
+ {
- t = allThreads[i];
- if (t && t !is tthis && t.state == TS.RUNNING)
+ Thread t = allThreads[i];
+ if (t && t.id != thisid && t.state == TS.RUNNING)
t.resume();
}
}
}
+ }
static void yield()
{
@@ -909,7 +914,6 @@
private:
static uint allThreadsDim;
- static Object threadLock;
// Set max to Windows equivalent for compatibility.
// pthread_create will fail gracefully if stack limit
@@ -938,7 +942,7 @@
int delegate() dg;
- void error(char[] msg)
+ void error(string msg)
{
throw new ThreadError(msg);
}
@@ -978,7 +982,7 @@
t.id = pthread_self();
version(skyos)
- installSignalHandlers();
+ installSignalHandlers(t);
t.stackBottom = getESP();
try
@@ -989,15 +993,14 @@
}
catch (Object o)
{
- printf("Error: ");
- o.print();
+ fprintf(stderr, "Error: %.*s\n", o.toString());
result = 1;
}
debug (thread) printf("Ending thread %d\n", t.idx);
- synchronized (threadLock)
+ t.state = TS.TERMINATED;
+ synchronized (Thread.classinfo)
{
- t.state = TS.TERMINATED;
allThreads[t.idx] = null;
t.idx = -1;
nthreads--;
@@ -1012,8 +1015,6 @@
public static void thread_init()
{
- threadLock = new Object();
-
Thread t = new Thread();
t.state = TS.RUNNING;
@@ -1033,7 +1034,7 @@
{
/* Install signal handlers so we can suspend/resume threads
*/
- installSignalHandlers();
+ installSignalHandlers(t);
}
return;
@@ -1047,7 +1048,7 @@
else
{
- private static void installSignalHandlers()
+ private static void installSignalHandlers(Thread t)
{
int result;
sigaction_t sigact;
@@ -1068,7 +1069,7 @@
return;
Lfail:
- getThis().error("cannot initialize threads");
+ t.error("cannot initialize threads");
}
Index: d/phobos/std/moduleinit.d
===================================================================
--- d/phobos/std/moduleinit.d (Revision 199)
+++ d/phobos/std/moduleinit.d (Arbeitskopie)
@@ -1,3 +1,4 @@
+// Written in the D programming language
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
@@ -23,6 +24,7 @@
MIctordone = 2, // finished construction
MIstandalone = 4, // module ctor does not depend on other module
// ctors being done first
+ MIhasictor = 8, // has ictor member
}
/***********************
@@ -36,10 +38,14 @@
uint flags; // initialization state
- void (*ctor)();
- void (*dtor)();
- void (*unitTest)();
+ void (*ctor)(); // module static constructor (order dependent)
+ void (*dtor)(); // module static destructor
+ void (*unitTest)(); // module unit tests
+ void* xgetMembers; // module getMembers() function
+
+ void (*ictor)(); // module static constructor (order independent)
+
/******************
* Return collection of all modules in the program.
*/
@@ -53,7 +59,8 @@
{
this(ModuleInfo m)
{
- super("circular initialization dependency with module " ~ m.name);
+ super(cast(string) ("circular initialization dependency with module "
+ ~ m.name));
}
}
@@ -119,6 +126,7 @@
_moduleinfo_dtors = new ModuleInfo[_moduleinfo_array.length];
debug printf("_moduleinfo_dtors = x%x\n", cast(void *)_moduleinfo_dtors);
+ _moduleIndependentCtors();
_moduleCtor2(_moduleinfo_array, 0);
version (none)
@@ -227,3 +235,20 @@
}
}
+/**********************************
+ * Run unit tests.
+ */
+
+extern (C) void _moduleIndependentCtors()
+{
+ debug printf("_moduleIndependentCtors()\n");
+ foreach (m; _moduleinfo_array)
+ {
+ if (m && m.flags & MIhasictor && m.ictor)
+ {
+ (*m.ictor)();
+ }
+ }
+}
+
+
Index: d/phobos/std/mmfile.d
===================================================================
--- d/phobos/std/mmfile.d (Revision 199)
+++ d/phobos/std/mmfile.d (Arbeitskopie)
@@ -1,4 +1,6 @@
-/* Copyright 2004-2005 by Digital Mars
+// Written in the D programming language
+
+/* Copyright 2004-2008 by Digital Mars
* Written by Walter Bright and Matthew Wilson
*
* This software is provided 'as-is', without any express or implied
@@ -105,7 +107,7 @@
* Throws:
* std.file.FileException
*/
- this(char[] filename)
+ this(string filename)
{
this(filename, Mode.Read, 0, null);
}
@@ -128,7 +130,7 @@
* Throws:
* std.file.FileException
*/
- this(char[] filename, Mode mode, ulong size, void* address,
+ this(string filename, Mode mode, ulong size, void* address,
size_t window = 0)
{
this.filename = filename;
@@ -194,9 +196,11 @@
assert(0);
}
+ if (filename)
+ {
if (useWfuncs)
{
- wchar* namez = std.utf.toUTF16z(filename);
+ auto namez = std.utf.toUTF16z(filename);
hFile = CreateFileW(namez,
dwDesiredAccess2,
dwShareMode,
@@ -207,7 +211,7 @@
}
else
{
- char* namez = std.file.toMBSz(filename);
+ auto namez = std.file.toMBSz(filename);
hFile = CreateFileA(namez,
dwDesiredAccess2,
dwShareMode,
@@ -218,6 +222,9 @@
}
if (hFile == INVALID_HANDLE_VALUE)
goto err1;
+ }
+ else
+ hFile = null;
int hi = cast(int)(size>>32);
hFileMap = CreateFileMappingA(hFile, null, flProtect, hi, cast(uint)size, null);
@@ -360,7 +367,7 @@
errNo();
hFileMap = null;
- if (hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
+ if (hFile && hFile != INVALID_HANDLE_VALUE && CloseHandle(hFile) != TRUE)
errNo();
hFile = INVALID_HANDLE_VALUE;
}
@@ -552,7 +559,7 @@
}
private:
- char[] filename;
+ string filename;
void[] data;
ulong start;
size_t window;
@@ -634,5 +641,8 @@
assert( data2[length-1] == 'b' );
delete mf;
std.file.remove("testing.txt");
+
+ // Create anonymous mapping
+ auto test = new MmFile(null, MmFile.Mode.ReadWriteNew, 1024*1024, null);
}
}
Index: d/phobos/std/file.d
===================================================================
--- d/phobos/std/file.d (Revision 199)
+++ d/phobos/std/file.d (Arbeitskopie)
@@ -852,11 +852,10 @@
private import std.c.unix.unix;
private import std.date;
+private import std.c.string;
alias std.c.unix.unix unix;
-extern (C) char* strerror(int);
-
/***********************************
*/
@@ -876,7 +875,8 @@
}
this(char[] name, uint errno)
- { char* s = strerror(errno);
+ { char[80] buf = void;
+ auto s = strerror_r(errno, buf.ptr, buf.length);
this(name, std.string.toString(s).dup);
this.errno = errno;
}
Index: d/phobos/std/socket.d
===================================================================
--- d/phobos/std/socket.d (Revision 199)
+++ d/phobos/std/socket.d (Arbeitskopie)
@@ -108,12 +108,10 @@
{
if(errorCode > 0)
{
- char* cs;
- size_t len;
+ char[80] buf;
+ auto cs = strerror_r(errorCode, buf.ptr, buf.length);
+ auto len = strlen(cs);
- cs = strerror(errorCode);
- len = strlen(cs);
-
if(cs[len - 1] == '\n')
len--;
if(cs[len - 1] == '\r')
@@ -484,7 +482,8 @@
*/
bool getHostByName(string name)
{
- hostent* he = gethostbyname(toStringz(name));
+ hostent* he;
+ synchronized(this.classinfo) he = gethostbyname(toStringz(name));
if(!he)
return false;
validHostent(he);
@@ -499,7 +498,8 @@
bool getHostByAddr(uint addr)
{
uint x = htonl(addr);
- hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
+ hostent* he;
+ synchronized(this.classinfo) he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
if(!he)
return false;
validHostent(he);
@@ -516,7 +516,8 @@
bool getHostByAddr(string addr)
{
uint x = inet_addr(std.string.toStringz(addr));
- hostent* he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
+ hostent* he;
+ synchronized(this.classinfo) he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
if(!he)
return false;
validHostent(he);
@@ -764,6 +765,7 @@
OOB = MSG_OOB, /// out-of-band stream data
PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving
DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending
+ NOSIGNAL = MSG_NOSIGNAL, /// don't send SIGPIPE signal on socket write error and instead return EPIPE
}
@@ -1325,6 +1327,7 @@
//returns number of bytes actually sent, or -1 on error
int send(void[] buf, SocketFlags flags)
{
+ flags |= SocketFlags.NOSIGNAL;
int sent = .send(sock, buf.ptr, buf.length, cast(int)flags);
return sent;
}
@@ -1332,7 +1335,7 @@
/// ditto
int send(void[] buf)
{
- return send(buf, SocketFlags.NONE);
+ return send(buf, SocketFlags.NOSIGNAL);
}
/**
@@ -1340,6 +1343,7 @@
*/
int sendTo(void[] buf, SocketFlags flags, Address to)
{
+ flags |= SocketFlags.NOSIGNAL;
int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, to.name(), to.nameLen());
return sent;
}
@@ -1355,6 +1359,7 @@
/// ditto
int sendTo(void[] buf, SocketFlags flags)
{
+ flags |= SocketFlags.NOSIGNAL;
int sent = .sendto(sock, buf.ptr, buf.length, cast(int)flags, null, 0);
return sent;
}
Index: d/phobos/unittest.d
===================================================================
--- d/phobos/unittest.d (Revision 199)
+++ d/phobos/unittest.d (Arbeitskopie)
@@ -52,6 +52,7 @@
import std.file;
import std.signals;
import std.cpuid;
+import std.socket;
int main(char[][] args)
{
Index: d/phobos/std.ddoc
===================================================================
--- d/phobos/std.ddoc (Revision 199)
+++ d/phobos/std.ddoc (Arbeitskopie)
@@ -3,7 +3,7 @@
<html>
<!--
- Copyright (c) 1999-2006 by Digital Mars
+ Copyright (c) 1999-2008 by Digital Mars
All Rights Reserved
Written by Walter Bright
www.digitalmars.com
@@ -62,7 +62,7 @@
<div id="copyright">
$(COPYRIGHT) |
-Page generated by $(LINK2 http://www.digitalmars.com/d/ddoc.html, Ddoc).
+Page generated by $(LINK2 http://www.digitalmars.com/d/1.0/ddoc.html, Ddoc).
</div>
</body>
@@ -89,7 +89,7 @@
<div id="searchbox">
<input id="q" name="q" size="10" value="RTL Search" onFocus='if(this.value == "RTL Search"){this.value="";}'>
<input type="hidden" id="domains" name="domains" value="www.digitalmars.com">
-<input type="hidden" id="sitesearch" name="sitesearch" value="www.digitalmars.com/d/phobos">
+<input type="hidden" id="sitesearch" name="sitesearch" value="www.digitalmars.com/d/1.0/phobos">
<input type="hidden" id="sourceid" name="sourceid" value="google-search">
<input type="submit" id="submit" name="submit" value="Go">
</div>
Index: d/phobos/linux.mak
===================================================================
--- d/phobos/linux.mak (Revision 199)
+++ d/phobos/linux.mak (Arbeitskopie)
@@ -198,17 +198,17 @@
#$(LIB) : $(OBJS) internal/gc/dmgc.a linux.mak
-$(LIB) : $(OBJS) internal/gc/dmgc.a $(ZLIB_OBJS) linux.mak
+$(LIB) : $(OBJS) $(GC_OBJS) $(ZLIB_OBJS) linux.mak
rm -f $(LIB)
ar -r $@ $(OBJS) $(ZLIB_OBJS) $(GC_OBJS)
###########################################################
-internal/gc/dmgc.a:
+$(GC_OBJS):
# cd internal/gc
# make -f linux.mak dmgc.a
# cd ../..
- make -C ./internal/gc -f linux.mak dmgc.a
+ make -C ./internal/gc -f linux.mak
$(ZLIB_OBJS):
# cd etc/c/zlib
@@ -594,3 +594,6 @@
clean:
$(RM) $(LIB) $(OBJS) unittest unittest.o
+ make -C ./internal/gc -f linux.mak clean
+ make -C ./etc/c/zlib -f linux.mak clean
+
Index: d/phobos/etc/c/zlib/linux.mak
===================================================================
--- d/phobos/etc/c/zlib/linux.mak (Revision 199)
+++ d/phobos/etc/c/zlib/linux.mak (Arbeitskopie)
@@ -74,4 +74,5 @@
echo hello world | minigzip | minigzip -d
clean:
- $(RM) $(OBJS) zlib.a example minigzip minigzip.o test foo.gz
+ $(RM) $(OBJS) zlib.a example.o example minigzip minigzip.o test foo.gz
+
Index: d/phobos/internal/arraycat.d
===================================================================
--- d/phobos/internal/arraycat.d (Revision 199)
+++ d/phobos/internal/arraycat.d (Arbeitskopie)
@@ -3,26 +3,9 @@
*/
/*
- * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
+ * http://www.digitalmars.com
* Written by Walter Bright
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the authors be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any purpose,
- * including commercial applications, and to alter it and redistribute it
- * freely, in both source and binary form, subject to the following
- * restrictions:
- *
- * o The origin of this software must not be misrepresented; you must not
- * claim that you wrote the original software. If you use this software
- * in a product, an acknowledgment in the product documentation would be
- * appreciated but is not required.
- * o Altered source versions must be plainly marked as such, and must not
- * be misrepresented as being the original software.
- * o This notice may not be removed or altered from any source
- * distribution.
+ * Placed in the Public Domain
*/
/* NOTE: This file has been patched from the original DMD distribution to
@@ -36,28 +19,28 @@
import object;
import std.string;
import std.c.string;
-import std.c.stdio;
-import std.c.stdarg;
extern (C)
-byte[] _d_arraycopy(size_t size, byte[] from, byte[] to)
+void[] _d_arraycopy(uint size, void[] from, void[] to)
{
- //printf("f = %p,%d, t = %p,%d, size = %d\n", (void*)from, from.length, (void*)to, to.length, size);
+ //printf("f = %p,%d, t = %p,%d, size = %d\n", from.ptr, from.length, to.ptr, to.length, size);
if (to.length != from.length)
{
//throw new Error(std.string.format("lengths don't match for array copy, %s = %s", to.length, from.length));
- throw new Error("lengths don't match for array copy," ~
- toString(to.length) ~ " = " ~ toString(from.length));
+ throw new Error(cast(string) ("lengths don't match for array copy," ~
+ toString(to.length) ~ " = "
+ ~ toString(from.length)));
}
- else if (cast(byte *)to + to.length * size <= cast(byte *)from ||
- cast(byte *)from + from.length * size <= cast(byte *)to)
+ else if (to.ptr + to.length * size <= from.ptr ||
+ from.ptr + from.length * size <= to.ptr)
{
- memcpy(cast(byte *)to, cast(byte *)from, to.length * size);
+ memcpy(to.ptr, from.ptr, to.length * size);
}
else
{
throw new Error("overlapping array copy");
+ //memmove(to.ptr, from.ptr, to.length * size);
}
return to;
}
Index: d/phobos/internal/object.d
===================================================================
--- d/phobos/internal/object.d (Revision 199)
+++ d/phobos/internal/object.d (Arbeitskopie)
@@ -312,6 +312,9 @@
/********************
* Create instance of Object represented by 'this'.
+ * Returns:
+ * the object created, or null if the Object does
+ * does not have a default constructor
*/
Object create()
{
Index: d/phobos/internal/gc/gcx.d
===================================================================
--- d/phobos/internal/gc/gcx.d (Revision 199)
+++ d/phobos/internal/gc/gcx.d (Arbeitskopie)
@@ -1,8 +1,28 @@
-//
-// Copyright (C) 2001-2006 by Digital Mars
-// All Rights Reserved
-// Written by Walter Bright
-// www.digitalmars.com
+/**
+ * This module contains the garbage collector implementation.
+ *
+ * Copyright: Copyright (C) 2001-2007 Digital Mars, www.digitalmars.com.
+ * All rights reserved.
+ * License:
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, in both source and binary form, subject to the following
+ * restrictions:
+ *
+ * o The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * o Altered source versions must be plainly marked as such, and must not
+ * be misrepresented as being the original software.
+ * o This notice may not be removed or altered from any source
+ * distribution.
+ * Authors: Walter Bright, David Friedman, Sean Kelly
+ */
/* NOTE: This file has been patched from the original DMD distribution to
work with the GDC compiler.
@@ -32,16 +52,16 @@
/***************************************************/
+private import gcbits;
+private import gcstats;
-debug (PRINTF) import std.c.stdio;
+private import cstdlib = std.c.stdlib : calloc, free, malloc, realloc;
+private import cstring = std.c.string : memcpy, memmove, memset;
-import std.c.stdio;
-import std.c.stdlib;
-import std.c.string;
-import gcbits;
+debug private import std.c.stdio;
+
import std.outofmemory;
import std.gc;
-import gcstats;
version (GNU)
{
@@ -72,7 +92,32 @@
import std.thread;
}
-//alias GC* gc_t;
+private void onOutOfMemoryError()
+{
+ _d_OutOfMemory();
+}
+
+private void* rt_stackBottom()
+{
+ version (Win32)
+ {
+ return win32.os_query_stackBottom();
+ }
+ version (GNU)
+ {
+ return gcgcc.os_query_stackBottom();
+ }
+ else version (linux)
+ {
+ return gclinux.os_query_stackBottom();
+ }
+}
+
+private bool thread_needLock()
+{
+ return std.thread.Thread.nthreads != 1;
+}
+
alias GC gc_t;
version (X86) version (D_InlineAsm) { version = Asm86; }
@@ -83,11 +128,11 @@
{
struct Log
{
- void *p;
+ void* p;
size_t size;
uint line;
- char *file;
- void *parent;
+ char* file;
+ void* parent;
void print()
{
@@ -103,14 +148,13 @@
struct LogArray
{
- size_t dim;
- size_t allocdim;
+ size_t dim, allocdim;
Log *data;
void Dtor()
{
if (data)
- std.c.stdlib.free(data);
+ cstdlib.free(data);
data = null;
}
@@ -123,18 +167,18 @@
assert(dim + nentries <= allocdim);
if (!data)
{
- data = cast(Log *)std.c.stdlib.malloc(allocdim * Log.sizeof);
+ data = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof);
if (!data && allocdim)
- _d_OutOfMemory();
+ onOutOfMemoryError();
}
else
{ Log *newdata;
- newdata = cast(Log *)std.c.stdlib.malloc(allocdim * Log.sizeof);
+ newdata = cast(Log *)cstdlib.malloc(allocdim * Log.sizeof);
if (!newdata && allocdim)
- _d_OutOfMemory();
- memcpy(newdata, data, dim * Log.sizeof);
- std.c.stdlib.free(data);
+ onOutOfMemoryError();
+ cstring.memcpy(newdata, data, dim * Log.sizeof);
+ cstdlib.free(data);
data = newdata;
}
}
@@ -148,7 +192,7 @@
void remove(size_t i)
{
- memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
+ cstring.memmove(data + i, data + i + 1, (dim - i) * Log.sizeof);
dim--;
}
@@ -176,10 +220,8 @@
/* ============================ GC =============================== */
+alias void (*GC_FINALIZER)(void *p, bool dummy);
-//alias int size_t;
-alias void (*GC_FINALIZER)(void *p, void *dummy);
-
class GCLock { } // just a dummy so we can get a global lock
const uint GCVERSION = 1; // increment every time we change interface
@@ -188,7 +230,7 @@
class GC
{
// For passing to debug code
- static uint line;
+ static size_t line;
static char *file;
uint gcversion = GCVERSION;
@@ -199,22 +241,11 @@
void initialize()
{
gcLock = GCLock.classinfo;
- gcx = cast(Gcx *)std.c.stdlib.calloc(1, Gcx.sizeof);
+ gcx = cast(Gcx *)cstdlib.calloc(1, Gcx.sizeof);
if (!gcx)
- _d_OutOfMemory();
+ onOutOfMemoryError();
gcx.initialize();
- version (Win32)
- {
- setStackBottom(win32.os_query_stackBottom());
- }
- else version (GNU)
- {
- setStackBottom(gcgcc.os_query_stackBottom());
- }
- else version (linux)
- {
- setStackBottom(gclinux.os_query_stackBottom());
- }
+ setStackBottom(rt_stackBottom());
}
@@ -229,45 +260,90 @@
if (gcx)
{
gcx.Dtor();
- std.c.stdlib.free(gcx);
+ cstdlib.free(gcx);
gcx = null;
}
}
- invariant
+
+ invariant()
{
if (gcx)
+ {
gcx.thread_Invariant();
}
+ }
+
+ /**
+ *
+ */
+ void enable()
+ {
+ if (!thread_needLock())
+ {
+ assert(gcx.disabled > 0);
+ gcx.disabled--;
+ }
+ else synchronized (gcLock)
+ {
+ assert(gcx.disabled > 0);
+ gcx.disabled--;
+ }
+ }
+
+
+ /**
+ *
+ */
+ void disable()
+ {
+ if (!thread_needLock())
+ {
+ gcx.disabled++;
+ }
+ else synchronized (gcLock)
+ {
+ gcx.disabled++;
+ }
+ }
+
+
+ /**
+ *
+ */
void *malloc(size_t size)
- { void *p;
+ {
+ if (!size)
+ {
+ return null;
+ }
- if (std.thread.Thread.nthreads == 1)
+ if (!thread_needLock())
{
- /* Single-threaded no-sync - Dave Fladebo.
- * The reason this works is because none of the gc code
- * can start up a new thread from within mallocNoSync().
- * Skip the sync for speed reasons.
- */
return mallocNoSync(size);
}
else synchronized (gcLock)
{
- p = mallocNoSync(size);
+ return mallocNoSync(size);
}
- return p;
}
- void *mallocNoSync(size_t size)
- { void *p = null;
+
+ //
+ //
+ //
+ private void *mallocNoSync(size_t size)
+ {
+ assert(size != 0);
+
+ void *p = null;
Bins bin;
//debug(PRINTF) printf("GC::malloc(size = %d, gcx = %p)\n", size, gcx);
assert(gcx);
//debug(PRINTF) printf("gcx.self = %x, pthread_self() = %x\n", gcx.self, pthread_self());
- if (size)
- {
+
size += SENTINEL_EXTRA;
// Compute size bin
@@ -290,7 +366,7 @@
{
if (!gcx.allocPage(bin) && !gcx.disabled) // try to find a new page
{
- if (std.thread.Thread.nthreads == 1)
+ if (!thread_needLock())
{
/* Then we haven't locked it yet. Be sure
* and lock for a collection, since a finalizer
@@ -319,13 +395,8 @@
// Return next item from free list
gcx.bucket[bin] = (cast(List *)p).next;
- version(GNU)
- memset(p + size, 0, binsize[bin] - size);
- else
- // 'inline' memset - Dave Fladebo.
- //foreach(inout byte b; cast(byte[])(p + size)[0..binsize[bin] - size]) { b = 0; }
- //debug(PRINTF) printf("\tmalloc => %x\n", p);
- debug (MEMSTOMP) memset(p, 0xF0, size);
+ cstring.memset(p + size, 0, binsize[bin] - size);
+ debug (MEMSTOMP) cstring.memset(p, 0xF0, size);
}
else
{
@@ -337,38 +408,49 @@
p = sentinel_add(p);
sentinel_init(p, size);
gcx.log_malloc(p, size);
- }
return p;
}
-
+ /**
+ *
+ */
void *calloc(size_t size, size_t n)
{
- size_t len;
- void *p;
+ size_t len = size * n;
+ if (!len) return null;
+ if (!thread_needLock()) return callocNoSync(len);
+ else synchronized (gcLock) return callocNoSync(len);
+ }
- len = size * n;
- p = malloc(len);
+ private void *callocNoSync(size_t size) {
+ assert(size != 0);
+ void *p = mallocNoSync(size);
if (p)
{ //debug(PRINTF) printf("calloc: %x len %d\n", p, len);
- memset(p, 0, len);
+ cstring.memset(p, 0, size);
}
return p;
}
-
+ /**
+ *
+ */
void *realloc(void *p, size_t size)
{
- gcx.p_cache = null;
+ if (!thread_needLock()) return reallocNoSync(p, size);
+ else synchronized (gcLock) return reallocNoSync(p, size);
+ }
+ private void *reallocNoSync(void *p, size_t size)
+ {
if (!size)
{ if (p)
- { free(p);
+ { freeNoSync(p);
p = null;
}
}
else if (!p)
{
- p = malloc(size);
+ p = mallocNoSync(size);
}
else
{ void *p2;
@@ -381,11 +463,11 @@
psize = *sentinel_size(p);
if (psize != size)
{
- p2 = malloc(size);
+ p2 = mallocNoSync(size);
if (psize < size)
size = psize;
//debug(PRINTF) printf("\tcopying %d bytes\n",size);
- memcpy(p2, p, size);
+ cstring.memcpy(p2, p, size);
p = p2;
}
}
@@ -404,49 +486,42 @@
if (newsz < psz)
{ // Shrink in place
- synchronized (gcLock)
- {
- debug (MEMSTOMP) memset(p + size, 0xF2, psize - size);
- pool.freePages(pagenum + newsz, psz - newsz);
- }
+ debug (MEMSTOMP) cstring.memset(p + size, 0xF2, psize - size);
+ pool.freePages(pagenum + newsz, psz - newsz);
return p;
}
else if (pagenum + newsz <= pool.npages)
{
// Attempt to expand in place
- synchronized (gcLock)
+ for (size_t i = pagenum + psz; 1;)
{
- for (size_t i = pagenum + psz; 1;)
+ if (i == pagenum + newsz)
{
- if (i == pagenum + newsz)
- {
- debug (MEMSTOMP) memset(p + psize, 0xF0, size - psize);
- memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz);
- return p;
- }
- if (i == pool.ncommitted)
- {
- auto u = pool.extendPages(pagenum + newsz - pool.ncommitted);
- if (u == ~0u)
- break;
- i = pagenum + newsz;
- continue;
- }
- if (pool.pagetable[i] != B_FREE)
+ debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, size - psize);
+ cstring.memset(&pool.pagetable[pagenum + psz], B_PAGEPLUS, newsz - psz);
+ return p;
+ }
+ if (i == pool.ncommitted)
+ {
+ auto u = pool.extendPages(pagenum + newsz - pool.ncommitted);
+ if (u == ~0u)
break;
- i++;
+ i = pagenum + newsz;
+ continue;
}
+ if (pool.pagetable[i] != B_FREE) break;
+ i++;
}
}
}
if (psize < size || // if new size is bigger
psize > size * 2) // or less than half
{
- p2 = malloc(size);
+ p2 = mallocNoSync(size);
if (psize < size)
size = psize;
//debug(PRINTF) printf("\tcopying %d bytes\n",size);
- memcpy(p2, p, size);
+ cstring.memcpy(p2, p, size);
p = p2;
}
}
@@ -454,17 +529,39 @@
return p;
}
+
/**
- * Attempt to in-place enlarge the memory block pointed to by p
- * by at least minbytes beyond its current capacity,
- * up to a maximum of maxbytes.
- * This does not attempt to move the memory block (like realloc() does).
+ * Attempt to in-place enlarge the memory block pointed to by p by at least
+ * minbytes beyond its current capacity, up to a maximum of maxsize. This
+ * does not attempt to move the memory block (like realloc() does).
+ *
* Returns:
* 0 if could not extend p,
* total size of entire memory block if successful.
*/
size_t extend(void* p, size_t minsize, size_t maxsize)
{
+ if (!thread_needLock())
+ {
+ return extendNoSync(p, minsize, maxsize);
+ }
+ else synchronized (gcLock)
+ {
+ return extendNoSync(p, minsize, maxsize);
+ }
+ }
+
+
+ //
+ //
+ //
+ private size_t extendNoSync(void* p, size_t minsize, size_t maxsize)
+ in
+ {
+ assert( minsize <= maxsize );
+ }
+ body
+ {
//debug(PRINTF) printf("GC::extend(p = %x, minsize = %u, maxsize = %u)\n", p, minsize, maxsize);
version (SENTINEL)
{
@@ -481,8 +578,6 @@
auto pool = gcx.findPool(p);
auto pagenum = (p - pool.baseAddr) / PAGESIZE;
- synchronized (gcLock)
- {
size_t sz;
for (sz = 0; sz < maxsz; sz++)
{
@@ -507,24 +602,47 @@
}
else
return 0;
- debug (MEMSTOMP) memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
- memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
+ debug (MEMSTOMP) cstring.memset(p + psize, 0xF0, (psz + sz) * PAGESIZE - psize);
+ cstring.memset(pool.pagetable + pagenum + psz, B_PAGEPLUS, sz);
gcx.p_cache = null;
gcx.size_cache = 0;
return (psz + sz) * PAGESIZE;
}
- }
+
+ /**
+ *
+ */
void free(void *p)
{
+ if (!p)
+ {
+ return;
+ }
+
+ if (!thread_needLock())
+ {
+ return freeNoSync(p);
+ }
+ else synchronized (gcLock)
+ {
+ return freeNoSync(p);
+ }
+ }
+
+
+ //
+ //
+ //
+ private void freeNoSync(void *p)
+ {
+ assert (p);
+
Pool *pool;
uint pagenum;
Bins bin;
uint biti;
- if (!p)
- return;
-
// Find which page it is in
pool = gcx.findPool(p);
if (!pool) // if not one of ours
@@ -532,18 +650,10 @@
sentinel_Invariant(p);
p = sentinel_sub(p);
pagenum = (p - pool.baseAddr) / PAGESIZE;
-
- synchronized (gcLock)
- {
biti = cast(uint)(p - pool.baseAddr) / 16;
- pool.noptrs.clear(biti);
- if (pool.finals.nbits && gcx.finalizer)
- {
- if (pool.finals.testClear(biti))
- {
- (*gcx.finalizer)(sentinel_add(p), null);
- }
- }
+ pool.noscan.clear(biti);
+ if (pool.finals.nbits && pool.finals.testClear(biti))
+ gcx.rt_finalize(sentinel_add(p), false);
gcx.p_cache = null;
bin = cast(Bins)pool.pagetable[pagenum];
@@ -556,31 +666,51 @@
n = pagenum;
while (++n < pool.ncommitted && pool.pagetable[n] == B_PAGEPLUS)
npages++;
- debug (MEMSTOMP) memset(p, 0xF2, npages * PAGESIZE);
+ debug (MEMSTOMP) cstring.memset(p, 0xF2, npages * PAGESIZE);
pool.freePages(pagenum, npages);
}
else
{ // Add to free list
List *list = cast(List *)p;
- debug (MEMSTOMP) memset(p, 0xF2, binsize[bin]);
+ debug (MEMSTOMP) cstring.memset(p, 0xF2, binsize[bin]);
list.next = gcx.bucket[bin];
gcx.bucket[bin] = list;
}
- }
gcx.log_free(sentinel_add(p));
}
- /****************************************
- * Determine the allocated size of pointer p.
- * If p is an interior pointer or not a gc allocated pointer,
- * return 0.
+ /**
+ * Determine the allocated size of pointer p. If p is an interior pointer
+ * or not a gc allocated pointer, return 0.
*/
-
size_t capacity(void *p)
{
+ if (!p)
+ {
+ return 0;
+ }
+
+ if (!thread_needLock())
+ {
+ return sizeOfNoSync(p);
+ }
+ else synchronized (gcLock)
+ {
+ return sizeOfNoSync(p);
+ }
+ }
+
+
+ //
+ //
+ //
+ private size_t sizeOfNoSync(void *p)
+ {
+ assert (p);
+
version (SENTINEL)
{
p = sentinel_sub(p);
@@ -618,7 +748,7 @@
}
- /****************************************
+ /**
* Verify that pointer p:
* 1) belongs to this memory pool
* 2) points to the start of an allocated piece of memory
@@ -627,10 +757,17 @@
void check(void *p)
{
- if (p)
- {
- synchronized (gcLock)
+ if (!p) return;
+ if (!thread_needLock())
+ checkNoSync(p);
+ else synchronized (gcLock)
+ checkNoSync(p);
+ }
+
+ private void checkNoSync(void *p)
{
+ assert(p);
+
sentinel_Invariant(p);
debug (PTRCHECK)
{
@@ -663,11 +800,12 @@
}
}
}
- }
- }
- void setStackBottom(void *p)
+ //
+ //
+ //
+ private void setStackBottom(void *p)
{
version (STACKGROWSDOWN)
{
@@ -689,6 +827,7 @@
}
}
+
static void scanStaticData(gc_t g)
{
void *pbot;
@@ -724,44 +863,104 @@
}
- void addRoot(void *p) // add p to list of roots
+ /**
+ * add p to list of roots
+ */
+ void addRoot(void *p)
{
- synchronized (gcLock)
+ if (!p)
+ {
+ return;
+ }
+
+ if (!thread_needLock())
+ {
+ gcx.addRoot(p);
+ }
+ else synchronized (gcLock)
{
gcx.addRoot(p);
}
}
- void removeRoot(void *p) // remove p from list of roots
+
+ /**
+ * remove p from list of roots
+ */
+ void removeRoot(void *p)
{
- synchronized (gcLock)
+ if (!p)
+ {
+ return;
+ }
+
+ if (!thread_needLock())
+ {
+ gcx.removeRoot(p);
+ }
+ else synchronized (gcLock)
{
gcx.removeRoot(p);
}
}
- void addRange(void *pbot, void *ptop) // add range to scan for roots
+
+ /**
+ * add range to scan for roots
+ */
+ void addRange(void *pbot, void *ptop)
{
+ if (!pbot || !ptop)
+ {
+ return;
+ }
+
//debug(PRINTF) printf("+GC.addRange(pbot = x%x, ptop = x%x)\n", pbot, ptop);
- synchronized (gcLock)
+ if (!thread_needLock())
+ {
+ gcx.addRange(pbot, ptop);
+ }
+ else synchronized (gcLock)
{
gcx.addRange(pbot, ptop);
}
//debug(PRINTF) printf("-GC.addRange()\n");
}
- void removeRange(void *pbot) // remove range
+
+ /**
+ * remove range
+ */
+ void removeRange(void *p)
{
- synchronized (gcLock)
+ if (!p)
{
- gcx.removeRange(pbot);
+ return;
+ }
+
+ if (!thread_needLock())
+ {
+ gcx.removeRange(p);
+ }
+ else synchronized (gcLock)
+ {
+ gcx.removeRange(p);
}
}
- void fullCollect() // do full garbage collection
+
+ /**
+ * do full garbage collection
+ */
+ void fullCollect()
{
debug(PRINTF) printf("GC.fullCollect()\n");
- synchronized (gcLock)
+
+ if (!thread_needLock())
+ {
+ gcx.fullcollectshell();
+ }
+ else synchronized (gcLock)
{
gcx.fullcollectshell();
}
@@ -778,14 +977,31 @@
gcx.log_collect();
}
- void fullCollectNoStack() // do full garbage collection
+
+ /**
+ * do full garbage collection ignoring roots
+ */
+ void fullCollectNoStack()
{
+ if (!thread_needLock())
+ {
gcx.noStack++;
- fullCollect();
+ gcx.fullcollectshell();
gcx.noStack--;
}
+ else synchronized (gcLock)
+ {
+ gcx.noStack++;
+ gcx.fullcollectshell();
+ gcx.noStack--;
+ }
+ }
- void genCollect() // do generational garbage collection
+
+ /**
+ * do generational garbage collection
+ */
+ void genCollect()
{
synchronized (gcLock)
{
@@ -807,6 +1023,7 @@
}
}
+
void hasPointers(void *p)
{
synchronized (gcLock)
@@ -815,6 +1032,7 @@
}
}
+
void hasNoPointers(void *p)
{
if (!gcx.conservative)
@@ -830,23 +1048,6 @@
gcx.conservative = 1;
}
- void enable()
- {
- synchronized (gcLock)
- {
- assert(gcx.disabled > 0);
- gcx.disabled--;
- }
- }
-
- void disable()
- {
- synchronized (gcLock)
- {
- gcx.disabled++;
- }
- }
-
/*****************************************
* Retrieve statistics about garbage collection.
* Useful for debugging and tuning.
@@ -854,6 +1055,11 @@
void getStats(out GCStats stats)
{
+ if (!thread_needLock()) getStatsNoSync(stats);
+ else synchronized (gcLock) getStatsNoSync(stats);
+ }
+ private void getStatsNoSync(out GCStats stats)
+ {
size_t psize = 0;
size_t usize = 0;
size_t flsize = 0;
@@ -864,24 +1070,20 @@
//debug(PRINTF) printf("getStats()\n");
memset(&stats, 0, GCStats.sizeof);
- synchronized (gcLock)
- {
- for (n = 0; n < gcx.npools; n++)
- { Pool *pool = gcx.pooltable[n];
+ for (n = 0; n < gcx.npools; n++)
+ { Pool *pool = gcx.pooltable[n];
- psize += pool.ncommitted * PAGESIZE;
- for (uint j = 0; j < pool.ncommitted; j++)
- {
- Bins bin = cast(Bins)pool.pagetable[j];
- if (bin == B_FREE)
- stats.freeblocks++;
- else if (bin == B_PAGE)
- stats.pageblocks++;
- else if (bin < B_PAGE)
- bsize += PAGESIZE;
- }
+ psize += pool.ncommitted * PAGESIZE;
+ for (uint j = 0; j < pool.ncommitted; j++)
+ {
+ Bins bin = cast(Bins)pool.pagetable[j];
+ if (bin == B_FREE)
+ stats.freeblocks++;
+ else if (bin == B_PAGE)
+ stats.pageblocks++;
+ else if (bin < B_PAGE)
+ bsize += PAGESIZE;
}
-
for (n = 0; n < B_PAGE; n++)
{
//debug(PRINTF) printf("bin %d\n", n);
@@ -902,16 +1104,15 @@
}
-
-
/* ============================ Gcx =============================== */
enum
{ PAGESIZE = 4096,
COMMITSIZE = (4096*16),
- POOLSIZE = (4096*256),
+ POOLSIZE = (4096*256)
}
+
enum
{
B_16,
@@ -929,26 +1130,30 @@
B_MAX
}
+
alias ubyte Bins;
+
struct List
{
List *next;
}
+
struct Range
{
void *pbot;
void *ptop;
}
+
const uint binsize[B_MAX] = [ 16,32,64,128,256,512,1024,2048,4096 ];
const uint notbinsize[B_MAX] = [ ~(16u-1),~(32u-1),~(64u-1),~(128u-1),~(256u-1),
~(512u-1),~(1024u-1),~(2048u-1),~(4096u-1) ];
-
/* ============================ Gcx =============================== */
+
struct Gcx
{
debug (THREADINVARIANT)
@@ -995,6 +1200,13 @@
GC_FINALIZER finalizer; // finalizer function (one per GC)
+ private void rt_finalize( void* p, bool dummy )
+ {
+ if (finalizer)
+ (*finalizer)(p, dummy);
+ }
+
+
void initialize()
{ int dummy;
@@ -1007,6 +1219,7 @@
inited = 1;
}
+
void Dtor()
{
inited = 0;
@@ -1015,21 +1228,23 @@
{ Pool *pool = pooltable[i];
pool.Dtor();
- std.c.stdlib.free(pool);
+ cstdlib.free(pool);
}
if (pooltable)
- std.c.stdlib.free(pooltable);
+ cstdlib.free(pooltable);
if (roots)
- std.c.stdlib.free(roots);
+ cstdlib.free(roots);
if (ranges)
- std.c.stdlib.free(ranges);
+ cstdlib.free(ranges);
}
+
void Invariant() { }
- invariant
+
+ invariant()
{
if (inited)
{
@@ -1086,7 +1301,8 @@
}
- /***************************************
+ /**
+ *
*/
void addRoot(void *p)
@@ -1096,12 +1312,12 @@
size_t newdim = rootdim * 2 + 16;
void **newroots;
- newroots = cast(void **)std.c.stdlib.malloc(newdim * newroots[0].sizeof);
+ newroots = cast(void **)cstdlib.malloc(newdim * newroots[0].sizeof);
if (!newroots)
- _d_OutOfMemory();
+ onOutOfMemoryError();
if (roots)
- { memcpy(newroots, roots, nroots * newroots[0].sizeof);
- std.c.stdlib.free(roots);
+ { cstring.memcpy(newroots, roots, nroots * newroots[0].sizeof);
+ cstdlib.free(roots);
}
roots = newroots;
rootdim = newdim;
@@ -1113,20 +1329,20 @@
void removeRoot(void *p)
{
- size_t i;
- for (i = nroots; i--;)
+ for (size_t i = nroots; i--;)
{
if (roots[i] == p)
{
nroots--;
- memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof);
+ cstring.memmove(roots + i, roots + i + 1, (nroots - i) * roots[0].sizeof);
return;
}
}
assert(0);
}
- /***************************************
+ /**
+ *
*/
void addRange(void *pbot, void *ptop)
@@ -1138,12 +1354,12 @@
size_t newdim = rangedim * 2 + 16;
Range *newranges;
- newranges = cast(Range *)std.c.stdlib.malloc(newdim * newranges[0].sizeof);
+ newranges = cast(Range *)cstdlib.malloc(newdim * newranges[0].sizeof);
if (!newranges)
- _d_OutOfMemory();
+ onOutOfMemoryError();
if (ranges)
- { memcpy(newranges, ranges, nranges * newranges[0].sizeof);
- std.c.stdlib.free(ranges);
+ { cstring.memcpy(newranges, ranges, nranges * newranges[0].sizeof);
+ cstdlib.free(ranges);
}
ranges = newranges;
rangedim = newdim;
@@ -1153,7 +1369,9 @@
nranges++;
}
-
+ /**
+ *
+ */
void removeRange(void *pbot)
{
debug(THREADINVARIANT) { debug(PRINTF) printf("Thread %x ", pthread_self()); }
@@ -1163,7 +1381,7 @@
if (ranges[i].pbot == pbot)
{
nranges--;
- memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof);
+ cstring.memmove(ranges + i, ranges + i + 1, (nranges - i) * ranges[0].sizeof);
return;
}
}
@@ -1175,12 +1393,12 @@
//assert(zero);
}
- /*******************************
+
+ /**
* Find Pool that pointer is in.
* Return null if not in a Pool.
* Assume pooltable[] is sorted.
*/
-
Pool *findPool(void *p)
{
if (p >= minAddr && p < maxAddr)
@@ -1205,7 +1423,7 @@
}
- /*******************************
+ /**
* Find size of pointer p.
* Returns 0 if not a gc'd pointer
*/
@@ -1242,7 +1460,7 @@
}
- /*******************************
+ /**
* Compute bin for size.
*/
@@ -1288,7 +1506,7 @@
return bin;
}
- /****************************************
+ /**
* Allocate a chunk of memory that is larger than a page.
* Return null if out of memory.
*/
@@ -1359,25 +1577,24 @@
L1:
pool.pagetable[pn] = B_PAGE;
if (npages > 1)
- memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
+ cstring.memset(&pool.pagetable[pn + 1], B_PAGEPLUS, npages - 1);
p = pool.baseAddr + pn * PAGESIZE;
- memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
- debug (MEMSTOMP) memset(p, 0xF1, size);
+ cstring.memset(cast(char *)p + size, 0, npages * PAGESIZE - size);
+ debug (MEMSTOMP) cstring.memset(p, 0xF1, size);
//debug(PRINTF) printf("\tp = %x\n", p);
return p;
Lnomemory:
- _d_OutOfMemory();
+ onOutOfMemoryError();
return null;
}
- /***********************************
+ /**
* Allocate a new pool with at least npages in it.
* Sort it into pooltable[].
* Return null if failed.
*/
-
Pool *newPool(uint npages)
{
Pool *pool;
@@ -1412,7 +1629,7 @@
npages = n;
}
- pool = cast(Pool *)std.c.stdlib.calloc(1, Pool.sizeof);
+ pool = cast(Pool *)cstdlib.calloc(1, Pool.sizeof);
if (pool)
{
pool.initialize(npages);
@@ -1420,7 +1637,7 @@
goto Lerr;
newnpools = npools + 1;
- newpooltable = cast(Pool **)std.c.stdlib.realloc(pooltable, newnpools * (Pool *).sizeof);
+ newpooltable = cast(Pool **)cstdlib.realloc(pooltable, newnpools * (Pool *).sizeof);
if (!newpooltable)
goto Lerr;
@@ -1430,7 +1647,7 @@
if (pool.opCmp(newpooltable[i]) < 0)
break;
}
- memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof);
+ cstring.memmove(newpooltable + i + 1, newpooltable + i, (npools - i) * (Pool *).sizeof);
newpooltable[i] = pool;
pooltable = newpooltable;
@@ -1443,17 +1660,16 @@
Lerr:
pool.Dtor();
- std.c.stdlib.free(pool);
+ cstdlib.free(pool);
return null;
}
- /*******************************
+ /**
* Allocate a page of bin's.
* Returns:
* 0 failed
*/
-
int allocPage(Bins bin)
{
Pool *pool;
@@ -1490,17 +1706,16 @@
}
- /************************************
+ /**
* Search a range of memory values and mark any pointers into the GC pool.
*/
-
void mark(void *pbot, void *ptop)
{
void **p1 = cast(void **)pbot;
void **p2 = cast(void **)ptop;
uint changes = 0;
- //if (log) debug(PRINTF) printf("Gcx::mark(%x .. %x)\n", pbot, ptop);
+ //printf("marking range: %p -> %p\n", pbot, ptop);
for (; p1 < p2; p1++)
{
Pool *pool;
@@ -1543,8 +1758,9 @@
{
//if (log) debug(PRINTF) printf("\t\tmarking %x\n", p);
pool.mark.set(biti);
- if (!pool.noptrs.test(biti))
- { pool.scan.set(biti);
+ if (!pool.noscan.test(biti))
+ {
+ pool.scan.set(biti);
changes = 1;
}
log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot));
@@ -1555,7 +1771,7 @@
anychanges |= changes;
}
- /*********************************
+ /**
* Return number of full pages free'd.
*/
@@ -1594,6 +1810,9 @@
return result;
}
+ /**
+ *
+ */
size_t fullcollect(void *stackTop)
{
uint n;
@@ -1812,17 +2031,14 @@
{
for (; p < ptop; p += size, biti += bitstride)
{
- if (finalizer && pool.finals.nbits &&
- pool.finals.testClear(biti))
- {
- (*finalizer)(cast(List *)sentinel_add(p), null);
- }
+ if (pool.finals.nbits && pool.finals.testClear(biti))
+ rt_finalize(cast(List *)sentinel_add(p), false);
List *list = cast(List *)p;
//debug(PRINTF) printf("\tcollecting %x\n", list);
log_free(sentinel_add(list));
- debug (MEMSTOMP) memset(p, 0xF3, size);
+ debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
}
pool.pagetable[pn] = B_FREE;
freed += PAGESIZE;
@@ -1837,18 +2053,15 @@
sentinel_Invariant(sentinel_add(p));
pool.freebits.set(biti);
- pool.noptrs.clear(biti);
- if (finalizer && pool.finals.nbits &&
- pool.finals.testClear(biti))
- {
- (*finalizer)(cast(List *)sentinel_add(p), null);
- }
+ pool.noscan.clear(biti);
+ if (pool.finals.nbits && pool.finals.testClear(biti))
+ rt_finalize(cast(List *)sentinel_add(p), false);
List *list = cast(List *)p;
debug(PRINTF) printf("\tcollecting %x\n", list);
log_free(sentinel_add(list));
- debug (MEMSTOMP) memset(p, 0xF3, size);
+ debug (MEMSTOMP) cstring.memset(p, 0xF3, size);
freed += size;
}
@@ -1861,18 +2074,15 @@
{ byte *p = pool.baseAddr + pn * PAGESIZE;
sentinel_Invariant(sentinel_add(p));
- pool.noptrs.clear(biti);
- if (finalizer && pool.finals.nbits &&
- pool.finals.testClear(biti))
- {
- (*finalizer)(sentinel_add(p), null);
- }
+ pool.noscan.clear(biti);
+ if (pool.finals.nbits && pool.finals.testClear(biti))
+ rt_finalize(sentinel_add(p), false);
debug(COLLECT_PRINTF) printf("\tcollecting big %x\n", p);
log_free(sentinel_add(p));
pool.pagetable[pn] = B_FREE;
freedpages++;
- debug (MEMSTOMP) memset(p, 0xF3, PAGESIZE);
+ debug (MEMSTOMP) cstring.memset(p, 0xF3, PAGESIZE);
while (pn + 1 < ncommitted && pool.pagetable[pn + 1] == B_PAGEPLUS)
{
pn++;
@@ -1881,7 +2091,7 @@
debug (MEMSTOMP)
{ p += PAGESIZE;
- memset(p, 0xF3, PAGESIZE);
+ cstring.memset(p, 0xF3, PAGESIZE);
}
}
}
@@ -1950,10 +2160,9 @@
}
- /*********************************
+ /**
* Run finalizer on p when it is free'd.
*/
-
void doFinalize(void *p)
{
Pool *pool = findPool(p);
@@ -1967,7 +2176,7 @@
}
- /*********************************
+ /**
* Indicate that block pointed to by p has possible pointers
* to GC allocated memory in it.
*/
@@ -1977,31 +2186,33 @@
Pool *pool = findPool(p);
assert(pool);
- pool.noptrs.clear((p - pool.baseAddr) / 16);
+ pool.noscan.clear((p - pool.baseAddr) / 16);
}
- /*********************************
+ /**
* Indicate that block pointed to by p has no possible pointers
* to GC allocated memory in it.
*/
-
void HasNoPointers(void *p)
{
//printf("HasNoPointers(%p)\n", p);
Pool *pool = findPool(p);
assert(pool);
- pool.noptrs.set((p - pool.baseAddr) / 16);
+ pool.noscan.set((p - pool.baseAddr) / 16);
}
/***** Leak Detector ******/
+
+
debug (LOGGING)
{
LogArray current;
LogArray prev;
+
void log_init()
{
//debug(PRINTF) printf("+log_init()\n");
@@ -2130,9 +2341,9 @@
byte* topAddr;
GCBits mark; // entries already scanned, or should not be scanned
GCBits scan; // entries that need to be scanned
- GCBits finals; // entries that need finalizer run on them
GCBits freebits; // entries that are on the free list
- GCBits noptrs; // entries that do not contain pointers
+ GCBits finals; // entries that need finalizer run on them
+ GCBits noscan; // entries that should not be scanned
uint npages;
uint ncommitted; // ncommitted <= npages
@@ -2164,17 +2375,18 @@
mark.alloc(poolsize / 16);
scan.alloc(poolsize / 16);
freebits.alloc(poolsize / 16);
- noptrs.alloc(poolsize / 16);
+ noscan.alloc(poolsize / 16);
- pagetable = cast(ubyte*)std.c.stdlib.malloc(npages);
+ pagetable = cast(ubyte*)cstdlib.malloc(npages);
if (!pagetable)
- _d_OutOfMemory();
- memset(pagetable, B_UNCOMMITTED, npages);
+ onOutOfMemoryError();
+ cstring.memset(pagetable, B_UNCOMMITTED, npages);
this.npages = npages;
ncommitted = 0;
}
+
void Dtor()
{
if (baseAddr)
@@ -2199,22 +2411,26 @@
topAddr = null;
}
if (pagetable)
- std.c.stdlib.free(pagetable);
+ cstdlib.free(pagetable);
mark.Dtor();
scan.Dtor();
+ freebits.Dtor();
finals.Dtor();
- freebits.Dtor();
+ noscan.Dtor();
}
+
void Invariant() { }
- invariant
+
+ invariant()
{
//mark.Invariant();
//scan.Invariant();
+ //freebits.Invariant();
//finals.Invariant();
- //freebits.Invariant();
+ //noscan.Invariant();
if (baseAddr)
{
@@ -2231,11 +2447,11 @@
}
}
- /**************************************
+
+ /**
* Allocate n pages from Pool.
* Returns ~0u on failure.
*/
-
uint allocPages(uint n)
{
uint i;
@@ -2258,11 +2474,10 @@
return extendPages(n);
}
- /**************************************
+ /**
* Extend Pool by n pages.
* Returns ~0u on failure.
*/
-
uint extendPages(uint n)
{
//debug(PRINTF) printf("Pool::extendPages(n = %d)\n", n);
@@ -2277,7 +2492,7 @@
//fflush(stdout);
if (os_mem_commit(baseAddr, ncommitted * PAGESIZE, tocommit * PAGESIZE) == 0)
{
- memset(pagetable + ncommitted, B_FREE, tocommit);
+ cstring.memset(pagetable + ncommitted, B_FREE, tocommit);
auto i = ncommitted;
ncommitted += tocommit;
@@ -2292,19 +2507,19 @@
return ~0u;
}
- /**********************************
+
+ /**
* Free npages pages starting with pagenum.
*/
-
void freePages(uint pagenum, uint npages)
{
- memset(&pagetable[pagenum], B_FREE, npages);
+ cstring.memset(&pagetable[pagenum], B_FREE, npages);
}
- /***************************
+
+ /**
* Used for sorting pooltable[]
*/
-
int opCmp(Pool *p2)
{
if (baseAddr < p2.baseAddr)
Index: d/phobos/internal/gc/testgc.d
===================================================================
--- d/phobos/internal/gc/testgc.d (Revision 199)
+++ d/phobos/internal/gc/testgc.d (Arbeitskopie)
@@ -128,7 +128,7 @@
/* ---------------------------- */
-void finalizer(void *p, void *dummy)
+void finalizer(void *p, bool dummy)
{
}
Index: d/phobos/internal/gc/gc.d
===================================================================
--- d/phobos/internal/gc/gc.d (Revision 199)
+++ d/phobos/internal/gc/gc.d (Arbeitskopie)
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com
+ * Copyright (C) 2004-2008 by Digital Mars, www.digitalmars.com
* Written by Walter Bright
*
* This software is provided 'as-is', without any express or implied
@@ -464,13 +464,25 @@
}
-void new_finalizer(void *p, void *dummy)
+void new_finalizer(void *p, bool dummy)
{
//printf("new_finalizer(p = %p)\n", p);
_d_callfinalizer(p);
}
extern (C)
+void _d_callinterfacefinalizer(void *p)
+{
+ //printf("_d_callinterfacefinalizer(p = %p)\n", p);
+ if (p)
+ {
+ Interface *pi = **cast(Interface ***)p;
+ Object o = cast(Object)(p - pi.offset);
+ _d_callfinalizer(cast(void*)o);
+ }
+}
+
+extern (C)
void _d_callfinalizer(void *p)
{
//printf("_d_callfinalizer(p = %p)\n", p);
Index: d/phobos/internal/minit.asm
===================================================================
--- d/phobos/internal/minit.asm (Revision 199)
+++ d/phobos/internal/minit.asm (Arbeitskopie)
@@ -1,11 +1,9 @@
;_ minit.asm
-; Copyright (C) 2001 by Digital Mars
-; All rights reserved
-; www.digitalmars.com
+; Written by Walter Bright
+; Digital Mars
+; http://www.digitalmars.com/d/
+; Placed into the Public Domain
-; Converts array of ModuleInfo pointers to a D dynamic array of them,
-; so they can be accessed via D.
-
include macros.asm
ifdef _WIN32
@@ -14,11 +12,30 @@
DATAGRP EQU DGROUP
endif
+; Provide a default resolution for weak extern records, no way in C
+; to define an omf symbol with a specific value
public __nullext
__nullext equ 0
extrn __moduleinfo_array:near
+; This bit of assembler is needed because, from C or D, one cannot
+; specify the names of data segments. Why does this matter?
+; All the ModuleInfo pointers are placed into a segment named 'FM'.
+; The order in which they are placed in 'FM' is arbitrarily up to the linker.
+; In order to walk all the pointers, we need to be able to find the
+; beginning and the end of the 'FM' segment.
+; This is done by bracketing the 'FM' segment with two other, empty,
+; segments named 'FMB' and 'FME'. Since this module is the only one that
+; ever refers to 'FMB' and 'FME', we get to control the order in which
+; these segments appear relative to 'FM' by using a GROUP statement.
+; So, we have in memory:
+; FMB empty segment
+; FM contains all the pointers
+; FME empty segment
+; and finding the limits of FM is as easy as taking the address of FMB
+; and the address of FME.
+
; These segments bracket FM, which contains the list of ModuleInfo pointers
FMB segment dword use32 public 'DATA'
FMB ends
@@ -40,6 +57,12 @@
begcode minit
+; extern (C) void _minit();
+; Converts array of ModuleInfo pointers to a D dynamic array of them,
+; so they can be accessed via D.
+; Result is written to:
+; extern (C) ModuleInfo[] _moduleinfo_array;
+
public __minit
__minit proc near
mov EDX,offset DATAGRP:FMB
Index: d/Make-lang.in
===================================================================
--- d/Make-lang.in (Revision 199)
+++ d/Make-lang.in (Arbeitskopie)
@@ -167,7 +167,7 @@
cp $(D_DRIVER_NAME)$(exeext) $(D_DRIVER_NAME)-cross$(exeext)
D_DMD_OBJS = \
- d/access.dmd.o d/array.dmd.o d/attrib.dmd.o d/cast.dmd.o d/class.dmd.o d/cond.dmd.o d/constfold.dmd.o d/dchar.dmd.o d/declaration.dmd.o d/delegatize.dmd.o d/doc.dmd.o \
+ d/access.dmd.o d/array.dmd.o d/attrib.dmd.o d/cast.dmd.o d/class.dmd.o d/clone.dmd.o d/cond.dmd.o d/constfold.dmd.o d/dchar.dmd.o d/declaration.dmd.o d/delegatize.dmd.o d/doc.dmd.o \
d/dsymbol.dmd.o d/dump.dmd.o d/entity.dmd.o d/enum.dmd.o d/expression.dmd.o d/func.dmd.o d/gnuc.dmd.o d/hdrgen.dmd.o d/html.dmd.o d/identifier.dmd.o d/import.dmd.o \
d/init.dmd.o d/inline.dmd.o d/interpret.dmd.o d/lexer.dmd.o d/lstring.dmd.o d/macro.dmd.o d/mangle.dmd.o d/mars.dmd.o d/mem.dmd.o d/mtype.dmd.o d/module.dmd.o d/opover.dmd.o d/optimize.dmd.o d/parse.dmd.o \
d/root.dmd.o d/scope.dmd.o d/statement.dmd.o d/staticassert.dmd.o d/stringtable.dmd.o d/struct.dmd.o d/template.dmd.o \
Index: d/dmd/mtype.c
===================================================================
--- d/dmd/mtype.c (Revision 199)
+++ d/dmd/mtype.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -136,8 +136,13 @@
Type::Type(TY ty, Type *next)
{
this->ty = ty;
+ this->mod = 0;
this->next = next;
this->deco = NULL;
+#if V2
+ this->cto = NULL;
+ this->ito = NULL;
+#endif
this->pto = NULL;
this->rto = NULL;
this->arrayof = NULL;
@@ -361,16 +366,6 @@
}
/********************************
- * Name mangling.
- */
-
-void Type::toTypeInfoBuffer(OutBuffer *buf)
-{
- assert(0);
- buf->writeByte(mangleChar[ty]);
-}
-
-/********************************
* For pretty-printing a type.
*/
@@ -379,27 +374,54 @@
HdrGenState hgs;
buf = new OutBuffer();
- toCBuffer2(buf, NULL, &hgs);
+ toCBuffer(buf, NULL, &hgs);
return buf->toChars();
}
void Type::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
- OutBuffer tbuf;
+ toCBuffer2(buf, hgs, 0);
+ if (ident)
+ { buf->writeByte(' ');
+ buf->writestring(ident->toChars());
+ }
+}
- toCBuffer2(&tbuf, ident, hgs);
- buf->write(&tbuf);
+void Type::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
+{
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
+ buf->writestring(toChars());
}
-void Type::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void Type::toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- buf->prependstring(toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { char *p;
+
+ switch (this->mod)
+ {
+ case 0:
+ toCBuffer2(buf, hgs, this->mod);
+ break;
+ case MODconst:
+ p = "const(";
+ goto L1;
+ case MODinvariant:
+ p = "invariant(";
+ L1: buf->writestring(p);
+ toCBuffer2(buf, hgs, this->mod);
+ buf->writeByte(')');
+ break;
+ default:
+ assert(0);
+ }
}
}
+
/************************************
*/
@@ -511,7 +533,7 @@
}
-Expression *Type::defaultInit()
+Expression *Type::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("Type::defaultInit() '%s'\n", toChars());
@@ -578,8 +600,7 @@
{
if (ty == Tvoid)
error(loc, "void does not have an initializer");
- e = defaultInit();
- e->loc = loc;
+ e = defaultInit(loc);
}
else if (ident == Id::mangleof)
{
@@ -656,7 +677,7 @@
e->isBool(0) &&
v->type->toBasetype()->ty == Tstruct)
{
- e = v->type->defaultInit();
+ e = v->type->defaultInit(loc);
}
}
e = e->optimize(WANTvalue | WANTinterpret);
@@ -666,8 +687,7 @@
return e;
}
#endif
- Expression *ex = defaultInit();
- ex->loc = e->loc;
+ Expression *ex = defaultInit(e->loc);
return ex;
}
}
@@ -931,13 +951,14 @@
return dstring;
}
-void TypeBasic::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeBasic::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- buf->prependstring(cstring);
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ //printf("TypeBasic::toCBuffer2(mod = %d, this->mod = %d)\n", mod, this->mod);
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ buf->writestring(dstring);
}
d_uns64 TypeBasic::size(Loc loc)
@@ -1381,7 +1402,7 @@
return e;
}
-Expression *TypeBasic::defaultInit()
+Expression *TypeBasic::defaultInit(Loc loc)
{ integer_t value = 0;
#if LOGDEFAULTINIT
@@ -1407,9 +1428,9 @@
case Tcomplex32:
case Tcomplex64:
case Tcomplex80:
- return getProperty(0, Id::nan);
+ return getProperty(loc, Id::nan);
}
- return new IntegerExp(0, value, this);
+ return new IntegerExp(loc, value, this);
}
int TypeBasic::isZeroInit()
@@ -1649,59 +1670,7 @@
return e;
}
-void TypeArray::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
-#if 1
- OutBuffer buf2;
- toPrettyBracket(&buf2, hgs);
- buf->prependstring(buf2.toChars());
- if (ident)
- {
- buf->writeByte(' ');
- buf->writestring(ident->toChars());
- }
- next->toCBuffer2(buf, NULL, hgs);
-#elif 1
- // The D way
- Type *t;
- OutBuffer buf2;
- for (t = this; 1; t = t->next)
- { TypeArray *ta;
- ta = dynamic_cast<TypeArray *>(t);
- if (!ta)
- break;
- ta->toPrettyBracket(&buf2, hgs);
- }
- buf->prependstring(buf2.toChars());
- if (ident)
- {
- buf2.writestring(ident->toChars());
- }
- t->toCBuffer2(buf, NULL, hgs);
-#else
- // The C way
- if (buf->offset)
- { buf->bracket('(', ')');
- assert(!ident);
- }
- else if (ident)
- buf->writestring(ident->toChars());
- Type *t = this;
- do
- { Expression *dim;
- buf->writeByte('[');
- dim = ((TypeSArray *)t)->dim;
- if (dim)
- buf->printf("%lld", dim->toInteger());
- buf->writeByte(']');
- t = t->next;
- } while (t->ty == Tsarray);
- t->toCBuffer2(buf, NULL, hgs);
-#endif
-}
-
-
/***************************** TypeSArray *****************************/
TypeSArray::TypeSArray(Type *t, Expression *dim)
@@ -1886,6 +1855,14 @@
dim = semanticLength(sc, tbn, dim);
dim = dim->optimize(WANTvalue | WANTinterpret);
+ if (sc->parameterSpecialization && dim->op == TOKvar &&
+ ((VarExp *)dim)->var->storage_class & STCtemplateparameter)
+ {
+ /* It could be a template parameter N which has no value yet:
+ * template Foo(T : T[N], size_t N);
+ */
+ return this;
+ }
integer_t d1 = dim->toInteger();
dim = dim->castTo(sc, tsize_t);
dim = dim->optimize(WANTvalue);
@@ -1954,15 +1931,13 @@
next->toDecoBuffer(buf);
}
-void TypeSArray::toTypeInfoBuffer(OutBuffer *buf)
+void TypeSArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- buf->writeByte(mangleChar[Tarray]);
- if (next)
- next->toTypeInfoBuffer(buf);
-}
-
-void TypeSArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
-{
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
+ next->toCBuffer2(buf, hgs, this->mod);
buf->printf("[%s]", dim->toChars());
}
@@ -2030,12 +2005,12 @@
return Type::implicitConvTo(to);
}
-Expression *TypeSArray::defaultInit()
+Expression *TypeSArray::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeSArray::defaultInit() '%s'\n", toChars());
#endif
- return next->defaultInit();
+ return next->defaultInit(loc);
}
int TypeSArray::isZeroInit()
@@ -2120,15 +2095,13 @@
next->toDecoBuffer(buf);
}
-void TypeDArray::toTypeInfoBuffer(OutBuffer *buf)
+void TypeDArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- buf->writeByte(mangleChar[ty]);
- if (next)
- next->toTypeInfoBuffer(buf);
-}
-
-void TypeDArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
-{
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
+ next->toCBuffer2(buf, hgs, this->mod);
buf->writestring("[]");
}
@@ -2188,13 +2161,13 @@
return Type::implicitConvTo(to);
}
-Expression *TypeDArray::defaultInit()
+Expression *TypeDArray::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeDArray::defaultInit() '%s'\n", toChars());
#endif
Expression *e;
- e = new NullExp(0);
+ e = new NullExp(loc);
e->type = this;
return e;
}
@@ -2393,24 +2366,25 @@
next->toDecoBuffer(buf);
}
-void TypeAArray::toPrettyBracket(OutBuffer *buf, HdrGenState *hgs)
+void TypeAArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
+ next->toCBuffer2(buf, hgs, this->mod);
buf->writeByte('[');
- { OutBuffer ibuf;
-
- index->toCBuffer2(&ibuf, NULL, hgs);
- buf->write(&ibuf);
- }
+ index->toCBuffer2(buf, hgs, 0);
buf->writeByte(']');
}
-Expression *TypeAArray::defaultInit()
+Expression *TypeAArray::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeAArray::defaultInit() '%s'\n", toChars());
#endif
Expression *e;
- e = new NullExp(0);
+ e = new NullExp(loc);
e->type = this;
return e;
}
@@ -2465,16 +2439,16 @@
return PTRSIZE;
}
-void TypePointer::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypePointer::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
//printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
- buf->prependstring("*");
- if (ident)
- {
- buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
- next->toCBuffer2(buf, NULL, hgs);
+ next->toCBuffer2(buf, hgs, this->mod);
+ if (next->ty != Tfunction)
+ buf->writeByte('*');
}
MATCH TypePointer::implicitConvTo(Type *to)
@@ -2512,13 +2486,13 @@
return TRUE;
}
-Expression *TypePointer::defaultInit()
+Expression *TypePointer::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypePointer::defaultInit() '%s'\n", toChars());
#endif
Expression *e;
- e = new NullExp(0);
+ e = new NullExp(loc);
e->type = this;
return e;
}
@@ -2559,14 +2533,14 @@
return PTRSIZE;
}
-void TypeReference::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeReference::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- buf->prependstring("&");
- if (ident)
- {
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
- next->toCBuffer2(buf, NULL, hgs);
+ next->toCBuffer2(buf, hgs, this->mod);
+ buf->writeByte('&');
}
Expression *TypeReference::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -2579,13 +2553,13 @@
return next->dotExp(sc, e, ident);
}
-Expression *TypeReference::defaultInit()
+Expression *TypeReference::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeReference::defaultInit() '%s'\n", toChars());
#endif
Expression *e;
- e = new NullExp(0);
+ e = new NullExp(loc);
e->type = this;
return e;
}
@@ -2735,7 +2709,7 @@
inuse--;
}
-void TypeFunction::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeFunction::toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
{
char *p = NULL;
@@ -2744,6 +2718,8 @@
return;
}
inuse++;
+ if (next && (!ident || ident->toHChars2() == ident->toChars()))
+ next->toCBuffer2(buf, hgs, 0);
if (hgs->ddoc != 1)
{
switch (linkage)
@@ -2758,25 +2734,45 @@
}
}
- if (buf->offset)
- {
if (!hgs->hdrgen && p)
- buf->prependstring(p);
- buf->bracket('(', ')');
- assert(!ident);
- }
- else
- {
- if (!hgs->hdrgen && p)
buf->writestring(p);
if (ident)
{ buf->writeByte(' ');
buf->writestring(ident->toHChars2());
}
+ Argument::argsToCBuffer(buf, hgs, parameters, varargs);
+ inuse--;
+}
+
+void TypeFunction::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
+{
+ char *p = NULL;
+
+ if (inuse)
+ { inuse = 2; // flag error to caller
+ return;
}
+ inuse++;
+ if (next)
+ next->toCBuffer2(buf, hgs, 0);
+ if (hgs->ddoc != 1)
+ {
+ switch (linkage)
+ {
+ case LINKd: p = NULL; break;
+ case LINKc: p = "C "; break;
+ case LINKwindows: p = "Windows "; break;
+ case LINKpascal: p = "Pascal "; break;
+ case LINKcpp: p = "C++ "; break;
+ default:
+ assert(0);
+ }
+ }
+
+ if (!hgs->hdrgen && p)
+ buf->writestring(p);
+ buf->writestring(" function");
Argument::argsToCBuffer(buf, hgs, parameters, varargs);
- if (next && (!ident || ident->toHChars2() == ident->toChars()))
- next->toCBuffer2(buf, NULL, hgs);
inuse--;
}
@@ -2789,38 +2785,50 @@
}
//printf("TypeFunction::semantic() this = %p\n", this);
- linkage = sc->linkage;
- if (!next)
+ TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
+ memcpy(tf, this, sizeof(TypeFunction));
+ if (parameters)
+ { tf->parameters = (Arguments *)parameters->copy();
+ for (size_t i = 0; i < parameters->dim; i++)
+ { Argument *arg = (Argument *)parameters->data[i];
+ Argument *cpy = (Argument *)mem.malloc(sizeof(Argument));
+ memcpy(cpy, arg, sizeof(Argument));
+ tf->parameters->data[i] = (void *)cpy;
+ }
+ }
+
+ tf->linkage = sc->linkage;
+ if (!tf->next)
{
assert(global.errors);
- next = tvoid;
+ tf->next = tvoid;
}
- next = next->semantic(loc,sc);
- if (next->toBasetype()->ty == Tsarray)
- { error(loc, "functions cannot return static array %s", next->toChars());
- next = Type::terror;
+ tf->next = tf->next->semantic(loc,sc);
+ if (tf->next->toBasetype()->ty == Tsarray)
+ { error(loc, "functions cannot return static array %s", tf->next->toChars());
+ tf->next = Type::terror;
}
- if (next->toBasetype()->ty == Tfunction)
+ if (tf->next->toBasetype()->ty == Tfunction)
{ error(loc, "functions cannot return a function");
- next = Type::terror;
+ tf->next = Type::terror;
}
- if (next->toBasetype()->ty == Ttuple)
+ if (tf->next->toBasetype()->ty == Ttuple)
{ error(loc, "functions cannot return a tuple");
- next = Type::terror;
+ tf->next = Type::terror;
}
- if (next->isauto() && !(sc->flags & SCOPEctor))
- error(loc, "functions cannot return auto %s", next->toChars());
+ if (tf->next->isauto() && !(sc->flags & SCOPEctor))
+ error(loc, "functions cannot return auto %s", tf->next->toChars());
- if (parameters)
- { size_t dim = Argument::dim(parameters);
+ if (tf->parameters)
+ { size_t dim = Argument::dim(tf->parameters);
for (size_t i = 0; i < dim; i++)
- { Argument *arg = Argument::getNth(parameters, i);
+ { Argument *arg = Argument::getNth(tf->parameters, i);
Type *t;
- inuse++;
+ tf->inuse++;
arg->type = arg->type->semantic(loc,sc);
- if (inuse == 1) inuse--;
+ if (tf->inuse == 1) tf->inuse--;
t = arg->type->toBasetype();
if (arg->storageClass & (STCout | STCref | STClazy))
@@ -2842,27 +2850,27 @@
* change.
*/
if (t->ty == Ttuple)
- { dim = Argument::dim(parameters);
+ { dim = Argument::dim(tf->parameters);
i--;
}
}
}
- deco = merge()->deco;
+ tf->deco = tf->merge()->deco;
- if (inuse)
+ if (tf->inuse)
{ error(loc, "recursive type");
- inuse = 0;
+ tf->inuse = 0;
return terror;
}
- if (varargs == 1 && linkage != LINKd && Argument::dim(parameters) == 0)
+ if (tf->varargs == 1 && tf->linkage != LINKd && Argument::dim(tf->parameters) == 0)
error(loc, "variadic functions with non-D linkage must have at least one parameter");
/* Don't return merge(), because arg identifiers and default args
* can be different
* even though the types match
*/
- return this;
+ return tf;
}
/********************************
@@ -3035,37 +3043,26 @@
return PTRSIZE * 2;
}
-void TypeDelegate::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeDelegate::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
-#if 1
- OutBuffer args;
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
TypeFunction *tf = (TypeFunction *)next;
- Argument::argsToCBuffer(&args, hgs, tf->parameters, tf->varargs);
- buf->prependstring(args.toChars());
- buf->prependstring(" delegate");
- if (ident)
- {
- buf->writeByte(' ');
- buf->writestring(ident->toChars());
- }
- next->next->toCBuffer2(buf, NULL, hgs);
-#else
- next->toCBuffer2(buf, Id::delegate, hgs);
- if (ident)
- {
- buf->writestring(ident->toChars());
- }
-#endif
+ tf->next->toCBuffer2(buf, hgs, 0);
+ buf->writestring(" delegate");
+ Argument::argsToCBuffer(buf, hgs, tf->parameters, tf->varargs);
}
-Expression *TypeDelegate::defaultInit()
+Expression *TypeDelegate::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeDelegate::defaultInit() '%s'\n", toChars());
#endif
Expression *e;
- e = new NullExp(0);
+ e = new NullExp(loc);
e->type = this;
return e;
}
@@ -3158,7 +3155,7 @@
idents.push(ident);
}
-void TypeQualified::toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeQualified::toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs)
{
int i;
@@ -3388,17 +3385,14 @@
//buf->printf("%c%s", mangleChar[ty], name);
}
-void TypeIdentifier::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeIdentifier::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- OutBuffer tmp;
-
- tmp.writestring(this->ident->toChars());
- toCBuffer2Helper(&tmp, NULL, hgs);
- buf->prependstring(tmp.toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ buf->writestring(this->ident->toChars());
+ toCBuffer2Helper(buf, hgs);
}
/*************************************
@@ -3520,17 +3514,14 @@
}
-void TypeInstance::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeInstance::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- OutBuffer tmp;
-
- tempinst->toCBuffer(&tmp, hgs);
- toCBuffer2Helper(&tmp, NULL, hgs);
- buf->prependstring(tmp.toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ tempinst->toCBuffer(buf, hgs);
+ toCBuffer2Helper(buf, hgs);
}
void TypeInstance::resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps)
@@ -3623,19 +3614,16 @@
return t->toDsymbol(sc);
}
-void TypeTypeof::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeTypeof::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- OutBuffer tmp;
-
- tmp.writestring("typeof(");
- exp->toCBuffer(&tmp, hgs);
- tmp.writeByte(')');
- toCBuffer2Helper(&tmp, NULL, hgs);
- buf->prependstring(tmp.toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ buf->writestring("typeof(");
+ exp->toCBuffer(buf, hgs);
+ buf->writeByte(')');
+ toCBuffer2Helper(buf, hgs);
}
Type *TypeTypeof::semantic(Loc loc, Scope *sc)
@@ -3812,18 +3800,13 @@
buf->printf("%c%s", mangleChar[ty], name);
}
-void TypeEnum::toTypeInfoBuffer(OutBuffer *buf)
+void TypeEnum::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- toBasetype()->toTypeInfoBuffer(buf);
-}
-
-void TypeEnum::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
- buf->prependstring(sym->toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ buf->writestring(sym->toChars());
}
Expression *TypeEnum::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -3871,7 +3854,7 @@
{
if (!sym->symtab)
goto Lfwd;
- e = defaultInit();
+ e = defaultInit(loc);
}
else
{
@@ -3920,14 +3903,14 @@
return m;
}
-Expression *TypeEnum::defaultInit()
+Expression *TypeEnum::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeEnum::defaultInit() '%s'\n", toChars());
#endif
// Initialize to first member of enum
Expression *e;
- e = new IntegerExp(0, sym->defaultval, this);
+ e = new IntegerExp(loc, sym->defaultval, this);
return e;
}
@@ -3993,19 +3976,14 @@
buf->printf("%c%s", mangleChar[ty], name);
}
-void TypeTypedef::toTypeInfoBuffer(OutBuffer *buf)
+void TypeTypedef::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- sym->basetype->toTypeInfoBuffer(buf);
-}
-
-void TypeTypedef::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
//printf("TypeTypedef::toCBuffer2() '%s'\n", sym->toChars());
- buf->prependstring(sym->toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ buf->writestring(sym->toChars());
}
Expression *TypeTypedef::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4020,6 +3998,15 @@
return sym->basetype->dotExp(sc, e, ident);
}
+Expression *TypeTypedef::getProperty(Loc loc, Identifier *ident)
+{
+ if (ident == Id::init)
+ {
+ return Type::getProperty(loc, ident);
+ }
+ return sym->basetype->getProperty(loc, ident);
+}
+
int TypeTypedef::isbit()
{
return sym->basetype->isbit();
@@ -4095,7 +4082,7 @@
return m;
}
-Expression *TypeTypedef::defaultInit()
+Expression *TypeTypedef::defaultInit(Loc loc)
{ Expression *e;
Type *bt;
@@ -4108,7 +4095,7 @@
return sym->init->toExpression();
}
bt = sym->basetype;
- e = bt->defaultInit();
+ e = bt->defaultInit(loc);
e->type = this;
while (bt->ty == Tsarray)
{
@@ -4212,20 +4199,19 @@
buf->printf("%c%s", mangleChar[ty], name);
}
-void TypeStruct::toTypeInfoBuffer(OutBuffer *buf)
+void TypeStruct::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- toDecoBuffer(buf);
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
+ TemplateInstance *ti = sym->parent->isTemplateInstance();
+ if (ti && ti->toAlias() == sym)
+ buf->writestring(ti->toChars());
+ else
+ buf->writestring(sym->toChars());
}
-
-void TypeStruct::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
-{
- buf->prependbyte(' ');
- buf->prependstring(toChars());
- if (ident)
- buf->writestring(ident->toChars());
-}
-
Expression *TypeStruct::dotExp(Scope *sc, Expression *e, Identifier *ident)
{ unsigned offset;
@@ -4323,6 +4309,18 @@
return e;
}
+ TemplateInstance *ti = s->isTemplateInstance();
+ if (ti)
+ { if (!ti->semanticdone)
+ ti->semantic(sc);
+ s = ti->inst->toAlias();
+ if (!s->isTemplateInstance())
+ goto L1;
+ Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
+ de->type = e->type;
+ return de;
+ }
+
d = s->isDeclaration();
#ifdef DEBUG
if (!d)
@@ -4386,7 +4384,7 @@
return sym->structalign;
}
-Expression *TypeStruct::defaultInit()
+Expression *TypeStruct::defaultInit(Loc loc)
{ Symbol *s;
Declaration *d;
@@ -4477,13 +4475,13 @@
buf->printf("%c%s", mangleChar[ty], name);
}
-void TypeClass::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeClass::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- buf->prependstring(sym->toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
}
+ buf->writestring(sym->toChars());
}
Expression *TypeClass::dotExp(Scope *sc, Expression *e, Identifier *ident)
@@ -4648,6 +4646,18 @@
return e;
}
+ TemplateInstance *ti = s->isTemplateInstance();
+ if (ti)
+ { if (!ti->semanticdone)
+ ti->semantic(sc);
+ s = ti->inst->toAlias();
+ if (!s->isTemplateInstance())
+ goto L1;
+ Expression *de = new DotExp(e->loc, e, new ScopeExp(e->loc, ti));
+ de->type = e->type;
+ return de;
+ }
+
d = s->isDeclaration();
if (!d)
{
@@ -4770,13 +4780,13 @@
return MATCHnomatch;
}
-Expression *TypeClass::defaultInit()
+Expression *TypeClass::defaultInit(Loc loc)
{
#if LOGDEFAULTINIT
printf("TypeClass::defaultInit() '%s'\n", toChars());
#endif
Expression *e;
- e = new NullExp(0);
+ e = new NullExp(loc);
e->type = this;
return e;
}
@@ -4899,15 +4909,9 @@
return NULL;
}
-void TypeTuple::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeTuple::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- OutBuffer buf2;
- Argument::argsToCBuffer(&buf2, hgs, arguments, 0);
- buf->prependstring(buf2.toChars());
- if (ident)
- { buf->writeByte(' ');
- buf->writestring(ident->toChars());
- }
+ Argument::argsToCBuffer(buf, hgs, arguments, 0);
}
void TypeTuple::toDecoBuffer(OutBuffer *buf)
@@ -5061,20 +5065,16 @@
}
}
-void TypeSlice::toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs)
+void TypeSlice::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
{
- OutBuffer buf2;
+ if (mod != this->mod)
+ { toCBuffer3(buf, hgs, mod);
+ return;
+ }
+ next->toCBuffer2(buf, hgs, this->mod);
- buf2.printf("[%s .. ", lwr->toChars());
- buf2.printf("%s]", upr->toChars());
-
- buf->prependstring(buf2.toChars());
- if (ident)
- {
- buf->writeByte(' ');
- buf->writestring(ident->toChars());
- }
- next->toCBuffer2(buf, NULL, hgs);
+ buf->printf("[%s .. ", lwr->toChars());
+ buf->printf("%s]", upr->toChars());
}
/***************************** Argument *****************************/
@@ -5131,7 +5131,7 @@
buf->writeByte(',');
arg = (Argument *)args->data[i];
argbuf.reset();
- arg->type->toCBuffer2(&argbuf, NULL, &hgs);
+ arg->type->toCBuffer2(&argbuf, &hgs, 0);
buf->write(&argbuf);
}
if (varargs)
@@ -5167,7 +5167,7 @@
else if (arg->storageClass & STClazy)
buf->writestring("lazy ");
argbuf.reset();
- arg->type->toCBuffer2(&argbuf, arg->ident, hgs);
+ arg->type->toCBuffer(&argbuf, arg->ident, hgs);
if (arg->defaultArg)
{
argbuf.writestring(" = ");
Index: d/dmd/optimize.c
===================================================================
--- d/dmd/optimize.c (Revision 199)
+++ d/dmd/optimize.c (Arbeitskopie)
@@ -295,7 +295,7 @@
if (fd)
{
Expression *eresult = fd->interpret(NULL, arguments);
- if (eresult)
+ if (eresult && eresult != EXP_VOID_INTERPRET)
e = eresult;
else if (result & WANTinterpret)
error("cannot evaluate %s at compile time", toChars());
Index: d/dmd/init.c
===================================================================
--- d/dmd/init.c (Revision 199)
+++ d/dmd/init.c (Arbeitskopie)
@@ -185,7 +185,7 @@
s = ad->search(loc, id, 0);
if (!s)
{
- error("'%s' is not a member of '%s'", id->toChars(), t->toChars());
+ error(loc, "'%s' is not a member of '%s'", id->toChars(), t->toChars());
continue;
}
Index: d/dmd/mtype.h
===================================================================
--- d/dmd/mtype.h (Revision 199)
+++ d/dmd/mtype.h (Arbeitskopie)
@@ -118,6 +118,9 @@
struct Type : Object
{
TY ty;
+ unsigned char mod; // modifiers (MODconst, MODinvariant)
+ #define MODconst 1 // type is const
+ #define MODinvariant 2 // type is invariant
Type *next;
char *deco;
Type *pto; // merged pointer to this type
@@ -206,10 +209,10 @@
virtual unsigned alignsize();
virtual Type *semantic(Loc loc, Scope *sc);
virtual void toDecoBuffer(OutBuffer *buf);
- virtual void toTypeInfoBuffer(OutBuffer *buf);
Type *merge();
- void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
- virtual void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
virtual int isbit();
virtual int isintegral();
virtual int isfloating(); // real, imaginary, or complex
@@ -233,7 +236,7 @@
virtual Expression *getProperty(Loc loc, Identifier *ident);
virtual Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
virtual unsigned memalign(unsigned salign);
- virtual Expression *defaultInit();
+ virtual Expression *defaultInit(Loc loc = 0);
virtual int isZeroInit(); // if initializer is 0
virtual dt_t **toDt(dt_t **pdt);
Identifier *getTypeInfoIdent(int internal);
@@ -273,7 +276,7 @@
Expression *getProperty(Loc loc, Identifier *ident);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
char *toChars();
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
int isintegral();
int isbit();
int isfloating();
@@ -283,7 +286,7 @@
int isscalar();
int isunsigned();
MATCH implicitConvTo(Type *to);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
int builtinTypeInfo();
@@ -294,8 +297,6 @@
struct TypeArray : Type
{
TypeArray(TY ty, Type *next);
- virtual void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs) = 0;
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
};
@@ -311,14 +312,13 @@
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
void toDecoBuffer(OutBuffer *buf);
- void toTypeInfoBuffer(OutBuffer *buf);
- void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit();
unsigned memalign(unsigned salign);
MATCH implicitConvTo(Type *to);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
dt_t **toDt(dt_t **pdt);
dt_t **toDtElem(dt_t **pdt, Expression *e);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -339,14 +339,13 @@
unsigned alignsize();
Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toTypeInfoBuffer(OutBuffer *buf);
- void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
int isString();
int isZeroInit();
int checkBoolean();
MATCH implicitConvTo(Type *to);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int builtinTypeInfo();
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
@@ -364,9 +363,9 @@
d_uns64 size(Loc loc);
Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -384,10 +383,10 @@
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
MATCH implicitConvTo(Type *to);
int isscalar();
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
TypeInfoDeclaration *getTypeInfoDeclaration();
int hasPointers();
@@ -400,9 +399,9 @@
TypeReference(Type *t);
Type *syntaxCopy();
d_uns64 size(Loc loc);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
};
@@ -425,7 +424,8 @@
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
Type *reliesOnTident();
@@ -443,8 +443,8 @@
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
- Expression *defaultInit();
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
+ Expression *defaultInit(Loc loc);
int isZeroInit();
int checkBoolean();
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -462,7 +462,7 @@
TypeQualified(TY ty, Loc loc);
void syntaxCopyHelper(TypeQualified *t);
void addIdent(Identifier *ident);
- void toCBuffer2Helper(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2Helper(OutBuffer *buf, HdrGenState *hgs);
d_uns64 size(Loc loc);
void resolveHelper(Loc loc, Scope *sc, Dsymbol *s, Dsymbol *scopesym,
Expression **pe, Type **pt, Dsymbol **ps);
@@ -476,7 +476,7 @@
Type *syntaxCopy();
//char *toChars();
void toDecoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Dsymbol *toDsymbol(Scope *sc);
Type *semantic(Loc loc, Scope *sc);
@@ -495,7 +495,7 @@
Type *syntaxCopy();
//char *toChars();
//void toDecoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
Type *semantic(Loc loc, Scope *sc);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -508,7 +508,7 @@
TypeTypeof(Loc loc, Expression *exp);
Type *syntaxCopy();
Dsymbol *toDsymbol(Scope *sc);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Type *semantic(Loc loc, Scope *sc);
d_uns64 size(Loc loc);
};
@@ -525,11 +525,10 @@
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toTypeInfoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
unsigned memalign(unsigned salign);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
int checkBoolean();
dt_t **toDt(dt_t **pdt);
@@ -551,8 +550,7 @@
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toTypeInfoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
Expression *getProperty(Loc loc, Identifier *ident);
int isintegral();
@@ -561,7 +559,7 @@
int isunsigned();
MATCH implicitConvTo(Type *to);
Type *toBasetype();
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -582,9 +580,9 @@
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toTypeInfoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+ Expression *getProperty(Loc loc, Identifier *ident);
int isbit();
int isintegral();
int isfloating();
@@ -596,7 +594,7 @@
int checkBoolean();
Type *toBasetype();
MATCH implicitConvTo(Type *to);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
dt_t **toDt(dt_t **pdt);
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
@@ -618,12 +616,12 @@
Type *semantic(Loc loc, Scope *sc);
Dsymbol *toDsymbol(Scope *sc);
void toDecoBuffer(OutBuffer *buf);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
ClassDeclaration *isClassHandle();
int isBaseOf(Type *t, target_ptrdiff_t *poffset);
MATCH implicitConvTo(Type *to);
- Expression *defaultInit();
+ Expression *defaultInit(Loc loc);
int isZeroInit();
MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
int isauto();
@@ -646,7 +644,7 @@
Type *semantic(Loc loc, Scope *sc);
int equals(Object *o);
Type *reliesOnTident();
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
void toDecoBuffer(OutBuffer *buf);
Expression *getProperty(Loc loc, Identifier *ident);
TypeInfoDeclaration *getTypeInfoDeclaration();
@@ -661,7 +659,7 @@
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void resolve(Loc loc, Scope *sc, Expression **pe, Type **pt, Dsymbol **ps);
- void toCBuffer2(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
+ void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
};
/**************************************************************/
Index: d/dmd/statement.c
===================================================================
--- d/dmd/statement.c (Revision 199)
+++ d/dmd/statement.c (Arbeitskopie)
@@ -528,7 +528,7 @@
int CompoundStatement::fallOffEnd()
{ int falloff = TRUE;
- //printf("CompoundStatement::fallOffEnd()\n");
+ //printf("CompoundStatement::fallOffEnd() %s\n", toChars());
for (int i = 0; i < statements->dim; i++)
{ Statement *s = (Statement *)statements->data[i];
@@ -648,25 +648,18 @@
}
int UnrolledLoopStatement::fallOffEnd()
-{ int falloff = TRUE;
-
+{
//printf("UnrolledLoopStatement::fallOffEnd()\n");
for (size_t i = 0; i < statements->dim; i++)
{ Statement *s = (Statement *)statements->data[i];
- if (!s)
- continue;
-
- if (!falloff && global.params.warnings && !s->comeFrom())
- {
- fprintf(stdmsg, "warning - ");
- s->error("statement is not reachable");
- }
- falloff = s->fallOffEnd();
+ if (s)
+ s->fallOffEnd();
}
- return falloff;
+ return TRUE;
}
+
int UnrolledLoopStatement::comeFrom()
{ int comefrom = FALSE;
@@ -1998,6 +1991,7 @@
{ condition = condition->integralPromotions(sc);
condition->checkIntegral();
}
+ condition = condition->optimize(WANTvalue);
sc = sc->push();
sc->sbreak = this;
@@ -3222,7 +3216,7 @@
int TryFinallyStatement::fallOffEnd()
{ int result;
- result = body->fallOffEnd();
+ result = body ? body->fallOffEnd() : TRUE;
// if (finalbody)
// result = finalbody->fallOffEnd();
return result;
Index: d/dmd/class.c
===================================================================
--- d/dmd/class.c (Revision 199)
+++ d/dmd/class.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -652,6 +652,7 @@
sizeok = 1;
Module::dprogress++;
+ dtor = buildDtor(sc);
sc->pop();
Index: d/dmd/toobj.c
===================================================================
--- d/dmd/toobj.c (Revision 199)
+++ d/dmd/toobj.c (Arbeitskopie)
@@ -100,7 +100,7 @@
{
Symbol *msym = toSymbol();
unsigned offset;
- unsigned sizeof_ModuleInfo = 12 * PTRSIZE;
+ unsigned sizeof_ModuleInfo = 14 * PTRSIZE;
//////////////////////////////////////////////
@@ -118,6 +118,8 @@
void *ctor;
void *dtor;
void *unitTest;
+ const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
+ void *ictor;
}
*/
dt_t *dt = NULL;
@@ -180,9 +182,9 @@
dtdword(&dt, 0);
if (needmoduleinfo)
- dti32(&dt, 0, true); // flags (4 means MIstandalone)
+ dti32(&dt, 8|0, true); // flags (4 means MIstandalone)
else
- dti32(&dt, 4, true); // flags (4 means MIstandalone)
+ dti32(&dt, 8|4, true); // flags (4 means MIstandalone)
if (sctor)
dtxoff(&dt, sctor, 0, TYnptr);
@@ -199,6 +201,13 @@
else
dtdword(&dt, 0);
+ dtdword(&dt, 0); // xgetMembers
+
+ if (sictor)
+ dtxoff(&dt, sictor, 0, TYnptr);
+ else
+ dtdword(&dt, 0);
+
//////////////////////////////////////////////
#ifdef IN_GCC
@@ -283,7 +292,6 @@
{ unsigned i;
unsigned offset;
Symbol *sinit;
- Symbol *sdtor;
enum_SC scclass;
//printf("ClassDeclaration::toObjFile('%s')\n", toChars());
@@ -309,8 +317,9 @@
member = (Dsymbol *)members->data[i];
member->toObjFile();
}
-
// Build destructor by aggregating dtors[]
+#if 0
+ Symbol *sdtor;
#ifndef IN_GCC
switch (dtors.dim)
{ case 0:
@@ -371,7 +380,7 @@
#else
sdtor = d_gcc_aggregate_dtors(this);
#endif
-
+#endif
// Generate C symbols
toSymbol();
toVtblSymbol();
@@ -458,8 +467,8 @@
dtdword(&dt, 0);
// destructor
- if (sdtor)
- dtxoff(&dt, sdtor, 0, TYnptr);
+ if (dtor)
+ dtxoff(&dt, dtor->toSymbol(), 0, TYnptr);
else
dtdword(&dt, 0);
Index: d/dmd/declaration.c
===================================================================
--- d/dmd/declaration.c (Revision 199)
+++ d/dmd/declaration.c (Arbeitskopie)
@@ -35,6 +35,7 @@
: Dsymbol(id)
{
type = NULL;
+ originalType = NULL;
storage_class = STCundefined;
protection = PROTundefined;
linkage = LINKdefault;
@@ -627,9 +628,13 @@
* declarations.
*/
storage_class &= ~STCauto;
+ originalType = type;
}
else
+ { if (!originalType)
+ originalType = type;
type = type->semantic(loc, sc);
+ }
type->checkDeprecated(loc, sc);
linkage = sc->linkage;
@@ -674,6 +679,7 @@
size_t nelems = Argument::dim(tt->arguments);
Objects *exps = new Objects();
exps->setDim(nelems);
+ Expression *ie = init ? init->toExpression() : NULL;
for (size_t i = 0; i < nelems; i++)
{ Argument *arg = Argument::getNth(tt->arguments, i);
@@ -684,7 +690,16 @@
char *name = (char *)buf.extractData();
Identifier *id = new Identifier(name, TOKidentifier);
- VarDeclaration *v = new VarDeclaration(loc, arg->type, id, NULL);
+ Expression *einit = ie;
+ if (ie && ie->op == TOKtuple)
+ { einit = (Expression *)((TupleExp *)ie)->exps->data[i];
+ }
+ Initializer *ti = init;
+ if (einit)
+ { ti = new ExpInitializer(einit->loc, einit);
+ }
+
+ VarDeclaration *v = new VarDeclaration(loc, arg->type, id, ti);
//printf("declaring field %s of type %s\n", v->toChars(), v->type->toChars());
v->semantic(sc);
@@ -780,7 +795,8 @@
}
if (!init && !sc->inunion && !isStatic() && !isConst() && fd &&
- !(storage_class & (STCfield | STCin | STCforeach)))
+ !(storage_class & (STCfield | STCin | STCforeach)) &&
+ type->size() != 0)
{
// Provide a default initializer
//printf("Providing default initializer for '%s'\n", toChars());
@@ -873,19 +889,19 @@
t = type->toBasetype();
if (t->ty == Tsarray)
{
+ ei->exp = ei->exp->semantic(sc);
+ if (!ei->exp->implicitConvTo(type))
+ {
dim = ((TypeSArray *)t)->dim->toInteger();
// If multidimensional static array, treat as one large array
while (1)
{
- t = t->next->toBasetype();
+ t = t->nextOf()->toBasetype();
if (t->ty != Tsarray)
break;
- if (t->next->toBasetype()->ty == Tbit)
- // t->size() gives size in bytes, convert to bits
- dim *= t->size() * 8;
- else
dim *= ((TypeSArray *)t)->dim->toInteger();
- e1->type = new TypeSArray(t->next, new IntegerExp(0, dim, Type::tindex));
+ e1->type = new TypeSArray(t->nextOf(), new IntegerExp(0, dim, Type::tindex));
+ }
}
e1 = new SliceExp(loc, e1, NULL, NULL);
}
@@ -1052,7 +1068,7 @@
void VarDeclaration::checkNestedReference(Scope *sc, Loc loc)
{
- if (!isDataseg() && parent != sc->parent && parent)
+ if (parent && !isDataseg() && parent != sc->parent)
{
FuncDeclaration *fdv = toParent()->isFuncDeclaration();
FuncDeclaration *fdthis = sc->parent->isFuncDeclaration();
@@ -1103,6 +1119,7 @@
Expression *VarDeclaration::callAutoDtor()
{ Expression *e = NULL;
+ //printf("VarDeclaration::callAutoDtor() %s\n", toChars());
if (storage_class & (STCauto | STCscope) && !noauto)
{
for (ClassDeclaration *cd = type->isClassHandle();
@@ -1113,6 +1130,8 @@
* classes to determine if there's no way the monitor
* could be set.
*/
+ //if (cd->isInterfaceDeclaration())
+ //error("interface %s cannot be scope", cd->toChars());
if (1 || onstack || cd->dtors.dim) // if any destructors
{
// delete this;
@@ -1189,6 +1208,24 @@
assert(linkage == LINKc);
}
+/***************************** TypeInfoConstDeclaration **********************/
+
+#if V2
+TypeInfoConstDeclaration::TypeInfoConstDeclaration(Type *tinfo)
+ : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
+/***************************** TypeInfoInvariantDeclaration **********************/
+
+#if V2
+TypeInfoInvariantDeclaration::TypeInfoInvariantDeclaration(Type *tinfo)
+ : TypeInfoDeclaration(tinfo, 0)
+{
+}
+#endif
+
/***************************** TypeInfoStructDeclaration **********************/
TypeInfoStructDeclaration::TypeInfoStructDeclaration(Type *tinfo)
Index: d/dmd/declaration.h
===================================================================
--- d/dmd/declaration.h (Revision 199)
+++ d/dmd/declaration.h (Arbeitskopie)
@@ -89,6 +89,7 @@
struct Declaration : Dsymbol
{
Type *type;
+ Type *originalType; // before semantic analysis
unsigned storage_class;
enum PROT protection;
enum LINK linkage;
@@ -113,6 +114,7 @@
int isFinal() { return storage_class & STCfinal; }
int isAbstract() { return storage_class & STCabstract; }
int isConst() { return storage_class & STCconst; }
+ int isInvariant() { return 0; }
int isAuto() { return storage_class & STCauto; }
int isScope() { return storage_class & (STCscope | STCauto); }
int isSynchronized() { return storage_class & STCsynchronized; }
@@ -413,6 +415,23 @@
/**************************************************************/
+#if V2
+
+enum BUILTIN
+{
+ BUILTINunknown = -1, // not known if this is a builtin
+ BUILTINnot, // this is not a builtin
+ BUILTINsin, // std.math.sin
+ BUILTINcos, // std.math.cos
+ BUILTINtan, // std.math.tan
+ BUILTINsqrt, // std.math.sqrt
+ BUILTINfabs, // std.math.fabs
+};
+
+Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
+
+#endif
+
struct FuncDeclaration : Declaration
{
Array *fthrows; // Array of Type's of exceptions (not used)
@@ -443,7 +462,6 @@
int inlineNest; // !=0 if nested inline
int cantInterpret; // !=0 if cannot interpret function
int semanticRun; // !=0 if semantic3() had been run
- int nestedFrameRef; // !=0 if nested variables referenced frame ptr
ForeachStatement *fes; // if foreach body, this is the foreach
int introducing; // !=0 if 'introducing' function
Type *tintro; // if !=NULL, then this is the type
@@ -463,6 +481,20 @@
VarDeclaration *nrvo_var; // variable to replace with shidden
Symbol *shidden; // hidden pointer passed to function
+#if V2
+ enum BUILTIN builtin; // set if this is a known, builtin
+ // function we can evaluate at compile
+ // time
+
+ int tookAddressOf; // set if someone took the address of
+ // this function
+ Dsymbols closureVars; // local variables in this function
+ // which are referenced by nested
+ // functions
+#else
+ int nestedFrameRef; // !=0 if nested variables referenced
+#endif
+
FuncDeclaration(Loc loc, Loc endloc, Identifier *id, enum STC storage_class, Type *type);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
@@ -559,6 +591,7 @@
struct DtorDeclaration : FuncDeclaration
{
DtorDeclaration(Loc loc, Loc endloc);
+ DtorDeclaration(Loc loc, Loc endloc, Identifier *id);
Dsymbol *syntaxCopy(Dsymbol *);
void semantic(Scope *sc);
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
Index: d/dmd/expression.c
===================================================================
--- d/dmd/expression.c (Revision 199)
+++ d/dmd/expression.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -92,6 +92,7 @@
void initPrecedence()
{
+ precedence[TOKdotvar] = PREC_primary;
precedence[TOKimport] = PREC_primary;
precedence[TOKidentifier] = PREC_primary;
precedence[TOKthis] = PREC_primary;
@@ -173,6 +174,8 @@
precedence[TOKquestion] = PREC_cond;
precedence[TOKassign] = PREC_assign;
+ precedence[TOKconstruct] = PREC_assign;
+ precedence[TOKblit] = PREC_assign;
precedence[TOKaddass] = PREC_assign;
precedence[TOKminass] = PREC_assign;
precedence[TOKcatass] = PREC_assign;
@@ -521,7 +524,7 @@
{
// BUG: should check that argument to ref is type 'invariant'
// BUG: assignments to ref should also be type 'invariant'
- arg = arg->modifiableLvalue(sc, NULL);
+ arg = arg->modifiableLvalue(sc, arg);
//if (arg->op == TOKslice)
//arg->error("cannot modify slice %s", arg->toChars());
@@ -646,7 +649,7 @@
if (i)
buf->writeByte(',');
argbuf.reset();
- arg->type->toCBuffer2(&argbuf, NULL, hgs);
+ arg->type->toCBuffer2(&argbuf, hgs, 0);
buf->write(&argbuf);
}
}
@@ -853,10 +856,13 @@
return this;
}
-void Expression::checkArithmetic()
+Expression *Expression::checkArithmetic()
{
if (!type->isintegral() && !type->isfloating())
- error("'%s' is not an arithmetic type", toChars());
+ { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
+ return new IntegerExp(0);
+ }
+ return this;
}
void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
@@ -1268,7 +1274,7 @@
char *RealExp::toChars()
{
- static char buffer[sizeof(value) * 3 + 8 + 1 + 1];
+ char buffer[sizeof(value) * 3 + 8 + 1 + 1];
#ifdef IN_GCC
value.format(buffer, sizeof(buffer));
@@ -1278,7 +1284,7 @@
sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
#endif
assert(strlen(buffer) < sizeof(buffer));
- return buffer;
+ return mem.strdup(buffer);
}
integer_t RealExp::toInteger()
@@ -1513,7 +1519,7 @@
char *ComplexExp::toChars()
{
- static char buffer[sizeof(value) * 3 + 8 + 1];
+ char buffer[sizeof(value) * 3 + 8 + 1];
#ifdef IN_GCC
char buf1[sizeof(value) * 3 + 8 + 1];
@@ -1525,7 +1531,7 @@
sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
assert(strlen(buffer) < sizeof(buffer));
#endif
- return buffer;
+ return mem.strdup(buffer);
}
integer_t ComplexExp::toInteger()
@@ -1794,7 +1800,7 @@
em = s->isEnumMember();
if (em)
{
- e = em->value;
+ e = em->value->copy();
e = e->semantic(sc);
return e;
}
@@ -2530,6 +2536,8 @@
#if LOGSEMANTIC
printf("ArrayLiteralExp::semantic('%s')\n", toChars());
#endif
+ if (type)
+ return this;
// Run semantic() on each element
for (int i = 0; i < elements->dim; i++)
@@ -3174,7 +3182,13 @@
if (cd->isInterfaceDeclaration())
error("cannot create instance of interface %s", cd->toChars());
else if (cd->isAbstract())
- error("cannot create instance of abstract class %s", cd->toChars());
+ { error("cannot create instance of abstract class %s", cd->toChars());
+ for (int i = 0; i < cd->vtbl.dim; i++)
+ { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
+ if (fd && fd->isAbstract())
+ error("function %s is abstract", fd->toChars());
+ }
+ }
checkDeprecated(sc, cd);
if (cd->isNested())
{ /* We need a 'this' pointer for the nested class.
@@ -3798,6 +3812,25 @@
}
}
+elem *TupleExp::toElem(IRState *irs)
+{ //elem *e = NULL;
+
+ printf("TupleExp::toElem() %s\n", toChars());
+ printf("EXPER: Uneducated guesswork ensues. Beware.");
+ Expression *res;
+ for (size_t i = 0; i < exps->dim; i++)
+ res = Expression::combine(res, (Expression *)exps->data[i]);
+ return res->toElem(irs);
+ /*
+ 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;*/
+}
+
/******************************** FuncExp *********************************/
FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
@@ -4381,7 +4414,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
type = e1->type;
if (type->toBasetype()->ty == Tbool)
@@ -4412,7 +4445,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
type = e1->type;
if (type->toBasetype()->ty == Tbool)
@@ -4432,6 +4465,8 @@
if (op == TOKplusplus ||
op == TOKminusminus ||
op == TOKassign ||
+ op == TOKconstruct ||
+ op == TOKblit ||
op == TOKaddass ||
op == TOKminass ||
op == TOKcatass ||
@@ -5558,9 +5593,9 @@
TemplateDeclaration *td = dte->td;
assert(td);
if (!arguments)
- // Should fix deduce() so it works on NULL argument
+ // Should fix deduceFunctionTemplate() so it works on NULL argument
arguments = new Expressions();
- f = td->deduce(sc, loc, NULL, arguments);
+ f = td->deduceFunctionTemplate(sc, loc, NULL, arguments);
if (!f)
{ type = Type::terror;
return this;
@@ -5735,7 +5770,7 @@
else if (e1->op == TOKtemplate)
{
TemplateExp *te = (TemplateExp *)e1;
- f = te->td->deduce(sc, loc, NULL, arguments);
+ f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments);
if (!f)
{ type = Type::terror;
return this;
@@ -6154,13 +6189,10 @@
if (f)
{
- Expression *e;
- Expression *ec;
Type *tpv = Type::tvoid->pointerTo();
- e = e1;
- e->type = tpv;
- ec = new VarExp(loc, f);
+ Expression *e = e1->castTo(sc, tpv);
+ Expression *ec = new VarExp(loc, f);
e = new CallExp(loc, ec, e);
return e->semantic(sc);
}
@@ -6252,7 +6284,10 @@
}
Type *tob = to->toBasetype();
- if (tob->ty == Tstruct && !tob->equals(e1->type->toBasetype()))
+ if (tob->ty == Tstruct &&
+ !tob->equals(e1->type->toBasetype()) &&
+ ((TypeStruct *)to)->sym->search(0, Id::call, 0)
+ )
{
/* Look to replace:
* cast(S)t
@@ -6893,7 +6928,7 @@
return e;
e = this;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
if (e1->type->ty == Tpointer)
@@ -7023,6 +7058,31 @@
e2 = resolveProperties(sc, e2);
assert(e1->type);
+ /* Rewrite tuple assignment as a tuple of assignments.
+ */
+ if (e1->op == TOKtuple && e2->op == TOKtuple)
+ { TupleExp *tup1 = (TupleExp *)e1;
+ TupleExp *tup2 = (TupleExp *)e2;
+ size_t dim = tup1->exps->dim;
+ if (dim != tup2->exps->dim)
+ {
+ error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
+ }
+ else
+ { Expressions *exps = new Expressions;
+ exps->setDim(dim);
+
+ for (int i = 0; i < dim; i++)
+ { Expression *ex1 = (Expression *)tup1->exps->data[i];
+ Expression *ex2 = (Expression *)tup2->exps->data[i];
+ exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
+ }
+ Expression *e = new TupleExp(loc, exps);
+ e = e->semantic(sc);
+ return e;
+ }
+ }
+
t1 = e1->type->toBasetype();
if (t1->ty == Tfunction)
@@ -7054,7 +7114,7 @@
// e1 is not an lvalue, but we let code generator handle it
ArrayLengthExp *ale = (ArrayLengthExp *)e1;
- ale->e1 = ale->e1->modifiableLvalue(sc, NULL);
+ ale->e1 = ale->e1->modifiableLvalue(sc, e1);
}
else if (e1->op == TOKslice)
;
@@ -7065,21 +7125,14 @@
}
if (e1->op == TOKslice &&
- t1->next &&
- !(t1->next->equals(e2->type->next) /*||
- (t1->next->ty == Tchar && e2->op == TOKstring)*/)
+ t1->nextOf() &&
+ e2->implicitConvTo(t1->nextOf())
+// !(t1->nextOf()->equals(e2->type->nextOf()))
)
{ // memset
+ ismemset = 1; // make it easy for back end to tell what this is
e2 = e2->implicitCastTo(sc, t1->next);
}
-#if 0
- else if (e1->op == TOKslice &&
- e2->op == TOKstring &&
- ((StringExp *)e2)->len == 1)
- { // memset
- e2 = e2->implicitCastTo(sc, e1->type->next);
- }
-#endif
else if (t1->ty == Tsarray)
{
error("cannot assign to static array %s", e1->toChars());
@@ -7123,7 +7176,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype();
@@ -7223,17 +7276,17 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
if (e1->type->ty == Tpointer && e2->type->isintegral())
e = scaleFactor(sc);
else
{
+ e1 = e1->checkArithmetic();
+ e2 = e2->checkArithmetic();
type = e1->type;
typeCombine(sc);
- e1->checkArithmetic();
- e2->checkArithmetic();
if (type->isreal() || type->isimaginary())
{
assert(e2->type->isfloating());
@@ -7268,11 +7321,13 @@
error("cannot append to static array %s", se->e1->type->toChars());
}
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
Type *tb1 = e1->type->toBasetype();
Type *tb2 = e2->type->toBasetype();
+ e2->rvalue();
+
if ((tb1->ty == Tarray) &&
(tb2->ty == Tarray || tb2->ty == Tsarray) &&
e2->implicitConvTo(e1->type)
@@ -7317,7 +7372,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
@@ -7373,7 +7428,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
@@ -7444,7 +7499,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
@@ -7472,7 +7527,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
@@ -7500,7 +7555,7 @@
if (e)
return e;
- e1 = e1->modifiableLvalue(sc, NULL);
+ e1 = e1->modifiableLvalue(sc, e1);
e1->checkScalar();
e1->checkNoBool();
type = e1->type;
@@ -8333,6 +8388,13 @@
return this;
BinExp::semanticp(sc);
+
+ if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
+ e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+ {
+ error("do not use null when comparing class types");
+ }
+
e = op_overload(sc);
if (e)
{
@@ -8386,6 +8448,7 @@
EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
: BinExp(loc, op, sizeof(EqualExp), e1, e2)
{
+ assert(op == TOKequal || op == TOKnotequal);
}
Expression *EqualExp::semantic(Scope *sc)
@@ -8420,6 +8483,14 @@
}
}
+ if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
+ e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
+ {
+ error("use '%s' instead of '%s' when comparing with null",
+ Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
+ Token::toChars(op));
+ }
+
//if (e2->op != TOKnull)
{
e = op_overload(sc);
Index: d/dmd/clone.c
===================================================================
--- d/dmd/clone.c (Revision 0)
+++ d/dmd/clone.c (Revision 0)
@@ -0,0 +1,175 @@
+
+// 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 <stdio.h>
+#include <assert.h>
+
+#include "root.h"
+#include "aggregate.h"
+#include "scope.h"
+#include "mtype.h"
+#include "declaration.h"
+#include "module.h"
+#include "id.h"
+#include "expression.h"
+#include "statement.h"
+
+
+/*********************************
+ * Generate expression that calls opClone()
+ * for each member of the struct
+ * (can be NULL for members that don't need one)
+ */
+
+#if V2
+Expression *StructDeclaration::cloneMembers()
+{
+ Expression *e = NULL;
+
+ for (size_t i = 0; i < fields.dim; i++)
+ {
+ Dsymbol *s = (Dsymbol *)fields.data[i];
+ VarDeclaration *v = s->isVarDeclaration();
+ assert(v && v->storage_class & STCfield);
+ Type *tv = v->type->toBasetype();
+ size_t dim = 1;
+ while (tv->ty == Tsarray)
+ { TypeSArray *ta = (TypeSArray *)tv;
+ dim *= ((TypeSArray *)tv)->dim->toInteger();
+ tv = tv->nextOf()->toBasetype();
+ }
+ if (tv->ty == Tstruct)
+ { TypeStruct *ts = (TypeStruct *)tv;
+ StructDeclaration *sd = ts->sym;
+ if (sd->opclone)
+ { Expression *ex;
+
+ // this.v
+ ex = new ThisExp(0);
+ ex = new DotVarExp(0, ex, v, 0);
+
+ if (dim == 1)
+ { // this.v.opClone()
+ ex = new DotVarExp(0, ex, sd->opclone, 0);
+ ex = new CallExp(0, ex);
+ }
+ else
+ {
+ // _callOpClones(&this.v, opclone, dim)
+ Expressions *args = new Expressions();
+ args->push(new AddrExp(0, ex));
+ args->push(new SymOffExp(0, sd->opclone, 0));
+ args->push(new IntegerExp(dim));
+ FuncDeclaration *ec = FuncDeclaration::genCfunc(Type::tvoid, "_callOpClones");
+ ex = new CallExp(0, new VarExp(0, ec), args);
+ }
+ e = Expression::combine(e, ex);
+ }
+ }
+ }
+ return e;
+}
+#endif
+
+/*****************************************
+ * Create inclusive destructor for struct by aggregating
+ * all the destructors in dtors[] with the destructors for
+ * all the members.
+ */
+
+FuncDeclaration *AggregateDeclaration::buildDtor(Scope *sc)
+{
+ //printf("StructDeclaration::buildDtor() %s\n", toChars());
+ Expression *e = NULL;
+
+#if V2
+ for (size_t i = 0; i < fields.dim; i++)
+ {
+ Dsymbol *s = (Dsymbol *)fields.data[i];
+ VarDeclaration *v = s->isVarDeclaration();
+ assert(v && v->storage_class & STCfield);
+ Type *tv = v->type->toBasetype();
+ size_t dim = 1;
+ while (tv->ty == Tsarray)
+ { TypeSArray *ta = (TypeSArray *)tv;
+ dim *= ((TypeSArray *)tv)->dim->toInteger();
+ tv = tv->nextOf()->toBasetype();
+ }
+ if (tv->ty == Tstruct)
+ { TypeStruct *ts = (TypeStruct *)tv;
+ StructDeclaration *sd = ts->sym;
+ if (sd->dtor)
+ { Expression *ex;
+
+ // this.v
+ ex = new ThisExp(0);
+ ex = new DotVarExp(0, ex, v, 0);
+
+ if (dim == 1)
+ { // this.v.dtor()
+ ex = new DotVarExp(0, ex, sd->dtor, 0);
+ ex = new CallExp(0, ex);
+ }
+ else
+ {
+ // Typeinfo.destroy(cast(void*)&this.v);
+ Expression *ea = new AddrExp(0, ex);
+ ea = new CastExp(0, ea, Type::tvoid->pointerTo());
+ Expressions *args = new Expressions();
+ args->push(ea);
+
+ Expression *et = v->type->getTypeInfo(sc);
+ et = new DotIdExp(0, et, Id::destroy);
+
+ ex = new CallExp(0, et, args);
+ }
+ e = Expression::combine(ex, e); // combine in reverse order
+ }
+ }
+ }
+
+ /* Build our own "destructor" which executes e
+ */
+ if (e)
+ { //printf("Building __fieldDtor()\n");
+ DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__fieldDtor"));
+ dd->fbody = new ExpStatement(0, e);
+ dtors.shift(dd);
+ members->push(dd);
+ dd->semantic(sc);
+ }
+#endif
+
+ switch (dtors.dim)
+ {
+ case 0:
+ return NULL;
+
+ case 1:
+ return (FuncDeclaration *)dtors.data[0];
+
+ default:
+ e = NULL;
+ for (size_t i = 0; i < dtors.dim; i++)
+ { FuncDeclaration *fd = (FuncDeclaration *)dtors.data[i];
+ Expression *ex = new ThisExp(0);
+ ex = new DotVarExp(0, ex, fd);
+ ex = new CallExp(0, ex);
+ e = Expression::combine(ex, e);
+ }
+ DtorDeclaration *dd = new DtorDeclaration(0, 0, Lexer::idPool("__aggrDtor"));
+ dd->fbody = new ExpStatement(0, e);
+ members->push(dd);
+ dd->semantic(sc);
+ return dd;
+ }
+}
+
+
Index: d/dmd/mars.c
===================================================================
--- d/dmd/mars.c (Revision 199)
+++ d/dmd/mars.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -64,9 +64,9 @@
obj_ext = "o";
#endif
- copyright = "Copyright (c) 1999-2007 by Digital Mars";
+ copyright = "Copyright (c) 1999-2008 by Digital Mars";
written = "written by Walter Bright";
- version = "v1.022";
+ version = "v1.028";
global.structalign = 8;
memset(¶ms, 0, sizeof(Param));
@@ -254,6 +254,7 @@
global.params.useInline = 0;
global.params.obj = 1;
global.params.Dversion = 2;
+ global.params.quiet = 1;
global.params.linkswitches = new Array();
global.params.libfiles = new Array();
Index: d/dmd/expression.h
===================================================================
--- d/dmd/expression.h (Revision 199)
+++ d/dmd/expression.h (Arbeitskopie)
@@ -113,7 +113,7 @@
void checkScalar();
void checkNoBool();
Expression *checkIntegral();
- void checkArithmetic();
+ Expression *checkArithmetic();
void checkDeprecated(Scope *sc, Dsymbol *s);
virtual Expression *checkToBoolean();
Expression *checkToPointer();
@@ -347,6 +347,7 @@
Expression *optimize(int result);
Expression *interpret(InterState *istate);
Expression *castTo(Scope *sc, Type *t);
+ elem *toElem(IRState *irs);
int inlineCost(InlineCostState *ics);
Expression *doInline(InlineDoState *ids);
Index: d/dmd/inline.c
===================================================================
--- d/dmd/inline.c (Revision 199)
+++ d/dmd/inline.c (Arbeitskopie)
@@ -546,8 +546,6 @@
;
else
{
- ExpInitializer *ie;
- ExpInitializer *ieto;
VarDeclaration *vto;
vto = new VarDeclaration(vd->loc, vd->type, vd->ident, vd->init);
@@ -559,16 +557,18 @@
ids->from.push(vd);
ids->to.push(vto);
+ if (vd->init)
+ {
if (vd->init->isVoidInitializer())
{
vto->init = new VoidInitializer(vd->init->loc);
}
else
{
- ie = vd->init->isExpInitializer();
+ ExpInitializer *ie = vd->init->isExpInitializer();
assert(ie);
- ieto = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
- vto->init = ieto;
+ vto->init = new ExpInitializer(ie->loc, ie->exp->doInline(ids));
+ }
}
de->declaration = (Dsymbol *) (void *)vto;
}
@@ -854,6 +854,7 @@
Statement *ForeachStatement::inlineScan(InlineScanState *iss)
{
aggr = aggr->inlineScan(iss);
+ if (body)
body = body->inlineScan(iss);
return this;
}
@@ -864,6 +865,7 @@
{
lwr = lwr->inlineScan(iss);
upr = upr->inlineScan(iss);
+ if (body)
body = body->inlineScan(iss);
return this;
}
@@ -1288,7 +1290,11 @@
#endif
isSynchronized() ||
isImportedSymbol() ||
+#if V2
+ closureVars.dim || // no nested references to this frame
+#else
nestedFrameRef || // no nested references to this frame
+#endif
(isVirtual() && !isFinal())
))
{
Index: d/dmd/module.c
===================================================================
--- d/dmd/module.c (Revision 199)
+++ d/dmd/module.c (Arbeitskopie)
@@ -85,6 +85,7 @@
vmoduleinfo = NULL;
massert = NULL;
marray = NULL;
+ sictor = NULL;
sctor = NULL;
sdtor = NULL;
stest = NULL;
Index: d/dmd/module.h
===================================================================
--- d/dmd/module.h (Revision 199)
+++ d/dmd/module.h (Arbeitskopie)
@@ -139,6 +139,7 @@
Symbol *cov; // private uint[] __coverage;
unsigned *covb; // bit array of valid code line numbers
+ Symbol *sictor; // module order independent constructor
Symbol *sctor; // module constructor
Symbol *sdtor; // module destructor
Symbol *stest; // module unit test
Index: d/dmd/func.c
===================================================================
--- d/dmd/func.c (Revision 199)
+++ d/dmd/func.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -147,6 +147,9 @@
if (isAbstract() && !isVirtual())
error("non-virtual functions cannot be abstract");
+
+ if (isAbstract() && isFinal())
+ error("cannot be both final and abstract");
#if 0
if (isAbstract() && fbody)
error("abstract functions cannot have bodies");
@@ -561,6 +564,8 @@
if (!parent)
{
+ if (global.errors)
+ return;
printf("FuncDeclaration::semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
assert(0);
}
@@ -612,7 +617,7 @@
sc2->sw = NULL;
sc2->fes = fes;
sc2->linkage = LINKd;
- sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated);
+ sc2->stc &= ~(STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STCfinal);
sc2->attributes = NULL;
sc2->protection = PROTpublic;
sc2->explicitProtection = 0;
@@ -2066,6 +2071,8 @@
Type *tret;
//printf("CtorDeclaration::semantic()\n");
+ if (type)
+ return;
sc = sc->push();
sc->stc &= ~STCstatic; // not a static constructor
@@ -2147,12 +2154,15 @@
{
}
+DtorDeclaration::DtorDeclaration(Loc loc, Loc endloc, Identifier *id)
+ : FuncDeclaration(loc, endloc, id, STCundefined, NULL)
+{
+}
+
Dsymbol *DtorDeclaration::syntaxCopy(Dsymbol *s)
{
- DtorDeclaration *dd;
-
assert(!s);
- dd = new DtorDeclaration(loc, endloc);
+ DtorDeclaration *dd = new DtorDeclaration(loc, endloc, ident);
return FuncDeclaration::syntaxCopy(dd);
}
Index: d/dmd/aggregate.h
===================================================================
--- d/dmd/aggregate.h (Revision 199)
+++ d/dmd/aggregate.h (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -57,6 +57,8 @@
// 2: cannot determine size; fwd referenced
int isdeprecated; // !=0 if deprecated
Scope *scope; // !=NULL means context to use
+ FuncDeclarations dtors; // Array of destructors
+ FuncDeclaration *dtor; // aggregate destructor
// Special member functions
InvariantDeclaration *inv; // invariant
@@ -77,6 +79,7 @@
Type *getType();
void addField(Scope *sc, VarDeclaration *v);
int isDeprecated(); // is aggregate deprecated?
+ FuncDeclaration *buildDtor(Scope *sc);
void emitComment(Scope *sc);
void toDocBuffer(OutBuffer *buf);
@@ -117,6 +120,7 @@
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
char *mangle();
char *kind();
+ Expression *cloneMembers();
void toDocBuffer(OutBuffer *buf);
PROT getAccess(Dsymbol *smember); // determine access to smember
@@ -168,7 +172,6 @@
ClassDeclaration *baseClass; // NULL only if this is Object
CtorDeclaration *ctor;
CtorDeclaration *defaultCtor; // default constructor
- FuncDeclarations dtors; // Array of destructors
FuncDeclaration *staticCtor;
FuncDeclaration *staticDtor;
Array vtbl; // Array of FuncDeclaration's making up the vtbl[]
@@ -185,7 +188,8 @@
// their own vtbl[]
ClassInfoDeclaration *vclassinfo; // the ClassInfo object for this ClassDeclaration
- int com; // !=0 if this is a COM class
+ int com; // !=0 if this is a COM class (meaning
+ // it derives from IUnknown)
int isauto; // !=0 if this is an auto class
int isabstract; // !=0 if abstract class
@@ -202,11 +206,17 @@
virtual int isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset);
Dsymbol *search(Loc, Identifier *ident, int flags);
+#if V2
+ int isFuncHidden(FuncDeclaration *fd);
+#endif
FuncDeclaration *findFunc(Identifier *ident, TypeFunction *tf);
void interfaceSemantic(Scope *sc);
int isNested();
int isCOMclass();
virtual int isCOMinterface();
+#if V2
+ virtual int isCPPinterface();
+#endif
int isAbstract();
virtual int vtblOffset();
char *kind();
@@ -233,6 +243,9 @@
struct InterfaceDeclaration : ClassDeclaration
{
+#if V2
+ int cpp; // !=0 if this is a C++ interface
+#endif
InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses);
Dsymbol *syntaxCopy(Dsymbol *s);
void semantic(Scope *sc);
@@ -240,6 +253,9 @@
int isBaseOf(BaseClass *bc, target_ptrdiff_t *poffset);
char *kind();
int vtblOffset();
+#if V2
+ int isCPPinterface();
+#endif
virtual int isCOMinterface();
void toObjFile(); // compile to .obj file
Index: d/dmd/e2ir.c
===================================================================
--- d/dmd/e2ir.c (Revision 0)
+++ d/dmd/e2ir.c (Revision 0)
@@ -0,0 +1,4189 @@
+
+// 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
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <complex.h>
+
+#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: %s\n", 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 (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(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)0, "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)
+{ 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;
+ 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 *VarExp::toElem(IRState *irs)
+{ Symbol *s;
+ elem *e;
+ tym_t tym;
+ Type *tb = type->toBasetype();
+ FuncDeclaration *fd;
+
+ //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 offset;
+
+ ethis = getEthis(loc, irs, fd);
+ ethis = el_una(OPaddr, TYnptr, ethis);
+
+ offset = 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)
+ {
+ offset -= 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, offset));
+ e = el_una(OPind, 0, ethis);
+ 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;
+}
+
+/*****************************************
+ */
+
+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->isConst() || vd->storage_class & STCextern)
+ vd->toObjFile();
+ 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);
+ //sd->toObjFile();
+ }
+ else if ((sd = s->isStructDeclaration()) != NULL)
+ {
+ irs->deferToObj->push(sd);
+ //sd->toObjFile();
+ }
+ else if ((fd = s->isFuncDeclaration()) != NULL)
+ {
+ //printf("function %s\n", fd->toChars());
+ irs->deferToObj->push(fd);
+ //fd->toObjFile();
+ }
+ 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 (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->sthis)
+ {
+#if V2
+ 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 V2
+ 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 == 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 = t->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)
+ {
+ d_uns64 elemsize = t->next->size();
+ Expression *di = t->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 = t->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;
+}
+
+elem *SymOffExp::toElem(IRState *irs)
+{ Symbol *s;
+ elem *e;
+ Type *tb = var->type->toBasetype();
+ 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);
+
+ soffset = s->Soffset;
+
+ // If fd is a non-static member function, then ethis isn't the
+ // frame pointer. We must offset it.
+ if (fd->vthis)
+ {
+ soffset -= fd->vthis->toSymbol()->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->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;
+}
+
+//////////////////////////// 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 *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 *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 operations not implemented");
+ }
+ 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);
+
+ ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
+ rtlfunc = RTLSYM_ARRAYCMP;
+ 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);
+
+ ep = el_params(telement->getInternalTypeInfo(NULL)->toElem(irs), ea2, ea1, NULL);
+ rtlfunc = RTLSYM_ARRAYEQ;
+ 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->key->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->key->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[]=n
+//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);
+ Lpair:
+ e = el_pair(TYullong, elength, e);
+ Lret2:
+ e = el_combine(einit, e);
+ //elem_print(e);
+ goto Lret;
+ }
+ 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;
+
+ size = t1->nextOf()->size();
+ esize = el_long(TYint, size);
+
+ if (e2->type->ty == Tpointer || !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);
+ }
+ else
+ {
+ // Generate:
+ // _d_arraycopy(eto, efrom, esize)
+
+ // If eto is a static array, need to convert it to
+ // a dynamic array.
+ //if (are->e1->type->ty == Tsarray)
+ // eto = sarray_toDarray(are->e1->type, eto);
+
+ 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) ? 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 *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->key->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);
+ rtl = RTLSYM_DELCLASS;
+ tb = e1->type->toBasetype();
+ switch (tb->ty)
+ {
+ case Tarray:
+ e = addressElem(e, e1->type);
+ rtl = RTLSYM_DELARRAY;
+ break;
+
+ 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(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->isCOMinterface())
+ {
+ if (cdto->isCOMinterface())
+ {
+ /* Casting from a com interface to a com interface
+ * is always a 'paint' operation
+ */
+ goto Lret; // no-op
+ }
+
+ /* Casting from a COM interface to a class
+ * always results in null because there is no runtime
+ * information available to do it.
+ *
+ * Casting from a COM interface to a non-COM 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(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, value);
+
+ TypeAArray *taa = (TypeAArray *)t1;
+ elem *keyti;
+ elem *ep;
+ int vsize = taa->next->size();
+ elem *valuesize;
+ Symbol *s;
+
+ n2 = e2->toElem(irs);
+ if (n2->Ety == TYstruct)
+ {
+ n2 = el_una(OPstrpar, TYstruct, n2);
+ n2->Enumbytes = n2->E1->Enumbytes;
+ assert(n2->Enumbytes);
+ }
+ valuesize = el_long(TYuint, vsize); // BUG: should be TYsize_t
+ if (modifiable)
+ {
+ n1 = el_una(OPaddr, TYnptr, n1);
+ s = taa->aaGetSymbol("Get", 1);
+ }
+ else
+ {
+ s = taa->aaGetSymbol("GetRvalue", 1);
+ }
+ //printf("taa->key = %s\n", taa->key->toChars());
+ keyti = taa->key->getInternalTypeInfo(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];
+ }
+ }
+ e = el_param(e, type->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 *ep = el->toElem(irs);
+
+ Type *t1b = v->type->toBasetype();
+ Type *t2b = el->type->toBasetype();
+ if (t1b->ty == Tsarray)
+ {
+ if (t2b->implicitConvTo(t1b))
+ { 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);
+ }
+ }
+ 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();
+ }
+ }
+ 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;
+}
Index: d/dmd/scope.c
===================================================================
--- d/dmd/scope.c (Revision 199)
+++ d/dmd/scope.c (Arbeitskopie)
@@ -75,6 +75,7 @@
this->incontract = 0;
this->nofree = 0;
this->noctor = 0;
+ this->noaccesscheck = 0;
this->intypeof = 0;
this->parameterSpecialization = 0;
this->callSuper = 0;
@@ -121,6 +122,7 @@
this->incontract = enclosing->incontract;
this->nofree = 0;
this->noctor = enclosing->noctor;
+ this->noaccesscheck = enclosing->noaccesscheck;
this->intypeof = enclosing->intypeof;
this->parameterSpecialization = enclosing->parameterSpecialization;
this->callSuper = enclosing->callSuper;
Index: d/dmd/opover.c
===================================================================
--- d/dmd/opover.c (Revision 199)
+++ d/dmd/opover.c (Arbeitskopie)
@@ -739,7 +739,7 @@
FuncDeclaration *fd;
assert(td);
- fd = td->deduce(sc, loc, targsi, arguments);
+ fd = td->deduceFunctionTemplate(sc, loc, targsi, arguments);
if (!fd)
return;
m->anyf = fd;
Index: d/dmd/template.c
===================================================================
--- d/dmd/template.c (Revision 199)
+++ d/dmd/template.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -81,6 +81,7 @@
return (Tuple *)o;
}
+
/***********************
* Try to get arg as a type.
*/
@@ -135,6 +136,7 @@
Dsymbol *s2 = isDsymbol(o2);
Tuple *v1 = isTuple(o1);
Tuple *v2 = isTuple(o2);
+ //printf("\t match t1 %p t2 %p, e1 %p e2 %p, s1 %p s2 %p, v1 %p v2 %p\n", t1,t2,e1,e2,s1,s2,v1,v2);
/* A proper implementation of the various equals() overrides
* should make it possible to just do o1->equals(o2), but
@@ -163,7 +165,7 @@
}
if (!t2 || !t1->equals(t2))
- goto L1;
+ goto Lnomatch;
}
else if (e1)
{
@@ -173,33 +175,39 @@
printf("match %d\n", e1->equals(e2));
e1->print();
e2->print();
+ e1->type->print();
+ e2->type->print();
}
#endif
- if (!e2 || !e1->equals(e2))
- goto L1;
+ if (!e2)
+ goto Lnomatch;
+ if (!e1->equals(e2))
+ goto Lnomatch;
}
else if (s1)
{
//printf("%p %s, %p %s\n", s1, s1->toChars(), s2, s2->toChars());
if (!s2 || !s1->equals(s2) || s1->parent != s2->parent)
- goto L1;
+ {
+ goto Lnomatch;
+ }
}
else if (v1)
{
if (!v2)
- goto L1;
+ goto Lnomatch;
if (v1->objects.dim != v2->objects.dim)
- goto L1;
+ goto Lnomatch;
for (size_t i = 0; i < v1->objects.dim; i++)
{
if (!match((Object *)v1->objects.data[i],
(Object *)v2->objects.data[i],
tempdecl, sc))
- goto L1;
+ goto Lnomatch;
}
}
return 1; // match
-L1:
+Lnomatch:
return 0; // nomatch;
}
@@ -208,12 +216,15 @@
void ObjectToCBuffer(OutBuffer *buf, HdrGenState *hgs, Object *oarg)
{
+ //printf("ObjectToCBuffer()\n");
Type *t = isType(oarg);
Expression *e = isExpression(oarg);
Dsymbol *s = isDsymbol(oarg);
Tuple *v = isTuple(oarg);
if (t)
+ { //printf("\tt: %s ty = %d\n", t->toChars(), t->ty);
t->toCBuffer(buf, NULL, hgs);
+ }
else if (e)
e->toCBuffer(buf, hgs);
else if (s)
@@ -270,6 +281,7 @@
#endif
this->loc = loc;
this->parameters = parameters;
+ this->origParameters = parameters;
this->members = decldefs;
this->overnext = NULL;
this->overroot = NULL;
@@ -338,6 +350,17 @@
Scope *paramscope = sc->push(paramsym);
paramscope->parameterSpecialization = 1;
+ if (global.params.doDocComments)
+ {
+ origParameters = new TemplateParameters();
+ origParameters->setDim(parameters->dim);
+ for (int i = 0; i < parameters->dim; i++)
+ {
+ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+ origParameters->data[i] = (void *)tp->syntaxCopy();
+ }
+ }
+
for (int i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
@@ -350,6 +373,8 @@
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
tp->semantic(paramscope);
+ if (i + 1 != parameters->dim && tp->isTemplateTupleParameter())
+ error("template tuple parameter must be last one");
}
paramscope->pop();
@@ -439,6 +464,7 @@
* those deduced types in dedtypes[].
* Input:
* flag 1: don't do semantic() because of dummy types
+ * 2: don't change types in matchArg()
* Output:
* dedtypes deduced arguments
* Return match level.
@@ -449,8 +475,9 @@
{ MATCH m;
int dedtypes_dim = dedtypes->dim;
-#if LOG
- printf("+TemplateDeclaration::matchWithInstance(this = %p, ti = %p, flag = %d)\n", this, ti, flag);
+#define LOGM 0
+#if LOGM
+ printf("\n+TemplateDeclaration::matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti->toChars(), flag);
#endif
#if 0
@@ -468,7 +495,7 @@
// If more arguments than parameters, no match
if (ti->tiargs->dim > parameters_dim && !variadic)
{
-#if LOG
+#if LOGM
printf(" no match: more arguments than parameters\n");
#endif
return MATCHnomatch;
@@ -491,14 +518,15 @@
Declaration *sparam;
//printf("\targument [%d]\n", i);
-#if 0
- printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
+#if LOGM
+ //printf("\targument [%d] is %s\n", i, oarg ? oarg->toChars() : "null");
TemplateTypeParameter *ttp = tp->isTemplateTypeParameter();
if (ttp)
printf("\tparameter[%d] is %s : %s\n", i, tp->ident->toChars(), ttp->specType ? ttp->specType->toChars() : "");
#endif
m2 = tp->matchArg(paramscope, ti->tiargs, i, parameters, dedtypes, &sparam);
+ //printf("\tm2 = %d\n", m2);
if (m2 == MATCHnomatch)
{
@@ -529,7 +557,7 @@
}
}
-#if 0
+#if LOGM
// Print out the results
printf("--------------------------\n");
printf("template %s\n", toChars());
@@ -554,20 +582,20 @@
goto Lnomatch;
#endif
-#if LOG
+#if LOGM
printf(" match = %d\n", m);
#endif
goto Lret;
Lnomatch:
-#if LOG
+#if LOGM
printf(" no match\n");
#endif
m = MATCHnomatch;
Lret:
paramscope->pop();
-#if LOG
+#if LOGM
printf("-TemplateDeclaration::matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
#endif
return m;
@@ -646,16 +674,19 @@
* fargs arguments to function
* Output:
* dedargs Expression/Type deduced template arguments
+ * Returns:
+ * match level
*/
-MATCH TemplateDeclaration::deduceMatch(Objects *targsi, Expressions *fargs,
+MATCH TemplateDeclaration::deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs,
Objects *dedargs)
{
size_t i;
size_t nfparams;
- size_t nfparams2;
size_t nfargs;
size_t nargsi;
+ int fptupindex = -1;
+ int tuple_dim = 0;
MATCH match = MATCHexact;
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
TypeFunction *fdtype;
@@ -663,7 +694,7 @@
Objects dedtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
#if 0
- printf("\nTemplateDeclaration::deduceMatch() %s\n", toChars());
+ printf("\nTemplateDeclaration::deduceFunctionTemplateMatch() %s\n", toChars());
for (i = 0; i < fargs->dim; i++)
{ Expression *e = (Expression *)fargs->data[i];
printf("\tfarg[%d] is %s, type is %s\n", i, e->toChars(), e->type->toChars());
@@ -683,13 +714,19 @@
paramsym->parent = scope->parent;
Scope *paramscope = scope->push(paramsym);
+ tp = isVariadic();
+
nargsi = 0;
if (targsi)
{ // Set initial template arguments
nargsi = targsi->dim;
if (nargsi > parameters->dim)
+ { if (!tp)
goto Lnomatch;
+ dedargs->setDim(nargsi);
+ dedargs->zero();
+ }
memcpy(dedargs->data, targsi->data, nargsi * sizeof(*dedargs->data));
@@ -699,6 +736,7 @@
Declaration *sparam;
m = tp->matchArg(paramscope, dedargs, i, parameters, &dedtypes, &sparam);
+ //printf("\tdeduceType m = %d\n", m);
if (m == MATCHnomatch)
goto Lnomatch;
if (m < match)
@@ -714,7 +752,6 @@
fdtype = (TypeFunction *)fd->type;
nfparams = Argument::dim(fdtype->parameters); // number of function parameters
- nfparams2 = nfparams;
nfargs = fargs->dim; // number of function arguments
/* Check for match of function arguments with variadic template
@@ -737,34 +774,39 @@
goto L1;
else
{
- /* See if 'A' of the template parameter matches 'A'
- * of the type of the last function parameter.
+ /* Figure out which of the function parameters matches
+ * the tuple template parameter. Do this by matching
+ * type identifiers.
+ * Set the index of this function parameter to fptupindex.
*/
- Argument *fparam = (Argument *)fdtype->parameters->data[nfparams - 1];
+ for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
+ {
+ Argument *fparam = (Argument *)fdtype->parameters->data[fptupindex];
if (fparam->type->ty != Tident)
- goto L1;
+ continue;
TypeIdentifier *tid = (TypeIdentifier *)fparam->type;
if (!tp->ident->equals(tid->ident) || tid->idents.dim)
- goto L1;
+ continue;
if (fdtype->varargs) // variadic function doesn't
goto Lnomatch; // go with variadic template
- /* The types of the function arguments [nfparams - 1 .. nfargs]
+ /* The types of the function arguments
* now form the tuple argument.
*/
Tuple *t = new Tuple();
dedargs->data[parameters->dim - 1] = (void *)t;
- int tuple_dim = nfargs - (nfparams - 1);
+ tuple_dim = nfargs - (nfparams - 1);
t->objects.setDim(tuple_dim);
for (i = 0; i < tuple_dim; i++)
- { Expression *farg = (Expression *)fargs->data[nfparams - 1 + i];
+ { Expression *farg = (Expression *)fargs->data[fptupindex + i];
t->objects.data[i] = (void *)farg->type;
}
- nfparams2--; // don't consider the last parameter for type deduction
goto L2;
}
+ fptupindex = -1;
+ }
}
L1:
@@ -779,8 +821,18 @@
L2:
// Loop through the function parameters
- for (i = 0; i < nfparams2; i++)
+ for (i = 0; i < nfparams; i++)
{
+ /* Skip over function parameters which wound up
+ * as part of a template tuple parameter.
+ */
+ if (i == fptupindex)
+ { if (fptupindex == nfparams - 1)
+ break;
+ i += tuple_dim - 1;
+ continue;
+ }
+
Argument *fparam = Argument::getNth(fdtype->parameters, i);
Expression *farg;
MATCH m;
@@ -809,12 +861,12 @@
if (!m && fparam->type->toBasetype()->ty == Tdelegate)
{
TypeDelegate *td = (TypeDelegate *)fparam->type->toBasetype();
- TypeFunction *tf = (TypeFunction *)td->nextOf();
+ TypeFunction *tf = (TypeFunction *)td->next;
if (!tf->varargs && Argument::dim(tf->parameters) == 0)
{
- m = farg->type->deduceType(scope, tf->nextOf(), parameters, &dedtypes);
- if (!m && tf->nextOf()->toBasetype()->ty == Tvoid)
+ m = farg->type->deduceType(scope, tf->next, parameters, &dedtypes);
+ if (!m && tf->next->toBasetype()->ty == Tvoid)
m = MATCHconvert;
}
//printf("\tm2 = %d\n", m);
@@ -968,6 +1020,15 @@
return ::isVariadic(parameters);
}
+/***********************************
+ * We can overload templates.
+ */
+
+int TemplateDeclaration::isOverloadable()
+{
+ return 1;
+}
+
/*************************************************
* Given function arguments, figure out which template function
* to expand, and return that function.
@@ -977,7 +1038,7 @@
* fargs arguments to function
*/
-FuncDeclaration *TemplateDeclaration::deduce(Scope *sc, Loc loc,
+FuncDeclaration *TemplateDeclaration::deduceFunctionTemplate(Scope *sc, Loc loc,
Objects *targsi, Expressions *fargs)
{
MATCH m_best = MATCHnomatch;
@@ -988,7 +1049,7 @@
FuncDeclaration *fd;
#if 0
- printf("TemplateDeclaration::deduce() %s\n", toChars());
+ printf("TemplateDeclaration::deduceFunctionTemplate() %s\n", toChars());
printf(" targsi:\n");
if (targsi)
{ for (int i = 0; i < targsi->dim; i++)
@@ -1020,8 +1081,8 @@
MATCH m;
Objects dedargs;
- m = td->deduceMatch(targsi, fargs, &dedargs);
- //printf("deduceMatch = %d\n", m);
+ m = td->deduceFunctionTemplateMatch(targsi, fargs, &dedargs);
+ //printf("deduceFunctionTemplateMatch = %d\n", m);
if (!m) // if no match
continue;
@@ -1036,9 +1097,9 @@
int c2 = td_best->leastAsSpecialized(td);
//printf("c1 = %d, c2 = %d\n", c1, c2);
- if (c1 && !c2)
+ if (c1 > c2)
goto Ltd;
- else if (!c1 && c2)
+ else if (c1 < c2)
goto Ltd_best;
else
goto Lambig;
@@ -1108,6 +1169,8 @@
for (int i = 0; i < parameters->dim; i++)
{
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+ if (hgs->ddoc)
+ tp = (TemplateParameter *)origParameters->data[i];
if (i)
buf->writeByte(',');
tp->toCBuffer(buf, hgs);
@@ -1158,6 +1221,17 @@
* Return -1 if not found.
*/
+int templateIdentifierLookup(Identifier *id, TemplateParameters *parameters)
+{
+ for (size_t i = 0; i < parameters->dim; i++)
+ { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+
+ if (tp->ident->equals(id))
+ return i;
+ }
+ return -1;
+}
+
int templateParameterLookup(Type *tparam, TemplateParameters *parameters)
{
assert(tparam->ty == Tident);
@@ -1165,14 +1239,7 @@
//printf("\ttident = '%s'\n", tident->toChars());
if (tident->idents.dim == 0)
{
- Identifier *id = tident->ident;
-
- for (size_t i = 0; i < parameters->dim; i++)
- { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
-
- if (tp->ident->equals(id))
- return i;
- }
+ return templateIdentifierLookup(tident->ident, parameters);
}
return -1;
}
@@ -1274,7 +1341,32 @@
if (tparam->ty == Tsarray)
{
TypeSArray *tp = (TypeSArray *)tparam;
- if (dim->toInteger() != tp->dim->toInteger())
+
+ if (tp->dim->op == TOKvar &&
+ ((VarExp *)tp->dim)->var->storage_class & STCtemplateparameter)
+ { int i = templateIdentifierLookup(((VarExp *)tp->dim)->var->ident, parameters);
+ // This code matches code in TypeInstance::deduceType()
+ if (i == -1)
+ goto Lnomatch;
+ TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+ TemplateValueParameter *tvp = tp->isTemplateValueParameter();
+ if (!tvp)
+ goto Lnomatch;
+ Expression *e = (Expression *)dedtypes->data[i];
+ if (e)
+ {
+ if (!dim->equals(e))
+ goto Lnomatch;
+ }
+ else
+ { Type *vt = tvp->valType->semantic(0, sc);
+ MATCH m = (MATCH)dim->implicitConvTo(vt);
+ if (!m)
+ goto Lnomatch;
+ dedtypes->data[i] = dim;
+ }
+ }
+ else if (dim->toInteger() != tp->dim->toInteger())
return MATCHnomatch;
}
else if (tparam->ty == Taarray)
@@ -1327,9 +1419,11 @@
MATCH TypeAArray::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes)
{
- //printf("TypeAArray::deduceType()\n");
- //printf("\tthis = %d, ", ty); print();
- //printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#if 0
+ printf("TypeAArray::deduceType()\n");
+ printf("\tthis = %d, ", ty); print();
+ printf("\ttparam = %d, ", tparam->ty); tparam->print();
+#endif
// Extra check that index type must match
if (tparam && tparam->ty == Taarray)
@@ -1469,15 +1563,58 @@
//printf("tempinst->tempdecl = %p\n", tempinst->tempdecl);
//printf("tp->tempinst->tempdecl = %p\n", tp->tempinst->tempdecl);
if (!tp->tempinst->tempdecl)
- { if (!tp->tempinst->name->equals(tempinst->name))
+ { //printf("tp->tempinst->name = '%s'\n", tp->tempinst->name->toChars());
+ if (!tp->tempinst->name->equals(tempinst->name))
+ {
+ /* Handle case of:
+ * template Foo(T : sa!(T), alias sa)
+ */
+ int i = templateIdentifierLookup(tp->tempinst->name, parameters);
+ if (i == -1)
+ { /* Didn't find it as a parameter identifier. Try looking
+ * it up and seeing if is an alias. See Bugzilla 1454
+ */
+ Dsymbol *s = tempinst->tempdecl->scope->search(0, tp->tempinst->name, NULL);
+ if (s)
+ {
+ s = s->toAlias();
+ TemplateDeclaration *td = s->isTemplateDeclaration();
+ if (td && td == tempinst->tempdecl)
+ goto L2;
+ }
goto Lnomatch;
}
+ TemplateParameter *tpx = (TemplateParameter *)parameters->data[i];
+ // This logic duplicates tpx->matchArg()
+ TemplateAliasParameter *ta = tpx->isTemplateAliasParameter();
+ if (!ta)
+ goto Lnomatch;
+ Dsymbol *sa = tempinst->tempdecl;
+ if (!sa)
+ goto Lnomatch;
+ if (ta->specAlias && sa != ta->specAlias)
+ goto Lnomatch;
+ if (dedtypes->data[i])
+ { // Must match already deduced symbol
+ Dsymbol *s = (Dsymbol *)dedtypes->data[i];
+
+ if (s != sa)
+ goto Lnomatch;
+ }
+ dedtypes->data[i] = sa;
+ }
+ }
else if (tempinst->tempdecl != tp->tempinst->tempdecl)
goto Lnomatch;
+ L2:
+ if (tempinst->tiargs->dim != tp->tempinst->tiargs->dim)
+ goto Lnomatch;
+
for (int i = 0; i < tempinst->tiargs->dim; i++)
{
- //printf("test: [%d]\n", i);
+ //printf("\ttest: tempinst->tiargs[%d]\n", i);
+ int j;
Object *o1 = (Object *)tempinst->tiargs->data[i];
Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
@@ -1502,18 +1639,29 @@
else if (e1 && e2)
{
if (!e1->equals(e2))
+ { if (e2->op == TOKvar)
+ {
+ /*
+ * (T:Number!(e2), int e2)
+ */
+ j = templateIdentifierLookup(((VarExp *)e2)->var->ident, parameters);
+ goto L1;
+ }
goto Lnomatch;
}
+ }
else if (e1 && t2 && t2->ty == Tident)
- { int i = templateParameterLookup(t2, parameters);
- if (i == -1)
+ {
+ j = templateParameterLookup(t2, parameters);
+ L1:
+ if (j == -1)
goto Lnomatch;
- TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
+ TemplateParameter *tp = (TemplateParameter *)parameters->data[j];
// BUG: use tp->matchArg() instead of the following
TemplateValueParameter *tv = tp->isTemplateValueParameter();
if (!tv)
goto Lnomatch;
- Expression *e = (Expression *)dedtypes->data[i];
+ Expression *e = (Expression *)dedtypes->data[j];
if (e)
{
if (!e1->equals(e))
@@ -1524,7 +1672,7 @@
MATCH m = (MATCH)e1->implicitConvTo(vt);
if (!m)
goto Lnomatch;
- dedtypes->data[i] = e1;
+ dedtypes->data[j] = e1;
}
}
// BUG: Need to handle alias and tuple parameters
@@ -1836,6 +1984,7 @@
if (t)
{ // Must match already deduced type
+ m = MATCHexact;
if (!t->equals(ta))
goto Lnomatch;
}
@@ -2282,6 +2431,7 @@
return m;
Lnomatch:
+ //printf("\tno match\n");
*psparam = NULL;
return MATCHnomatch;
}
@@ -2769,7 +2919,7 @@
objFileModule = m;
#endif
}
- for (i = 0; 1; i++)
+ for (int i = 0; 1; i++)
{
if (i == a->dim)
{
@@ -2946,7 +3096,7 @@
Expression *ea = isExpression(o);
Dsymbol *sa = isDsymbol(o);
- //printf("1: tiargs->data[%d] = %p, %p, %p\n", j, o, isDsymbol(o), isTuple(o));
+ //printf("1: tiargs->data[%d] = %p, %p, %p, ea=%p, ta=%p\n", j, o, isDsymbol(o), isTuple(o), ea, ta);
if (ta)
{
//printf("type %s\n", ta->toChars());
@@ -3004,6 +3154,8 @@
ea = ea->semantic(sc);
ea = ea->optimize(WANTvalue | WANTinterpret);
tiargs->data[j] = ea;
+ if (ea->op == TOKtype)
+ tiargs->data[j] = ea->type;
}
else if (sa)
{
@@ -3055,6 +3207,7 @@
}
#if LOG
printf("It's an instance of '%s' kind '%s'\n", s->toChars(), s->kind());
+ if (s->parent)
printf("s->parent = '%s'\n", s->parent->toChars());
#endif
withsym = scopesym->isWithScopeSymbol();
@@ -3160,12 +3313,14 @@
}
dedtypes.setDim(td->parameters->dim);
+ dedtypes.zero();
if (!td->scope)
{
error("forward reference to template declaration %s", td->toChars());
return NULL;
}
m = td->matchWithInstance(this, &dedtypes, 0);
+ //printf("m = %d\n", m);
if (!m) // no match at all
continue;
@@ -3184,9 +3339,9 @@
int c2 = td_best->leastAsSpecialized(td);
//printf("c1 = %d, c2 = %d\n", c1, c2);
- if (c1 && !c2)
+ if (c1 > c2)
goto Ltd;
- else if (!c1 && c2)
+ else if (c1 < c2)
goto Ltd_best;
else
goto Lambig;
@@ -3285,15 +3440,38 @@
Lsa:
Declaration *d = sa->isDeclaration();
if (d && !d->isDataseg() &&
+#if V2
+ !(d->storage_class & STCmanifest) &&
+#endif
(!d->isFuncDeclaration() || d->isFuncDeclaration()->isNested()) &&
!isTemplateMixin())
{
// if module level template
if (tempdecl->toParent()->isModule())
+ { Dsymbol *dparent = d->toParent();
+ if (!isnested)
+ isnested = dparent;
+ else if (isnested != dparent)
{
- if (isnested && isnested != d->toParent())
- error("inconsistent nesting levels %s and %s", isnested->toChars(), d->toParent()->toChars());
- isnested = d->toParent();
+ /* Select the more deeply nested of the two.
+ * Error if one is not nested inside the other.
+ */
+ for (Dsymbol *p = isnested; p; p = p->parent)
+ {
+ if (p == dparent)
+ goto L1; // isnested is most nested
+ }
+ for (Dsymbol *p = dparent; 1; p = p->parent)
+ {
+ if (p == isnested)
+ { isnested = dparent;
+ goto L1; // dparent is most nested
+ }
+ }
+ error("is nested in both %s and %s", isnested->toChars(), dparent->toChars());
+ }
+ L1:
+ //printf("\tnested inside %s\n", isnested->toChars());
nested |= 1;
}
else
@@ -3825,6 +4003,8 @@
argsym->parent = scy->parent;
Scope *scope = scy->push(argsym);
+ unsigned errorsave = global.errors;
+
// Declare each template parameter as an alias for the argument type
declareParameters(scope);
@@ -3866,6 +4046,12 @@
semantic3(sc2);
}
+ // Give additional context info if error occurred during instantiation
+ if (global.errors != errorsave)
+ {
+ error("error instantiating");
+ }
+
sc2->pop();
scope->pop();
Index: d/dmd/scope.h
===================================================================
--- d/dmd/scope.h (Revision 199)
+++ d/dmd/scope.h (Arbeitskopie)
@@ -61,6 +61,7 @@
int noctor; // set if constructor calls aren't allowed
int intypeof; // in typeof(exp)
int parameterSpecialization; // if in template parameter specialization
+ int noaccesscheck; // don't do access checks
unsigned callSuper; // primitive flow analysis for constructors
#define CSXthis_ctor 1 // called this()
Index: d/dmd/template.h
===================================================================
--- d/dmd/template.h (Revision 199)
+++ d/dmd/template.h (Arbeitskopie)
@@ -48,6 +48,9 @@
struct TemplateDeclaration : ScopeDsymbol
{
TemplateParameters *parameters; // array of TemplateParameter's
+
+ TemplateParameters *origParameters; // originals for Ddoc
+
Array instances; // array of TemplateInstance's
TemplateDeclaration *overnext; // next overloaded TemplateDeclaration
@@ -70,13 +73,14 @@
MATCH matchWithInstance(TemplateInstance *ti, Objects *atypes, int flag);
int leastAsSpecialized(TemplateDeclaration *td2);
- MATCH deduceMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
- FuncDeclaration *deduce(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
+ MATCH deduceFunctionTemplateMatch(Objects *targsi, Expressions *fargs, Objects *dedargs);
+ FuncDeclaration *deduceFunctionTemplate(Scope *sc, Loc loc, Objects *targsi, Expressions *fargs);
void declareParameter(Scope *sc, TemplateParameter *tp, Object *o);
TemplateDeclaration *isTemplateDeclaration() { return this; }
TemplateTupleParameter *isVariadic();
+ int isOverloadable();
};
struct TemplateParameter
Index: d/dmd/mangle.c
===================================================================
--- d/dmd/mangle.c (Revision 199)
+++ d/dmd/mangle.c (Arbeitskopie)
@@ -147,6 +147,9 @@
if (isMain())
return "_Dmain";
+ if (isWinMain() || isDllMain())
+ return ident->toChars();
+
assert(this);
return Declaration::mangle();
}
Index: d/dmd/doc.c
===================================================================
--- d/dmd/doc.c (Revision 199)
+++ d/dmd/doc.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2006 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -102,6 +102,7 @@
unsigned char *skipwhitespace(unsigned char *p);
unsigned skiptoident(OutBuffer *buf, unsigned i);
unsigned skippastident(OutBuffer *buf, unsigned i);
+unsigned skippastURL(OutBuffer *buf, unsigned i);
void highlightText(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
void highlightCode(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
void highlightCode2(Scope *sc, Dsymbol *s, OutBuffer *buf, unsigned offset);
@@ -114,7 +115,7 @@
</head><body>\n\
<h1>$(TITLE)</h1>\n\
$(BODY)\n\
- <hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/ddoc.html, Ddoc). $(COPYRIGHT))\n\
+ <hr>$(SMALL Page generated by $(LINK2 http://www.digitalmars.com/d/1.0/ddoc.html, Ddoc). $(COPYRIGHT))\n\
</body></html>\n\
\n\
B = <b>$0</b>\n\
@@ -269,7 +270,6 @@
}
buf.printf("$(DDOC_COMMENT Generated by Ddoc from %s)\n", srcfile->toChars());
-
if (isDocFile)
{
size_t commentlen = strlen((char *)comment);
@@ -283,7 +283,6 @@
}
else
{
-
dc->writeSections(sc, this, sc->docbuf);
emitMemberComments(sc);
}
@@ -373,6 +372,7 @@
void Dsymbol::emitDitto(Scope *sc)
{
+ //printf("Dsymbol::emitDitto() %s %s\n", kind(), toChars());
OutBuffer *buf = sc->docbuf;
unsigned o;
OutBuffer b;
@@ -380,6 +380,17 @@
b.writestring("$(DDOC_DITTO ");
o = b.offset;
toDocBuffer(&b);
+ //printf("b: '%.*s'\n", b.offset, b.data);
+ /* If 'this' is a function template, then highlightCode() was
+ * already run by FuncDeclaration::toDocbuffer().
+ */
+ TemplateDeclaration *td;
+ if (parent &&
+ (td = parent->isTemplateDeclaration()) != NULL &&
+ td->onemember == this)
+ {
+ }
+ else
highlightCode(sc, this, &b, o);
b.writeByte(')');
buf->spread(sc->lastoffset, b.offset);
@@ -437,6 +448,7 @@
void Dsymbol::emitComment(Scope *sc) { }
void InvariantDeclaration::emitComment(Scope *sc) { }
+//void PostBlitDeclaration::emitComment(Scope *sc) { }
void DtorDeclaration::emitComment(Scope *sc) { }
void StaticCtorDeclaration::emitComment(Scope *sc) { }
void StaticDtorDeclaration::emitComment(Scope *sc) { }
@@ -637,6 +649,7 @@
//printf("Dsymbol::toDocbuffer() %s\n", toChars());
HdrGenState hgs;
+ hgs.ddoc = 1;
toCBuffer(buf, &hgs);
}
@@ -654,6 +667,10 @@
buf->writestring("static ");
if (d->isConst())
buf->writestring("const ");
+#if V2
+ if (d->isInvariant())
+ buf->writestring("invariant ");
+#endif
if (d->isFinal())
buf->writestring("final ");
if (d->isSynchronized())
@@ -663,7 +680,7 @@
void Declaration::toDocBuffer(OutBuffer *buf)
{
- //printf("Declaration::toDocbuffer() %s\n", toChars());
+ //printf("Declaration::toDocbuffer() %s, originalType = %p\n", toChars(), originalType);
if (ident)
{
prefix(buf, this);
@@ -671,6 +688,11 @@
if (type)
{ HdrGenState hgs;
hgs.ddoc = 1;
+ if (originalType)
+ { //originalType->print();
+ originalType->toCBuffer(buf, ident, &hgs);
+ }
+ else
type->toCBuffer(buf, ident, &hgs);
}
else
@@ -723,22 +745,22 @@
td->onemember == this)
{ HdrGenState hgs;
unsigned o = buf->offset;
+ TypeFunction *tf = (TypeFunction *)type;
hgs.ddoc = 1;
prefix(buf, td);
- type->next->toCBuffer(buf, NULL, &hgs);
+ tf->next->toCBuffer(buf, NULL, &hgs);
buf->writeByte(' ');
buf->writestring(ident->toChars());
buf->writeByte('(');
- for (int i = 0; i < td->parameters->dim; i++)
+ for (int i = 0; i < td->origParameters->dim; i++)
{
- TemplateParameter *tp = (TemplateParameter *)td->parameters->data[i];
+ TemplateParameter *tp = (TemplateParameter *)td->origParameters->data[i];
if (i)
buf->writeByte(',');
tp->toCBuffer(buf, &hgs);
}
buf->writeByte(')');
- TypeFunction *tf = (TypeFunction *)type;
Argument::argsToCBuffer(buf, &hgs, tf->parameters, tf->varargs);
buf->writestring(";\n");
@@ -1484,6 +1506,55 @@
}
+/************************************************
+ * Scan forward past URL starting at i.
+ * We don't want to highlight parts of a URL.
+ * Returns:
+ * i if not a URL
+ * index just past it if it is a URL
+ */
+
+unsigned skippastURL(OutBuffer *buf, unsigned i)
+{ unsigned length = buf->offset - i;
+ unsigned char *p = &buf->data[i];
+ unsigned j;
+ unsigned sawdot = 0;
+
+ if (length > 7 && memicmp((char *)p, "http://", 7) == 0)
+ {
+ j = 7;
+ }
+ else if (length > 8 && memicmp((char *)p, "https://", 8) == 0)
+ {
+ j = 8;
+ }
+ else
+ goto Lno;
+
+ for (; j < length; j++)
+ { unsigned char c = p[j];
+ if (isalnum(c))
+ continue;
+ if (c == '-' || c == '_' || c == '?' ||
+ c == '=' || c == '%' || c == '&' ||
+ c == '/' || c == '+' || c == '#' ||
+ c == '~')
+ continue;
+ if (c == '.')
+ {
+ sawdot = 1;
+ continue;
+ }
+ break;
+ }
+ if (sawdot)
+ return i + j;
+
+Lno:
+ return i;
+}
+
+
/****************************************************
*/
@@ -1728,6 +1799,12 @@
j = skippastident(buf, i);
if (j > i)
{
+ unsigned k = skippastURL(buf, i);
+ if (k > i)
+ { i = k - 1;
+ break;
+ }
+
if (buf->data[i] == '_') // leading '_' means no highlight
{
buf->remove(i, 1);
Index: d/dmd/parse.c
===================================================================
--- d/dmd/parse.c (Revision 199)
+++ d/dmd/parse.c (Arbeitskopie)
@@ -650,6 +650,14 @@
id = token.ident;
else if (token.value == TOKint32v)
level = (unsigned)token.uns64value;
+#if V2
+ /* Allow:
+ * version (unittest)
+ * even though unittest is a keyword
+ */
+ else if (token.value == TOKunittest)
+ id = Lexer::idPool(Token::toChars(TOKunittest));
+#endif
else
error("identifier or integer expected, not %s", token.toChars());
nextToken();
@@ -1232,13 +1240,12 @@
TemplateParameters *Parser::parseTemplateParameterList()
{
- TemplateParameters *tpl;
+ TemplateParameters *tpl = new TemplateParameters();
if (token.value != TOKlparen)
{ error("parenthesized TemplateParameterList expected following TemplateIdentifier");
goto Lerr;
}
- tpl = new TemplateParameters();
nextToken();
// Get array of TemplateParameters
@@ -1322,7 +1329,7 @@
if (!tp_ident)
{
error("no identifier for template value parameter");
- goto Lerr;
+ tp_ident = new Identifier("error", TOKidentifier);
}
if (token.value == TOKcolon) // : CondExpression
{
@@ -1343,10 +1350,8 @@
}
}
check(TOKrparen);
+Lerr:
return tpl;
-
-Lerr:
- return NULL;
}
/******************************************
@@ -2261,6 +2266,9 @@
break;
continue;
+ case TOKeof:
+ break;
+
default:
continue;
}
@@ -2301,6 +2309,10 @@
nextToken();
break;
+ case TOKeof:
+ error("found EOF instead of initializer");
+ break;
+
default:
value = parseInitializer();
is->addInit(NULL, value);
Index: d/dmd/interpret.c
===================================================================
--- d/dmd/interpret.c (Revision 199)
+++ d/dmd/interpret.c (Arbeitskopie)
@@ -57,7 +57,7 @@
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments)
{
#if LOG
- printf("FuncDeclaration::interpret() %s\n", toChars());
+ printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun);
#endif
if (global.errors)
@@ -161,7 +161,15 @@
else
{ /* Value parameters
*/
- earg = earg->interpret(&istatex);
+ Type *ta = arg->type->toBasetype();
+ if (ta->ty == Tsarray && earg->op == TOKaddress)
+ {
+ /* Static arrays are passed by a simple pointer.
+ * Skip past this to get at the actual arg.
+ */
+ earg = ((AddrExp *)earg)->e1;
+ }
+ earg = earg->interpret(istate ? istate : &istatex);
if (earg == EXP_CANT_INTERPRET)
return NULL;
v->value = earg;
@@ -177,13 +185,13 @@
Expressions valueSaves;
if (istate)
{
- //printf("saving state...\n");
+ //printf("saving local variables...\n");
valueSaves.setDim(istate->vars.dim);
for (size_t i = 0; i < istate->vars.dim; i++)
{ VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
if (v)
{
- //printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value->toChars());
+ //printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
valueSaves.data[i] = v->value;
v->value = NULL;
}
@@ -230,10 +238,13 @@
{
/* Restore the variable values
*/
+ //printf("restoring local variables...\n");
for (size_t i = 0; i < istate->vars.dim; i++)
{ VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
if (v)
- v->value = (Expression *)valueSaves.data[i];
+ { v->value = (Expression *)valueSaves.data[i];
+ //printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
+ }
}
}
@@ -591,10 +602,13 @@
if (e && e != EXP_CONTINUE_INTERPRET)
break;
Lcontinue:
+ if (increment)
+ {
e = increment->interpret(istate);
if (e == EXP_CANT_INTERPRET)
break;
}
+ }
else if (e->isBool(FALSE))
{ e = NULL;
break;
@@ -904,6 +918,8 @@
{
#if LOG
printf("Expression::interpret() %s\n", toChars());
+ printf("type = %s\n", type->toChars());
+ dump(0);
#endif
return EXP_CANT_INTERPRET;
}
@@ -949,7 +965,11 @@
SymbolDeclaration *s = d->isSymbolDeclaration();
if (v)
{
+#if V2
+ if ((v->isConst() || v->isInvariant()) && v->init && !v->value)
+#else
if (v->isConst() && v->init)
+#endif
{ e = v->init->toExpression();
if (e && !e->type)
e->type = v->type;
@@ -1001,7 +1021,11 @@
else if (v->init->isVoidInitializer())
e = NULL;
}
+#if V2
+ else if (s == v && (v->isConst() || v->isInvariant()) && v->init)
+#else
else if (s == v && v->isConst() && v->init)
+#endif
{ e = v->init->toExpression();
if (!e)
e = EXP_CANT_INTERPRET;
@@ -1416,8 +1440,16 @@
*/
if (v->value && v->value->op == TOKvar)
{
- ve = (VarExp *)v->value;
- v = ve->var->isVarDeclaration();
+ VarExp *ve2 = (VarExp *)v->value;
+ if (ve2->var->isSymbolDeclaration())
+ {
+ /* This can happen if v is a struct initialized to
+ * 0 using an __initZ SymbolDeclaration from
+ * TypeStruct::defaultInit()
+ */
+ }
+ else
+ v = ve2->var->isVarDeclaration();
assert(v);
}
@@ -1445,6 +1477,7 @@
{
if (i == istate->vars.dim)
{ istate->vars.push(v);
+ //printf("\tadding %s to istate\n", v->toChars());
break;
}
if (v == (VarDeclaration *)istate->vars.data[i])
@@ -1797,7 +1830,27 @@
{
FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
if (fd)
- { // Inline .dup
+ {
+#if V2
+ enum BUILTIN b = fd->isBuiltin();
+ if (b)
+ { Expressions args;
+ args.setDim(arguments->dim);
+ for (size_t i = 0; i < args.dim; i++)
+ {
+ Expression *earg = (Expression *)arguments->data[i];
+ earg = earg->interpret(istate);
+ if (earg == EXP_CANT_INTERPRET)
+ return earg;
+ args.data[i] = (void *)earg;
+ }
+ e = eval_builtin(b, &args);
+ if (!e)
+ e = EXP_CANT_INTERPRET;
+ }
+ else
+#endif
+ // Inline .dup
if (fd->ident == Id::adDup && arguments && arguments->dim == 2)
{
e = (Expression *)arguments->data[1];
@@ -1812,7 +1865,7 @@
Expression *eresult = fd->interpret(istate, arguments);
if (eresult)
e = eresult;
- else if (fd->type->toBasetype()->nextOf()->ty == Tvoid)
+ else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
e = EXP_VOID_INTERPRET;
else
error("cannot evaluate %s at compile time", toChars());
Index: d/dmd/toir.c
===================================================================
--- d/dmd/toir.c (Revision 199)
+++ d/dmd/toir.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -102,6 +102,11 @@
{ /* Going down one nesting level, i.e. we're calling
* a nested function from its enclosing function.
*/
+#if V2
+ if (irs->sclosure)
+ ethis = el_var(irs->sclosure);
+ else
+#endif
if (irs->sthis)
{ // We have a 'this' pointer for the current function
ethis = el_var(irs->sthis);
@@ -111,7 +116,11 @@
* adding this frame into the linked list of stack
* frames.
*/
+#if V2
+ if (thisfd->closureVars.dim)
+#else
if (thisfd->nestedFrameRef)
+#endif
{ /* Local variables are referenced, can't skip.
* Address of 'this' gives the 'this' for the nested
* function
@@ -124,7 +133,11 @@
* use NULL if no references to the current function's frame
*/
ethis = el_long(TYnptr, 0);
+#if V2
+ if (thisfd->closureVars.dim)
+#else
if (thisfd->nestedFrameRef)
+#endif
{ /* OPframeptr is an operator that gets the frame pointer
* for the current function, i.e. for the x86 it gets
* the value of EBP
@@ -160,7 +173,11 @@
if (thisfd->isNested())
{
FuncDeclaration *p = s->toParent2()->isFuncDeclaration();
+#if V2
+ if (!p || p->closureVars.dim)
+#else
if (!p || p->nestedFrameRef)
+#endif
ethis = el_una(OPind, TYnptr, ethis);
}
else if (thisfd->vthis)
@@ -174,13 +191,15 @@
* function must be a member function of that class.
*/
ClassDeclaration *cd = s->isClassDeclaration();
- assert(cd);
+ if (!cd)
+ goto Lnoframe;
if (//cd->baseClass == fd ||
fd->isClassDeclaration() &&
fd->isClassDeclaration()->isBaseOf(cd, NULL))
break;
if (!cd->isNested() || !cd->vthis)
{
+ Lnoframe:
irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars());
return el_long(TYnptr, 0); // error recovery
}
@@ -194,7 +213,11 @@
* nested references are skipped in the linked list
* of frames.
*/
+#if V2
+ if (s->toParent2()->isFuncDeclaration()->closureVars.dim)
+#else
if (s->toParent2()->isFuncDeclaration()->nestedFrameRef)
+#endif
ethis = el_una(OPind, TYnptr, ethis);
break;
}
@@ -204,7 +227,11 @@
* nested references are skipped in the linked list
* of frames.
*/
+#if V2
+ if (s->toParent2()->isFuncDeclaration()->closureVars.dim)
+#else
if (s->toParent2()->isFuncDeclaration()->nestedFrameRef)
+#endif
ethis = el_una(OPind, TYnptr, ethis);
}
}
@@ -351,4 +378,110 @@
return einit;
}
+/*************************************
+ * Closures are implemented by taking the local variables that
+ * need to survive the scope of the function, and copying them
+ * into a gc allocated chuck of memory. That chunk, called the
+ * closure here, is inserted into the linked list of stack
+ * frames instead of the usual stack frame.
+ *
+ * buildClosure() inserts code just after the function prolog
+ * is complete. It allocates memory for the closure, allocates
+ * a local variable (sclosure) to point to it, inserts into it
+ * the link to the enclosing frame, and copies into it the parameters
+ * that are referred to in nested functions.
+ * In VarExp::toElem and SymOffExp::toElem, when referring to a
+ * variable that is in a closure, takes the offset from sclosure rather
+ * than from the frame pointer.
+ *
+ * getEthis() and NewExp::toElem need to use sclosure, if set, rather
+ * than the current frame pointer.
+ */
+#if V2
+
+void FuncDeclaration::buildClosure(IRState *irs)
+{
+ if (needsClosure())
+ { // Generate closure on the heap
+ // BUG: doesn't capture variadic arguments passed to this function
+
+ Symbol *sclosure;
+ sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype());
+ sclosure->Sflags |= SFLtrue | SFLfree;
+ symbol_add(sclosure);
+ irs->sclosure = sclosure;
+
+ unsigned offset = PTRSIZE; // leave room for previous sthis
+ for (int i = 0; i < closureVars.dim; i++)
+ { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
+ assert(v->isVarDeclaration());
+
+ /* Align and allocate space for v in the closure
+ * just like AggregateDeclaration::addField() does.
+ */
+ unsigned memsize = v->type->size();
+ unsigned memalignsize = v->type->alignsize();
+ unsigned xalign = v->type->memalign(global.structalign);
+ AggregateDeclaration::alignmember(xalign, memalignsize, &offset);
+ v->offset = offset;
+ offset += memsize;
+
+ /* Can't do nrvo if the variable is put in a closure, since
+ * what the shidden points to may no longer exist.
+ */
+ if (nrvo_can && nrvo_var == v)
+ {
+ nrvo_can = 0;
+ }
+ }
+ // offset is now the size of the closure
+
+ // Allocate memory for the closure
+ elem *e;
+ e = el_long(TYint, offset);
+ e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e);
+
+ // Assign block of memory to sclosure
+ // sclosure = allocmemory(sz);
+ e = el_bin(OPeq, TYvoid, el_var(sclosure), e);
+
+ // Set the first element to sthis
+ // *(sclosure + 0) = sthis;
+ elem *ethis;
+ if (irs->sthis)
+ ethis = el_var(irs->sthis);
+ else
+ ethis = el_long(TYnptr, 0);
+ elem *ex = el_una(OPind, TYnptr, el_var(sclosure));
+ ex = el_bin(OPeq, TYnptr, ex, ethis);
+ e = el_combine(e, ex);
+
+ // Copy function parameters into closure
+ for (int i = 0; i < closureVars.dim; i++)
+ { VarDeclaration *v = (VarDeclaration *)closureVars.data[i];
+
+ if (!v->isParameter())
+ continue;
+ tym_t tym = v->type->totym();
+ if (v->type->toBasetype()->ty == Tsarray || v->isOut() || v->isRef())
+ tym = TYnptr; // reference parameters are just pointers
+ ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYint, v->offset));
+ ex = el_una(OPind, tym, ex);
+ if (ex->Ety == TYstruct)
+ { ex->Enumbytes = v->type->size();
+ ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol()));
+ ex->Enumbytes = v->type->size();
+ }
+ else
+ ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol()));
+
+ e = el_combine(e, ex);
+ }
+
+ block_appendexp(irs->blx->curblock, e);
+ }
+}
+
+#endif
+
Index: d/dmd/lexer.c
===================================================================
--- d/dmd/lexer.c (Revision 199)
+++ d/dmd/lexer.c (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -602,8 +602,20 @@
do
{
p++;
+ switch (*p)
+ {
+ case 'u':
+ case 'U':
+ case '&':
c = escapeSequence();
stringbuffer.writeUTF8(c);
+ break;
+
+ default:
+ c = escapeSequence();
+ stringbuffer.writeByte(c);
+ break;
+ }
} while (*p == '\\');
t->len = stringbuffer.offset;
stringbuffer.writeByte(0);
@@ -727,6 +739,15 @@
t->value = TOKint64v;
t->uns64value = major * 1000 + minor;
}
+#if V2
+ else if (id == Id::EOFX)
+ {
+ t->value = TOKeof;
+ // Advance scanner to end of file
+ while (!(*p == 0 || *p == 0x1A))
+ p++;
+ }
+#endif
}
//printf("t->value = %d\n",t->value);
return;
@@ -1299,7 +1320,7 @@
default:
if (isoctal(c))
- { unsigned char v;
+ { unsigned v;
n = 0;
v = 0;
@@ -1309,6 +1330,8 @@
c = *++p;
} while (++n < 3 && isoctal(c));
c = v;
+ if (c > 0xFF)
+ error("0%03o is larger than a byte", c);
}
else
error("undefined escape sequence \\%c\n",c);
@@ -1496,7 +1519,6 @@
{
case '\n':
Lnextline:
-printf("Lnextline\n");
loc.linnum++;
startline = 1;
if (blankrol)
@@ -1553,7 +1575,7 @@
}
else
{ hereid = t.ident;
-printf("hereid = '%s'\n", hereid->toChars());
+ //printf("hereid = '%s'\n", hereid->toChars());
blankrol = 1;
}
nest = 0;
@@ -1587,11 +1609,10 @@
unsigned char *psave = p;
p--;
scan(&t); // read in possible heredoc identifier
-printf("endid = '%s'\n", t.ident->toChars());
+ //printf("endid = '%s'\n", t.ident->toChars());
if (t.value == TOKidentifier && t.ident->equals(hereid))
{ /* should check that rest of line is blank
*/
-printf("done\n");
goto Ldone;
}
p = psave;
@@ -2171,7 +2192,7 @@
break;
if (d >= r)
break;
- if (n * r + d < n)
+ if (n && n * r + d <= n)
{
error ("integer overflow");
break;
@@ -2751,13 +2772,10 @@
*/
Identifier *Lexer::idPool(const char *s)
-{ unsigned len;
- Identifier *id;
- StringValue *sv;
-
- len = strlen(s);
- sv = stringtable.update(s, len);
- id = (Identifier *) sv->ptrvalue;
+{
+ size_t len = strlen(s);
+ StringValue *sv = stringtable.update(s, len);
+ Identifier *id = (Identifier *) sv->ptrvalue;
if (!id)
{
id = new Identifier(sv->lstring.string, TOKidentifier);
@@ -2766,6 +2784,25 @@
return id;
}
+/*********************************************
+ * Create a unique identifier using the prefix s.
+ */
+
+Identifier *Lexer::uniqueId(const char *s, int num)
+{ char buffer[32];
+ size_t slen = strlen(s);
+
+ assert(slen + sizeof(num) * 3 + 1 <= sizeof(buffer));
+ sprintf(buffer, "%s%d", s, num);
+ return idPool(buffer);
+}
+
+Identifier *Lexer::uniqueId(const char *s)
+{
+ static int num;
+ return uniqueId(s, ++num);
+}
+
/****************************************
*/
@@ -2884,12 +2921,16 @@
{ "invariant", TOKinvariant },
{ "unittest", TOKunittest },
{ "version", TOKversion },
+ //{ "manifest", TOKmanifest },
// Added after 1.0
{ "ref", TOKref },
{ "macro", TOKmacro },
#if V2
+ { "pure", TOKpure },
+ { "nothrow", TOKnothrow },
{ "__traits", TOKtraits },
+ { "__overloadset", TOKoverloadset },
#endif
};
@@ -2942,6 +2983,9 @@
Token::tochars[TOKxorass] = "^=";
Token::tochars[TOKassign] = "=";
Token::tochars[TOKconstruct] = "=";
+#if V2
+ Token::tochars[TOKblit] = "=";
+#endif
Token::tochars[TOKlt] = "<";
Token::tochars[TOKgt] = ">";
Token::tochars[TOKle] = "<=";
@@ -3025,4 +3069,5 @@
Token::tochars[TOKtuple] = "tuple";
Token::tochars[TOKdeclaration] = "declaration";
Token::tochars[TOKdottd] = "dottd";
+ Token::tochars[TOKon_scope_exit] = "scope(exit)";
}
Index: d/dmd/lexer.h
===================================================================
--- d/dmd/lexer.h (Revision 199)
+++ d/dmd/lexer.h (Arbeitskopie)
@@ -1,6 +1,6 @@
// Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2008 by Digital Mars
// All Rights Reserved
// written by Walter Bright
// http://www.digitalmars.com
@@ -92,11 +92,11 @@
TOKand, TOKor, TOKxor,
TOKandass, TOKorass, TOKxorass,
TOKassign, TOKnot, TOKtilde,
- TOKplusplus, TOKminusminus, TOKconstruct,
+ TOKplusplus, TOKminusminus, TOKconstruct, TOKblit,
TOKdot, TOKarrow, TOKcomma,
TOKquestion, TOKandand, TOKoror,
-// 103
+// 104
// Numeric literals
TOKint32v, TOKuns32v,
TOKint64v, TOKuns64v,
@@ -131,7 +131,7 @@
TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
- TOKauto, TOKpackage,
+ TOKauto, TOKpackage, TOKmanifest,
// Statements
TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
@@ -152,6 +152,8 @@
TOKmacro,
#if V2
TOKtraits,
+ TOKoverloadset,
+ TOKpure,
#endif
TOKMAX
@@ -261,6 +263,8 @@
static void initKeywords();
static Identifier *idPool(const char *s);
+ static Identifier *uniqueId(const char *s);
+ static Identifier *uniqueId(const char *s, int num);
TOK nextToken();
void scan(Token *t);
Index: d/dmd/cast.c
===================================================================
--- d/dmd/cast.c (Revision 199)
+++ d/dmd/cast.c (Arbeitskopie)
@@ -578,30 +578,27 @@
*/
Expression *Expression::castTo(Scope *sc, Type *t)
-{ Expression *e;
- Type *tb;
-
+{
//printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars());
#if 0
printf("Expression::castTo(this=%s, type=%s, t=%s)\n",
toChars(), type->toChars(), t->toChars());
#endif
- e = this;
- tb = t->toBasetype();
- type = type->toBasetype();
- if (tb != type)
+ if (type == t)
+ return this;
+ Expression *e = this;
+ Type *tb = t->toBasetype();
+ Type *typeb = type->toBasetype();
+ if (tb != typeb)
{
- if (tb->ty == Tbit && isBit())
- ;
-
// Do (type *) cast of (type [dim])
- else if (tb->ty == Tpointer &&
- type->ty == Tsarray
+ if (tb->ty == Tpointer &&
+ typeb->ty == Tsarray
)
{
//printf("Converting [dim] to *\n");
- if (type->size(loc) == 0)
+ if (typeb->size(loc) == 0)
e = new NullExp(loc);
else
e = new AddrExp(loc, e);
@@ -610,8 +607,8 @@
else if (tb->ty == Tdelegate && type->ty != Tdelegate)
{
TypeDelegate *td = (TypeDelegate *)tb;
- TypeFunction *tf = (TypeFunction *)td->next;
- return toDelegate(sc, tf->next);
+ TypeFunction *tf = (TypeFunction *)td->nextOf();
+ return toDelegate(sc, tf->nextOf());
}
#endif
else
@@ -619,6 +616,11 @@
e = new CastExp(loc, e, tb);
}
}
+ else
+ {
+ e = e->copy(); // because of COW for assignment to e->type
+ }
+ assert(e != this);
e->type = t;
//printf("Returning: %s\n", e->toChars());
return e;
@@ -626,47 +628,62 @@
Expression *RealExp::castTo(Scope *sc, Type *t)
-{
- if (type->isreal() && t->isreal())
- type = t;
- else if (type->isimaginary() && t->isimaginary())
- type = t;
+{ Expression *e = this;
+ if (type != t)
+ {
+ if ((type->isreal() && t->isreal()) ||
+ (type->isimaginary() && t->isimaginary())
+ )
+ { e = copy();
+ e->type = t;
+ }
else
- return Expression::castTo(sc, t);
- return this;
+ e = Expression::castTo(sc, t);
+ }
+ return e;
}
Expression *ComplexExp::castTo(Scope *sc, Type *t)
-{
+{ Expression *e = this;
+ if (type != t)
+ {
if (type->iscomplex() && t->iscomplex())
- type = t;
+ { e = copy();
+ e->type = t;
+ }
else
- return Expression::castTo(sc, t);
- return this;
+ e = Expression::castTo(sc, t);
+ }
+ return e;
}
Expression *NullExp::castTo(Scope *sc, Type *t)
-{ Expression *e;
+{ NullExp *e;
Type *tb;
//printf("NullExp::castTo(t = %p)\n", t);
+ if (type == t)
+ {
committed = 1;
- e = this;
+ return this;
+ }
+ e = (NullExp *)copy();
+ e->committed = 1;
tb = t->toBasetype();
- type = type->toBasetype();
- if (tb != type)
+ e->type = type->toBasetype();
+ if (tb != e->type)
{
// NULL implicitly converts to any pointer type or dynamic array
- if (type->ty == Tpointer && type->next->ty == Tvoid &&
+ if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid &&
(tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray ||
tb->ty == Tdelegate))
{
#if 0
if (tb->ty == Tdelegate)
{ TypeDelegate *td = (TypeDelegate *)tb;
- TypeFunction *tf = (TypeFunction *)td->next;
+ TypeFunction *tf = (TypeFunction *)td->nextOf();
if (!tf->varargs &&
!(tf->arguments && tf->arguments->dim)
@@ -679,8 +696,7 @@
}
else
{
- return Expression::castTo(sc, t);
- //e = new CastExp(loc, e, tb);
+ return e->Expression::castTo(sc, t);
}
}
e->type = t;
@@ -950,23 +966,31 @@
Expression *TupleExp::castTo(Scope *sc, Type *t)
-{
- for (size_t i = 0; i < exps->dim; i++)
- { Expression *e = (Expression *)exps->data[i];
- e = e->castTo(sc, t);
- exps->data[i] = (void *)e;
+{ TupleExp *e = (TupleExp *)copy();
+ e->exps = (Expressions *)exps->copy();
+ for (size_t i = 0; i < e->exps->dim; i++)
+ { Expression *ex = (Expression *)e->exps->data[i];
+ ex = ex->castTo(sc, t);
+ e->exps->data[i] = (void *)ex;
}
- return this;
+ return e;
}
Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t)
{
+#if 0
+ printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n",
+ toChars(), type->toChars(), t->toChars());
+#endif
+ if (type == t)
+ return this;
+ ArrayLiteralExp *e = this;
Type *typeb = type->toBasetype();
Type *tb = t->toBasetype();
if ((tb->ty == Tarray || tb->ty == Tsarray) &&
(typeb->ty == Tarray || typeb->ty == Tsarray) &&
- tb->next->toBasetype()->ty != Tvoid)
+ tb->nextOf()->toBasetype()->ty != Tvoid)
{
if (tb->ty == Tsarray)
{ TypeSArray *tsa = (TypeSArray *)tb;
@@ -974,46 +998,56 @@
goto L1;
}
+ e = (ArrayLiteralExp *)copy();
+ e->elements = (Expressions *)elements->copy();
for (int i = 0; i < elements->dim; i++)
- { Expression *e = (Expression *)elements->data[i];
- e = e->castTo(sc, tb->next);
- elements->data[i] = (void *)e;
+ { Expression *ex = (Expression *)elements->data[i];
+ ex = ex->castTo(sc, tb->nextOf());
+ e->elements->data[i] = (void *)ex;
}
- type = t;
- return this;
+ e->type = t;
+ return e;
}
if (tb->ty == Tpointer && typeb->ty == Tsarray)
{
- type = typeb->next->pointerTo();
+ e = (ArrayLiteralExp *)copy();
+ e->type = typeb->nextOf()->pointerTo();
}
L1:
- return Expression::castTo(sc, t);
+ return e->Expression::castTo(sc, t);
}
Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t)
{
+ if (type == t)
+ return this;
+ AssocArrayLiteralExp *e = this;
Type *typeb = type->toBasetype();
Type *tb = t->toBasetype();
if (tb->ty == Taarray && typeb->ty == Taarray &&
- tb->next->toBasetype()->ty != Tvoid)
+ tb->nextOf()->toBasetype()->ty != Tvoid)
{
+ e = (AssocArrayLiteralExp *)copy();
+ e->keys = (Expressions *)keys->copy();
+ e->values = (Expressions *)values->copy();
assert(keys->dim == values->dim);
for (size_t i = 0; i < keys->dim; i++)
- { Expression *e = (Expression *)values->data[i];
- e = e->castTo(sc, tb->next);
- values->data[i] = (void *)e;
+ { Expression *ex = (Expression *)values->data[i];
+ ex = ex->castTo(sc, tb->nextOf());
+ e->values->data[i] = (void *)ex;
- e = (Expression *)keys->data[i];
- e = e->castTo(sc, ((TypeAArray *)tb)->key);
- keys->data[i] = (void *)e;
+ ex = (Expression *)keys->data[i];
+ ex = ex->castTo(sc, ((TypeAArray *)tb)->index);
+ e->keys->data[i] = (void *)ex;
}
- type = t;
- return this;
+ e->type = t;
+ return e;
}
L1:
- return Expression::castTo(sc, t);
+ return e->Expression::castTo(sc, t);
}
+
Expression *SymOffExp::castTo(Scope *sc, Type *t)
{
Type *tb;
Index: d/dmd/link.c
===================================================================
--- d/dmd/link.c (Revision 199)
+++ d/dmd/link.c (Arbeitskopie)
@@ -255,7 +255,7 @@
argv.push((void *)"-lpthread");
argv.push((void *)"-lm");
- if (!global.params.quiet)
+ if (!global.params.quiet || global.params.verbose)
{
// Print it
for (i = 0; i < argv.dim; i++)