changeset 5:63623152e82a

Fixed memory corruption bug which was introduced when attempting to restore GC functionality
author dkoroskin <>
date Tue, 08 Dec 2009 21:39:17 +0300
parents d706d958e4e8
children 69d413ef14ad
files dmd/FileName.d dmd/Module.d dmd/OutBuffer.d dmd/StringExp.d dmd/SwitchErrorStatement.d dmd/SwitchStatement.d dmd/backend/Util.d dmd/backend/block.d dmd/backend/iasm.d dmd/codegen/Util.d
diffstat 10 files changed, 639 insertions(+), 595 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/FileName.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/FileName.d	Tue Dec 08 21:39:17 2009 +0300
@@ -7,7 +7,7 @@
 
 import core.memory;
 
-import core.stdc.stdlib : alloca;
+import core.stdc.stdlib : malloc, alloca;
 import core.stdc.string : memcpy, strlen;
 import core.stdc.ctype : isspace;
 
@@ -412,7 +412,7 @@
 			size_t len = e.ptr - name.ptr;
 			size_t extlen = ext.length;
 
-			char* s = cast(char*)GC.malloc(len + extlen + 1);
+			char* s = cast(char*)malloc(len + extlen + 1);  /// !
 			memcpy(s, name.ptr, len);
 			memcpy(s + len, ext.ptr, extlen + 1);
 			return new FileName(assumeUnique(s[0..len+extlen]));
--- a/dmd/Module.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/Module.d	Tue Dec 08 21:39:17 2009 +0300
@@ -931,13 +931,13 @@
 
 			covb = cast(uint*)GC.calloc(((numlines + 32) / 32) * (*covb).sizeof);
 		}
-
+		
 		for (int i = 0; i < members.dim; i++)
 		{
 			Dsymbol member = cast(Dsymbol)members.data[i];
 			member.toObjFile(multiobj);
 		}
-
+		
 		if (global.params.cov)
 		{
 			/* Generate
@@ -1124,12 +1124,13 @@
 				writefunc(ma);
 			}
 		}
+		
 
 static if (true) {
 		// Always generate module info, because of templates and -cov
 		if (1 || needModuleInfo())
 			genmoduleinfo();
-		}
+}
 		
 		obj_termfile();
 	}
--- a/dmd/OutBuffer.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/OutBuffer.d	Tue Dec 08 21:39:17 2009 +0300
@@ -7,6 +7,7 @@
 import core.stdc.string;
 
 import core.memory;
+import core.stdc.stdlib;
 
 class OutBuffer
 {
@@ -41,7 +42,7 @@
 		if (size - offset < nbytes)
 		{
 			size = (offset + nbytes) * 2;
-			data = cast(ubyte*)GC.realloc(data, size);
+			data = cast(ubyte*)realloc(data, size);
 		}
 	}
 	
@@ -266,7 +267,12 @@
 	
     string toChars()
 	{
-		return getString().idup;
+	   char[] s = getString();
+	   char* copy = cast(char*)malloc(s.length);
+	   memcpy(copy, s.ptr, s.length);
+	   return assumeUnique(copy[0..s.length]);
+
+		//return getString().idup;
 	}
 
     final string extractString()
--- a/dmd/StringExp.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/StringExp.d	Tue Dec 08 21:39:17 2009 +0300
@@ -1,57 +1,58 @@
-module dmd.StringExp;
-
-import dmd.Expression;
-import dmd.backend.elem;
-import dmd.InterState;
-import dmd.TypeSArray;
-import dmd.CastExp;
-import dmd.MATCH;
-import dmd.TY;
-import dmd.TypeDArray;
-import dmd.Type;
-import dmd.TOK;
-import dmd.OutBuffer;
-import dmd.Loc;
-import dmd.Scope;
-import dmd.IRState;
-import dmd.StringExp;
-import dmd.HdrGenState;
-import dmd.Utf;
-import dmd.backend.dt_t;
-import dmd.backend.Symbol;
-import dmd.backend.StringTab;
-import dmd.backend.Util;
-import dmd.backend.SC;
-import dmd.backend.TYM;
-import dmd.backend.FL;
-import dmd.backend.TYPE;
-import dmd.backend.OPER;
-
-import core.memory;
-
-import core.stdc.string;
-
+module dmd.StringExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.TypeSArray;
+import dmd.CastExp;
+import dmd.MATCH;
+import dmd.TY;
+import dmd.TypeDArray;
+import dmd.Type;
+import dmd.TOK;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.StringExp;
+import dmd.HdrGenState;
+import dmd.Utf;
+import dmd.backend.dt_t;
+import dmd.backend.Symbol;
+import dmd.backend.StringTab;
+import dmd.backend.Util;
+import dmd.backend.SC;
+import dmd.backend.TYM;
+import dmd.backend.FL;
+import dmd.backend.TYPE;
+import dmd.backend.OPER;
+
+import core.memory;
+
+import core.stdc.string;
+import core.stdc.stdlib;
+
 class StringExp : Expression
 {
-	void* string_;	// char, wchar, or dchar data
-    size_t len;		// number of chars, wchars, or dchars
-    ubyte sz;	// 1: char, 2: wchar, 4: dchar
-    ubyte committed;	// !=0 if type is committed
+	void* string_;	// char, wchar, or dchar data
+    size_t len;		// number of chars, wchars, or dchars
+    ubyte sz;	// 1: char, 2: wchar, 4: dchar
+    ubyte committed;	// !=0 if type is committed
     ubyte postfix;	// 'c', 'w', 'd'
 
 	this(Loc loc, string s)
-	{
+	{
 		this(loc, s, 0);
 	}
 
 	this(Loc loc, string s, ubyte postfix)
 	{
-		super(loc, TOK.TOKstring, StringExp.sizeof);
-		
-		this.string_ = cast(void*)s.ptr;
-		this.len = s.length;
-		this.sz = 1;
-		this.committed = 0;
+		super(loc, TOK.TOKstring, StringExp.sizeof);
+		
+		this.string_ = cast(void*)s.ptr;
+		this.len = s.length;
+		this.sz = 1;
+		this.committed = 0;
 		this.postfix = postfix;
 	}
 
@@ -67,80 +68,80 @@
 
 	Expression semantic(Scope sc)
 	{
-version (LOGSEMANTIC) {
-		printf("StringExp.semantic() %s\n", toChars());
-}
-		if (!type)
-		{	
-			scope OutBuffer buffer = new OutBuffer();
-			size_t newlen = 0;
-			string p;
-			size_t u;
-			dchar c;
-
-			switch (postfix)
-			{
-				case 'd':
-					for (u = 0; u < len;)
-					{
-						p = utf_decodeChar(cast(string)string_[0..len], &u, &c);
-						if (p !is null)
-						{	
-							error("%s", p);
-							break;
-						}
-						else
-						{	
-							buffer.write4(c);
-							newlen++;
-						}
-					}
-					buffer.write4(0);
-					string_ = buffer.extractData();
-					len = newlen;
-					sz = 4;
-					//type = new TypeSArray(Type.tdchar, new IntegerExp(loc, len, Type.tindex));
-					type = new TypeDArray(Type.tdchar.invariantOf());
-					committed = 1;
-					break;
-
-				case 'w':
-					for (u = 0; u < len;)
-					{
-						p = utf_decodeChar(cast(string)string_[0..len], &u, &c);
-						if (p !is null)
-						{	
-							error("%s", p);
-							break;
-						}
-						else
-						{	
-							buffer.writeUTF16(c);
-							newlen++;
-							if (c >= 0x10000)
-								newlen++;
-						}
-					}
-					buffer.writeUTF16(0);
-					string_ = buffer.extractData();
-					len = newlen;
-					sz = 2;
-					//type = new TypeSArray(Type.twchar, new IntegerExp(loc, len, Type.tindex));
-					type = new TypeDArray(Type.twchar.invariantOf());
-					committed = 1;
-					break;
-
-				case 'c':
-					committed = 1;
-				default:
-					//type = new TypeSArray(Type.tchar, new IntegerExp(loc, len, Type.tindex));
-					type = new TypeDArray(Type.tchar.invariantOf());
-					break;
-			}
-			type = type.semantic(loc, sc);
-			//type = type.invariantOf();
-			//printf("type = %s\n", type.toChars());
-		}
+version (LOGSEMANTIC) {
+		printf("StringExp.semantic() %s\n", toChars());
+}
+		if (!type)
+		{	
+			scope OutBuffer buffer = new OutBuffer();
+			size_t newlen = 0;
+			string p;
+			size_t u;
+			dchar c;
+
+			switch (postfix)
+			{
+				case 'd':
+					for (u = 0; u < len;)
+					{
+						p = utf_decodeChar(cast(string)string_[0..len], &u, &c);
+						if (p !is null)
+						{	
+							error("%s", p);
+							break;
+						}
+						else
+						{	
+							buffer.write4(c);
+							newlen++;
+						}
+					}
+					buffer.write4(0);
+					string_ = buffer.extractData();
+					len = newlen;
+					sz = 4;
+					//type = new TypeSArray(Type.tdchar, new IntegerExp(loc, len, Type.tindex));
+					type = new TypeDArray(Type.tdchar.invariantOf());
+					committed = 1;
+					break;
+
+				case 'w':
+					for (u = 0; u < len;)
+					{
+						p = utf_decodeChar(cast(string)string_[0..len], &u, &c);
+						if (p !is null)
+						{	
+							error("%s", p);
+							break;
+						}
+						else
+						{	
+							buffer.writeUTF16(c);
+							newlen++;
+							if (c >= 0x10000)
+								newlen++;
+						}
+					}
+					buffer.writeUTF16(0);
+					string_ = buffer.extractData();
+					len = newlen;
+					sz = 2;
+					//type = new TypeSArray(Type.twchar, new IntegerExp(loc, len, Type.tindex));
+					type = new TypeDArray(Type.twchar.invariantOf());
+					committed = 1;
+					break;
+
+				case 'c':
+					committed = 1;
+				default:
+					//type = new TypeSArray(Type.tchar, new IntegerExp(loc, len, Type.tindex));
+					type = new TypeDArray(Type.tchar.invariantOf());
+					break;
+			}
+			type = type.semantic(loc, sc);
+			//type = type.invariantOf();
+			//printf("type = %s\n", type.toChars());
+		}
 		return this;
 	}
 
@@ -161,335 +162,335 @@
 
 	Expression implicitCastTo(Scope sc, Type t)
 	{
-		//printf("StringExp.implicitCastTo(%s of type %s) => %s\n", toChars(), type.toChars(), t.toChars());
-		ubyte committed = this.committed;
-		Expression e = Expression.implicitCastTo(sc, t);
-		if (e.op == TOK.TOKstring)
-		{
-			// Retain polysemous nature if it started out that way
-			(cast(StringExp)e).committed = committed;
-		}
+		//printf("StringExp.implicitCastTo(%s of type %s) => %s\n", toChars(), type.toChars(), t.toChars());
+		ubyte committed = this.committed;
+		Expression e = Expression.implicitCastTo(sc, t);
+		if (e.op == TOK.TOKstring)
+		{
+			// Retain polysemous nature if it started out that way
+			(cast(StringExp)e).committed = committed;
+		}
 		return e;
 	}
 
 	MATCH implicitConvTo(Type t)
 	{
-		MATCH m;
-
-static if (false) {
-		printf("StringExp.implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n",
-			toChars(), committed, type.toChars(), t.toChars());
-}
-		if (!committed)
-		{
-			if (!committed && t.ty == TY.Tpointer && t.nextOf().ty == TY.Tvoid)
-			{
-				return MATCH.MATCHnomatch;
-			}
-			if (type.ty == TY.Tsarray || type.ty == TY.Tarray || type.ty == TY.Tpointer)
-			{
-				TY tyn = type.nextOf().ty;
-				if (tyn == TY.Tchar || tyn == TY.Twchar || tyn == TY.Tdchar)
-				{   
-					Type tn;
-					MATCH mm;
-
-					switch (t.ty)
-					{
-						case TY.Tsarray:
-							if (type.ty == TY.Tsarray)
-							{
-								if ((cast(TypeSArray)type).dim.toInteger() !=
-									(cast(TypeSArray)t).dim.toInteger())
-									return MATCH.MATCHnomatch;
-								TY tynto = t.nextOf().ty;
-								if (tynto == TY.Tchar || tynto == TY.Twchar || tynto == TY.Tdchar)
-									return MATCH.MATCHexact;
-							}
-							else if (type.ty == TY.Tarray)
-							{
-								if (length() > (cast(TypeSArray)t).dim.toInteger())
-									return MATCH.MATCHnomatch;
-								TY tynto = t.nextOf().ty;
-								if (tynto == TY.Tchar || tynto == TY.Twchar || tynto == TY.Tdchar)
-									return MATCH.MATCHexact;
-							}
-						case TY.Tarray:
-						case TY.Tpointer:
-							tn = t.nextOf();
-							mm = MATCH.MATCHexact;
-							if (type.nextOf().mod != tn.mod)
-							{	
-								if (!tn.isConst())
-									return MATCH.MATCHnomatch;
-								mm = MATCH.MATCHconst;
-							}
-							switch (tn.ty)
-							{
-								case TY.Tchar:
-								case TY.Twchar:
-								case TY.Tdchar:
-									return mm;
-							}
-							break;
-						default:
-							break;	///
-					}
-				}
-			}
-		}
-		return Expression.implicitConvTo(t);
-static if (false) {
-		m = cast(MATCH)type.implicitConvTo(t);
-		if (m)
-		{
-			return m;
-		}
-
-		return MATCH.MATCHnomatch;
+		MATCH m;
+
+static if (false) {
+		printf("StringExp.implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n",
+			toChars(), committed, type.toChars(), t.toChars());
 }
-	}
-	
-	static uint X(TY tf, TY tt) {
-		return ((tf) * 256 + (tt));
+		if (!committed)
+		{
+			if (!committed && t.ty == TY.Tpointer && t.nextOf().ty == TY.Tvoid)
+			{
+				return MATCH.MATCHnomatch;
+			}
+			if (type.ty == TY.Tsarray || type.ty == TY.Tarray || type.ty == TY.Tpointer)
+			{
+				TY tyn = type.nextOf().ty;
+				if (tyn == TY.Tchar || tyn == TY.Twchar || tyn == TY.Tdchar)
+				{   
+					Type tn;
+					MATCH mm;
+
+					switch (t.ty)
+					{
+						case TY.Tsarray:
+							if (type.ty == TY.Tsarray)
+							{
+								if ((cast(TypeSArray)type).dim.toInteger() !=
+									(cast(TypeSArray)t).dim.toInteger())
+									return MATCH.MATCHnomatch;
+								TY tynto = t.nextOf().ty;
+								if (tynto == TY.Tchar || tynto == TY.Twchar || tynto == TY.Tdchar)
+									return MATCH.MATCHexact;
+							}
+							else if (type.ty == TY.Tarray)
+							{
+								if (length() > (cast(TypeSArray)t).dim.toInteger())
+									return MATCH.MATCHnomatch;
+								TY tynto = t.nextOf().ty;
+								if (tynto == TY.Tchar || tynto == TY.Twchar || tynto == TY.Tdchar)
+									return MATCH.MATCHexact;
+							}
+						case TY.Tarray:
+						case TY.Tpointer:
+							tn = t.nextOf();
+							mm = MATCH.MATCHexact;
+							if (type.nextOf().mod != tn.mod)
+							{	
+								if (!tn.isConst())
+									return MATCH.MATCHnomatch;
+								mm = MATCH.MATCHconst;
+							}
+							switch (tn.ty)
+							{
+								case TY.Tchar:
+								case TY.Twchar:
+								case TY.Tdchar:
+									return mm;
+							}
+							break;
+						default:
+							break;	///
+					}
+				}
+			}
+		}
+		return Expression.implicitConvTo(t);
+static if (false) {
+		m = cast(MATCH)type.implicitConvTo(t);
+		if (m)
+		{
+			return m;
+		}
+
+		return MATCH.MATCHnomatch;
+}
+	}
+	
+	static uint X(TY tf, TY tt) {
+		return ((tf) * 256 + (tt));
 	}
 
 	Expression castTo(Scope sc, Type t)
-	{
-		/* This follows copy-on-write; any changes to 'this'
-		 * will result in a copy.
-		 * The this.string member is considered immutable.
-		 */
-		StringExp se;
-		Type tb;
-		int copied = 0;
-
-		//printf("StringExp.castTo(t = %s), '%s' committed = %d\n", t.toChars(), toChars(), committed);
-
-		if (!committed && t.ty == TY.Tpointer && t.nextOf().ty == TY.Tvoid)
-		{
-			error("cannot convert string literal to void*");
-		}
-
-		se = this;
-		if (!committed)
-		{   
-			se = cast(StringExp)copy();
-			se.committed = 1;
-			copied = 1;
-		}
-
-		if (type == t)
-		{
-			return se;
-		}
-
-		tb = t.toBasetype();
-		//printf("\ttype = %s\n", type.toChars());
-		if (tb.ty == TY.Tdelegate && type.toBasetype().ty != TY.Tdelegate)
-			return Expression.castTo(sc, t);
-
-		Type typeb = type.toBasetype();
-		if (typeb == tb)
-		{
-			if (!copied)
-			{   
-				se = cast(StringExp)copy();
-				copied = 1;
-			}
-			se.type = t;
-			return se;
-		}
-
-		if (committed && tb.ty == TY.Tsarray && typeb.ty == TY.Tarray)
-		{
-			se = cast(StringExp)copy();
-			se.sz = cast(ubyte)tb.nextOf().size();
-			se.len = (len * sz) / se.sz;
-			se.committed = 1;
-			se.type = t;
-			return se;
-		}
-
-		if (tb.ty != TY.Tsarray && tb.ty != TY.Tarray && tb.ty != TY.Tpointer)
-		{
-			if (!copied)
-			{   
-				se = cast(StringExp)copy();
-				copied = 1;
-			}
-			goto Lcast;
-		}
-		if (typeb.ty != TY.Tsarray && typeb.ty != TY.Tarray && typeb.ty != TY.Tpointer)
-		{	
-			if (!copied)
-			{   
-				se = cast(StringExp)copy();
-				copied = 1;
-			}
-			goto Lcast;
-		}
-
-		if (typeb.nextOf().size() == tb.nextOf().size())
-		{
-			if (!copied)
-			{
-				se = cast(StringExp)copy();
-				copied = 1;
-			}
-			
-			if (tb.ty == TY.Tsarray)
-				goto L2;	// handle possible change in static array dimension
-			se.type = t;
-			return se;
-		}
-
-		if (committed)
-			goto Lcast;
-
-		{
-			scope OutBuffer buffer = new OutBuffer();
-			size_t newlen = 0;
-			TY tfty = typeb.nextOf().toBasetype().ty;
-			TY ttty = tb.nextOf().toBasetype().ty;
-			switch (X(tfty, ttty))
-			{
-				case X(TY.Tchar, TY.Tchar):
-				case X(TY.Twchar,TY.Twchar):
-				case X(TY.Tdchar,TY.Tdchar):
-					break;
-
-				case X(TY.Tchar, TY.Twchar):
-					for (size_t u = 0; u < len;)
-					{	
-						dchar c;
-						string p = utf_decodeChar(cast(string)se.string_[0..len], &u, &c);
-						if (p !is null)
-							error("%s", p);
-						else
-							buffer.writeUTF16(c);
-					}
-					newlen = buffer.offset / 2;
-					buffer.writeUTF16(0);
-					goto L1;
-
-				case X(TY.Tchar, TY.Tdchar):
-					for (size_t u = 0; u < len;)
-					{	
-						dchar c;
-						string p = utf_decodeChar(cast(string)se.string_[0..len], &u, &c);
-						if (p !is null)
-							error("%s", p);
-						buffer.write4(c);
-						newlen++;
-					}
-					buffer.write4(0);
-					goto L1;
-
-				case X(TY.Twchar,TY.Tchar):
-					for (size_t u = 0; u < len;)
-					{	
-						dchar c;
-						string p = utf_decodeWchar(cast(wstring)se.string_[0..len], &u, &c);
-						if (p)
-							error("%s", p);
-						else
-							buffer.writeUTF8(c);
-					}
-					newlen = buffer.offset;
-					buffer.writeUTF8(0);
-					goto L1;
-
-				case X(TY.Twchar,TY.Tdchar):
-					for (size_t u = 0; u < len;)
-					{	
-						dchar c;
-						string p = utf_decodeWchar(cast(wstring)se.string_[0..len], &u, &c);
-						if (p)
-							error("%s", p);
-						buffer.write4(c);
-						newlen++;
-					}
-					buffer.write4(0);
-					goto L1;
-
-				case X(TY.Tdchar,TY.Tchar):
-					for (size_t u = 0; u < len; u++)
-					{
-						dchar c = (cast(dchar*)se.string_)[u];
-						if (!utf_isValidDchar(c))
-							error("invalid UCS-32 char \\U%08x", c);
-						else
-							buffer.writeUTF8(c);
-						newlen++;
-					}
-					newlen = buffer.offset;
-					buffer.writeUTF8(0);
-					goto L1;
-
-				case X(TY.Tdchar,TY.Twchar):
-					for (size_t u = 0; u < len; u++)
-					{
-						dchar c = (cast(dchar*)se.string_)[u];
-						if (!utf_isValidDchar(c))
-							error("invalid UCS-32 char \\U%08x", c);
-						else
-							buffer.writeUTF16(c);
-						newlen++;
-					}
-					newlen = buffer.offset / 2;
-					buffer.writeUTF16(0);
-					goto L1;
-
-				L1:
-					if (!copied)
-					{   
-						se = cast(StringExp)copy();
-						copied = 1;
-					}
-					se.string_ = buffer.extractData();
-					se.len = newlen;
-					se.sz = cast(ubyte)tb.nextOf().size();
-					break;
-
-				default:
-					assert(typeb.nextOf().size() != tb.nextOf().size());
-					goto Lcast;
-			}
-		}
-	L2:
-		assert(copied);
-
-		// See if need to truncate or extend the literal
-		if (tb.ty == TY.Tsarray)
-		{
-			int dim2 = cast(int)(cast(TypeSArray)tb).dim.toInteger();
-
-			//printf("dim from = %d, to = %d\n", se.len, dim2);
-
-			// Changing dimensions
-			if (dim2 != se.len)
-			{
-				// Copy when changing the string literal
-				uint newsz = se.sz;
-				void *s;
-				int d;
-
-				d = (dim2 < se.len) ? dim2 : se.len;
-				s = cast(ubyte*)GC.malloc((dim2 + 1) * newsz);
-				memcpy(s, se.string_, d * newsz);
-				// Extend with 0, add terminating 0
-				memset(cast(char*)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
-				se.string_ = s;
-				se.len = dim2;
-			}
-		}
-		se.type = t;
-		return se;
-
-	Lcast:
-		Expression e = new CastExp(loc, se, t);
-		e.type = t;	// so semantic() won't be run on e
+	{
+		/* This follows copy-on-write; any changes to 'this'
+		 * will result in a copy.
+		 * The this.string member is considered immutable.
+		 */
+		StringExp se;
+		Type tb;
+		int copied = 0;
+
+		//printf("StringExp.castTo(t = %s), '%s' committed = %d\n", t.toChars(), toChars(), committed);
+
+		if (!committed && t.ty == TY.Tpointer && t.nextOf().ty == TY.Tvoid)
+		{
+			error("cannot convert string literal to void*");
+		}
+
+		se = this;
+		if (!committed)
+		{   
+			se = cast(StringExp)copy();
+			se.committed = 1;
+			copied = 1;
+		}
+
+		if (type == t)
+		{
+			return se;
+		}
+
+		tb = t.toBasetype();
+		//printf("\ttype = %s\n", type.toChars());
+		if (tb.ty == TY.Tdelegate && type.toBasetype().ty != TY.Tdelegate)
+			return Expression.castTo(sc, t);
+
+		Type typeb = type.toBasetype();
+		if (typeb == tb)
+		{
+			if (!copied)
+			{   
+				se = cast(StringExp)copy();
+				copied = 1;
+			}
+			se.type = t;
+			return se;
+		}
+
+		if (committed && tb.ty == TY.Tsarray && typeb.ty == TY.Tarray)
+		{
+			se = cast(StringExp)copy();
+			se.sz = cast(ubyte)tb.nextOf().size();
+			se.len = (len * sz) / se.sz;
+			se.committed = 1;
+			se.type = t;
+			return se;
+		}
+
+		if (tb.ty != TY.Tsarray && tb.ty != TY.Tarray && tb.ty != TY.Tpointer)
+		{
+			if (!copied)
+			{   
+				se = cast(StringExp)copy();
+				copied = 1;
+			}
+			goto Lcast;
+		}
+		if (typeb.ty != TY.Tsarray && typeb.ty != TY.Tarray && typeb.ty != TY.Tpointer)
+		{	
+			if (!copied)
+			{   
+				se = cast(StringExp)copy();
+				copied = 1;
+			}
+			goto Lcast;
+		}
+
+		if (typeb.nextOf().size() == tb.nextOf().size())
+		{
+			if (!copied)
+			{
+				se = cast(StringExp)copy();
+				copied = 1;
+			}
+			
+			if (tb.ty == TY.Tsarray)
+				goto L2;	// handle possible change in static array dimension
+			se.type = t;
+			return se;
+		}
+
+		if (committed)
+			goto Lcast;
+
+		{
+			scope OutBuffer buffer = new OutBuffer();
+			size_t newlen = 0;
+			TY tfty = typeb.nextOf().toBasetype().ty;
+			TY ttty = tb.nextOf().toBasetype().ty;
+			switch (X(tfty, ttty))
+			{
+				case X(TY.Tchar, TY.Tchar):
+				case X(TY.Twchar,TY.Twchar):
+				case X(TY.Tdchar,TY.Tdchar):
+					break;
+
+				case X(TY.Tchar, TY.Twchar):
+					for (size_t u = 0; u < len;)
+					{	
+						dchar c;
+						string p = utf_decodeChar(cast(string)se.string_[0..len], &u, &c);
+						if (p !is null)
+							error("%s", p);
+						else
+							buffer.writeUTF16(c);
+					}
+					newlen = buffer.offset / 2;
+					buffer.writeUTF16(0);
+					goto L1;
+
+				case X(TY.Tchar, TY.Tdchar):
+					for (size_t u = 0; u < len;)
+					{	
+						dchar c;
+						string p = utf_decodeChar(cast(string)se.string_[0..len], &u, &c);
+						if (p !is null)
+							error("%s", p);
+						buffer.write4(c);
+						newlen++;
+					}
+					buffer.write4(0);
+					goto L1;
+
+				case X(TY.Twchar,TY.Tchar):
+					for (size_t u = 0; u < len;)
+					{	
+						dchar c;
+						string p = utf_decodeWchar(cast(wstring)se.string_[0..len], &u, &c);
+						if (p)
+							error("%s", p);
+						else
+							buffer.writeUTF8(c);
+					}
+					newlen = buffer.offset;
+					buffer.writeUTF8(0);
+					goto L1;
+
+				case X(TY.Twchar,TY.Tdchar):
+					for (size_t u = 0; u < len;)
+					{	
+						dchar c;
+						string p = utf_decodeWchar(cast(wstring)se.string_[0..len], &u, &c);
+						if (p)
+							error("%s", p);
+						buffer.write4(c);
+						newlen++;
+					}
+					buffer.write4(0);
+					goto L1;
+
+				case X(TY.Tdchar,TY.Tchar):
+					for (size_t u = 0; u < len; u++)
+					{
+						dchar c = (cast(dchar*)se.string_)[u];
+						if (!utf_isValidDchar(c))
+							error("invalid UCS-32 char \\U%08x", c);
+						else
+							buffer.writeUTF8(c);
+						newlen++;
+					}
+					newlen = buffer.offset;
+					buffer.writeUTF8(0);
+					goto L1;
+
+				case X(TY.Tdchar,TY.Twchar):
+					for (size_t u = 0; u < len; u++)
+					{
+						dchar c = (cast(dchar*)se.string_)[u];
+						if (!utf_isValidDchar(c))
+							error("invalid UCS-32 char \\U%08x", c);
+						else
+							buffer.writeUTF16(c);
+						newlen++;
+					}
+					newlen = buffer.offset / 2;
+					buffer.writeUTF16(0);
+					goto L1;
+
+				L1:
+					if (!copied)
+					{   
+						se = cast(StringExp)copy();
+						copied = 1;
+					}
+					se.string_ = buffer.extractData();
+					se.len = newlen;
+					se.sz = cast(ubyte)tb.nextOf().size();
+					break;
+
+				default:
+					assert(typeb.nextOf().size() != tb.nextOf().size());
+					goto Lcast;
+			}
+		}
+	L2:
+		assert(copied);
+
+		// See if need to truncate or extend the literal
+		if (tb.ty == TY.Tsarray)
+		{
+			int dim2 = cast(int)(cast(TypeSArray)tb).dim.toInteger();
+
+			//printf("dim from = %d, to = %d\n", se.len, dim2);
+
+			// Changing dimensions
+			if (dim2 != se.len)
+			{
+				// Copy when changing the string literal
+				uint newsz = se.sz;
+				void *s;
+				int d;
+
+				d = (dim2 < se.len) ? dim2 : se.len;
+				s = cast(ubyte*)GC.malloc((dim2 + 1) * newsz);
+				memcpy(s, se.string_, d * newsz);
+				// Extend with 0, add terminating 0
+				memset(cast(char*)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
+				se.string_ = s;
+				se.len = dim2;
+			}
+		}
+		se.type = t;
+		return se;
+
+	Lcast:
+		Expression e = new CastExp(loc, se, t);
+		e.type = t;	// so semantic() won't be run on e
 		return e;
 	}
 
@@ -520,151 +521,151 @@
 
 	elem* toElem(IRState* irs)
 	{
-		elem* e;
-		Type tb = type.toBasetype();
-
-static if (false) {
-		printf("StringExp.toElem() %s, type = %s\n", toChars(), type.toChars());
-}
-
-		if (tb.ty == TY.Tarray)
-		{
-			Symbol* si;
-			dt_t* dt;
-			StringTab* st;
-
-static if (false) {
-			printf("irs.m = %p\n", irs.m);
-			printf(" m   = %s\n", irs.m.toChars());
-			printf(" len = %d\n", len);
-			printf(" sz  = %d\n", sz);
-}
-			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 is 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(SC.SCstatic, type_fake(TYM.TYdarray));
-			si.Sdt = dt;
-			si.Sfl = FL.FLdata;
-version (ELFOBJ) {// Burton
-			si.Sseg = Segment.CDATA;
-}
-version (MACHOBJ) {
-			si.Sseg = Segment.DATA;
-}
-			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 == TY.Tsarray)
-		{
-			Symbol *si;
-			dt_t *dt = null;
-
-			toDt(&dt);
-			dtnzeros(&dt, sz);		// leave terminating 0
-
-			si = symbol_generate(SC.SCstatic,type_allocn(TYM.TYarray, tschar));
-			si.Sdt = dt;
-			si.Sfl = FL.FLdata;
-
-version (ELFOBJ_OR_MACHOBJ) { // Burton
-			si.Sseg = Segment.CDATA;
-		}
-			outdata(si);
-
-			e = el_var(si);
-		}
-		else if (tb.ty == TY.Tpointer)
-		{
-			e = el_calloc();
-			e.Eoper = OPER.OPstring;
-static if (true) {
-			// Match MEM_PH_FREE for OPstring in ztc\el.c
-			e.EV.ss.Vstring = cast(char*)GC.malloc((len + 1) * sz);
-			memcpy(e.EV.ss.Vstring, string_, (len + 1) * sz);
-} else {
-			e.EV.ss.Vstring = cast(char*)string_;
-}
-			e.EV.ss.Vstrlen = (len + 1) * sz;
-			e.Ety = TYM.TYnptr;
-		}
-		else
-		{
-			writef("type is %s\n", type.toChars());
-			assert(0);
-		}
-		el_setLoc(e,loc);
+		elem* e;
+		Type tb = type.toBasetype();
+
+static if (false) {
+		printf("StringExp.toElem() %s, type = %s\n", toChars(), type.toChars());
+}
+
+		if (tb.ty == TY.Tarray)
+		{
+			Symbol* si;
+			dt_t* dt;
+			StringTab* st;
+
+static if (false) {
+			printf("irs.m = %p\n", irs.m);
+			printf(" m   = %s\n", irs.m.toChars());
+			printf(" len = %d\n", len);
+			printf(" sz  = %d\n", sz);
+}
+			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 is 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(SC.SCstatic, type_fake(TYM.TYdarray));
+			si.Sdt = dt;
+			si.Sfl = FL.FLdata;
+version (ELFOBJ) {// Burton
+			si.Sseg = Segment.CDATA;
+}
+version (MACHOBJ) {
+			si.Sseg = Segment.DATA;
+}
+			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 == TY.Tsarray)
+		{
+			Symbol *si;
+			dt_t *dt = null;
+
+			toDt(&dt);
+			dtnzeros(&dt, sz);		// leave terminating 0
+
+			si = symbol_generate(SC.SCstatic,type_allocn(TYM.TYarray, tschar));
+			si.Sdt = dt;
+			si.Sfl = FL.FLdata;
+
+version (ELFOBJ_OR_MACHOBJ) { // Burton
+			si.Sseg = Segment.CDATA;
+		}
+			outdata(si);
+
+			e = el_var(si);
+		}
+		else if (tb.ty == TY.Tpointer)
+		{
+			e = el_calloc();
+			e.Eoper = OPER.OPstring;
+static if (true) {
+			// Match MEM_PH_FREE for OPstring in ztc\el.c
+			e.EV.ss.Vstring = cast(char*)malloc((len + 1) * sz); /// !
+			memcpy(e.EV.ss.Vstring, string_, (len + 1) * sz);
+} else {
+			e.EV.ss.Vstring = cast(char*)string_;
+}
+			e.EV.ss.Vstrlen = (len + 1) * sz;
+			e.Ety = TYM.TYnptr;
+		}
+		else
+		{
+			writef("type is %s\n", type.toChars());
+			assert(0);
+		}
+		el_setLoc(e,loc);
 		return e;
 	}
 
 	dt_t** toDt(dt_t** pdt)
 	{
-		//printf("StringExp.toDt() '%s', type = %s\n", toChars(), type.toChars());
-		Type t = type.toBasetype();
-
-		// BUG: should implement some form of static string pooling
-		switch (t.ty)
-		{
-			case TY.Tarray:
-				dtdword(pdt, len);
-				pdt = dtabytes(pdt, TYM.TYnptr, 0, (len + 1) * sz, cast(char*)string_);
-				break;
-
-			case TY.Tsarray:
-			{   
-				TypeSArray tsa = cast(TypeSArray)type;
-				long dim;
-
-				pdt = dtnbytes(pdt, len * sz, cast(const(char)*)string_);
-				if (tsa.dim)
-				{
-					dim = tsa.dim.toInteger();
-					if (len < dim)
-					{
-						// Pad remainder with 0
-						pdt = dtnzeros(pdt, cast(uint)((dim - len) * tsa.next.size()));
-					}
-				}
-				break;
-			}
-
-			case TY.Tpointer:
-				pdt = dtabytes(pdt, TYM.TYnptr, 0, (len + 1) * sz, cast(char*)string_);
-				break;
-
-			default:
-				writef("StringExp.toDt(type = %s)\n", type.toChars());
-				assert(0);
-		}
-
+		//printf("StringExp.toDt() '%s', type = %s\n", toChars(), type.toChars());
+		Type t = type.toBasetype();
+
+		// BUG: should implement some form of static string pooling
+		switch (t.ty)
+		{
+			case TY.Tarray:
+				dtdword(pdt, len);
+				pdt = dtabytes(pdt, TYM.TYnptr, 0, (len + 1) * sz, cast(char*)string_);
+				break;
+
+			case TY.Tsarray:
+			{   
+				TypeSArray tsa = cast(TypeSArray)type;
+				long dim;
+
+				pdt = dtnbytes(pdt, len * sz, cast(const(char)*)string_);
+				if (tsa.dim)
+				{
+					dim = tsa.dim.toInteger();
+					if (len < dim)
+					{
+						// Pad remainder with 0
+						pdt = dtnzeros(pdt, cast(uint)((dim - len) * tsa.next.size()));
+					}
+				}
+				break;
+			}
+
+			case TY.Tpointer:
+				pdt = dtabytes(pdt, TYM.TYnptr, 0, (len + 1) * sz, cast(char*)string_);
+				break;
+
+			default:
+				writef("StringExp.toDt(type = %s)\n", type.toChars());
+				assert(0);
+		}
+
 		return pdt;
 	}
 }
--- a/dmd/SwitchErrorStatement.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/SwitchErrorStatement.d	Tue Dec 08 21:39:17 2009 +0300
@@ -5,29 +5,46 @@
 import dmd.Loc;
 import dmd.IRState;
 import dmd.HdrGenState;
-import dmd.BE;
+import dmd.BE;
+
+import dmd.backend.elem;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+import dmd.backend.RTLSYM;
 
 class SwitchErrorStatement : Statement
 {
 	this(Loc loc)
 	{
-		assert(false);
 		super(loc);
 	}
 
 	BE blockExit()
 	{
-		assert(false);
+		return BE.BEthrow;
 	}
 
 	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
 	{
-		assert(false);
+		buf.writestring("SwitchErrorStatement.toCBuffer()");
+		buf.writenl();
 	}
 
 	void toIR(IRState* irs)
 	{
-		assert(false);
+		elem* e;
+		elem* elinnum;
+		elem* efilename;
+		Blockx* blx = irs.blx;
+
+		//printf("SwitchErrorStatement.toIR()\n");
+
+		efilename = blx.module_.toEmodulename();
+		elinnum = el_long(TYM.TYint, loc.linnum);
+		e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM_DSWITCHERR]), el_param(elinnum, efilename));
+		block_appendexp(blx.curblock, e);
 	}
 }
 
--- a/dmd/SwitchStatement.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/SwitchStatement.d	Tue Dec 08 21:39:17 2009 +0300
@@ -49,6 +49,8 @@
 
 import core.memory;
 
+import core.stdc.stdlib;
+
 class SwitchStatement : Statement
 {
     Expression condition;
@@ -408,7 +410,8 @@
 		block_appendexp(mystate.switchBlock, econd);
 		block_next(blx,BCswitch,null);
 
-		targ_llong* pu = cast(targ_llong*) GC.malloc(targ_llong.sizeof * (numcases + 1));
+		/// 
+		targ_llong* pu = cast(targ_llong*) malloc(targ_llong.sizeof * (numcases + 1));
 		mystate.switchBlock.Bswitch = pu;
 		/* First pair is the number of cases, and the default block
 		 */
--- a/dmd/backend/Util.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/backend/Util.d	Tue Dec 08 21:39:17 2009 +0300
@@ -19,6 +19,8 @@
 import dmd.backend.code;
 
 import std.string;
+import core.stdc.stdlib;
+import core.stdc.string;
 
 alias ubyte mangle_t;
 
@@ -51,7 +53,10 @@
 alias elem* elem_p;		// data type big enough for type masks
 
 void el_setLoc(elem* e, Loc loc) {
-	e.Esrcpos.Sfilename = cast(char*)toStringz(loc.filename);
+   size_t len = loc.filename.length;
+   e.Esrcpos.Sfilename = cast(char*)malloc(len + 1);
+   memcpy(e.Esrcpos.Sfilename, loc.filename.ptr, len);
+   e.Esrcpos.Sfilename[len] = 0;
 	e.Esrcpos.Slinnum = loc.linnum;
 }
 
--- a/dmd/backend/block.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/backend/block.d	Tue Dec 08 21:39:17 2009 +0300
@@ -150,4 +150,13 @@
 ///	BFLlooprt = 0x40,	// set if looprotate() changes it's Bnext
 ///}
 	BFLvolatile = 0x4000,	// block is volatile
+}
+
+void dump_block(block* foo)
+{
+	foreach (a, b; foo.tupleof)
+	{
+		std.stdio.writeln(foo.tupleof[a].stringof, " ", cast(char*)&foo.tupleof[a] - cast(char*)foo, " = ", foo.tupleof[a]);
+		//std.stdio.writeln("printf(\"", foo.tupleof[a].stringof, " %d = %d\\n\",(char*)(&", foo.tupleof[a].stringof, ")-(char*)foo, ", foo.tupleof[a].stringof, ");");
+	}
 }
\ No newline at end of file
--- a/dmd/backend/iasm.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/backend/iasm.d	Tue Dec 08 21:39:17 2009 +0300
@@ -45,6 +45,7 @@
 
 import core.stdc.stdio : printf;
 import core.stdc.string : strlen;
+import core.stdc.stdlib : realloc;
 import core.stdc.limits;
 
 import std.bitmanip;
@@ -1872,7 +1873,7 @@
 		if (usBytes+usSize > usMaxbytes)
 		{   
 			usMaxbytes = usBytes + usSize + 10;
-			c.IEV1.as.bytes = cast(char*)GC.realloc(c.IEV1.as.bytes,usMaxbytes);
+			c.IEV1.as.bytes = cast(char*)realloc(c.IEV1.as.bytes,usMaxbytes);
 		}
 		switch (tok_value)
 		{
@@ -1932,7 +1933,7 @@
 				if (len)
 				{
 					usMaxbytes += len * usSize;
-					c.IEV1.as.bytes =  cast(char*)GC.realloc(c.IEV1.as.bytes,usMaxbytes);
+					c.IEV1.as.bytes =  cast(char*)realloc(c.IEV1.as.bytes,usMaxbytes);
 					memcpy(c.IEV1.as.bytes + usBytes,asmtok.ustring,len);
 
 					char* p = c.IEV1.as.bytes + usBytes;
--- a/dmd/codegen/Util.d	Mon Oct 26 16:28:19 2009 +0300
+++ b/dmd/codegen/Util.d	Tue Dec 08 21:39:17 2009 +0300
@@ -54,6 +54,7 @@
 
 import std.string;
 import core.stdc.string;
+import core.stdc.stdlib;
 
 import core.memory;
 
@@ -999,7 +1000,7 @@
 					es.Eoper = OPER.OPstring;
 
 					// Match MEM_PH_FREE for OPstring in ztc\el.c
-					es.EV.ss.Vstring = cast(char*)GC.malloc(len);	///
+					es.EV.ss.Vstring = cast(char*)malloc(len);	/// !
 					memcpy(es.EV.ss.Vstring, &e.EV, len);
 
 					es.EV.ss.Vstrlen = len;