changeset 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 5a2059196104
files bridge/bridge.cpp build.bat commands.txt dbg/Debug.d dbg/image/PE.d dbg/symbol/CodeView.d dbg/ui/CrashWindow.d ddmd.def ddmd.dice dlib/CrashHandler.d dmd/AddAssignExp.d dmd/AddExp.d dmd/AddrExp.d dmd/AggregateDeclaration.d dmd/AliasDeclaration.d dmd/AliasThis.d dmd/AlignDeclaration.d dmd/AndAndExp.d dmd/AndAssignExp.d dmd/AndExp.d dmd/AnonDeclaration.d dmd/AnonymousAggregateDeclaration.d dmd/Argument.d dmd/Array.d dmd/ArrayExp.d dmd/ArrayInitializer.d dmd/ArrayLengthExp.d dmd/ArrayLiteralExp.d dmd/ArrayScopeSymbol.d dmd/ArrayT.d dmd/ArrayTypes.d dmd/AsmStatement.d dmd/AssertExp.d dmd/AssignExp.d dmd/AssocArrayLiteralExp.d dmd/AttribDeclaration.d dmd/BE.d dmd/BUILTIN.d dmd/BaseClass.d dmd/BinExp.d dmd/BoolExp.d dmd/BreakStatement.d dmd/CSX.d dmd/CallExp.d dmd/CaseRangeStatement.d dmd/CaseStatement.d dmd/Cast.d dmd/CastExp.d dmd/CatAssignExp.d dmd/CatExp.d dmd/Catch.d dmd/ClassDeclaration.d dmd/ClassInfoDeclaration.d dmd/CmpExp.d dmd/ComExp.d dmd/CommaExp.d dmd/CompileDeclaration.d dmd/CompileExp.d dmd/CompileStatement.d dmd/Complex.d dmd/ComplexExp.d dmd/CompoundDeclarationStatement.d dmd/CompoundStatement.d dmd/CondExp.d dmd/Condition.d dmd/ConditionalDeclaration.d dmd/ConditionalStatement.d dmd/ContinueStatement.d dmd/CppMangleState.d dmd/CtorDeclaration.d dmd/DVCondition.d dmd/DYNCAST.d dmd/Dchar.d dmd/DebugCondition.d dmd/DebugSymbol.d dmd/Declaration.d dmd/DeclarationExp.d dmd/DeclarationStatement.d dmd/DefaultInitExp.d dmd/DefaultStatement.d dmd/DelegateExp.d dmd/DeleteDeclaration.d dmd/DeleteExp.d dmd/DivAssignExp.d dmd/DivExp.d dmd/DoStatement.d dmd/DocComment.d dmd/DollarExp.d dmd/DotExp.d dmd/DotIdExp.d dmd/DotTemplateExp.d dmd/DotTemplateInstanceExp.d dmd/DotTypeExp.d dmd/DotVarExp.d dmd/Dsymbol.d dmd/DsymbolExp.d dmd/DsymbolTable.d dmd/DtorDeclaration.d dmd/EnumDeclaration.d dmd/EnumMember.d dmd/EnumUtils.d dmd/EqualExp.d dmd/ErrorExp.d dmd/Escape.d dmd/ExpInitializer.d dmd/ExpStatement.d dmd/Expression.d dmd/File.d dmd/FileExp.d dmd/FileInitExp.d dmd/FileName.d dmd/ForStatement.d dmd/ForeachRangeStatement.d dmd/ForeachStatement.d dmd/FuncAliasDeclaration.d dmd/FuncDeclaration.d dmd/FuncExp.d dmd/FuncLiteralDeclaration.d dmd/Global.d dmd/GlobalExpressions.d dmd/GotoCaseStatement.d dmd/GotoDefaultStatement.d dmd/GotoStatement.d dmd/HaltExp.d dmd/HdrGenState.d dmd/ILS.d dmd/IRState.d dmd/Id.d dmd/Identifier.d dmd/IdentifierExp.d dmd/IdentityExp.d dmd/IfStatement.d dmd/Import.d dmd/InExp.d dmd/IndexExp.d dmd/Initializer.d dmd/InlineCostState.d dmd/InlineDoState.d dmd/InlineScanState.d dmd/IntRange.d dmd/IntegerExp.d dmd/InterState.d dmd/InterfaceDeclaration.d dmd/InvariantDeclaration.d dmd/IsExp.d dmd/Keyword.d dmd/LINK.d dmd/LabelDsymbol.d dmd/LabelStatement.d dmd/Lexer.d dmd/Library.d dmd/Library__.d dmd/LineInitExp.d dmd/LinkDeclaration.d dmd/Loc.d dmd/Lstring.d dmd/MATCH.d dmd/MOD.d dmd/Macro.d dmd/MinAssignExp.d dmd/MinExp.d dmd/ModAssignExp.d dmd/ModExp.d dmd/Module.d dmd/ModuleDeclaration.d dmd/ModuleInfoDeclaration.d dmd/MulAssignExp.d dmd/MulExp.d dmd/NegExp.d dmd/NewAnonClassExp.d dmd/NewDeclaration.d dmd/NewExp.d dmd/NotExp.d dmd/NullExp.d dmd/ObjModule.d dmd/OnScopeStatement.d dmd/Optimize.d dmd/OrAssignExp.d dmd/OrExp.d dmd/OrOrExp.d dmd/OutBuffer.d dmd/OverExp.d dmd/OverloadSet.d dmd/PREC.d dmd/PROT.d dmd/Package.d dmd/Param.d dmd/ParseStatementFlags.d dmd/Parser.d dmd/PeelStatement.d dmd/Port.d dmd/PostBlitDeclaration.d dmd/PostExp.d dmd/PragmaDeclaration.d dmd/PragmaStatement.d dmd/ProtDeclaration.d dmd/PtrExp.d dmd/RET.d dmd/RealExp.d dmd/RemoveExp.d dmd/ReturnStatement.d dmd/STC.d dmd/Scope.d dmd/ScopeDsymbol.d dmd/ScopeExp.d dmd/ScopeStatement.d dmd/Section.d dmd/ShlAssignExp.d dmd/ShlExp.d dmd/ShrAssignExp.d dmd/ShrExp.d dmd/SliceExp.d dmd/Statement.d dmd/StaticAssert.d dmd/StaticAssertStatement.d dmd/StaticCtorDeclaration.d dmd/StaticDtorDeclaration.d dmd/StaticIfCondition.d dmd/StaticIfDeclaration.d dmd/StorageClassDeclaration.d dmd/String.d dmd/StringEntry.d dmd/StringExp.d dmd/StringTable.d dmd/StringValue.d dmd/StructDeclaration.d dmd/StructInitializer.d dmd/StructLiteralExp.d dmd/SuperExp.d dmd/SwitchErrorStatement.d dmd/SwitchStatement.d dmd/SymOffExp.d dmd/SymbolDeclaration.d dmd/SymbolExp.d dmd/SynchronizedStatement.d dmd/TFLAGS.d dmd/TOK.d dmd/TY.d dmd/TemplateAliasParameter.d dmd/TemplateDeclaration.d dmd/TemplateExp.d dmd/TemplateInstance.d dmd/TemplateMixin.d dmd/TemplateParameter.d dmd/TemplateThisParameter.d dmd/TemplateTupleParameter.d dmd/TemplateTypeParameter.d dmd/TemplateValueParameter.d dmd/ThisDeclaration.d dmd/ThisExp.d dmd/ThrowStatement.d dmd/Token.d dmd/TraitsExp.d dmd/TryCatchStatement.d dmd/TryFinallyStatement.d dmd/Tuple.d dmd/TupleDeclaration.d dmd/TupleExp.d dmd/Type.d dmd/TypeAArray.d dmd/TypeArray.d dmd/TypeBasic.d dmd/TypeClass.d dmd/TypeDArray.d dmd/TypeDelegate.d dmd/TypeEnum.d dmd/TypeExp.d dmd/TypeFunction.d dmd/TypeIdentifier.d dmd/TypeInfoArrayDeclaration.d dmd/TypeInfoClassDeclaration.d dmd/TypeInfoConstDeclaration.d dmd/TypeInfoDeclaration.d dmd/TypeInfoDelegateDeclaration.d dmd/TypeInfoEnumDeclaration.d dmd/TypeInfoInterfaceDeclaration.d dmd/TypeInfoInvariantDeclaration.d dmd/TypeInfoPointerDeclaration.d dmd/TypeInfoSharedDeclaration.d dmd/TypeInfoStructDeclaration.d dmd/TypeInfoTypedefDeclaration.d dmd/TypeInstance.d dmd/TypeNext.d dmd/TypePointer.d dmd/TypeQualified.d dmd/TypeReference.d dmd/TypeReturn.d dmd/TypeSArray.d dmd/TypeSlice.d dmd/TypeStruct.d dmd/TypeTuple.d dmd/TypeTypedef.d dmd/TypeTypeof.d dmd/TypedefDeclaration.d dmd/TypeidExp.d dmd/UAddExp.d dmd/UnaExp.d dmd/UnionDeclaration.d dmd/UnitTestDeclaration.d dmd/UnrolledLoopStatement.d dmd/UshrAssignExp.d dmd/UshrExp.d dmd/Utf.d dmd/Util.d dmd/VarDeclaration.d dmd/VarExp.d dmd/VersionCondition.d dmd/VersionSymbol.d dmd/VoidInitializer.d dmd/VolatileStatement.d dmd/WANT.d dmd/WhileStatement.d dmd/WithScopeSymbol.d dmd/WithStatement.d dmd/XorAssignExp.d dmd/XorExp.d dmd/backend/BC.d dmd/backend/Blockx.d dmd/backend/Classsym.d dmd/backend/Config.d dmd/backend/Configv.d dmd/backend/Cstate.d dmd/backend/DT.d dmd/backend/F.d dmd/backend/FL.d dmd/backend/Funcsym.d dmd/backend/LANG.d dmd/backend/LINKAGE.d dmd/backend/LIST.d dmd/backend/OPER.d dmd/backend/PARAM.d dmd/backend/REG.d dmd/backend/REGMAX.d dmd/backend/RTLSYM.d dmd/backend/SC.d dmd/backend/SEN.d dmd/backend/SFL.d dmd/backend/STR.d dmd/backend/SYMIDX.d dmd/backend/Srcpos.d dmd/backend/StringTab.d dmd/backend/Symbol.d dmd/backend/TF.d dmd/backend/TYFL.d dmd/backend/TYM.d dmd/backend/TYPE.d dmd/backend/Thunk.d dmd/backend/Util.d dmd/backend/block.d dmd/backend/code.d dmd/backend/con_t.d dmd/backend/cse_t.d dmd/backend/dt_t.d dmd/backend/elem.d dmd/backend/enum_t.d dmd/backend/func_t.d dmd/backend/glue.d dmd/backend/iasm.d dmd/backend/immed_t.d dmd/backend/mTY.d dmd/backend/mTYman.d dmd/backend/regm_t.d dmd/backend/rel.d dmd/backend/struct_t.d dmd/backend/symtab_t.d dmd/backend/targ_types.d dmd/backend/template_t.d dmd/backend/token_t.d dmd/backend/vec_t.d dmd/codegen/Util.d dmd/condition/util/findCondition.d dmd/declaration/Match.d dmd/expression/Add.d dmd/expression/And.d dmd/expression/ArrayLength.d dmd/expression/Cat.d dmd/expression/Cmp.d dmd/expression/Com.d dmd/expression/Div.d dmd/expression/Equal.d dmd/expression/Identity.d dmd/expression/Index.d dmd/expression/Min.d dmd/expression/Mod.d dmd/expression/Mul.d dmd/expression/Neg.d dmd/expression/Not.d dmd/expression/Or.d dmd/expression/Ptr.d dmd/expression/Shl.d dmd/expression/Shr.d dmd/expression/Slice.d dmd/expression/Ushr.d dmd/expression/Util.d dmd/expression/Xor.d dmd/expression/shift_optimize.d dmd/expression/util/arrayTypeCompatible.d dmd/type/Util.d main.d
diffstat 399 files changed, 88636 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bridge/bridge.cpp	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,181 @@
+struct Symbol;
+struct dt_t;
+struct TYPE;
+struct elem;
+struct Blockx;
+struct block;
+
+typedef TYPE type;
+
+int reftoident(int a, unsigned long b, Symbol* c, unsigned long d, int e);
+
+int reftoident(int a, unsigned int b, Symbol* c, unsigned int d, int e)
+{
+	return reftoident(a, (unsigned long)b, c, (unsigned long)d, e);
+}
+
+dt_t** dtnzeros(dt_t**, unsigned long);
+
+dt_t** dtnzeros(dt_t** a, unsigned int b)
+{
+	return dtnzeros(a, (unsigned long)b);
+}
+
+TYPE* type_fake(unsigned long a);
+
+TYPE* type_fake(unsigned int a)
+{
+	return type_fake((unsigned long)a);
+}
+
+elem* el_long(unsigned long a, long long b);
+
+elem* el_long(unsigned int a, long long b)
+{
+	return el_long((unsigned long)a, b);
+}
+
+type* type_alloc(unsigned long a);
+
+type* type_alloc(unsigned int a)
+{
+	return type_alloc((unsigned long)a);
+}
+
+elem* el_bin(unsigned int a, unsigned long b, elem* c, elem* d);
+
+elem* el_bin(unsigned int a, unsigned int b, elem* c, elem* d)
+{
+	return el_bin(a, (unsigned long)b, c, d);
+}
+
+dt_t** dtnbytes(dt_t** a, unsigned long b, const char* c);
+
+dt_t** dtnbytes(dt_t** a, unsigned int b, const char* c)
+{
+	return dtnbytes(a, (unsigned long)b, c);
+}
+
+extern unsigned char tytab[];
+unsigned char* get_tytab()
+{
+	return tytab;
+}
+
+extern unsigned char tytab2[];
+unsigned char* get_tytab2()
+{
+	return tytab2;
+}
+
+extern signed char tysize[];
+signed char* get_tysize()
+{
+	return tysize;
+}
+
+type* type_setcv(type** pt, unsigned long cv);
+
+type* type_setcv(type** pt, unsigned int cv)
+{
+	return type_setcv(pt, (unsigned long) cv);
+}
+
+elem* el_una(unsigned int op, unsigned long ty, elem* e1);
+
+elem* el_una(unsigned int op, unsigned int ty, elem* e1)
+{
+	return el_una(op, (unsigned long) ty, e1);
+}
+
+type* type_allocn(unsigned long a, type* b);
+
+type* type_allocn(unsigned int a, type* b)
+{
+	return type_allocn((unsigned long)a, b);
+}
+
+void block_next(Blockx* bctx, enum BC bc, block* bn);
+
+void block_next(Blockx* bctx, int bc, block* bn)
+{
+	block_next(bctx, (enum BC)bc, bn);
+}
+
+block* block_goto(Blockx* bctx, enum BC bc, block* bn);
+
+block* block_goto(Blockx* bctx, int bc, block* bn)
+{
+	return block_goto(bctx, (enum BC)bc, bn);
+}
+
+dt_t** dtxoff(dt_t** pdtend, Symbol* s, unsigned long offset, unsigned long ty);
+
+dt_t** dtxoff(dt_t** pdtend, Symbol* s, unsigned int offset, unsigned int ty)
+{
+	return dtxoff(pdtend, s, (unsigned long)offset, (unsigned long)ty);
+}
+
+dt_t** dtabytes(dt_t** pdtend,  unsigned long ty, unsigned long offset, unsigned long size, const char* ptr);
+
+dt_t** dtabytes(dt_t** pdtend,  unsigned int ty, unsigned int offset, unsigned int size, const char* ptr)
+{
+	return dtabytes(pdtend,  (unsigned long)ty, (unsigned long)offset, (unsigned long)size, ptr);
+}
+
+dt_t** dtdword(dt_t** pdtend, long value);
+
+dt_t** dtdword(dt_t** pdtend, int value)
+{
+	return dtdword(pdtend, (long)value);
+}
+
+type* type_setty(type** a, long b);
+
+type* type_setty(type** a, int b)
+{
+	return type_setty(a, (long)b);
+}
+
+elem* el_pair(unsigned long a, elem* b, elem* c);
+
+elem* el_pair(unsigned int a, elem* b, elem* c)
+{
+	return el_pair((unsigned long)a, b, c);
+}
+
+extern unsigned char rel_not[];
+extern unsigned char rel_swap[];
+extern unsigned char rel_integral[];
+extern unsigned char rel_exception[];
+extern unsigned char rel_unord[];
+
+unsigned char* get_rel_not() { return rel_not; }
+unsigned char* get_rel_swap() { return rel_swap; }
+unsigned char* get_rel_integral() { return rel_integral; }
+unsigned char* get_rel_exception() { return rel_exception; }
+unsigned char* get_rel_unord() { return rel_unord; }
+
+unsigned long type_paramsize(type* t);
+unsigned int type_paramsize_i(type* t)
+{
+	return (unsigned int)type_paramsize(t);
+}
+
+void cod3_thunk(Symbol* sthunk, Symbol* sfunc, unsigned int p, unsigned long thisty, unsigned long d, int i, unsigned long d2);
+void cod3_thunk(Symbol* sthunk, Symbol* sfunc, unsigned int p, unsigned int  thisty, unsigned int  d, int i, unsigned int  d2)
+{
+	return cod3_thunk(sthunk, sfunc, p, (unsigned long)thisty, (unsigned long)d, i, (unsigned long)d2);
+}
+
+elem* el_const(unsigned long a, union eve* b);
+elem* el_const(unsigned int a, union eve* b)
+{
+	return el_const((unsigned long)a, b);
+}
+
+extern const unsigned long tytouns[];
+unsigned int* get_tytouns()
+{
+	return (unsigned int*)tytouns;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/build.bat	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,2 @@
+@echo off
+cls && c:\dm\bin\dmc.exe bridge\bridge.cpp -c && c:\dmd_2.031\windows\bin\dmd.exe @commands.txt
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/commands.txt	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,382 @@
+-g
+-debug
+-version=DMDV2
+-version=TX86
+-version=MARS
+-version=TARGET_WINDOS
+-version=_WIN32
+-version=WindowsXP
+-version=DumbClone
+-version=STRUCTTHISREF
+-version=CCASTSYNTAX
+-version=CARRAYDECL
+-version=BREAKABI
+-version=SEH
+-version=OMFOBJ
+-version=SNAN_DEFAULT_INIT
+-ofc:\dmd_2.032\windows\bin\dmd.exe
+bridge.obj
+ddmd.def
+c:\dmd_2.032\src\dmd\dmd.lib
+main.d
+win32\windef.d
+win32\winuser.d
+win32\wingdi.d
+dlib\CrashHandler.d
+dbg\ui\CrashWindow.d
+dbg\Debug.d
+dbg\symbol\CodeView.d
+dbg\image\PE.d
+dmd\AggregateDeclaration.d
+dmd\VarExp.d
+dmd\Tuple.d
+dmd\UnrolledLoopStatement.d
+dmd\SwitchErrorStatement.d
+dmd\NewAnonClassExp.d
+dmd\StructLiteralExp.d
+dmd\StaticIfCondition.d
+dmd\BoolExp.d
+dmd\ShlAssignExp.d
+dmd\ShrAssignExp.d
+dmd\UshrAssignExp.d
+dmd\CatAssignExp.d
+dmd\Port.d
+dmd\declaration\MATCH.d
+dmd\expression\Util.d
+dmd\expression\Add.d
+dmd\expression\Xor.d
+dmd\expression\Ptr.d
+dmd\expression\Min.d
+dmd\expression\And.d
+dmd\expression\Shr.d
+dmd\expression\Not.d
+dmd\expression\Mod.d
+dmd\expression\Mul.d
+dmd\expression\Com.d
+dmd\expression\Ushr.d
+dmd\expression\Shl.d
+dmd\expression\Div.d
+dmd\expression\Cmp.d
+dmd\expression\Identity.d
+dmd\expression\ArrayLength.d
+dmd\expression\Equal.d
+dmd\expression\Or.d
+dmd\expression\Neg.d
+dmd\expression\Cat.d
+dmd\expression\Slice.d
+dmd\expression\Index.d
+dmd\expression\shift_optimize.d
+dmd\expression\util\arrayTypeCompatible.d
+dmd\condition\util\findCondition.d
+dmd\OverExp.d
+dmd\Cast.d
+dmd\TupleExp.d
+dmd\ArrayLengthExp.d
+dmd\TypeInfoConstDeclaration.d
+dmd\TypeInfoInvariantDeclaration.d
+dmd\TypeInfoSharedDeclaration.d
+dmd\TypeInfoStructDeclaration.d
+dmd\TypeInfoInterfaceDeclaration.d
+dmd\TypeInfoEnumDeclaration.d
+dmd\TypeInfoClassDeclaration.d
+dmd\TypeInfoArrayDeclaration.d
+dmd\TypeInfoDelegateDeclaration.d
+dmd\TypeInfoTypedefDeclaration.d
+dmd\TypeInfoPointerDeclaration.d
+dmd\DsymbolExp.d
+dmd\GlobalExpressions.d
+dmd\NewExp.d
+dmd\PeelStatement.d
+dmd\HaltExp.d
+dmd\SymOffExp.d
+dmd\type\Util.d
+dmd\SymbolExp.d
+dmd\Optimize.d
+dmd\DotVarExp.d
+dmd\DeclarationExp.d
+dmd\TraitsExp.d
+dmd\ComplexExp.d
+dmd\ErrorExp.d
+dmd\AssignExp.d
+dmd\DotExp.d
+dmd\AliasDeclaration.d
+dmd\DefaultInitExp.d
+dmd\FileInitExp.d
+dmd\LineInitExp.d
+dmd\AnonDeclaration.d
+dmd\AliasThis.d
+dmd\AlignDeclaration.d
+dmd\AnonymousAggregateDeclaration.d
+dmd\Argument.d
+dmd\FuncExp.d
+dmd\ArrayLiteralExp.d
+dmd\AssocArrayLiteralExp.d
+dmd\AssertExp.d
+dmd\IsExp.d
+dmd\TypeExp.d
+dmd\StringExp.d
+dmd\NullExp.d
+dmd\RealExp.d
+dmd\ThisExp.d
+dmd\ScopeExp.d
+dmd\Array.d
+dmd\DotIdExp.d
+dmd\FileExp.d
+dmd\SuperExp.d
+dmd\TypeidExp.d
+dmd\CompileExp.d
+dmd\IdentifierExp.d
+dmd\DollarExp.d
+dmd\ArrayT.d
+dmd\AndAndExp.d
+dmd\DotTemplateInstanceExp.d
+dmd\OrExp.d
+dmd\PostExp.d
+dmd\CallExp.d
+dmd\SliceExp.d
+dmd\ArrayExp.d
+dmd\AddrExp.d
+dmd\UAddExp.d
+dmd\XorExp.d
+dmd\CommaExp.d
+dmd\BinExp.d
+dmd\CondExp.d
+dmd\OrOrExp.d
+dmd\AndExp.d
+dmd\InExp.d
+dmd\EqualExp.d
+dmd\CmpExp.d
+dmd\ShlExp.d
+dmd\AddExp.d
+dmd\CatExp.d
+dmd\MinExp.d
+dmd\MulExp.d
+dmd\ModExp.d
+dmd\DivExp.d
+dmd\ShrExp.d
+dmd\UshrExp.d
+dmd\CastExp.d
+dmd\DeleteExp.d
+dmd\ComExp.d
+dmd\NotExp.d
+dmd\UnaExp.d
+dmd\NegExp.d
+dmd\PtrExp.d
+dmd\IntegerExp.d
+dmd\AddAssignExp.d
+dmd\AndAssignExp.d
+dmd\DivAssignExp.d
+dmd\MinAssignExp.d
+dmd\ModAssignExp.d
+dmd\MulAssignExp.d
+dmd\OrAssignExp.d
+dmd\XorAssignExp.d
+dmd\IdentityExp.d
+dmd\ArrayInitializer.d
+dmd\ArrayScopeSymbol.d
+dmd\ArrayTypes.d
+dmd\AsmStatement.d
+dmd\AttribDeclaration.d
+dmd\BUILTIN.d
+dmd\BaseClass.d
+dmd\BreakStatement.d
+dmd\CaseRangeStatement.d
+dmd\CaseStatement.d
+dmd\Catch.d
+dmd\ClassDeclaration.d
+dmd\ClassInfoDeclaration.d
+dmd\CompileDeclaration.d
+dmd\CompileStatement.d
+dmd\CompoundDeclarationStatement.d
+dmd\CompoundStatement.d
+dmd\Condition.d
+dmd\ConditionalDeclaration.d
+dmd\ConditionalStatement.d
+dmd\ContinueStatement.d
+dmd\CppMangleState.d
+dmd\CtorDeclaration.d
+dmd\DVCondition.d
+dmd\Dchar.d
+dmd\DebugCondition.d
+dmd\DebugSymbol.d
+dmd\Declaration.d
+dmd\DeclarationStatement.d
+dmd\DefaultStatement.d
+dmd\DeleteDeclaration.d
+dmd\DoStatement.d
+dmd\DocComment.d
+dmd\Dsymbol.d
+dmd\DsymbolTable.d
+dmd\DtorDeclaration.d
+dmd\EnumDeclaration.d
+dmd\EnumMember.d
+dmd\Escape.d
+dmd\ExpInitializer.d
+dmd\ExpStatement.d
+dmd\Expression.d
+dmd\File.d
+dmd\FileName.d
+dmd\ForStatement.d
+dmd\ForeachRangeStatement.d
+dmd\ForeachStatement.d
+dmd\FuncAliasDeclaration.d
+dmd\FuncDeclaration.d
+dmd\FuncLiteralDeclaration.d
+dmd\Global.d
+dmd\GotoCaseStatement.d
+dmd\GotoDefaultStatement.d
+dmd\GotoStatement.d
+dmd\HdrGenState.d
+dmd\ILS.d
+dmd\IRState.d
+dmd\Id.d
+dmd\Identifier.d
+dmd\IfStatement.d
+dmd\Import.d
+dmd\Initializer.d
+dmd\InlineCostState.d
+dmd\InlineDoState.d
+dmd\InlineScanState.d
+dmd\IntRange.d
+dmd\InterState.d
+dmd\InterfaceDeclaration.d
+dmd\InvariantDeclaration.d
+dmd\LINK.d
+dmd\LabelDsymbol.d
+dmd\LabelStatement.d
+dmd\Lexer.d
+dmd\Library.d
+dmd\LinkDeclaration.d
+dmd\Loc.d
+dmd\Lstring.d
+dmd\MATCH.d
+dmd\Macro.d
+dmd\Module.d
+dmd\ModuleDeclaration.d
+dmd\ModuleInfoDeclaration.d
+dmd\NewDeclaration.d
+dmd\ObjModule.d
+dmd\OnScopeStatement.d
+dmd\OutBuffer.d
+dmd\OverloadSet.d
+dmd\PREC.d
+dmd\PROT.d
+dmd\Package.d
+dmd\Param.d
+dmd\Parser.d
+dmd\PostBlitDeclaration.d
+dmd\PragmaDeclaration.d
+dmd\PragmaStatement.d
+dmd\ProtDeclaration.d
+dmd\RET.d
+dmd\ReturnStatement.d
+dmd\STC.d
+dmd\Scope.d
+dmd\ScopeDsymbol.d
+dmd\ScopeStatement.d
+dmd\Section.d
+dmd\Statement.d
+dmd\StaticAssert.d
+dmd\StaticAssertStatement.d
+dmd\StaticCtorDeclaration.d
+dmd\StaticDtorDeclaration.d
+dmd\StaticIfDeclaration.d
+dmd\StorageClassDeclaration.d
+dmd\String.d
+dmd\StringEntry.d
+dmd\StringTable.d
+dmd\StringValue.d
+dmd\StructDeclaration.d
+dmd\StructInitializer.d
+dmd\SwitchStatement.d
+dmd\SymbolDeclaration.d
+dmd\SynchronizedStatement.d
+dmd\TOK.d
+dmd\TY.d
+dmd\TemplateAliasParameter.d
+dmd\TemplateDeclaration.d
+dmd\TemplateInstance.d
+dmd\TemplateMixin.d
+dmd\TemplateParameter.d
+dmd\TemplateThisParameter.d
+dmd\TemplateTupleParameter.d
+dmd\TemplateTypeParameter.d
+dmd\TemplateValueParameter.d
+dmd\ThisDeclaration.d
+dmd\ThrowStatement.d
+dmd\Token.d
+dmd\TryCatchStatement.d
+dmd\TryFinallyStatement.d
+dmd\TupleDeclaration.d
+dmd\Type.d
+dmd\TypeAArray.d
+dmd\TypeArray.d
+dmd\TypeBasic.d
+dmd\TypeClass.d
+dmd\TypeDArray.d
+dmd\TypeDelegate.d
+dmd\TypeEnum.d
+dmd\TypeFunction.d
+dmd\TypeIdentifier.d
+dmd\TypeInfoDeclaration.d
+dmd\TypeInstance.d
+dmd\TypeNext.d
+dmd\TypePointer.d
+dmd\TypeQualified.d
+dmd\TypeReference.d
+dmd\TypeReturn.d
+dmd\TypeSArray.d
+dmd\EnumUtils.d
+dmd\TypeSlice.d
+dmd\TypeStruct.d
+dmd\TypeTuple.d
+dmd\TypeTypedef.d
+dmd\TypeTypeof.d
+dmd\TypedefDeclaration.d
+dmd\UnionDeclaration.d
+dmd\UnitTestDeclaration.d
+dmd\Utf.d
+dmd\Util.d
+dmd\DotTemplateExp.d
+dmd\DelegateExp.d
+dmd\RemoveExp.d
+dmd\TemplateExp.d
+dmd\DotTypeExp.d
+dmd\IndexExp.d
+dmd\VarDeclaration.d
+dmd\VersionCondition.d
+dmd\VersionSymbol.d
+dmd\VoidInitializer.d
+dmd\VolatileStatement.d
+dmd\WhileStatement.d
+dmd\WithScopeSymbol.d
+dmd\WithStatement.d
+dmd\backend\Blockx.d
+dmd\backend\enum_t.d
+dmd\backend\Symbol.d
+dmd\backend\Util.d
+dmd\backend\TYPE.d
+dmd\backend\TYM.d
+dmd\backend\mTY.d
+dmd\backend\block.d
+dmd\backend\code.d
+dmd\backend\glue.d
+dmd\backend\dt_t.d
+dmd\backend\elem.d
+dmd\backend\func_t.d
+dmd\backend\Cstate.d
+dmd\backend\TYFL.d
+dmd\backend\RTLSYM.d
+dmd\backend\symtab_t.d
+dmd\backend\Classsym.d
+dmd\backend\con_t.d
+dmd\backend\cse_t.d
+dmd\backend\struct_t.d
+dmd\backend\OPER.d
+dmd\backend\StringTab.d
+dmd\backend\DT.d
+dmd\backend\Configv.d
+dmd\backend\iasm.d
+dmd\backend\rel.d
+dmd\backend\LIST.d
+dmd\codegen\Util.d
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg/Debug.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,33 @@
+/**
+ Common interfaces for the debugging package.
+
+ Authors:
+	Jeremie Pelletier
+*/
+module dbg.Debug;
+
+interface IExecutableImage {
+	uint codeOffset() const;
+
+	ISymbolicDebugInfo debugInfo();
+}
+
+interface ISymbolicDebugInfo {
+	SymbolInfo ResolveSymbol(size_t rva) const;
+	FileLineInfo ResolveFileLine(size_t rva) const;
+}
+
+struct SymbolInfo {
+	string	name;
+	uint	offset;
+}
+
+struct FileLineInfo {
+	string	file;
+	uint	line;
+}
+
+void SystemException()
+{
+	throw new Exception("SystemException");
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg/image/PE.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,361 @@
+/**
+ A simple PE/COFF image format reader.
+
+ Authors:
+	Jeremie Pelletier
+
+ References:
+	$(LINK http://www.csn.ul.ie/~caolan/publink/winresdump/winresdump/doc/pefile.html)
+
+ License:
+	Public Domain
+*/
+module dbg.image.PE;
+
+version(Windows) {
+
+import std.c.string : strncmp;
+import dbg.Debug;
+import dbg.symbol.CodeView;
+//import dbg.symbol.COFF;
+//import sys.windows.FileSystem;
+//import sys.windows.Memory;
+//import sys.windows.Security : GENERIC_READ;
+//import sys.windows.Information : CloseHandle;
+//import sys.windows.Image;
+
+import win32.windows;
+import win32.winbase;
+
+enum IMAGE_SIZEOF_NT_OPTIONAL64_HEADER = 240;
+
+struct IMAGE_NT_HEADERS64 {
+    DWORD Signature;
+    IMAGE_FILE_HEADER FileHeader;
+    IMAGE_OPTIONAL_HEADER64 OptionalHeader;
+}
+
+auto IMAGE_FIRST_SECTION64( const(IMAGE_NT_HEADERS64*) ntheader ) {
+	return cast(PIMAGE_SECTION_HEADER) ((cast(UINT_PTR)ntheader) + IMAGE_NT_HEADERS64.OptionalHeader.offsetof + (cast(PIMAGE_NT_HEADERS64)(ntheader)).FileHeader.SizeOfOptionalHeader);
+}
+
+auto IMAGE_FIRST_SECTION32( const(IMAGE_NT_HEADERS32*) ntheader ) {
+	return cast(PIMAGE_SECTION_HEADER)((cast(UINT_PTR)ntheader) + IMAGE_NT_HEADERS32.OptionalHeader.offsetof + (cast(PIMAGE_NT_HEADERS32)ntheader).FileHeader.SizeOfOptionalHeader);
+}
+
+class PEImage : IExecutableImage {
+	/**
+	 Loads and validate the image file.
+
+	 Params:
+		fileName =	Path to the image file.
+	*/
+	this(string fileName)
+	in {
+		assert(fileName.length && fileName.ptr);
+	}
+	body {
+		_filename = fileName;
+
+		// Create the file mapping
+		_file = CreateFileA((fileName ~ '\0').ptr, GENERIC_READ, FILE_SHARE_READ,
+			null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, null);
+		if(_file == INVALID_HANDLE_VALUE) SystemException();
+
+		GetFileSizeEx(_file, &_fileSize);
+
+		_map = CreateFileMapping(_file, null, PAGE_READONLY, 0, 0, null);
+		if(!_map) SystemException();
+
+		_view = cast(const(ubyte)*)MapViewOfFile(_map, FILE_MAP_READ, 0, 0, 0);
+		if(!_view) SystemException();
+
+		// Verify image headers
+		if(_dos.e_magic != IMAGE_DOS_SIGNATURE) goto Error;
+		CheckOffset(_dos.e_lfanew);
+
+		_nt = cast(IMAGE_NT_HEADERS32*)(_view + _dos.e_lfanew);
+		if(_nt.Signature != IMAGE_NT_SIGNATURE) goto Error;
+
+		_is64 = _nt.FileHeader.SizeOfOptionalHeader == IMAGE_SIZEOF_NT_OPTIONAL64_HEADER;
+
+		if(_is64) {
+			if(_nt64.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC)
+				goto Error;
+		}
+		else {
+			if(_nt.OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
+				goto Error;
+		}
+
+		// Create the RVA lookup table
+		auto sections = this.sections;
+		RVAEntry* e = void;
+		_rvaTable.length = sections.length;
+		foreach(i, ref s; sections) with(s) {
+			e = &_rvaTable[i];
+			e.start = VirtualAddress;
+			e.end = VirtualAddress + SizeOfRawData;
+			e.base = PointerToRawData;
+		}
+
+		return;
+
+	Error:
+		throw new PEInvalidException(this);
+	}
+
+	/**
+	 Unloads the PE file.
+	*/
+	~this() {
+		if(_dos && !UnmapViewOfFile(cast(void*)_dos)) SystemException();
+		if(_map && !CloseHandle(_map)) SystemException();
+		if(_file && !CloseHandle(_file)) SystemException();
+	}
+
+	/**
+	 Get the filename of the image
+	*/
+	string filename() const {
+		return _filename;
+	}
+
+	/**
+	 Get whether the image uses the 64bit structures or not
+	*/
+	bool is64() const {
+		return _is64;
+	}
+
+	/**
+	 Get the base address of the image
+	*/
+	long imageBase() const {
+		return _is64 ? _nt64.OptionalHeader.ImageBase : _nt.OptionalHeader.ImageBase;
+	}
+
+	/**
+	 Get the raw image data
+	*/
+	const(ubyte)[] data() const {
+		return _view[0 .. cast(size_t)_fileSize.QuadPart];
+	}
+
+	/**
+	 Get the dos, nt or nt64 headers
+	*/
+	const(IMAGE_DOS_HEADER)* dosHeader() const { return _dos; }
+	const(IMAGE_NT_HEADERS32)* ntHeaders32() const { return _nt; }
+	const(IMAGE_NT_HEADERS64)* ntHeaders64() const { return _nt64; }
+
+	/**
+	 Get the array of data directories
+	*/
+	const(IMAGE_DATA_DIRECTORY)[] dataDirectory() const {
+		return _is64 ? _nt64.OptionalHeader.DataDirectory : _nt.OptionalHeader.DataDirectory;
+	}
+
+	/**
+	 Get the array of section headers
+	*/
+	const(IMAGE_SECTION_HEADER)[] sections() const {
+		return (_is64 ? IMAGE_FIRST_SECTION64(_nt64) : IMAGE_FIRST_SECTION32(_nt))
+			[0 .. _nt.FileHeader.NumberOfSections];
+	}
+
+	/**
+	 Translate the given Virtual Address to its corresponding data offset.
+	*/
+	long LookupVA(long va) const {
+		return LookupRVA(va - imageBase);
+	}
+
+	/**
+	 Translate the given Relative Virtual Address to its corresponding
+	 data offset.
+	*/
+	long LookupRVA(long rva) const {
+		foreach(ref e; _rvaTable) with(e) {
+			if(rva >= start && rva < end) {
+				long offset = base + (rva - start);
+				CheckOffset(offset);
+				return offset;
+			}
+		}
+
+		return 0;
+	}
+
+	/**
+	 Get a data structure in the image from its RVA
+	*/
+	const(T)* GetDataFromRVA(T : T*)(long rva) const {
+		long offset = LookupRVA(rva);
+		return offset ? cast(T*)(_view + offset) : null;
+	}
+
+	/**
+	 Get a data directory in the image from its ID
+	*/
+	const(T)* GetDirectory(T)(uint id) const {
+		const IMAGE_DATA_DIRECTORY* dir = &dataDirectory[id];
+		return dir.VirtualAddress && dir.Size ?
+			GetDataFromRVA!(T*)(dir.VirtualAddress) : null;
+	}
+
+	/**
+	 Find the first section matching the given flags mask
+	*/
+	const(IMAGE_SECTION_HEADER)* FindSection(uint mask) const
+	in {
+		assert(mask);
+	}
+	body {
+		foreach(ref section; sections)
+			if(section.Characteristics & mask)
+				return &section;
+
+		return null;
+	}
+
+	/**
+	 Find a section by its name
+	*/
+	const(IMAGE_SECTION_HEADER)* FindSection(string name) const
+	in {
+		assert(name.length && name.ptr);
+	}
+	body {
+		foreach(ref section; sections)
+			if(strncmp(cast(char*)section.Name.ptr, name.ptr, section.Name.length) == 0)
+				return &section;
+
+		return null;
+	}
+
+	/**
+	 Get the offset to the code segment
+	*/
+	uint codeOffset() const {
+		const(IMAGE_SECTION_HEADER)* section = FindSection(IMAGE_SCN_MEM_EXECUTE);
+		return section ? section.VirtualAddress : 0;
+	}
+
+	/**
+	 Get the symbolic debug info object for this image
+	*/
+	ISymbolicDebugInfo debugInfo() {
+		uint va = _nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
+		if(!va) return null;
+
+		const(IMAGE_DEBUG_DIRECTORY)* dir = void;
+		uint size = _nt.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
+		uint offset = void;
+
+		// Borland directory
+		const(IMAGE_SECTION_HEADER)* section = FindSection(".debug");
+		if(section && section.VirtualAddress == va) {
+			CheckOffset(section.PointerToRawData);
+
+			dir = cast(IMAGE_DEBUG_DIRECTORY*)(_view + section.PointerToRawData);
+		}
+		// Microsoft directory
+		else {
+			section = FindSection(".rdata");
+			if(!section) goto NoDebug;
+
+			offset = section.PointerToRawData + (va - section.VirtualAddress);
+			CheckOffset(offset);
+
+			dir = cast(IMAGE_DEBUG_DIRECTORY*)(_view + offset);
+		}
+
+		const(void)* end = cast(void*)dir + size;
+		Scan: for(; dir < end; dir++) {
+			switch(dir.Type) {
+			//case IMAGE_DEBUG_TYPE_COFF:
+			case IMAGE_DEBUG_TYPE_CODEVIEW:
+			// TODO: support more types
+				break Scan;
+
+			default:
+			}
+		}
+
+		if(dir >= end) goto NoDebug;
+
+		offset = dir.PointerToRawData + dir.SizeOfData;
+		CheckOffset(offset);
+		auto debugView = _view[dir.PointerToRawData .. offset];
+
+		switch(dir.Type) {
+		//case IMAGE_DEBUG_TYPE_COFF:
+		//	return new COFFDebugInfo(debugView);
+		case IMAGE_DEBUG_TYPE_CODEVIEW:
+			return new CodeViewDebugInfo(debugView);
+		default:
+			assert(0);
+		}
+
+	NoDebug:
+		// TODO: we have no debug section or directory, but there csould still
+		// be external symbol files we can use.
+		return null;
+	}
+
+private:
+
+	/**
+	 Verify a file offset before accessing it
+	*/
+	void CheckOffset(long offset) const {
+		if(offset > _fileSize.QuadPart) throw new PECorruptedException(this);
+	}
+
+	string							_filename;
+	HANDLE							_file;
+	HANDLE							_map;
+	LARGE_INTEGER					_fileSize;
+	bool							_is64;
+
+	union {
+		const(ubyte)*				_view;
+		const(IMAGE_DOS_HEADER)*	_dos;
+	}
+	union {
+		const(IMAGE_NT_HEADERS32)*	_nt;
+		const(IMAGE_NT_HEADERS64)*	_nt64;
+	}
+
+	struct RVAEntry {
+		uint start;
+		uint end;
+		uint base;
+	}
+
+	RVAEntry[] _rvaTable;
+}
+
+/// Thrown if file open failed.
+class PEException : Exception {
+	this(string msg) {
+		super("PEImage: " ~ msg);
+	}
+}
+
+/// Thrown if not a valid module file
+class PEInvalidException : PEException {
+	this(in PEImage img) {
+		super("Invalid PE file.");
+	}
+}
+
+/// Thrown on corrupted module file.
+class PECorruptedException : PEException {
+	this(in PEImage img) {
+		super("Corrupted PE file.");
+	}
+}
+
+} // version(Windows)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg/symbol/CodeView.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1759 @@
+/**
+ This module is used to extract CodeView symbolic debugging information and to
+ perform queries upon that information.
+
+ TODO:
+	* Add support for CodeView 5.0 and PDB formats.
+	* Add support to extract type information.
+
+ Authors:
+	Jeremie Pelletier
+
+ References:
+	$(LINK http://www.x86.org/ftp/manuals/tools/sym.pdf)
+	$(LINK http://undocumented.rawol.com/sbs-w2k-1-windows-2000-debugging-support.pdf)
+	$(LINK http://www.microsoft.com/msj/0399/hood/hood0399.aspx)
+	$(LINK http://source.winehq.org/source/include/wine/mscvpdb.h)
+	$(LINK http://www.digitalmars.com/d/2.0/abi.html)
+
+ License:
+	Public Domain
+*/
+module dbg.symbol.CodeView;
+
+import dbg.Debug;
+
+class CodeViewDebugInfo : ISymbolicDebugInfo {
+	/**
+	 Load CodeView data from the given memory view.
+	*/
+	this(in void[] view)
+	in {
+		assert(view.length && view.ptr);
+	}
+	body {
+		_view = view;
+
+		auto header = cast(CV_HEADER*)_view.ptr;
+		CheckOffset(header.offset);
+
+		// TODO: Only supporting NB09 (CodeView 4.10) right now
+		if(!header.signature == CV_SIGNATURE_NB09)
+			throw new CodeViewUnsupportedException(this);
+
+		auto dir = cast(CV_DIRECTORY*)(view.ptr + header.offset);
+		if(dir.dirSize != CV_DIRECTORY.sizeof || dir.entrySize != CV_ENTRY.sizeof)
+			throw new CodeViewCorruptedException(this);
+
+		CvModule globalModule;
+		_modules ~= globalModule;
+
+		foreach(ref e; dir.entries) {
+			CheckOffset(e.offset);
+
+			switch(e.sst) {
+			case sstModule:			ParseModule(&e);		break;
+			case sstLibraries:		ParseLibraries(&e);		break;
+			case sstAlignSym:		ParseAlignSymbols(&e);	break;
+			case sstSrcModule:		ParseSrcModule(&e);		break;
+			case sstGlobalPub:
+			case sstStaticSym:
+			case sstGlobalSym:		ParseHashSymbols(&e);	break;
+			case sstGlobalTypes:	ParseGlobalTypes(&e);	break;
+
+			// TODO:
+			/*case sstFileIndex:
+			case sstSegMap:
+			case sstSegName:*/
+
+			default:
+			}
+		}
+	}
+
+	/**
+	 Get the procedure symbol matching the given address.
+	*/
+	SymbolInfo ResolveSymbol(size_t rva) const
+	in {
+		assert(rva);
+	}
+	body {
+		SymbolInfo symbol;
+
+		foreach(ref m; _modules[0 .. _maxSymModule + 1])
+			if(m.symbols.QueryProc(rva, &symbol))
+				goto Found;
+
+		foreach(ref m; _modules[0 .. _maxSymModule + 1])
+			if(m.symbols.QueryCodeData(rva, &symbol))
+				goto Found;
+
+	Found:
+		return symbol;
+	}
+
+	/**
+	 Get the file/line mapping corresponding to the given relative address.
+	*/
+	FileLineInfo ResolveFileLine(size_t rva) const
+	in {
+		assert(rva);
+	}
+	body {
+		FileLineInfo fileLine;
+
+		if(_maxSrcModule)
+			foreach(m; _modules[1 .. _maxSrcModule + 1])
+				if(m.src.Query(rva, &fileLine))
+					break;
+
+		return fileLine;
+	}
+
+private:
+
+	void ParseModule(in CV_ENTRY* e) {
+		auto mod = cast(CV_MODULE*)(_view.ptr + e.offset);
+
+		if(e.modIndex != _modules.length || mod.style != CV_MOD_STYLE)
+			throw new CodeViewCorruptedException(this);
+
+		with(*mod)
+		_modules ~= CvModule(overlay, lib, segments, name.name);
+	}
+
+	void ParseLibraries(in CV_ENTRY* e) {
+		if(e.modIndex != ushort.max) throw new CodeViewCorruptedException(this);
+
+		auto name = cast(OMF_NAME*)(_view.ptr + e.offset);
+		auto end = cast(const(void)*)name + e.size;
+
+		while(name < end) {
+			if(name.len) _libraries ~= name.name;
+
+			name = cast(OMF_NAME*)(cast(void*)name + 1 + name.len);
+		}
+	}
+
+	void ParseAlignSymbols(in CV_ENTRY* e) {
+		if(e.modIndex == ushort.max || e.modIndex <= 0 || e.modIndex >= _modules.length)
+			throw new CodeViewCorruptedException(this);
+
+		if(e.modIndex > _maxSymModule) _maxSymModule = e.modIndex;
+
+		auto sym = cast(CV_SYMBOL*)(_view.ptr + e.offset);
+
+		if(sym.header.type == 0) sym = cast(CV_SYMBOL*)(cast(void*)sym + 4);
+
+		_modules[e.modIndex].symbols.Init(sym, cast(void*)sym + e.size);
+	}
+
+	void ParseHashSymbols(in CV_ENTRY* e) {
+		if(e.modIndex != ushort.max) throw new CodeViewCorruptedException(this);
+
+		auto hash = cast(CV_SYMHASH*)(_view.ptr + e.offset);
+		auto p = cast(void*)hash + CV_SYMHASH.sizeof;
+
+		_modules[0].symbols.Init(cast(CV_SYMBOL*)p, p + hash.symInfoSize);
+	}
+
+	void ParseSrcModule(in CV_ENTRY* e) {
+		if(e.modIndex == ushort.max || e.modIndex <= 0 || e.modIndex >= _modules.length)
+			throw new CodeViewCorruptedException(this);
+
+		if(e.modIndex > _maxSrcModule) _maxSrcModule = e.modIndex;
+
+		auto src = cast(CV_SRCMODULE*)(_view.ptr + e.offset);
+
+		with(_modules[e.modIndex].src) {
+			data = src;
+			fileOffsets = src.fileOffsets;
+			codeOffsets = src.codeOffsets;
+			segmentIds = src.segmentIds;
+		}
+	}
+
+	void ParseGlobalTypes(in CV_ENTRY* e) {
+		if(e.modIndex != ushort.max) throw new CodeViewCorruptedException(this);
+
+		// TODO: this currently crash stuff randomly
+		/*auto header = cast(CV_GLOBALTYPES*)(_view.ptr + e.offset);
+		_types.Init(header, cast(void*)header + e.size);*/
+	}
+
+	void CheckOffset(int offset) {
+		if(offset > _view.length) throw new CodeViewCorruptedException(this);
+	}
+
+	const(void)[]	_view;
+
+	CvModule[]		_modules;
+	uint			_maxSymModule;
+	uint			_maxSrcModule;
+	string[]		_libraries;
+	CvTypes			_types;
+}
+
+abstract class CodeViewException : Exception {
+	this(string msg) {
+		super(msg);
+	}
+}
+
+class CodeViewUnsupportedException : CodeViewException {
+	this(in CodeViewDebugInfo cv) {
+		super("CodeView version unsupported.");
+	}
+}
+
+class CodeViewCorruptedException : CodeViewException {
+	this(in CodeViewDebugInfo cv) {
+		super("Corrupted CodeView data.");
+	}
+}
+
+private:
+alias int cmp_t;
+uint BinarySearch(scope cmp_t delegate(uint i) dg, uint low, uint high) {
+	if(high < low) return uint.max;
+
+	uint mid = low + ((high - low) / 2);
+	cmp_t cmp = dg(mid);
+
+	if(cmp > 0) return BinarySearch(dg, low, mid - 1);
+	if(cmp < 0) return BinarySearch(dg, mid + 1, high);
+	return mid;
+}
+
+uint BinarySearch(in uint[] a, uint value, uint low, uint high) {
+	if(high < low) return uint.max;
+
+	uint mid = low + ((high - low) / 2);
+
+	if(a[mid] > value) return BinarySearch(a, value, low, mid - 1);
+	if(a[mid] < value) return BinarySearch(a, value, mid + 1, high);
+	return mid;
+}
+
+struct CvModule {
+	ushort			overlay;
+	ushort			lib;
+	CV_SEGMENT[]	segments;
+	string			name;
+
+	CvSymbols		symbols;
+	CvSrcModule		src;
+}
+
+struct CvSymbols {
+	ubyte		compileMachine;
+	ubyte		compileLanguage;
+	ushort		compileFlags;
+	string		compileName;
+	ushort		segment;
+
+	CvProc[]	procSymbols;
+	CvData[]	codeSymbols;
+
+	void Init(const(CV_SYMBOL)* sym, in void* end) {
+		int i = 0;
+		while(sym < end && i < 100) {
+			++i;
+			switch(sym.header.type) {
+			case S_COMPILE_V1:
+				with(sym.compile_v1) {
+					compileMachine = machine;
+					compileLanguage = language;
+					compileFlags = flags;
+					compileName = name.name;
+				}
+				break;
+
+			case S_SSEARCH_V1:
+				if(!segment) segment = sym.ssearch.segment;
+				break;
+
+			case S_UDT_V1:
+				break;
+
+			case S_BPREL_V1:
+				break;
+
+			case S_LDATA_V1:
+			case S_GDATA_V1:
+			case S_PUB_V1:
+				CvData data = void;
+
+				with(sym.data_v1) {
+					// TODO: its bad to assume 2 to always be the only code segment!
+					if(segment != 2) break;
+
+					data.offset = offset;
+					data.name = name.name;
+				}
+
+				codeSymbols ~= data;
+				break;
+
+			case S_LPROC_V1:
+			case S_GPROC_V1:
+				CvProc proc = void;
+
+				with(sym.proc_v1) {
+					proc.offset = offset;
+					proc.length = procLength;
+					proc.name = name.name;
+				}
+
+				procSymbols ~= proc;
+				break;
+
+			case S_PROCREF_V1:
+			case S_DATAREF_V1:
+			case S_ALIGN_V1:
+				break;
+
+			case S_END_V1:
+			case S_ENDARG_V1:
+			case S_RETURN_V1:
+				break;
+
+			default:
+			}
+
+			sym = cast(CV_SYMBOL*)(cast(void*)sym + sym.header.size + 2);
+		}
+
+		codeSymbols.sort;
+	}
+
+	bool QueryProc(uint rva, SymbolInfo* symbol) const {
+		if(!procSymbols.length) return false;
+
+		cmp_t CmpProc(uint i) {
+			if(i >= procSymbols.length) return 0;
+
+			uint offset = procSymbols[i].offset;
+			if(offset > rva) return 1;
+			if(offset + procSymbols[i].length < rva) return -1;
+			return 0;
+		}
+
+		uint index = BinarySearch(&CmpProc, 0, procSymbols.length - 1);
+
+		if(index < procSymbols.length) with(procSymbols[index]) {
+			symbol.name = name.idup;
+			symbol.offset = rva - offset;
+			return true;
+		}
+
+		return false;
+	}
+
+	bool QueryCodeData(uint rva, SymbolInfo* symbol) const {
+		if(!codeSymbols.length) return false;
+
+		cmp_t CmpData(uint i) {
+			if(i >= codeSymbols.length) return 0;
+
+			if(codeSymbols[i].offset > rva) return 1;
+			if(i + 1 != codeSymbols.length && codeSymbols[i + 1].offset < rva) return -1;
+			return 0;
+		}
+
+		uint index = BinarySearch(&CmpData, 0, codeSymbols.length - 1);
+
+		if(index < codeSymbols.length) with(codeSymbols[index]) {
+			symbol.name = name.idup;
+			symbol.offset = rva - offset;
+			return true;
+		}
+
+		return false;
+	}
+}
+
+struct CvProc {
+	uint	offset;
+	uint	length;
+	string	name;
+}
+
+struct CvData {
+	uint offset;
+	string name;
+
+	cmp_t opCmp(ref const CvData data) const {
+		if(data.offset < offset) return -1;
+		return data.offset > offset;
+	}
+}
+
+struct CvSrcModule {
+	bool Query(uint rva, FileLineInfo* fileLine) const {
+		if(!codeOffsets.length || rva < codeOffsets[0][0] || rva > codeOffsets[$ - 1][1])
+			return false;
+
+		uint fIndex;
+
+		// Get the next CV_SRCFILE record having rva within it's code range
+		// The code offsets here may overlap over file records, we have to walk
+		// through them and possibly keep walking if the next section doesn't
+		// find a matching line record.
+	NextFile:
+		if(fIndex == fileOffsets.length) return false;
+
+		CV_SRCFILE* srcFile = cast(CV_SRCFILE*)(data + fileOffsets[fIndex++]);
+		uint[2][] offsets = srcFile.codeOffsets;
+
+		if(rva < offsets[0][0] || rva > offsets[$ - 1][1])
+			goto NextFile;
+
+		CV_SRCSEGMENT* srcSeg;
+
+		// Address is possibly within this file, now get the CV_SEGMENT record.
+		cmp_t CmpFile(uint i) {
+			if(i >= offsets.length) return 0;
+
+			if(offsets[i][0] > rva) return 1;
+			if(offsets[i][1] < rva) return -1;
+
+			srcSeg = cast(CV_SRCSEGMENT*)(data + srcFile.lineOffsets[i]);
+			return 0;
+		}
+
+		// Ignore the return value from BinarySearch, if CmpSegment matched, we
+		// already have srcSeg set. In some rare cases there may not be a
+		// matching segment record even if the file's segment range said so.
+		BinarySearch(&CmpFile, 0, offsets.length - 1);
+		if(!srcSeg) goto NextFile;
+
+		// Finally look within the segment's offsets for a matching record.
+		uint[] segOffsets = srcSeg.offsets;
+		ushort[] lineNumbers = srcSeg.lineNumbers;
+
+		cmp_t CmpSegment(uint i) {
+			if(i >= segOffsets.length) return 0;
+
+			if(segOffsets[i] > rva) return 1;
+			if(i + 1 < segOffsets.length && segOffsets[i + 1] < rva) return -1;
+
+			return 0;
+		}
+
+		uint sIndex = BinarySearch(&CmpSegment, 0, segOffsets.length - 1);
+		if(sIndex >= lineNumbers.length) goto NextFile;
+
+		// Found our record
+		fileLine.file = srcFile.name.name.idup;
+		fileLine.line = srcSeg.lineNumbers[sIndex];
+
+		return true;
+	}
+
+	const(void)*		data;
+	const(uint)[]		fileOffsets;
+	const(uint[2])[]	codeOffsets;
+	const(ushort)[]		segmentIds;
+}
+
+// TODO!
+struct CvTypes {
+	void Init(in CV_GLOBALTYPES* gtypes, in void* end) {
+		debug(CodeView) TraceA("CvTypes[%p].Init(gtypes=%p, end=%p)",
+			&this, gtypes, end);
+
+		offsets = gtypes.typeOffsets[0 .. gtypes.nTypes].idup;
+
+		void* dataStart = gtypes.types;
+		data = dataStart[0 .. end - dataStart].idup;
+	}
+
+	void GetType(ushort index) {
+		/+
+		CheckOffset(typeOffsets[index]);
+
+		CV_TYPE* type = cast(CV_TYPE*)(p + typeOffsets[i]);
+
+		switch(type.header.type) {
+		case LF_MODIFIER_V1:
+			break;
+
+		case LF_POINTER_V1:
+			break;
+
+		case LF_ARRAY_V1:
+			break;
+
+		case LF_CLASS_V1:
+			break;
+
+		case LF_STRUCTURE_V1:
+			break;
+
+		case LF_UNION_V1:
+			break;
+
+		case LF_ENUM_V1:
+			break;
+
+		case LF_PROCEDURE_V1:
+			break;
+
+		case LF_MFUNCTION_V1:
+			break;
+
+		case LF_VTSHAPE_V1:
+			break;
+
+		case LF_OEM_V1:
+			with(type.oem_v1) {
+				// Ignore unknown OEMs
+				if(oem != OEM_DIGITALMARS || nIndices != 2) break;
+
+				switch(rec) {
+				case D_DYN_ARRAY:
+					break;
+
+				case D_ASSOC_ARRAY:
+					break;
+
+				case D_DELEGATE:
+					break;
+
+				default:
+				}
+			}
+			break;
+
+		case LF_ARGLIST_V1:
+			break;
+
+		case LF_FIELDLIST_V1:
+			break;
+
+		case LF_DERIVED_V1:
+			break;
+
+		case LF_METHODLIST_V1:
+			break;
+
+		default:
+			TraceA("New leaf %x", cast(uint)type.header.type);
+			Pause;
+		}
+		+/
+	}
+
+	const(uint)[]	offsets;
+	const(void)[]	data;
+}
+
+// ----------------------------------------------------------------------------
+// O M F  S t r u c t u r e s
+// ----------------------------------------------------------------------------
+
+align(1):
+
+/**
+ Packed variant header
+*/
+struct OMF_HEADER {
+	short size;
+	short type;
+}
+
+/**
+ Packed name, may be 0 padded to maintain alignment
+*/
+struct OMF_NAME {
+	ubyte len;
+	//char[1] name;
+
+	string name() const {
+		return (cast(immutable(char)*)(&len + 1))[0 .. len];
+	}
+}
+
+// ----------------------------------------------------------------------------
+// C o d e V i e w  C o m m o n  S t r u c t u r e s
+// ----------------------------------------------------------------------------
+
+/**
+ Version signatures
+*/
+enum : uint {
+	CV_SIGNATURE_NB09	= 0x3930424E,	/// CodeView 4.10
+	CV_SIGNATURE_NB11	= 0x3131424E,	/// CodeView 5.0
+	CV_SIGNATURE_NB10	= 0x3130424E,	/// CodeView PDB 2.0
+	CV_SIGNATURE_RSDS	= 0x53445352	/// CodeView PDB 7.0
+}
+
+/**
+ SubSection Types
+*/
+enum : ushort {
+	sstModule 		= 0x0120,
+	sstTypes 		= 0x0121,
+	sstPublic 		= 0x0122,
+	sstPublicSym 	= 0x0123,
+	sstSymbols 		= 0x0124,
+	sstAlignSym 	= 0x0125,
+	sstSrcLnSeg 	= 0x0126,
+	sstSrcModule 	= 0x0127,
+	sstLibraries 	= 0x0128,
+	sstGlobalSym 	= 0x0129,
+	sstGlobalPub 	= 0x012A,
+	sstGlobalTypes 	= 0x012B,
+	sstMPC 			= 0x012C,
+	sstSegMap 		= 0x012D,
+	sstSegName 		= 0x012E,
+	sstPreComp 		= 0x012F,
+	sstPreCompMap 	= 0x0130,
+	sstOffsetMap16 	= 0x0131,
+	sstOffsetMap32 	= 0x0132,
+	sstFileIndex 	= 0x0133,
+	sstStaticSym 	= 0x0134
+}
+
+/**
+ Header used with "NB09" and "NB11"
+*/
+struct CV_HEADER {
+	uint	signature;
+	int		offset;
+}
+
+/**
+ Header used with "NB10"
+*/
+struct CV_HEADER_NB10 {
+	uint			signature;
+	int				offset;
+	uint			timestamp;
+	uint			age;
+	OMF_NAME		name;
+}
+
+/**
+ Header used with "RSDS"
+*/
+/*struct CV_HEADER_RSDS {
+	uint			signature;
+	GUID			guid;
+	uint			age;
+	OMF_NAME		name;
+}*/
+
+/**
+ Directory header
+*/
+struct CV_DIRECTORY {
+	ushort			dirSize;
+	ushort			entrySize;
+	uint			nEntries;
+	int				offset;
+	uint			flags;
+	//CV_ENTRY[1]	entries;
+
+	CV_ENTRY[] entries() const {
+		return (cast(CV_ENTRY*)(&this + 1))[0 .. nEntries];
+	}
+}
+
+/**
+ Subsection record
+*/
+struct CV_ENTRY {
+	ushort			sst;
+	ushort			modIndex;
+	int				offset;
+	uint			size;
+}
+
+// ----------------------------------------------------------------------------
+// sstModule
+// ----------------------------------------------------------------------------
+
+/**
+ Module style, always "CV"
+*/
+enum CV_MOD_STYLE = 0x5643;
+
+/**
+ Module
+*/
+struct CV_MODULE {
+	ushort			overlay;
+	ushort			lib;
+	ushort			nSegments;
+	ushort			style;
+	//CV_SEGMENT[1]	segments;
+	//OMF_NAME		name;
+
+	CV_SEGMENT[] segments() const {
+		return (cast(CV_SEGMENT*)(&style + 1))[0 .. nSegments];
+	}
+
+	OMF_NAME name() const {
+		return *cast(OMF_NAME*)(cast(void*)segments + nSegments * CV_SEGMENT.sizeof);
+	}
+}
+
+/**
+ Module segment
+*/
+struct CV_SEGMENT {
+	ushort			segIndex;
+	ushort			padding;
+	uint			offset;
+	uint			size;
+}
+
+// ----------------------------------------------------------------------------
+// sstGlobalPub, sstStaticSym, sstGlobalSym, sstAlignSym
+// ----------------------------------------------------------------------------
+
+/**
+ Symbol IDs, used by CV_SYMBOL.header.type
+*/
+enum : ushort {
+	S_COMPILE_V1	= 0x0001,
+	S_REGISTER_V1	= 0x0002,
+	S_CONSTANT_V1	= 0x0003,
+	S_UDT_V1		= 0x0004,
+	S_SSEARCH_V1	= 0x0005,
+	S_END_V1		= 0x0006,
+	S_SKIP_V1		= 0x0007,
+	S_CVRESERVE_V1	= 0x0008,
+	S_OBJNAME_V1	= 0x0009,
+	S_ENDARG_V1		= 0x000A,
+	S_COBOLUDT_V1	= 0x000B,
+	S_MANYREG_V1	= 0x000C,
+	S_RETURN_V1		= 0x000D,
+	S_ENTRYTHIS_V1	= 0x000E,
+
+	S_BPREL_V1 		= 0x0200,
+	S_LDATA_V1 		= 0x0201,
+	S_GDATA_V1 		= 0x0202,
+	S_PUB_V1 		= 0x0203,
+	S_LPROC_V1 		= 0x0204,
+	S_GPROC_V1 		= 0x0205,
+	S_THUNK_V1 		= 0x0206,
+	S_BLOCK_V1 		= 0x0207,
+	S_WITH_V1 		= 0x0208,
+	S_LABEL_V1 		= 0x0209,
+	S_CEXMODEL_V1 	= 0x020A,
+	S_VFTPATH_V1 	= 0x020B,
+	S_REGREL_V1 	= 0x020C,
+	S_LTHREAD_V1 	= 0x020D,
+	S_GTHREAD_V1 	= 0x020E,
+
+	S_PROCREF_V1	= 0x0400,
+	S_DATAREF_V1	= 0x0401,
+	S_ALIGN_V1		= 0x0402,
+	S_LPROCREF_V1	= 0x0403,
+
+	// Variants with 32bit type indices
+	S_REGISTER_V2	= 0x1001,	/// CV_REGISTER_V2
+	S_CONSTANT_V2	= 0x1002,	/// CV_CONSTANT_V2
+	S_UDT_V2		= 0x1003,	/// CV_UDT_V2
+	S_COBOLUDT_V2	= 0x1004,
+	S_MANYREG_V2	= 0x1005,
+	S_BPREL_V2		= 0x1006,	/// CV_BPREL_V2
+	S_LDATA_V2		= 0x1007,	/// CV_DATA_V2
+	S_GDATA_V2		= 0x1008,	/// CV_DATA_V2
+	S_PUB_V2		= 0x1009,	/// CV_DATA_V2
+	S_LPROC_V2		= 0x100A,	/// CV_PROC_V2
+	S_GPROC_V2		= 0x100B,	/// CV_PROC_V2
+	S_VFTTABLE_V2	= 0x100C,
+	S_REGREL_V2		= 0x100D,
+	S_LTHREAD_V2	= 0x100E,
+	S_GTHREAD_V2	= 0x100F,
+	S_FUNCINFO_V2	= 0x1012,
+	S_COMPILAND_V2	= 0x1013,	/// CV_COMPILE_V2
+
+	S_COMPILAND_V3	= 0x1101,
+	S_THUNK_V3		= 0x1102,
+	S_BLOCK_V3		= 0x1103,
+	S_LABEL_V3		= 0x1105,
+	S_REGISTER_V3	= 0x1106,
+	S_CONSTANT_V3	= 0x1107,
+	S_UDT_V3		= 0x1108,
+	S_BPREL_V3		= 0x110B,
+	S_LDATA_V3		= 0x110C,
+	S_GDATA_V3		= 0x110D,
+	S_PUB_V3		= 0x110E,
+	S_LPROC_V3		= 0x110F,
+	S_GPROC_V3		= 0x1110,
+	S_BPREL_XXXX_V3	= 0x1111,  /* not really understood, but looks like bprel... */
+	S_MSTOOL_V3		= 0x1116,  /* compiler command line options and build information */
+	S_PUB_FUNC1_V3	= 0x1125,  /* didn't get the difference between the two */
+	S_PUB_FUNC2_V3	= 0x1127,
+	S_SECTINFO_V3	= 0x1136,
+	S_SUBSECTINFO_V3= 0x1137,
+	S_ENTRYPOINT_V3	= 0x1138,
+	S_SECUCOOKIE_V3	= 0x113A,
+	S_MSTOOLINFO_V3	= 0x113C,
+	S_MSTOOLENV_V3	= 0x113D
+}
+
+/**
+ Packed symbols header
+*/
+struct CV_SYMHASH {
+	ushort			symIndex;
+	ushort			addrIndex;
+	uint			symInfoSize;
+	uint			symHashSize;
+	uint			addrHashSize;
+}
+
+/**
+ Symbol variant record
+*/
+struct CV_SYMBOL {
+	OMF_HEADER			header;
+	union {
+		CV_COMPILE_V1	compile_v1;
+		CV_COMPILE_V2	compile_v2;
+		CV_REGISTER_V1	register_v1;
+		CV_REGISTER_V2	register_v2;
+		CV_CONSTANT_V1	constant_v1;
+		CV_CONSTANT_V2	constant_v2;
+		CV_UDT_V1		udt_v1;
+		CV_UDT_V2		udt_v2;
+		CV_SSEARCH		ssearch;
+		CV_STACK_V1		stack_v1;
+		CV_STACK_V2		stack_v2;
+		CV_DATA_V1		data_v1;
+		CV_DATA_V2		data_v2;
+		CV_PROC_V1		proc_v1;
+		CV_PROC_V2		proc_v2;
+		CV_THUNK		thunk;
+		CV_BLOCK		block;
+		CV_LABEL		label;
+	}
+}
+
+/**
+ Compiler information symbol
+*/
+struct CV_COMPILE_V1 {
+	ubyte			machine;
+	ubyte			language;
+	ushort			flags;
+	OMF_NAME		name;
+}
+struct CV_COMPILE_V2 {
+	uint[4]			unknown1;
+	ushort			unknown2;
+	OMF_NAME		name;
+}
+
+/**
+ Register data symbol
+*/
+struct CV_REGISTER_V1 {
+	ushort			typeIndex;
+	ushort			reg;
+	OMF_NAME		name;
+}
+struct CV_REGISTER_V2 {
+	uint			typeIndex;
+	ushort			reg;
+	OMF_NAME		name;
+}
+
+/**
+ Constant data symbol
+*/
+struct CV_CONSTANT_V1 {
+	ushort			typeIndex;
+	ushort			value;
+	OMF_NAME		name;
+}
+struct CV_CONSTANT_V2 {
+	uint			typeIndex;
+	ushort			value;
+	OMF_NAME		name;
+}
+
+/**
+ User defined type Symbol
+*/
+struct CV_UDT_V1 {
+	ushort			typeIndex;
+	OMF_NAME		name;
+}
+struct CV_UDT_V2 {
+	uint			typeIndex;
+	OMF_NAME		name;
+}
+
+/**
+ Start of Search symbol
+*/
+struct CV_SSEARCH {
+	uint			offset;
+	ushort			segment;
+}
+
+/**
+ Object name symbol
+*/
+struct CV_OBJNAME {
+	uint			signature;
+	OMF_NAME		name;
+}
+
+/**
+ Stack data symbol
+*/
+struct CV_STACK_V1 {
+	uint			offset;
+	ushort			typeIndex;
+	OMF_NAME		name;
+}
+struct CV_STACK_V2 {
+	uint			offset;
+	uint			typeIndex;
+	OMF_NAME		name;
+}
+
+/**
+ Data symbol
+*/
+struct CV_DATA_V1 {
+	uint			offset;
+	short			segment;
+	short			typeIndex;
+	OMF_NAME		name;
+}
+struct CV_DATA_V2 {
+	uint			typeIndex;
+	uint			offset;
+	short			segment;
+	OMF_NAME		name;
+}
+
+/**
+ Procedure symbol
+*/
+struct CV_PROC_V1 {
+	uint			parent;
+	uint			end;
+	uint			next;
+	uint			procLength;
+	uint			dbgStart;
+	uint			dbgEnd;
+	uint			offset;
+	ushort			segment;
+	ushort			procType;
+	ubyte			flags;
+	OMF_NAME		name;
+}
+struct CV_PROC_V2 {
+	uint			parent;
+	uint			end;
+	uint			next;
+	uint			procLength;
+	uint			dbgStart;
+	uint			dbgEnd;
+	uint			procType;
+	uint			offset;
+	ushort			segment;
+	ubyte			flags;
+	OMF_NAME		name;
+}
+
+/**
+ Thunk symbol
+*/
+struct CV_THUNK {
+	uint 			parent;
+	uint			end;
+	uint			next;
+	uint			offset;
+	ushort			segment;
+	ushort			size;
+	ubyte			type;
+	OMF_NAME		name;
+}
+
+/**
+ Block symbol
+*/
+struct CV_BLOCK {
+	uint			parent;
+	uint			end;
+	uint			length;
+	uint			offset;
+	ushort			segment;
+	OMF_NAME		name;
+}
+
+/**
+ Label symbol
+*/
+struct CV_LABEL {
+	uint			offset;
+	ushort			segment;
+	ubyte			flags;
+	OMF_NAME		name;
+}
+
+// ----------------------------------------------------------------------------
+// sstSrcModule
+// ----------------------------------------------------------------------------
+
+/**
+ Source module header
+*/
+struct CV_SRCMODULE {
+	ushort			nFiles;			/// number of CV_SRCFILE records
+	ushort			nSegments;		/// number of segments in module
+	//uint[]		fileOffsets;
+	//uint[2][]		codeOffsets;
+	//ushort[]		segmentIds;
+
+	/// array of offsets to every CV_SRCFILE record
+	uint[] fileOffsets() const {
+		return (cast(uint*)(&nSegments + 1))[0 .. nFiles];
+	}
+
+	/// array of segment start/end pairs, length = nSegments
+	uint[2][] codeOffsets() const {
+		return (cast(uint[2]*)(cast(void*)fileOffsets + nFiles * uint.sizeof))[0 .. nSegments];
+	}
+
+	/// array of linker indices, length = nSegments
+	ushort[] segmentIds() const {
+		return (cast(ushort*)(cast(void*)codeOffsets + nSegments * (uint[2]).sizeof))[0 .. nSegments];
+	}
+}
+
+/**
+ Source file record
+*/
+struct CV_SRCFILE {
+	ushort			nSegments;		/// number of CV_SRCSEGMENT records
+	ushort			reserved;
+	//uint[]		lineOffsets;
+	//uint[2][]		codeOffsets;
+	//OMF_NAME		name;
+
+	// array of offsets to every CV_SRCSEGMENT record, length = nSegments
+	uint[] lineOffsets() const {
+		return (cast(uint*)(&reserved + 1))[0 .. nSegments];
+	}
+
+	/// array of segment start/end pairs, length = nSegments
+	uint[2][] codeOffsets() const {
+		return (cast(uint[2]*)(cast(void*)lineOffsets + nSegments * uint.sizeof))[0 .. nSegments];
+	}
+
+	/// name of file padded to long boundary
+	OMF_NAME* name() const {
+		return cast(OMF_NAME*)(cast(void*)codeOffsets + nSegments * (uint[2]).sizeof);
+	}
+}
+
+/**
+ Source segment record
+*/
+struct CV_SRCSEGMENT {
+	ushort			segment;		/// linker segment index
+	ushort			nPairs;			/// count of line/offset pairs
+	//uint[]		offsets;
+	//ushort[]		lineNumbers;
+
+	/// array of offsets in segment, length = nPairs
+	uint[] offsets() const {
+		return (cast(uint*)(&nPairs + 1))[0 .. nPairs];
+	}
+
+	/// array of line lumber in source, length = nPairs
+	ushort[] lineNumbers() const {
+		return (cast(ushort*)(cast(void*)offsets + nPairs * uint.sizeof))[0 .. nPairs];
+	}
+}
+
+// ----------------------------------------------------------------------------
+// sstGlobalTypes
+// ----------------------------------------------------------------------------
+
+/**
+ Basic types
+
+ Official MS documentation says that type (< 0x4000, so 12 bits) is made of:
+
+ +----------+------+------+----------+------+
+ |    11    | 10-8 | 7-4  |     3    | 2-0  |
+ +----------+------+------+----------+------+
+ | reserved | mode | type | reserved | size |
+ +----------+------+------+----------+------+
+*/
+
+/**
+ Basic type: Type bits
+*/
+enum : ubyte {
+	T_SPECIAL_BITS		= 0x00,	/// Special
+	T_SIGNED_BITS		= 0x10, /// Signed integral value
+	T_UNSIGNED_BITS		= 0x20, /// Unsigned integral value
+	T_BOOLEAN_BITS		= 0x30, /// Boolean
+	T_REAL_BITS			= 0x40, /// Real
+	T_COMPLEX_BITS		= 0x50, /// Complex
+	T_SPECIAL2_BITS		= 0x60, /// Special2
+	T_INT_BITS			= 0x70, /// Real int value
+}
+
+/**
+ Basic type: Size bits
+*/
+enum : ubyte {
+	// Special types
+	T_NOTYPE_BITS		= 0x00, /// No type
+	T_ABS_BITS			= 0x01, /// Absolute symbol
+	T_SEGMENT_BITS		= 0x02, /// Segment
+	T_VOID_BITS			= 0x03, /// Void
+	T_CURRENCY_BITS		= 0x04, /// Basic 8-byte currency value
+	T_NBASICSTR_BITS	= 0x05, /// Near Basic string
+	T_FBASICSTR_BITS	= 0x06, /// Far Basic string
+	T_NOTRANS_BITS		= 0x07, /// Untranslated type from previous Microsoft symbol formats
+
+	// Signed/Unsigned/Boolean types
+	T_INT08_BITS		= 0x00, /// 1 byte
+	T_INT16_BITS		= 0x01, /// 2 byte
+	T_INT32_BITS		= 0x02, /// 4 byte
+	T_INT64_BITS		= 0x03, /// 8 byte
+
+	// Real/Complex types
+	T_REAL32_BITS		= 0x00, /// 32 bit
+	T_REAL64_BITS		= 0x01, /// 64 bit
+	T_REAL80_BITS		= 0x02, /// 80 bit
+	T_REAL128_BITS		= 0x03, /// 128 bit
+	T_REAL48_BITS		= 0x04, /// 48 bit
+
+	// Special2 types
+	T_BIT_BITS			= 0x00, /// Bit
+	T_PASCHAR_BITS		= 0x01, /// Pascal CHAR
+
+	// Real Int types
+	T_CHAR_BITS			= 0x00, /// Char
+	T_WCHAR_BITS		= 0x01, /// Wide character
+	T_INT2_BITS			= 0x02, /// 2-byte signed integer
+	T_UINT2_BITS		= 0x03, /// 2-byte unsigned integer
+	T_INT4_BITS			= 0x04, /// 4-byte signed integer
+	T_UINT4_BITS		= 0x05, /// 4-byte unsigned integer
+	T_INT8_BITS			= 0x06, /// 8-byte signed integer
+	T_UINT8_BITS		= 0x07, /// 8-byte unsigned integer
+	T_DCHAR_BITS		= 0x08, /// dchar, DigitalMars D extension
+}
+
+/**
+ Basic type: Mode bits
+*/
+enum : ushort {
+	T_DIRECT_BITS		= 0x0000, /// Direct; not a pointer
+	T_NEARPTR_BITS		= 0x0100, /// Near pointer
+	T_FARPTR_BITS		= 0x0200, /// Far pointer
+	T_HUGEPTR_BITS		= 0x0300, /// Huge pointer
+	T_NEAR32PTR_BITS	= 0x0400, /// 32-bit near pointer
+	T_FAR32PTR_BITS		= 0x0500, /// 32-bit far pointer
+	T_NEAR64PTR_BITS	= 0x0600, /// 64-bit near pointer
+}
+
+/**
+ Basic type bit masks
+*/
+enum : ushort {
+	T_TYPE_MASK			= 0x00F0, /// type type mask (data treatment mode)
+	T_SIZE_MASK			= 0x000F, /// type size mask (depends on 'type' value)
+	T_MODE_MASK			= 0x0700, /// type mode mask (ptr/non-ptr)
+}
+
+/**
+ Leaf types, used by CV_TYPE.header.type
+*/
+enum : ushort {
+	// Can be referenced from symbols
+	LF_MODIFIER_V1		= 0x0001,
+	LF_POINTER_V1		= 0x0002,
+	LF_ARRAY_V1			= 0x0003,
+	LF_CLASS_V1			= 0x0004,
+	LF_STRUCTURE_V1		= 0x0005,
+	LF_UNION_V1			= 0x0006,
+	LF_ENUM_V1			= 0x0007,
+	LF_PROCEDURE_V1		= 0x0008,
+	LF_MFUNCTION_V1		= 0x0009,
+	LF_VTSHAPE_V1		= 0x000A,
+	LF_COBOL0_V1		= 0x000B,
+	LF_COBOL1_V1		= 0x000C,
+	LF_BARRAY_V1		= 0x000D,
+	LF_LABEL_V1			= 0x000E,
+	LF_NULL_V1			= 0x000F,
+	LF_NOTTRAN_V1		= 0x0010,
+	LF_DIMARRAY_V1		= 0x0011,
+	LF_VFTPATH_V1		= 0x0012,
+	LF_PRECOMP_V1		= 0x0013,
+	LF_ENDPRECOMP_V1	= 0x0014,
+	LF_OEM_V1			= 0x0015,
+	LF_TYPESERVER_V1	= 0x0016,
+
+	LF_MODIFIER_V2		= 0x1001,
+	LF_POINTER_V2		= 0x1002,
+	LF_ARRAY_V2			= 0x1003,
+	LF_CLASS_V2			= 0x1004,
+	LF_STRUCTURE_V2		= 0x1005,
+	LF_UNION_V2			= 0x1006,
+	LF_ENUM_V2			= 0x1007,
+	LF_PROCEDURE_V2		= 0x1008,
+	LF_MFUNCTION_V2		= 0x1009,
+	LF_COBOL0_V2		= 0x100A,
+	LF_BARRAY_V2		= 0x100B,
+	LF_DIMARRAY_V2		= 0x100C,
+	LF_VFTPATH_V2		= 0x100D,
+	LF_PRECOMP_V2		= 0x100E,
+	LF_OEM_V2			= 0x100F,
+
+	// Can be referenced from other type records
+	LF_SKIP_V1			= 0x0200,
+	LF_ARGLIST_V1		= 0x0201,
+	LF_DEFARG_V1		= 0x0202,
+	LF_LIST_V1			= 0x0203,
+	LF_FIELDLIST_V1		= 0x0204,
+	LF_DERIVED_V1		= 0x0205,
+	LF_BITFIELD_V1		= 0x0206,
+	LF_METHODLIST_V1	= 0x0207,
+	LF_DIMCONU_V1		= 0x0208,
+	LF_DIMCONLU_V1		= 0x0209,
+	LF_DIMVARU_V1		= 0x020A,
+	LF_DIMVARLU_V1		= 0x020B,
+	LF_REFSYM_V1		= 0x020C,
+
+	LF_SKIP_V2			= 0x1200,
+	LF_ARGLIST_V2		= 0x1201,
+	LF_DEFARG_V2		= 0x1202,
+	LF_FIELDLIST_V2		= 0x1203,
+	LF_DERIVED_V2		= 0x1204,
+	LF_BITFIELD_V2		= 0x1205,
+	LF_METHODLIST_V2	= 0x1206,
+	LF_DIMCONU_V2		= 0x1207,
+	LF_DIMCONLU_V2		= 0x1208,
+	LF_DIMVARU_V2		= 0x1209,
+	LF_DIMVARLU_V2		= 0x120A,
+
+	// Field lists
+	LF_BCLASS_V1		= 0x0400,
+	LF_VBCLASS_V1		= 0x0401,
+	LF_IVBCLASS_V1		= 0x0402,
+	LF_ENUMERATE_V1		= 0x0403,
+	LF_FRIENDFCN_V1		= 0x0404,
+	LF_INDEX_V1			= 0x0405,
+	LF_MEMBER_V1		= 0x0406,
+	LF_STMEMBER_V1		= 0x0407,
+	LF_METHOD_V1		= 0x0408,
+	LF_NESTTYPE_V1		= 0x0409,
+	LF_VFUNCTAB_V1		= 0x040A,
+	LF_FRIENDCLS_V1		= 0x040B,
+	LF_ONEMETHOD_V1		= 0x040C,
+	LF_VFUNCOFF_V1		= 0x040D,
+	LF_NESTTYPEEX_V1	= 0x040E,
+	LF_MEMBERMODIFY_V1	= 0x040F,
+
+	LF_BCLASS_V2		= 0x1400,
+	LF_VBCLASS_V2		= 0x1401,
+	LF_IVBCLASS_V2		= 0x1402,
+	LF_FRIENDFCN_V2		= 0x1403,
+	LF_INDEX_V2			= 0x1404,
+	LF_MEMBER_V2		= 0x1405,
+	LF_STMEMBER_V2		= 0x1406,
+	LF_METHOD_V2		= 0x1407,
+	LF_NESTTYPE_V2		= 0x1408,
+	LF_VFUNCTAB_V2		= 0x1409,
+	LF_FRIENDCLS_V2		= 0x140A,
+	LF_ONEMETHOD_V2		= 0x140B,
+	LF_VFUNCOFF_V2		= 0x140C,
+	LF_NESTTYPEEX_V2	= 0x140D,
+
+	LF_ENUMERATE_V3		= 0x1502,
+	LF_ARRAY_V3			= 0x1503,
+	LF_CLASS_V3			= 0x1504,
+	LF_STRUCTURE_V3		= 0x1505,
+	LF_UNION_V3			= 0x1506,
+	LF_ENUM_V3			= 0x1507,
+	LF_MEMBER_V3		= 0x150D,
+	LF_STMEMBER_V3		= 0x150E,
+	LF_METHOD_V3		= 0x150F,
+	LF_NESTTYPE_V3		= 0x1510,
+	LF_ONEMETHOD_V3		= 0x1511,
+
+	// Numeric leaf types
+	LF_NUMERIC			= 0x8000,
+	LF_CHAR				= 0x8000,
+	LF_SHORT			= 0x8001,
+	LF_USHORT			= 0x8002,
+	LF_LONG				= 0x8003,
+	LF_ULONG			= 0x8004,
+	LF_REAL32			= 0x8005,
+	LF_REAL64			= 0x8006,
+	LF_REAL80			= 0x8007,
+	LF_REAL128			= 0x8008,
+	LF_QUADWORD			= 0x8009,
+	LF_UQUADWORD		= 0x800A,
+	LF_REAL48			= 0x800B,
+	LF_COMPLEX32		= 0x800C,
+	LF_COMPLEX64		= 0x800D,
+	LF_COMPLEX80		= 0x800E,
+	LF_COMPLEX128		= 0x800F,
+	LF_VARSTRING		= 0x8010,
+	LF_DCHAR			= 0x8011
+}
+
+/**
+ Global types header
+*/
+struct CV_GLOBALTYPES {
+	ubyte[3]		unused;
+	ubyte			flags;
+	uint			nTypes;
+	//uint[1]		typeOffsets;
+	//CV_TYPE[1]	types;
+
+	/// array of offsets to CV_TYPE records
+	uint* typeOffsets() const {
+		return cast(uint*)(&nTypes + 1);
+	}
+
+	// Get the first CV_TYPE record
+	CV_TYPE* types() const {
+		return cast(CV_TYPE*)(cast(void*)(&nTypes + 1) + nTypes * uint.sizeof);
+	}
+}
+
+/**
+ Type variant record
+*/
+struct CV_TYPE {
+	OMF_HEADER			header;
+	union {
+		// Types
+		CV_MODIFIER_V1	modifier_v1;
+		CV_MODIFIER_V2	modifier_v2;
+		CV_POINTER_V1	pointer_v1;
+		CV_POINTER_V2	pointer_v2;
+		CV_ARRAY_V1		array_v1;
+		CV_ARRAY_V2		array_v2;
+		CV_STRUCT_V1	struct_v1;
+		CV_STRUCT_V2	struct_v2;
+		CV_UNION_V1		union_v1;
+		CV_UNION_V2		union_v2;
+		CV_ENUM_V1		enum_v1;
+		CV_ENUM_V2		enum_v2;
+		CV_PROCEDURE_V1	proc_v1;
+		CV_PROCEDURE_V2	proc_v2;
+		CV_MFUNCTION_V1	method_v1;
+		CV_MFUNCTION_V2	method_v2;
+		CV_OEM_V1		oem_v1;
+		CV_OEM_V2		oem_v2;
+
+		// Referenced types
+		CV_FIELDLIST	fieldlist;
+		CV_BITFIELD_V1	bitfield_v1;
+		CV_BITFIELD_V2	bitfield_v2;
+		CV_ARGLIST_V1	arglist_v1;
+		CV_ARGLIST_V2	arglist_v2;
+		CV_DERIVED_V1	derived_v1;
+		CV_DERIVED_V2	derived_v2;
+
+		// Field types
+	}
+}
+
+/**
+ Modifier type
+*/
+struct CV_MODIFIER_V1 {
+	ushort			attribute;
+	ushort			type;
+}
+struct CV_MODIFIER_V2 {
+	uint			type;
+	ushort			attribute;
+}
+
+/**
+ Pointer type
+*/
+struct CV_POINTER_V1 {
+	ushort			attribute;
+	ushort			type;
+	OMF_NAME		name;
+}
+struct CV_POINTER_V2 {
+	uint			type;
+	uint			attribute;
+	OMF_NAME		name;
+}
+
+/**
+ Array type
+*/
+struct CV_ARRAY_V1 {
+	ushort			elemType;
+	ushort			indexType;
+	ushort			length;		/// numeric leaf
+	OMF_NAME		name;
+}
+struct CV_ARRAY_V2 {
+	uint			elemType;
+	uint			indexType;
+	ushort			length;		/// numeric leaf
+	OMF_NAME		name;
+}
+
+/**
+ Struct type
+*/
+struct CV_STRUCT_V1 {
+	ushort			nElement;
+	ushort			fieldlist;
+	ushort			property;
+	ushort			derived;
+	ushort			vshape;
+	ushort			length;		/// numeric leaf
+	OMF_NAME		name;
+}
+struct CV_STRUCT_V2 {
+	ushort			nElement;
+	ushort			property;
+	uint			fieldlist;
+	uint			derived;
+	uint			vshape;
+	ushort			length;		/// numeric leaf
+	OMF_NAME		name;
+}
+
+/**
+ Union type
+*/
+struct CV_UNION_V1 {
+	ushort			count;
+	ushort			fieldlist;
+	ushort			property;
+	ushort			length;		/// numeric leaf
+	OMF_NAME		name;
+}
+struct CV_UNION_V2 {
+	ushort			count;
+	ushort			property;
+	uint			fieldlist;
+	ushort			length;		/// numeric leaf
+	OMF_NAME		name;
+}
+
+/**
+ Enumeration type
+*/
+struct CV_ENUM_V1 {
+	ushort			length;
+	ushort			id;
+	ushort			count;
+	ushort			type;
+	ushort			fieldlist;
+	ushort			property;
+	OMF_NAME		p_name;
+}
+struct CV_ENUM_V2 {
+	ushort			length;
+	ushort			id;
+	ushort			count;
+	ushort			property;
+	uint			type;
+	uint			fieldlist;
+	OMF_NAME		p_name;
+}
+
+/**
+ Procedure type
+*/
+struct CV_PROCEDURE_V1 {
+	ushort			retType;
+	ubyte			call;
+	ubyte			reserved;
+	ushort			nParams;
+	ushort			argList;
+}
+struct CV_PROCEDURE_V2 {
+	uint			retType;
+	ubyte			call;
+	ubyte			reserved;
+	ushort			nParams;
+	uint			argList;
+}
+
+/**
+ Method type
+*/
+struct CV_MFUNCTION_V1 {
+	ushort			retType;
+	ushort			classType;
+	ushort			thisType;
+	ubyte			call;
+	ubyte			reserved;
+	ushort			nParams;
+	ushort			arglist;
+	uint			thisAdjust;
+}
+struct CV_MFUNCTION_V2 {
+	uint			retType;
+	uint			classType;
+	uint			thisType;
+	ubyte			call;
+	ubyte			reserved;
+	ushort			nParams;
+	uint			arglist;
+	uint			thisAdjust;
+}
+
+/**
+ OEM type
+*/
+struct CV_OEM_V1 {
+	ushort			oem;
+	ushort			rec;
+	ushort			nIndices;
+	//ushort[1]		indices;
+
+	ushort* indices() const {
+		return cast(ushort*)(&nIndices + 1);
+	}
+}
+struct CV_OEM_V2 {
+	// UNKNOWN!
+}
+
+enum {
+	OEM_DIGITALMARS	= 0x0042,
+	D_DYN_ARRAY		= 0x0001,
+	D_ASSOC_ARRAY	= 0x0002,
+	D_DELEGATE		= 0x0003
+}
+
+struct CV_D_DYNARRAY {
+	ushort			indexType;
+	ushort			elemType;
+}
+
+struct CV_D_ASSOCARRAY {
+	ushort			keyType;
+	ushort			elemType;
+}
+
+struct CV_D_DELEGATE {
+	ushort			thisType;
+	ushort			funcType;
+}
+
+/**
+ Field list
+*/
+struct CV_FIELDLIST {
+	ubyte[1]		list;
+}
+
+/**
+ Bit field
+*/
+struct CV_BITFIELD_V1 {
+	ubyte			nBits;
+	ubyte			bitOffset;
+	ushort			type;
+}
+struct CV_BITFIELD_V2 {
+	uint			type;
+	ubyte			nBits;
+	ubyte			bitOffset;
+}
+
+/**
+ Arguments list
+*/
+struct CV_ARGLIST_V1 {
+	ushort			count;
+	ushort[1]		args;
+}
+struct CV_ARGLIST_V2 {
+	uint			count;
+	uint[1]			args;
+}
+
+/**
+ Derived
+*/
+struct CV_DERIVED_V1 {
+	ushort			count;
+	ushort[1]		derivedClasses;
+}
+struct CV_DERIVED_V2 {
+	uint			count;
+	uint[1]			derivedClasses;
+}
+
+/**
+ Class type
+*/
+struct CV_CLASS_V1 {
+	ushort			type;
+	ushort			attribute;
+	ushort			offset;		/// numeric leaf
+}
+struct CV_CLASS_V2 {
+	ushort			attribute;
+	uint			type;
+	ushort			offset;		/// numeric leaf
+}
+
+struct CvTypeClass {
+	ushort			count;
+	ushort			fieldList;
+	ushort			flags;
+	ushort			dList;
+	ushort			vShape;
+	// length
+	// name
+}
+
+// ----------------------------------------------------------------------------
+// sstSegMap
+// ----------------------------------------------------------------------------
+
+struct CV_SEGMAP {
+	ushort				total;
+	ushort				logical;
+	//CV_SEGMAPDESC[1]	descriptors;
+
+	CV_SEGMAPDESC* descriptors() const {
+		return cast(CV_SEGMAPDESC*)(&logical + 1);
+	}
+}
+
+struct CV_SEGMAPDESC {
+	ushort	flags;
+	ushort	overlay;
+	ushort	group;
+	ushort	frame;
+	ushort	name;
+	ushort	className;
+	uint	offset;
+	uint	size;
+}
+
+// ----------------------------------------------------------------------------
+// sstPreCompMap
+// ----------------------------------------------------------------------------
+
+struct OMFPreCompMap {
+	ushort			FirstType;		// first precompiled type index
+	ushort			cTypes;			// number of precompiled types
+	uint			signature;		// precompiled types signature
+	ushort			padding;
+	//CV_typ_t[]	map;			// mapping of precompiled types
+}
+
+// ----------------------------------------------------------------------------
+// sstOffsetMap16, sstOffsetMap32
+// ----------------------------------------------------------------------------
+
+struct OMFOffsetMap16 {
+	uint			csegment;	// Count of physical segments
+
+    // The next six items are repeated for each segment
+
+    //uint			crangeLog;	// Count of logical offset ranges
+    //ushort[]		rgoffLog;	// Array of logical offsets
+    //short[]		rgbiasLog;	// Array of logical->physical bias
+    //uint			crangePhys;	// Count of physical offset ranges
+    //ushort[]		rgoffPhys;	// Array of physical offsets
+    //short[]		rgbiasPhys;	// Array of physical->logical bias
+}
+
+struct OMFOffsetMap32 {
+	uint			csection;	// Count of physical sections
+
+    // The next six items are repeated for each section
+
+    //uint			crangeLog;	// Count of logical offset ranges
+    //uint[]		rgoffLog;	// Array of logical offsets
+    //int[]			rgbiasLog;	// Array of logical->physical bias
+    //uint			crangePhys;	// Count of physical offset ranges
+    //uint[]		rgoffPhys;	// Array of physical offsets
+    //int[]			rgbiasPhys;	// Array of physical->logical bias
+}
+
+// ----------------------------------------------------------------------------
+// sstFileIndex
+// ----------------------------------------------------------------------------
+
+struct OMFFileIndex {
+	ushort			cmodules;	// Number of modules
+	ushort			cfilerefs;	// Number of file references
+	//ushort[]		modulelist;	// Index to beginning of list of files
+								// for module i. (0 for module w/o files)
+	//ushort[]		cfiles;		// Number of file names associated
+								// with module i.
+	//uint[]		ulNames;	// Offsets from the beginning of this
+								// table to the file names
+	//char[]		Names;		// The length prefixed names of files
+}
+
+struct OMFMpcDebugInfo {
+	ushort			cSeg;		// number of segments in module
+	//ushort[]		mpSegFrame;	// map seg (zero based) to frame
+}
+
+
+
+
+
+
+
+// Procedure flags
+enum {
+	PROC_FPO		= 1 << 0, // Frame pointer omitted
+	PROC_INTERRUPT	= 1 << 1, // Interrupt
+	PROC_RETURN		= 1 << 2, // Far return
+	PROC_NEVER		= 1 << 3, // Never returns
+}
+
+// Procedure calling conventions
+enum {
+	CALL_C_NEAR			= 0x00,
+	CALL_C_FAR			= 0x01,
+	CALL_PASCAL_NEAR	= 0x02,
+	CALL_PASCAL_FAR		= 0x03,
+	CALL_FASTCALL_NEAR	= 0x04,
+	CALL_FASTCALL_FAR	= 0x05,
+	CALL_STDCALL_NEAR	= 0x07,
+	CALL_STDCALL_FAR	= 0x08,
+	CALL_SYSCALL_NEAR	= 0x09,
+	CALL_SYSCALL_FAR	= 0x10,
+	CALL_THIS			= 0x11,
+	CALL_MIPS			= 0x12,
+	CALL_GENERIC		= 0x13
+}
+
+enum {
+	STRUCT_PACKED		= 1 << 0,
+	STRUCT_CTOR			= 1 << 1,
+	STRUCT_OVERLOADS	= 1 << 2,
+	STRUCT_IS_NESTED	= 1 << 3,
+	STRUCT_HAS_NESTED	= 1 << 4,
+	STRUCT_OPASSIGN		= 1 << 5,
+	STRUCT_OPCAST		= 1 << 6,
+	STRUCT_FWDREF		= 1 << 7,
+	STRUCT_SCOPED		= 1 << 8
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dbg/ui/CrashWindow.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,369 @@
+/**
+ A window used to display the data from a CrashInfo struct generated by the
+ runtime's crash handler.
+
+ TODO:
+	* Send report - need SMTP implementation
+	* Save report
+
+ Authors:
+	Jeremie Pelletier
+
+ License:
+	Public Domain
+*/
+module dbg.ui.CrashWindow;
+
+import std.c.string;
+import dlib.CrashHandler;
+import dbg.Debug : SystemException;
+
+import std.stdio;
+
+private enum {
+	ReportWindowWidth		= 640,
+	ReportWindowHeight		= 480,
+	ReportWindowMinWidth	= 320,
+	ReportWindowMinHeight	= 240,
+	ReportWindowTitle		= "Unhandled exception!"
+}
+
+// ----------------------------------------------------------------------------
+// W i n 3 2
+// ----------------------------------------------------------------------------
+
+version(Windows) {
+
+import win32.windows;
+
+private enum {
+	ID_LABEL			= 100,
+	ID_SAVE_BTN			= 101,
+	ID_SEND_BTN			= 102,
+	ID_CLOSE_BTN		= 103,
+	ID_REPORT			= 104
+}
+
+enum CLEARTYPE_QUALITY = 5;
+enum LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x20;
+
+/**
+ Create the crash window for the given crash information, the routine will
+ return when the window is closed.
+*/
+void ShowCrashWindow(CrashInfo* crashInfo)
+in {
+	assert(crashInfo);
+}
+body {
+	try {
+
+	HINSTANCE inst = GetModuleHandle(null);
+
+	WNDCLASSEXA wc;
+	wc.cbSize = WNDCLASSEX.sizeof;
+	wc.lpfnWndProc = &ReportWndProc;
+	wc.hInstance = inst;
+	wc.hIcon = cast(HICON)LoadImage(HINSTANCE.init, MAKEINTRESOURCE(OIC_ERROR), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE);
+	wc.hCursor = cast(HCURSOR)LoadImage(HINSTANCE.init, MAKEINTRESOURCE(OCR_NORMAL), IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
+	wc.hbrBackground = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+	wc.lpszClassName = "CrashWindowClass";
+
+	if(!RegisterClassExA(&wc)) SystemException();
+	scope(exit) if(!UnregisterClassA("CrashWindowClass", inst)) SystemException();
+
+	RECT rc = void;
+	GetClientRect(GetDesktopWindow(), &rc);
+	
+	writeln(crashInfo.toString);
+
+	HWND wnd = CreateWindowExA(
+		WS_EX_WINDOWEDGE,
+		"CrashWindowClass", ReportWindowTitle,
+		WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+		(rc.right >> 1) - (ReportWindowWidth >> 1), (rc.bottom >> 1) - (ReportWindowHeight >> 1),
+		ReportWindowWidth, ReportWindowHeight,
+		HWND.init, HMENU.init, inst, cast(void*)crashInfo.toString.ptr
+	);
+	if(!wnd) SystemException();
+
+	MSG msg = void;
+	while(GetMessage(&msg, HWND.init, 0, 0)) {
+		TranslateMessage(&msg);
+		DispatchMessage(&msg);
+	}
+
+	} // try
+	catch(Throwable e) {
+		MessageBoxA(HWND.init, (e.toString ~ '\0').ptr, "Crash Window Error!", MB_ICONERROR | MB_OK);
+	}
+}
+
+private:
+
+__gshared HWND saveButton, sendButton, closeButton, reportField;
+
+extern(Windows)
+LRESULT ReportWndProc(HWND wnd, uint msg, WPARAM w, LPARAM l) {
+	try {
+
+	switch(msg) {
+	case WM_CREATE:
+		HINSTANCE inst = cast(HINSTANCE).GetModuleHandle(null);
+		CREATESTRUCT* cs = cast(CREATESTRUCT*)l;
+
+		LOGFONTA lf;
+		lf.lfHeight = 15;
+		lf.lfWeight = FW_REGULAR;
+		lf.lfCharSet = DEFAULT_CHARSET;
+		lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+		lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+		lf.lfQuality = CLEARTYPE_QUALITY;
+		lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+		HFONT font = .CreateFontIndirectA(&lf);
+		if(!font) SystemException();
+
+		HINSTANCE iconMod = LoadLibraryExA("shell32.dll", null,
+			DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
+
+		HWND CreateButton(string caption, uint id, ushort iconId) {
+			HWND ret = CreateWindowExA(
+				0, "BUTTON", caption.ptr, WS_CHILD | WS_VISIBLE,
+				0, 0, 0, 0, wnd, cast(HMENU)id, inst, null
+			);
+			if(!ret) SystemException();
+
+			SendMessageA(ret, WM_SETFONT, cast(WPARAM)font, 0);
+
+			if(iconMod) {
+				HANDLE icon = LoadImage(iconMod, MAKEINTRESOURCE(iconId), IMAGE_ICON, 24, 24, 0);
+				if(icon) SendMessageA(ret, BM_SETIMAGE, IMAGE_ICON, cast(uint)icon);
+			}
+
+			return ret;
+		}
+
+		saveButton = CreateButton("Save Report", ID_SAVE_BTN, 7);
+		sendButton = CreateButton("Send Report", ID_SEND_BTN, 27);
+		closeButton = CreateButton("Close", ID_CLOSE_BTN, 28);
+
+		if(iconMod) FreeLibrary(cast(HMODULE)iconMod);
+
+		enum ReportFont = "Courier New\0";
+		lf.lfHeight = 14;
+		lf.lfFaceName[0 .. ReportFont.length] = ReportFont;
+
+		font = CreateFontIndirectA(&lf);
+		if(!font) SystemException();
+
+		reportField = CreateWindowExA(
+			WS_EX_CLIENTEDGE, "EDIT", null,
+			WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_VISIBLE |
+				ES_READONLY | ES_MULTILINE | ES_AUTOVSCROLL,
+			0, 0, 0, 0, wnd, cast(HMENU)ID_REPORT, inst, null
+		);
+		if(!reportField) SystemException();
+
+		SendMessageA(reportField, EM_SETMARGINS, EC_LEFTMARGIN | EC_RIGHTMARGIN, MAKELONG(5, 5));
+		SendMessageA(reportField, WM_SETFONT, cast(WPARAM)font, 0);
+		SendMessageA(reportField, WM_SETTEXT, 0, cast(LPARAM)cs.lpCreateParams);
+
+		break;
+
+	case WM_DESTROY:
+		PostQuitMessage(0);
+		break;
+
+	case WM_GETMINMAXINFO:
+		MINMAXINFO* mm = cast(MINMAXINFO*)l;
+		mm.ptMinTrackSize.x = ReportWindowMinWidth;
+		mm.ptMinTrackSize.y = ReportWindowMinHeight;
+		break;
+
+	case WM_SIZE:
+		int width = LOWORD(l), halfWidth = width >> 1;
+		int height = HIWORD(l);
+
+		enum {
+			BtnWidth = 125,
+			BtnHeight = 35,
+			NumBtns = 3,
+			Pad = 10,
+			ReportHPad = Pad * 2,
+			ReportVPad = BtnHeight + Pad * 3,
+			BtnVPad = BtnHeight + Pad,
+			BtnHalfWidth = (BtnWidth * NumBtns + (Pad * (NumBtns - 1))) >> 1
+		}
+
+		if(!MoveWindow(reportField, Pad, Pad, width - ReportHPad, height - ReportVPad, true))
+			SystemException();
+
+		void Move(HWND wnd, int i) {
+			if(!MoveWindow(wnd, halfWidth - BtnHalfWidth + BtnWidth * i + Pad * i,
+				height - BtnVPad, BtnWidth, BtnHeight, true))
+					SystemException();
+		}
+
+		Move(saveButton, 0);
+		Move(sendButton, 1);
+		Move(closeButton, 2);
+
+		break;
+
+	case WM_COMMAND:
+		if(HIWORD(w) != BN_CLICKED) break;
+
+		int id = LOWORD(w);
+
+		// GetSaveFileName fails on win7.. no idea why
+		if(id == ID_SAVE_BTN) {
+			/*char[256] path = void;
+			path[0 .. 11] = "Report.txt\0";
+
+			OPENFILENAMEA ofn;
+			ofn.lStructSize = OPENFILENAME.sizeof;
+			ofn.hwndOwner = wnd;
+			ofn.lpstrFilter = "Text File\0*.txt\0\0";
+			ofn.lpstrFile = path.ptr;
+			ofn.nMaxFile = path.length;
+			ofn.Flags = OFN_OVERWRITEPROMPT;
+
+			try {
+				if(!GetSaveFileNameA(&ofn)) SystemException();
+
+				uint len = strlen(path.ptr);
+				if(path[len-4 .. len] != ".txt") path[len .. len + 5] = ".txt\0";
+
+				HANDLE file = CreateFileA(path.ptr, GENERIC_WRITE, 0,
+					null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, null);
+
+				if(file == INVALID_HANDLE_VALUE) SystemException();
+				scope(exit) if(!CloseHandle(file)) SystemException();
+
+				char* text;
+				SendMessageA(reportField, WM_GETTEXT, 0, cast(LPARAM)text);
+				len = strlen(text);
+
+				uint written = void;
+				if(!WriteFile(file, text, len, &written, null))
+					SystemException();
+
+				if(written != len) throw new SystemException("Couldn't write entire data.");
+
+				id = ID_CLOSE_BTN;
+			}
+			catch(SystemException e) {
+				MessageBoxA(wnd, (e.toString ~ '\0').ptr, "Error!", MB_OK | MB_ICONERROR);
+			}*/
+
+			MessageBoxA(wnd, "TODO", "Error!", MB_OK | MB_ICONERROR);
+		}
+
+		if(id == ID_SEND_BTN)
+			MessageBoxA(wnd, "TODO", "Error!", MB_OK | MB_ICONERROR);
+
+		if(id == ID_CLOSE_BTN)
+			SendMessageA(wnd, WM_CLOSE, 0, 0);
+
+		break;
+
+	default:
+		return DefWindowProcA(wnd, msg, w, l);
+	}
+
+	} // try
+	catch(Exception e) {
+		MessageBoxA(HWND.init, (e.toString ~ '\0').ptr, "Crash Window Handler Error!", MB_ICONERROR | MB_OK);
+		PostQuitMessage(0);
+	}
+
+	return 0;
+}
+
+} // version(Windows)
+
+else version(Gnome) {
+
+import std.c.stdio;	
+
+import ext.Gnome.gtk;
+import ext.Gnome.gobject;
+
+void ErrorGUI(in ErrorReport* report) {
+	int argc;
+	if(!gtk_init_check(&argc, null)) {
+		printf("gtk failed!\n");
+		Pause;
+	}
+
+	void SetSignal(A, B)(A* widget, string signal, B callback) {
+		g_signal_connect(cast(void*)widget, signal.ptr, cast(GCallback)callback, null);
+	}
+
+	// Create the report window
+	GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+	gtk_window_set_title(cast(GtkWindow*)window, ReportWindowTitle);
+	gtk_window_set_default_size(cast(GtkWindow*)window, ReportWindowWidth, ReportWindowHeight);
+	gtk_window_set_icon_name(cast(GtkWindow*)window, GTK_STOCK_DIALOG_ERROR);
+
+	SetSignal(window, "destroy", &gtk_main_quit);
+
+	// Create the root box
+	GtkWidget* vbox = gtk_vbox_new(false, 0);
+	gtk_container_add(cast(GtkContainer*)window, vbox);
+
+	// Create the report edit
+	GtkWidget* view = gtk_text_view_new();
+	gtk_text_view_set_editable(cast(GtkTextView*)view, false);
+	gtk_text_view_set_cursor_visible(cast(GtkTextView*)view, false);
+
+	GtkTextBuffer* buffer = gtk_text_view_get_buffer(cast(GtkTextView*)view);
+	gtk_text_buffer_set_text(buffer, report.dumpText.ptr, -1);
+
+	gtk_box_pack_start(cast(GtkBox*)vbox, view, true, true, 0);
+
+	// Create the buttons box
+	GtkWidget* hbox = gtk_hbutton_box_new();
+	gtk_box_set_spacing(cast(GtkBox*)hbox, 10);
+	gtk_button_box_set_layout(cast(GtkButtonBox*)hbox, GTK_BUTTONBOX_CENTER);
+	gtk_box_pack_start(cast(GtkBox*)vbox, hbox, false, true, 10);
+
+	// Create the buttons
+	GtkWidget* CreateButton(B)(string label, string stockId, B callback) {
+		GtkWidget* button = gtk_button_new_with_label(label.ptr);
+
+		GtkWidget* image = gtk_image_new_from_stock(stockId.ptr, GTK_ICON_SIZE_BUTTON);
+		gtk_button_set_image(cast(GtkButton*)button, image);
+
+		gtk_container_add(cast(GtkContainer*)hbox, button);
+
+		if(callback) SetSignal(button, "clicked", callback);
+
+		return button;
+	}
+
+	CreateButton("Save Report", GTK_STOCK_SAVE_AS, &OnClickSave);
+	CreateButton("Send Report", GTK_STOCK_CONNECT, &OnClickSend);
+	GtkWidget* close = CreateButton("Close", GTK_STOCK_CLOSE, null);
+
+	g_signal_connect_swapped(cast(void*)close, "clicked",
+		cast(GCallback)(&gtk_widget_destroy), cast(void*)(window));
+
+	// Display the window and run the main loop
+	gtk_widget_show_all(window);
+	gtk_main();
+}
+
+extern(C):
+
+void OnClickSave(GtkButton* button, gpointer user_data) {
+	// TODO
+}
+
+void OnClickSend(GtkButton* button, gpointer user_data) {
+	// TODO
+}
+
+} // version(Gnome)
+else static assert(0);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ddmd.def	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,8 @@
+EXETYPE NT
+
+IMPORTS
+_EnumProcessModules@16 = psapi.EnumProcessModules
+_GetFileVersionInfoSizeA@8 = version.GetFileVersionInfoSizeA
+_GetFileVersionInfoA@16 = version.GetFileVersionInfoA
+_VerQueryValueA@16 = version.VerQueryValueA
+_CommandLineToArgvW@8 = shell32.CommandLineToArgvW
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ddmd.dice	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,340 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
+<Dice>
+	<Project name = "ddmd">
+		<Files>
+			<File path="." name="main.d" />
+			<File path="." name="win32\windef.d" />
+			<File path="." name="win32\winuser.d" />
+			<File path="." name="win32\wingdi.d" />
+			<File path="." name="dlib\CrashHandler.d" />
+			<File path="." name="dbg\ui\CrashWindow.d" />
+			<File path="." name="dbg\Debug.d" />
+			<File path="." name="dbg\symbol\CodeView.d" />
+			<File path="." name="dbg\image\PE.d" />
+			<File path="." name="dmd\AggregateDeclaration.d" />
+			<File path="." name="dmd\VarExp.d" />
+			<File path="." name="dmd\StructLiteralExp.d" />
+			<File path="." name="dmd\declaration\MATCH.d" />
+			<File path="." name="dmd\expression\Util.d" />
+			<File path="." name="dmd\expression\Add.d" />
+			<File path="." name="dmd\expression\Min.d" />
+			<File path="." name="dmd\OverExp.d" />
+			<File path="." name="dmd\Cast.d" />
+			<File path="." name="dmd\TupleExp.d" />
+			<File path="." name="dmd\ArrayLengthExp.d" />
+			<File path="." name="dmd\TypeInfoConstDeclaration.d" />
+			<File path="." name="dmd\TypeInfoInvariantDeclaration.d" />
+			<File path="." name="dmd\TypeInfoSharedDeclaration.d" />
+			<File path="." name="dmd\TypeInfoStructDeclaration.d" />
+			<File path="." name="dmd\DsymbolExp.d" />
+			<File path="." name="dmd\GlobalExpressions.d" />
+			<File path="." name="dmd\NewExp.d" />
+			<File path="." name="dmd\PeelStatement.d" />
+			<File path="." name="dmd\HaltExp.d" />
+			<File path="." name="dmd\SymOffExp.d" />
+			<File path="." name="dmd\type\Util.d" />
+			<File path="." name="dmd\SymbolExp.d" />
+			<File path="." name="dmd\Optimize.d" />
+			<File path="." name="dmd\DotVarExp.d" />
+			<File path="." name="dmd\DeclarationExp.d" />
+			<File path="." name="dmd\TraitsExp.d" />
+			<File path="." name="dmd\ComplexExp.d" />
+			<File path="." name="dmd\ErrorExp.d" />
+			<File path="." name="dmd\AssignExp.d" />
+			<File path="." name="dmd\DotExp.d" />
+			<File path="." name="dmd\AliasDeclaration.d" />
+			<File path="." name="dmd\DefaultInitExp.d" />
+			<File path="." name="dmd\FileInitExp.d" />
+			<File path="." name="dmd\LineInitExp.d" />
+			<File path="." name="dmd\AnonDeclaration.d" />
+			<File path="." name="dmd\AliasThis.d" />
+			<File path="." name="dmd\AlignDeclaration.d" />
+			<File path="." name="dmd\AnonymousAggregateDeclaration.d" />
+			<File path="." name="dmd\Argument.d" />
+			<File path="." name="dmd\FuncExp.d" />
+			<File path="." name="dmd\ArrayLiteralExp.d" />
+			<File path="." name="dmd\AssocArrayLiteralExp.d" />
+			<File path="." name="dmd\AssertExp.d" />
+			<File path="." name="dmd\IsExp.d" />
+			<File path="." name="dmd\TypeExp.d" />
+			<File path="." name="dmd\StringExp.d" />
+			<File path="." name="dmd\NullExp.d" />
+			<File path="." name="dmd\RealExp.d" />
+			<File path="." name="dmd\ThisExp.d" />
+			<File path="." name="dmd\ScopeExp.d" />
+			<File path="." name="dmd\Array.d" />
+			<File path="." name="dmd\DotIdExp.d" />
+			<File path="." name="dmd\FileExp.d" />
+			<File path="." name="dmd\SuperExp.d" />
+			<File path="." name="dmd\TypeidExp.d" />
+			<File path="." name="dmd\CompileExp.d" />
+			<File path="." name="dmd\IdentifierExp.d" />
+			<File path="." name="dmd\DollarExp.d" />
+			<File path="." name="dmd\ArrayT.d" />
+			<File path="." name="dmd\AndAndExp.d" />
+			<File path="." name="dmd\DotTemplateInstanceExp.d" />
+			<File path="." name="dmd\OrExp.d" />
+			<File path="." name="dmd\PostExp.d" />
+			<File path="." name="dmd\CallExp.d" />
+			<File path="." name="dmd\SliceExp.d" />
+			<File path="." name="dmd\ArrayExp.d" />
+			<File path="." name="dmd\AddrExp.d" />
+			<File path="." name="dmd\UAddExp.d" />
+			<File path="." name="dmd\XorExp.d" />
+			<File path="." name="dmd\CommaExp.d" />
+			<File path="." name="dmd\BinExp.d" />
+			<File path="." name="dmd\CondExp.d" />
+			<File path="." name="dmd\OrOrExp.d" />
+			<File path="." name="dmd\AndExp.d" />
+			<File path="." name="dmd\InExp.d" />
+			<File path="." name="dmd\EqualExp.d" />
+			<File path="." name="dmd\CmpExp.d" />
+			<File path="." name="dmd\ShlExp.d" />
+			<File path="." name="dmd\AddExp.d" />
+			<File path="." name="dmd\CatExp.d" />
+			<File path="." name="dmd\MinExp.d" />
+			<File path="." name="dmd\MulExp.d" />
+			<File path="." name="dmd\ModExp.d" />
+			<File path="." name="dmd\DivExp.d" />
+			<File path="." name="dmd\ShrExp.d" />
+			<File path="." name="dmd\UshrExp.d" />
+			<File path="." name="dmd\CastExp.d" />
+			<File path="." name="dmd\DeleteExp.d" />
+			<File path="." name="dmd\ComExp.d" />
+			<File path="." name="dmd\NotExp.d" />
+			<File path="." name="dmd\UnaExp.d" />
+			<File path="." name="dmd\NegExp.d" />
+			<File path="." name="dmd\PtrExp.d" />
+			<File path="." name="dmd\IntegerExp.d" />
+			<File path="." name="dmd\AddAssignExp.d" />
+			<File path="." name="dmd\AndAssignExp.d" />
+			<File path="." name="dmd\DivAssignExp.d" />
+			<File path="." name="dmd\MinAssignExp.d" />
+			<File path="." name="dmd\ModAssignExp.d" />
+			<File path="." name="dmd\MulAssignExp.d" />
+			<File path="." name="dmd\OrAssignExp.d" />
+			<File path="." name="dmd\XorAssignExp.d" />
+			<File path="." name="dmd\IdentityExp.d" />
+			<File path="." name="dmd\ArrayInitializer.d" />
+			<File path="." name="dmd\ArrayScopeSymbol.d" />
+			<File path="." name="dmd\ArrayTypes.d" />
+			<File path="." name="dmd\AsmStatement.d" />
+			<File path="." name="dmd\AttribDeclaration.d" />
+			<File path="." name="dmd\BUILTIN.d" />
+			<File path="." name="dmd\BaseClass.d" />
+			<File path="." name="dmd\BreakStatement.d" />
+			<File path="." name="dmd\CaseRangeStatement.d" />
+			<File path="." name="dmd\CaseStatement.d" />
+			<File path="." name="dmd\Catch.d" />
+			<File path="." name="dmd\ClassDeclaration.d" />
+			<File path="." name="dmd\ClassInfoDeclaration.d" />
+			<File path="." name="dmd\CompileDeclaration.d" />
+			<File path="." name="dmd\CompileStatement.d" />
+			<File path="." name="dmd\CompoundDeclarationStatement.d" />
+			<File path="." name="dmd\CompoundStatement.d" />
+			<File path="." name="dmd\Condition.d" />
+			<File path="." name="dmd\ConditionalDeclaration.d" />
+			<File path="." name="dmd\ConditionalStatement.d" />
+			<File path="." name="dmd\ContinueStatement.d" />
+			<File path="." name="dmd\CppMangleState.d" />
+			<File path="." name="dmd\CtorDeclaration.d" />
+			<File path="." name="dmd\DVCondition.d" />
+			<File path="." name="dmd\Dchar.d" />
+			<File path="." name="dmd\DebugCondition.d" />
+			<File path="." name="dmd\DebugSymbol.d" />
+			<File path="." name="dmd\Declaration.d" />
+			<File path="." name="dmd\DeclarationStatement.d" />
+			<File path="." name="dmd\DefaultStatement.d" />
+			<File path="." name="dmd\DeleteDeclaration.d" />
+			<File path="." name="dmd\DoStatement.d" />
+			<File path="." name="dmd\DocComment.d" />
+			<File path="." name="dmd\Dsymbol.d" />
+			<File path="." name="dmd\DsymbolTable.d" />
+			<File path="." name="dmd\DtorDeclaration.d" />
+			<File path="." name="dmd\EnumDeclaration.d" />
+			<File path="." name="dmd\EnumMember.d" />
+			<File path="." name="dmd\Escape.d" />
+			<File path="." name="dmd\ExpInitializer.d" />
+			<File path="." name="dmd\ExpStatement.d" />
+			<File path="." name="dmd\Expression.d" />
+			<File path="." name="dmd\File.d" />
+			<File path="." name="dmd\FileName.d" />
+			<File path="." name="dmd\ForStatement.d" />
+			<File path="." name="dmd\ForeachRangeStatement.d" />
+			<File path="." name="dmd\ForeachStatement.d" />
+			<File path="." name="dmd\FuncAliasDeclaration.d" />
+			<File path="." name="dmd\FuncDeclaration.d" />
+			<File path="." name="dmd\FuncLiteralDeclaration.d" />
+			<File path="." name="dmd\Global.d" />
+			<File path="." name="dmd\GotoCaseStatement.d" />
+			<File path="." name="dmd\GotoDefaultStatement.d" />
+			<File path="." name="dmd\GotoStatement.d" />
+			<File path="." name="dmd\HdrGenState.d" />
+			<File path="." name="dmd\ILS.d" />
+			<File path="." name="dmd\IRState.d" />
+			<File path="." name="dmd\Id.d" />
+			<File path="." name="dmd\Identifier.d" />
+			<File path="." name="dmd\IfStatement.d" />
+			<File path="." name="dmd\Import.d" />
+			<File path="." name="dmd\Initializer.d" />
+			<File path="." name="dmd\InlineCostState.d" />
+			<File path="." name="dmd\InlineDoState.d" />
+			<File path="." name="dmd\InlineScanState.d" />
+			<File path="." name="dmd\IntRange.d" />
+			<File path="." name="dmd\InterState.d" />
+			<File path="." name="dmd\InterfaceDeclaration.d" />
+			<File path="." name="dmd\InvariantDeclaration.d" />
+			<File path="." name="dmd\LINK.d" />
+			<File path="." name="dmd\LabelDsymbol.d" />
+			<File path="." name="dmd\LabelStatement.d" />
+			<File path="." name="dmd\Lexer.d" />
+			<File path="." name="dmd\Library.d" />
+			<File path="." name="dmd\LinkDeclaration.d" />
+			<File path="." name="dmd\Loc.d" />
+			<File path="." name="dmd\Lstring.d" />
+			<File path="." name="dmd\MATCH.d" />
+			<File path="." name="dmd\Macro.d" />
+			<File path="." name="dmd\Module.d" />
+			<File path="." name="dmd\ModuleDeclaration.d" />
+			<File path="." name="dmd\ModuleInfoDeclaration.d" />
+			<File path="." name="dmd\NewDeclaration.d" />
+			<File path="." name="dmd\ObjModule.d" />
+			<File path="." name="dmd\OnScopeStatement.d" />
+			<File path="." name="dmd\OutBuffer.d" />
+			<File path="." name="dmd\OverloadSet.d" />
+			<File path="." name="dmd\PREC.d" />
+			<File path="." name="dmd\PROT.d" />
+			<File path="." name="dmd\Package.d" />
+			<File path="." name="dmd\Param.d" />
+			<File path="." name="dmd\Parser.d" />
+			<File path="." name="dmd\PostBlitDeclaration.d" />
+			<File path="." name="dmd\PragmaDeclaration.d" />
+			<File path="." name="dmd\PragmaStatement.d" />
+			<File path="." name="dmd\ProtDeclaration.d" />
+			<File path="." name="dmd\RET.d" />
+			<File path="." name="dmd\ReturnStatement.d" />
+			<File path="." name="dmd\STC.d" />
+			<File path="." name="dmd\Scope.d" />
+			<File path="." name="dmd\ScopeDsymbol.d" />
+			<File path="." name="dmd\ScopeStatement.d" />
+			<File path="." name="dmd\Section.d" />
+			<File path="." name="dmd\Statement.d" />
+			<File path="." name="dmd\StaticAssert.d" />
+			<File path="." name="dmd\StaticAssertStatement.d" />
+			<File path="." name="dmd\StaticCtorDeclaration.d" />
+			<File path="." name="dmd\StaticDtorDeclaration.d" />
+			<File path="." name="dmd\StaticIfDeclaration.d" />
+			<File path="." name="dmd\StorageClassDeclaration.d" />
+			<File path="." name="dmd\String.d" />
+			<File path="." name="dmd\StringEntry.d" />
+			<File path="." name="dmd\StringTable.d" />
+			<File path="." name="dmd\StringValue.d" />
+			<File path="." name="dmd\StructDeclaration.d" />
+			<File path="." name="dmd\StructInitializer.d" />
+			<File path="." name="dmd\SwitchStatement.d" />
+			<File path="." name="dmd\SymbolDeclaration.d" />
+			<File path="." name="dmd\SynchronizedStatement.d" />
+			<File path="." name="dmd\TOK.d" />
+			<File path="." name="dmd\TY.d" />
+			<File path="." name="dmd\TemplateAliasParameter.d" />
+			<File path="." name="dmd\TemplateDeclaration.d" />
+			<File path="." name="dmd\TemplateInstance.d" />
+			<File path="." name="dmd\TemplateMixin.d" />
+			<File path="." name="dmd\TemplateParameter.d" />
+			<File path="." name="dmd\TemplateThisParameter.d" />
+			<File path="." name="dmd\TemplateTupleParameter.d" />
+			<File path="." name="dmd\TemplateTypeParameter.d" />
+			<File path="." name="dmd\TemplateValueParameter.d" />
+			<File path="." name="dmd\ThisDeclaration.d" />
+			<File path="." name="dmd\ThrowStatement.d" />
+			<File path="." name="dmd\Token.d" />
+			<File path="." name="dmd\TryCatchStatement.d" />
+			<File path="." name="dmd\TryFinallyStatement.d" />
+			<File path="." name="dmd\TupleDeclaration.d" />
+			<File path="." name="dmd\Type.d" />
+			<File path="." name="dmd\TypeAArray.d" />
+			<File path="." name="dmd\TypeArray.d" />
+			<File path="." name="dmd\TypeBasic.d" />
+			<File path="." name="dmd\TypeClass.d" />
+			<File path="." name="dmd\TypeDArray.d" />
+			<File path="." name="dmd\TypeDelegate.d" />
+			<File path="." name="dmd\TypeEnum.d" />
+			<File path="." name="dmd\TypeFunction.d" />
+			<File path="." name="dmd\TypeIdentifier.d" />
+			<File path="." name="dmd\TypeInfoDeclaration.d" />
+			<File path="." name="dmd\TypeInstance.d" />
+			<File path="." name="dmd\TypeNext.d" />
+			<File path="." name="dmd\TypePointer.d" />
+			<File path="." name="dmd\TypeQualified.d" />
+			<File path="." name="dmd\TypeReference.d" />
+			<File path="." name="dmd\TypeReturn.d" />
+			<File path="." name="dmd\TypeSArray.d" />
+			<File path="." name="dmd\TypeSlice.d" />
+			<File path="." name="dmd\TypeStruct.d" />
+			<File path="." name="dmd\TypeTuple.d" />
+			<File path="." name="dmd\TypeTypedef.d" />
+			<File path="." name="dmd\TypeTypeof.d" />
+			<File path="." name="dmd\TypedefDeclaration.d" />
+			<File path="." name="dmd\UnionDeclaration.d" />
+			<File path="." name="dmd\UnitTestDeclaration.d" />
+			<File path="." name="dmd\Utf.d" />
+			<File path="." name="dmd\Util.d" />
+			<File path="." name="dmd\DotTemplateExp.d" />
+			<File path="." name="dmd\DelegateExp.d" />
+			<File path="." name="dmd\RemoveExp.d" />
+			<File path="." name="dmd\TemplateExp.d" />
+			<File path="." name="dmd\DotTypeExp.d" />
+			<File path="." name="dmd\IndexExp.d" />
+			<File path="." name="dmd\VarDeclaration.d" />
+			<File path="." name="dmd\VersionCondition.d" />
+			<File path="." name="dmd\VersionSymbol.d" />
+			<File path="." name="dmd\VoidInitializer.d" />
+			<File path="." name="dmd\VolatileStatement.d" />
+			<File path="." name="dmd\WhileStatement.d" />
+			<File path="." name="dmd\WithScopeSymbol.d" />
+			<File path="." name="dmd\WithStatement.d" />
+			<File path="." name="dmd\backend\Blockx.d" />
+			<File path="." name="dmd\backend\enum_t.d" />
+			<File path="." name="dmd\backend\Symbol.d" />
+			<File path="." name="dmd\backend\Util.d" />
+			<File path="." name="dmd\backend\TYPE.d" />
+			<File path="." name="dmd\backend\TYM.d" />
+			<File path="." name="dmd\backend\mTY.d" />
+			<File path="." name="dmd\backend\block.d" />
+			<File path="." name="dmd\backend\code.d" />
+			<File path="." name="dmd\backend\glue.d" />
+			<File path="." name="dmd\backend\dt_t.d" />
+			<File path="." name="dmd\backend\elem.d" />
+			<File path="." name="dmd\backend\func_t.d" />
+			<File path="." name="dmd\backend\Cstate.d" />
+			<File path="." name="dmd\backend\TYFL.d" />
+			<File path="." name="dmd\backend\RTLSYM.d" />
+			<File path="." name="dmd\backend\symtab_t.d" />
+			<File path="." name="dmd\backend\Classsym.d" />
+			<File path="." name="dmd\backend\con_t.d" />
+			<File path="." name="dmd\backend\cse_t.d" />
+			<File path="." name="dmd\backend\struct_t.d" />
+			<File path="." name="dmd\backend\OPER.d" />
+			<File path="." name="dmd\backend\StringTab.d" />
+			<File path="." name="dmd\backend\DT.d" />
+			<File path="." name="dmd\codegen\Util.d" />
+		</Files>
+		<CompileSettings>
+			<Version>DMDV2</Version>
+			<Version>TX86</Version>
+			<Version>MARS</Version>
+			<Version>TARGET_WINDOS</Version>
+			<Version>_WIN32</Version>
+			<Version>WindowsXP</Version>
+			<Version>DumbClone</Version>
+		</CompileSettings>
+		<Dependencies>
+			<Library>D:\Projects\ddmd\bridge.obj</Library>
+			<Library>D:\Projects\ddmd\ddmd.def</Library>
+			<Library>c:\dmd_2.032\src\dmd\dmd.lib</Library>
+		</Dependencies>
+		<Output type="Executable">
+			<Path>c:\dmd_2.032\windows\bin\ddmd.exe</Path>
+		</Output>
+	</Project>
+</Dice>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dlib/CrashHandler.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,450 @@
+/**
+ A simple runtime crash handler which collects various informations about
+ the crash such as registers, stack traces, and loaded modules.
+
+ TODO:
+	* Threading support
+	* Stack dumps
+
+ Authors:
+	Jeremie Pelletier
+
+ License:
+	Public Domain
+*/
+module dlib.CrashHandler;
+
+debug = CrashHandler;
+
+import std.c.stdio;
+import dbg.Debug;
+import dbg.ui.CrashWindow;
+
+version(X86) {}
+else static assert(0, "Unsupported architecture.");
+
+version(DigitalMars) {
+	//import dlib.dmd.ErrorHandling;
+}
+else static assert(0, "Unsupported compiler.");
+
+version(Windows) {
+	import win32.windows;
+	import win32.psapi;
+	//import sys.windows.Memory;
+	//import dlib.Module;
+	import dbg.image.PE;
+	import dbg.symbol.CodeView;
+}
+else version(Posix) {
+	import sys.posix.ucontext;
+	import std.c.signal;
+	import std.c.stdlib : free, exit, EXIT_FAILURE;
+}
+else static assert(0, "Unsupported platform.");
+
+/**
+ Register the crash handler
+*/
+void CrashHandlerInit() {
+	version(Windows) {
+		//SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS);
+		SetErrorMode(0);
+		SetUnhandledExceptionFilter(&UnhandledExceptionHandler);
+	}
+	else version(Posix) {
+		sigaction_t sa;
+		sa.sa_handler = cast(sighandler_t)&SignalHandler;
+		sigemptyset(&sa.sa_mask);
+		sa.sa_flags = SA_RESTART | SA_SIGINFO;
+
+		sigaction(SIGILL, &sa, null);
+		sigaction(SIGFPE, &sa, null);
+		sigaction(SIGSEGV, &sa, null);
+	}
+	else static assert(0);
+}
+
+/**
+ Information collected by the crash handler
+*/
+struct CrashInfo {
+	struct Registers {
+		version(X86) {
+			uint EAX, EBX, ECX, EDX;
+			uint EDI, ESI;
+			uint EBP, ESP;
+		}
+		else static assert(0);
+	}
+
+	struct Module {
+		string fileName;
+		ushort[4] fileVersion;
+	}
+
+	Throwable	error;
+	string		moduleName;
+	Registers	registers;
+	size_t[]	backtrace;
+	Module[]	modules;
+
+	void Dump() {
+		// TODO: support more dump methods
+		ShowCrashWindow(&this);
+	}
+
+	/**
+	 Formats the crash info as plain-text
+	*/
+	string toString() {
+		string text;
+		char[255] buffer = void;
+		uint len = void;
+
+		text ~= error.toString();
+		text ~= "\r\n\r\n";
+
+		version(X86) {
+			with(registers) len = snprintf(buffer.ptr, buffer.length,
+				" Registers:\r\n" ~
+				"========================================\r\n" ~
+				"  EAX=0x%08X  EBX=0x%08X  ECX=0x%08X  EDX=0x%08X\r\n" ~
+				"  EDI=0x%08X  ESI=0x%08X  EBP=0x%08X  ESP=0x%08X\r\n",
+				EAX, EBX, ECX, EDX, EDI, ESI, EBP, ESP
+			);
+			text ~= buffer[0 .. len] ~ "\r\n";
+		}
+		else static assert(0);
+
+		text ~= " Stack Trace:\r\n" ~
+			"========================================\r\n";
+
+		scope auto frames = new StackFrameInfo[backtrace.length];
+		ResolveStackFrames(frames);
+
+		foreach(ref frame; frames) {
+			//len = snprintf(buffer.ptr, buffer.length, "%p", frame.va);
+			//text ~= "  " ~ buffer[0 .. len] ~ ": " ~ frame.moduleName ~ "\r\n";
+
+			//with(frame.symbol) if(name.length) {
+			//	len = snprintf(buffer.ptr, buffer.length, "%X", offset);
+			//	text ~= "    " ~ name ~ " @ 0x" ~ buffer[0 .. len] ~ "\r\n";
+			//}
+
+			with(frame.fileLine) if(line) {
+				len = snprintf(buffer.ptr, buffer.length, "%u", line);
+				text ~= "    " ~ file ~ ":" ~ buffer[0 .. len] ~ "\r\n";
+			}
+
+			//text ~= "\r\n";
+		}
+/+
+		text ~= " Loaded Modules:\r\n" ~
+			"========================================\r\n";
+
+		foreach(mod; modules) {
+			len = snprintf(buffer.ptr, buffer.length, "%hu.%hu.%hu.%hu",
+				mod.fileVersion[0], mod.fileVersion[1],
+				mod.fileVersion[2], mod.fileVersion[3]);
+
+			text ~= "  " ~ mod.fileName ~ "\r\n    " ~ buffer[0 .. len] ~ "\r\n";
+		}
++/
+		text ~= '\0';
+
+		return text;
+	}
+
+private:
+
+	struct StackFrameInfo {
+		size_t			va;
+		string			moduleName;
+		SymbolInfo		symbol;
+		FileLineInfo	fileLine;
+	}
+
+	struct DebugImage {
+		DebugImage*			next;
+		string				moduleName;
+		size_t				baseAddress;
+		uint				rvaOffset;
+		IExecutableImage	exeModule;
+		ISymbolicDebugInfo	debugInfo;
+	}
+
+	version(X86) {
+	void ResolveStackFrames(StackFrameInfo[] frames) const {
+		StackFrameInfo* frame = void;
+		DebugImage* imageList, image = void;
+		char[255] buffer = void;
+		uint len = void;
+		uint rva = void;
+
+		version(Windows) MEMORY_BASIC_INFORMATION mbi = void;
+
+		foreach(i, va; backtrace) {
+			frame = &frames[i];
+			frame.va = va;
+
+			version(Windows) {
+				// mbi.Allocation base is the handle to stack frame's module
+				VirtualQuery(cast(void*)va, &mbi, MEMORY_BASIC_INFORMATION.sizeof);
+				if(!mbi.AllocationBase) break;
+
+				image = imageList;
+				while(image) {
+					if(image.baseAddress == cast(size_t)mbi.AllocationBase) break;
+					image = image.next;
+				}
+
+				if(!image) {
+					image = new DebugImage;
+
+					with(*image) {
+						next = imageList;
+						imageList = image;
+						baseAddress = cast(size_t)mbi.AllocationBase;
+
+						len = GetModuleFileNameA(cast(HMODULE)baseAddress, buffer.ptr, buffer.length);
+						moduleName = buffer[0 .. len].idup;
+
+						exeModule = new PEImage(moduleName);
+						rvaOffset = baseAddress + exeModule.codeOffset;
+						debugInfo = exeModule.debugInfo;
+					}
+				}
+			}
+			else static assert(0);
+
+			frame.moduleName = image.moduleName;
+
+			if(!image.debugInfo) continue;
+
+			rva = va - image.rvaOffset;
+
+			with(image.debugInfo) {
+				frame.symbol = ResolveSymbol(rva);
+				frame.fileLine = ResolveFileLine(rva);
+			}
+		}
+
+		while(imageList) {
+			image = imageList.next;
+			delete imageList.debugInfo;
+			delete imageList.exeModule;
+			delete imageList;
+			imageList = image;
+		}
+	}
+	} // version(X86)
+	else static assert(0);
+}
+
+// ----------------------------------------------------------------------------
+// W i n d o w s  C r a s h  H a n d l e r
+// ----------------------------------------------------------------------------
+
+version(Windows) {
+
+extern(C) Throwable _d_translate_se_to_d_exception(EXCEPTION_RECORD* exception_record);
+
+/**
+ D exceptions are built on top of Windows' SEH, a simple registered callback
+ will catch any exceptions unwinding past a thread's entry point.
+*/
+extern(Windows)
+int UnhandledExceptionHandler(EXCEPTION_POINTERS* e) {
+	CrashInfo crashInfo = void;
+	char[256] buffer = void;
+	uint len = void;
+	size_t ip = void, bp = void;
+
+	try {
+		with(crashInfo) {
+
+		version(DigitalMars)
+			error = _d_translate_se_to_d_exception(e.ExceptionRecord);
+		else
+			static assert(0);
+
+		len = GetModuleFileNameA(GetModuleHandle(null), buffer.ptr, buffer.length);
+		moduleName = buffer[0 .. len].idup;
+
+		version(X86) with(*e.ContextRecord) {
+			with(registers) {
+				EAX = Eax, EBX = Ebx, ECX = Ecx, EDX = Edx;
+				EDI = Edi, ESI = Esi;
+				EBP = Ebp, ESP = Esp;
+			}
+
+			ip = Eip;
+			bp = Ebp;
+		}
+		else static assert(0);
+
+		backtrace = null;
+		while(ip) {
+			backtrace ~= ip;
+
+			ip = cast(size_t)*(cast(void**)bp + 1);
+			bp = cast(size_t)*cast(void**)bp;
+		}
+
+		HANDLE process = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
+			0, GetCurrentProcessId());
+
+		if(process == INVALID_HANDLE_VALUE) SystemException();
+		scope(exit) if(!CloseHandle(process)) SystemException();
+
+		scope HMODULE[] hmodules = new HMODULE[64];
+		uint size = HMODULE.sizeof * hmodules.length;
+		uint sizeNeeded = void;
+		uint nModules = void;
+
+	GetModules:
+		if(!EnumProcessModules(process, hmodules.ptr, size, &sizeNeeded))
+			SystemException();
+
+		nModules = sizeNeeded / HMODULE.sizeof;
+
+		if(sizeNeeded > size) {
+			hmodules.length = nModules;
+			size = sizeNeeded;
+			goto GetModules;
+		}
+
+		Module mod = void;
+		char[] versionInfo;
+		VS_FIXEDFILEINFO* fixedVersionInfo = void;
+
+		modules = null;
+		foreach(i; 0 .. nModules) {
+			len = GetModuleFileNameA(hmodules[i], buffer.ptr, buffer.length);
+			mod.fileName = buffer[0 .. len].idup;
+
+			sizeNeeded = GetFileVersionInfoSizeA(buffer.ptr, &size);
+
+			if(sizeNeeded) {
+				if(versionInfo.length < sizeNeeded) versionInfo.length = sizeNeeded;
+
+				if(!GetFileVersionInfoA(buffer.ptr, 0, versionInfo.length, versionInfo.ptr))
+					SystemException();
+
+				if(!VerQueryValueA(versionInfo.ptr, cast(char*)"\\".ptr, cast(void**)&fixedVersionInfo, &size))
+					SystemException();
+
+				with(*fixedVersionInfo) with(mod) {
+					fileVersion[0] = HIWORD(dwProductVersionMS);
+					fileVersion[1] = LOWORD(dwProductVersionMS);
+					fileVersion[2] = HIWORD(dwProductVersionLS);
+					fileVersion[3] = LOWORD(dwProductVersionLS);
+				}
+			}
+			else {
+				mod.fileVersion[] = 0;
+			}
+
+			modules ~= mod;
+		}
+
+		} // with(crashInfo)
+
+		crashInfo.Dump();
+	}
+	catch(Throwable e) {
+		debug MessageBoxA(HWND.init, (e.toString ~ '\0').ptr, "Exception Handler Error!", MB_ICONERROR | MB_OK);
+	}
+
+	return EXCEPTION_EXECUTE_HANDLER;
+}
+
+} // version(Windows)
+
+// ----------------------------------------------------------------------------
+// P o s i x  C r a s h  H a n d l e r
+// ----------------------------------------------------------------------------
+
+else version(Posix) {
+
+/**
+ This handler catches system signals and throws the appropriate D exception.
+ The exception will unwind down to the thread's entry point where it is catched
+ and sent to UnhandledExceptionHandler().
+*/
+extern(C)
+void SignalHandler(int signum, siginfo_t* siginfo, ucontext_t* ucontext) {
+	string msg = void;
+
+	switch(signum) {
+	case SIGILL:	msg = "Illegal instruction";		break;
+	case SIGFPE:	msg = "Floating-point exception";	break;
+	case SIGSEGV:	msg = "Segmentation fault";			break;
+	default:		msg = "Unknown signal";
+	}
+
+	SystemException e = new SystemException(msg);
+
+	e._context = ucontext;
+	e.GetBackTrace();
+
+	// The kernel fixed the stack frame to make us believe we called this
+	// routine ourselves, with the nasty side effect of losing the faulty
+	// routine's address. The undocumented parameter ucontext contains our
+	// lost EIP.
+	version(X86) {
+		// It should be the 3rd frame: 
+		//	SignalHandler() -> GetBackTrace() -> backtrace()
+		if(e._backtrace.length > 2)
+			e._backtrace[2] = cast(void*)ucontext.uc_mcontext.gregs[REG_EIP];
+	}
+	else static assert(0);
+
+	throw e;
+}
+
+/**
+ This handler is called when an exception unwinds down to the thread's entry
+ point, which should catch it and manually call this routine.
+*/
+void UnhandledExceptionHandler(Throwable e) {
+	ErrorReport crashInfo = void;
+
+	with(crashInfo) {
+assert(0);
+	/+error = e;
+
+	// Get the module filename
+	// TODO
+
+	// Dump the general purpose registers
+	if(e._context) {
+		gregset_t gregs = e._context.uc_mcontext.gregs;
+
+		version(X86) {
+			registers.Eax = gregs[REG_EAX];
+			registers.Ebx = gregs[REG_EBX];
+			registers.Ecx = gregs[REG_ECX];
+			registers.Edx = gregs[REG_EDX];
+			registers.Edi = gregs[REG_EDI];
+			registers.Esi = gregs[REG_ESI];
+			registers.Ebp = gregs[REG_EBP];
+			registers.Esp = gregs[REG_ESP];
+		}
+		else static assert(0);
+	}
+
+	// Dump stack backtrace
+	addresses = e._backtrace;
+
+	// Dump the loaded modules
+	// TODO+/
+
+	} // with(crashInfo)
+
+	crashInfo.Dump();
+}
+
+} // version(Posix)
+else static assert(0);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AddAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,175 @@
+module dmd.AddAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+import dmd.AddExp;
+import dmd.CastExp;
+import dmd.AssignExp;
+import dmd.Global;
+import dmd.Id;
+
+import dmd.backend.OPER;
+import dmd.backend.elem;
+
+class AddAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKaddass, AddAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (type)
+			return this;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		Type tb1 = e1.type.toBasetype();
+		Type tb2 = e2.type.toBasetype();
+
+		if (e1.op == TOK.TOKslice)
+		{
+			typeCombine(sc);
+			type = e1.type;
+			return arrayOp(sc);
+		}
+		else
+		{
+			e1 = e1.modifiableLvalue(sc, e1);
+		}
+
+		if ((tb1.ty == TY.Tarray || tb1.ty == TY.Tsarray) && (tb2.ty == TY.Tarray || tb2.ty == TY.Tsarray) && tb1.nextOf().equals(tb2.nextOf()))
+		{
+			type = e1.type;
+			typeCombine(sc);
+			e = this;
+		}
+		else
+		{
+			e1.checkScalar();
+			e1.checkNoBool();
+			if (tb1.ty == TY.Tpointer && tb2.isintegral())
+				e = scaleFactor(sc);
+			else if (tb1.ty == TY.Tbit || tb1.ty == TY.Tbool)
+			{
+static if (false) {
+				// Need to rethink this
+				if (e1.op != TOK.TOKvar)
+				{   
+					// Rewrite e1+=e2 to (v=&e1),*v=*v+e2
+					VarDeclaration v;
+					Expression ea;
+					Expression ex;
+
+					Identifier id = Lexer.uniqueId("__name");
+
+					v = new VarDeclaration(loc, tb1.pointerTo(), id, null);
+					v.semantic(sc);
+					if (!sc.insert(v))
+						assert(0);
+
+					v.parent = sc.func;
+
+					ea = new AddrExp(loc, e1);
+					ea = new AssignExp(loc, new VarExp(loc, v), ea);
+
+					ex = new VarExp(loc, v);
+					ex = new PtrExp(loc, ex);
+					e = new AddExp(loc, ex, e2);
+					e = new CastExp(loc, e, e1.type);
+					e = new AssignExp(loc, ex.syntaxCopy(), e);
+
+					e = new CommaExp(loc, ea, e);
+				}
+				else
+				{
+					// Rewrite e1+=e2 to e1=e1+e2
+					// BUG: doesn't account for side effects in e1
+					// BUG: other assignment operators for bits aren't handled at all
+					e = new AddExp(loc, e1, e2);
+					e = new CastExp(loc, e, e1.type);
+					e = new AssignExp(loc, e1.syntaxCopy(), e);
+				}
+} else {
+				// Rewrite e1+=e2 to e1=e1+e2
+				// BUG: doesn't account for side effects in e1
+				// BUG: other assignment operators for bits aren't handled at all
+				e = new AddExp(loc, e1, e2);
+				e = new CastExp(loc, e, e1.type);
+				e = new AssignExp(loc, e1.syntaxCopy(), e);
+}
+				e = e.semantic(sc);
+			}
+			else
+			{
+				type = e1.type;
+				typeCombine(sc);
+				e1.checkArithmetic();
+				e2.checkArithmetic();
+
+				if (type.isreal() || type.isimaginary())
+				{
+					assert(global.errors || e2.type.isfloating());
+					e2 = e2.castTo(sc, e1.type);
+				}
+				e = this;
+			}
+		}
+		return e;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.addass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		//printf("AddAssignExp::toElem() %s\n", toChars());
+		elem *e;
+		Type tb1 = e1.type.toBasetype();
+		Type tb2 = e2.type.toBasetype();
+
+		if ((tb1.ty == TY.Tarray || tb1.ty == TY.Tsarray) && (tb2.ty == TY.Tarray || tb2.ty == TY.Tsarray))
+		{
+			error("Array operations not implemented");
+		}
+		else
+			e = toElemBin(irs, OPER.OPaddass);
+
+		return e;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AddExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,161 @@
+module dmd.AddExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Id;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.Type;
+import dmd.TOK;
+import dmd.TY;
+
+import dmd.expression.Add;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class AddExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKadd, AddExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+version (LOGSEMANTIC) {
+		printf("AddExp.semantic('%s')\n", toChars());
+}
+		if (!type)
+		{
+			BinExp.semanticp(sc);
+
+			e = op_overload(sc);
+			if (e)
+				return e;
+
+			Type tb1 = e1.type.toBasetype();
+			Type tb2 = e2.type.toBasetype();
+
+			if ((tb1.ty == TY.Tarray || tb1.ty == TY.Tsarray) &&
+				(tb2.ty == TY.Tarray || tb2.ty == TY.Tsarray) &&
+				tb1.nextOf().equals(tb2.nextOf())
+			   )
+			{
+				type = e1.type;
+				e = this;
+			}
+			else if (tb1.ty == TY.Tpointer && e2.type.isintegral() ||
+				tb2.ty == TY.Tpointer && e1.type.isintegral())
+				e = scaleFactor(sc);
+			else if (tb1.ty == TY.Tpointer && tb2.ty == TY.Tpointer)
+			{
+				incompatibleTypes();
+				type = e1.type;
+				e = this;
+			}
+			else
+			{
+				typeCombine(sc);
+				if ((e1.type.isreal() && e2.type.isimaginary()) ||
+				(e1.type.isimaginary() && e2.type.isreal()))
+				{
+					switch (type.toBasetype().ty)
+					{
+						case TY.Tfloat32:
+						case TY.Timaginary32:
+							type = Type.tcomplex32;
+							break;
+
+						case TY.Tfloat64:
+						case TY.Timaginary64:
+							type = Type.tcomplex64;
+							break;
+
+						case TY.Tfloat80:
+						case TY.Timaginary80:
+							type = Type.tcomplex80;
+							break;
+					}
+				}
+				e = this;
+			}
+			return e;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("AddExp::optimize(%s)\n", toChars());
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() && e2.isConst())
+		{
+			if (e1.op == TOK.TOKsymoff && e2.op == TOK.TOKsymoff)
+				return this;
+			e = Add(type, e1, e2);
+		}
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.add;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.add_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e;
+		Type tb1 = e1.type.toBasetype();
+		Type tb2 = e2.type.toBasetype();
+
+		if ((tb1.ty == TY.Tarray || tb1.ty == TY.Tsarray) && (tb2.ty == TY.Tarray || tb2.ty == TY.Tsarray))
+		{
+			error("Array operation %s not implemented", toChars());
+			e = el_long(type.totym(), 0);	// error recovery
+		}
+		else
+			e = toElemBin(irs, OPER.OPadd);
+
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AddrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,355 @@
+module dmd.AddrExp;
+
+import dmd.Expression;
+import dmd.UnaExp;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ErrorExp;
+import dmd.DotVarExp;
+import dmd.FuncDeclaration;
+import dmd.DelegateExp;
+import dmd.VarExp;
+import dmd.VarDeclaration;
+import dmd.ThisExp;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.CommaExp;
+import dmd.STC;
+import dmd.PtrExp;
+import dmd.SymOffExp;
+import dmd.IndexExp;
+import dmd.OverExp;
+import dmd.Dsymbol;
+import dmd.ScopeDsymbol;
+import dmd.TY;
+import dmd.TypeSArray;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+
+class AddrExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKaddress, AddrExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("AddrExp.semantic('%s')\n", toChars());
+	}
+		if (!type)
+		{
+			UnaExp.semantic(sc);
+			e1 = e1.toLvalue(sc, null);
+			if (!e1.type)
+			{
+				error("cannot take address of %s", e1.toChars());
+				return new ErrorExp();
+			}
+			if (!e1.type.deco)
+			{
+				/* No deco means semantic() was not run on the type.
+				 * We have to run semantic() on the symbol to get the right type:
+				 *	auto x = &bar;
+				 *	pure: int bar() { return 1;}
+				 * otherwise the 'pure' is missing from the type assigned to x.
+				 */
+
+				error("forward reference to %s", e1.toChars());
+				return new ErrorExp();
+			}
+
+		//printf("test3 deco = %p\n", e1.type.deco);
+			type = e1.type.pointerTo();
+
+			// See if this should really be a delegate
+			if (e1.op == TOKdotvar)
+			{
+				DotVarExp dve = cast(DotVarExp)e1;
+				FuncDeclaration f = dve.var.isFuncDeclaration();
+
+				if (f)
+				{
+					if (!dve.hasOverloads)
+						f.tookAddressOf++;
+					Expression e = new DelegateExp(loc, dve.e1, f, dve.hasOverloads);
+					e = e.semantic(sc);
+					return e;
+				}
+			}
+			else if (e1.op == TOKvar)
+			{
+				VarExp ve = cast(VarExp)e1;
+
+				VarDeclaration v = ve.var.isVarDeclaration();
+				if (v && !v.canTakeAddressOf())
+					error("cannot take address of %s", e1.toChars());
+
+				FuncDeclaration f = ve.var.isFuncDeclaration();
+
+				if (f)
+				{
+					if (!ve.hasOverloads ||
+						/* Because nested functions cannot be overloaded,
+						 * mark here that we took its address because castTo()
+						 * may not be called with an exact match.
+						 */
+						f.toParent2().isFuncDeclaration())
+						f.tookAddressOf++;
+
+					if (f.isNested())
+					{
+						Expression e = new DelegateExp(loc, e1, f, ve.hasOverloads);
+						e = e.semantic(sc);
+						return e;
+					}
+					if (f.needThis() && hasThis(sc))
+					{
+						/* Should probably supply 'this' after overload resolution,
+						 * not before.
+						 */
+						Expression ethis = new ThisExp(loc);
+						Expression e = new DelegateExp(loc, ethis, f, ve.hasOverloads);
+						e = e.semantic(sc);
+						return e;
+					}
+				}
+			}
+			return optimize(WANTvalue);
+		}
+		return this;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+
+		//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;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+	static if (false) {
+		printf("AddrExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
+		toChars(), type.toChars(), t.toChars());
+	}
+		MATCH result;
+
+		result = type.implicitConvTo(t);
+		//printf("\tresult = %d\n", result);
+
+		if (result == MATCHnomatch)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+
+			t = t.toBasetype();
+
+			if (e1.op == TOKoverloadset &&
+				(t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
+			{   
+				OverExp eo = cast(OverExp)e1;
+				FuncDeclaration f = null;
+				for (int i = 0; i < eo.vars.a.dim; i++)
+				{   
+					Dsymbol s = cast(Dsymbol)eo.vars.a.data[i];
+					FuncDeclaration f2 = s.isFuncDeclaration();
+					assert(f2);
+					if (f2.overloadExactMatch(t.nextOf()))
+					{   
+						if (f)
+							/* Error if match in more than one overload set,
+							 * even if one is a 'better' match than the other.
+							 */
+							ScopeDsymbol.multiplyDefined(loc, f, f2);
+						else
+							f = f2;
+						result = MATCHexact;
+					}
+				}
+			}
+
+			if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
+				t.ty == Tpointer && t.nextOf().ty == Tfunction &&
+				e1.op == TOKvar)
+			{
+				/* I don't think this can ever happen -
+				 * it should have been
+				 * converted to a SymOffExp.
+				 */
+				assert(0);
+				VarExp ve = cast(VarExp)e1;
+				FuncDeclaration f = ve.var.isFuncDeclaration();
+				if (f && f.overloadExactMatch(t.nextOf()))
+					result = MATCHexact;
+			}
+		}
+
+		//printf("\tresult = %d\n", result);
+		return result;
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	    Type tb;
+
+	static if (false) {
+		printf("AddrExp.castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		Expression e = this;
+
+		tb = t.toBasetype();
+		type = type.toBasetype();
+		if (tb != type)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+
+			if (e1.op == TOKoverloadset &&
+				(t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
+			{   
+				OverExp eo = cast(OverExp)e1;
+				FuncDeclaration f = null;
+				for (int i = 0; i < eo.vars.a.dim; i++)
+				{   
+					Dsymbol s = cast(Dsymbol)eo.vars.a.data[i];
+					FuncDeclaration f2 = s.isFuncDeclaration();
+					assert(f2);
+					if (f2.overloadExactMatch(t.nextOf()))
+					{   
+						if (f)
+							/* Error if match in more than one overload set,
+							 * even if one is a 'better' match than the other.
+							 */
+							ScopeDsymbol.multiplyDefined(loc, f, f2);
+						else
+							f = f2;
+					}
+				}
+				if (f)
+				{	
+					f.tookAddressOf++;
+					SymOffExp se = new SymOffExp(loc, f, 0, 0);
+					se.semantic(sc);
+					// Let SymOffExp.castTo() do the heavy lifting
+					return se.castTo(sc, t);
+				}
+			}
+
+
+			if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
+				tb.ty == Tpointer && tb.nextOf().ty == Tfunction &&
+				e1.op == TOKvar)
+			{
+				VarExp ve = cast(VarExp)e1;
+				FuncDeclaration f = ve.var.isFuncDeclaration();
+				if (f)
+				{
+					assert(0);	// should be SymOffExp instead
+					f = f.overloadExactMatch(tb.nextOf());
+					if (f)
+					{
+						e = new VarExp(loc, f);
+						e.type = f.type;
+						e = new AddrExp(loc, e);
+						e.type = t;
+						return e;
+					}
+				}
+			}
+			e = Expression.castTo(sc, t);
+		}
+		e.type = t;
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("AddrExp.optimize(result = %d) %s\n", result, toChars());
+
+		/* Rewrite &(a,b) as (a,&b)
+		 */
+		if (e1.op == TOKcomma)
+		{	
+			CommaExp ce = cast(CommaExp)e1;
+			AddrExp ae = new AddrExp(loc, ce.e2);
+			ae.type = type;
+			e = new CommaExp(ce.loc, ce.e1, ae);
+			e.type = type;
+			return e.optimize(result);
+		}
+
+		if (e1.op == TOKvar)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			if (ve.var.storage_class & STCmanifest)
+				e1 = e1.optimize(result);
+		}
+		else
+			e1 = e1.optimize(result);
+
+		// Convert &*ex to ex
+		if (e1.op == TOKstar)
+		{	
+			Expression ex;
+
+			ex = (cast(PtrExp)e1).e1;
+			if (type.equals(ex.type))
+				e = ex;
+			else
+			{
+				e = ex.copy();
+				e.type = type;
+			}
+			return e;
+		}
+		if (e1.op == TOKvar)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			if (!ve.var.isOut() && !ve.var.isRef() &&
+				!ve.var.isImportedSymbol())
+			{
+				SymOffExp se = new SymOffExp(loc, ve.var, 0, ve.hasOverloads);
+				se.type = type;
+				return se;
+			}
+		}
+		if (e1.op == TOKindex)
+		{	
+			// Convert &array[n] to &array+n
+			IndexExp ae = cast(IndexExp)e1;
+
+			if (ae.e2.op == TOKint64 && ae.e1.op == TOKvar)
+			{
+				long index = ae.e2.toInteger();
+				VarExp ve = cast(VarExp)ae.e1;
+				if (ve.type.ty == Tsarray
+					&& !ve.var.isImportedSymbol())
+				{
+					TypeSArray ts = cast(TypeSArray)ve.type;
+					long dim = ts.dim.toInteger();
+					if (index < 0 || index >= dim)
+						error("array index %jd is out of bounds [0..%jd]", index, dim);
+					e = new SymOffExp(loc, ve.var, cast(uint)(index * ts.nextOf().size()));
+					e.type = type;
+					return e;
+				}
+			}
+		}
+		return this;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AggregateDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,643 @@
+module dmd.AggregateDeclaration;
+
+import dmd.ScopeDsymbol;
+import dmd.Type;
+import dmd.Id;
+import dmd.ExpStatement;
+import dmd.AddrExp;
+import dmd.CastExp;
+import dmd.TypeSArray;
+import dmd.DotVarExp;
+import dmd.TypeStruct;
+import dmd.StructDeclaration;
+import dmd.Declaration;
+import dmd.TypeClass;
+import dmd.TOK;
+import dmd.ThisExp;
+import dmd.PROT;
+import dmd.Expression;
+import dmd.STC;
+import dmd.DotIdExp;
+import dmd.CallExp;
+import dmd.DtorDeclaration;
+import dmd.Lexer;
+import dmd.TY;
+import dmd.Array;
+import dmd.ArrayTypes;
+import dmd.VarDeclaration;
+import dmd.InvariantDeclaration;
+import dmd.NewDeclaration;
+import dmd.DeleteDeclaration;
+import dmd.CtorDeclaration;
+import dmd.FuncDeclaration;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.ClassDeclaration;
+import dmd.BaseClass;
+import dmd.Util;
+
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.Util;
+import dmd.backend.LIST;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.codegen.Util;
+
+/****************************************
+ * Determine if scope sc has package level access to s.
+ */
+
+bool hasPackageAccess(Scope sc, Dsymbol s)
+{
+version (LOG) {
+    printf("hasPackageAccess(s = '%s', sc = '%p')\n", s.toChars(), sc);
+}
+
+    for (; s; s = s.parent)
+    {
+		if (s.isPackage() && !s.isModule())
+			break;
+    }
+version (LOG) {
+    if (s)
+		printf("\tthis is in package '%s'\n", s.toChars());
+}
+
+    if (s && s == sc.module_.parent)
+    {
+version (LOG) {
+		printf("\ts is in same package as sc\n");
+}
+		return true;
+    }
+
+
+version (LOG) {
+    printf("\tno package access\n");
+}
+
+    return false;
+}
+
+/********************************************************
+ * Helper function for ClassDeclaration.accessCheck()
+ * Returns:
+ *	0	no access
+ * 	1	access
+ */
+
+bool accessCheckX(Dsymbol smember, Dsymbol sfunc, AggregateDeclaration dthis, AggregateDeclaration cdscope)
+{
+    assert(dthis);
+
+static if (false) {
+    writef("accessCheckX for %s.%s in function %s() in scope %s\n", dthis.toChars(), smember.toChars(), sfunc ? sfunc.toChars() : "null", cdscope ? cdscope.toChars() : "null");
+}
+    if (dthis.hasPrivateAccess(sfunc) || dthis.isFriendOf(cdscope))
+    {
+		if (smember.toParent() == dthis)
+			return true;
+		else
+		{
+			ClassDeclaration cdthis = dthis.isClassDeclaration();
+			if (cdthis)
+			{
+				for (int i = 0; i < cdthis.baseclasses.dim; i++)
+				{   
+					BaseClass b = cast(BaseClass)cdthis.baseclasses.data[i];
+					PROT access = b.base.getAccess(smember);
+
+					if (access >= PROT.PROTprotected || accessCheckX(smember, sfunc, b.base, cdscope))
+						return true;
+				}
+			}
+		}
+    }
+    else
+    {
+		if (smember.toParent() != dthis)
+		{
+			ClassDeclaration cdthis = dthis.isClassDeclaration();
+			if (cdthis)
+			{
+				for (int i = 0; i < cdthis.baseclasses.dim; i++)
+				{   
+					BaseClass b = cast(BaseClass)cdthis.baseclasses.data[i];
+
+					if (accessCheckX(smember, sfunc, b.base, cdscope))
+						return true;
+				}
+			}
+		}
+    }
+
+    return false;
+}
+
+class AggregateDeclaration : ScopeDsymbol
+{
+    Type type;
+    uint storage_class;
+    PROT protection = PROT.PROTpublic;
+    Type handle;		// 'this' type
+    uint structsize;	// size of struct
+    uint alignsize;		// size of struct for alignment purposes
+    uint structalign;	// struct member alignment in effect
+    int hasUnions;		// set if aggregate has overlapping fields
+    Array fields;		// VarDeclaration fields
+    uint sizeok;		// set when structsize contains valid data
+				// 0: no size
+				// 1: size is correct
+				// 2: cannot determine size; fwd referenced
+    bool isdeprecated;		// true if deprecated
+
+    bool isnested;		// true if is nested
+    VarDeclaration vthis;	// 'this' parameter if this aggregate is nested
+
+    // Special member functions
+    InvariantDeclaration inv;		// invariant
+    NewDeclaration aggNew;		// allocator
+    DeleteDeclaration aggDelete;	// deallocator
+
+version (DMDV2) {
+    //CtorDeclaration *ctor;
+    Dsymbol ctor;			// CtorDeclaration or TemplateDeclaration
+    CtorDeclaration defaultCtor;	// default constructor
+    Dsymbol aliasthis;			// forward unresolved lookups to aliasthis
+}
+
+    FuncDeclarations dtors;	// Array of destructors
+    FuncDeclaration dtor;	// aggregate destructor
+
+version (IN_GCC) {
+    Array methods;              // flat list of all methods for debug information
+}
+
+    this(Loc loc, Identifier id)
+	{
+		super(id);
+		this.loc = loc;
+		
+		fields = new Array();	///
+		dtors = new FuncDeclarations();
+	}
+
+    void semantic2(Scope sc)
+	{
+		//printf("AggregateDeclaration.semantic2(%s)\n", toChars());
+		if (scope_ && members)
+		{	
+			error("has forward references");
+			return;
+		}
+		if (members)
+		{
+			sc = sc.push(this);
+			for (size_t i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+				s.semantic2(sc);
+			}
+			sc.pop();
+		}
+	}
+
+    void semantic3(Scope sc)
+	{
+		int i;
+
+		//printf("AggregateDeclaration.semantic3(%s)\n", toChars());
+		if (members)
+		{
+			sc = sc.push(this);
+			for (i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+				s.semantic3(sc);
+			}
+			sc.pop();
+		}
+	}
+
+    void inlineScan()
+	{
+		int i;
+
+		//printf("AggregateDeclaration.inlineScan(%s)\n", toChars());
+		if (members)
+		{
+			for (i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+				//printf("inline scan aggregate symbol '%s'\n", s.toChars());
+				s.inlineScan();
+			}
+		}
+	}
+	
+    uint size(Loc loc)
+	{
+		//printf("AggregateDeclaration.size() = %d\n", structsize);
+		if (!members)
+			error(loc, "unknown size");
+
+		if (sizeok != 1)
+		{	
+			error(loc, "no size yet for forward reference");
+			//*(char*)0=0;
+		}
+
+		return structsize;
+	}
+	
+	/****************************
+	 * Do byte or word alignment as necessary.
+	 * Align sizes of 0, as we may not know array sizes yet.
+	 */
+    static void alignmember(uint salign, uint size, uint* poffset)
+	{
+		//printf("salign = %d, size = %d, offset = %d\n",salign,size,offset);
+		if (salign > 1)
+		{
+			assert(size != 3);
+			int sa = size;
+			if (sa == 0 || salign < sa)
+				sa = salign;
+			*poffset = (*poffset + sa - 1) & ~(sa - 1);
+		}
+		//printf("result = %d\n",offset);
+	}
+	
+    Type getType()
+	{
+		return type;
+	}
+	
+    void addField(Scope sc, VarDeclaration v)
+	{
+		uint memsize;		// size of member
+		uint memalignsize;	// size of member for alignment purposes
+		uint xalign;		// alignment boundaries
+
+		//printf("AggregateDeclaration.addField('%s') %s\n", v.toChars(), toChars());
+		assert(!(v.storage_class & (STC.STCstatic | STC.STCextern | STC.STCparameter | STC.STCtls)));
+
+		// Check for forward referenced types which will fail the size() call
+		Type t = v.type.toBasetype();
+		if (v.storage_class & STC.STCref)
+		{	// References are the size of a pointer
+		t = Type.tvoidptr;
+		}
+		if (t.ty == TY.Tstruct /*&& isStructDeclaration()*/)
+		{	TypeStruct ts = cast(TypeStruct)t;
+version (DMDV2) {
+		if (ts.sym == this)
+		{
+			error("cannot have field %s with same struct type", v.toChars());
+		}
+}
+
+		if (ts.sym.sizeok != 1)
+		{
+			sizeok = 2;		// cannot finish; flag as forward referenced
+			return;
+		}
+		}
+		if (t.ty == TY.Tident)
+		{
+			sizeok = 2;		// cannot finish; flag as forward referenced
+			return;
+		}
+
+		memsize = cast(uint)t.size(loc);		///
+		memalignsize = t.alignsize();
+		xalign = t.memalign(sc.structalign);
+		alignmember(xalign, memalignsize, &sc.offset);
+		v.offset = sc.offset;
+		sc.offset += memsize;
+		if (sc.offset > structsize)
+		structsize = sc.offset;
+		if (sc.structalign < memalignsize)
+		memalignsize = sc.structalign;
+		if (alignsize < memalignsize)
+		alignsize = memalignsize;
+		//printf("\talignsize = %d\n", alignsize);
+
+		v.storage_class |= STC.STCfield;
+		//printf(" addField '%s' to '%s' at offset %d, size = %d\n", v.toChars(), toChars(), v.offset, memsize);
+		fields.push(cast(void*)v);
+	}
+	
+    bool isDeprecated()		// is aggregate deprecated?
+	{
+		return isdeprecated;
+	}
+
+	/*****************************************
+	 * Create inclusive destructor for struct/class by aggregating
+	 * all the destructors in dtors[] with the destructors for
+	 * all the members.
+	 * Note the close similarity with StructDeclaration.buildPostBlit(),
+	 * and the ordering changes (runs backward instead of forwards).
+	 */
+    FuncDeclaration buildDtor(Scope sc)
+	{
+		 //printf("AggregateDeclaration.buildDtor() %s\n", toChars());
+		Expression e = null;
+
+version (DMDV2) {
+		for (size_t i = 0; i < fields.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)fields.data[i];
+			VarDeclaration v = s.isVarDeclaration();
+			assert(v && v.storage_class & STC.STCfield);
+			if (v.storage_class & STC.STCref)
+				continue;
+			Type tv = v.type.toBasetype();
+			size_t dim = 1;
+			while (tv.ty == TY.Tsarray)
+			{   TypeSArray ta = cast(TypeSArray)tv;
+				dim *= (cast(TypeSArray)tv).dim.toInteger();
+				tv = tv.nextOf().toBasetype();
+			}
+			if (tv.ty == TY.Tstruct)
+			{   TypeStruct ts = cast(TypeStruct)tv;
+				StructDeclaration sd = ts.sym;
+				if (sd.dtor)
+				{	
+					Expression ex;
+
+					// this.v
+					ex = new ThisExp(Loc(0));
+					ex = new DotVarExp(Loc(0), ex, v, 0);
+
+					if (dim == 1)
+					{   
+						// this.v.dtor()
+						ex = new DotVarExp(Loc(0), ex, sd.dtor, 0);
+						ex = new CallExp(Loc(0), ex);
+					}
+					else
+					{
+						// Typeinfo.destroy(cast(void*)&this.v);
+						Expression ea = new AddrExp(Loc(0), ex);
+						ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo());
+
+						Expression et = v.type.getTypeInfo(sc);
+						et = new DotIdExp(Loc(0), et, Id.destroy);
+
+						ex = new CallExp(Loc(0), et, ea);
+					}
+					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(Loc(0), Loc(0), Lexer.idPool("__fieldDtor"));
+			dd.fbody = new ExpStatement(Loc(0), e);
+			dtors.shift(cast(void*)dd);
+			members.push(cast(void*)dd);
+			dd.semantic(sc);
+		}
+}
+
+		switch (dtors.dim)
+		{
+			case 0:
+				return null;
+
+			case 1:
+				return cast(FuncDeclaration)dtors.data[0];
+
+			default:
+				e = null;
+				for (size_t i = 0; i < dtors.dim; i++)
+				{
+					FuncDeclaration fd = cast(FuncDeclaration)dtors.data[i];
+					Expression ex = new ThisExp(Loc(0));
+					ex = new DotVarExp(Loc(0), ex, fd, 0);
+					ex = new CallExp(Loc(0), ex);
+					e = Expression.combine(ex, e);
+				}
+				DtorDeclaration dd = new DtorDeclaration(Loc(0), Loc(0), Lexer.idPool("__aggrDtor"));
+				dd.fbody = new ExpStatement(Loc(0), e);
+				members.push(cast(void*)dd);
+				dd.semantic(sc);
+				return dd;
+		}
+	}
+
+	/****************************************
+	 * Returns true if there's an extra member which is the 'this'
+	 * pointer to the enclosing context (enclosing aggregate or function)
+	 */
+    bool isNested()
+	{
+		return isnested;
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    // For access checking
+    PROT getAccess(Dsymbol smember)	// determine access to smember
+	{
+		assert(false);
+	}
+
+	/****************************************
+	 * Determine if this is the same or friend of cd.
+	 */
+    bool isFriendOf(AggregateDeclaration cd)
+	{
+version (LOG) {
+		printf("AggregateDeclaration.isFriendOf(this = '%s', cd = '%s')\n", toChars(), cd ? cd.toChars() : "null");
+}
+		if (this is cd)
+			return true;
+
+		// Friends if both are in the same module
+		//if (toParent() == cd.toParent())
+		if (cd && getModule() == cd.getModule())
+		{
+version (LOG) {
+			printf("\tin same module\n");
+}
+			return true;
+		}
+
+version (LOG) {
+		printf("\tnot friend\n");
+}
+		return false;
+	}
+	
+	/**********************************
+	 * Determine if smember has access to private members of this declaration.
+	 */
+    bool hasPrivateAccess(Dsymbol smember)	// does smember have private access to members of this class?
+	{
+		if (smember)
+		{
+			AggregateDeclaration cd = null;
+			Dsymbol smemberparent = smember.toParent();
+			if (smemberparent)
+				cd = smemberparent.isAggregateDeclaration();
+
+		version (LOG) {
+			printf("AggregateDeclaration::hasPrivateAccess(class %s, member %s)\n", toChars(), smember.toChars());
+		}
+
+			if (this == cd)		// smember is a member of this class
+			{
+		version (LOG) {
+				printf("\tyes 1\n");
+		}
+				return true;		// so we get private access
+			}
+
+			// If both are members of the same module, grant access
+			while (true)
+			{   
+				Dsymbol sp = smember.toParent();
+				if (sp.isFuncDeclaration() && smember.isFuncDeclaration())
+					smember = sp;
+				else
+					break;
+			}
+			if (!cd && toParent() == smember.toParent())
+			{
+		version (LOG) {
+				printf("\tyes 2\n");
+		}
+				return true;
+			}
+			if (!cd && getModule() == smember.getModule())
+			{
+		version (LOG) {
+				printf("\tyes 3\n");
+		}
+				return true;
+			}
+		}
+	version (LOG) {
+		printf("\tno\n");
+	}
+		return false;
+	}
+	
+	/*******************************
+	 * Do access check for member of this class, this class being the
+	 * type of the 'this' pointer used to access smember.
+	 */
+    void accessCheck(Loc loc, Scope sc, Dsymbol smember)
+	{
+		bool result;
+
+		FuncDeclaration f = sc.func;
+		AggregateDeclaration cdscope = sc.getStructClassScope();
+		PROT access;
+
+version (LOG) {
+		printf("AggregateDeclaration.accessCheck() for %s.%s in function %s() in scope %s\n", toChars(), smember.toChars(), f ? f.toChars() : null, cdscope ? cdscope.toChars() : null);
+}
+
+		Dsymbol smemberparent = smember.toParent();
+		if (!smemberparent || !smemberparent.isAggregateDeclaration())
+		{
+	version (LOG) {
+			printf("not an aggregate member\n");
+	}
+			return;				// then it is accessible
+		}
+
+		// BUG: should enable this check
+		//assert(smember.parent.isBaseOf(this, null));
+
+		if (smemberparent == this)
+		{	
+			PROT access2 = smember.prot();
+
+			result = access2 >= PROT.PROTpublic ||
+				hasPrivateAccess(f) ||
+				isFriendOf(cdscope) ||
+				(access2 == PROT.PROTpackage && hasPackageAccess(sc, this));
+
+version (LOG) {
+			printf("result1 = %d\n", result);
+}
+		}
+		else if ((access = this.getAccess(smember)) >= PROT.PROTpublic)
+		{
+			result = true;
+version (LOG) {
+			printf("result2 = %d\n", result);
+}
+		}
+		else if (access == PROT.PROTpackage && hasPackageAccess(sc, this))
+		{
+			result = true;
+version (LOG) {
+			printf("result3 = %d\n", result);
+}
+		}
+		else
+		{
+			result = accessCheckX(smember, f, this, cdscope);
+version (LOG) {
+			printf("result4 = %d\n", result);
+}
+		}
+		if (!result)
+		{
+			error(loc, "member %s is not accessible", smember.toChars());
+			halt();
+		}
+	}
+
+    PROT prot()
+	{
+		assert(false);
+	}
+
+    // Back end
+    Symbol* stag;		// tag symbol for debug data
+    Symbol* sinit;
+
+    Symbol* toInitializer()
+	{
+		Symbol* s;
+		Classsym* stag;
+
+		if (!sinit)
+		{
+			stag = fake_classsym(Id.ClassInfo);
+			s = toSymbolX("__init", SC.SCextern, stag.Stype, "Z");
+			s.Sfl = FL.FLextern;
+			s.Sflags |= SFL.SFLnodebug;
+			slist_add(s);
+			sinit = s;
+		}
+
+		return sinit;
+	}
+
+    AggregateDeclaration isAggregateDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AliasDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,233 @@
+module dmd.AliasDeclaration;
+
+import dmd.LINK;
+import dmd.Declaration;
+import dmd.TypedefDeclaration;
+import dmd.VarDeclaration;
+import dmd.FuncDeclaration;
+import dmd.FuncAliasDeclaration;
+import dmd.Dsymbol;
+import dmd.ScopeDsymbol;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.STC;
+import dmd.Expression;
+import dmd.Global;
+
+class AliasDeclaration : Declaration
+{
+    Dsymbol aliassym;
+    Dsymbol overnext;		// next in overload list
+    int inSemantic;
+
+    this(Loc loc, Identifier ident, Type type)
+	{
+		super(ident);
+		
+		//printf("AliasDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
+		//printf("type = '%s'\n", type.toChars());
+		this.loc = loc;
+		this.type = type;
+		this.aliassym = null;
+	version (_DH) {
+		this.htype = null;
+		this.haliassym = null;
+	}
+
+		assert(type);
+	}
+	
+    this(Loc loc, Identifier id, Dsymbol s)
+	{
+		super(id);
+		
+		//printf("AliasDeclaration(id = '%s', s = %p)\n", id->toChars(), s);
+		assert(s !is this);	/// huh?
+		this.loc = loc;
+		this.type = null;
+		this.aliassym = s;
+	version (_DH) {
+		this.htype = null;
+		this.haliassym = null;
+	}
+		assert(s);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("AliasDeclaration.semantic() %s\n", toChars());
+		if (aliassym)
+		{
+			if (aliassym.isTemplateInstance())
+				aliassym.semantic(sc);
+			return;
+		}
+		this.inSemantic = 1;
+
+		if (storage_class & STC.STCconst)
+			error("cannot be const");
+
+		storage_class |= sc.stc & STC.STCdeprecated;
+
+		// Given:
+		//	alias foo.bar.abc def;
+		// it is not knowable from the syntax whether this is an alias
+		// for a type or an alias for a symbol. It is up to the semantic()
+		// pass to distinguish.
+		// If it is a type, then type is set and getType() will return that
+		// type. If it is a symbol, then aliassym is set and type is null -
+		// toAlias() will return aliasssym.
+
+		Dsymbol s;
+		Type t;
+		Expression e;
+
+		/* This section is needed because resolve() will:
+		 *   const x = 3;
+		 *   alias x y;
+		 * try to alias y to 3.
+		 */
+		s = type.toDsymbol(sc);
+		if (s && ((s.getType() && type.equals(s.getType())) || s.isEnumMember()))
+			goto L2;			// it's a symbolic alias
+
+///version (DMDV2) {
+		if (storage_class & STC.STCref)
+		{	// For 'ref' to be attached to function types, and picked
+			// up by Type.resolve(), it has to go into sc.
+			sc = sc.push();
+			sc.stc |= STC.STCref;
+			type.resolve(loc, sc, &e, &t, &s);
+			sc = sc.pop();
+		}
+		else
+///	#endif
+		type.resolve(loc, sc, &e, &t, &s);
+		if (s)
+		{
+			goto L2;
+		}
+		else if (e)
+		{
+			// Try to convert Expression to Dsymbol
+			s = getDsymbol(e);
+			if (s)
+				goto L2;
+
+			error("cannot alias an expression %s", e.toChars());
+			t = e.type;
+		}
+		else if (t)
+		{
+			type = t;
+		}
+		if (overnext)
+			ScopeDsymbol.multiplyDefined(Loc(0), this, overnext);
+		this.inSemantic = 0;
+		return;
+
+	  L2:
+		//printf("alias is a symbol %s %s\n", s.kind(), s.toChars());
+		type = null;
+		VarDeclaration v = s.isVarDeclaration();
+		if (v && v.linkage == LINK.LINKdefault)
+		{
+			error("forward reference of %s", v.toChars());
+			s = null;
+		}
+		else
+		{
+			FuncDeclaration f = s.toAlias().isFuncDeclaration();
+			if (f)
+			{
+				if (overnext)
+				{
+					FuncAliasDeclaration fa = new FuncAliasDeclaration(f);
+					if (!fa.overloadInsert(overnext))
+						ScopeDsymbol.multiplyDefined(Loc(0), f, overnext);
+					overnext = null;
+					s = fa;
+					s.parent = sc.parent;
+				}
+			}
+			if (overnext)
+				ScopeDsymbol.multiplyDefined(Loc(0), s, overnext);
+			if (s == this)
+			{
+				assert(global.errors);
+				s = null;
+			}
+		}
+		//printf("setting aliassym %p to %p\n", this, s);
+		aliassym = s;
+		this.inSemantic = 0;
+	}
+	
+    bool overloadInsert(Dsymbol s)
+	{
+		/* Don't know yet what the aliased symbol is, so assume it can
+		 * be overloaded and check later for correctness.
+		 */
+
+		//printf("AliasDeclaration.overloadInsert('%s')\n", s.toChars());
+		if (overnext is null)
+		{	
+			overnext = s;
+			return true;
+		}
+		else
+		{
+			return overnext.overloadInsert(s);
+		}
+	}
+	
+    string kind()
+	{
+		return "alias";
+	}
+	
+    Type getType()
+	{
+		return type;
+	}
+    
+	Dsymbol toAlias()
+	{
+		//printf("AliasDeclaration::toAlias('%s', this = %p, aliassym = %p, kind = '%s')\n", toChars(), this, aliassym, aliassym ? aliassym->kind() : "");
+		assert(this !is aliassym);
+		//static int count; if (++count == 10) *(char*)0=0;
+		if (inSemantic)
+		{
+			error("recursive alias declaration");
+			aliassym = new TypedefDeclaration(loc, ident, Type.terror, null);
+		}
+
+		Dsymbol s = aliassym ? aliassym.toAlias() : this;
+		return s;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+version (_DH) {
+    Type htype;
+    Dsymbol haliassym;
+}
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    AliasDeclaration isAliasDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AliasThis.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,41 @@
+module dmd.AliasThis;
+
+import dmd.Dsymbol;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class AliasThis : Dsymbol
+{
+   // alias Identifier this;
+    Identifier ident;
+
+    this(Loc loc, Identifier ident)
+	{
+		assert(false);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+		
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    AliasThis isAliasThis() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AlignDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,47 @@
+module dmd.AlignDeclaration;
+
+import dmd.AttribDeclaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.Array;
+
+class AlignDeclaration : AttribDeclaration
+{
+    uint salign;
+
+    this(uint sa, Array decl)
+	{
+		super(decl);
+		salign = sa;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void setScope(Scope sc)
+	{
+		//printf("\tAlignDeclaration::setScope '%s'\n",toChars());
+		if (decl)
+		{
+			setScopeNewSc(sc, sc.stc, sc.linkage, sc.protection, sc.explicitProtection, salign);
+		}
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("\tAlignDeclaration::semantic '%s'\n",toChars());
+		if (decl)
+		{
+			semanticNewSc(sc, sc.stc, sc.linkage, sc.protection, sc.explicitProtection, salign);
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AndAndExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,126 @@
+module dmd.AndAndExp;
+
+import dmd.Expression;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.CommaExp;
+import dmd.Global;
+import dmd.BoolExp;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.IntegerExp;
+import dmd.Type;
+import dmd.TY;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class AndAndExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKandand, AndAndExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		uint cs1;
+
+		// same as for OrOr
+		e1 = e1.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		e1 = e1.checkToPointer();
+		e1 = e1.checkToBoolean();
+		cs1 = sc.callSuper;
+
+		if (sc.flags & SCOPE.SCOPEstaticif)
+		{
+			/* If in static if, don't evaluate e2 if we don't have to.
+			 */
+			e1 = e1.optimize(WANTflags);
+			if (e1.isBool(false))
+			{
+				return new IntegerExp(loc, 0, Type.tboolean);
+			}
+		}
+
+		e2 = e2.semantic(sc);
+		sc.mergeCallSuper(loc, cs1);
+		e2 = resolveProperties(sc, e2);
+		e2 = e2.checkToPointer();
+
+		type = Type.tboolean;
+		if (e2.type.ty == Tvoid)
+			type = Type.tvoid;
+		if (e2.op == TOKtype || e2.op == TOKimport)
+			error("%s is not an expression", e2.toChars());
+		return this;
+	}
+
+	Expression checkToBoolean()
+	{
+		e2 = e2.checkToBoolean();
+		return this;
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("AndAndExp::optimize(%d) %s\n", result, toChars());
+		e1 = e1.optimize(WANTflags | (result & WANTinterpret));
+		Expression e = this;
+		if (e1.isBool(false))
+		{
+			e = new CommaExp(loc, e1, new IntegerExp(loc, 0, type));
+			e.type = type;
+			e = e.optimize(result);
+		}
+		else
+		{
+			e2 = e2.optimize(WANTflags | (result & WANTinterpret));
+			if (result && e2.type.toBasetype().ty == Tvoid && !global.errors)
+				error("void has no value");
+
+			if (e1.isConst())
+			{
+				if (e2.isConst())
+				{	
+					int n1 = e1.isBool(1);
+					int n2 = e2.isBool(1);
+
+					e = new IntegerExp(loc, n1 && n2, type);
+				}
+				else if (e1.isBool(true))
+					e = new BoolExp(loc, e2, type);
+			}
+		}
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	elem* 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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AndAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,54 @@
+module dmd.AndAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Id;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+
+class AndAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKandass, AndAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		return commonSemanticAssignIntegral(sc);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.andass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPER.OPandass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AndExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,116 @@
+module dmd.AndExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.ArrayTypes;
+import dmd.TY;
+import dmd.Type;
+import dmd.Id;
+import dmd.Global;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.expression.Util;
+import dmd.expression.And;
+
+class AndExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKand, AndExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+
+			if (e)
+				return e;
+
+			if (e1.type.toBasetype().ty == TY.Tbool && e2.type.toBasetype().ty == TY.Tbool)
+			{
+				type = e1.type;
+				e = this;
+			}
+			else
+			{
+				typeCombine(sc);
+				if (e1.op != TOK.TOKslice && e2.op != TOK.TOKslice)
+				{   
+					e1.checkIntegral();
+					e2.checkIntegral();
+				}
+			}
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() == 1 && e2.isConst() == 1)
+			e = And(type, e1, e2);
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.iand;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.iand_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPER.OPand);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AnonDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,169 @@
+module dmd.AnonDeclaration;
+
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Array;
+import dmd.AttribDeclaration;
+import dmd.HdrGenState;
+import dmd.Dsymbol;
+import dmd.AggregateDeclaration;
+import dmd.AnonymousAggregateDeclaration;
+import dmd.STC;
+import dmd.Module;
+import dmd.VarDeclaration;
+
+class AnonDeclaration : AttribDeclaration
+{
+	int isunion;
+	int sem = 0;			// 1 if successful semantic()
+
+	this(Loc loc, int isunion, Array decl)
+	{
+		super(decl);
+		this.loc = loc;
+		this.isunion = isunion;
+	}
+
+	Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+
+	void semantic(Scope sc)
+	{
+		//printf("\tAnonDeclaration::semantic %s %p\n", isunion ? "union" : "struct", this);
+
+		Scope scx = null;
+		if (scope_)
+		{   
+			sc = scope_;
+			scx = scope_;
+			scope_ = null;
+		}
+
+		assert(sc.parent);
+
+		Dsymbol parent = sc.parent.pastMixin();
+		AggregateDeclaration ad = parent.isAggregateDeclaration();
+
+		if (!ad || (!ad.isStructDeclaration() && !ad.isClassDeclaration()))
+		{
+			error("can only be a part of an aggregate");
+			return;
+		}
+
+		if (decl)
+		{
+			AnonymousAggregateDeclaration aad = new AnonymousAggregateDeclaration();
+			int adisunion;
+
+			if (sc.anonAgg)
+			{   
+				ad = sc.anonAgg;
+				adisunion = sc.inunion;
+			}
+			else
+				adisunion = ad.isUnionDeclaration() !is null;
+
+		//	printf("\tsc.anonAgg = %p\n", sc.anonAgg);
+		//	printf("\tad  = %p\n", ad);
+		//	printf("\taad = %p\n", &aad);
+
+			sc = sc.push();
+			sc.anonAgg = aad;
+			sc.stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCgshared);
+			sc.inunion = isunion;
+			sc.offset = 0;
+			sc.flags = cast(SCOPE)0;
+			aad.structalign = sc.structalign;
+			aad.parent = ad;
+
+			for (uint i = 0; i < decl.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)decl.data[i];
+
+				s.semantic(sc);
+				if (isunion)
+					sc.offset = 0;
+				if (aad.sizeok == 2)
+					break;
+			}
+			sc = sc.pop();
+
+			// If failed due to forward references, unwind and try again later
+			if (aad.sizeok == 2)
+			{
+				ad.sizeok = 2;
+				//printf("\tsetting ad.sizeok %p to 2\n", ad);
+				if (!sc.anonAgg)
+				{
+					scope_ = scx ? scx : new Scope(sc);	///<
+					scope_.setNoFree();
+					scope_.module_.addDeferredSemantic(this);
+				}
+				//printf("\tforward reference %p\n", this);
+				return;
+			}
+			if (sem == 0)
+			{   
+				Module.dprogress++;
+				sem = 1;
+				//printf("\tcompleted %p\n", this);
+			}
+			else {
+				;//printf("\talready completed %p\n", this);
+			}
+
+			// 0 sized structs are set to 1 byte
+			if (aad.structsize == 0)
+			{
+				aad.structsize = 1;
+				aad.alignsize = 1;
+			}
+
+			// Align size of anonymous aggregate
+		//printf("aad.structalign = %d, aad.alignsize = %d, sc.offset = %d\n", aad.structalign, aad.alignsize, sc.offset);
+			ad.alignmember(aad.structalign, aad.alignsize, &sc.offset);
+			//ad.structsize = sc.offset;
+		//printf("sc.offset = %d\n", sc.offset);
+
+			// Add members of aad to ad
+			//printf("\tadding members of aad to '%s'\n", ad.toChars());
+			for (uint i = 0; i < aad.fields.dim; i++)
+			{
+				VarDeclaration v = cast(VarDeclaration)aad.fields.data[i];
+
+				v.offset += sc.offset;
+				ad.fields.push(cast(void*)v);
+			}
+
+			// Add size of aad to ad
+			if (adisunion)
+			{
+				if (aad.structsize > ad.structsize)
+				ad.structsize = aad.structsize;
+				sc.offset = 0;
+			}
+			else
+			{
+				ad.structsize = sc.offset + aad.structsize;
+				sc.offset = ad.structsize;
+			}
+
+			if (ad.alignsize < aad.alignsize)
+				ad.alignsize = aad.alignsize;
+		}
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	string kind()
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AnonymousAggregateDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.AnonymousAggregateDeclaration;
+
+import dmd.AggregateDeclaration;
+import dmd.Loc;
+
+class AnonymousAggregateDeclaration : AggregateDeclaration
+{
+    this()
+    {
+		super(Loc(0), null);
+    }
+
+    AnonymousAggregateDeclaration isAnonymousAggregateDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Argument.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,278 @@
+module dmd.Argument;
+
+import dmd.Type;
+import dmd.Identifier;
+import dmd.TypeTuple;
+import dmd.TY;
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.StorageClassDeclaration;
+import dmd.Global;
+import dmd.MOD;
+import dmd.CppMangleState;
+import dmd.STC;
+
+class Argument
+{
+    //enum InOut inout;
+    STC storageClass;
+    Type type;
+    Identifier ident;
+    Expression defaultArg;
+
+    this(STC storageClass, Type type, Identifier ident, Expression defaultArg)
+	{
+		this.type = type;
+		this.ident = ident;
+		this.storageClass = storageClass;
+		this.defaultArg = defaultArg;
+	}
+	
+	Argument clone()
+	{
+		return new Argument(storageClass, type, ident, defaultArg);
+	}
+	
+    Argument syntaxCopy()
+	{
+		return new Argument(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null);
+	}
+	
+    Type isLazyArray()
+	{
+		assert(false);
+	}
+	
+    void toDecoBuffer(OutBuffer buf)
+	{
+		if (storageClass & STC.STCscope)
+			buf.writeByte('M');
+		switch (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy))
+		{   
+			case STC.STCundefined:
+			case STC.STCin:
+				break;
+			case STC.STCout:
+				buf.writeByte('J');
+				break;
+			case STC.STCref:
+				buf.writeByte('K');
+				break;
+			case STC.STClazy:
+				buf.writeByte('L');
+				break;
+		}
+static if (false) {
+		int mod = 0x100;
+		if (type.toBasetype().ty == TY.Tclass)
+			mod = 0;
+		type.toDecoBuffer(buf, mod);
+} else {
+		//type.toHeadMutable().toDecoBuffer(buf, 0);
+		type.toDecoBuffer(buf, 0);
+}
+	}
+	
+    static Arguments arraySyntaxCopy(Arguments args)
+	{
+		Arguments a = null;
+
+		if (args)
+		{
+			a = new Arguments();
+			a.setDim(args.dim);
+
+			for (size_t i = 0; i < a.dim; i++)
+			{   
+				Argument arg = cast(Argument)args.data[i];
+
+				arg = arg.syntaxCopy();
+				a.data[i] = cast(void*)arg;
+			}
+		}
+	
+		return a;
+	}
+	
+    static string argsTypesToChars(Arguments args, int varargs)
+	{
+		scope OutBuffer buf = new OutBuffer();
+
+	static if (true) {
+		HdrGenState hgs;
+		argsToCBuffer(buf, &hgs, args, varargs);
+	} else {
+		buf.writeByte('(');
+		if (args)
+		{	
+			OutBuffer argbuf;
+			HdrGenState hgs;
+
+			for (int i = 0; i < args.dim; i++)
+			{   
+				if (i)
+					buf.writeByte(',');
+				Argument arg = cast(Argument)args.data[i];
+				argbuf.reset();
+				arg.type.toCBuffer2(&argbuf, &hgs, 0);
+				buf.write(&argbuf);
+			}
+			if (varargs)
+			{
+				if (i && varargs == 1)
+					buf.writeByte(',');
+				buf.writestring("...");
+			}
+		}
+		buf.writeByte(')');
+	}
+		return buf.toChars();
+	}
+	
+    static void argsCppMangle(OutBuffer buf, CppMangleState* cms, Arguments arguments, int varargs)
+	{
+		assert(false);
+	}
+	
+    static void argsToCBuffer(OutBuffer buf, HdrGenState* hgs, Arguments arguments, int varargs)
+	{
+		buf.writeByte('(');
+		if (arguments)
+		{	
+			int i;
+			scope OutBuffer argbuf = new OutBuffer();
+
+			for (i = 0; i < arguments.dim; i++)
+			{
+				if (i)
+					buf.writestring(", ");
+				Argument arg = cast(Argument)arguments.data[i];
+
+				if (arg.storageClass & STCout)
+					buf.writestring("out ");
+				else if (arg.storageClass & STCref)
+					buf.writestring((global.params.Dversion == 1) ? "inout " : "ref ");
+				else if (arg.storageClass & STCin)
+					buf.writestring("in ");
+				else if (arg.storageClass & STClazy)
+					buf.writestring("lazy ");
+				else if (arg.storageClass & STCalias)
+					buf.writestring("alias ");
+				else if (arg.storageClass & STCauto)
+					buf.writestring("auto ");
+
+				uint stc = arg.storageClass;
+				if (arg.type && arg.type.mod & MODshared)
+					stc &= ~STCshared;
+
+				StorageClassDeclaration.stcToCBuffer(buf, stc & (STCconst | STCimmutable | STCshared | STCscope));
+
+				argbuf.reset();
+				if (arg.storageClass & STCalias)
+				{	
+					if (arg.ident)
+						argbuf.writestring(arg.ident.toChars());
+				}
+				else
+					arg.type.toCBuffer(argbuf, arg.ident, hgs);
+				if (arg.defaultArg)
+				{
+					argbuf.writestring(" = ");
+					arg.defaultArg.toCBuffer(argbuf, hgs);
+				}
+				buf.write(argbuf);
+			}
+			if (varargs)
+			{
+				if (i && varargs == 1)
+					buf.writeByte(',');
+				buf.writestring("...");
+			}
+		}
+		buf.writeByte(')');
+	}
+	
+    static void argsToDecoBuffer(OutBuffer buf, Arguments arguments)
+	{
+		//printf("Argument::argsToDecoBuffer()\n");
+
+		// Write argument types
+		if (arguments)
+		{
+			size_t dim = Argument.dim(arguments);
+			for (size_t i = 0; i < dim; i++)
+			{
+				Argument arg = Argument.getNth(arguments, i);
+				arg.toDecoBuffer(buf);
+			}
+		}
+	}
+	
+    static int isTPL(Arguments arguments)
+	{
+		assert(false);
+	}
+
+	/***************************************
+	 * Determine number of arguments, folding in tuples.
+	 */	
+    static size_t dim(Arguments args)
+	{
+		size_t n = 0;
+		if (args)
+		{
+			for (size_t i = 0; i < args.dim; i++)
+			{   
+				Argument arg = cast(Argument)args.data[i];
+				Type t = arg.type.toBasetype();
+
+				if (t.ty == TY.Ttuple)
+				{   
+					TypeTuple tu = cast(TypeTuple)t;
+					n += dim(tu.arguments);
+				}
+				else
+					n++;
+			}
+		}
+		return n;
+	}
+	
+	/***************************************
+	 * Get nth Argument, folding in tuples.
+	 * Returns:
+	 *	Argument	nth Argument
+	 *	null		not found, *pn gets incremented by the number
+	 *			of Arguments
+	 */
+    static Argument getNth(Arguments args, size_t nth, size_t* pn = null)
+	{
+		if (!args)
+			return null;
+
+		size_t n = 0;
+		for (size_t i = 0; i < args.dim; i++)
+		{   
+			Argument arg = cast(Argument)args.data[i];
+			Type t = arg.type.toBasetype();
+
+			if (t.ty == TY.Ttuple)
+			{   TypeTuple tu = cast(TypeTuple)t;
+				arg = getNth(tu.arguments, nth - n, &n);
+				if (arg)
+					return arg;
+			}
+			else if (n == nth)
+				return arg;
+			else
+				n++;
+		}
+
+		if (pn)
+			*pn += n;
+
+		return null;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Array.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,183 @@
+module dmd.Array;
+
+import std.contracts;
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class Array
+{
+	uint dim = 0;
+    uint allocdim = 0;
+    void** data = null;
+
+    ~this()
+	{
+		///mem.free(data);
+		free(data);
+	}
+	
+    void mark()
+	{
+		///unsigned u;
+		///mem.mark(data);
+		///for (u = 0; u < dim; u++)
+		///mem.mark(data[u]);	// BUG: what if arrays of Object's?
+	}
+	
+    string toString()
+	{
+		char *p;
+
+		///char **buf = cast(char**)alloca(dim * (char*).sizeof);
+		scope string[] buf = new string[dim];
+		uint len = 2;
+		for (uint u = 0; u < dim; u++) {
+			buf[u] = (cast(Object)data[u]).toString();
+			len += buf[u].length + 1;
+		}
+
+		char* str = cast(char*)malloc(len);
+
+		str[0] = '[';
+		p = str + 1;
+
+		for (uint u = 0; u < dim; u++)
+		{
+			if (u != 0) {
+				*p++ = ',';
+			}
+			uint length = buf[u].length;
+			p[0..length] = buf[u][];
+
+			p += length;
+		}
+
+		*p++ = ']';
+		*p = 0;
+
+		return assumeUnique(str[0..len]);
+	}
+
+    final void reserve(uint nentries)
+	{
+		//printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+		if (allocdim - dim < nentries) {
+			allocdim = dim + nentries;
+			/// data = (void **)mem.realloc(data, allocdim * sizeof(*data));
+			data = cast(void**)realloc(data, allocdim * (*data).sizeof);
+		}
+	}
+	
+    final void setDim(uint newdim)
+	{
+		if (dim < newdim) {
+			reserve(newdim - dim);
+		}
+
+		dim = newdim;
+	}
+	
+    final void fixDim()
+	{
+		if (dim != allocdim)
+		{
+			///data = (void**)mem.realloc(data, dim * sizeof(*data));
+			data = cast(void**)realloc(data, dim * (*data).sizeof);
+			allocdim = dim;
+		}
+	}
+	
+    final void push(void* ptr)
+	{
+		reserve(1);
+		data[dim++] = ptr;
+	}
+
+    final void* pop()
+	{
+		return data[--dim];
+	}
+	
+    final void shift(void* ptr)
+	{
+		reserve(1);
+		memmove(data + 1, data, dim * (*data).sizeof);
+		data[0] = ptr;
+		dim++;
+	}
+	
+    final void insert(uint index, void* ptr)
+	{
+		reserve(1);
+		memmove(data + index + 1, data + index, (dim - index) * (*data).sizeof);
+		data[index] = ptr;
+		dim++;
+	}
+	
+    final void insert(uint index, Array a)
+	{
+		if (a !is null) {
+			uint d = a.dim;
+			reserve(d);
+
+			if (dim != index) {
+				memmove(data + index + d, data + index, (dim - index) * (*data).sizeof);
+			}
+
+			memcpy(data + index, a.data, d * (*data).sizeof);
+			dim += d;
+		}
+	}
+	
+	/***********************************
+	 * Append array a to this array.
+	 */
+    final void append(Array a)
+	{
+		insert(dim, a);
+	}
+
+    final void remove(uint i)
+	{
+		memmove(data + i, data + i + 1, (dim - i) * (*data).sizeof);
+		dim--;
+	}
+	
+    final void zero()
+	{
+		memset(data, 0, dim * (*data).sizeof);
+	}
+
+    final void* tos()
+	{
+		return dim ? data[dim - 1] : null;
+	}
+
+	private static extern (C) int Array_sort_compare(const(void*) x, const(void*) y)
+	{
+		Object ox = *cast(Object *)x;
+		Object oy = *cast(Object *)y;
+
+		return ox.opCmp(oy);
+	}
+
+    final void sort()
+	{
+		if (dim) {
+			qsort(cast(void*)data, dim, Object.sizeof, &Array_sort_compare);
+		}
+	}
+	
+	final Array copyTo(Array a)
+	{
+		a.setDim(dim);
+		memcpy(a.data, data, dim * (*data).sizeof);
+
+		return a;
+	}
+
+    final Array copy()
+	{
+		return copyTo(new Array());
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,132 @@
+module dmd.ArrayExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+import dmd.Id;
+import dmd.IndexExp;
+
+import dmd.expression.Util;
+
+class ArrayExp : UnaExp
+{
+	Expressions arguments;
+
+	this(Loc loc, Expression e1, Expressions args)
+	{
+		super(loc, TOK.TOKarray, ArrayExp.sizeof, e1);
+		arguments = args;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t1;
+
+	version (LOGSEMANTIC) {
+		printf("ArrayExp::semantic('%s')\n", toChars());
+	}
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+
+		t1 = e1.type.toBasetype();
+		if (t1.ty != Tclass && t1.ty != Tstruct)
+		{	
+			// Convert to IndexExp
+			if (arguments.dim != 1)
+				error("only one index allowed to index %s", t1.toChars());
+			e = new IndexExp(loc, e1, cast(Expression)arguments.data[0]);
+			return e.semantic(sc);
+		}
+
+		// Run semantic() on each argument
+		for (size_t i = 0; i < arguments.dim; i++)
+		{	
+			e = cast(Expression)arguments.data[i];
+
+			e = e.semantic(sc);
+			if (!e.type)
+				error("%s has no value", e.toChars());
+			arguments.data[i] = cast(void*)e;
+		}
+
+		expandTuples(arguments);
+		assert(arguments && arguments.dim);
+
+		e = op_overload(sc);
+		if (!e)
+		{
+			error("no [] operator overload for type %s", e1.type.toChars());
+			e = e1;
+		}
+		return e;
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.index;
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics) + arrayInlineCost(ics, arguments);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		ArrayExp ce;
+
+		ce = cast(ArrayExp)copy();
+		ce.e1 = e1.doInline(ids);
+		ce.arguments = arrayExpressiondoInline(arguments, ids);
+		return ce;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		Expression e = this;
+
+		//printf("ArrayExp.inlineScan()\n");
+		e1 = e1.inlineScan(iss);
+		arrayInlineScan(iss, arguments);
+
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayInitializer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,373 @@
+module dmd.ArrayInitializer;
+
+import dmd.ArrayTypes;
+import dmd.Type;
+import dmd.TypeNext;
+import dmd.Array;
+import dmd.Loc;
+import dmd.Initializer;
+import dmd.WANT;
+import dmd.Util;
+import dmd.TY;
+import dmd.TypeSArray;
+import dmd.IntegerExp;
+import dmd.Expression;
+import dmd.ArrayLiteralExp;
+import dmd.Scope;
+import dmd.ErrorExp;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.TYM;
+import dmd.backend.Symbol;
+
+class ArrayInitializer : Initializer
+{
+    Expressions index;	// indices
+    Initializers value;	// of Initializer *'s
+    uint dim = 0;		// length of array being initialized
+    Type type = null;	// type that array will be used to initialize
+    int sem = 0;		// !=0 if semantic() is run
+
+    this(Loc loc)
+	{
+		super(loc);
+		index = new Expressions();
+		value = new Initializers();
+	}
+	
+    Initializer syntaxCopy()
+	{
+		//printf("ArrayInitializer.syntaxCopy()\n");
+
+		ArrayInitializer ai = new ArrayInitializer(loc);
+
+		assert(index.dim == value.dim);
+		ai.index.setDim(index.dim);
+		ai.value.setDim(value.dim);
+		for (int i = 0; i < ai.value.dim; i++)
+		{	
+			Expression e = cast(Expression)index.data[i];
+			if (e)
+				e = e.syntaxCopy();
+			ai.index.data[i] = cast(void*)e;
+
+			Initializer init = cast(Initializer)value.data[i];
+			init = init.syntaxCopy();
+			ai.value.data[i] = cast(void*)init;
+		}
+		return ai;
+	}
+	
+    void addInit(Expression index, Initializer value)
+	{
+		this.index.push(cast(void*)index);
+		this.value.push(cast(void*)value);
+		dim = 0;
+		type = null;
+	}
+	
+    Initializer semantic(Scope sc, Type t)
+	{
+		uint i;
+		uint length;
+
+		//printf("ArrayInitializer.semantic(%s)\n", t.toChars());
+		if (sem)				// if semantic() already run
+			return this;
+
+		sem = 1;
+		type = t;
+		t = t.toBasetype();
+		switch (t.ty)
+		{
+			case Tpointer:
+			case Tsarray:
+			case Tarray:
+				break;
+
+			default:
+				error(loc, "cannot use array to initialize %s", type.toChars());
+				return this;
+		}
+
+		length = 0;
+		for (i = 0; i < index.dim; i++)
+		{	
+			Expression idx;
+			Initializer val;
+
+			idx = cast(Expression)index.data[i];
+			if (idx)
+			{   
+				idx = idx.semantic(sc);
+				idx = idx.optimize(WANTvalue | WANTinterpret);
+				index.data[i] = cast(void*)idx;
+				length = cast(uint)idx.toInteger();
+			}
+
+			val = cast(Initializer)value.data[i];
+			val = val.semantic(sc, t.nextOf());
+			value.data[i] = cast(void*)val;
+			length++;
+			if (length == 0)
+				error(loc, "array dimension overflow");
+			if (length > dim)
+				dim = length;
+		}
+		uint amax = 0x80000000;
+		if (cast(uint) (dim * t.nextOf().size()) >= amax)
+			error(loc, "array dimension %u exceeds max of %ju", dim, amax / t.nextOf().size());
+
+		return this;
+	}
+	
+    Type inferType(Scope sc)
+	{
+		//printf("ArrayInitializer.inferType() %s\n", toChars());
+		type = Type.terror;
+		for (size_t i = 0; i < value.dim; i++)
+		{
+			if (index.data[i])
+				goto Lno;
+		}
+
+		for (size_t i = 0; i < value.dim; i++)
+		{
+			Initializer iz = cast(Initializer)value.data[i];
+			if (iz)
+			{   
+				Type t = iz.inferType(sc);
+				if (i == 0)
+				{	
+					t = new TypeSArray(t, new IntegerExp(value.dim));
+					t = t.semantic(loc, sc);
+					type = t;
+				}
+			}
+		}
+		return type;
+
+	Lno:
+		error(loc, "cannot infer type from this array initializer");
+		return Type.terror;
+	}
+
+	/********************************
+	 * If possible, convert array initializer to array literal.
+	 */	
+    Expression toExpression()
+	{
+		Expression e;
+
+		//printf("ArrayInitializer.toExpression(), dim = %d\n", dim);
+		//static int i; if (++i == 2) halt();
+
+		size_t edim;
+		Type t = null;
+		if (type)
+		{
+			t = type.toBasetype();
+			switch (t.ty)
+			{
+				case Tsarray:
+					edim = cast(uint)(cast(TypeSArray)t).dim.toInteger();
+					break;
+
+				case Tpointer:
+				case Tarray:
+					edim = dim;
+					break;
+
+				default:
+					assert(0);
+			}
+		}
+		else
+		{
+			edim = value.dim;
+			for (size_t i = 0, j = 0; i < value.dim; i++, j++)
+			{
+				if (index.data[i])
+					j = cast(uint)(cast(Expression)index.data[i]).toInteger();
+				if (j >= edim)
+					edim = j + 1;
+			}
+		}
+
+		Expressions elements = new Expressions();
+		elements.setDim(edim);
+		for (size_t i = 0, j = 0; i < value.dim; i++, j++)
+		{
+			if (index.data[i])
+				j = cast(uint)(cast(Expression)index.data[i]).toInteger();
+			assert(j < edim);
+			Initializer iz = cast(Initializer)value.data[i];
+			if (!iz)
+				goto Lno;
+			Expression ex = iz.toExpression();
+			if (!ex)
+			{
+				goto Lno;
+			}
+			elements.data[j] = cast(void*)ex;
+		}
+
+		/* Fill in any missing elements with the default initializer
+		 */
+		{
+			Expression init = null;
+			for (size_t i = 0; i < edim; i++)
+			{
+				if (!elements.data[i])
+				{
+					if (!type)
+						goto Lno;
+					if (!init)
+						init = (cast(TypeNext)t).next.defaultInit(Loc(0));
+					elements.data[i] = cast(void*)init;
+				}
+			}
+
+			Expression e2 = new ArrayLiteralExp(loc, elements);
+			e2.type = type;
+			return e2;
+		}
+
+	Lno:
+		delete elements;
+		error(loc, "array initializers as expressions are not allowed");
+		return new ErrorExp();
+	}
+	
+    Initializer toAssocArrayInitializer()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    dt_t* toDt()
+	{
+		//printf("ArrayInitializer.toDt('%s')\n", toChars());
+		Type tb = type.toBasetype();
+		Type tn = tb.nextOf().toBasetype();
+
+		scope Array dts = new Array();
+		uint size;
+		uint length;
+		uint i;
+		dt_t* dt;
+		dt_t* d;
+		dt_t** pdtend;
+
+		//printf("\tdim = %d\n", dim);
+		dts.setDim(dim);
+		dts.zero();
+
+		size = cast(uint)tn.size();
+
+		length = 0;
+		for (i = 0; i < index.dim; i++)
+		{
+			Expression idx;
+			Initializer val;
+
+			idx = cast(Expression)index.data[i];
+			if (idx)
+				length = cast(uint)idx.toInteger();
+			//printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);
+
+			assert(length < dim);
+			val = cast(Initializer)value.data[i];
+			dt = val.toDt();
+			if (dts.data[length])
+				error(loc, "duplicate initializations for index %d", length);
+			dts.data[length] = cast(void*)dt;
+			length++;
+		}
+
+		Expression edefault = tb.nextOf().defaultInit(Loc(0));
+
+		uint n = 1;
+		for (Type tbn = tn; tbn.ty == Tsarray; tbn = tbn.nextOf().toBasetype())
+		{	
+			TypeSArray tsa = cast(TypeSArray)tbn;
+			n *= tsa.dim.toInteger();
+		}
+
+		d = null;
+		pdtend = &d;
+		for (i = 0; i < dim; i++)
+		{
+			dt = cast(dt_t*)dts.data[i];
+			if (dt)
+				pdtend = dtcat(pdtend, dt);
+			else
+			{
+				for (int j = 0; j < n; j++)
+					pdtend = edefault.toDt(pdtend);
+			}
+		}
+		switch (tb.ty)
+		{
+			case Tsarray:
+			{   
+				uint tadim;
+				TypeSArray ta = cast(TypeSArray)tb;
+
+				tadim = cast(uint)ta.dim.toInteger();
+				if (dim < tadim)
+				{
+					if (edefault.isBool(false))
+						// pad out end of array
+						pdtend = dtnzeros(pdtend, size * (tadim - dim));
+					else
+					{
+						for (i = dim; i < tadim; i++)
+						{	
+							for (int j = 0; j < n; j++)
+								pdtend = edefault.toDt(pdtend);
+						}
+					}
+				}
+				else if (dim > tadim)
+				{
+					debug writef("1: ");
+					error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
+				}
+				break;
+			}
+
+			case Tpointer:
+			case Tarray:
+				// Create symbol, and then refer to it
+				Symbol* s = static_sym();
+				s.Sdt = d;
+				outdata(s);
+
+				d = null;
+				if (tb.ty == Tarray)
+					dtdword(&d, dim);
+				dtxoff(&d, s, 0, TYnptr);
+				break;
+
+			default:
+				assert(0);
+		}
+		return d;
+	}
+	
+    dt_t* toDtBit()	// for bit arrays
+	{
+		assert(false);
+	}
+
+    ArrayInitializer isArrayInitializer() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayLengthExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,75 @@
+module dmd.ArrayLengthExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.Type;
+import dmd.WANT;
+
+import dmd.expression.ArrayLength;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class ArrayLengthExp : UnaExp
+{
+	this(Loc loc, Expression e1)
+	{
+		super(loc, TOK.TOKarraylength, ArrayLengthExp.sizeof, e1);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+	version (LOGSEMANTIC) {
+		printf("ArrayLengthExp::semantic('%s')\n", toChars());
+	}
+		if (!type)
+		{
+			UnaExp.semantic(sc);
+			e1 = resolveProperties(sc, e1);
+
+			type = Type.tsize_t;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars());
+		e1 = e1.optimize(WANTvalue | (result & WANTinterpret));
+		Expression e = this;
+		if (e1.op == TOKstring || e1.op == TOKarrayliteral || e1.op == TOKassocarrayliteral)
+		{
+			e = ArrayLength(type, e1);
+		}
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e = e1.toElem(irs);
+		e = el_una(OP64_32, type.totym(), e);
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayLiteralExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,363 @@
+module dmd.ArrayLiteralExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.WANT;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.backend.dt_t;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.IntegerExp;
+import dmd.TypeSArray;
+import dmd.TY;
+import dmd.StringExp;
+
+import dmd.expression.Util;
+import dmd.backend.Util;
+import dmd.backend.RTLSYM;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+class ArrayLiteralExp : Expression
+{
+	Expressions elements;
+
+	this(Loc loc, Expressions elements)
+	{
+		super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof);
+		this.elements = elements;
+	}
+
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof);
+		elements = new Expressions();
+		elements.push(cast(void*)e);
+	}
+
+	Expression syntaxCopy()
+	{
+		return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t0 = null;
+
+	version (LOGSEMANTIC) {
+		printf("ArrayLiteralExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			return this;
+
+		// Run semantic() on each element
+		for (int i = 0; i < elements.dim; i++)
+		{	
+			e = cast(Expression)elements.data[i];
+			e = e.semantic(sc);
+			assert(e.type);
+			elements.data[i] = cast(void*)e;
+		}
+
+		expandTuples(elements);
+
+		for (int i = 0; i < elements.dim; i++)
+		{	
+			e = cast(Expression)elements.data[i];
+
+			if (!e.type)
+				error("%s has no value", e.toChars());
+
+			e = resolveProperties(sc, e);
+
+			ubyte committed = 1;
+			if (e.op == TOKstring)
+				committed = (cast(StringExp)e).committed;
+
+			if (!t0)
+			{   
+				t0 = e.type;
+				// Convert any static arrays to dynamic arrays
+				if (t0.ty == Tsarray)
+				{
+					t0 = (cast(TypeSArray)t0).next.arrayOf();
+					e = e.implicitCastTo(sc, t0);
+				}
+			}
+			else
+				e = e.implicitCastTo(sc, t0);
+
+			if (!committed && e.op == TOKstring)
+			{   
+				StringExp se = cast(StringExp)e;
+				se.committed = 0;
+			}
+			elements.data[i] = cast(void*)e;
+		}
+
+		if (!t0)
+			t0 = Type.tvoid;
+		type = new TypeSArray(t0, new IntegerExp(elements.dim));
+		type = type.semantic(loc, sc);
+		return this;
+	}
+
+	bool isBool(bool result)
+	{
+		size_t dim = elements ? elements.dim : 0;
+		return result ? (dim != 0) : (dim == 0);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		size_t dim;
+
+		//printf("ArrayLiteralExp.toElem() %s\n", toChars());
+		if (elements)
+		{
+			scope Expressions args = new Expressions();
+			dim = elements.dim;
+			args.setDim(dim + 1);		// +1 for number of args parameter
+			e = el_long(TYint, dim);
+			args.data[dim] = cast(void*)e;
+			for (size_t i = 0; i < dim; i++)
+			{   
+				Expression el = cast(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 = cast(uint)el.type.size();
+				}
+				args.data[dim - (i + 1)] = cast(void *)ep;
+			}
+
+			/* Because the number of parameters can get very large, produce
+			 * a balanced binary tree so we don't blow up the stack in
+			 * the subsequent tree walking code.
+			 */
+			e = el_params(args.data, dim + 1);
+		}
+		else
+		{	
+			dim = 0;
+			e = el_long(TYint, 0);
+		}
+		Type tb = type.toBasetype();
+	static if (true) {
+		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);
+	}
+		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 = cast(uint)type.size();
+		}
+
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		bool f = false;
+
+		for (size_t i = 0; i < elements.dim; i++)
+		{	
+			Expression e = cast(Expression)elements.data[i];
+			f |= e.checkSideEffect(2);
+		}
+		if (flag == 0 && f == false)
+			Expression.checkSideEffect(0);
+
+		return f;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writeByte('[');
+		argsToCBuffer(buf, elements, hgs);
+		buf.writeByte(']');
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		size_t dim = elements ? elements.dim : 0;
+		buf.printf("A%u", dim);
+		for (size_t i = 0; i < dim; i++)
+		{	
+			Expression e = cast(Expression)elements.data[i];
+			e.toMangleBuffer(buf);
+		}
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		if (elements)
+		{
+			for (size_t i = 0; i < elements.dim; i++)
+			{   
+				Expression e = cast(Expression)elements.data[i];
+
+				e = e.optimize(WANTvalue | (result & WANTinterpret));
+				elements.data[i] = cast(void*)e;
+			}
+		}
+
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+		MATCH result = MATCHexact;
+
+	static if (false) {
+		printf("ArrayLiteralExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
+		toChars(), type.toChars(), t.toChars());
+	}
+		Type typeb = type.toBasetype();
+		Type tb = t.toBasetype();
+		if ((tb.ty == Tarray || tb.ty == Tsarray) &&
+			(typeb.ty == Tarray || typeb.ty == Tsarray))
+		{
+			if (tb.ty == Tsarray)
+			{   
+				TypeSArray tsa = cast(TypeSArray)tb;
+				if (elements.dim != tsa.dim.toInteger())
+					result = MATCHnomatch;
+			}
+
+			for (int i = 0; i < elements.dim; i++)
+			{
+				Expression e = cast(Expression)elements.data[i];
+				MATCH m = cast(MATCH)e.implicitConvTo(tb.nextOf());
+				if (m < result)
+					result = m;			// remember worst match
+				if (result == MATCHnomatch)
+					break;				// no need to check for worse
+			}
+			return result;
+		}
+		else
+			return Expression.implicitConvTo(t);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	static if (false) {
+		printf("ArrayLiteralExp.castTo(this=%s, type=%s, => %s)\n",
+		toChars(), type.toChars(), t.toChars());
+	}
+		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) &&
+			// Not trying to convert non-void[] to void[]
+			!(tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid))
+		{
+			if (tb.ty == Tsarray)
+			{   
+				TypeSArray tsa = cast(TypeSArray)tb;
+				if (elements.dim != tsa.dim.toInteger())
+					goto L1;
+			}
+
+			e = cast(ArrayLiteralExp)copy();
+			e.elements = cast(Expressions)elements.copy();
+			for (int i = 0; i < elements.dim; i++)
+			{   
+				Expression ex = cast(Expression)elements.data[i];
+				ex = ex.castTo(sc, tb.nextOf());
+				e.elements.data[i] = cast(void*)ex;
+			}
+			e.type = t;
+			return e;
+		}
+		if (tb.ty == Tpointer && typeb.ty == Tsarray)
+		{
+			Type tp = typeb.nextOf().pointerTo();
+			if (!tp.equals(e.type))
+			{   
+				e = cast(ArrayLiteralExp)copy();
+				e.type = tp;
+			}
+		}
+	L1:
+		return e.Expression.castTo(sc, t);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		return 1;	// because it can fail allocating memory
+	}
+}
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + arrayInlineCost(ics, elements);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		ArrayLiteralExp ce = cast(ArrayLiteralExp)copy();
+		ce.elements = arrayExpressiondoInline(elements, ids);
+		return ce;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		Expression e = this;
+
+		//printf("ArrayLiteralExp.inlineScan()\n");
+		arrayInlineScan(iss, elements);
+
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayScopeSymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,166 @@
+module dmd.ArrayScopeSymbol;
+
+import dmd.ScopeDsymbol;
+import dmd.Expression;
+import dmd.TypeTuple;
+import dmd.TupleDeclaration;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Identifier;
+import dmd.Id;
+import dmd.TY;
+import dmd.TupleExp;
+import dmd.StringExp;
+import dmd.WANT;
+import dmd.TypeExp;
+import dmd.Type;
+import dmd.SliceExp;
+import dmd.IndexExp;
+import dmd.IntegerExp;
+import dmd.STC;
+import dmd.ExpInitializer;
+import dmd.VarDeclaration;
+import dmd.ArrayLiteralExp;
+import dmd.expression.Util;
+
+class ArrayScopeSymbol : ScopeDsymbol
+{
+    Expression exp;	// IndexExp or SliceExp
+    TypeTuple type;	// for tuple[length]
+    TupleDeclaration td;	// for tuples of objects
+    Scope sc;
+
+    this(Scope sc, Expression e)
+	{
+		super();
+		assert(e.op == TOKindex || e.op == TOKslice);
+		this.exp = e;
+		this.sc = sc;
+	}
+	
+    this(Scope sc, TypeTuple t)
+	{
+		assert(false);
+	}
+	
+    this(Scope sc, TupleDeclaration td)
+	{
+		assert(false);
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		//printf("ArrayScopeSymbol.search('%s', flags = %d)\n", ident.toChars(), flags);
+		if (ident == Id.length || ident == Id.dollar)
+		{
+			VarDeclaration* pvar;
+			Expression ce;
+
+		L1:
+			if (td)
+			{   /* $ gives the number of elements in the tuple
+				 */
+				VarDeclaration v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+				Expression e = new IntegerExp(Loc(0), td.objects.dim, Type.tsize_t);
+				v.init = new ExpInitializer(Loc(0), e);
+				v.storage_class |= STCstatic | STCconst;
+				v.semantic(sc);
+				return v;
+			}
+
+			if (type)
+			{   /* $ gives the number of type entries in the type tuple
+				 */
+				VarDeclaration v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+				Expression e = new IntegerExp(Loc(0), type.arguments.dim, Type.tsize_t);
+				v.init = new ExpInitializer(Loc(0), e);
+				v.storage_class |= STCstatic | STCconst;
+				v.semantic(sc);
+				return v;
+			}
+
+			if (exp.op == TOKindex)
+			{   /* array[index] where index is some function of $
+				 */
+				IndexExp ie = cast(IndexExp)exp;
+
+				pvar = &ie.lengthVar;
+				ce = ie.e1;
+			}
+			else if (exp.op == TOKslice)
+			{   /* array[lwr .. upr] where lwr or upr is some function of $
+				 */
+				SliceExp se = cast(SliceExp)exp;
+
+				pvar = &se.lengthVar;
+				ce = se.e1;
+			}
+			else
+				/* Didn't find $, look in enclosing scope(s).
+				 */
+				return null;
+
+			/* If we are indexing into an array that is really a type
+			 * tuple, rewrite this as an index into a type tuple and
+			 * try again.
+			 */
+			if (ce.op == TOKtype)
+			{
+				Type t = (cast(TypeExp)ce).type;
+				if (t.ty == Ttuple)
+				{	
+					type = cast(TypeTuple)t;
+					goto L1;
+				}
+			}
+
+			/* *pvar is lazily initialized, so if we refer to $
+			 * multiple times, it gets set only once.
+			 */
+			if (!*pvar)		// if not already initialized
+			{   /* Create variable v and set it to the value of $,
+				 * which will be a constant.
+				 */
+				VarDeclaration v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
+
+				if (ce.op == TOKvar)
+				{	// if ce is const, get its initializer
+					ce = fromConstInitializer(WANTvalue | WANTinterpret, ce);
+				}
+
+				if (ce.op == TOKstring)
+				{	/* It is for a string literal, so the
+					 * length will be a const.
+					 */
+					Expression e = new IntegerExp(Loc(0), (cast(StringExp)ce).len, Type.tsize_t);
+					v.init = new ExpInitializer(Loc(0), e);
+					v.storage_class |= STCstatic | STCconst;
+				}
+				else if (ce.op == TOKarrayliteral)
+				{	/* It is for an array literal, so the
+					 * length will be a const.
+					 */
+					Expression e = new IntegerExp(Loc(0), (cast(ArrayLiteralExp)ce).elements.dim, Type.tsize_t);
+					v.init = new ExpInitializer(Loc(0), e);
+					v.storage_class |= STCstatic | STCconst;
+				}
+				else if (ce.op == TOKtuple)
+				{	/* It is for an expression tuple, so the
+					 * length will be a const.
+					 */
+					Expression e = new IntegerExp(Loc(0), (cast(TupleExp)ce).exps.dim, Type.tsize_t);
+					v.init = new ExpInitializer(Loc(0), e);
+					v.storage_class |= STCstatic | STCconst;
+				}
+				*pvar = v;
+			}
+			(*pvar).semantic(sc);
+			return (*pvar);
+		}
+		return null;
+	}
+
+    ArrayScopeSymbol isArrayScopeSymbol() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayT.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,173 @@
+module dmd.ArrayT;
+
+import std.contracts;
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class ArrayT(T)
+{
+	uint dim;
+    uint allocdim;
+    T* data;
+
+    ~this()
+	{
+		free(data);
+	}
+
+    void mark()
+	{
+	}
+	
+    string toString()
+	{
+		char *p;
+
+		///char **buf = cast(char**)alloca(dim * (char*).sizeof);
+		scope string[] buf = new string[dim];
+		uint len = 2;
+		for (uint u = 0; u < dim; u++) {
+			buf[u] = (cast(Object)data[u]).toString();
+			len += buf[u].length + 1;
+		}
+
+		char* str = cast(char*)malloc(len);
+
+		str[0] = '[';
+		p = str + 1;
+
+		for (uint u = 0; u < dim; u++)
+		{
+			if (u != 0) {
+				*p++ = ',';
+			}
+			uint length = buf[u].length;
+			p[0..length] = buf[u][];
+
+			p += length;
+		}
+
+		*p++ = ']';
+		*p = 0;
+
+		return assumeUnique(str[0..len]);
+	}
+
+    final void reserve(uint nentries)
+	{
+		//printf("ArrayT::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+		if (allocdim - dim < nentries) {
+			allocdim = dim + nentries;
+			data = cast(T*)realloc(data, allocdim * (*data).sizeof);
+		}
+	}
+	
+    final void setDim(uint newdim)
+	{
+		if (dim < newdim) {
+			reserve(newdim - dim);
+		}
+
+		dim = newdim;
+	}
+	
+    final void fixDim()
+	{
+		if (dim != allocdim)
+		{
+			data = cast(T*)realloc(data, dim * (*data).sizeof);
+			allocdim = dim;
+		}
+	}
+	
+    final void push(void* ptr)
+	{
+		reserve(1);
+		data[dim++] = ptr;
+	}
+
+    final void* pop()
+	{
+		return data[--dim];
+	}
+	
+    final void shift(void* ptr)
+	{
+		reserve(1);
+		memmove(data + 1, data, dim * (*data).sizeof);
+		data[0] = ptr;
+		dim++;
+	}
+	
+    final void insert(uint index, void* ptr)
+	{
+		reserve(1);
+		memmove(data + index + 1, data + index, (dim - index) * (*data).sizeof);
+		data[index] = ptr;
+		dim++;
+	}
+	
+    final void insert(uint index, ArrayT a)
+	{
+		if (a !is null) {
+			uint d = a.dim;
+			reserve(d);
+
+			if (dim != index) {
+				memmove(data + index + d, data + index, (dim - index) * (*data).sizeof);
+			}
+
+			memcpy(data + index, a.data, d * (*data).sizeof);
+			dim += d;
+		}
+	}
+	
+	/***********************************
+	 * Append array a to this array.
+	 */
+    final void append(ArrayT a)
+	{
+		insert(dim, a);
+	}
+
+    final void remove(uint i)
+	{
+		memmove(data + i, data + i + 1, (dim - i) * (*data).sizeof);
+		dim--;
+	}
+	
+    final void zero()
+	{
+		memset(data, 0, dim * (*data).sizeof);
+	}
+
+    final void* tos()
+	{
+		return dim ? data[dim - 1] : null;
+	}
+
+	private static extern (C) int Array_sort_compare(const(void*) x, const(void*) y)
+	{
+		Object ox = *cast(Object *)x;
+		Object oy = *cast(Object *)y;
+
+		return ox.opCmp(oy);
+	}
+
+    final void sort()
+	{
+		if (dim) {
+			qsort(cast(void*)data, dim, Object.sizeof, &ArrayT_sort_compare);
+		}
+	}
+
+    final ArrayT copy()
+	{
+		ArrayT a = new TArray();
+		a.setDim(dim);
+
+		memcpy(a.data, data, dim * (*data).sizeof);
+
+		return a;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ArrayTypes.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,25 @@
+module dmd.ArrayTypes;
+
+import dmd.Array;
+
+class TemplateParameters : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Expressions : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Statements : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class BaseClasses : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class ClassDeclarations : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Dsymbols : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Objects : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class FuncDeclarations : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Arguments : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Identifiers : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
+
+class Initializers : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AsmStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,373 @@
+module dmd.AsmStatement;
+
+import dmd.Loc;
+import dmd.Statement;
+import dmd.Token;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.LabelDsymbol;
+import dmd.Dsymbol;
+import dmd.Id;
+import dmd.TOK;
+import dmd.Global;
+import dmd.FuncDeclaration;
+import dmd.Declaration;
+import dmd.LabelStatement;
+import dmd.Util;
+
+import dmd.backend.code;
+import dmd.backend.iasm;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.BC;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.backend.SC;
+import dmd.backend.mTY;
+import dmd.backend.Symbol;
+import dmd.backend.LIST;
+
+import core.stdc.string : memset;
+import core.stdc.stdlib : exit, EXIT_FAILURE;
+
+class AsmStatement : Statement
+{
+    Token* tokens;
+    code* asmcode;
+    uint asmalign;		// alignment of this statement
+    bool refparam;		// true if function parameter is referenced
+    bool naked;		// true if function is to be naked
+    uint regs;		// mask of registers modified
+
+    this(Loc loc, Token* tokens)
+	{
+		super(loc);
+		this.tokens = tokens;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("AsmStatement.semantic()\n");
+
+		if (global.params.safe && !sc.module_.safe)
+		{
+			error("inline assembler not allowed in safe mode");
+		}
+
+		OP* o;
+		OPND* o1 = null;
+		OPND* o2 = null;
+		OPND* o3 = null;
+
+		PTRNTAB ptb;
+		uint usNumops;
+		ubyte uchPrefix = 0;
+		ubyte bAsmseen;
+		char* pszLabel = null;
+		code* c;
+		FuncDeclaration fd = sc.parent.isFuncDeclaration();
+
+		assert(fd);
+		fd.inlineAsm = 1;
+
+		if (!tokens)
+			return null;
+
+		memset(&asmstate, 0, asmstate.sizeof);
+
+		asmstate.statement = this;
+		asmstate.sc = sc;
+
+static if (false) {
+		// don't use bReturnax anymore, and will fail anyway if we use return type inference
+		// Scalar return values will always be in AX.  So if it is a scalar
+		// then asm block sets return value if it modifies AX, if it is non-scalar
+		// then always assume that the ASM block sets up an appropriate return
+		// value.
+
+		asmstate.bReturnax = 1;
+		if (sc.func.type.nextOf().isscalar())
+			asmstate.bReturnax = 0;
+}
+
+		// Assume assembler code takes care of setting the return value
+		sc.func.hasReturnExp |= 8;
+		
+		if (!asmstate.bInit)
+		{
+			asmstate.bInit = true;
+			init_optab();
+			asmstate.psDollar = new LabelDsymbol(Id.__dollar);
+			//asmstate.psLocalsize = new VarDeclaration(0, Type.tint32, Id.__LOCAL_SIZE, null);
+			asmstate.psLocalsize = new Dsymbol(Id.__LOCAL_SIZE);
+			cod3_set386();
+		}
+		
+		asmstate.loc = loc;
+
+		asmtok = tokens;
+		asm_token_trans(asmtok);
+		if (setjmp(asmstate.env))
+		{	
+			asmtok = null;			// skip rest of line
+			tok_value = TOK.TOKeof;
+			exit(EXIT_FAILURE);
+			goto AFTER_EMIT;
+		}
+
+		switch (cast(int)tok_value)
+		{
+			case ASMTK.ASMTKnaked:
+				naked = true;
+				sc.func.naked = true;
+				asm_token();
+				break;
+
+			case ASMTK.ASMTKeven:
+				asm_token();
+				asmalign = 2;
+				break;
+
+			case TOK.TOKalign:
+			{   
+				asm_token();
+				uint align_ = asm_getnum();
+				if (ispow2(align_) == -1)
+					asmerr(ASMERRMSGS.EM_align, align_);	// power of 2 expected
+				else
+					asmalign = align_;
+				break;
+			}
+
+			// The following three convert the keywords 'int', 'in', 'out'
+			// to identifiers, since they are x86 instructions.
+			case TOK.TOKint32:
+				o = asm_op_lookup(Id.__int.toChars());
+				goto Lopcode;
+
+			case TOK.TOKin:
+				o = asm_op_lookup(Id.___in.toChars());
+				goto Lopcode;
+
+			case TOK.TOKout:
+				o = asm_op_lookup(Id.___out.toChars());
+				goto Lopcode;
+
+			case TOK.TOKidentifier:
+				o = asm_op_lookup(asmtok.ident.toChars());
+				if (!o)
+					goto OPCODE_EXPECTED;
+
+			Lopcode:
+				asmstate.ucItype = o.usNumops & IT.ITMASK;
+				asm_token();
+				if (o.usNumops > 3)
+				{
+					switch (asmstate.ucItype)
+					{
+						case IT.ITdata:
+							asmcode = asm_db_parse(o);
+							goto AFTER_EMIT;
+
+						case IT.ITaddr:
+							asmcode = asm_da_parse(o);
+							goto AFTER_EMIT;
+						
+						default:
+							break;
+					}
+				}
+				// get the first part of an expr
+				o1 = asm_cond_exp();
+				if (tok_value == TOK.TOKcomma)
+				{
+					asm_token();
+					o2 = asm_cond_exp();
+				}
+				if (tok_value == TOK.TOKcomma)
+				{
+					asm_token();
+					o3 = asm_cond_exp();
+				}
+				// match opcode and operands in ptrntab to verify legal inst and
+				// generate
+
+				ptb = asm_classify(o, o1, o2, o3, &usNumops);
+				assert(ptb.pptb0);
+
+				//
+				// The Multiply instruction takes 3 operands, but if only 2 are seen
+				// then the third should be the second and the second should
+				// be a duplicate of the first.
+				//
+						
+				if (asmstate.ucItype == IT.ITopt &&
+					(usNumops == 2) &&
+					(ASM_GET_aopty(o2.usFlags) == ASM_OPERAND_TYPE._imm) &&
+					((o.usNumops & IT.ITSIZE) == 3))
+				{
+					o3 = o2;
+					o2 = opnd_calloc();
+					*o2 = *o1;
+
+					// Re-classify the opcode because the first classification
+					// assumed 2 operands.
+
+					ptb = asm_classify(o, o1, o2, o3, &usNumops);
+				}
+				else
+				{
+static if (false) {
+					if (asmstate.ucItype == IT.ITshift && (ptb.pptb2.usOp2 == 0 ||
+						(ptb.pptb2.usOp2 & _cl))) {
+						opnd_free(o2);
+						o2 = null;
+						usNumops = 1;
+					}
+}
+				}
+
+				asmcode = asm_emit(loc, usNumops, ptb, o, o1, o2, o3);
+				break;
+
+			default:
+			OPCODE_EXPECTED:
+				asmerr(ASMERRMSGS.EM_opcode_exp, asmtok.toChars());	// assembler opcode expected
+				break;
+		}
+
+	AFTER_EMIT:
+		opnd_free(o1);
+		opnd_free(o2);
+		opnd_free(o3);
+		o1 = o2 = o3 = null;
+
+		if (tok_value != TOK.TOKeof)
+			asmerr(ASMERRMSGS.EM_eol);			// end of line expected
+
+		//return asmstate.bReturnax;
+		return this;
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    bool comeFrom()
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    AsmStatement isAsmStatement() { return this; }
+
+    void toIR(IRState *irs)
+	{
+		block* bpre;
+		block* basm;
+		Declaration d;
+		Symbol* s;
+		Blockx* blx = irs.blx;
+
+//		dumpCode(asmcode);
+
+		//printf("AsmStatement::toIR(asmcode = %x)\n", asmcode);
+		bpre = blx.curblock;
+		block_next(blx,BCgoto,null);
+		basm = blx.curblock;
+		list_append(&bpre.Bsucc, basm);
+		basm.Bcode = asmcode;
+		basm.Balign = cast(ubyte)asmalign;
+static if (false) {
+		if (label)
+		{	
+			block* b = labelToBlock(loc, blx, label);
+			printf("AsmStatement::toIR() %p\n", b);
+			if (b)
+				list_append(&basm.Bsucc, b);
+		}
+}
+		// Loop through each instruction, fixing Dsymbols into Symbol's
+		for (code* c = asmcode; c; c = c.next)
+		{	
+			LabelDsymbol label;
+			block* b;
+
+			switch (c.IFL1)
+			{
+				case FLblockoff:
+				case FLblock:
+					// FLblock and FLblockoff have LabelDsymbol's - convert to blocks
+					label = c.IEVlsym1;
+					b = labelToBlock(loc, blx, label);
+					list_append(&basm.Bsucc, b);
+					c.IEV1.Vblock = b;
+					break;
+
+				case FLdsymbol:
+				case FLfunc:
+					s = c.IEVdsym1.toSymbol();
+					if (s.Sclass == SCauto && s.Ssymnum == -1)
+						symbol_add(s);
+					c.IEVsym1() = s;
+					c.IFL1 = s.Sfl ? s.Sfl : FLauto;
+					break;
+				default:
+					break;
+			}
+
+			// Repeat for second operand
+			switch (c.IFL2)
+			{
+				case FLblockoff:
+				case FLblock:
+					label = c.IEVlsym2;
+					b = labelToBlock(loc, blx, label);
+					list_append(&basm.Bsucc, b);
+					c.IEV2.Vblock = b;
+					break;
+
+				case FLdsymbol:
+				case FLfunc:
+					d = c.IEVdsym2;
+					s = d.toSymbol();
+					if (s.Sclass == SCauto && s.Ssymnum == -1)
+						symbol_add(s);
+					c.IEVsym2() = s;
+					c.IFL2 = s.Sfl ? s.Sfl : FLauto;
+					if (d.isDataseg())
+						s.Sflags |= SFLlivexit;
+					break;
+				default:
+					break;
+			}
+			//c.print();
+		}
+
+		basm.bIasmrefparam = refparam;		// are parameters reference?
+		basm.usIasmregs = cast(ushort)regs;			// registers modified
+
+		block_next(blx,BCasm, null);
+		list_prepend(&basm.Bsucc, blx.curblock);
+
+		if (naked)
+		{
+			blx.funcsym.Stype.Tty |= mTYnaked;
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AssertExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,254 @@
+module dmd.AssertExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.Type;
+import dmd.Global;
+import dmd.InvariantDeclaration;
+import dmd.TOK;
+import dmd.TY;
+import dmd.TypeClass;
+import dmd.Module;
+import dmd.WANT;
+import dmd.FuncDeclaration;
+import dmd.HaltExp;
+import dmd.TypeStruct;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.RTLSYM;
+import dmd.backend.Symbol;
+import dmd.backend.dt_t;
+import dmd.backend.SC;
+import dmd.backend.FL;
+
+import core.stdc.string;
+import std.string : toStringz;
+
+static __gshared Symbol* assertexp_sfilename = null;
+static __gshared string assertexp_name = null;
+static __gshared Module assertexp_mn = null;
+
+class AssertExp : UnaExp
+{
+	Expression msg;
+
+	this(Loc loc, Expression e, Expression msg = null)
+	{
+		super(loc, TOK.TOKassert, AssertExp.sizeof, e);
+		this.msg = msg;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("AssertExp.semantic('%s')\n", toChars());
+	}
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		// BUG: see if we can do compile time elimination of the Assert
+		e1 = e1.optimize(WANTvalue);
+		e1 = e1.checkToBoolean();
+		if (msg)
+		{
+			msg = msg.semantic(sc);
+			msg = resolveProperties(sc, msg);
+			msg = msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
+			msg = msg.optimize(WANTvalue);
+		}
+		if (e1.isBool(false))
+		{
+			FuncDeclaration fd = sc.parent.isFuncDeclaration();
+			fd.hasReturnExp |= 4;
+
+			if (!global.params.useAssert)
+			{   
+				Expression e = new HaltExp(loc);
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+		type = Type.tvoid;
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		return true;
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		/* assert()s are non-recoverable errors, so functions that
+		 * use them can be considered "nothrow"
+		 */
+		return 0; //(global.params.useAssert != 0);
+	}
+}
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics) + (msg ? msg.inlineCost(ics) : 0);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		AssertExp ae = cast(AssertExp)copy();
+
+		ae.e1 = e1.doInline(ids);
+		if (msg)
+			ae.msg = msg.doInline(ids);
+		return ae;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		e1 = e1.inlineScan(iss);
+		if (msg)
+			msg = msg.inlineScan(iss);
+		return this;
+	}
+	
+	static private void* castToVoid(int i)
+	{
+		return cast(void*)i;
+	}
+
+	elem* 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 = cast(InvariantDeclaration)castToVoid(1);
+
+			// If e1 is a class object, call the class invariant on it
+			if (global.params.useInvariants && t1.ty == Tclass &&
+				!(cast(TypeClass)t1).sym.isInterfaceDeclaration())
+			{
+		version (XXX) {///TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
+				e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM__DINVARIANT]), e);
+		} else {
+				e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DINVARIANT]), e);
+		}
+			}
+			// 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 = (cast(TypeStruct)t1.nextOf()).sym.inv) !is 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_;
+				string 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 || loc.filename != mname))
+				{	
+					elem* efilename;
+
+					/* Cache values.
+					 */
+					//static Symbol *assertexp_sfilename = null;
+					//static char *assertexp_name = null;
+					//static Module *assertexp_mn = null;
+
+					if (!assertexp_sfilename || loc.filename != assertexp_name || assertexp_mn != m)
+					{
+						dt_t* dt = null;
+
+						string id = loc.filename;
+						int len = id.length;
+						dtdword(&dt, len);
+						dtabytes(&dt,TYnptr, 0, len + 1, toStringz(id));
+
+						assertexp_sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
+						assertexp_sfilename.Sdt = dt;
+						assertexp_sfilename.Sfl = FLdata;
+			version (ELFOBJ) {
+						assertexp_sfilename.Sseg = CDATA;
+			}
+			version (MACHOBJ) {
+						assertexp_sfilename.Sseg = DATA;
+			}
+						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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,857 @@
+module dmd.AssignExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.IndexExp;
+import dmd.CallExp;
+import dmd.TypeSArray;
+import dmd.StructLiteralExp;
+import dmd.ArrayLengthExp;
+import dmd.TypeStruct;
+import dmd.StructDeclaration;
+import dmd.VarExp;
+import dmd.TY;
+import dmd.SliceExp;
+import dmd.CommaExp;
+import dmd.ArrayExp;
+import dmd.AggregateDeclaration;
+import dmd.CondExp;
+import dmd.DotVarExp;
+import dmd.WANT;
+import dmd.Id;
+import dmd.TypeClass;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.TupleExp;
+import dmd.VarDeclaration;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Global;
+import dmd.Declaration;
+import dmd.TypeFunction;
+import dmd.Type;
+import dmd.RET;
+import dmd.STC;
+import dmd.DotIdExp;
+
+import dmd.backend.Util;
+import dmd.backend.Symbol;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.RTLSYM;
+import dmd.codegen.Util;
+import dmd.expression.Util;
+
+class AssignExp : BinExp
+{
+	int ismemset = 0;
+
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKassign, AssignExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e1old = e1;
+
+version (LOGSEMANTIC) {
+		printf("AssignExp.semantic('%s')\n", toChars());
+}
+		//printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op));
+		//printf("e2.op = %d, '%s'\n", e2.op, Token.toChars(e2.op));
+
+		if (type)
+			return this;
+
+		if (e2.op == TOK.TOKcomma)
+		{	
+			/* Rewrite to get rid of the comma from rvalue
+			 */
+			AssignExp ea = new AssignExp(loc, e1, (cast(CommaExp)e2).e2);
+			ea.op = op;
+			Expression e = new CommaExp(loc, (cast(CommaExp)e2).e1, ea);
+			return e.semantic(sc);
+		}
+
+		/* Look for operator overloading of a[i]=value.
+		 * Do it before semantic() otherwise the a[i] will have been
+		 * converted to a.opIndex() already.
+		 */
+		if (e1.op == TOK.TOKarray)
+		{
+			ArrayExp ae = cast(ArrayExp)e1;
+			AggregateDeclaration ad;
+			Identifier id = Id.index;
+
+			ae.e1 = ae.e1.semantic(sc);
+			Type t1 = ae.e1.type.toBasetype();
+			if (t1.ty == TY.Tstruct)
+			{
+				ad = (cast(TypeStruct)t1).sym;
+				goto L1;
+			}
+			else if (t1.ty == TY.Tclass)
+			{
+				ad = (cast(TypeClass)t1).sym;
+			  L1:
+				// Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
+				if (search_function(ad, Id.indexass))
+				{	
+					Expression e = new DotIdExp(loc, ae.e1, Id.indexass);
+					Expressions a = cast(Expressions)ae.arguments.copy();
+
+					a.insert(0, cast(void*)e2);
+					e = new CallExp(loc, e, a);
+					e = e.semantic(sc);
+					return e;
+				}
+				else
+				{
+					// Rewrite (a[i] = value) to (a.opIndex(i, value))
+					if (search_function(ad, id))
+					{   
+						Expression e = new DotIdExp(loc, ae.e1, id);
+
+						if (1 || !global.params.useDeprecated)
+							error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
+
+						e = new CallExp(loc, e, cast(Expression)ae.arguments.data[0], e2);
+						e = e.semantic(sc);
+						return e;
+					}
+				}
+			}
+		}
+		/* Look for operator overloading of a[i..j]=value.
+		 * Do it before semantic() otherwise the a[i..j] will have been
+		 * converted to a.opSlice() already.
+		 */
+		if (e1.op == TOK.TOKslice)
+		{
+			Type t1;
+			SliceExp ae = cast(SliceExp)e1;
+			AggregateDeclaration ad;
+			Identifier id = Id.index;
+
+			ae.e1 = ae.e1.semantic(sc);
+			ae.e1 = resolveProperties(sc, ae.e1);
+			t1 = ae.e1.type.toBasetype();
+			if (t1.ty == TY.Tstruct)
+			{
+				ad = (cast(TypeStruct)t1).sym;
+				goto L2;
+			}
+			else if (t1.ty == TY.Tclass)
+			{
+				ad = (cast(TypeClass)t1).sym;
+			  L2:
+				// Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
+				if (search_function(ad, Id.sliceass))
+				{	
+					Expression e = new DotIdExp(loc, ae.e1, Id.sliceass);
+					Expressions a = new Expressions();
+
+					a.push(cast(void*)e2);
+					if (ae.lwr)
+					{   
+						a.push(cast(void*)ae.lwr);
+						assert(ae.upr);
+						a.push(cast(void*)ae.upr);
+					}
+					else
+						assert(!ae.upr);
+
+					e = new CallExp(loc, e, a);
+					e = e.semantic(sc);
+					return e;
+				}
+			}
+		}
+
+		BinExp.semantic(sc);
+
+		if (e1.op == TOK.TOKdottd)
+		{	
+			// Rewrite a.b=e2, when b is a template, as a.b(e2)
+			Expression e = new CallExp(loc, e1, e2);
+			e = e.semantic(sc);
+			return e;
+		}
+
+		e2 = resolveProperties(sc, e2);
+		assert(e1.type);
+
+		/* Rewrite tuple assignment as a tuple of assignments.
+		 */
+		if (e1.op == TOK.TOKtuple && e2.op == TOK.TOKtuple)
+		{	
+			TupleExp tup1 = cast(TupleExp)e1;
+			TupleExp tup2 = cast(TupleExp)e2;
+			size_t dim = tup1.exps.dim;
+			if (dim != tup2.exps.dim)
+			{
+				error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
+			}
+			else
+			{   
+				Expressions exps = new Expressions;
+				exps.setDim(dim);
+
+				for (int i = 0; i < dim; i++)
+				{	
+					Expression ex1 = cast(Expression)tup1.exps.data[i];
+					Expression ex2 = cast(Expression)tup2.exps.data[i];
+					exps.data[i] = cast(void*) new AssignExp(loc, ex1, ex2);
+				}
+				Expression e = new TupleExp(loc, exps);
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+
+		// Determine if this is an initialization of a reference
+		int refinit = 0;
+		if (op == TOK.TOKconstruct && e1.op == TOK.TOKvar)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			VarDeclaration v = ve.var.isVarDeclaration();
+			if (v.storage_class & (STC.STCout | STC.STCref))
+				refinit = 1;
+		}
+
+		Type t1 = e1.type.toBasetype();
+
+		if (t1.ty == TY.Tfunction)
+		{	
+			// Rewrite f=value to f(value)
+			Expression e = new CallExp(loc, e1, e2);
+			e = e.semantic(sc);
+			return e;
+		}
+
+		/* If it is an assignment from a 'foreign' type,
+		 * check for operator overloading.
+		 */
+		if (t1.ty == TY.Tstruct)
+		{
+			StructDeclaration sd = (cast(TypeStruct)t1).sym;
+			if (op == TOK.TOKassign)
+			{
+				Expression e = op_overload(sc);
+				if (e)
+					return e;
+			}
+			else if (op == TOK.TOKconstruct && !refinit)
+			{   
+				Type t2 = e2.type.toBasetype();
+				if (t2.ty == TY.Tstruct && sd == (cast(TypeStruct)t2).sym && sd.cpctor)
+				{	
+					/* We have a copy constructor for this
+					 */
+					if (e2.op == TOK.TOKquestion)
+					{   /* Write as:
+						 *	a ? e1 = b : e1 = c;
+						 */
+						CondExp ec = cast(CondExp)e2;
+						AssignExp ea1 = new AssignExp(ec.e1.loc, e1, ec.e1);
+						ea1.op = op;
+						AssignExp ea2 = new AssignExp(ec.e1.loc, e1, ec.e2);
+						ea2.op = op;
+						Expression e = new CondExp(loc, ec.econd, ea1, ea2);
+						return e.semantic(sc);
+					}
+					else if (e2.op == TOK.TOKvar || e2.op == TOK.TOKdotvar || e2.op == TOK.TOKstar || e2.op == TOK.TOKindex)
+					{   /* Write as:
+						 *	e1.cpctor(e2);
+						 */
+						Expression e = new DotVarExp(loc, e1, sd.cpctor, 0);
+						e = new CallExp(loc, e, e2);
+						return e.semantic(sc);
+					}
+				}
+			}
+		}
+		else if (t1.ty == TY.Tclass)
+		{	
+			// Disallow assignment operator overloads for same type
+			if (!e2.type.implicitConvTo(e1.type))
+			{
+				Expression e = op_overload(sc);
+				if (e)
+					return e;
+			}
+		}
+
+		if (t1.ty == TY.Tsarray && !refinit)
+		{	
+			// Convert e1 to e1[]
+			Expression e = new SliceExp(e1.loc, e1, null, null);
+			e1 = e.semantic(sc);
+			t1 = e1.type.toBasetype();
+		}
+
+		e2.rvalue();
+
+		if (e1.op == TOK.TOKarraylength)
+		{
+			// e1 is not an lvalue, but we let code generator handle it
+			ArrayLengthExp ale = cast(ArrayLengthExp)e1;
+			ale.e1 = ale.e1.modifiableLvalue(sc, e1);
+		}
+		else if (e1.op == TOK.TOKslice)
+		{
+			Type tn = e1.type.nextOf();
+			if (tn && !tn.isMutable() && op != TOK.TOKconstruct)
+				error("slice %s is not mutable", e1.toChars());
+		}
+		else
+		{	
+			// Try to do a decent error message with the expression
+			// before it got constant folded
+			if (e1.op != TOK.TOKvar)
+				e1 = e1.optimize(WANT.WANTvalue);
+
+			if (op != TOK.TOKconstruct)
+				e1 = e1.modifiableLvalue(sc, e1old);
+		}
+
+		Type t2 = e2.type;
+		if (e1.op == TOK.TOKslice && t1.nextOf() && e2.implicitConvTo(t1.nextOf()))
+		{	
+			// memset
+			ismemset = 1;	// make it easy for back end to tell what this is
+			e2 = e2.implicitCastTo(sc, t1.nextOf());
+		}
+		else if (t1.ty == TY.Tsarray)
+		{
+			/* Should have already converted e1 => e1[]
+			 */
+			assert(op == TOK.TOKconstruct);
+			//error("cannot assign to static array %s", e1.toChars());
+		}
+		else if (e1.op == TOK.TOKslice)
+		{
+			e2 = e2.implicitCastTo(sc, e1.type.constOf());
+		}
+		else
+		{
+			e2 = e2.implicitCastTo(sc, e1.type);
+		}
+
+		/* Look for array operations
+		 */
+		if (e1.op == TOK.TOKslice && !ismemset &&
+			(e2.op == TOK.TOKadd || e2.op == TOK.TOKmin ||
+			 e2.op == TOK.TOKmul || e2.op == TOK.TOKdiv ||
+			 e2.op == TOK.TOKmod || e2.op == TOK.TOKxor ||
+			 e2.op == TOK.TOKand || e2.op == TOK.TOKor  ||
+			 e2.op == TOK.TOKtilde || e2.op == TOK.TOKneg))
+		{
+			type = e1.type;
+			return arrayOp(sc);
+		}
+
+		type = e1.type;
+		assert(type);
+		return this;
+	}
+
+	Expression checkToBoolean()
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.assign;
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	elem* 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 == TOK.TOKarraylength)
+		{
+			// Generate:
+			//	_d_arraysetlength(e2, sizeelem, &ale.e1);
+
+			ArrayLengthExp ale = cast(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();
+
+static if (true) {
+			// 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(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT;
+} else {
+			if (t1.next.isZeroInit())
+			{   
+				p2 = t1.getTypeInfo(null).toElem(irs);
+				ep = el_params(p3, p1, p2, null);	// c function
+				r = RTLSYM.RTLSYM_ARRAYSETLENGTHT;
+			}
+			else
+			{
+				p2 = el_long(TYM.TYint, t1.next.size());
+				ep = el_params(p3, p2, p1, null);	// c function
+				Expression init = t1.next.defaultInit();
+				ep = el_param(el_long(TYM.TYint, init.type.size()), ep);
+				elem* ei = init.toElem(irs);
+				ep = el_param(ei, ep);
+				r = RTLSYM.RTLSYM_ARRAYSETLENGTH3;
+			}
+}
+			e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep);
+			el_setLoc(e, loc);
+			return e;
+		}
+
+		// Look for array[]=n
+		if (e1.op == TOK.TOKslice)
+		{
+			Type t1 = t1b;
+			Type t2 = e2.type.toBasetype();
+
+			// which we do if the 'next' types match
+			if (ismemset)
+			{   
+				// Do a memset for array[]=v
+				//printf("Lpair %s\n", toChars());
+				SliceExp are = cast(SliceExp)e1;
+				elem* elwr;
+				elem* eupr;
+				elem* n1;
+				elem* evalue;
+				elem* enbytes;
+				elem* elength;
+				elem* einit;
+				long value;
+				Type ta = are.e1.type.toBasetype();
+				Type tb = ta.nextOf().toBasetype();
+				int sz = cast(uint)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 == TY.Tsarray)
+				{
+					TypeSArray ts = cast(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 == TY.Tarray)
+				{
+					n1 = el_same(&n1x);
+					einit = resolveLengthVar(are.lengthVar, &n1, ta);
+					enbytes = el_copytree(n1);
+					n1 = array_toPtr(ta, n1);
+					enbytes = el_una(OPER.OP64_32, TYM.TYint, enbytes);
+				}
+				else if (ta.ty == TY.Tpointer)
+				{
+					n1 = el_same(&n1x);
+					enbytes = el_long(TYM.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);
+
+	static if (false) {
+				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);
+	}
+				einit = el_combine(n1x, einit);
+				einit = el_combine(einit, elwrx);
+				einit = el_combine(einit, euprx);
+
+				evalue = this.e2.toElem(irs);
+
+	static if (false) {
+				printf("n1\n");
+				elem_print(n1);
+				printf("enbytes\n");
+				elem_print(enbytes);
+	}
+
+				if (global.params.useArrayBounds && eupr && ta.ty != TY.Tpointer)
+				{
+					elem *c1;
+					elem *c2;
+					elem *ea;
+					elem *eb;
+					elem *enbytesx;
+
+					assert(elwr);
+					enbytesx = enbytes;
+					enbytes = el_same(&enbytesx);
+					c1 = el_bin(OPER.OPle, TYM.TYint, el_copytree(eupr), enbytesx);
+					c2 = el_bin(OPER.OPle, TYM.TYint, el_copytree(elwr), el_copytree(eupr));
+					c1 = el_bin(OPER.OPandand, TYM.TYint, c1, c2);
+
+					// Construct: (c1 || ModuleArray(line))
+					Symbol *sassert;
+
+					sassert = irs.blx.module_.toModuleArray();
+					ea = el_bin(OPER.OPcall,TYM.TYvoid,el_var(sassert), el_long(TYM.TYint, loc.linnum));
+					eb = el_bin(OPER.OPoror,TYM.TYvoid,c1,ea);
+					einit = el_combine(einit, eb);
+				}
+
+				if (elwr)
+				{   
+					elem *elwr2;
+
+					el_free(enbytes);
+					elwr2 = el_copytree(elwr);
+					elwr2 = el_bin(OPER.OPmul, TYM.TYint, elwr2, el_long(TYM.TYint, sz));
+					n1 = el_bin(OPER.OPadd, TYM.TYnptr, n1, elwr2);
+					enbytes = el_bin(OPER.OPmin, TYM.TYint, eupr, elwr);
+					elength = el_copytree(enbytes);
+				}
+				else
+					elength = el_copytree(enbytes);
+
+				e = setArray(n1, enbytes, tb, evalue, irs, op);
+			Lpair:
+				e = el_pair(TYM.TYullong, elength, e);
+			Lret2:
+				e = el_combine(einit, e);
+				//elem_print(e);
+				goto Lret;
+			}
+///static if (false) {
+///			else if (e2.op == TOK.TOKadd || e2.op == TOK.TOKmin)
+///			{
+///				/* It's ea[] = eb[] +- ec[]
+///				 */
+///				BinExp e2a = cast(BinExp)e2;
+///				Type t = e2.type.toBasetype().nextOf().toBasetype();
+///				if (t.ty != TY.Tfloat32 && t.ty != TY.Tfloat64 && t.ty != TY.Tfloat80)
+///				{
+///					e2.error("array add/min for %s not supported", t.toChars());
+///					return el_long(TYM.TYint, 0);
+///				}
+///				elem* ea = e1.toElem(irs);
+///				ea = array_toDarray(e1.type, ea);
+///				elem* eb = e2a.e1.toElem(irs);
+///				eb = array_toDarray(e2a.e1.type, eb);
+///				elem* ec = e2a.e2.toElem(irs);
+///				ec = array_toDarray(e2a.e2.type, ec);
+///
+///				int rtl = RTLSYM.RTLSYM_ARRAYASSADDFLOAT;
+///				if (t.ty == Tfloat64)
+///				rtl = RTLSYM.RTLSYM_ARRAYASSADDDOUBLE;
+///				else if (t.ty == Tfloat80)
+///				rtl = RTLSYM.RTLSYM_ARRAYASSADDREAL;
+///				if (e2.op == TOK.TOKmin)
+///				{
+///				rtl = RTLSYM.RTLSYM_ARRAYASSMINFLOAT;
+///				if (t.ty == Tfloat64)
+///					rtl = RTLSYM.RTLSYM_ARRAYASSMINDOUBLE;
+///				else if (t.ty == Tfloat80)
+///					rtl = RTLSYM.RTLSYM_ARRAYASSMINREAL;
+///				}
+///
+///				/* Set parameters so the order of evaluation is eb, ec, ea
+///				 */
+///				elem* ep = el_params(eb, ec, ea, null);
+///				e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[rtl]), ep);
+///				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);
+
+				uint size = cast(uint)t1.nextOf().size();
+				esize = el_long(TYM.TYint, size);
+
+				/* Determine if we need to do postblit
+				 */
+				int postblit = 0;
+				if (needsPostblit(t1))
+					postblit = 1;
+
+				assert(e2.type.ty != TY.Tpointer);
+
+				if (!postblit && !global.params.useArrayBounds)
+				{	
+					elem* epto;
+					elem* epfr;
+					elem* elen;
+					elem* ex;
+
+					ex = el_same(&eto);
+
+					// Determine if elen is a constant
+					if (eto.Eoper == OPER.OPpair && eto.E1.Eoper == OPER.OPconst)
+					{
+						elen = el_copytree(eto.E1);
+					}
+					else
+					{
+						// It's not a constant, so pull it from the dynamic array
+						elen = el_una(OPER.OP64_32, TYM.TYint, el_copytree(ex));
+					}
+
+					esize = el_bin(OPER.OPmul, TYM.TYint, elen, esize);
+					epto = array_toPtr(e1.type, ex);
+					epfr = array_toPtr(e2.type, efrom);
+	static if (true) {
+					// memcpy() is faster, so if we can't beat 'em, join 'em
+					e = el_params(esize, epfr, epto, null);
+					e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[RTLSYM.RTLSYM_MEMCPY]), e);
+	} else {
+					e = el_bin(OPER.OPmemcpy, TYM.TYnptr, epto, el_param(epfr, esize));
+	}
+					e = el_pair(eto.Ety, el_copytree(elen), e);
+					e = el_combine(eto, e);
+				}
+///version (DMDV2) {
+				else if (postblit && op != TOK.TOKblit)
+				{
+					/* Generate:
+					 *	_d_arrayassign(ti, efrom, eto)
+					 * or:
+					 *	_d_arrayctor(ti, efrom, eto)
+					 */
+					el_free(esize);
+					Expression ti = t1.nextOf().toBasetype().getTypeInfo(null);
+					ep = el_params(eto, efrom, ti.toElem(irs), null);
+					int rtl = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYCTOR : RTLSYM.RTLSYM_ARRAYASSIGN;
+					e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[rtl]), ep);
+				}
+///}
+				else
+				{
+					// Generate:
+					//	_d_arraycopy(eto, efrom, esize)
+
+					ep = el_params(eto, efrom, esize, null);
+					e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[RTLSYM.RTLSYM_ARRAYCOPY]), ep);
+				}
+				el_setLoc(e, loc);
+				return e;
+			}
+		}
+
+		if (e1.op == TOK.TOKindex)
+		{
+			elem* eb;
+			elem* ei;
+			elem* ev;
+			TY ty;
+			Type ta;
+
+			ae = cast(IndexExp)e1;
+			ta = ae.e1.type.toBasetype();
+			ty = ta.ty;
+		}
+
+version (DMDV2) {
+		/* Look for reference initializations
+		 */
+		if (op == TOK.TOKconstruct && e1.op == TOK.TOKvar)
+		{
+			VarExp ve = cast(VarExp)e1;
+			Declaration s = ve.var;
+			if (s.storage_class & STC.STCref)
+			{
+static if (false) {
+				Expression ae = e2.addressOf(null);
+				e = ae.toElem(irs);
+} else {
+				e = e2.toElem(irs);
+				e = addressElem(e, e2.type);
+}
+				elem* es = el_var(s.toSymbol());
+				es.Ety = TYM.TYnptr;
+				e = el_bin(OPER.OPeq, TYM.TYnptr, es, e);
+				// BUG: type is struct, and e2 is TOKint64
+				goto Lret;
+			}
+		}
+}
+
+static if (true) {
+		/* 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 == TOK.TOKconstruct && e2.op == TOK.TOKcall)
+		{	
+			CallExp ce = cast(CallExp)e2;
+
+			TypeFunction tf = cast(TypeFunction)ce.e1.type.toBasetype();
+			if (tf.ty == TY.Tfunction && tf.retStyle() == RET.RETstack)
+			{
+				elem* ehidden = e1.toElem(irs);
+				ehidden = el_una(OPER.OPaddr, TYM.TYnptr, ehidden);
+				assert(!irs.ehidden);
+				irs.ehidden = ehidden;
+				e = e2.toElem(irs);
+				goto Lret;
+			}
+		}
+}
+	//printf("test2 %d\n", op);
+	//if (op == TOK.TOKconstruct) printf("construct\n");
+		if (t1b.ty == TY.Tstruct)
+		{
+			elem* eleft = e1.toElem(irs);
+
+			if (e2.op == TOK.TOKint64)
+			{   
+				/* Implement:
+				 *	(struct = 0)
+				 * with:
+				 *	memset(&struct, 0, struct.sizeof)
+				 */
+				elem* ey = null;
+				int sz = cast(int)e1.type.size();
+				StructDeclaration sd = (cast(TypeStruct)t1b).sym;
+				if (sd.isnested && op == TOK.TOKconstruct)
+				{
+					ey = el_una(OPER.OPaddr, TYM.TYnptr, eleft);
+					eleft = el_same(&ey);
+					ey = setEthis(loc, irs, ey, sd);
+					sz = sd.vthis.offset;
+				}
+
+				elem *el = eleft;
+				elem *enbytes = el_long(TYM.TYint, sz);
+				elem *evalue = el_long(TYM.TYint, 0);
+
+				if (!(sd.isnested && op == TOK.TOKconstruct))
+					el = el_una(OPER.OPaddr, TYM.TYnptr, el);
+
+				e = el_param(enbytes, evalue);
+				e = el_bin(OPER.OPmemset, TYM.TYnptr,el,e);
+				e = el_combine(ey, e);
+				el_setLoc(e, loc);
+				//e = el_una(OPER.OPind, TYM.TYstruct, e);
+			}
+			else
+			{
+				//printf("toElemBin() '%s'\n", toChars());
+
+				tym_t tym = type.totym();
+
+				elem* e1 = eleft;
+				elem* ex = e1;
+				if (e1.Eoper == OPER.OPind)
+					ex = e1.E1;
+
+				if (this.e2.op == TOK.TOKstructliteral && ex.Eoper == OPER.OPvar && ex.EV.sp.Voffset == 0)
+				{	
+					StructLiteralExp se = cast(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 == TOK.TOKconstruct || op == TOK.TOKblit) ? 1 : 0;
+
+					el_free(e1);
+					e = this.e2.toElem(irs);
+
+					se.sym = symSave;
+					se.soffset = soffsetSave;
+					se.fillHoles = fillHolesSave;
+				}
+				else
+				{
+					elem* e2 = this.e2.toElem(irs);
+					e = el_bin(OPER.OPstreq,tym,e1,e2);
+					e.Enumbytes = cast(uint)this.e1.type.size();
+				}
+				goto Lret;
+			}
+		}
+		else
+			e = toElemBin(irs,OPER.OPeq);
+
+		return e;
+
+	  Lret:
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AssocArrayLiteralExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,111 @@
+module dmd.AssocArrayLiteralExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+
+class AssocArrayLiteralExp : Expression
+{
+	Expressions keys;
+
+	Expressions values;
+
+	this(Loc loc, Expressions keys, Expressions values)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+		assert(false);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		assert(false);
+	}
+
+	bool canThrow()
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/AttribDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,265 @@
+module dmd.AttribDeclaration;
+
+import dmd.Dsymbol;
+import dmd.Array;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.LINK;
+import dmd.STC;
+import dmd.PROT;
+import dmd.ArrayTypes;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class AttribDeclaration : Dsymbol
+{
+    Array decl;	// array of Dsymbol's
+
+    this(Array decl)
+	{
+		this.decl = decl;
+	}
+	
+    Array include(Scope sc, ScopeDsymbol sd)
+	{
+		return decl;
+	}
+	
+    bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
+	{
+		bool m = false;
+		Array d = include(sc, sd);
+
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				m |= s.addMember(sc, sd, m | memnum);
+			}
+		}
+
+		return m;
+	}
+	
+    void setScopeNewSc(Scope sc, STC stc, LINK linkage, PROT protection, int explicitProtection, uint structalign)
+	{
+		if (decl)
+		{
+			Scope newsc = sc;
+			if (stc != sc.stc || linkage != sc.linkage || protection != sc.protection || explicitProtection != sc.explicitProtection || structalign != sc.structalign)
+			{
+				// create new one for changes
+				newsc = new Scope(sc);
+				newsc.offset = sc.offset;
+				newsc.scopesym = sc.scopesym;
+				newsc.flags &= ~SCOPE.SCOPEfree;
+				newsc.stc = stc;
+				newsc.linkage = linkage;
+				newsc.protection = protection;
+				newsc.explicitProtection = explicitProtection;
+				newsc.structalign = structalign;
+			}
+			for (uint i = 0; i < decl.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)decl.data[i];
+				s.setScope(newsc);	// yes, the only difference from semanticNewSc()
+			}
+			if (newsc != sc)
+			{
+				sc.offset = newsc.offset;
+				newsc.pop();
+			}
+		}
+	}
+	
+    void semanticNewSc(Scope sc, STC stc, LINK linkage, PROT protection, int explicitProtection, uint structalign)
+	{
+		if (decl)
+		{
+			Scope newsc = sc;
+			if (stc != sc.stc || linkage != sc.linkage || protection != sc.protection || explicitProtection != sc.explicitProtection || structalign != sc.structalign)
+			{
+				// create new one for changes
+				newsc = new Scope(sc);
+				newsc.offset = sc.offset;
+				newsc.scopesym = sc.scopesym;
+				newsc.flags &= ~SCOPE.SCOPEfree;
+				newsc.stc = stc;
+				newsc.linkage = linkage;
+				newsc.protection = protection;
+				newsc.explicitProtection = explicitProtection;
+				newsc.structalign = structalign;
+			}
+			for (uint i = 0; i < decl.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)decl.data[i];
+				s.semantic(newsc);
+			}
+			if (newsc != sc)
+			{
+				sc.offset = newsc.offset;
+				newsc.pop();
+			}
+		}
+	}
+	
+    void semantic(Scope sc)
+	{
+		Array d = include(sc, null);
+
+		//printf("\tAttribDeclaration::semantic '%s', d = %p\n",toChars(), d);
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)d.data[i];
+
+				s.semantic(sc);
+			}
+		}
+	}
+	
+    void semantic2(Scope sc)
+	{
+		Array d = include(sc, null);
+
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   Dsymbol s = cast(Dsymbol)d.data[i];
+				s.semantic2(sc);
+			}
+		}
+	}
+	
+    void semantic3(Scope sc)
+	{
+		Array d = include(sc, null);
+
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				s.semantic3(sc);
+			}
+		}
+	}
+	
+    void inlineScan()
+	{
+		Array d = include(null, null);
+
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				//printf("AttribDeclaration.inlineScan %s\n", s.toChars());
+				s.inlineScan();
+			}
+		}
+	}
+	
+    void addComment(ubyte* comment)
+	{
+		if (comment !is null)
+		{
+			Array d = include(null, null);
+			if (d)
+			{
+				for (uint i = 0; i < d.dim; i++)
+				{  
+					Dsymbol s = cast(Dsymbol)d.data[i];
+					//printf("AttribDeclaration::addComment %s\n", s.toChars());
+					s.addComment(comment);
+				}
+			}
+		}
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    bool hasPointers()
+	{
+		Array d = include(null, null);
+
+		if (d)
+		{
+			for (size_t i = 0; i < d.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				if (s.hasPointers())
+					return true;
+			}
+		}
+
+		return 0;
+	}
+	
+    void checkCtorConstInit()
+	{
+		Array d = include(null, null);
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				s.checkCtorConstInit();
+			}
+		}
+	}
+	
+    void addLocalClass(ClassDeclarations aclasses)
+	{
+		Array d = include(null, null);
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				s.addLocalClass(aclasses);
+			}
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    AttribDeclaration isAttribDeclaration() { return this; }
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		Array d = include(null, null);
+
+		if (d)
+		{
+			for (uint i = 0; i < d.dim; i++)
+			{   
+				Dsymbol s = cast(Dsymbol)d.data[i];
+				s.toObjFile(multiobj);
+			}
+		}
+	}
+	
+    int cvMember(ubyte* p)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BE.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,16 @@
+module dmd.BE;
+
+/* How a statement exits; this is returned by blockExit()
+ */
+enum BE
+{
+	BEnone =	 0,
+    BEfallthru = 1,
+    BEthrow =    2,
+    BEreturn =   4,
+    BEgoto =     8,
+    BEhalt =	 0x10,
+    BEbreak =	 0x20,
+    BEcontinue = 0x40,
+    BEany = (BEfallthru | BEthrow | BEreturn | BEgoto | BEhalt),
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BUILTIN.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,12 @@
+module dmd.BUILTIN;
+
+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
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BaseClass.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,138 @@
+module dmd.BaseClass;
+
+import dmd.Type;
+import dmd.PROT;
+import dmd.ClassDeclaration;
+import dmd.Array;
+import dmd.TY;
+import dmd.TypeFunction;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.ArrayTypes;
+
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class BaseClass
+{
+    Type type;				// (before semantic processing)
+    PROT protection;		// protection for the base interface
+
+    ClassDeclaration base;
+    int offset;				// 'this' pointer offset
+    Array vtbl;				// for interfaces: Array of FuncDeclaration's
+					// making up the vtbl[]
+
+    //int baseInterfaces_dim;
+    BaseClass[] baseInterfaces;		// if BaseClass is an interface, these
+					// are a copy of the InterfaceDeclaration::interfaces
+
+    this()
+	{
+		vtbl = new Array();
+	}
+
+    this(Type type, PROT protection)
+	{
+		//printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
+		this.type = type;
+		this.protection = protection;
+		
+		vtbl = new Array();
+	}
+
+	/****************************************
+	 * Fill in vtbl[] for base class based on member functions of class cd.
+	 * Input:
+	 *	vtbl		if !=null, fill it in
+	 *	newinstance	!=0 means all entries must be filled in by members
+	 *			of cd, not members of any base classes of cd.
+	 * Returns:
+	 *	true if any entries were filled in by members of cd (not exclusively
+	 *	by base classes)
+	 */
+    bool fillVtbl(ClassDeclaration cd, Array vtbl, int newinstance)
+	{
+		ClassDeclaration id = base;
+		int j;
+		bool result = false;
+
+		//printf("BaseClass.fillVtbl(this='%s', cd='%s')\n", base.toChars(), cd.toChars());
+		if (vtbl)
+			vtbl.setDim(base.vtbl.dim);
+
+		// first entry is ClassInfo reference
+		for (j = base.vtblOffset(); j < base.vtbl.dim; j++)
+		{
+			FuncDeclaration ifd = (cast(Dsymbol)base.vtbl.data[j]).isFuncDeclaration();
+			FuncDeclaration fd;
+			TypeFunction tf;
+
+			//printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd.toChars() : "null");
+
+			assert(ifd);
+			// Find corresponding function in this class
+			tf = (ifd.type.ty == Tfunction) ? cast(TypeFunction)(ifd.type) : null;
+			fd = cd.findFunc(ifd.ident, tf);
+			if (fd && !fd.isAbstract())
+			{
+				//printf("            found\n");
+				// Check that calling conventions match
+				if (fd.linkage != ifd.linkage)
+					fd.error("linkage doesn't match interface function");
+
+				// Check that it is current
+				if (newinstance &&
+					fd.toParent() != cd &&
+					ifd.toParent() == base
+				)
+					cd.error("interface function %s.%s is not implemented",
+					id.toChars(), ifd.ident.toChars());
+
+				if (fd.toParent() == cd)
+					result = true;
+			}
+			else
+			{
+				//printf("            not found\n");
+				// BUG: should mark this class as abstract?
+				if (!cd.isAbstract())
+					cd.error("interface function %s.%s isn't implemented", id.toChars(), ifd.ident.toChars());
+				fd = null;
+			}
+			if (vtbl)
+				vtbl.data[j] = cast(void*)fd;
+		}
+
+		return result;
+	}
+	
+    void copyBaseInterfaces(BaseClasses vtblInterfaces)
+	{
+		//printf("+copyBaseInterfaces(), %s\n", base.toChars());
+	//    if (baseInterfaces_dim)
+	//	return;
+
+		baseInterfaces.length = base.interfaces_dim;
+
+		int size = BaseClass.classinfo.init.length;
+
+		//printf("%s.copyBaseInterfaces()\n", base.toChars());
+		for (int i = 0; i < baseInterfaces.length; i++)
+		{
+			BaseClass b2 = base.interfaces[i];
+			assert(b2.vtbl.dim == 0);	// should not be filled yet
+
+			void* mem = malloc(size);
+			memcpy(mem, cast(void*)b2, size);
+
+			BaseClass b = cast(BaseClass)mem;
+			baseInterfaces[i] = b;
+
+			if (i)				// single inheritance is i==0
+				vtblInterfaces.push(cast(void*)b);	// only need for M.I.
+			b.copyBaseInterfaces(vtblInterfaces);
+		}
+		//printf("-copyBaseInterfaces\n");
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BinExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,920 @@
+module dmd.BinExp;
+
+import dmd.Expression;
+import dmd.Loc;
+import dmd.ClassDeclaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.IRState;
+import dmd.Scope;
+import dmd.Type;
+import dmd.InterState;
+import dmd.InlineCostState;
+import dmd.InlineScanState;
+import dmd.InlineDoState;
+import dmd.AggregateDeclaration;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.declaration.Match;
+import dmd.ArrayTypes;
+import dmd.TY;
+import dmd.TypeClass;
+import dmd.TypeStruct;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.TemplateDeclaration;
+import dmd.DotIdExp;
+import dmd.ErrorExp;
+import dmd.WANT;
+import dmd.IntegerExp;
+import dmd.MulExp;
+import dmd.Token;
+import dmd.PREC;
+
+import dmd.expression.Util;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+
+import std.stdio : writef;
+
+/**************************************
+ * Combine types.
+ * Output:
+ *	*pt	merged type, if *pt is not null
+ *	*pe1	rewritten e1
+ *	*pe2	rewritten e2
+ * Returns:
+ *	!=0	success
+ *	0	failed
+ */
+
+int typeMerge(Scope sc, Expression e, Type* pt, Expression* pe1, Expression* pe2)
+{
+    //printf("typeMerge() %s op %s\n", (*pe1).toChars(), (*pe2).toChars());
+    //dump(0);
+
+    Expression e1 = (*pe1).integralPromotions(sc);
+    Expression e2 = (*pe2).integralPromotions(sc);
+
+    Type t1 = e1.type;
+    Type t2 = e2.type;
+    assert(t1);
+    Type t = t1;
+
+    //if (t1) printf("\tt1 = %s\n", t1.toChars());
+    //if (t2) printf("\tt2 = %s\n", t2.toChars());
+debug {
+    if (!t2) writef("\te2 = '%s'\n", e2.toChars());
+}
+    assert(t2);
+
+    Type t1b = t1.toBasetype();
+    Type t2b = t2.toBasetype();
+
+    TY ty = cast(TY)Type.impcnvResult[t1b.ty][t2b.ty];
+    if (ty != TY.Terror)
+    {
+		TY ty1;
+		TY ty2;
+
+		ty1 = cast(TY)Type.impcnvType1[t1b.ty][t2b.ty];
+		ty2 = cast(TY)Type.impcnvType2[t1b.ty][t2b.ty];
+
+		if (t1b.ty == ty1)	// if no promotions
+		{
+			if (t1 == t2)
+			{
+				t = t1;
+				goto Lret;
+			}
+
+			if (t1b == t2b)
+			{
+				t = t1b;
+				goto Lret;
+			}
+		}
+
+		t = Type.basic[ty];
+
+		t1 = Type.basic[ty1];
+		t2 = Type.basic[ty2];
+
+		e1 = e1.castTo(sc, t1);
+		e2 = e2.castTo(sc, t2);
+		//printf("after typeCombine():\n");
+		//dump(0);
+		//printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2);
+		goto Lret;
+    }
+
+    t1 = t1b;
+    t2 = t2b;
+
+Lagain:
+    if (t1 == t2)
+    {
+    }
+    else if (t1.ty == TY.Tpointer && t2.ty == TY.Tpointer)
+    {
+		// Bring pointers to compatible type
+		Type t1n = t1.nextOf();
+		Type t2n = t2.nextOf();
+
+		if (t1n == t2n) {
+			;
+		} else if (t1n.ty == TY.Tvoid)	{// pointers to void are always compatible
+			t = t2;
+		} else if (t2n.ty == TY.Tvoid) {
+			;
+		} else if (t1n.mod != t2n.mod) {
+			t1 = t1n.mutableOf().constOf().pointerTo();
+			t2 = t2n.mutableOf().constOf().pointerTo();
+			t = t1;
+			goto Lagain;
+		} else if (t1n.ty == TY.Tclass && t2n.ty == TY.Tclass) {
+			ClassDeclaration cd1 = t1n.isClassHandle();
+			ClassDeclaration cd2 = t2n.isClassHandle();
+			int offset;
+
+			if (cd1.isBaseOf(cd2, &offset))
+			{
+			if (offset)
+				e2 = e2.castTo(sc, t);
+			}
+			else if (cd2.isBaseOf(cd1, &offset))
+			{
+			t = t2;
+			if (offset)
+				e1 = e1.castTo(sc, t);
+			}
+			else
+			goto Lincompatible;
+		} else {
+			goto Lincompatible;
+		}
+    }
+    else if ((t1.ty == TY.Tsarray || t1.ty == TY.Tarray) &&
+	     e2.op == TOK.TOKnull && t2.ty == TY.Tpointer && t2.nextOf().ty == TY.Tvoid)
+    {	/*  (T[n] op void*)
+		 *  (T[] op void*)
+		 */
+		goto Lx1;
+    }
+    else if ((t2.ty == TY.Tsarray || t2.ty == TY.Tarray) &&
+	     e1.op == TOK.TOKnull && t1.ty == TY.Tpointer && t1.nextOf().ty == TY.Tvoid)
+    {	/*  (void* op T[n])
+		 *  (void* op T[])
+		 */
+		goto Lx2;
+    }
+    else if ((t1.ty == TY.Tsarray || t1.ty == TY.Tarray) && t1.implicitConvTo(t2))
+    {
+		goto Lt2;
+    }
+    else if ((t2.ty == TY.Tsarray || t2.ty == TY.Tarray) && t2.implicitConvTo(t1))
+    {
+		goto Lt1;
+    }
+    /* If one is mutable and the other invariant, then retry
+     * with both of them as const
+     */
+    else if ((t1.ty == TY.Tsarray || t1.ty == TY.Tarray || t1.ty == TY.Tpointer) &&
+	     (t2.ty == TY.Tsarray || t2.ty == TY.Tarray || t2.ty == TY.Tpointer) &&
+	     t1.nextOf().mod != t2.nextOf().mod
+	    )
+    {
+		if (t1.ty == TY.Tpointer)
+			t1 = t1.nextOf().mutableOf().constOf().pointerTo();
+		else
+			t1 = t1.nextOf().mutableOf().constOf().arrayOf();
+
+		if (t2.ty == TY.Tpointer)
+			t2 = t2.nextOf().mutableOf().constOf().pointerTo();
+		else
+			t2 = t2.nextOf().mutableOf().constOf().arrayOf();
+		t = t1;
+		goto Lagain;
+    }
+    else if (t1.ty == TY.Tclass || t2.ty == TY.Tclass)
+    {
+		while (1)
+		{
+			int i1 = e2.implicitConvTo(t1);
+			int i2 = e1.implicitConvTo(t2);
+
+			if (i1 && i2)
+			{
+			// We have the case of class vs. void*, so pick class
+			if (t1.ty == TY.Tpointer)
+				i1 = 0;
+			else if (t2.ty == TY.Tpointer)
+				i2 = 0;
+			}
+
+			if (i2)
+			{
+				goto Lt2;
+			}
+			else if (i1)
+			{
+				goto Lt1;
+			}
+			else if (t1.ty == TY.Tclass && t2.ty == TY.Tclass)
+			{	
+				TypeClass tc1 = cast(TypeClass)t1;
+				TypeClass tc2 = cast(TypeClass)t2;
+
+				/* Pick 'tightest' type
+				 */
+				ClassDeclaration cd1 = tc1.sym.baseClass;
+				ClassDeclaration cd2 = tc2.sym.baseClass;
+
+				if (cd1 && cd2)
+				{   t1 = cd1.type;
+					t2 = cd2.type;
+				}
+				else if (cd1)
+					t1 = cd1.type;
+				else if (cd2)
+					t2 = cd2.type;
+				else
+					goto Lincompatible;
+			}
+			else
+				goto Lincompatible;
+		}
+    }
+    else if (t1.ty == TY.Tstruct && t2.ty == TY.Tstruct)
+    {
+		if ((cast(TypeStruct)t1).sym != (cast(TypeStruct)t2).sym)
+			goto Lincompatible;
+    }
+    else if ((e1.op == TOK.TOKstring || e1.op == TOK.TOKnull) && e1.implicitConvTo(t2))
+    {
+		goto Lt2;
+    }
+    else if ((e2.op == TOK.TOKstring || e2.op == TOK.TOKnull) && e2.implicitConvTo(t1))
+    {
+		goto Lt1;
+    }
+    else if (t1.ty == TY.Tsarray && t2.ty == TY.Tsarray &&
+	     e2.implicitConvTo(t1.nextOf().arrayOf()))
+    {
+     Lx1:
+		t = t1.nextOf().arrayOf();
+		e1 = e1.castTo(sc, t);
+		e2 = e2.castTo(sc, t);
+    }
+    else if (t1.ty == TY.Tsarray && t2.ty == TY.Tsarray &&
+	     e1.implicitConvTo(t2.nextOf().arrayOf()))
+    {
+     Lx2:
+		t = t2.nextOf().arrayOf();
+		e1 = e1.castTo(sc, t);
+		e2 = e2.castTo(sc, t);
+    }
+    else if (t1.isintegral() && t2.isintegral())
+    {
+		assert(0);
+    }
+    else if (e1.op == TOK.TOKslice && t1.ty == TY.Tarray &&
+	     e2.implicitConvTo(t1.nextOf()))
+    {	// T[] op T
+		e2 = e2.castTo(sc, t1.nextOf());
+		t = t1.nextOf().arrayOf();
+    }
+    else if (e2.op == TOK.TOKslice && t2.ty == TY.Tarray &&
+	     e1.implicitConvTo(t2.nextOf()))
+    {	// T op T[]
+		e1 = e1.castTo(sc, t2.nextOf());
+		t = t2.nextOf().arrayOf();
+
+		//printf("test %s\n", e.toChars());
+		e1 = e1.optimize(WANT.WANTvalue);
+		if (e && e.isCommutative() && e1.isConst())
+		{   /* Swap operands to minimize number of functions generated
+			 */
+			//printf("swap %s\n", e.toChars());
+			Expression tmp = e1;
+			e1 = e2;
+			e2 = tmp;
+		}
+    }
+    else
+    {
+     Lincompatible:
+		return 0;
+    }
+Lret:
+    if (!*pt)
+	*pt = t;
+    *pe1 = e1;
+    *pe2 = e2;
+static if (false) {
+    printf("-typeMerge() %s op %s\n", e1.toChars(), e2.toChars());
+    if (e1.type) printf("\tt1 = %s\n", e1.type.toChars());
+    if (e2.type) printf("\tt2 = %s\n", e2.type.toChars());
+    printf("\ttype = %s\n", t.toChars());
+}
+    //dump(0);
+    return 1;
+
+
+Lt1:
+    e2 = e2.castTo(sc, t1);
+    t = t1;
+    goto Lret;
+
+Lt2:
+    e1 = e1.castTo(sc, t2);
+    t = t2;
+    goto Lret;
+}
+
+class BinExp : Expression
+{
+    Expression e1;
+    Expression e2;
+
+    this(Loc loc, TOK op, int size, Expression e1, Expression e2)
+	{
+		super(loc, op, size);
+		this.e1 = e1;
+		this.e2 = e2;
+	}
+	
+    Expression syntaxCopy()
+	{
+		BinExp e = cast(BinExp)copy();
+		e.type = null;
+		e.e1 = e.e1.syntaxCopy();
+		e.e2 = e.e2.syntaxCopy();
+
+		return e;
+	}
+
+    Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("BinExp.semantic('%s')\n", toChars());
+}
+		e1 = e1.semantic(sc);
+		if (!e1.type && !(op == TOK.TOKassign && e1.op == TOK.TOKdottd))	// a.template = e2
+		{
+			error("%s has no value", e1.toChars());
+			e1.type = Type.terror;
+		}
+		e2 = e2.semantic(sc);
+		if (!e2.type)
+		{
+			error("%s has no value", e2.toChars());
+			e2.type = Type.terror;
+		}
+		return this;
+	}
+	
+    Expression semanticp(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("BinExp.semantic('%s')\n", toChars());
+}
+		e1 = e1.semantic(sc);
+		if (!e1.type &&
+		!(op == TOK.TOKassign && e1.op == TOK.TOKdottd))	// a.template = e2
+		{
+			error("%s has no value", e1.toChars());
+			e1.type = Type.terror;
+		}
+		e2 = e2.semantic(sc);
+		if (!e2.type)
+		{
+			error("%s has no value", e2.toChars());
+			e2.type = Type.terror;
+		}
+		return this;
+	}
+	
+    Expression commonSemanticAssign(Scope sc)
+	{
+		assert(false);
+	}
+
+    Expression commonSemanticAssignIntegral(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{
+			BinExp.semantic(sc);
+			e2 = resolveProperties(sc, e2);
+
+			e = op_overload(sc);
+			if (e)
+				return e;
+
+			if (e1.op == TOK.TOKslice)
+			{   // T[] op= ...
+				typeCombine(sc);
+				type = e1.type;
+				return arrayOp(sc);
+			}
+
+			e1 = e1.modifiableLvalue(sc, e1);
+			e1.checkScalar();
+			type = e1.type;
+			if (type.toBasetype().ty == TY.Tbool)
+			{
+				e2 = e2.implicitCastTo(sc, type);
+			}
+
+			typeCombine(sc);
+			e1.checkIntegral();
+			e2.checkIntegral();
+		}
+
+		return this;
+	}
+	
+    bool checkSideEffect(int flag)
+	{
+		switch (op) {
+			case TOK.TOKplusplus:
+			case TOK.TOKminusminus:
+			case TOK.TOKassign:
+			case TOK.TOKconstruct:
+			case TOK.TOKblit:
+			case TOK.TOKaddass:
+			case TOK.TOKminass:
+			case TOK.TOKcatass:
+			case TOK.TOKmulass:
+			case TOK.TOKdivass:
+			case TOK.TOKmodass:
+			case TOK.TOKshlass:
+			case TOK.TOKshrass:
+			case TOK.TOKushrass:
+			case TOK.TOKandass:
+			case TOK.TOKorass:
+			case TOK.TOKxorass:
+			case TOK.TOKin:
+			case TOK.TOKremove:
+				return true;
+
+			default:
+				return Expression.checkSideEffect(flag);
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		expToCBuffer(buf, hgs, e1, precedence[op]);
+		buf.writeByte(' ');
+		buf.writestring(Token.toChars(op));
+		buf.writeByte(' ');
+		expToCBuffer(buf, hgs, e2, cast(PREC)(precedence[op] + 1));
+	}
+
+	/****************************************
+	 * Scale addition/subtraction to/from pointer.
+	 */
+    Expression scaleFactor(Scope sc)
+	{
+		ulong stride;
+		Type t1b = e1.type.toBasetype();
+		Type t2b = e2.type.toBasetype();
+
+		if (t1b.ty == Tpointer && t2b.isintegral())
+		{   
+			// Need to adjust operator by the stride
+			// Replace (ptr + int) with (ptr + (int * stride))
+			Type t = Type.tptrdiff_t;
+
+			stride = t1b.nextOf().size(loc);
+			if (!t.equals(t2b))
+				e2 = e2.castTo(sc, t);
+			e2 = new MulExp(loc, e2, new IntegerExp(Loc(0), stride, t));
+			e2.type = t;
+			type = e1.type;
+		}
+		else if (t2b.ty == Tpointer && t1b.isintegral())
+		{   
+			// Need to adjust operator by the stride
+			// Replace (int + ptr) with (ptr + (int * stride))
+			Type t = Type.tptrdiff_t;
+			Expression e;
+
+			stride = t2b.nextOf().size(loc);
+			if (!t.equals(t1b))
+				e = e1.castTo(sc, t);
+			else
+				e = e1;
+			e = new MulExp(loc, e, new IntegerExp(Loc(0), stride, t));
+			e.type = t;
+			type = e2.type;
+			e1 = e2;
+			e2 = e;
+		}
+		return this;
+	}
+	
+	/************************************
+	 * Bring leaves to common type.
+	 */
+    Expression typeCombine(Scope sc)
+	{
+		Type t1 = e1.type.toBasetype();
+		Type t2 = e2.type.toBasetype();
+
+		if (op == TOK.TOKmin || op == TOK.TOKadd)
+		{
+			if (t1.ty == TY.Tstruct)
+			{
+				if (t2.ty == TY.Tstruct && (cast(TypeStruct)t1).sym is (cast(TypeStruct)t2).sym)
+					goto Lerror;
+			}
+			else if (t1.ty == TY.Tclass)
+			{
+				if (t2.ty == TY.Tclass)
+					goto Lerror;
+			}
+		}
+
+		if (!typeMerge(sc, this, &type, &e1, &e2))
+			goto Lerror;
+		return this;
+
+	Lerror:
+		incompatibleTypes();
+		type = Type.terror;
+		e1 = new ErrorExp();
+		e2 = new ErrorExp();
+		return this;
+	}
+
+    Expression optimize(int result)
+	{
+		//printf("BinExp.optimize(result = %d) %s\n", result, toChars());
+		if (op != TOK.TOKconstruct && op != TOK.TOKblit)	// don't replace const variable with its initializer
+			e1 = e1.optimize(result);
+
+		e2 = e2.optimize(result);
+		if (op == TOK.TOKshlass || op == TOK.TOKshrass || op == TOK.TOKushrass)
+		{
+			if (e2.isConst() == 1)
+			{
+				long  i2 = e2.toInteger();
+				ulong sz = e1.type.size() * 8;
+
+				if (i2 < 0 || i2 > sz)
+				{   
+					error("shift assign by %jd is outside the range 0..%zu", i2, sz);
+					e2 = new IntegerExp(0);
+				}
+			}
+		}
+
+		return this;
+	}
+
+    bool isunsigned()
+	{
+		assert(false);
+	}
+	
+    void incompatibleTypes()
+	{
+		error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
+         e1.toChars(), Token.toChars(op), e2.toChars(),
+         e1.type.toChars(), e2.type.toChars());
+	}
+
+    void dump(int indent)
+	{
+		assert(false);
+	}
+
+    void scanForNestedRef(Scope *sc)
+	{
+		assert(false);
+	}
+	
+    Expression interpretCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *))
+	{
+		assert(false);
+	}
+
+    Expression interpretCommon2(InterState *istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *))
+	{
+		assert(false);
+	}
+	
+    Expression interpretAssignCommon(InterState *istate, Expression *(*fp)(Type *, Expression *, Expression *), int post = 0)
+	{
+		assert(false);
+	}
+	
+    bool canThrow()
+	{
+		return e1.canThrow() || e2.canThrow();
+	}
+
+    Expression arrayOp(Scope sc)
+	{
+		assert(false);
+	}
+
+    int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics) + e2.inlineCost(ics);
+	}
+	
+    Expression doInline(InlineDoState ids)
+	{
+		BinExp be = cast(BinExp)copy();
+
+		be.e1 = e1.doInline(ids);
+		be.e2 = e2.doInline(ids);
+		return be;
+	}
+	
+    Expression inlineScan(InlineScanState* iss)
+	{
+		e1 = e1.inlineScan(iss);
+		e2 = e2.inlineScan(iss);
+		return this;
+	}
+
+    Expression op_overload(Scope sc)
+	{
+		//printf("BinExp.op_overload() (%s)\n", toChars());
+
+		AggregateDeclaration ad;
+		Type t1 = e1.type.toBasetype();
+		Type t2 = e2.type.toBasetype();
+		Identifier id = opId();
+		Identifier id_r = opId_r();
+
+		Match m;
+		scope Expressions args1 = new Expressions();
+		scope Expressions args2 = new Expressions();
+		int argsset = 0;
+
+		AggregateDeclaration ad1;
+		if (t1.ty == TY.Tclass)
+			ad1 = (cast(TypeClass)t1).sym;
+		else if (t1.ty == TY.Tstruct)
+			ad1 = (cast(TypeStruct)t1).sym;
+		else
+			ad1 = null;
+
+		AggregateDeclaration ad2;
+		if (t2.ty == TY.Tclass)
+			ad2 = (cast(TypeClass)t2).sym;
+		else if (t2.ty == TY.Tstruct)
+			ad2 = (cast(TypeStruct)t2).sym;
+		else
+			ad2 = null;
+
+		Dsymbol s = null;
+		Dsymbol s_r = null;
+		FuncDeclaration fd = null;
+		TemplateDeclaration td = null;
+		if (ad1 && id)
+		{
+			s = search_function(ad1, id);
+		}
+		if (ad2 && id_r)
+		{
+			s_r = search_function(ad2, id_r);
+		}
+
+		if (s || s_r)
+		{
+			/* Try:
+			 *	a.opfunc(b)
+			 *	b.opfunc_r(a)
+			 * and see which is better.
+			 */
+			Expression e;
+			FuncDeclaration lastf;
+
+			args1.setDim(1);
+			args1.data[0] = cast(void*) e1;
+			args2.setDim(1);
+			args2.data[0] = cast(void*) e2;
+			argsset = 1;
+
+			///memset(&m, 0, sizeof(m));
+			m.last = MATCH.MATCHnomatch;
+
+			if (s)
+			{
+				fd = s.isFuncDeclaration();
+				if (fd)
+				{
+					overloadResolveX(&m, fd, null, args2);
+				}
+				else
+				{   
+					td = s.isTemplateDeclaration();
+					templateResolve(&m, td, sc, loc, null, null, args2);
+				}
+			}
+			
+			lastf = m.lastf;
+
+			if (s_r)
+			{
+				fd = s_r.isFuncDeclaration();
+				if (fd)
+				{
+					overloadResolveX(&m, fd, null, args1);
+				}
+				else
+				{  
+					td = s_r.isTemplateDeclaration();
+					templateResolve(&m, td, sc, loc, null, null, args1);
+				}
+			}
+
+			if (m.count > 1)
+			{
+				// Error, ambiguous
+				error("overloads %s and %s both match argument list for %s",
+					m.lastf.type.toChars(),
+					m.nextf.type.toChars(),
+					m.lastf.toChars());
+			}
+			else if (m.last == MATCH.MATCHnomatch)
+			{
+				m.lastf = m.anyf;
+			}
+
+			if (op == TOK.TOKplusplus || op == TOK.TOKminusminus)
+				// Kludge because operator overloading regards e++ and e--
+				// as unary, but it's implemented as a binary.
+				// Rewrite (e1 ++ e2) as e1.postinc()
+				// Rewrite (e1 -- e2) as e1.postdec()
+				e = build_overload(loc, sc, e1, null, id);
+			else if (lastf && m.lastf == lastf || m.last == MATCH.MATCHnomatch)
+				// Rewrite (e1 op e2) as e1.opfunc(e2)
+				e = build_overload(loc, sc, e1, e2, id);
+			else
+				// Rewrite (e1 op e2) as e2.opfunc_r(e1)
+				e = build_overload(loc, sc, e2, e1, id_r);
+			return e;
+		}
+
+		if (isCommutative())
+		{
+			s = null;
+			s_r = null;
+			if (ad1 && id_r)
+			{
+				s_r = search_function(ad1, id_r);
+			}
+			if (ad2 && id)
+			{
+				s = search_function(ad2, id);
+			}
+
+			if (s || s_r)
+			{
+				/* Try:
+				 *	a.opfunc_r(b)
+				 *	b.opfunc(a)
+				 * and see which is better.
+				 */
+
+				if (!argsset)
+				{	
+					args1.setDim(1);
+					args1.data[0] = cast(void*) e1;
+					args2.setDim(1);
+					args2.data[0] = cast(void*) e2;
+				}
+
+				///memset(&m, 0, sizeof(m));
+				m.last = MATCH.MATCHnomatch;
+
+				if (s_r)
+				{
+					fd = s_r.isFuncDeclaration();
+					if (fd)
+					{
+						overloadResolveX(&m, fd, null, args2);
+					}
+					else
+					{   td = s_r.isTemplateDeclaration();
+						templateResolve(&m, td, sc, loc, null, null, args2);
+					}
+				}
+				FuncDeclaration lastf = m.lastf;
+
+				if (s)
+				{
+					fd = s.isFuncDeclaration();
+					if (fd)
+					{
+						overloadResolveX(&m, fd, null, args1);
+					}
+					else
+					{   td = s.isTemplateDeclaration();
+						templateResolve(&m, td, sc, loc, null, null, args1);
+					}
+				}
+
+				if (m.count > 1)
+				{
+					// Error, ambiguous
+					error("overloads %s and %s both match argument list for %s",
+						m.lastf.type.toChars(),
+						m.nextf.type.toChars(),
+						m.lastf.toChars());
+				}
+				else if (m.last == MATCH.MATCHnomatch)
+				{
+					m.lastf = m.anyf;
+				}
+
+				Expression e;
+				if (lastf && m.lastf == lastf || id_r && m.last == MATCH.MATCHnomatch)
+					// Rewrite (e1 op e2) as e1.opfunc_r(e2)
+					e = build_overload(loc, sc, e1, e2, id_r);
+				else
+					// Rewrite (e1 op e2) as e2.opfunc(e1)
+					e = build_overload(loc, sc, e2, e1, id);
+
+				// When reversing operands of comparison operators,
+				// need to reverse the sense of the op
+				switch (op)
+				{
+					case TOK.TOKlt:		op = TOK.TOKgt;	break;
+					case TOK.TOKgt:		op = TOK.TOKlt;	break;
+					case TOK.TOKle:		op = TOK.TOKge;	break;
+					case TOK.TOKge:		op = TOK.TOKle;	break;
+
+					// Floating point compares
+					case TOK.TOKule:	op = TOK.TOKuge; break;
+					case TOK.TOKul:		op = TOK.TOKug;	 break;
+					case TOK.TOKuge:	op = TOK.TOKule; break;
+					case TOK.TOKug:		op = TOK.TOKul;	 break;
+
+					// These are symmetric
+					case TOK.TOKunord:
+					case TOK.TOKlg:
+					case TOK.TOKleg:
+					case TOK.TOKue:
+						break;
+				}
+
+				return e;
+			}
+		}
+
+version (DMDV2) {
+		// Try alias this on first operand
+		if (ad1 && ad1.aliasthis)
+		{
+			/* Rewrite (e1 op e2) as:
+			 *	(e1.aliasthis op e2)
+			 */
+			Expression e1 = new DotIdExp(loc, this.e1, ad1.aliasthis.ident);
+			Expression e = copy();
+			(cast(BinExp)e).e1 = e1;
+			e = e.semantic(sc);
+			return e;
+		}
+
+		// Try alias this on second operand
+		if (ad2 && ad2.aliasthis)
+		{
+			/* Rewrite (e1 op e2) as:
+			 *	(e1 op e2.aliasthis)
+			 */
+			Expression e2 = new DotIdExp(loc, this.e2, ad2.aliasthis.ident);
+			Expression e = copy();
+			(cast(BinExp)e).e2 = e2;
+			e = e.semantic(sc);
+			return e;
+		}
+}
+		return null;
+	}
+
+    elem* 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;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BoolExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,54 @@
+module dmd.BoolExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.TOK;
+
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class BoolExp : UnaExp
+{
+	this(Loc loc, Expression e, Type t)
+	{
+		super(loc, TOK.init, 0, e);
+		type = t;
+	}
+
+	Expression semantic(Scope sc)
+	{
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		e1 = e1.checkToBoolean();
+		type = Type.tboolean;
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	int isBit()
+	{
+		return true;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e1 = this.e1.toElem(irs);
+		return el_una(OPbool,type.totym(),e1);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/BreakStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,138 @@
+module dmd.BreakStatement;
+
+import dmd.Statement;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.FuncDeclaration;
+import dmd.LabelStatement;
+import dmd.ReturnStatement;
+import dmd.IntegerExp;
+
+import dmd.backend.Util;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.BC;
+
+class BreakStatement : Statement
+{
+    Identifier ident;
+
+    this(Loc loc, Identifier ident)
+	{
+		super(loc);
+		this.ident = ident;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("BreakStatement::semantic()\n");
+		// If:
+		//	break Identifier;
+		if (ident)
+		{
+			Scope scx;
+			FuncDeclaration thisfunc = sc.func;
+
+			for (scx = sc; scx; scx = scx.enclosing)
+			{
+				LabelStatement ls;
+
+				if (scx.func != thisfunc)	// if in enclosing function
+				{
+					if (sc.fes)		// if this is the body of a foreach
+					{
+						/* Post this statement to the fes, and replace
+						 * it with a return value that caller will put into
+						 * a switch. Caller will figure out where the break
+						 * label actually is.
+						 * Case numbers start with 2, not 0, as 0 is continue
+						 * and 1 is break.
+						 */
+						Statement s;
+						sc.fes.cases.push(cast(void*)this);
+						s = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1));
+						return s;
+					}
+					break;			// can't break to it
+				}
+
+				ls = scx.slabel;
+				if (ls && ls.ident == ident)
+				{
+					Statement s = ls.statement;
+
+					if (!s.hasBreak())
+						error("label '%s' has no break", ident.toChars());
+					if (ls.tf != sc.tf)
+						error("cannot break out of finally block");
+					return this;
+				}
+			}
+			error("enclosing label '%s' for break not found", ident.toChars());
+		}
+		else if (!sc.sbreak)
+		{
+			if (sc.fes)
+			{   
+				Statement s;
+
+				// Replace break; with return 1;
+				s = new ReturnStatement(Loc(0), new IntegerExp(1));
+				return s;
+			}
+			error("break is not inside a loop or switch");
+		}
+		return this;
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		//printf("BreakStatement::blockExit(%p) = x%x\n", this, ident ? BEgoto : BEbreak);
+		return ident ? BE.BEgoto : BE.BEbreak;
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    void toIR(IRState* irs)
+	{
+		block* bbreak;
+		block* b;
+		Blockx* blx = irs.blx;
+
+		bbreak = irs.getBreakBlock(ident);
+		assert(bbreak);
+		b = blx.curblock;
+		incUsage(irs, loc);
+
+		// Adjust exception handler scope index if in different try blocks
+		if (b.Btry != bbreak.Btry)
+		{
+			//setScopeIndex(blx, b, bbreak.Btry ? bbreak.Btry.Bscope_index : -1);
+		}
+
+		/* Nothing more than a 'goto' to the current break destination
+		 */
+		list_append(&b.Bsucc, bbreak);
+		block_next(blx, BCgoto, null);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CSX.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,15 @@
+module dmd.CSX;
+
+enum CSX
+{
+	CSXthis_ctor = 1,	// called this()
+	CSXsuper_ctor = 2,	// called super()
+	CSXthis	= 4,	// referenced this
+	CSXsuper = 8,	// referenced super
+	CSXlabel = 0x10,	// seen a label
+	CSXreturn = 0x20,	// seen a return statement
+	CSXany_ctor = 0x40,	// either this() or super() was called
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(CSX));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CallExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1056 @@
+module dmd.CallExp;
+
+import dmd.Expression;
+import dmd.WANT;
+import dmd.BUILTIN;
+import dmd.TypeFunction;
+import dmd.ScopeDsymbol;
+import dmd.CastExp;
+import dmd.GlobalExpressions;
+import dmd.TypePointer;
+import dmd.ThisExp;
+import dmd.OverExp;
+import dmd.Dsymbol;
+import dmd.CSX;
+import dmd.AggregateDeclaration;
+import dmd.TypeDelegate;
+import dmd.ClassDeclaration;
+import dmd.DsymbolExp;
+import dmd.DotExp;
+import dmd.TemplateExp;
+import dmd.TypeStruct;
+import dmd.TypeClass;
+import dmd.Identifier;
+import dmd.Lexer;
+import dmd.VarDeclaration;
+import dmd.DeclarationExp;
+import dmd.CtorDeclaration;
+import dmd.PtrExp;
+import dmd.TemplateDeclaration;
+import dmd.StructLiteralExp;
+import dmd.StructDeclaration;
+import dmd.DotTemplateExp;
+import dmd.CommaExp;
+import dmd.AggregateDeclaration;
+import dmd.FuncDeclaration;
+import dmd.Type;
+import dmd.ScopeExp;
+import dmd.VarExp;
+import dmd.STC;
+import dmd.LINK;
+import dmd.Global;
+import dmd.DotTemplateInstanceExp;
+import dmd.TemplateInstance;
+import dmd.DelegateExp;
+import dmd.IdentifierExp;
+import dmd.DotVarExp;
+import dmd.DotIdExp;
+import dmd.TY;
+import dmd.Id;
+import dmd.TypeAArray;
+import dmd.RemoveExp;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.PREC;
+import dmd.expression.Util;
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.codegen.Util;
+
+class CallExp : UnaExp
+{
+	Expressions arguments;
+
+	this(Loc loc, Expression e, Expressions exps)
+	{
+		super(loc, TOK.TOKcall, CallExp.sizeof, e);
+		this.arguments = exps;
+	}
+
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKcall, CallExp.sizeof, e);
+	}
+
+	this(Loc loc, Expression e, Expression earg1)
+	{
+		super(loc, TOK.TOKcall, CallExp.sizeof, e);
+		
+		Expressions arguments = new Expressions();
+		arguments.setDim(1);
+		arguments.data[0] = cast(void*)earg1;
+
+		this.arguments = arguments;
+	}
+
+	this(Loc loc, Expression e, Expression earg1, Expression earg2)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e);
+	}
+
+	Expression syntaxCopy()
+	{
+		return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments));
+	}
+
+	Expression semantic(Scope sc)
+	{
+		TypeFunction tf;
+		FuncDeclaration f;
+		int i;
+		Type t1;
+		int istemp;
+		Objects targsi;	// initial list of template arguments
+		TemplateInstance tierror;
+
+version (LOGSEMANTIC) {
+		printf("CallExp.semantic() %s\n", toChars());
+}
+		if (type)
+			return this;		// semantic() already run
+
+static if (false) {
+		if (arguments && arguments.dim)
+		{
+			Expression earg = cast(Expression)arguments.data[0];
+			earg.print();
+			if (earg.type) earg.type.print();
+		}
+}
+
+		if (e1.op == TOK.TOKdelegate)
+		{	
+			DelegateExp de = cast(DelegateExp)e1;
+
+			e1 = new DotVarExp(de.loc, de.e1, de.func);
+			return semantic(sc);
+		}
+
+		/* Transform:
+		 *	array.id(args) into .id(array,args)
+		 *	aa.remove(arg) into delete aa[arg]
+		 */
+		if (e1.op == TOK.TOKdot)
+		{
+			// BUG: we should handle array.a.b.c.e(args) too
+
+			DotIdExp dotid = cast(DotIdExp)(e1);
+			dotid.e1 = dotid.e1.semantic(sc);
+			assert(dotid.e1);
+			if (dotid.e1.type)
+			{
+				TY e1ty = dotid.e1.type.toBasetype().ty;
+				if (e1ty == TY.Taarray && dotid.ident == Id.remove)
+				{
+					if (!arguments || arguments.dim != 1)
+					{  
+						error("expected key as argument to aa.remove()");
+						goto Lagain;
+					}
+					Expression key = cast(Expression)arguments.data[0];
+					key = key.semantic(sc);
+					key = resolveProperties(sc, key);
+					key.rvalue();
+
+					TypeAArray taa = cast(TypeAArray)dotid.e1.type.toBasetype();
+					key = key.implicitCastTo(sc, taa.index);
+
+					return new RemoveExp(loc, dotid.e1, key);
+				}
+				else if (e1ty == TY.Tarray || e1ty == TY.Tsarray || e1ty == TY.Taarray)
+				{
+					if (!arguments)
+						arguments = new Expressions();
+					arguments.shift(cast(void*)dotid.e1);
+version (DMDV2) {
+					e1 = new DotIdExp(dotid.loc, new IdentifierExp(dotid.loc, Id.empty), dotid.ident);
+} else {
+					e1 = new IdentifierExp(dotid.loc, dotid.ident);
+}
+				}
+			}
+		}
+
+static if (true) {
+		/* This recognizes:
+		 *	foo!(tiargs)(funcargs)
+		 */
+		if (e1.op == TOK.TOKimport && !e1.type)
+		{	
+			ScopeExp se = cast(ScopeExp)e1;
+			TemplateInstance ti = se.sds.isTemplateInstance();
+			if (ti && !ti.semanticRun)
+			{
+				/* Attempt to instantiate ti. If that works, go with it.
+				 * If not, go with partial explicit specialization.
+				 */
+				ti.semanticTiargs(sc);
+				uint errors = global.errors;
+				global.gag++;
+				ti.semantic(sc);
+				global.gag--;
+				if (errors != global.errors)
+				{
+					/* Didn't work, go with partial explicit specialization
+					 */
+					global.errors = errors;
+					targsi = ti.tiargs;
+					tierror = ti;			// for error reporting
+					e1 = new IdentifierExp(loc, ti.name);
+				}
+			}
+		}
+
+		/* This recognizes:
+		 *	expr.foo!(tiargs)(funcargs)
+		 */
+		if (e1.op == TOK.TOKdotti && !e1.type)
+		{	
+			DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1;
+			TemplateInstance ti = se.ti;
+			if (!ti.semanticRun)
+			{
+				/* Attempt to instantiate ti. If that works, go with it.
+				 * If not, go with partial explicit specialization.
+				 */
+				ti.semanticTiargs(sc);
+				Expression etmp = e1.trySemantic(sc);
+				if (etmp)
+					e1 = etmp;	// it worked
+				else		// didn't work
+				{
+					targsi = ti.tiargs;
+					tierror = ti;		// for error reporting
+					e1 = new DotIdExp(loc, se.e1, ti.name);
+				}
+			}
+		}
+}
+
+		istemp = 0;
+	Lagain:
+		//printf("Lagain: %s\n", toChars());
+		f = null;
+		if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper)
+		{
+			// semantic() run later for these
+		}
+		else
+		{
+			UnaExp.semantic(sc);
+
+			/* Look for e1 being a lazy parameter
+			 */
+			if (e1.op == TOK.TOKvar)
+			{   
+				VarExp ve = cast(VarExp)e1;
+
+				if (ve.var.storage_class & STC.STClazy)
+				{
+					TypeFunction tff = new TypeFunction(null, ve.var.type, 0, LINK.LINKd);
+					TypeDelegate t = new TypeDelegate(tff);
+					ve.type = t.semantic(loc, sc);
+				}
+			}
+
+			if (e1.op == TOK.TOKimport)
+			{   
+				// Perhaps this should be moved to ScopeExp.semantic()
+				ScopeExp se = cast(ScopeExp)e1;
+				e1 = new DsymbolExp(loc, se.sds);
+				e1 = e1.semantic(sc);
+			}
+///static if (true) {	// patch for #540 by Oskar Linde
+			else if (e1.op == TOK.TOKdotexp)
+			{
+				DotExp de = cast(DotExp)e1;
+
+				if (de.e2.op == TOK.TOKimport)
+				{   
+					// This should *really* be moved to ScopeExp.semantic()
+					ScopeExp se = cast(ScopeExp)de.e2;
+					de.e2 = new DsymbolExp(loc, se.sds);
+					de.e2 = de.e2.semantic(sc);
+				}
+
+				if (de.e2.op == TOK.TOKtemplate)
+				{   
+					TemplateExp te = cast(TemplateExp)de.e2;
+					e1 = new DotTemplateExp(loc,de.e1,te.td);
+				}
+			}
+///}
+		}
+
+		if (e1.op == TOK.TOKcomma)
+		{
+			CommaExp ce = cast(CommaExp)e1;
+
+			e1 = ce.e2;
+			e1.type = ce.type;
+			ce.e2 = this;
+			ce.type = null;
+			return ce.semantic(sc);
+		}
+
+		t1 = null;
+		if (e1.type)
+		t1 = e1.type.toBasetype();
+
+		// Check for call operator overload
+		if (t1)
+		{	
+			AggregateDeclaration ad;
+
+			if (t1.ty == TY.Tstruct)
+			{
+				ad = (cast(TypeStruct)t1).sym;
+version (DMDV2) {
+				// First look for constructor
+				if (ad.ctor && arguments && arguments.dim)
+				{
+					// Create variable that will get constructed
+					Identifier idtmp = Lexer.uniqueId("__ctmp");
+					VarDeclaration tmp = new VarDeclaration(loc, t1, idtmp, null);
+					Expression av = new DeclarationExp(loc, tmp);
+					av = new CommaExp(loc, av, new VarExp(loc, tmp));
+
+					Expression e;
+					CtorDeclaration cf = ad.ctor.isCtorDeclaration();
+					if (cf)
+						e = new DotVarExp(loc, av, cf, 1);
+					else
+					{   
+						TemplateDeclaration td = ad.ctor.isTemplateDeclaration();
+						assert(td);
+						e = new DotTemplateExp(loc, av, td);
+					}
+					e = new CallExp(loc, e, arguments);
+			version (STRUCTTHISREF) {
+			} else {
+					/* Constructors return a pointer to the instance
+					 */
+					e = new PtrExp(loc, e);
+			}
+					e = e.semantic(sc);
+					return e;
+				}
+}
+				// No constructor, look for overload of opCall
+				if (search_function(ad, Id.call))
+					goto L1;	// overload of opCall, therefore it's a call
+
+				if (e1.op != TOK.TOKtype)
+					error("%s %s does not overload ()", ad.kind(), ad.toChars());
+				
+				/* It's a struct literal
+				 */
+				Expression e = new StructLiteralExp(loc, cast(StructDeclaration)ad, arguments);
+				e = e.semantic(sc);
+				e.type = e1.type;		// in case e1.type was a typedef
+				return e;
+			}
+			else if (t1.ty == TY.Tclass)
+			{
+				ad = (cast(TypeClass)t1).sym;
+				goto L1;
+			L1:
+				// Rewrite as e1.call(arguments)
+				Expression e = new DotIdExp(loc, e1, Id.call);
+				e = new CallExp(loc, e, arguments);
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+
+		arrayExpressionSemantic(arguments, sc);
+		preFunctionArguments(loc, sc, arguments);
+
+		if (e1.op == TOK.TOKdotvar && t1.ty == TY.Tfunction ||
+			e1.op == TOK.TOKdottd)
+		{
+			DotVarExp dve;
+			DotTemplateExp dte;
+			AggregateDeclaration ad;
+			UnaExp ue = cast(UnaExp)e1;
+
+			if (e1.op == TOK.TOKdotvar)
+			{   
+				// Do overload resolution
+				dve = cast(DotVarExp)e1;
+
+				f = dve.var.isFuncDeclaration();
+				assert(f);
+				f = f.overloadResolve(loc, ue.e1, arguments);
+
+				ad = f.toParent().isAggregateDeclaration();
+			}
+			else
+			{   
+				dte = cast(DotTemplateExp)e1;
+				TemplateDeclaration td = dte.td;
+				assert(td);
+
+				if (!arguments)
+					// Should fix deduceFunctionTemplate() so it works on null argument
+					arguments = new Expressions();
+
+				f = td.deduceFunctionTemplate(sc, loc, targsi, ue.e1, arguments);
+				if (!f)
+				{	
+					type = Type.terror;
+					return this;
+				}
+				ad = td.toParent().isAggregateDeclaration();
+			}
+
+			if (f.needThis())
+			{
+				ue.e1 = getRightThis(loc, sc, ad, ue.e1, f);
+			}
+
+			/* Cannot call public functions from inside invariant
+			 * (because then the invariant would have infinite recursion)
+			 */
+			if (sc.func && sc.func.isInvariantDeclaration() &&
+				ue.e1.op == TOK.TOKthis && f.addPostInvariant())
+			{
+				error("cannot call public/export function %s from invariant", f.toChars());
+			}
+
+			checkDeprecated(sc, f);
+	version (DMDV2) {
+			checkPurity(sc, f);
+	}
+			accessCheck(loc, sc, ue.e1, f);
+			if (!f.needThis())
+			{
+				VarExp ve = new VarExp(loc, f);
+				e1 = new CommaExp(loc, ue.e1, ve);
+				e1.type = f.type;
+			}
+			else
+			{
+				if (e1.op == TOK.TOKdotvar)		
+					dve.var = f;
+				else
+					e1 = new DotVarExp(loc, dte.e1, f);
+
+				e1.type = f.type;
+static if (false) {
+				printf("ue.e1 = %s\n", ue.e1.toChars());
+				printf("f = %s\n", f.toChars());
+				printf("t = %s\n", t.toChars());
+				printf("e1 = %s\n", e1.toChars());
+				printf("e1.type = %s\n", e1.type.toChars());
+}
+				// Const member function can take const/immutable/mutable this
+				if (!(f.type.isConst()))
+				{
+					// Check for const/immutable compatibility
+					Type tthis = ue.e1.type.toBasetype();
+					if (tthis.ty == TY.Tpointer)
+						tthis = tthis.nextOf().toBasetype();
+
+	static if (false) {	// this checking should have been already done
+					if (f.type.isInvariant())
+					{
+						if (tthis.mod != MOD.MODinvariant)
+							error("%s can only be called with an immutable object", e1.toChars());
+					}
+					else if (f.type.isShared())
+					{
+						if (tthis.mod != MOD.MODinvariant && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst))
+							error("shared %s can only be called with a shared or immutable object", e1.toChars());
+					}
+					else
+					{
+						if (tthis.mod != MOD.MODundefined)
+						{	
+							//printf("mod = %x\n", tthis.mod);
+							error("%s can only be called with a mutable object, not %s", e1.toChars(), tthis.toChars());
+						}
+					}
+	}
+					/* Cannot call mutable method on a final struct
+					 */
+					if (tthis.ty == TY.Tstruct &&
+						ue.e1.op == TOK.TOKvar)
+					{
+						VarExp v = cast(VarExp)ue.e1;
+						if (v.var.storage_class & STC.STCfinal)
+							error("cannot call mutable method on final struct");
+					}
+				}
+
+				// See if we need to adjust the 'this' pointer
+				AggregateDeclaration add = f.isThis();
+				ClassDeclaration cd = ue.e1.type.isClassHandle();
+				if (add && cd && add.isClassDeclaration() && add != cd && ue.e1.op != TOK.TOKsuper)
+				{
+					ue.e1 = ue.e1.castTo(sc, add.type); //new CastExp(loc, ue.e1, add.type);
+					ue.e1 = ue.e1.semantic(sc);
+				}
+			}
+			t1 = e1.type;
+		}
+		else if (e1.op == TOK.TOKsuper)
+		{
+			// Base class constructor call
+			ClassDeclaration cd = null;
+
+			if (sc.func)
+				cd = sc.func.toParent().isClassDeclaration();
+			if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
+			{
+				error("super class constructor call must be in a constructor");
+				type = Type.terror;
+				return this;
+			}
+			else
+			{
+				if (!cd.baseClass.ctor)
+				{	
+					error("no super class constructor for %s", cd.baseClass.toChars());
+					type = Type.terror;
+					return this;
+				}
+				else
+				{
+					if (!sc.intypeof)
+					{
+static if (false) {
+						if (sc.callSuper & (CSX.CSXthis | CSX.CSXsuper))
+							error("reference to this before super()");
+}
+						if (sc.noctor || sc.callSuper & CSX.CSXlabel)
+							error("constructor calls not allowed in loops or after labels");
+						if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
+							error("multiple constructor calls");
+						sc.callSuper |= CSX.CSXany_ctor | CSX.CSXsuper_ctor;
+					}
+
+					f = resolveFuncCall(sc, loc, cd.baseClass.ctor, null, null, arguments, 0);
+					checkDeprecated(sc, f);
+version (DMDV2) {
+					checkPurity(sc, f);
+}
+					e1 = new DotVarExp(e1.loc, e1, f);
+					e1 = e1.semantic(sc);
+					t1 = e1.type;
+				}
+			}
+		}
+		else if (e1.op == TOK.TOKthis)
+		{
+			// same class constructor call
+			AggregateDeclaration cd = null;
+
+			if (sc.func)
+				cd = sc.func.toParent().isAggregateDeclaration();
+			if (!cd || !sc.func.isCtorDeclaration())
+			{
+				error("constructor call must be in a constructor");
+				type = Type.terror;
+				return this;
+			}
+			else
+			{
+				if (!sc.intypeof)
+				{
+static if (false) {
+					if (sc.callSuper & (CSXthis | CSXsuper))
+						error("reference to this before super()");
+}
+					if (sc.noctor || sc.callSuper & CSX.CSXlabel)
+						error("constructor calls not allowed in loops or after labels");
+					if (sc.callSuper & (CSX.CSXsuper_ctor | CSX.CSXthis_ctor))
+						error("multiple constructor calls");
+					sc.callSuper |= CSX.CSXany_ctor | CSX.CSXthis_ctor;
+				}
+
+				f = resolveFuncCall(sc, loc, cd.ctor, null, null, arguments, 0);
+				checkDeprecated(sc, f);
+version (DMDV2) {
+				checkPurity(sc, f);
+}
+				e1 = new DotVarExp(e1.loc, e1, f);
+				e1 = e1.semantic(sc);
+				t1 = e1.type;
+
+				// BUG: this should really be done by checking the static
+				// call graph
+				if (f == sc.func)
+					error("cyclic constructor call");
+			}
+		}
+		else if (e1.op == TOK.TOKoverloadset)
+		{
+			OverExp eo = cast(OverExp)e1;
+			FuncDeclaration ff = null;
+			for (int j = 0; j < eo.vars.a.dim; j++)
+			{   
+				Dsymbol s = cast(Dsymbol)eo.vars.a.data[j];
+				FuncDeclaration f2 = s.isFuncDeclaration();
+				if (f2)
+				{
+					f2 = f2.overloadResolve(loc, null, arguments, 1);
+				}
+				else
+				{	
+					TemplateDeclaration td = s.isTemplateDeclaration();
+					assert(td);
+					f2 = td.deduceFunctionTemplate(sc, loc, targsi, null, arguments, 1);
+				}
+				if (f2)
+				{	
+					if (ff)
+						/* Error if match in more than one overload set,
+						 * even if one is a 'better' match than the other.
+						 */
+						ScopeDsymbol.multiplyDefined(loc, ff, f2);
+					else
+						ff = f2;
+				}
+			}
+			if (!ff)
+			{   
+				/* No overload matches, just set ff and rely on error
+				 * message being generated later.
+				 */
+				ff = cast(FuncDeclaration)eo.vars.a.data[0];
+			}
+			e1 = new VarExp(loc, ff);
+			goto Lagain;
+		}
+		else if (!t1)
+		{
+			error("function expected before (), not '%s'", e1.toChars());
+			type = Type.terror;
+			return this;
+		}
+		else if (t1.ty != TY.Tfunction)
+		{
+			if (t1.ty == TY.Tdelegate)
+			{   
+				TypeDelegate td = cast(TypeDelegate)t1;
+				assert(td.next.ty == TY.Tfunction);
+				tf = cast(TypeFunction)(td.next);
+				if (sc.func && sc.func.isPure() && !tf.ispure)
+				{
+					error("pure function '%s' cannot call impure delegate '%s'", sc.func.toChars(), e1.toChars());
+				}
+				goto Lcheckargs;
+			}
+			else if (t1.ty == TY.Tpointer && (cast(TypePointer)t1).next.ty == TY.Tfunction)
+			{   
+				Expression e = new PtrExp(loc, e1);
+				t1 = (cast(TypePointer)t1).next;
+				if (sc.func && sc.func.isPure() && !(cast(TypeFunction)t1).ispure)
+				{
+					error("pure function '%s' cannot call impure function pointer '%s'", sc.func.toChars(), e1.toChars());
+				}
+				e.type = t1;
+				e1 = e;
+			}
+			else if (e1.op == TOK.TOKtemplate)
+			{
+				TemplateExp te = cast(TemplateExp)e1;
+				f = te.td.deduceFunctionTemplate(sc, loc, targsi, null, arguments);
+				if (!f)
+				{	
+					if (tierror)
+						tierror.error("errors instantiating template");	// give better error message
+					type = Type.terror;
+					return this;
+				}
+				if (f.needThis() && hasThis(sc))
+				{
+					// Supply an implicit 'this', as in
+					//	  this.ident
+
+					e1 = new DotTemplateExp(loc, (new ThisExp(loc)).semantic(sc), te.td);
+					goto Lagain;
+				}
+
+				e1 = new VarExp(loc, f);
+				goto Lagain;
+			}
+			else
+			{   
+				error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars());
+				type = Type.terror;
+				return this;
+			}
+		}
+		else if (e1.op == TOK.TOKvar)
+		{
+			// Do overload resolution
+			VarExp ve = cast(VarExp)e1;
+
+			f = ve.var.isFuncDeclaration();
+			assert(f);
+
+			if (ve.hasOverloads)
+				f = f.overloadResolve(loc, null, arguments);
+
+			checkDeprecated(sc, f);
+version (DMDV2) {
+			checkPurity(sc, f);
+}
+
+			if (f.needThis() && hasThis(sc))
+			{
+				// Supply an implicit 'this', as in
+				//	  this.ident
+
+				e1 = new DotVarExp(loc, new ThisExp(loc), f);
+				goto Lagain;
+			}
+
+			accessCheck(loc, sc, null, f);
+
+			ve.var = f;
+		//	ve.hasOverloads = 0;
+			ve.type = f.type;
+			t1 = f.type;
+		}
+		assert(t1.ty == TY.Tfunction);
+		tf = cast(TypeFunction)t1;
+
+	Lcheckargs:
+		assert(tf.ty == TY.Tfunction);
+		type = tf.next;
+
+		if (!arguments)
+			arguments = new Expressions();
+
+		functionArguments(loc, sc, tf, arguments);
+
+		if (!type)
+		{
+			error("forward reference to inferred return type of function call %s", toChars());
+			type = Type.terror;
+		}
+
+		if (f && f.tintro)
+		{
+			Type t = type;
+			int offset = 0;
+			TypeFunction tff = cast(TypeFunction)f.tintro;
+
+			if (tff.next.isBaseOf(t, &offset) && offset)
+			{
+				type = tff.next;
+				return castTo(sc, t);
+			}
+		}
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("CallExp::optimize(result = %d) %s\n", result, toChars());
+		Expression e = this;
+
+		// Optimize parameters
+		if (arguments)
+		{
+			for (size_t i = 0; i < arguments.dim; i++)
+			{   
+				Expression ee = cast(Expression)arguments.data[i];
+
+				ee = ee.optimize(WANT.WANTvalue);
+				arguments.data[i] = cast(void*)ee;
+			}
+		}
+
+		e1 = e1.optimize(result);
+		if (e1.op == TOK.TOKvar)
+		{
+			FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration();
+			if (fd)
+			{
+				BUILTIN b = fd.isBuiltin();
+				if (b)
+				{
+					e = eval_builtin(b, arguments);
+					if (!e)			// failed
+						e = this;		// evaluate at runtime
+				}
+				else if (result & WANT.WANTinterpret)
+				{
+					Expression eresult = fd.interpret(null, arguments);
+					if (eresult && eresult !is EXP_VOID_INTERPRET)
+						e = eresult;
+					else
+						error("cannot evaluate %s at compile time", toChars());
+				}
+			}
+		}
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+version (DMDV2) {
+		if (flag != 2)
+			return true;
+
+		if (e1.checkSideEffect(2))
+			return true;
+
+		/* If any of the arguments have side effects, this expression does
+		 */
+		for (size_t i = 0; i < arguments.dim; i++)
+		{   
+			Expression e = cast(Expression)arguments.data[i];
+
+			if (e.checkSideEffect(2))
+				return true;
+		}
+
+		/* If calling a function or delegate that is typed as pure,
+		 * then this expression has no side effects.
+		 */
+		Type t = e1.type.toBasetype();
+		if (t.ty == TY.Tfunction && (cast(TypeFunction)t).ispure)
+			return false;
+		if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).ispure)
+			return false;
+}
+		return true;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		int i;
+		expToCBuffer(buf, hgs, e1, precedence[op]);
+		buf.writeByte('(');
+		argsToCBuffer(buf, arguments, hgs);
+		buf.writeByte(')');
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	elem* 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 == TOK.TOKdotvar && t1.ty != TY.Tdelegate)
+		{	
+			DotVarExp dve = cast(DotVarExp)e1;
+
+			fd = dve.var.isFuncDeclaration();
+			Expression ex = dve.e1;
+			while (1)
+			{
+				switch (ex.op)
+				{
+				case TOK.TOKsuper:		// super.member() calls directly
+				case TOK.TOKdottype:	// type.member() calls directly
+					directcall = 1;
+					break;
+
+				case TOK.TOKcast:
+					ex = (cast(CastExp)ex).e1;
+					continue;
+
+				default:
+					//ex.dump(0);
+					break;
+				}
+				break;
+			}
+			ec = dve.e1.toElem(irs);
+			ectype = dve.e1.type.toBasetype();
+		}
+		else if (e1.op == TOK.TOKvar)
+		{
+			fd = (cast(VarExp)e1).var.isFuncDeclaration();
+
+			if (fd && fd.ident == Id.alloca && !fd.fbody && fd.linkage == LINK.LINKc && arguments && arguments.dim == 1)
+			{   
+				Expression arg = cast(Expression)arguments.data[0];
+				arg = arg.optimize(WANT.WANTvalue);
+				if (arg.isConst() && arg.type.isintegral())
+				{	
+					long 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(TYM.TYarray, tschar);
+						t.Tdim = cast(uint)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;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+	
+version (DMDV2) {
+	int isLvalue()
+	{
+		//    if (type.toBasetype().ty == Tstruct)
+		//	return 1;
+		Type tb = e1.type.toBasetype();
+		if (tb.ty == Tfunction && (cast(TypeFunction)tb).isref)
+			return 1;		// function returns a reference
+		return 0;
+	}
+}
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		if (isLvalue())
+			return this;
+		return Expression.toLvalue(sc, e);
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		//printf("CallExp::canThrow() %s\n", toChars());
+		if (e1.canThrow())
+			return true;
+
+		/* If any of the arguments can throw, then this expression can throw
+		 */
+		for (size_t i = 0; i < arguments.dim; i++)
+		{   
+			Expression e = cast(Expression)arguments.data[i];
+
+			if (e && e.canThrow())
+				return true;
+		}
+
+		if (global.errors && !e1.type)
+			return false;			// error recovery
+
+		/* If calling a function or delegate that is typed as nothrow,
+		 * then this expression cannot throw.
+		 * Note that pure functions can throw.
+		 */
+		Type t = e1.type.toBasetype();
+		if (t.ty == TY.Tfunction && (cast(TypeFunction)t).isnothrow)
+			return false;
+		if (t.ty == TY.Tdelegate && (cast(TypeFunction)(cast(TypeDelegate)t).next).isnothrow)
+			return false;
+
+		return true;
+	}
+}
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics) + arrayInlineCost(ics, arguments);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		CallExp ce = cast(CallExp)copy();
+		ce.e1 = e1.doInline(ids);
+		ce.arguments = arrayExpressiondoInline(arguments, ids);
+		return ce;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		Expression e = this;
+
+		//printf("CallExp.inlineScan()\n");
+		e1 = e1.inlineScan(iss);
+		arrayInlineScan(iss, arguments);
+
+		if (e1.op == TOKvar)
+		{
+			VarExp ve = cast(VarExp)e1;
+			FuncDeclaration fd = ve.var.isFuncDeclaration();
+
+			if (fd && fd != iss.fd && fd.canInline(0))
+			{
+				e = fd.doInline(iss, null, arguments);
+			}
+		}
+		else if (e1.op == TOKdotvar)
+		{
+			DotVarExp dve = cast(DotVarExp)e1;
+			FuncDeclaration fd = dve.var.isFuncDeclaration();
+
+			if (fd && fd != iss.fd && fd.canInline(1))
+			{
+				if (dve.e1.op == TOKcall &&
+					dve.e1.type.toBasetype().ty == Tstruct)
+				{
+					/* To create ethis, we'll need to take the address
+					 * of dve.e1, but this won't work if dve.e1 is
+					 * a function call.
+					 */
+					;
+				}
+				else
+					e = fd.doInline(iss, dve.e1, arguments);
+			}
+		}
+
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CaseRangeStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,37 @@
+module dmd.CaseRangeStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Statement;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+
+class CaseRangeStatement : Statement
+{
+    Expression first;
+    Expression last;
+    Statement statement;
+
+    this(Loc loc, Expression first, Expression last, Statement s)
+	{
+		assert(false);
+		super(loc);
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CaseStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,177 @@
+module dmd.CaseStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Statement;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.InlineScanState;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+import dmd.InterState;
+import dmd.BE;
+import dmd.SwitchStatement;
+import dmd.WANT;
+import dmd.TOK;
+import dmd.VarExp;
+import dmd.VarDeclaration;
+import dmd.Type;
+import dmd.TY;
+import dmd.IntegerExp;
+import dmd.GotoCaseStatement;
+
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.backend.BC;
+
+class CaseStatement : Statement
+{
+    Expression exp;
+    Statement statement;
+
+    int index = 0;			// which case it is (since we sort this)
+    block* cblock = null;	// back end: label for the block
+
+    this(Loc loc, Expression exp, Statement s)
+	{
+		super(loc);
+		
+		this.exp = exp;
+		this.statement = s;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		SwitchStatement sw = sc.sw;
+
+		//printf("CaseStatement.semantic() %s\n", toChars());
+		exp = exp.semantic(sc);
+		if (sw)
+		{
+			exp = exp.implicitCastTo(sc, sw.condition.type);
+			exp = exp.optimize(WANTvalue | WANTinterpret);
+
+			/* This is where variables are allowed as case expressions.
+			 */
+			if (exp.op == TOKvar)
+			{   VarExp ve = cast(VarExp)exp;
+				VarDeclaration v = ve.var.isVarDeclaration();
+				Type t = exp.type.toBasetype();
+				if (v && (t.isintegral() || t.ty == Tclass))
+				{
+					/* Flag that we need to do special code generation
+					 * for this, i.e. generate a sequence of if-then-else
+					 */
+					sw.hasVars = 1;
+					if (sw.isFinal)
+						error("case variables not allowed in final switch statements");
+					goto L1;
+				}
+			}
+
+			if (exp.op != TOKstring && exp.op != TOKint64)
+			{
+				error("case must be a string or an integral constant, not %s", exp.toChars());
+				exp = new IntegerExp(0);
+			}
+
+			L1:
+			for (int i = 0; i < sw.cases.dim; i++)
+			{
+				CaseStatement cs = cast(CaseStatement)sw.cases.data[i];
+
+				//printf("comparing '%s' with '%s'\n", exp.toChars(), cs.exp.toChars());
+				if (cs.exp.equals(exp))
+				{	
+					error("duplicate case %s in switch statement", exp.toChars());
+					break;
+				}
+			}
+
+			sw.cases.push(cast(void*)this);
+
+			// Resolve any goto case's with no exp to this case statement
+			for (int i = 0; i < sw.gotoCases.dim; i++)
+			{
+				GotoCaseStatement gcs = cast(GotoCaseStatement)sw.gotoCases.data[i];
+
+				if (!gcs.exp)
+				{
+					gcs.cs = this;
+					sw.gotoCases.remove(i);	// remove from array
+				}
+			}
+
+			if (sc.sw.tf !is sc.tf)
+				error("switch and case are in different finally blocks");
+		}
+		else
+			error("case not in switch statement");
+		statement = statement.semantic(sc);
+		return this;
+	}
+	
+    int compare(Object obj)
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		return statement.blockExit();
+	}
+	
+    bool comeFrom()
+	{
+		return true;
+	}
+	
+    Expression interpret(InterState *istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		//printf("CaseStatement.inlineScan()\n");
+		exp = exp.inlineScan(iss);
+		if (statement)
+			statement = statement.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState *irs)
+	{
+		Blockx* blx = irs.blx;
+		block* bcase = blx.curblock;
+		if (!cblock)
+			cblock = block_calloc(blx);
+		block_next(blx,BCgoto,cblock);
+		block* bsw = irs.getSwitchBlock();
+		if (bsw.BC == BCswitch)
+			list_append(&bsw.Bsucc,cblock);	// second entry in pair
+		list_append(&bcase.Bsucc,cblock);
+		if (blx.tryblock != bsw.Btry)
+			error("case cannot be in different try block level from switch");
+		incUsage(irs, loc);
+		if (statement)
+			statement.toIR(irs);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Cast.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,142 @@
+module dmd.Cast;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.Loc;
+import dmd.MATCH;
+import dmd.IntegerExp;
+import dmd.RealExp;
+import dmd.ComplexExp;
+import dmd.StructDeclaration;
+import dmd.ArrayTypes;
+import dmd.Dsymbol;
+import dmd.VarDeclaration;
+import dmd.StructLiteralExp;
+import dmd.Util;
+import dmd.TY;
+import dmd.TOK;
+import dmd.GlobalExpressions;
+
+import dmd.Complex;
+
+Expression expType(Type type, Expression e)
+{
+    if (type !is e.type)
+    {
+		e = e.copy();
+		e.type = type;
+    }
+    return e;
+}
+
+/* Also returns EXP_CANT_INTERPRET if cannot be computed.
+ *  to:	type to cast to
+ *  type: type to paint the result
+ */
+
+Expression Cast(Type type, Type to, Expression e1)
+{   
+	Expression e = EXP_CANT_INTERPRET;
+    Loc loc = e1.loc;
+
+    //printf("Cast(type = %s, to = %s, e1 = %s)\n", type.toChars(), to.toChars(), e1.toChars());
+    //printf("\te1.type = %s\n", e1.type.toChars());
+    if (e1.type.equals(type) && type.equals(to))
+		return e1;
+    if (e1.type.implicitConvTo(to) >= MATCH.MATCHconst || to.implicitConvTo(e1.type) >= MATCH.MATCHconst)
+		return expType(to, e1);
+
+    Type tb = to.toBasetype();
+    Type typeb = type.toBasetype();
+
+    /* Allow casting from one string type to another
+     */
+    if (e1.op == TOK.TOKstring)
+    {
+		if (tb.ty == TY.Tarray && typeb.ty == TY.Tarray &&
+			tb.nextOf().size() == typeb.nextOf().size())
+		{
+			return expType(to, e1);
+		}
+    }
+
+    if (e1.isConst() != 1)
+		return EXP_CANT_INTERPRET;
+
+    if (tb.ty == TY.Tbool)
+		e = new IntegerExp(loc, e1.toInteger() != 0, type);
+    else if (type.isintegral())
+    {
+		if (e1.type.isfloating())
+		{   
+			long result;
+			real r = e1.toReal();
+
+			switch (typeb.ty)
+			{
+				case TY.Tint8:	result = cast(byte)r;	break;
+				case TY.Tchar:
+				case TY.Tuns8:	result = cast(ubyte)r;	break;
+				case TY.Tint16:	result = cast(short)r;	break;
+				case TY.Twchar:
+				case TY.Tuns16:	result = cast(ushort)r;	break;
+				case TY.Tint32:	result = cast(int)r;	break;
+				case TY.Tdchar:
+				case TY.Tuns32:	result = cast(uint)r;	break;
+				case TY.Tint64:	result = cast(long)r;	break;
+				case TY.Tuns64:	result = cast(ulong)r;	break;
+			}
+
+			e = new IntegerExp(loc, result, type);
+		}
+		else if (type.isunsigned())
+			e = new IntegerExp(loc, e1.toUInteger(), type);
+		else
+			e = new IntegerExp(loc, e1.toInteger(), type);
+    }
+    else if (tb.isreal())
+    {
+		real value = e1.toReal();
+		e = new RealExp(loc, value, type);
+    }
+    else if (tb.isimaginary())
+    {   
+		real value = e1.toImaginary();
+		e = new RealExp(loc, value, type);
+    }
+    else if (tb.iscomplex())
+    {   
+		Complex!(real) value = e1.toComplex();
+		e = new ComplexExp(loc, value, type);
+    }
+    else if (tb.isscalar())
+		e = new IntegerExp(loc, e1.toInteger(), type);
+    else if (tb.ty == TY.Tvoid)
+		e = EXP_CANT_INTERPRET;
+    else if (tb.ty == TY.Tstruct && e1.op == TOK.TOKint64)
+    {	
+		// Struct = 0;
+		StructDeclaration sd = tb.toDsymbol(null).isStructDeclaration();
+		assert(sd);
+		Expressions elements = new Expressions;
+		for (size_t i = 0; i < sd.fields.dim; i++)
+		{   Dsymbol s = cast(Dsymbol)sd.fields.data[i];
+			VarDeclaration v = s.isVarDeclaration();
+			assert(v);
+
+			Expression exp = new IntegerExp(0);
+			exp = Cast(v.type, v.type, exp);
+			if (exp == EXP_CANT_INTERPRET)
+				return exp;
+			elements.push(cast(void*)exp);
+		}
+		e = new StructLiteralExp(loc, sd, elements);
+		e.type = type;
+    }
+    else
+    {
+		error(loc, "cannot cast %s to %s", e1.type.toChars(), type.toChars());
+		e = new IntegerExp(loc, 0, Type.tint32);
+    }
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CastExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1201 @@
+module dmd.CastExp;
+
+import dmd.Expression;
+import dmd.TY;
+import dmd.TypeStruct;
+import dmd.TypeExp;
+import dmd.DotIdExp;
+import dmd.CallExp;
+import dmd.Global;
+import dmd.Id;
+import dmd.Identifier;
+import dmd.BinExp;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.VarExp;
+import dmd.Token;
+import dmd.VarDeclaration;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.HdrGenState;
+import dmd.MOD;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.ClassDeclaration;
+
+import dmd.Optimize;
+import dmd.PREC;
+import dmd.Cast;
+
+import dmd.backend.Util;
+import dmd.expression.Util;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+import dmd.codegen.Util;
+import dmd.backend.RTLSYM;
+
+class CastExp : UnaExp
+{
+	// Possible to cast to one type while painting to another type
+	Type to;				// type to cast to
+	MOD mod;				// MODxxxxx
+
+	this(Loc loc, Expression e, Type t)
+	{
+		super(loc, TOK.TOKcast, CastExp.sizeof, e);
+		to = t;
+		this.mod = cast(MOD)~0;
+	}
+
+	this(Loc loc, Expression e, MOD mod)
+	{
+		super(loc, TOK.TOKcast, CastExp.sizeof, e);
+		to = null;
+		this.mod = mod;
+	}
+
+	Expression syntaxCopy()
+	{
+		return to ? new CastExp(loc, e1.syntaxCopy(), to.syntaxCopy())
+	      : new CastExp(loc, e1.syntaxCopy(), mod);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		BinExp b;
+		UnaExp u;
+
+version (LOGSEMANTIC) {
+		printf("CastExp.semantic('%s')\n", toChars());
+}
+
+		//static int x; assert(++x < 10);
+
+		if (type)
+			return this;
+		super.semantic(sc);
+		if (e1.type)		// if not a tuple
+		{
+		e1 = resolveProperties(sc, e1);
+
+		if (!to)
+		{
+			/* Handle cast(const) and cast(immutable), etc.
+			 */
+			to = e1.type.castMod(mod);
+		}
+		else
+			to = to.semantic(loc, sc);
+
+		if (!to.equals(e1.type))
+		{
+			e = op_overload(sc);
+			if (e)
+			{
+			return e.implicitCastTo(sc, to);
+			}
+		}
+
+		Type t1b = e1.type.toBasetype();
+		Type tob = to.toBasetype();
+		if (tob.ty == TY.Tstruct &&
+			!tob.equals(t1b) &&
+			(cast(TypeStruct)tob).sym.search(Loc(0), Id.call, 0)
+		   )
+		{
+			/* Look to replace:
+			 *	cast(S)t
+			 * with:
+			 *	S(t)
+			 */
+
+			// Rewrite as to.call(e1)
+			e = new TypeExp(loc, to);
+			e = new DotIdExp(loc, e, Id.call);
+			e = new CallExp(loc, e, e1);
+			e = e.semantic(sc);
+			return e;
+		}
+		}
+		else if (!to)
+		{	error("cannot cast tuple");
+		to = Type.terror;
+		}
+
+		if (global.params.safe && !sc.module_.safe && !sc.intypeof)
+		{	// Disallow unsafe casts
+			Type tob = to.toBasetype();
+			Type t1b = e1.type.toBasetype();
+			if (!t1b.isMutable() && tob.isMutable())
+			{   // Cast not mutable to mutable
+			  Lunsafe:
+				error("cast from %s to %s not allowed in safe mode", e1.type.toChars(), to.toChars());
+			}
+			else if (t1b.isShared() && !tob.isShared())
+				// Cast away shared
+				goto Lunsafe;
+			else if (tob.ty == TY.Tpointer)
+			{   if (t1b.ty != TY.Tpointer)
+				goto Lunsafe;
+				Type tobn = tob.nextOf().toBasetype();
+				Type t1bn = t1b.nextOf().toBasetype();
+
+				if (!t1bn.isMutable() && tobn.isMutable())
+					// Cast away pointer to not mutable
+					goto Lunsafe;
+
+				if (t1bn.isShared() && !tobn.isShared())
+					// Cast away pointer to shared
+					goto Lunsafe;
+
+				if (tobn.isTypeBasic() && tobn.size() < t1bn.size()) {
+					// Allow things like casting a long* to an int*
+					;
+				} else if (tobn.ty != TY.Tvoid) {
+					// Cast to a pointer other than void*
+					goto Lunsafe;
+				}
+			}
+
+			// BUG: Check for casting array types, such as void[] to int*[]
+		}
+
+		e = e1.castTo(sc, to);
+		return e;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+	static if (false) {
+		printf("CastExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		MATCH result = type.implicitConvTo(t);
+
+		if (result == MATCHnomatch)
+		{
+			if (t.isintegral() &&
+				e1.type.isintegral() &&
+				e1.implicitConvTo(t) != MATCHnomatch)
+				result = MATCHconvert;
+			else
+				result = Expression.implicitConvTo(t);
+		}
+		return result;
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("CastExp.optimize(result = %d) %s\n", result, toChars());
+		//printf("from %s to %s\n", type.toChars(), to.toChars());
+		//printf("from %s\n", type.toChars());
+		//printf("e1.type %s\n", e1.type.toChars());
+		//printf("type = %p\n", type);
+		assert(type);
+		TOK op1 = e1.op;
+
+		Expression e1old = e1;
+		e1 = e1.optimize(result);
+		e1 = fromConstInitializer(result, e1);
+
+		if (e1 == e1old &&
+		e1.op == TOK.TOKarrayliteral &&
+		type.toBasetype().ty == TY.Tpointer &&
+		e1.type.toBasetype().ty != TY.Tsarray)
+		{
+		// Casting this will result in the same expression, and
+		// infinite loop because of Expression.implicitCastTo()
+		return this;		// no change
+		}
+
+		if ((e1.op == TOK.TOKstring || e1.op == TOK.TOKarrayliteral) &&
+		(type.ty == TY.Tpointer || type.ty == TY.Tarray) &&
+		e1.type.nextOf().size() == type.nextOf().size()
+		   )
+		{
+		Expression e = e1.castTo(null, type);
+
+static if (false) {
+		printf(" returning1 %s\n", e.toChars());
+}
+		return e;
+		}
+
+		if (e1.op == TOK.TOKstructliteral &&
+		e1.type.implicitConvTo(type) >= MATCH.MATCHconst)
+		{
+		e1.type = type;
+static if (false) {
+		printf(" returning2 %s\n", e1.toChars());
+}
+		return e1;
+		}
+
+		/* The first test here is to prevent infinite loops
+		 */
+		if (op1 != TOK.TOKarrayliteral && e1.op == TOK.TOKarrayliteral)
+		return e1.castTo(null, to);
+		if (e1.op == TOK.TOKnull &&
+		(type.ty == TY.Tpointer || type.ty == TY.Tclass || type.ty == TY.Tarray))
+		{
+		e1.type = type;
+static if (false) {
+		printf(" returning3 %s\n", e1.toChars());
+}
+		return e1;
+		}
+
+		if (result & WANT.WANTflags && type.ty == TY.Tclass && e1.type.ty == TY.Tclass)
+		{
+		// See if we can remove an unnecessary cast
+		ClassDeclaration cdfrom;
+		ClassDeclaration cdto;
+		int offset;
+
+		cdfrom = e1.type.isClassHandle();
+		cdto   = type.isClassHandle();
+		if (cdto.isBaseOf(cdfrom, &offset) && offset == 0)
+		{
+			e1.type = type;
+static if (false) {
+			printf(" returning4 %s\n", e1.toChars());
+}
+			return e1;
+		}
+		}
+
+		// We can convert 'head const' to mutable
+		if (to.constOf().equals(e1.type.constOf()))
+	//    if (to.constConv(e1.type) >= MATCHconst)
+		{
+		e1.type = type;
+static if (false) {
+		printf(" returning5 %s\n", e1.toChars());
+}
+		return e1;
+		}
+
+		Expression e;
+
+		if (e1.isConst())
+		{
+		if (e1.op == TOK.TOKsymoff)
+		{
+			if (type.size() == e1.type.size() &&
+			type.toBasetype().ty != TY.Tsarray)
+			{
+			e1.type = type;
+			return e1;
+			}
+			return this;
+		}
+		if (to.toBasetype().ty == TY.Tvoid)
+			e = this;
+		else
+			e = Cast(type, to, e1);
+		}
+		else
+		e = this;
+static if (false) {
+		printf(" returning6 %s\n", e.toChars());
+}
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	void checkEscape()
+	{
+		Type tb = type.toBasetype();
+		if (tb.ty == TY.Tarray && e1.op == TOK.TOKvar && e1.type.toBasetype().ty ==TY.Tsarray)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			VarDeclaration v = ve.var.isVarDeclaration();
+			if (v)
+			{
+				if (!v.isDataseg() && !v.isParameter())
+					error("escaping reference to local %s", v.toChars());
+			}
+		}
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("cast(");
+	version (DMDV1) {
+		to.toCBuffer(buf, null, hgs);
+	} else {
+		if (to)
+			to.toCBuffer(buf, null, hgs);
+		else
+		{
+			switch (mod)
+			{   
+				case MODundefined:
+					break;
+				case MODconst:
+					buf.writestring(Token.tochars[TOKconst]);
+					break;
+				case MODinvariant:
+					buf.writestring(Token.tochars[TOKimmutable]);
+					break;
+				case MODshared:
+					buf.writestring(Token.tochars[TOKshared]);
+					break;
+				case MODshared | MODconst:
+					buf.writestring(Token.tochars[TOKshared]);
+					buf.writeByte(' ');
+					buf.writestring(Token.tochars[TOKconst]);
+					break;
+				default:
+					assert(0);
+			}
+		}
+	}
+		buf.writeByte(')');
+		expToCBuffer(buf, hgs, e1, precedence[op]);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+	
+	static int X(int fty, int tty) {
+		return ((fty) * TY.TMAX + (tty));
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		TY fty;
+		TY tty;
+		tym_t ftym;
+		tym_t ttym;
+		OPER eop;
+		Type t;
+		Type tfrom;
+
+static if (false) {
+		printf("CastExp::toElem()\n");
+		print();
+		printf("\tfrom: %s\n", e1.type.toChars());
+		printf("\tto  : %s\n", to.toChars());
+}
+
+		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 == TY.Tpointer && fty == TY.Tarray
+///static if (false) {
+///		&& (t.next.ty == Tvoid || t.next.equals(e1.type.next))
+///}
+		   )
+		{
+			if (e.Eoper == OPER.OPvar)
+			{
+				// e1 . *(&e1 + 4)
+				e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+				e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, 4));
+				e = el_una(OPER.OPind, t.totym(),e);
+			}
+			else
+			{
+				// e1 . (unsigned)(e1 >> 32)
+				e = el_bin(OPER.OPshr, TYM.TYullong, e, el_long(TYM.TYint, 32));
+				e = el_una(OPER.OP64_32, t.totym(), e);
+			}
+			goto Lret;
+		}
+
+		if (tty == TY.Tpointer && fty == TY.Tsarray
+///static if (false) {
+///		&& (t.next.ty == Tvoid || t.next.equals(e1.type.next))
+///}
+		)
+		{
+			// e1 . &e1
+			e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+			goto Lret;
+		}
+
+		// Convert from static array to dynamic array
+		if (tty == TY.Tarray && fty == TY.Tsarray)
+		{
+			e = sarray_toDarray(loc, tfrom, t, e);
+			goto Lret;
+		}
+
+		// Convert from dynamic array to dynamic array
+		if (tty == TY.Tarray && fty == TY.Tarray)
+		{
+			uint fsize = cast(uint)tfrom.nextOf().size();
+			uint tsize = cast(uint)t.nextOf().size();
+
+			if (fsize != tsize)
+			{
+				elem* ep = el_params(e, el_long(TYM.TYint, fsize), el_long(TYM.TYint, tsize), null);
+				e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[RTLSYM.RTLSYM_ARRAYCAST]), ep);
+			}
+			goto Lret;
+		}
+
+static if (false) {
+		// Convert from dynamic array string literal to static array
+		if (tty == TY.Tsarray && fty == TY.Tarray && e1.op == TOK.TOKstring)
+		{
+			goto Lret;	// treat as a 'paint'
+		}
+}
+
+		// Casting from base class to derived class requires a runtime check
+		if (fty == TY.Tclass && tty == TY.Tclass)
+		{
+			// Casting from derived class to base class is a no-op
+			ClassDeclaration cdfrom;
+			ClassDeclaration cdto;
+			int offset;
+			int rtl = RTLSYM.RTLSYM_DYNAMIC_CAST;
+
+			cdfrom = tfrom.isClassHandle();
+			cdto   = t.isClassHandle();
+			if (cdfrom.isInterfaceDeclaration())
+			{
+				rtl = RTLSYM.RTLSYM_INTERFACE_CAST;
+				if (cdfrom.isCPPinterface())
+				{
+					if (cdto.isCPPinterface())
+					{
+						/* Casting from a C++ interface to a C++ interface
+						 * is always a 'paint' operation
+						 */
+						goto Lret;			// no-op
+					}
+
+					/* Casting from a C++ interface to a class
+					 * always results in null because there is no runtime
+					 * information available to do it.
+					 *
+					 * Casting from a C++ interface to a non-C++ interface
+					 * always results in null because there's no way one
+					 * can be derived from the other.
+					 */
+					e = el_bin(OPER.OPcomma, TYM.TYnptr, e, el_long(TYM.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 == TOK.TOKthis)
+					{   
+						// Assume 'this' is never null, so skip null check
+						e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, offset));
+					}
+					else
+					{
+						etmp = el_same(&e);
+						ex = el_bin(OPER.OPadd, TYM.TYnptr, etmp, el_long(TYM.TYint, offset));
+						ex = el_bin(OPER.OPcolon, TYM.TYnptr, ex, el_long(TYM.TYnptr, 0));
+						e = el_bin(OPER.OPcond, TYM.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(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[rtl]), ep);
+			goto Lret;
+		}
+
+		ftym = e.Ety;
+		ttym = t.totym();
+		if (ftym == ttym)
+		goto Lret;
+
+		switch (tty)
+		{
+			case TY.Tpointer:
+				if (fty == TY.Tdelegate)
+					goto Lpaint;
+				tty = TY.Tuns32;
+				break;
+
+			case TY.Tchar:
+				tty = TY.Tuns8;	
+				break;
+			case TY.Twchar:
+				tty = TY.Tuns16;	
+				break;
+			case TY.Tdchar:	
+				tty = TY.Tuns32;	
+				break;
+			case TY.Tvoid:	
+				goto Lpaint;
+
+			case TY.Tbool:
+			{
+				// Construct e?true:false
+				elem* eq;
+
+				e = el_una(OPER.OPbool, ttym, e);
+				goto Lret;
+			}
+			
+			default:
+				break;	///
+		}
+
+		switch (fty)
+		{
+			case TY.Tpointer:	fty = TY.Tuns32;	break;
+			case TY.Tchar:		fty = TY.Tuns8;		break;
+			case TY.Twchar:		fty = TY.Tuns16;	break;
+			case TY.Tdchar:		fty = TY.Tuns32;	break;
+			default:	break;	///
+		}
+
+	Lagain:
+		switch (X(fty,tty))
+		{
+static if (false) {
+			case X(TY.Tbit,TY.Tint8):
+			case X(TY.Tbit,TY.Tuns8):
+				goto Lpaint;
+			case X(TY.Tbit,TY.Tint16):
+			case X(TY.Tbit,TY.Tuns16):
+			case X(TY.Tbit,TY.Tint32):
+			case X(TY.Tbit,TY.Tuns32):	
+				eop = OPu8_16;
+				goto Leop;
+			case X(TY.Tbit,TY.Tint64):
+			case X(TY.Tbit,TY.Tuns64):
+			case X(TY.Tbit,TY.Tfloat32):
+			case X(TY.Tbit,TY.Tfloat64):
+			case X(TY.Tbit,TY.Tfloat80):
+			case X(TY.Tbit,TY.Tcomplex32):
+			case X(TY.Tbit,TY.Tcomplex64):
+			case X(TY.Tbit,TY.Tcomplex80):
+				e = el_una(OPER.OPu8_16, TYM.TYuint, e);
+				fty = TY.Tuns32;
+				goto Lagain;
+			case X(Tbit,Timaginary32):
+			case X(Tbit,Timaginary64):
+			case X(Tbit,Timaginary80):
+				goto Lzero;
+}
+		/* ============================= */
+
+		case X(TY.Tbool,TY.Tint8):
+		case X(TY.Tbool,TY.Tuns8):
+			goto Lpaint;
+		case X(TY.Tbool,TY.Tint16):
+		case X(TY.Tbool,TY.Tuns16):
+		case X(TY.Tbool,TY.Tint32):
+		case X(TY.Tbool,TY.Tuns32):
+			eop = OPER.OPu8_16;
+			goto Leop;
+		case X(TY.Tbool,TY.Tint64):
+		case X(TY.Tbool,TY.Tuns64):
+		case X(TY.Tbool,TY.Tfloat32):
+		case X(TY.Tbool,TY.Tfloat64):
+		case X(TY.Tbool,TY.Tfloat80):
+		case X(TY.Tbool,TY.Tcomplex32):
+		case X(TY.Tbool,TY.Tcomplex64):
+		case X(TY.Tbool,TY.Tcomplex80):
+			e = el_una(OPER.OPu8_16, TYM.TYuint, e);
+			fty = TY.Tuns32;
+			goto Lagain;
+		case X(TY.Tbool,TY.Timaginary32):
+		case X(TY.Tbool,TY.Timaginary64):
+		case X(TY.Tbool,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tint8,TY.Tuns8):
+			goto Lpaint;
+		case X(TY.Tint8,TY.Tint16):
+		case X(TY.Tint8,TY.Tuns16):
+		case X(TY.Tint8,TY.Tint32):
+		case X(TY.Tint8,TY.Tuns32):
+			eop = OPER.OPs8_16;
+			goto Leop;
+		case X(TY.Tint8,TY.Tint64):
+		case X(TY.Tint8,TY.Tuns64):
+		case X(TY.Tint8,TY.Tfloat32):
+		case X(TY.Tint8,TY.Tfloat64):
+		case X(TY.Tint8,TY.Tfloat80):
+		case X(TY.Tint8,TY.Tcomplex32):
+		case X(TY.Tint8,TY.Tcomplex64):
+		case X(TY.Tint8,TY.Tcomplex80):
+			e = el_una(OPER.OPs8_16, TYM.TYint, e);
+			fty = TY.Tint32;
+			goto Lagain;
+		case X(TY.Tint8,TY.Timaginary32):
+		case X(TY.Tint8,TY.Timaginary64):
+		case X(TY.Tint8,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tuns8,TY.Tint8):
+			goto Lpaint;
+		case X(TY.Tuns8,TY.Tint16):
+		case X(TY.Tuns8,TY.Tuns16):
+		case X(TY.Tuns8,TY.Tint32):
+		case X(TY.Tuns8,TY.Tuns32):
+			eop = OPER.OPu8_16;
+			goto Leop;
+		case X(TY.Tuns8,TY.Tint64):
+		case X(TY.Tuns8,TY.Tuns64):
+		case X(TY.Tuns8,TY.Tfloat32):
+		case X(TY.Tuns8,TY.Tfloat64):
+		case X(TY.Tuns8,TY.Tfloat80):
+		case X(TY.Tuns8,TY.Tcomplex32):
+		case X(TY.Tuns8,TY.Tcomplex64):
+		case X(TY.Tuns8,TY.Tcomplex80):
+			e = el_una(OPER.OPu8_16, TYM.TYuint, e);
+			fty = TY.Tuns32;
+			goto Lagain;
+		case X(TY.Tuns8,TY.Timaginary32):
+		case X(TY.Tuns8,TY.Timaginary64):
+		case X(TY.Tuns8,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tint16,TY.Tint8):
+		case X(TY.Tint16,TY.Tuns8):
+			eop = OPER.OP16_8;
+			goto Leop;
+		case X(TY.Tint16,TY.Tuns16):
+			goto Lpaint;
+		case X(TY.Tint16,TY.Tint32):
+		case X(TY.Tint16,TY.Tuns32):
+			eop = OPER.OPs16_32;
+			goto Leop;
+		case X(TY.Tint16,TY.Tint64):
+		case X(TY.Tint16,TY.Tuns64):
+			e = el_una(OPER.OPs16_32, TYM.TYint, e);
+			fty = TY.Tint32;
+			goto Lagain;
+		case X(TY.Tint16,TY.Tfloat32):
+		case X(TY.Tint16,TY.Tfloat64):
+		case X(TY.Tint16,TY.Tfloat80):
+		case X(TY.Tint16,TY.Tcomplex32):
+		case X(TY.Tint16,TY.Tcomplex64):
+		case X(TY.Tint16,TY.Tcomplex80):
+			e = el_una(OPER.OPs16_d, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tint16,TY.Timaginary32):
+		case X(TY.Tint16,TY.Timaginary64):
+		case X(TY.Tint16,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tuns16,TY.Tint8):
+		case X(TY.Tuns16,TY.Tuns8):
+			eop = OPER.OP16_8;
+			goto Leop;
+		case X(TY.Tuns16,TY.Tint16):
+			goto Lpaint;
+		case X(TY.Tuns16,TY.Tint32):
+		case X(TY.Tuns16,TY.Tuns32):
+			eop = OPER.OPu16_32;
+			goto Leop;
+		case X(TY.Tuns16,TY.Tint64):
+		case X(TY.Tuns16,TY.Tuns64):
+		case X(TY.Tuns16,TY.Tfloat64):
+		case X(TY.Tuns16,TY.Tfloat32):
+		case X(TY.Tuns16,TY.Tfloat80):
+		case X(TY.Tuns16,TY.Tcomplex32):
+		case X(TY.Tuns16,TY.Tcomplex64):
+		case X(TY.Tuns16,TY.Tcomplex80):
+			e = el_una(OPER.OPu16_32, TYM.TYuint, e);
+			fty = TY.Tuns32;
+			goto Lagain;
+		case X(TY.Tuns16,TY.Timaginary32):
+		case X(TY.Tuns16,TY.Timaginary64):
+		case X(TY.Tuns16,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tint32,TY.Tint8):
+		case X(TY.Tint32,TY.Tuns8):	
+			e = el_una(OPER.OP32_16, TYM.TYshort, e);
+			fty = TY.Tint16;
+			goto Lagain;
+		case X(TY.Tint32,TY.Tint16):
+		case X(TY.Tint32,TY.Tuns16):
+			eop = OPER.OP32_16;
+			goto Leop;
+		case X(TY.Tint32,TY.Tuns32):
+			goto Lpaint;
+		case X(TY.Tint32,TY.Tint64):
+		case X(TY.Tint32,TY.Tuns64):
+			eop = OPER.OPs32_64;
+			goto Leop;
+		case X(TY.Tint32,TY.Tfloat32):
+		case X(TY.Tint32,TY.Tfloat64):
+		case X(TY.Tint32,TY.Tfloat80):
+		case X(TY.Tint32,TY.Tcomplex32):
+		case X(TY.Tint32,TY.Tcomplex64):
+		case X(TY.Tint32,TY.Tcomplex80):
+			e = el_una(OPER.OPs32_d, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tint32,TY.Timaginary32):
+		case X(TY.Tint32,TY.Timaginary64):
+		case X(TY.Tint32,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tuns32,TY.Tint8):
+		case X(TY.Tuns32,TY.Tuns8):
+			e = el_una(OPER.OP32_16, TYM.TYshort, e);
+			fty = TY.Tuns16;
+			goto Lagain;
+		case X(TY.Tuns32,TY.Tint16):
+		case X(TY.Tuns32,TY.Tuns16):
+			eop = OPER.OP32_16;
+			goto Leop;
+		case X(TY.Tuns32,TY.Tint32):
+			goto Lpaint;
+		case X(TY.Tuns32,TY.Tint64):
+		case X(TY.Tuns32,TY.Tuns64):
+			eop = OPER.OPu32_64;
+			goto Leop;
+		case X(TY.Tuns32,TY.Tfloat32):
+		case X(TY.Tuns32,TY.Tfloat64):
+		case X(TY.Tuns32,TY.Tfloat80):
+		case X(TY.Tuns32,TY.Tcomplex32):
+		case X(TY.Tuns32,TY.Tcomplex64):
+		case X(TY.Tuns32,TY.Tcomplex80):
+			e = el_una(OPER.OPu32_d, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tuns32,TY.Timaginary32):
+		case X(TY.Tuns32,TY.Timaginary64):
+		case X(TY.Tuns32,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tint64,TY.Tint8):
+		case X(TY.Tint64,TY.Tuns8):
+		case X(TY.Tint64,TY.Tint16):
+		case X(TY.Tint64,TY.Tuns16):
+			e = el_una(OPER.OP64_32, TYM.TYint, e);
+			fty = TY.Tint32;
+			goto Lagain;
+		case X(TY.Tint64,TY.Tint32):
+		case X(TY.Tint64,TY.Tuns32):
+			eop = OPER.OP64_32;
+			goto Leop;
+		case X(TY.Tint64,TY.Tuns64):
+			goto Lpaint;
+		case X(TY.Tint64,TY.Tfloat32):
+		case X(TY.Tint64,TY.Tfloat64):
+		case X(TY.Tint64,TY.Tfloat80):
+		case X(TY.Tint64,TY.Tcomplex32):
+		case X(TY.Tint64,TY.Tcomplex64):
+		case X(TY.Tint64,TY.Tcomplex80):
+			e = el_una(OPER.OPs64_d, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tint64,TY.Timaginary32):
+		case X(TY.Tint64,TY.Timaginary64):
+		case X(TY.Tint64,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tuns64,TY.Tint8):
+		case X(TY.Tuns64,TY.Tuns8):
+		case X(TY.Tuns64,TY.Tint16):
+		case X(TY.Tuns64,TY.Tuns16):
+			e = el_una(OPER.OP64_32, TYM.TYint, e);
+			fty = TY.Tint32;
+			goto Lagain;
+		case X(TY.Tuns64,TY.Tint32):
+		case X(TY.Tuns64,TY.Tuns32):
+			eop = OPER.OP64_32;
+			goto Leop;
+		case X(TY.Tuns64,TY.Tint64):
+			goto Lpaint;
+		case X(TY.Tuns64,TY.Tfloat32):
+		case X(TY.Tuns64,TY.Tfloat64):
+		case X(TY.Tuns64,TY.Tfloat80):
+		case X(TY.Tuns64,TY.Tcomplex32):
+		case X(TY.Tuns64,TY.Tcomplex64):
+		case X(TY.Tuns64,TY.Tcomplex80):
+			 e = el_una(OPER.OPu64_d, TYM.TYdouble, e);
+			 fty = TY.Tfloat64;
+			 goto Lagain;
+		case X(TY.Tuns64,TY.Timaginary32):
+		case X(TY.Tuns64,TY.Timaginary64):
+		case X(TY.Tuns64,TY.Timaginary80):
+			goto Lzero;
+
+		/* ============================= */
+
+		case X(TY.Tfloat32,TY.Tint8):
+		case X(TY.Tfloat32,TY.Tuns8):
+		case X(TY.Tfloat32,TY.Tint16):
+		case X(TY.Tfloat32,TY.Tuns16):
+		case X(TY.Tfloat32,TY.Tint32):
+		case X(TY.Tfloat32,TY.Tuns32):
+		case X(TY.Tfloat32,TY.Tint64):
+		case X(TY.Tfloat32,TY.Tuns64):
+		case X(TY.Tfloat32,TY.Tfloat80):
+			e = el_una(OPER.OPf_d, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tfloat32,TY.Tfloat64):
+			eop = OPER.OPf_d;
+			goto Leop;
+		case X(TY.Tfloat32,TY.Timaginary32):
+			goto Lzero;
+		case X(TY.Tfloat32,TY.Timaginary64):
+			goto Lzero;
+		case X(TY.Tfloat32,TY.Timaginary80):
+			goto Lzero;
+		case X(TY.Tfloat32,TY.Tcomplex32):
+		case X(TY.Tfloat32,TY.Tcomplex64):
+		case X(TY.Tfloat32,TY.Tcomplex80):
+			e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYifloat,0),e);
+			fty = TY.Tcomplex32;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Tfloat64,TY.Tint8):
+		case X(TY.Tfloat64,TY.Tuns8):
+			e = el_una(OPER.OPd_s16, TYM.TYshort, e);
+			fty = TY.Tint16;
+			goto Lagain;
+		case X(TY.Tfloat64,TY.Tint16):  
+			eop = OPER.OPd_s16;
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tuns16):  
+			eop = OPER.OPd_u16;
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tint32):   
+			eop = OPER.OPd_s32; 
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tuns32):   
+			eop = OPER.OPd_u32; 
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tint64):   
+			eop = OPER.OPd_s64; 
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tuns64):   
+			eop = OPER.OPd_u64; 
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tfloat32): 
+			eop = OPER.OPd_f;   
+			goto Leop;
+		case X(TY.Tfloat64,TY.Tfloat80): 
+			eop = OPER.OPd_ld;  
+			goto Leop;
+		case X(TY.Tfloat64,TY.Timaginary32):	
+			goto Lzero;
+		case X(TY.Tfloat64,TY.Timaginary64):	
+			goto Lzero;
+		case X(TY.Tfloat64,TY.Timaginary80):	
+			goto Lzero;
+		case X(TY.Tfloat64,TY.Tcomplex32):
+		case X(TY.Tfloat64,TY.Tcomplex64):
+		case X(TY.Tfloat64,TY.Tcomplex80):
+			e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYidouble,0),e);
+			fty = TY.Tcomplex64;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Tfloat80,TY.Tint8):
+		case X(TY.Tfloat80,TY.Tuns8):
+		case X(TY.Tfloat80,TY.Tint16):
+		case X(TY.Tfloat80,TY.Tuns16):
+		case X(TY.Tfloat80,TY.Tint32):
+		case X(TY.Tfloat80,TY.Tuns32):
+		case X(TY.Tfloat80,TY.Tint64):
+		case X(TY.Tfloat80,TY.Tfloat32):
+			e = el_una(OPER.OPld_d, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tfloat80,TY.Tuns64):
+			eop = OPER.OPld_u64;
+			goto Leop;
+		case X(TY.Tfloat80,TY.Tfloat64):
+			eop = OPER.OPld_d;
+			goto Leop;
+		case X(TY.Tfloat80,TY.Timaginary32):
+			goto Lzero;
+		case X(TY.Tfloat80,TY.Timaginary64):
+			goto Lzero;
+		case X(TY.Tfloat80,TY.Timaginary80):
+			goto Lzero;
+		case X(TY.Tfloat80,TY.Tcomplex32):
+		case X(TY.Tfloat80,TY.Tcomplex64):
+		case X(TY.Tfloat80,TY.Tcomplex80):
+			e = el_bin(OPER.OPadd,TYM.TYcldouble,e,el_long(TYM.TYildouble,0));
+			fty = TY.Tcomplex80;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Timaginary32,TY.Tint8):
+		case X(TY.Timaginary32,TY.Tuns8):
+		case X(TY.Timaginary32,TY.Tint16):
+		case X(TY.Timaginary32,TY.Tuns16):
+		case X(TY.Timaginary32,TY.Tint32):
+		case X(TY.Timaginary32,TY.Tuns32):
+		case X(TY.Timaginary32,TY.Tint64):
+		case X(TY.Timaginary32,TY.Tuns64):
+		case X(TY.Timaginary32,TY.Tfloat32):
+		case X(TY.Timaginary32,TY.Tfloat64):
+		case X(TY.Timaginary32,TY.Tfloat80):
+			goto Lzero;
+		case X(TY.Timaginary32,TY.Timaginary64):
+			eop = OPER.OPf_d;
+			goto Leop;
+		case X(TY.Timaginary32,TY.Timaginary80):
+			e = el_una(OPER.OPf_d, TYM.TYidouble, e);
+			fty = TY.Timaginary64;
+			goto Lagain;
+		case X(TY.Timaginary32,TY.Tcomplex32):
+		case X(TY.Timaginary32,TY.Tcomplex64):
+		case X(TY.Timaginary32,TY.Tcomplex80):
+			e = el_bin(OPER.OPadd,TYM.TYcfloat,el_long(TYM.TYfloat,0),e);
+			fty = TY.Tcomplex32;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Timaginary64,TY.Tint8):
+		case X(TY.Timaginary64,TY.Tuns8):
+		case X(TY.Timaginary64,TY.Tint16):
+		case X(TY.Timaginary64,TY.Tuns16):
+		case X(TY.Timaginary64,TY.Tint32):
+		case X(TY.Timaginary64,TY.Tuns32):
+		case X(TY.Timaginary64,TY.Tint64):
+		case X(TY.Timaginary64,TY.Tuns64):
+		case X(TY.Timaginary64,TY.Tfloat32):
+		case X(TY.Timaginary64,TY.Tfloat64):
+		case X(TY.Timaginary64,TY.Tfloat80):
+			goto Lzero;
+		case X(TY.Timaginary64,TY.Timaginary32):
+			eop = OPER.OPd_f;  
+			goto Leop;
+		case X(TY.Timaginary64,TY.Timaginary80):
+			eop = OPER.OPd_ld; 
+			goto Leop;
+		case X(TY.Timaginary64,TY.Tcomplex32):
+		case X(TY.Timaginary64,TY.Tcomplex64):
+		case X(TY.Timaginary64,TY.Tcomplex80):
+			e = el_bin(OPER.OPadd, TYM.TYcdouble, el_long(TYM.TYdouble,0), e);
+			fty = TY.Tcomplex64;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Timaginary80,TY.Tint8):
+		case X(TY.Timaginary80,TY.Tuns8):
+		case X(TY.Timaginary80,TY.Tint16):
+		case X(TY.Timaginary80,TY.Tuns16):
+		case X(TY.Timaginary80,TY.Tint32):
+		case X(TY.Timaginary80,TY.Tuns32):
+		case X(TY.Timaginary80,TY.Tint64):
+		case X(TY.Timaginary80,TY.Tuns64):
+		case X(TY.Timaginary80,TY.Tfloat32):
+		case X(TY.Timaginary80,TY.Tfloat64):
+		case X(TY.Timaginary80,TY.Tfloat80):
+			goto Lzero;
+		case X(TY.Timaginary80,TY.Timaginary32):
+			e = el_una(OPER.OPf_d, TYM.TYidouble, e);
+			fty = TY.Timaginary64;
+			goto Lagain;
+		case X(TY.Timaginary80,TY.Timaginary64):
+			eop = OPER.OPld_d;
+			goto Leop;
+		case X(TY.Timaginary80,TY.Tcomplex32):
+		case X(TY.Timaginary80,TY.Tcomplex64):
+		case X(TY.Timaginary80,TY.Tcomplex80):
+			e = el_bin(OPER.OPadd, TYM.TYcldouble, el_long(TYM.TYldouble,0), e);
+			fty = TY.Tcomplex80;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Tcomplex32,TY.Tint8):
+		case X(TY.Tcomplex32,TY.Tuns8):
+		case X(TY.Tcomplex32,TY.Tint16):
+		case X(TY.Tcomplex32,TY.Tuns16):
+		case X(TY.Tcomplex32,TY.Tint32):
+		case X(TY.Tcomplex32,TY.Tuns32):
+		case X(TY.Tcomplex32,TY.Tint64):
+		case X(TY.Tcomplex32,TY.Tuns64):
+		case X(TY.Tcomplex32,TY.Tfloat32):
+		case X(TY.Tcomplex32,TY.Tfloat64):
+		case X(TY.Tcomplex32,TY.Tfloat80):
+			e = el_una(OPER.OPc_r, TYM.TYfloat, e);
+			fty = TY.Tfloat32;
+			goto Lagain;
+		case X(TY.Tcomplex32,TY.Timaginary32):
+		case X(TY.Tcomplex32,TY.Timaginary64):
+		case X(TY.Tcomplex32,TY.Timaginary80):
+			e = el_una(OPER.OPc_i, TYM.TYifloat, e);
+			fty = TY.Timaginary32;
+			goto Lagain;
+		case X(TY.Tcomplex32,TY.Tcomplex64):
+		case X(TY.Tcomplex32,TY.Tcomplex80):
+			e = el_una(OPER.OPf_d, TYM.TYcdouble, e);
+			fty = TY.Tcomplex64;
+			goto Lagain;
+
+		/* ============================= */
+
+		case X(TY.Tcomplex64,TY.Tint8):
+		case X(TY.Tcomplex64,TY.Tuns8):
+		case X(TY.Tcomplex64,TY.Tint16):
+		case X(TY.Tcomplex64,TY.Tuns16):
+		case X(TY.Tcomplex64,TY.Tint32):
+		case X(TY.Tcomplex64,TY.Tuns32):
+		case X(TY.Tcomplex64,TY.Tint64):
+		case X(TY.Tcomplex64,TY.Tuns64):
+		case X(TY.Tcomplex64,TY.Tfloat32):
+		case X(TY.Tcomplex64,TY.Tfloat64):
+		case X(TY.Tcomplex64,TY.Tfloat80):
+			e = el_una(OPER.OPc_r, TYM.TYdouble, e);
+			fty = TY.Tfloat64;
+			goto Lagain;
+		case X(TY.Tcomplex64,TY.Timaginary32):
+		case X(TY.Tcomplex64,TY.Timaginary64):
+		case X(TY.Tcomplex64,TY.Timaginary80):
+			e = el_una(OPER.OPc_i, TYM.TYidouble, e);
+			fty = TY.Timaginary64;
+			goto Lagain;
+		case X(TY.Tcomplex64,TY.Tcomplex32):
+			eop = OPER.OPd_f;
+			goto Leop;
+		case X(TY.Tcomplex64,TY.Tcomplex80):
+			eop = OPER.OPd_ld;
+			goto Leop;
+
+		/* ============================= */
+
+		case X(TY.Tcomplex80,TY.Tint8):
+		case X(TY.Tcomplex80,TY.Tuns8):
+		case X(TY.Tcomplex80,TY.Tint16):
+		case X(TY.Tcomplex80,TY.Tuns16):
+		case X(TY.Tcomplex80,TY.Tint32):
+		case X(TY.Tcomplex80,TY.Tuns32):
+		case X(TY.Tcomplex80,TY.Tint64):
+		case X(TY.Tcomplex80,TY.Tuns64):
+		case X(TY.Tcomplex80,TY.Tfloat32):
+		case X(TY.Tcomplex80,TY.Tfloat64):
+		case X(TY.Tcomplex80,TY.Tfloat80):
+			e = el_una(OPER.OPc_r, TYM.TYldouble, e);
+			fty = TY.Tfloat80;
+			goto Lagain;
+		case X(TY.Tcomplex80,TY.Timaginary32):
+		case X(TY.Tcomplex80,TY.Timaginary64):
+		case X(TY.Tcomplex80,TY.Timaginary80):
+			e = el_una(OPER.OPc_i, TYM.TYildouble, e);
+			fty = TY.Timaginary80;
+			goto Lagain;
+		case X(TY.Tcomplex80,TY.Tcomplex32):
+		case X(TY.Tcomplex80,TY.Tcomplex64):
+			e = el_una(OPER.OPld_d, TYM.TYcdouble, e);
+			fty = TY.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;
+	}
+
+	Identifier opId()
+	{
+		return Id.cast_;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CatAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,146 @@
+module dmd.CatAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.SliceExp;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.TY;
+import dmd.Id;
+import dmd.Type;
+import dmd.backend.elem;
+import dmd.backend.RTLSYM;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+import dmd.expression.Util;
+
+class CatAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKcatass, CatAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		if (e1.op == TOKslice)
+		{	
+			SliceExp se = cast(SliceExp)e1;
+
+			if (se.e1.type.toBasetype().ty == Tsarray)
+				error("cannot append to static array %s", se.e1.type.toChars());
+		}
+
+		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) ||
+			tb2.nextOf().implicitConvTo(tb1.nextOf()))
+		   )
+		{	// Append array
+			e2 = e2.castTo(sc, e1.type);
+			type = e1.type;
+			e = this;
+		}
+		else if ((tb1.ty == Tarray) &&
+			e2.implicitConvTo(tb1.nextOf())
+		   )
+		{	// Append element
+			e2 = e2.castTo(sc, tb1.nextOf());
+			type = e1.type;
+			e = this;
+		}
+		else
+		{
+			error("cannot append type %s to type %s", tb2.toChars(), tb1.toChars());
+			type = Type.tint32;
+			e = this;
+		}
+		return e;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.catass;
+	}
+
+    elem* 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 (tybasic(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
+		static if (true) {
+				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);
+		}
+			}
+			else
+			{   // Append element
+		static if (true) {
+				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);
+		}
+			}
+			el_setLoc(e,loc);
+		}
+		else
+			assert(0);
+
+		return e;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CatExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,255 @@
+module dmd.CatExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+import dmd.MATCH;
+import dmd.ArrayLiteralExp;
+import dmd.StringExp;
+import dmd.WANT;
+import dmd.Id;
+import dmd.GlobalExpressions;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+import dmd.backend.RTLSYM;
+import dmd.codegen.Util;
+import dmd.expression.Cat;
+
+class CatExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKcat, CatExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		//printf("CatExp.semantic() %s\n", toChars());
+		if (!type)
+		{
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+			if (e)
+				return e;
+
+			Type tb1 = e1.type.toBasetype();
+			Type tb2 = e2.type.toBasetype();
+
+
+			/* BUG: Should handle things like:
+			 *	char c;
+			 *	c ~ ' '
+			 *	' ' ~ c;
+			 */
+
+static if (false) {
+			e1.type.print();
+			e2.type.print();
+}
+			if ((tb1.ty == Tsarray || tb1.ty == Tarray) &&
+				e2.type.implicitConvTo(tb1.nextOf()) >= MATCHconst)
+			{
+				type = tb1.nextOf().arrayOf();
+				if (tb2.ty == Tarray)
+				{	
+					// Make e2 into [e2]
+					e2 = new ArrayLiteralExp(e2.loc, e2);
+					e2.type = type;
+				}
+				return this;
+			}
+			else if ((tb2.ty == Tsarray || tb2.ty == Tarray) &&
+				e1.type.implicitConvTo(tb2.nextOf()) >= MATCHconst)
+			{
+				type = tb2.nextOf().arrayOf();
+				if (tb1.ty == Tarray)
+				{	
+					// Make e1 into [e1]
+					e1 = new ArrayLiteralExp(e1.loc, e1);
+					e1.type = type;
+				}
+				return this;
+			}
+
+			if ((tb1.ty == Tsarray || tb1.ty == Tarray) &&
+				(tb2.ty == Tsarray || tb2.ty == Tarray) &&
+				(tb1.nextOf().mod || tb2.nextOf().mod) &&
+				(tb1.nextOf().mod != tb2.nextOf().mod)
+			   )
+			{
+				Type t1 = tb1.nextOf().mutableOf().constOf().arrayOf();
+				Type t2 = tb2.nextOf().mutableOf().constOf().arrayOf();
+				if (e1.op == TOKstring && !(cast(StringExp)e1).committed)
+					e1.type = t1;
+				else
+					e1 = e1.castTo(sc, t1);
+				if (e2.op == TOKstring && !(cast(StringExp)e2).committed)
+					e2.type = t2;
+				else
+					e2 = e2.castTo(sc, t2);
+			}
+
+			typeCombine(sc);
+			type = type.toHeadMutable();
+
+			Type tb = type.toBasetype();
+			if (tb.ty == Tsarray)
+				type = tb.nextOf().arrayOf();
+			if (type.ty == Tarray && tb1.nextOf() && tb2.nextOf() &&
+				tb1.nextOf().mod != tb2.nextOf().mod)
+			{
+				type = type.nextOf().toHeadMutable().arrayOf();
+			}
+static if (false) {
+			e1.type.print();
+			e2.type.print();
+			type.print();
+			print();
+}
+			Type t1 = e1.type.toBasetype();
+			Type t2 = e2.type.toBasetype();
+			if (e1.op == TOKstring && e2.op == TOKstring)
+				e = optimize(WANTvalue);
+			else if ((t1.ty == Tarray || t1.ty == Tsarray) &&
+				 (t2.ty == Tarray || t2.ty == Tsarray))
+			{
+				e = this;
+			}
+			else
+			{
+				//printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars());
+				error("Can only concatenate arrays, not (%s ~ %s)",
+				e1.type.toChars(), e2.type.toChars());
+				type = Type.tint32;
+				e = this;
+			}
+			e.type = e.type.semantic(loc, sc);
+			return e;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("CatExp::optimize(%d) %s\n", result, toChars());
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		Expression e = Cat(type, e1, e2);
+		if (e is EXP_CANT_INTERPRET)
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.cat;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.cat_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e;
+
+static if (false) {
+		printf("CatExp::toElem()\n");
+		print();
+}
+
+		Type tb1 = e1.type.toBasetype();
+		Type tb2 = e2.type.toBasetype();
+		Type tn;
+
+///static if (false) {
+///		if ((tb1.ty == Tarray || tb1.ty == Tsarray) &&
+///			(tb2.ty == Tarray || tb2.ty == Tsarray)
+///		   )
+///}
+
+		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 = cast(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));
+	static if (true) {
+			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);
+	}
+		}
+		else
+		{
+			elem *e1;
+			elem *e2;
+			elem *ep;
+
+			e1 = eval_Darray(irs, this.e1);
+			e2 = eval_Darray(irs, this.e2);
+	static if (true) {
+			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);
+	}
+		}
+		el_setLoc(e,loc);
+		}
+///	static if (false) {
+///		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);
+///	}
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Catch.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,88 @@
+module dmd.Catch;
+
+import dmd.Loc;
+import dmd.Type;
+import dmd.Scope;
+import dmd.Identifier;
+import dmd.VarDeclaration;
+import dmd.Statement;
+import dmd.OutBuffer;
+import dmd.Id;
+import dmd.TypeIdentifier;
+import dmd.Util;
+import dmd.ScopeDsymbol;
+import dmd.HdrGenState;
+import dmd.BE;
+
+class Catch
+{
+    Loc loc;
+    Type type;
+    Identifier ident;
+    VarDeclaration var = null;
+    Statement handler;
+
+    this(Loc loc, Type t, Identifier id, Statement handler)
+	{
+		//printf("Catch(%s, loc = %s)\n", id.toChars(), loc.toChars());
+		this.loc = loc;
+		this.type = t;
+		this.ident = id;
+		this.handler = handler;
+	}
+
+    Catch syntaxCopy()
+	{
+		assert(false);
+	}
+
+    void semantic(Scope sc)
+	{
+		ScopeDsymbol sym;
+
+		//printf("Catch.semantic(%s)\n", ident.toChars());
+
+	version (IN_GCC) {
+	} else {
+		if (sc.tf)
+		{
+			/* This is because the _d_local_unwind() gets the stack munged
+			 * up on this. The workaround is to place any try-catches into
+			 * a separate function, and call that.
+			 * To fix, have the compiler automatically convert the finally
+			 * body into a nested function.
+			 */
+			error(loc, "cannot put catch statement inside finally block");
+		}
+	}
+
+		sym = new ScopeDsymbol();
+		sym.parent = sc.scopesym;
+		sc = sc.push(sym);
+
+		if (!type)
+			type = new TypeIdentifier(Loc(0), Id.Object_);
+		type = type.semantic(loc, sc);
+		if (!type.toBasetype().isClassHandle())
+			error("can only catch class objects, not '%s'", type.toChars());
+		else if (ident)
+		{
+			var = new VarDeclaration(loc, type, ident, null);
+			var.parent = sc.parent;
+			sc.insert(var);
+		}
+		handler = handler.semantic(sc);
+
+		sc.pop();
+	}
+
+    BE blockExit()
+	{
+		return handler ? handler.blockExit() : BE.BEfallthru;
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ClassDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1885 @@
+module dmd.ClassDeclaration;
+
+import dmd.AggregateDeclaration;
+import dmd.InterfaceDeclaration;
+import dmd.ThisDeclaration;
+import dmd.CompoundStatement;
+import dmd.DeleteDeclaration;
+import dmd.NewDeclaration;
+import dmd.CtorDeclaration;
+import dmd.TypeIdentifier;
+import dmd.STC;
+import dmd.Argument;
+import dmd.TypeTuple;
+import dmd.TY;
+import dmd.LINK;
+import dmd.DsymbolTable;
+import dmd.FuncDeclaration;
+import dmd.Array;
+import dmd.TypeClass;
+import dmd.Module;
+import dmd.Id;
+import dmd.Type;
+import dmd.OverloadSet;
+import dmd.ArrayTypes;
+import dmd.BaseClass;
+import dmd.ClassInfoDeclaration;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.TypeFunction;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.VarDeclaration;
+import dmd.Initializer;
+import dmd.ExpInitializer;
+import dmd.TypeSArray;
+import dmd.ScopeDsymbol;
+import dmd.PROT;
+import dmd.Util;
+import dmd.Global;
+
+import dmd.expression.Util;
+
+import dmd.backend.Symbol;
+import dmd.backend.dt_t;
+import dmd.backend.TYPE;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.backend.mTY;
+import dmd.backend.SC;
+import dmd.backend.mTYman;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.Classsym;
+import dmd.backend.glue;
+import dmd.backend.RTLSYM;
+import dmd.backend.LIST;
+
+import dmd.codegen.Util;
+
+import std.string;
+
+version (DMDV2) {
+	enum CLASSINFO_SIZE = (0x3C+16+4);	// value of ClassInfo.size
+} else {
+	enum CLASSINFO_SIZE = (0x3C+12+4);	// value of ClassInfo.size
+}
+
+enum OFFSET_RUNTIME = 0x76543210;
+
+struct Param
+{
+	int isf(FuncDeclaration fd2)
+	{
+		//printf("param = %p, fd = %p %s\n", param, fd, fd.toChars());
+		return fd is fd2;
+	}
+	
+	FuncDeclaration fd;
+}
+
+class ClassDeclaration : AggregateDeclaration
+{
+    static __gshared ClassDeclaration object;
+    static __gshared ClassDeclaration classinfo;
+
+    ClassDeclaration baseClass;	// null only if this is Object
+    FuncDeclaration staticCtor;
+    FuncDeclaration staticDtor;
+    Array vtbl;				// Array of FuncDeclaration's making up the vtbl[]
+    Array vtblFinal;			// More FuncDeclaration's that aren't in vtbl[]
+
+    BaseClasses baseclasses;		// Array of BaseClass's; first is super,
+					// rest are Interface's
+
+    int interfaces_dim;
+    BaseClass* interfaces;		// interfaces[interfaces_dim] for this class
+					// (does not include baseClass)
+
+    BaseClasses vtblInterfaces;	// array of base interfaces that have
+					// their own vtbl[]
+
+    ClassInfoDeclaration vclassinfo;	// the ClassInfo object for this ClassDeclaration
+    bool com;				// true if this is a COM class (meaning
+					// it derives from IUnknown)
+    bool isauto;				// true if this is an auto class
+    bool isabstract;			// true if abstract class
+
+    int inuse;				// to prevent recursive attempts
+
+    this(Loc loc, Identifier id, BaseClasses baseclasses)
+	{
+		super(loc, id);
+		
+		vtbl = new Array();
+		vtblFinal = new Array();
+		
+		enum msg = "only object.d can define this reserved class name";
+
+		if (baseclasses) {
+			this.baseclasses = baseclasses;
+		} else {
+			this.baseclasses = new BaseClasses();
+		}
+
+		//printf("ClassDeclaration(%s), dim = %d\n", id.toChars(), this.baseclasses.dim);
+
+		// For forward references
+		type = new TypeClass(this);
+
+		if (id)
+		{
+			// Look for special class names
+
+			if (id is Id.__sizeof || id is Id.alignof_ || id is Id.mangleof_)
+				error("illegal class name");
+
+			// BUG: What if this is the wrong TypeInfo, i.e. it is nested?
+			if (id.toChars()[0] == 'T')
+			{
+				if (id is Id.TypeInfo)
+				{	
+					if (Type.typeinfo)
+						Type.typeinfo.error("%s", msg);
+					Type.typeinfo = this;
+				}
+
+				if (id is Id.TypeInfo_Class)
+				{	
+					if (Type.typeinfoclass)
+						Type.typeinfoclass.error("%s", msg);
+					Type.typeinfoclass = this;
+				}
+
+				if (id is Id.TypeInfo_Interface)
+				{	
+					if (Type.typeinfointerface)
+						Type.typeinfointerface.error("%s", msg);
+					Type.typeinfointerface = this;
+				}
+
+				if (id is Id.TypeInfo_Struct)
+				{	
+					if (Type.typeinfostruct)
+						Type.typeinfostruct.error("%s", msg);
+					Type.typeinfostruct = this;
+				}
+
+				if (id is Id.TypeInfo_Typedef)
+				{	
+					if (Type.typeinfotypedef)
+						Type.typeinfotypedef.error("%s", msg);
+					Type.typeinfotypedef = this;
+				}
+
+				if (id is Id.TypeInfo_Pointer)
+				{	
+					if (Type.typeinfopointer)
+						Type.typeinfopointer.error("%s", msg);
+					Type.typeinfopointer = this;
+				}
+
+				if (id is Id.TypeInfo_Array)
+				{	
+					if (Type.typeinfoarray)
+						Type.typeinfoarray.error("%s", msg);
+					Type.typeinfoarray = this;
+				}
+
+				if (id is Id.TypeInfo_StaticArray)
+				{	//if (Type.typeinfostaticarray)
+					//Type.typeinfostaticarray.error("%s", msg);
+					Type.typeinfostaticarray = this;
+				}
+
+				if (id is Id.TypeInfo_AssociativeArray)
+				{	
+					if (Type.typeinfoassociativearray)
+						Type.typeinfoassociativearray.error("%s", msg);
+					Type.typeinfoassociativearray = this;
+				}
+
+				if (id is Id.TypeInfo_Enum)
+				{	
+					if (Type.typeinfoenum)
+						Type.typeinfoenum.error("%s", msg);
+					Type.typeinfoenum = this;
+				}
+
+				if (id is Id.TypeInfo_Function)
+				{	
+					if (Type.typeinfofunction)
+						Type.typeinfofunction.error("%s", msg);
+					Type.typeinfofunction = this;
+				}
+
+				if (id is Id.TypeInfo_Delegate)
+				{	
+					if (Type.typeinfodelegate)
+						Type.typeinfodelegate.error("%s", msg);
+					Type.typeinfodelegate = this;
+				}
+
+				if (id is Id.TypeInfo_Tuple)
+				{	
+					if (Type.typeinfotypelist)
+						Type.typeinfotypelist.error("%s", msg);
+					Type.typeinfotypelist = this;
+				}
+
+	version (DMDV2) {
+				if (id is Id.TypeInfo_Const)
+				{	
+					if (Type.typeinfoconst)
+						Type.typeinfoconst.error("%s", msg);
+					Type.typeinfoconst = this;
+				}
+
+				if (id is Id.TypeInfo_Invariant)
+				{	
+					if (Type.typeinfoinvariant)
+						Type.typeinfoinvariant.error("%s", msg);
+					Type.typeinfoinvariant = this;
+				}
+
+				if (id is Id.TypeInfo_Shared)
+				{	
+					if (Type.typeinfoshared)
+						Type.typeinfoshared.error("%s", msg);
+					Type.typeinfoshared = this;
+				}
+	}
+			}
+
+			if (id is Id.Object_)
+			{   
+				if (object)
+					object.error("%s", msg);
+				object = this;
+			}
+
+			if (id is Id.ClassInfo)
+			{   
+				if (classinfo)
+					classinfo.error("%s", msg);
+				classinfo = this;
+			}
+
+			if (id is Id.ModuleInfo)
+			{   
+				if (Module.moduleinfo)
+					Module.moduleinfo.error("%s", msg);
+				Module.moduleinfo = this;
+			}
+		}
+
+		com = 0;
+		isauto = false;
+		isabstract = false;
+		inuse = 0;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		int i;
+		uint offset;
+
+		//printf("ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
+		//printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
+		//printf("sc.stc = %x\n", sc.stc);
+
+		//{ static int n;  if (++n == 20) *(char*)0=0; }
+
+		if (!ident)		// if anonymous class
+		{	
+			string id = "__anonclass";
+			ident = Identifier.generateId(id);
+		}
+
+		if (!sc)
+			sc = scope_;
+
+		if (!parent && sc.parent && !sc.parent.isModule())
+			parent = sc.parent;
+
+		type = type.semantic(loc, sc);
+		handle = type;
+
+		if (!members)			// if forward reference
+		{	
+			//printf("\tclass '%s' is forward referenced\n", toChars());
+			return;
+		}
+		if (symtab)
+		{	if (!scope_)
+		{   //printf("\tsemantic for '%s' is already completed\n", toChars());
+			return;		// semantic() already completed
+		}
+		}
+		else
+		symtab = new DsymbolTable();
+
+		Scope scx = null;
+		if (scope_)
+		{	sc = scope_;
+			scx = scope_;		// save so we don't make redundant copies
+		scope_ = null;
+		}
+version (IN_GCC) {
+		methods.setDim(0);
+}
+
+		if (sc.stc & STC.STCdeprecated)
+		{
+		isdeprecated = 1;
+		}
+
+		if (sc.linkage == LINK.LINKcpp)
+		error("cannot create C++ classes");
+
+		// Expand any tuples in baseclasses[]
+		for (i = 0; i < baseclasses.dim; )
+		{	
+			BaseClass b = cast(BaseClass)baseclasses.data[i];
+		//printf("test1 %s %s\n", toChars(), b.type.toChars());
+			b.type = b.type.semantic(loc, sc);
+		//printf("test2\n");
+			Type tb = b.type.toBasetype();
+
+			if (tb.ty == TY.Ttuple)
+			{   
+				TypeTuple tup = cast(TypeTuple)tb;
+				enum PROT protection = b.protection;
+				baseclasses.remove(i);
+				size_t dim = Argument.dim(tup.arguments);
+				for (size_t j = 0; j < dim; j++)
+				{	
+					Argument arg = Argument.getNth(tup.arguments, j);
+					b = new BaseClass(arg.type, protection);
+					baseclasses.insert(i + j, cast(void*)b);
+				}
+			}
+			else
+				i++;
+		}
+
+		// See if there's a base class as first in baseclasses[]
+		if (baseclasses.dim)
+		{	
+			TypeClass tc;
+			BaseClass b;
+			Type tb;
+
+			b = cast(BaseClass)baseclasses.data[0];
+			//b.type = b.type.semantic(loc, sc);
+			tb = b.type.toBasetype();
+			if (tb.ty != TY.Tclass)
+			{   error("base type must be class or interface, not %s", b.type.toChars());
+				baseclasses.remove(0);
+			}
+			else
+			{
+				tc = cast(TypeClass)(tb);
+
+				if (tc.sym.isDeprecated())
+				{
+				if (!isDeprecated())
+				{
+					// Deriving from deprecated class makes this one deprecated too
+					isdeprecated = 1;
+
+					tc.checkDeprecated(loc, sc);
+				}
+				}
+
+				if (tc.sym.isInterfaceDeclaration()) {
+					;
+				} else {
+					for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
+					{
+						if (cdb == this)
+						{
+							error("circular inheritance");
+							baseclasses.remove(0);
+							goto L7;
+						}
+					}
+					if (!tc.sym.symtab || tc.sym.sizeok == 0)
+					{   // Try to resolve forward reference
+						if (sc.mustsemantic && tc.sym.scope_)
+						tc.sym.semantic(null);
+					}
+					if (!tc.sym.symtab || tc.sym.scope_ || tc.sym.sizeok == 0)
+					{
+						//printf("%s: forward reference of base class %s\n", toChars(), tc.sym.toChars());
+						//error("forward reference of base class %s", baseClass.toChars());
+						// Forward reference of base class, try again later
+						//printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
+						scope_ = scx ? scx : new Scope(sc);
+						scope_.setNoFree();
+						if (tc.sym.scope_)
+							tc.sym.scope_.module_.addDeferredSemantic(tc.sym);
+						scope_.module_.addDeferredSemantic(this);
+						return;
+					}
+					else
+					{   baseClass = tc.sym;
+						b.base = baseClass;
+					}
+				 L7: ;
+				}
+			}
+		}
+
+		// Treat the remaining entries in baseclasses as interfaces
+		// Check for errors, handle forward references
+		for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
+		{	TypeClass tc;
+		BaseClass b;
+		Type tb;
+
+		b = cast(BaseClass)baseclasses.data[i];
+		b.type = b.type.semantic(loc, sc);
+		tb = b.type.toBasetype();
+		if (tb.ty == TY.Tclass)
+			tc = cast(TypeClass)tb;
+		else
+			tc = null;
+		if (!tc || !tc.sym.isInterfaceDeclaration())
+		{
+			error("base type must be interface, not %s", b.type.toChars());
+			baseclasses.remove(i);
+			continue;
+		}
+		else
+		{
+			if (tc.sym.isDeprecated())
+			{
+			if (!isDeprecated())
+			{
+				// Deriving from deprecated class makes this one deprecated too
+				isdeprecated = 1;
+
+				tc.checkDeprecated(loc, sc);
+			}
+			}
+
+			// Check for duplicate interfaces
+			for (size_t j = (baseClass ? 1 : 0); j < i; j++)
+			{
+			BaseClass b2 = cast(BaseClass)baseclasses.data[j];
+			if (b2.base == tc.sym)
+				error("inherits from duplicate interface %s", b2.base.toChars());
+			}
+
+			if (!tc.sym.symtab)
+			{   // Try to resolve forward reference
+			if (sc.mustsemantic && tc.sym.scope_)
+				tc.sym.semantic(null);
+			}
+
+			b.base = tc.sym;
+			if (!b.base.symtab || b.base.scope_)
+			{
+			//error("forward reference of base class %s", baseClass.toChars());
+			// Forward reference of base, try again later
+			//printf("\ttry later, forward reference of base %s\n", baseClass.toChars());
+			scope_ = scx ? scx : new Scope(sc);
+			scope_.setNoFree();
+			if (tc.sym.scope_)
+				tc.sym.scope_.module_.addDeferredSemantic(tc.sym);
+			scope_.module_.addDeferredSemantic(this);
+			return;
+			}
+		}
+		i++;
+		}
+
+
+		// If no base class, and this is not an Object, use Object as base class
+		if (!baseClass && ident !is Id.Object_)
+		{
+			// BUG: what if Object is redefined in an inner scope?
+			Type tbase = new TypeIdentifier(Loc(0), Id.Object_);
+			BaseClass b;
+			TypeClass tc;
+			Type bt;
+
+			if (!object)
+			{
+				error("missing or corrupt object.d");
+				fatal();
+			}
+			bt = tbase.semantic(loc, sc).toBasetype();
+			b = new BaseClass(bt, PROT.PROTpublic);
+			baseclasses.shift(cast(void*)b);
+			assert(b.type.ty == TY.Tclass);
+			tc = cast(TypeClass)(b.type);
+			baseClass = tc.sym;
+			assert(!baseClass.isInterfaceDeclaration());
+			b.base = baseClass;
+		}
+
+		interfaces_dim = baseclasses.dim;
+		interfaces = cast(BaseClass*)baseclasses.data;
+
+		if (baseClass)
+		{
+			if (baseClass.storage_class & STC.STCfinal)
+				error("cannot inherit from final class %s", baseClass.toChars());
+
+			interfaces_dim--;
+			interfaces++;
+
+			// Copy vtbl[] from base class
+			vtbl.setDim(baseClass.vtbl.dim);
+			memcpy(vtbl.data, baseClass.vtbl.data, (void*).sizeof * vtbl.dim);
+
+			// Inherit properties from base class
+			com = baseClass.isCOMclass();
+			isauto = baseClass.isauto;
+			vthis = baseClass.vthis;
+			storage_class |= baseClass.storage_class & STC.STC_TYPECTOR;
+		}
+		else
+		{
+			// No base class, so this is the root of the class hierarchy
+			vtbl.setDim(0);
+			vtbl.push(cast(void*)this);		// leave room for classinfo as first member
+		}
+
+		protection = sc.protection;
+		storage_class |= sc.stc;
+
+		if (sizeok == 0)
+		{
+		interfaceSemantic(sc);
+
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.addMember(sc, this, 1);
+		}
+
+		/* If this is a nested class, add the hidden 'this'
+		 * member which is a pointer to the enclosing scope.
+		 */
+		if (vthis)		// if inheriting from nested class
+		{   // Use the base class's 'this' member
+			isnested = true;
+			if (storage_class & STC.STCstatic)
+			error("static class cannot inherit from nested class %s", baseClass.toChars());
+			if (toParent2() != baseClass.toParent2())
+			{
+			if (toParent2())
+			{
+				error("is nested within %s, but super class %s is nested within %s",
+				toParent2().toChars(),
+				baseClass.toChars(),
+				baseClass.toParent2().toChars());
+			}
+			else
+			{
+				error("is not nested, but super class %s is nested within %s",
+				baseClass.toChars(),
+				baseClass.toParent2().toChars());
+			}
+			isnested = false;
+			}
+		}
+		else if (!(storage_class & STC.STCstatic))
+		{   
+			Dsymbol s = toParent2();
+			if (s)
+			{
+				AggregateDeclaration ad = s.isClassDeclaration();
+				FuncDeclaration fd = s.isFuncDeclaration();
+
+				if (ad || fd)
+				{   isnested = true;
+					Type t;
+					if (ad)
+						t = ad.handle;
+					else if (fd)
+					{	
+						AggregateDeclaration ad2 = fd.isMember2();
+						if (ad2)
+							t = ad2.handle;
+						else
+						{
+							t = Type.tvoidptr;
+						}
+					}
+					else
+						assert(0);
+					if (t.ty == TY.Tstruct)	// ref to struct
+						t = Type.tvoidptr;
+					assert(!vthis);
+					vthis = new ThisDeclaration(loc, t);
+					members.push(cast(void*)vthis);
+				}
+			}
+		}
+		}
+
+		if (storage_class & (STC.STCauto | STC.STCscope))
+			isauto = true;
+		if (storage_class & STC.STCabstract)
+			isabstract = true;
+		if (storage_class & STC.STCimmutable)
+			type = type.invariantOf();
+		else if (storage_class & STC.STCconst)
+			type = type.constOf();
+		else if (storage_class & STC.STCshared)
+			type = type.sharedOf();
+
+		sc = sc.push(this);
+		sc.stc &= ~(STC.STCfinal | STC.STCauto | STC.STCscope | STC.STCstatic |
+			 STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCtls | STC.STCgshared);
+		sc.stc |= storage_class & STC.STC_TYPECTOR;
+		sc.parent = this;
+		sc.inunion = 0;
+
+		if (isCOMclass())
+		{
+version (_WIN32) {
+		sc.linkage = LINK.LINKwindows;
+} else {
+		/* This enables us to use COM objects under Linux and
+		 * work with things like XPCOM
+		 */
+		sc.linkage = LINK.LINKc;
+}
+		}
+		sc.protection = PROT.PROTpublic;
+		sc.explicitProtection = 0;
+		sc.structalign = 8;
+		structalign = sc.structalign;
+		if (baseClass)
+		{	sc.offset = baseClass.structsize;
+		alignsize = baseClass.alignsize;
+	//	if (isnested)
+	//	    sc.offset += PTRSIZE;	// room for uplevel context pointer
+		}
+		else
+		{	sc.offset = PTRSIZE * 2;	// allow room for __vptr and __monitor
+		alignsize = PTRSIZE;
+		}
+		structsize = sc.offset;
+		Scope scsave = sc;	/// a copy must be created?
+		int members_dim = members.dim;
+		sizeok = 0;
+		for (i = 0; i < members_dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.semantic(sc);
+		}
+
+		if (sizeok == 2)
+		{	// semantic() failed because of forward references.
+		// Unwind what we did, and defer it for later
+		fields.setDim(0);
+		structsize = 0;
+		alignsize = 0;
+		structalign = 0;
+
+		sc = sc.pop();
+
+		scope_ = scx ? scx : new Scope(sc);
+		scope_.setNoFree();
+		scope_.module_.addDeferredSemantic(this);
+
+		//printf("\tsemantic('%s') failed due to forward references\n", toChars());
+		return;
+		}
+
+		//printf("\tsemantic('%s') successful\n", toChars());
+
+		structsize = sc.offset;
+		//members.print();
+
+		/* Look for special member functions.
+		 * They must be in this class, not in a base class.
+		 */
+		ctor = cast(CtorDeclaration)search(Loc(0), Id.ctor, 0);
+		if (ctor && (ctor.toParent() != this || !ctor.isCtorDeclaration()))
+		ctor = null;
+
+	//    dtor = (DtorDeclaration *)search(Id.dtor, 0);
+	//    if (dtor && dtor.toParent() != this)
+	//	dtor = null;
+
+	//    inv = (InvariantDeclaration *)search(Id.classInvariant, 0);
+	//    if (inv && inv.toParent() != this)
+	//	inv = null;
+
+		// Can be in base class
+		aggNew = cast(NewDeclaration)search(Loc(0), Id.classNew, 0);
+		aggDelete = cast(DeleteDeclaration)search(Loc(0), Id.classDelete, 0);
+
+		// If this class has no constructor, but base class does, create
+		// a constructor:
+		//    this() { }
+		if (!ctor && baseClass && baseClass.ctor)
+		{
+		//printf("Creating default this(){} for class %s\n", toChars());
+		CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0);
+		ctor.fbody = new CompoundStatement(Loc(0), new Statements());
+		members.push(cast(void*)ctor);
+		ctor.addMember(sc, this, 1);
+		sc = scsave;	// why? What about sc.nofree?	///
+		sc.offset = structsize;
+		ctor.semantic(sc);
+		this.ctor = ctor;
+		defaultCtor = ctor;
+		}
+
+static if (false) {
+		if (baseClass)
+		{	if (!aggDelete)
+			aggDelete = baseClass.aggDelete;
+		if (!aggNew)
+			aggNew = baseClass.aggNew;
+		}
+}
+
+		// Allocate instance of each new interface
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			uint thissize = PTRSIZE;
+
+			alignmember(structalign, thissize, &sc.offset);
+			assert(b.offset == 0);
+			b.offset = sc.offset;
+
+			// Take care of single inheritance offsets
+			while (b.baseInterfaces.length)
+			{
+				b = b.baseInterfaces[0];
+				b.offset = sc.offset;
+			}
+
+			sc.offset += thissize;
+			if (alignsize < thissize)
+				alignsize = thissize;
+		}
+		structsize = sc.offset;
+		sizeok = 1;
+		Module.dprogress++;
+
+		dtor = buildDtor(sc);
+
+		sc.pop();
+
+static if (false) { // Do not call until toObjfile() because of forward references
+		// Fill in base class vtbl[]s
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+
+		//b.fillVtbl(this, &b.vtbl, 1);
+		}
+}
+		//printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+	/*********************************************
+	 * Determine if 'this' is a base class of cd.
+	 * This is used to detect circular inheritance only.
+	 */
+    int isBaseOf2(ClassDeclaration cd)
+	{
+		if (!cd)
+			return 0;
+		//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+		for (int i = 0; i < cd.baseclasses.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
+
+			if (b.base is this || isBaseOf2(b.base))
+				return 1;
+		}
+		return 0;
+	}
+
+	/*******************************************
+	 * Determine if 'this' is a base class of cd.
+	 */
+///    #define OFFSET_RUNTIME 0x76543210
+    bool isBaseOf(ClassDeclaration cd, int* poffset)
+	{
+		if (!cd)
+			return 0;
+		//printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+		for (int i = 0; i < cd.baseclasses.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
+
+			if (b.base == this || isBaseOf2(b.base))
+				return 1;
+		}
+
+		return 0;
+	}
+
+    Dsymbol search(Loc, Identifier ident, int flags)
+	{
+		Dsymbol s;
+		//printf("%s.ClassDeclaration.search('%s')\n", toChars(), ident.toChars());
+
+		if (scope_)
+		{
+			Scope sc = scope_;
+			sc.mustsemantic++;
+			semantic(sc);
+			sc.mustsemantic--;
+		}
+
+		if (!members || !symtab || scope_)
+		{
+			error("is forward referenced when looking for '%s'", ident.toChars());
+			//*(char*)0=0;
+			return null;
+		}
+
+		s = ScopeDsymbol.search(loc, ident, flags);
+		if (!s)
+		{
+			// Search bases classes in depth-first, left to right order
+
+			int i;
+
+			for (i = 0; i < baseclasses.dim; i++)
+			{
+				BaseClass b = cast(BaseClass)baseclasses.data[i];
+
+				if (b.base)
+				{
+					if (!b.base.symtab)
+						error("base %s is forward referenced", b.base.ident.toChars());
+					else
+					{
+						s = b.base.search(loc, ident, flags);
+						if (s is this)	// happens if s is nested in this and derives from this
+							s = null;
+						else if (s)
+							break;
+					}
+				}
+			}
+		}
+		return s;
+	}
+	
+version (DMDV2) {
+    bool isFuncHidden(FuncDeclaration fd)
+	{
+		//printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toChars());
+		Dsymbol s = search(Loc(0), fd.ident, 4|2);
+		if (!s)
+		{	
+			//printf("not found\n");
+			/* Because, due to a hack, if there are multiple definitions
+			 * of fd.ident, null is returned.
+			 */
+			return false;
+		}
+		
+		Param p; p.fd = fd;
+
+		s = s.toAlias();
+		OverloadSet os = s.isOverloadSet();	
+		if (os)
+		{
+			for (int i = 0; i < os.a.dim; i++)
+			{   
+				Dsymbol s2 = cast(Dsymbol)os.a.data[i];
+				FuncDeclaration f2 = s2.isFuncDeclaration();
+				if (f2 && overloadApply(f2, &p.isf))
+					return false;
+			}
+			return true;
+		}
+		else
+		{
+			FuncDeclaration fdstart = s.isFuncDeclaration();
+			//printf("%s fdstart = %p\n", s.kind(), fdstart);
+			return !overloadApply(fdstart, &p.isf);
+		}
+	}
+}
+    FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
+	{
+		//printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars());
+
+		ClassDeclaration cd = this;
+		Array vtbl = cd.vtbl;
+		while (true)
+		{
+			for (size_t i = 0; i < vtbl.dim; i++)
+			{
+				FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
+				if (!fd)
+					continue;		// the first entry might be a ClassInfo
+
+				//printf("\t[%d] = %s\n", i, fd.toChars());
+				if (ident == fd.ident &&
+					//tf.equals(fd.type)
+					fd.type.covariant(tf) == 1
+				   )
+				{   //printf("\t\tfound\n");
+					return fd;
+				}
+				//else printf("\t\t%d\n", fd.type.covariant(tf));
+			}
+			if (!cd)
+				break;
+
+			vtbl = cd.vtblFinal;
+			cd = cd.baseClass;
+		}
+
+		return null;
+	}
+
+    void interfaceSemantic(Scope sc)
+	{
+		InterfaceDeclaration id = isInterfaceDeclaration();
+
+		vtblInterfaces = new BaseClasses();
+		vtblInterfaces.reserve(interfaces_dim);
+
+		for (size_t i = 0; i < interfaces_dim; i++)
+		{
+			BaseClass b = interfaces[i];
+
+			// If this is an interface, and it derives from a COM interface,
+			// then this is a COM interface too.
+			if (b.base.isCOMinterface())
+				com = 1;
+
+			if (b.base.isCPPinterface() && id)
+				id.cpp = 1;
+
+			vtblInterfaces.push(cast(void*)b);
+			b.copyBaseInterfaces(vtblInterfaces);
+		}
+	}
+
+    bool isCOMclass()
+	{
+		return com;
+	}
+	
+    bool isCOMinterface()
+	{
+		return false;
+	}
+
+version (DMDV2) {
+    bool isCPPinterface()
+	{
+		return false;
+	}
+}
+    bool isAbstract()
+	{
+		if (isabstract)
+			return true;
+
+		for (int i = 1; i < vtbl.dim; i++)
+		{
+			FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
+
+			//printf("\tvtbl[%d] = %p\n", i, fd);
+			if (!fd || fd.isAbstract())
+			{
+				isabstract = true;
+				return true;
+			}
+		}
+
+		return false;
+	}
+	
+    int vtblOffset()
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		return "class";
+	}
+	
+    string mangle()
+	{
+		Dsymbol parentsave = parent;
+
+		//printf("ClassDeclaration.mangle() %s.%s\n", parent.toChars(), toChars());
+
+		/* These are reserved to the compiler, so keep simple
+		 * names for them.
+		 */
+		if (ident is Id.Exception)
+		{	
+			if (parent.ident is Id.object)
+				parent = null;
+		}
+		else if (ident is Id.TypeInfo   ||
+		//	ident is Id.Exception ||
+			ident is Id.TypeInfo_Struct   ||
+			ident is Id.TypeInfo_Class    ||
+			ident is Id.TypeInfo_Typedef  ||
+			ident is Id.TypeInfo_Tuple ||
+			this is object     ||
+			this is classinfo  ||
+			this is Module.moduleinfo ||
+			ident.toChars().startsWith("TypeInfo_")
+		   )
+		{
+			parent = null;
+		}
+
+		string id = Dsymbol.mangle();
+		parent = parentsave;
+		return id;
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    PROT getAccess(Dsymbol smember)	// determine access to smember
+	{
+		PROT access_ret = PROT.PROTnone;
+
+	version (LOG) {
+		printf("+ClassDeclaration::getAccess(this = '%s', smember = '%s')\n",
+			toChars(), smember.toChars());
+	}
+		if (smember.toParent() is this)
+		{
+			access_ret = smember.prot();
+		}
+		else
+		{
+			PROT access;
+			int i;
+
+			if (smember.isDeclaration().isStatic())
+			{
+				access_ret = smember.prot();
+			}
+
+			for (i = 0; i < baseclasses.dim; i++)
+			{   
+				BaseClass b = cast(BaseClass)baseclasses.data[i];
+
+				access = b.base.getAccess(smember);
+				switch (access)
+				{
+					case PROT.PROTnone:
+						break;
+
+					case PROT.PROTprivate:
+						access = PROT.PROTnone;	// private members of base class not accessible
+						break;
+
+					case PROT.PROTpackage:
+					case PROT.PROTprotected:
+					case PROT.PROTpublic:
+					case PROT.PROTexport:
+						// If access is to be tightened
+						if (b.protection < access)
+							access = b.protection;
+
+						// Pick path with loosest access
+						if (access > access_ret)
+							access_ret = access;
+						break;
+
+					default:
+						assert(0);
+				}
+			}
+		}
+
+	version (LOG) {
+		printf("-ClassDeclaration::getAccess(this = '%s', smember = '%s') = %d\n",
+			toChars(), smember.toChars(), access_ret);
+	}
+
+		return access_ret;
+	}
+
+    void addLocalClass(ClassDeclarations aclasses)
+	{
+		aclasses.push(cast(void*)this);
+	}
+
+    // Back end
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		uint i;
+		uint offset;
+		Symbol* sinit;
+		enum_SC scclass;
+
+		//printf("ClassDeclaration.toObjFile('%s')\n", toChars());
+
+		if (!members)
+			return;
+
+		if (multiobj)
+		{	
+			obj_append(this);
+			return;
+		}
+
+		if (global.params.symdebug)
+			toDebug();
+
+		assert(!scope_);	// semantic() should have been run to completion
+
+		scclass = SCglobal;
+		if (inTemplateInstance())
+			scclass = SCcomdat;
+
+		// Put out the members
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol member;
+
+			member = cast(Dsymbol)members.data[i];
+			member.toObjFile(0);
+		}
+
+static if (false) {
+		// Build destructor by aggregating dtors[]
+		Symbol* sdtor;
+		switch (dtors.dim)
+		{	
+			case 0:
+				// No destructors for this class
+				sdtor = null;
+				break;
+
+			case 1:
+				// One destructor, just use it directly
+				sdtor = (cast(DtorDeclaration)dtors.data[0]).toSymbol();
+				break;
+
+			default:
+			{   
+				/* Build a destructor that calls all the
+				 * other destructors in dtors[].
+				 */
+
+				elem* edtor = null;
+
+				// Declare 'this' pointer for our new destructor
+				Symbol* sthis = symbol_calloc("this");
+				sthis.Stype = type_fake(TYnptr);
+				sthis.Stype.Tcount++;
+				sthis.Sclass = SCfastpar;
+				sthis.Spreg = AX;
+				sthis.Sfl = FLauto;
+
+				// Call each of the destructors in dtors[]
+				// in reverse order
+				for (i = 0; i < dtors.dim; i++)
+				{	
+					DtorDeclaration d = cast(DtorDeclaration)dtors.data[i];
+					Symbol* s = d.toSymbol();
+					elem* e = el_bin(OPcall, TYvoid, el_var(s), el_var(sthis));
+					edtor = el_combine(e, edtor);
+				}
+
+				// Create type for the function
+				.type* t = type_alloc(TYjfunc);
+				t.Tflags |= TFprototype | TFfixed;
+				t.Tmangle = mTYman_d;
+				t.Tnext = tsvoid;
+				tsvoid.Tcount++;
+
+				// Create the function, sdtor, and write it out
+				localgot = null;
+				sdtor = toSymbolX("__dtor", SCglobal, t, "FZv");
+				block* b = block_calloc();
+				b.BC = BCret;
+				b.Belem = edtor;
+				sdtor.Sfunc.Fstartblock = b;
+				cstate.CSpsymtab = &sdtor.Sfunc.Flocsym;
+				symbol_add(sthis);
+				writefunc(sdtor);
+			}
+		}
+}
+
+		// Generate C symbols
+		toSymbol();
+		toVtblSymbol();
+		sinit = toInitializer();
+
+		//////////////////////////////////////////////
+
+		// Generate static initializer
+		sinit.Sclass = scclass;
+		sinit.Sfl = FLdata;
+	version (ELFOBJ) { // Burton
+		sinit.Sseg = CDATA;
+	}
+	version (MACHOBJ) {
+		sinit.Sseg = DATA;
+	}
+		toDt(&sinit.Sdt);
+		outdata(sinit);
+
+		//////////////////////////////////////////////
+
+		// Put out the TypeInfo
+		type.getTypeInfo(null);
+		type.vtinfo.toObjFile(multiobj);
+
+		//////////////////////////////////////////////
+
+		// Put out the ClassInfo
+		csym.Sclass = scclass;
+		csym.Sfl = FLdata;
+
+		/* The layout is:
+		   {
+			void **vptr;
+			monitor_t monitor;
+			byte[] initializer;		// static initialization data
+			char[] name;		// class name
+			void *[] vtbl;
+			Interface[] interfaces;
+			ClassInfo *base;		// base class
+			void *destructor;
+			void *invariant;		// class invariant
+			uint flags;
+			void *deallocator;
+			OffsetTypeInfo[] offTi;
+			void *defaultConstructor;
+			const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
+			TypeInfo typeinfo;
+		   }
+		 */
+		dt_t* dt = null;
+		offset = CLASSINFO_SIZE;			// must be ClassInfo.size
+		if (classinfo)
+		{
+			if (classinfo.structsize != CLASSINFO_SIZE)
+				error("D compiler and phobos' object.d are mismatched");
+		}
+
+		if (classinfo)
+			dtxoff(&dt, classinfo.toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
+		else
+			dtdword(&dt, 0);		// BUG: should be an assert()
+
+		dtdword(&dt, 0);			// monitor
+
+		// initializer[]
+		assert(structsize >= 8);
+		dtdword(&dt, structsize);		// size
+		dtxoff(&dt, sinit, 0, TYnptr);	// initializer
+
+		// name[]
+		string name = ident.toChars();
+		size_t namelen = name.length;
+		if (!(namelen > 9 && name[0..9] == "TypeInfo_"))
+		{	
+			name = toPrettyChars();
+			namelen = name.length;
+		}
+		dtdword(&dt, namelen);
+		dtabytes(&dt, TYnptr, 0, namelen + 1, toStringz(name));
+
+		// vtbl[]
+		dtdword(&dt, vtbl.dim);
+		dtxoff(&dt, vtblsym, 0, TYnptr);
+
+		// interfaces[]
+		dtdword(&dt, vtblInterfaces.dim);
+		if (vtblInterfaces.dim)
+			dtxoff(&dt, csym, offset, TYnptr);	// (*)
+		else
+			dtdword(&dt, 0);
+
+		// base
+		if (baseClass)
+			dtxoff(&dt, baseClass.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// destructor
+		if (dtor)
+			dtxoff(&dt, dtor.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// invariant
+		if (inv)
+			dtxoff(&dt, inv.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// flags
+		int flags = 4 | isCOMclass();
+	version (DMDV2) {
+		flags |= 16;
+	}
+		flags |= 32;
+
+		if (ctor)
+			flags |= 8;
+		for (ClassDeclaration cd = this; cd; cd = cd.baseClass)
+		{
+			if (cd.members)
+			{
+				for (size_t j = 0; j < cd.members.dim; j++)
+				{
+					Dsymbol sm = cast(Dsymbol)cd.members.data[j];
+					//printf("sm = %s %s\n", sm.kind(), sm.toChars());
+					if (sm.hasPointers())
+						goto L2;
+				}
+			}
+		}
+		flags |= 2;			// no pointers
+	  L2:
+		dtdword(&dt, flags);
+
+
+		// deallocator
+		if (aggDelete)
+			dtxoff(&dt, aggDelete.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// offTi[]
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);		// null for now, fix later
+
+		// defaultConstructor
+		if (defaultCtor)
+			dtxoff(&dt, defaultCtor.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);
+
+	version (DMDV2) {
+		FuncDeclaration sgetmembers = findGetMembers();
+		if (sgetmembers)
+			dtxoff(&dt, sgetmembers.toSymbol(), 0, TYnptr);
+		else
+			dtdword(&dt, 0);	// module getMembers() function
+	}
+
+		dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr);	// typeinfo
+		//dtdword(&dt, 0);
+
+		//////////////////////////////////////////////
+
+		// Put out vtblInterfaces.data[]. Must immediately follow csym, because
+		// of the fixup (*)
+
+		offset += vtblInterfaces.dim * (4 * PTRSIZE);
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration id = b.base;
+
+			/* The layout is:
+			 *  {
+			 *	ClassInfo *interface;
+			 *	void *[] vtbl;
+			 *	unsigned offset;
+			 *  }
+			 */
+
+			// Fill in vtbl[]
+			b.fillVtbl(this, b.vtbl, 1);
+
+			dtxoff(&dt, id.toSymbol(), 0, TYnptr);		// ClassInfo
+
+			// vtbl[]
+			dtdword(&dt, id.vtbl.dim);
+			dtxoff(&dt, csym, offset, TYnptr);
+
+			dtdword(&dt, b.offset);			// this offset
+
+			offset += id.vtbl.dim * PTRSIZE;
+		}
+
+		// Put out the vtblInterfaces.data[].vtbl[]
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces.dim, toChars());
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration id = b.base;
+			int j;
+
+			//printf("    interface[%d] is '%s'\n", i, id.toChars());
+			j = 0;
+			if (id.vtblOffset())
+			{
+				// First entry is ClassInfo reference
+				//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+				// First entry is struct Interface reference
+				dtxoff(&dt, csym, CLASSINFO_SIZE + i * (4 * PTRSIZE), TYnptr);
+				j = 1;
+			}
+			
+			assert(id.vtbl.dim == b.vtbl.dim);
+			for (; j < id.vtbl.dim; j++)
+			{
+				FuncDeclaration fd;
+
+				assert(j < b.vtbl.dim);
+		static if (false) {
+				Object o = cast(Object)b.vtbl.data[j];
+				if (o)
+				{
+					printf("o = %p\n", o);
+					assert(o.dyncast() == DYNCAST_DSYMBOL);
+					Dsymbol s = cast(Dsymbol)o;
+					printf("s.kind() = '%s'\n", s.kind());
+				}
+		}
+				fd = cast(FuncDeclaration)b.vtbl.data[j];
+				if (fd)
+					dtxoff(&dt, fd.toThunkSymbol(b.offset), 0, TYnptr);
+				else
+					dtdword(&dt, 0);
+			}
+		}
+
+	static if (true) {
+		// Put out the overriding interface vtbl[]s.
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
+		ClassDeclaration cd;
+		scope Array bvtbl = new Array();
+
+		for (cd = this.baseClass; cd; cd = cd.baseClass)
+		{
+			for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+			{   
+				BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+				if (bs.fillVtbl(this, bvtbl, 0))
+				{
+					//printf("\toverriding vtbl[] for %s\n", bs.base.toChars());
+					ClassDeclaration id = bs.base;
+					int j;
+
+					j = 0;
+					if (id.vtblOffset())
+					{
+						// First entry is ClassInfo reference
+						//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+						// First entry is struct Interface reference
+						dtxoff(&dt, cd.toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
+						j = 1;
+					}
+
+					for (; j < id.vtbl.dim; j++)
+					{
+						assert(j < bvtbl.dim);
+						FuncDeclaration fd = cast(FuncDeclaration)bvtbl.data[j];
+						if (fd)
+							dtxoff(&dt, fd.toThunkSymbol(bs.offset), 0, TYnptr);
+						else
+							dtdword(&dt, 0);
+					}
+				}
+			}
+		}
+	}
+	
+	version (INTERFACE_VIRTUAL) {
+		// Put out the overriding interface vtbl[]s.
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration cd;
+
+			for (cd = this.baseClass; cd; cd = cd.baseClass)
+			{
+				for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+				{	
+					BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+					if (b.base == bs.base)
+					{
+						//printf("\toverriding vtbl[] for %s\n", b.base.toChars());
+						ClassDeclaration id = b.base;
+						int j;
+
+						j = 0;
+						if (id.vtblOffset())
+						{
+							// First entry is ClassInfo reference
+							//dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+							// First entry is struct Interface reference
+							dtxoff(&dt, cd.toSymbol(), CLASSINFO_SIZE + k * (4 * PTRSIZE), TYnptr);
+							j = 1;
+						}
+
+						for (; j < id.vtbl.dim; j++)
+						{
+							assert(j < b.vtbl.dim);
+							FuncDeclaration fd = cast(FuncDeclaration)b.vtbl.data[j];
+							if (fd)
+								dtxoff(&dt, fd.toThunkSymbol(bs.offset), 0, TYnptr);
+							else
+								dtdword(&dt, 0);
+						}
+					}
+				}
+			}
+		}
+	}
+
+
+		csym.Sdt = dt;
+	version (ELFOBJ_OR_MACHOBJ) { // Burton
+		// ClassInfo cannot be const data, because we use the monitor on it
+		csym.Sseg = DATA;
+	}
+		outdata(csym);
+		if (isExport())
+			obj_export(csym,0);
+
+		//////////////////////////////////////////////
+
+		// Put out the vtbl[]
+		//printf("putting out %s.vtbl[]\n", toChars());
+		dt = null;
+		if (0)
+			i = 0;
+		else
+		{	
+			dtxoff(&dt, csym, 0, TYnptr);		// first entry is ClassInfo reference
+			i = 1;
+		}
+		for (; i < vtbl.dim; i++)
+		{
+			FuncDeclaration fd = (cast(Dsymbol)vtbl.data[i]).isFuncDeclaration();
+
+			//printf("\tvtbl[%d] = %p\n", i, fd);
+			if (fd && (fd.fbody || !isAbstract()))
+			{   
+				Symbol* s = fd.toSymbol();
+
+		version (DMDV2) {
+				if (isFuncHidden(fd))
+				{	
+					/* fd is hidden from the view of this class.
+					 * If fd overlaps with any function in the vtbl[], then
+					 * issue 'hidden' error.
+					 */
+					for (int j = 1; j < vtbl.dim; j++)
+					{   
+						if (j == i)
+							continue;
+						FuncDeclaration fd2 = (cast(Dsymbol)vtbl.data[j]).isFuncDeclaration();
+						if (!fd2.ident.equals(fd.ident))
+							continue;
+						if (fd.leastAsSpecialized(fd2) || fd2.leastAsSpecialized(fd))
+						{
+							if (global.params.warnings)
+							{
+								TypeFunction tf = cast(TypeFunction)fd.type;
+								if (tf.ty == Tfunction)
+									warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Argument.argsTypesToChars(tf.parameters, tf.varargs), toChars());
+								else
+									warning("%s is hidden by %s\n", fd.toPrettyChars(), toChars());
+							}
+							s = rtlsym[RTLSYM_DHIDDENFUNC];
+							break;
+						}
+					}
+				}
+		}
+				dtxoff(&dt, s, 0, TYnptr);
+			}
+			else
+				dtdword(&dt, 0);
+		}
+
+		vtblsym.Sdt = dt;
+		vtblsym.Sclass = scclass;
+		vtblsym.Sfl = FLdata;
+	version (ELFOBJ) {
+		vtblsym.Sseg = CDATA;
+	}
+	version (MACHOBJ) {
+		vtblsym.Sseg = DATA;
+	}
+		outdata(vtblsym);
+		if (isExport())
+			obj_export(vtblsym,0);
+	}
+	
+    void toDebug()
+	{
+		assert(false);
+	}
+	
+	/******************************************
+	 * Get offset of base class's vtbl[] initializer from start of csym.
+	 * Returns ~0 if not this csym.
+	 */
+    uint baseVtblOffset(BaseClass bc)
+	{
+		uint csymoffset;
+		int i;
+
+		//printf("ClassDeclaration.baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
+		csymoffset = CLASSINFO_SIZE;
+		csymoffset += vtblInterfaces.dim * (4 * PTRSIZE);
+
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+
+			if (b == bc)
+				return csymoffset;
+			csymoffset += b.base.vtbl.dim * PTRSIZE;
+		}
+
+	static if (true) {
+		// Put out the overriding interface vtbl[]s.
+		// This must be mirrored with ClassDeclaration.baseVtblOffset()
+		//printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
+		ClassDeclaration cd;
+		Array bvtbl;
+
+		for (cd = this.baseClass; cd; cd = cd.baseClass)
+		{
+			for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+			{   
+				BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+				if (bs.fillVtbl(this, null, 0))
+				{
+					if (bc == bs)
+					{   
+						//printf("\tcsymoffset = x%x\n", csymoffset);
+						return csymoffset;
+					}
+					csymoffset += bs.base.vtbl.dim * PTRSIZE;
+				}
+			}
+		}
+	}
+	version (INTERFACE_VIRTUAL) {
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration cd;
+
+			for (cd = this.baseClass; cd; cd = cd.baseClass)
+			{
+				//printf("\tbase class %s\n", cd.toChars());
+				for (int k = 0; k < cd.vtblInterfaces.dim; k++)
+				{	
+					BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k];
+
+					if (bc == bs)
+					{   
+						//printf("\tcsymoffset = x%x\n", csymoffset);
+						return csymoffset;
+					}
+					if (b.base == bs.base)
+						csymoffset += bs.base.vtbl.dim * PTRSIZE;
+				}
+			}
+		}
+	}
+
+		return ~0;
+	}
+	
+	static private __gshared Classsym* scc;
+
+	/*************************************
+	 * Create the "ClassInfo" symbol
+	 */
+    Symbol* toSymbol()
+	{
+		if (!csym)
+		{
+			Symbol* s;
+
+			if (!scc)
+				scc = fake_classsym(Id.ClassInfo);
+
+			s = toSymbolX("__Class", SC.SCextern, scc.Stype, "Z");
+			s.Sfl = FL.FLextern;
+			s.Sflags |= SFL.SFLnodebug;
+			csym = s;
+			slist_add(s);
+		}
+
+		return csym;
+	}
+
+	/*************************************
+	 * This is accessible via the ClassData, but since it is frequently
+	 * needed directly (like for rtti comparisons), make it directly accessible.
+	 */
+    Symbol* toVtblSymbol()
+	{
+		if (!vtblsym)
+		{
+			if (!csym)
+				toSymbol();
+
+			TYPE* t = type_alloc(TYM.TYnptr | mTY.mTYconst);
+			t.Tnext = tsvoid;
+			t.Tnext.Tcount++;
+			t.Tmangle = mTYman.mTYman_d;
+
+			Symbol* s = toSymbolX("__vtbl", SC.SCextern, t, "Z");
+			s.Sflags |= SFL.SFLnodebug;
+			s.Sfl = FL.FLextern;
+			vtblsym = s;
+			slist_add(s);
+		}
+		return vtblsym;
+	}
+	
+	// Generate the data for the static initializer.
+    void toDt(dt_t **pdt)
+	{
+		//printf("ClassDeclaration.toDt(this = '%s')\n", toChars());
+
+		// Put in first two members, the vtbl[] and the monitor
+		dtxoff(pdt, toVtblSymbol(), 0, TYnptr);
+		dtdword(pdt, 0);			// monitor
+
+		// Put in the rest
+		toDt2(pdt, this);
+
+		//printf("-ClassDeclaration.toDt(this = '%s')\n", toChars());
+	}
+	
+    void toDt2(dt_t** pdt, ClassDeclaration cd)
+	{
+		uint offset;
+		uint i;
+		dt_t* dt;
+		uint csymoffset;
+
+	version (LOG) {
+		printf("ClassDeclaration.toDt2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
+	}
+		if (baseClass)
+		{
+			baseClass.toDt2(pdt, cd);
+			offset = baseClass.structsize;
+		}
+		else
+		{
+			offset = 8;
+		}
+
+		// Note equivalence of this loop to struct's
+		for (i = 0; i < fields.dim; i++)
+		{
+			VarDeclaration v = cast(VarDeclaration)fields.data[i];
+			Initializer init;
+
+			//printf("\t\tv = '%s' v.offset = %2d, offset = %2d\n", v.toChars(), v.offset, offset);
+			dt = null;
+			init = v.init;
+			if (init)
+			{   
+				//printf("\t\t%s has initializer %s\n", v.toChars(), init.toChars());
+				ExpInitializer ei = init.isExpInitializer();
+				Type tb = v.type.toBasetype();
+				if (ei && tb.ty == Tsarray)
+					(cast(TypeSArray)tb).toDtElem(&dt, ei.exp);
+				else
+					dt = init.toDt();
+			}
+			else if (v.offset >= offset)
+			{   //printf("\t\tdefault initializer\n");
+				v.type.toDt(&dt);
+			}
+			if (dt)
+			{
+				if (v.offset < offset)
+					error("duplicated union initialization for %s", v.toChars());
+				else
+				{
+					if (offset < v.offset)
+						dtnzeros(pdt, v.offset - offset);
+					dtcat(pdt, dt);
+					offset = v.offset + cast(uint)v.type.size();
+				}
+			}
+		}
+
+		// Interface vptr initializations
+		toSymbol();						// define csym
+
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+
+///		version (1 || INTERFACE_VIRTUAL) {
+			for (ClassDeclaration cd2 = cd; 1; cd2 = cd2.baseClass)
+			{
+				assert(cd2);
+				csymoffset = cd2.baseVtblOffset(b);
+				if (csymoffset != ~0)
+				{
+					if (offset < b.offset)
+						dtnzeros(pdt, b.offset - offset);
+					dtxoff(pdt, cd2.toSymbol(), csymoffset, TYnptr);
+					break;
+				}
+			}
+///		} else {
+///			csymoffset = baseVtblOffset(b);
+///			assert(csymoffset != ~0);
+///			dtxoff(pdt, csym, csymoffset, TYnptr);
+///		}
+			offset = b.offset + 4;
+		}
+
+		if (offset < structsize)
+			dtnzeros(pdt, structsize - offset);
+	}
+
+    Symbol* vtblsym;
+
+    ///ClassDeclaration isClassDeclaration() { return cast(ClassDeclaration)this; }	/// huh?
+    ClassDeclaration isClassDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ClassInfoDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,50 @@
+module dmd.ClassInfoDeclaration;
+
+import dmd.VarDeclaration;
+import dmd.ClassDeclaration;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.Id;
+import dmd.STC;
+
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.codegen.Util;
+import dmd.backend.SC;
+import dmd.backend.Util;
+
+class ClassInfoDeclaration : VarDeclaration
+{
+    ClassDeclaration cd;
+
+    this(ClassDeclaration cd)
+	{
+		super(Loc(0), ClassDeclaration.classinfo.type, cd.ident, null);
+		
+		this.cd = cd;
+		storage_class = STC.STCstatic | STC.STCgshared;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+
+    Symbol* toSymbol()
+	{
+		return cd.toSymbol();
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CmpExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,245 @@
+module dmd.CmpExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.Type;
+import dmd.Id;
+import dmd.TY;
+import dmd.ErrorExp;
+import dmd.IntegerExp;
+import dmd.MATCH;
+import dmd.BinExp;
+import dmd.WANT;
+import dmd.GlobalExpressions;
+
+import dmd.expression.Util;
+import dmd.codegen.Util;
+import dmd.expression.Cmp;
+
+import dmd.backend.Util;
+import dmd.backend.RTLSYM;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+import dmd.backend.rel;
+
+class CmpExp : BinExp
+{
+	this(TOK op, Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, op, CmpExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t1;
+		Type t2;
+
+	version (LOGSEMANTIC) {
+		printf("CmpExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			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)
+		{
+			if (!e.type.isscalar() && e.type.equals(e1.type))
+			{
+				error("recursive opCmp expansion");
+				e = new ErrorExp();
+			}
+			else
+			{   
+				e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type.tint32));
+				e = e.semantic(sc);
+			}
+			return e;
+		}
+
+		typeCombine(sc);
+		type = Type.tboolean;
+
+		// Special handling for array comparisons
+		t1 = e1.type.toBasetype();
+		t2 = e2.type.toBasetype();
+		if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) &&
+			(t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
+		{
+			if (t1.nextOf().implicitConvTo(t2.nextOf()) < MATCHconst &&
+				t2.nextOf().implicitConvTo(t1.nextOf()) < MATCHconst &&
+				(t1.nextOf().ty != Tvoid && t2.nextOf().ty != Tvoid))
+				error("array comparison type mismatch, %s vs %s", t1.nextOf().toChars(), t2.nextOf().toChars());
+			e = this;
+		}
+		else if (t1.ty == Tstruct || t2.ty == Tstruct ||
+			 (t1.ty == Tclass && t2.ty == Tclass))
+		{
+			if (t2.ty == Tstruct)
+				error("need member function opCmp() for %s %s to compare", t2.toDsymbol(sc).kind(), t2.toChars());
+			else
+				error("need member function opCmp() for %s %s to compare", t1.toDsymbol(sc).kind(), t1.toChars());
+			e = this;
+		}
+///	static if (true) {
+		else if (t1.iscomplex() || t2.iscomplex())
+		{
+			error("compare not defined for complex operands");
+			e = new ErrorExp();
+		}
+///	}
+		else
+		{	
+			e1.rvalue();
+			e2.rvalue();
+			e = this;
+		}
+
+		//printf("CmpExp: %s, type = %s\n", e.toChars(), e.type.toChars());
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("CmpExp::optimize() %s\n", toChars());
+		e1 = e1.optimize(WANTvalue | (result & WANTinterpret));
+		e2 = e2.optimize(WANTvalue | (result & WANTinterpret));
+
+		Expression e1 = fromConstInitializer(result, this.e1);
+		Expression e2 = fromConstInitializer(result, this.e2);
+
+		e = Cmp(op, type, e1, e2);
+		if (e is EXP_CANT_INTERPRET)
+			e = this;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.cmp;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e;
+		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 = cast(OPER)rel_integral(eop);
+		}
+		if (cast(int)eop > 1 && t1.ty == Tclass && t2.ty == Tclass)
+		{
+	static if (true) {
+		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));
+	}
+		}
+		else if (cast(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);
+
+		version (DMDV2) {
+			ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs),
+				ea2, ea1, null);
+			rtlfunc = RTLSYM_ARRAYCMP2;
+		} else {
+			ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null);
+			rtlfunc = RTLSYM_ARRAYCMP;
+		}
+			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 (cast(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,cast(int)eop));
+			}
+			else
+				e = toElemBin(irs,eop);
+		}
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ComExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,98 @@
+module dmd.ComExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.TY;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+import dmd.expression.Util;
+import dmd.expression.Com;
+
+class ComExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOKtilde, ComExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{
+			UnaExp.semantic(sc);
+			e1 = resolveProperties(sc, e1);
+			e = op_overload(sc);
+			if (e)
+				return e;
+
+			e1.checkNoBool();
+			if (e1.op != TOKslice)
+				e1 = e1.checkIntegral();
+			type = e1.type;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		if (e1.isConst() == 1)
+		{
+			e = Com(type, e1);
+		}
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		assert(false);
+	}
+
+	elem* 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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CommaExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,123 @@
+module dmd.CommaExp;
+
+import dmd.Loc;
+import dmd.BinExp;
+import dmd.IRState;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.Expression;
+import dmd.MATCH;
+import dmd.WANT;
+import dmd.TOK;
+import dmd.Type;
+import dmd.InterState;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+
+class CommaExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKcomma, CommaExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			type = e2.type;
+		}
+		return this;
+	}
+	
+    void checkEscape()
+	{
+		e2.checkEscape();
+	}
+	
+    IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+version (DMDV2) {
+    int isLvalue()
+	{
+		return e2.isLvalue();
+	}
+}
+    Expression toLvalue(Scope sc, Expression e)
+	{
+		e2 = e2.toLvalue(sc, null);
+		return this;
+	}
+	
+    Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		e2 = e2.modifiableLvalue(sc, e);
+		return this;
+	}
+	
+    bool isBool(bool result)
+	{
+		return e2.isBool(result);
+	}
+	
+    bool checkSideEffect(int flag)
+	{
+		if (flag == 2)
+			return e1.checkSideEffect(2) || e2.checkSideEffect(2);
+		else
+		{
+			// Don't check e1 until we cast(void) the a,b code generation
+			return e2.checkSideEffect(flag);
+		}
+	}
+	
+    MATCH implicitConvTo(Type t)
+	{
+		assert(false);
+	}
+	
+    Expression castTo(Scope sc, Type t)
+	{
+		assert(false);
+	}
+	
+    Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("CommaExp.optimize(result = %d) %s\n", result, toChars());
+		e1 = e1.optimize(result & WANTinterpret);
+		e2 = e2.optimize(result);
+		if (!e1 || e1.op == TOKint64 || e1.op == TOKfloat64 || !e1.checkSideEffect(2))
+		{
+			e = e2;
+			if (e)
+				e.type = type;
+		}
+		else
+			e = this;
+		//printf("-CommaExp.optimize(result = %d) %s\n", result, e.toChars());
+		return e;
+	}
+	
+    Expression interpret(InterState* istate)
+	{	
+		assert(false);
+	}
+	
+    elem* 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;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CompileDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,51 @@
+module dmd.CompileDeclaration;
+
+import dmd.AttribDeclaration;
+import dmd.Expression;
+import dmd.ScopeDsymbol;
+import dmd.Dsymbol;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+// Mixin declarations
+
+class CompileDeclaration : AttribDeclaration
+{
+    Expression exp;
+
+    ScopeDsymbol *sd;
+    int compiled;
+
+    this(Loc loc, Expression exp)
+	{
+		assert(false);
+		super(null);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
+	{
+		assert(false);
+	}
+	
+    void compileIt(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CompileExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,29 @@
+module dmd.CompileExp;
+
+import dmd.Expression;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class CompileExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, null);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CompileStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,40 @@
+module dmd.CompileStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+
+class CompileStatement : Statement
+{
+    Expression exp;
+
+    this(Loc loc, Expression exp)
+	{
+		assert(false);
+		super(loc);
+	}
+
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statements flatten(Scope sc)
+	{
+		assert(false);
+	}
+
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Complex.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,7 @@
+module dmd.Complex;
+
+struct Complex(T)
+{
+	T re;
+	T im;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ComplexExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,239 @@
+module dmd.ComplexExp;
+
+import dmd.Expression;
+import dmd.InterState;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.Type;
+import dmd.TOK;
+import dmd.TY;
+import dmd.Port;
+import dmd.Complex;
+
+import dmd.backend.dt_t;
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+class ComplexExp : Expression
+{
+	Complex!(real) value;
+
+	this(Loc loc, Complex!(real) value, Type type)
+	{
+		super(loc, TOK.TOKcomplex80, ComplexExp.sizeof);
+		this.value = value;
+		this.type = type;
+		//printf("ComplexExp.ComplexExp(%s)\n", toChars());
+	}
+
+	int equals(Object o)
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		if (!type)
+			type = Type.tcomplex80;
+		else
+			type = type.semantic(loc, sc);
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+		assert(false);
+	}
+
+	ulong toInteger()
+	{
+		return cast(ulong) toReal();
+	}
+
+	ulong toUInteger()
+	{
+		return cast(long) toReal();
+	}
+
+	real toReal()
+	{
+		return value.re;
+	}
+
+	real toImaginary()
+	{
+		return value.im;
+	}
+
+	Complex!(real) toComplex()
+	{
+		return value;
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		Expression e = this;
+		if (type != t)
+		{
+			if (type.iscomplex() && t.iscomplex())
+			{   
+				e = copy();
+				e.type = t;
+			}
+			else
+				e = Expression.castTo(sc, t);
+		}
+		return e;
+	}
+
+	int isConst()
+	{
+		assert(false);
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+version (_DH) {
+
+	OutBuffer hexp;
+}
+
+	elem* toElem(IRState* irs)
+	{
+		eve c;
+		tym_t ty;
+
+		//printf("ComplexExp.toElem(%p) %s\n", this, toChars());
+
+		///memset(&c, 0, c.sizeof);
+
+		ty = type.totym();
+		switch (tybasic(ty))
+		{
+		case TYcfloat:
+		{
+			c.Vcfloat.re = cast(float) value.re;
+			if (Port.isSignallingNan(value.re)) {
+				(cast(uint*)&c.Vcfloat.re)[0] &= 0xFFBFFFFFL;
+				std.stdio.writeln("float.re is snan");
+			}
+			c.Vcfloat.im = cast(float) value.im;
+			if (Port.isSignallingNan(value.im)) {
+				(cast(uint*)&c.Vcfloat.im)[0] &= 0xFFBFFFFFL;
+				std.stdio.writeln("float.im is snan");
+			}
+			break;
+		}
+
+		case TYcdouble:
+		{
+			c.Vcdouble.re = cast(double) value.re;
+			if (Port.isSignallingNan(value.re)) {
+				std.stdio.writeln("double.re is snan");
+				(cast(uint*)&c.Vcdouble.re)[1] &= 0xFFF7FFFFL;
+			}
+			c.Vcdouble.im = cast(double) value.im;
+			if (Port.isSignallingNan(value.im)) {
+				(cast(uint*)&c.Vcdouble.im)[1] &= 0xFFF7FFFFL;
+				std.stdio.writeln("double.im is snan");
+			}
+			break;
+		}
+
+		case TYcldouble:
+		{
+	static if (true) {
+			c.Vcldouble = value;
+	} else {
+			{
+				ushort* p = cast(ushort*)&c.Vcldouble;
+				for (int i = 0; i < (LNGDBLSIZE*2)/2; i++) printf("%04x ", p[i]);
+					printf("\n");
+			}
+				c.Vcldouble.im = im;
+			{
+				ushort* p = cast(ushort*)&c.Vcldouble;
+				for (int i = 0; i < (LNGDBLSIZE*2)/2; i++) printf("%04x ", p[i]);
+					printf("\n");
+			}
+			c.Vcldouble.re = re;
+			{
+				ushort* p = cast(ushort*)&c.Vcldouble;
+				for (int i = 0; i < (LNGDBLSIZE*2)/2; i++) printf("%04x ", p[i]);
+					printf("\n");
+			}
+	}
+			break;
+		}
+
+			default:
+				assert(0);
+		}
+		return el_const(ty, &c);
+	}
+	
+	static private char[6] zeropad;
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		//printf("ComplexExp.toDt() '%s'\n", toChars());
+		float fvalue;
+		double dvalue;
+		real evalue;
+
+		switch (type.toBasetype().ty)
+		{
+		case Tcomplex32:
+			fvalue = value.re;
+			pdt = dtnbytes(pdt,4,cast(char*)&fvalue);
+			fvalue = value.im;
+			pdt = dtnbytes(pdt,4,cast(char*)&fvalue);
+			break;
+
+		case Tcomplex64:
+			dvalue = value.re;
+			pdt = dtnbytes(pdt,8,cast(char*)&dvalue);
+			dvalue = value.im;
+			pdt = dtnbytes(pdt,8,cast(char*)&dvalue);
+			break;
+
+		case Tcomplex80:
+			evalue = value.re;
+			pdt = dtnbytes(pdt,REALSIZE - REALPAD,cast(char*)&evalue);
+			pdt = dtnbytes(pdt,REALPAD,zeropad.ptr);
+			evalue = value.im;
+			pdt = dtnbytes(pdt,REALSIZE - REALPAD, cast(char*)&evalue);
+			pdt = dtnbytes(pdt,REALPAD,zeropad.ptr);
+			break;
+
+		default:
+			assert(0);
+			break;
+		}
+		return pdt;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CompoundDeclarationStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,27 @@
+module dmd.CompoundDeclarationStatement;
+
+import dmd.CompoundStatement;
+import dmd.Loc;
+import dmd.ArrayTypes;
+import dmd.Statement;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class CompoundDeclarationStatement : CompoundStatement
+{
+    this(Loc loc, Statements s)
+	{
+		super(loc, s);
+		///statements = s;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CompoundStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,355 @@
+module dmd.CompoundStatement;
+
+import dmd.Loc;
+import dmd.Statement;
+import dmd.Array;
+import dmd.TryCatchStatement;
+import dmd.TryFinallyStatement;
+import dmd.Catch;
+import dmd.ScopeStatement;
+import dmd.Identifier;
+import dmd.Lexer;
+import dmd.ThrowStatement;
+import dmd.IdentifierExp;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.ReturnStatement;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.InlineDoState;
+import dmd.InlineCostState;
+import dmd.InlineScanState;
+import dmd.IfStatement;
+import dmd.IRState;
+import dmd.BE;
+import dmd.Util;
+
+class CompoundStatement : Statement
+{
+    Statements statements;
+
+    this(Loc loc, Statements s)
+	{
+		super(loc);
+		statements = s;
+	}
+	
+    this(Loc loc, Statement s1, Statement s2)
+	{
+		super(loc);
+		
+		statements = new Statements();
+		statements.reserve(2);
+		statements.push(cast(void*)s1);
+		statements.push(cast(void*)s2);
+	}
+	
+    Statement syntaxCopy()
+	{
+		Statements a = new Statements();
+		a.setDim(statements.dim);
+
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement)statements.data[i];
+			if (s)
+				s = s.syntaxCopy();
+			a.data[i] = cast(void*)s;
+		}
+
+		return new CompoundStatement(loc, a);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+	static int indent = 0;
+	static int depth = 0;
+	
+    Statement semantic(Scope sc)
+	{
+		Statement s;
+
+		//printf("CompoundStatement.semantic(this = %p, sc = %p)\n", this, sc);
+
+		for (size_t i = 0; i < statements.dim; )
+		{
+			s = cast(Statement) statements.data[i];
+			if (s)
+			{   
+				Statements a = s.flatten(sc);
+
+				if (a)
+				{
+					statements.remove(i);
+					statements.insert(i, a);
+					continue;
+				}
+
+				s = s.semantic(sc);
+
+				statements.data[i] = cast(void*)s;
+				if (s)
+				{
+					Statement sentry;
+					Statement sexception;
+					Statement sfinally;
+
+					s.scopeCode(sc, &sentry, &sexception, &sfinally);
+					if (sentry)
+					{
+						sentry = sentry.semantic(sc);
+						if (s.isDeclarationStatement())
+						{	
+							statements.insert(i, cast(void*)sentry);
+							i++;
+						}
+						else
+							statements.data[i] = cast(void*)sentry;
+					}
+					if (sexception)
+					{
+						if (i + 1 == statements.dim && !sfinally)
+						{
+		static if (true) {
+						sexception = sexception.semantic(sc);
+		} else {
+						statements.push(sexception);
+						if (sfinally)
+							// Assume sexception does not throw
+							statements.push(sfinally);
+		}
+						}
+						else
+						{
+							/* Rewrite:
+							 *	s; s1; s2;
+							 * As:
+							 *	s;
+							 *	try { s1; s2; }
+							 *	catch (Object __o)
+							 *	{ sexception; throw __o; }
+							 */
+							Statement body_;
+							Statements aa = new Statements();
+
+							for (int j = i + 1; j < statements.dim; j++)
+							{
+								aa.push(statements.data[j]);
+							}
+							body_ = new CompoundStatement(Loc(0), aa);
+							body_ = new ScopeStatement(Loc(0), body_);
+
+							Identifier id = Lexer.uniqueId("__o");
+
+							Statement handler = new ThrowStatement(Loc(0), new IdentifierExp(Loc(0), id));
+							handler = new CompoundStatement(Loc(0), sexception, handler);
+
+							Array catches = new Array();
+							Catch ctch = new Catch(Loc(0), null, id, handler);
+							catches.push(cast(void*)ctch);
+							s = new TryCatchStatement(Loc(0), body_, catches);
+
+							if (sfinally)
+								s = new TryFinallyStatement(Loc(0), s, sfinally);
+							s = s.semantic(sc);
+							statements.setDim(i + 1);
+							statements.push(cast(void*)s);
+							break;
+						}
+					}
+					else if (sfinally)
+					{
+						if (0 && i + 1 == statements.dim)
+						{
+							statements.push(cast(void*)sfinally);
+						}
+						else
+						{
+							/* Rewrite:
+							 *	s; s1; s2;
+							 * As:
+							 *	s; try { s1; s2; } finally { sfinally; }
+							 */
+							Statement body_;
+							Statements aa = new Statements();
+
+							for (int j = i + 1; j < statements.dim; j++)
+							{
+								aa.push(statements.data[j]);
+							}
+							body_ = new CompoundStatement(Loc(0), aa);
+							s = new TryFinallyStatement(Loc(0), body_, sfinally);
+							s = s.semantic(sc);
+							statements.setDim(i + 1);
+							statements.push(cast(void*)s);
+							break;
+						}
+					}
+				}
+			}
+			i++;
+		}
+		if (statements.dim == 1)
+		{
+			return cast(Statement)statements.data[0];
+		}
+		return this;
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		//printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim);
+		BE result = BE.BEfallthru;
+		for (size_t i = 0; i < statements.dim; i++)
+		{	Statement s = cast(Statement)statements.data[i];
+			if (s)
+			{
+				//printf("result = x%x\n", result);
+				//printf("%s\n", s->toChars());
+				if (!(result & BE.BEfallthru) && !s.comeFrom())
+				{
+					if (s.blockExit() != BE.BEhalt)
+						s.warning("statement is not reachable");
+				}
+
+				result &= ~BE.BEfallthru;
+				result |= s.blockExit();
+			}
+		}
+
+		return result;
+	}
+	
+    bool comeFrom()
+	{
+		assert(false);
+	}
+	
+    bool isEmpty()
+	{
+		for (int i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement) statements.data[i];
+			if (s && !s.isEmpty())
+				return false;
+		}
+		return true;
+	}
+
+    Statements flatten(Scope sc)
+	{
+		return statements;
+	}
+
+    ReturnStatement isReturnStatement()
+	{
+		ReturnStatement rs = null;
+
+		for (int i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement) statements.data[i];
+			if (s)
+			{
+				rs = s.isReturnStatement();
+				if (rs)
+					break;
+			}
+		}
+		return rs;
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    int inlineCost(InlineCostState* ics)
+	{
+		int cost = 0;
+
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement)statements.data[i];
+			if (s)
+			{
+				cost += s.inlineCost(ics);
+				if (cost >= COST_MAX)
+					break;
+			}
+		}
+
+		return cost;
+	}
+
+    Expression doInline(InlineDoState ids)
+	{
+		Expression e = null;
+
+		//printf("CompoundStatement.doInline() %d\n", statements.dim);
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement)statements.data[i];
+			if (s)
+			{
+				Expression e2 = s.doInline(ids);
+				e = Expression.combine(e, e2);
+				if (s.isReturnStatement())
+					break;
+
+				/* Check for:
+				 *	if (condition)
+				 *	    return exp1;
+				 *	else
+				 *	    return exp2;
+				 */
+				IfStatement ifs = s.isIfStatement();
+				if (ifs && ifs.elsebody && ifs.ifbody &&
+					ifs.ifbody.isReturnStatement() &&
+					ifs.elsebody.isReturnStatement()
+				)
+					break;
+			}
+		}
+		return e;
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		for (size_t i = 0; i < statements.dim; i++)
+		{	
+			Statement s = cast(Statement) statements.data[i];
+			if (s)
+				statements.data[i] = cast(void*)s.inlineScan(iss);
+		}
+
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		if (statements)
+		{
+			size_t dim = statements.dim;
+			for (size_t i = 0 ; i < dim ; i++)
+			{
+				Statement s = cast(Statement)statements.data[i];
+				if (s !is null)
+				{
+					s.toIR(irs);
+				}
+			}
+		}
+	}
+
+    CompoundStatement isCompoundStatement() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CondExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,281 @@
+module dmd.CondExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.MATCH;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Type;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.TY;
+import dmd.WANT;
+import dmd.Global;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.mTY;
+import dmd.backend.TYM;
+import dmd.codegen.Util;
+
+class CondExp : BinExp
+{
+    Expression econd;
+
+    this(Loc loc, Expression econd, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKquestion, CondExp.sizeof, e1, e2);
+		this.econd = econd;
+	}
+	
+    Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+    Expression semantic(Scope sc)
+	{
+		Type t1;
+		Type t2;
+		uint cs0;
+		uint cs1;
+
+	version (LOGSEMANTIC) {
+		printf("CondExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			return this;
+
+		econd = econd.semantic(sc);
+		econd = resolveProperties(sc, econd);
+		econd = econd.checkToPointer();
+		econd = econd.checkToBoolean();
+
+	static if (false) {
+		/* this cannot work right because the types of e1 and e2
+		 * both contribute to the type of the result.
+		 */
+		if (sc.flags & SCOPEstaticif)
+		{
+			/* If in static if, don't evaluate what we don't have to.
+			 */
+			econd = econd.optimize(WANTflags);
+			if (econd.isBool(TRUE))
+			{
+				e1 = e1.semantic(sc);
+				e1 = resolveProperties(sc, e1);
+				return e1;
+			}
+			else if (econd.isBool(FALSE))
+			{
+				e2 = e2.semantic(sc);
+				e2 = resolveProperties(sc, e2);
+				return e2;
+			}
+		}
+	}
+
+		cs0 = sc.callSuper;
+		e1 = e1.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		cs1 = sc.callSuper;
+		sc.callSuper = cs0;
+		e2 = e2.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+		sc.mergeCallSuper(loc, cs1);
+
+		// If either operand is void, the result is void
+		t1 = e1.type;
+		t2 = e2.type;
+		if (t1.ty == Tvoid || t2.ty == Tvoid)
+			type = Type.tvoid;
+		else if (t1 == t2)
+			type = t1;
+		else
+		{
+			typeCombine(sc);
+			switch (e1.type.toBasetype().ty)
+			{
+				case Tcomplex32:
+				case Tcomplex64:
+				case Tcomplex80:
+					e2 = e2.castTo(sc, e1.type);
+					break;
+				default:
+					break;
+			}
+			switch (e2.type.toBasetype().ty)
+			{
+				case Tcomplex32:
+				case Tcomplex64:
+				case Tcomplex80:
+					e1 = e1.castTo(sc, e2.type);
+					break;
+				default:
+					break;
+			}
+			if (type.toBasetype().ty == Tarray)
+			{
+				e1 = e1.castTo(sc, type);
+				e2 = e2.castTo(sc, type);
+			}
+		}
+	static if (false) {
+		printf("res: %s\n", type.toChars());
+		printf("e1 : %s\n", e1.type.toChars());
+		printf("e2 : %s\n", e2.type.toChars());
+	}
+		return this;
+	}
+
+    Expression optimize(int result)
+	{
+		Expression e;
+
+		econd = econd.optimize(WANTflags | (result & WANTinterpret));
+		if (econd.isBool(true))
+			e = e1.optimize(result);
+		else if (econd.isBool(false))
+			e = e2.optimize(result);
+		else
+		{	
+			e1 = e1.optimize(result);
+			e2 = e2.optimize(result);
+			e = this;
+		}
+
+		return e;
+	}
+	
+    Expression interpret(InterState istate)
+	{
+		assert(false);
+	}
+
+    void checkEscape()
+	{
+		e1.checkEscape();
+		e2.checkEscape();
+	}
+
+    int isLvalue()
+	{
+		assert(false);
+	}
+
+    Expression toLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+
+    Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+
+    Expression checkToBoolean()
+	{
+		assert(false);
+	}
+
+    bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    MATCH implicitConvTo(Type t)
+	{
+		MATCH m1 = e1.implicitConvTo(t);
+		MATCH m2 = e2.implicitConvTo(t);
+		//printf("CondExp: m1 %d m2 %d\n", m1, m2);
+
+		// Pick the worst match
+		return (m1 < m2) ? m1 : m2;
+	}
+
+    Expression castTo(Scope sc, Type t)
+	{
+		Expression e = this;
+
+		if (type !is t)
+		{
+			if (1 || e1.op == TOKstring || e2.op == TOKstring)
+			{   
+				e = new CondExp(loc, econd, e1.castTo(sc, t), e2.castTo(sc, t));
+				e.type = t;
+			}
+			else
+				e = Expression.castTo(sc, t);
+		}
+		return e;
+	}
+
+    void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+    bool canThrow()
+	{
+		return econd.canThrow() || e1.canThrow() || e2.canThrow();
+	}
+
+    int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics) + e2.inlineCost(ics) + econd.inlineCost(ics);
+	}
+	
+    Expression doInline(InlineDoState ids)
+	{
+		CondExp ce = cast(CondExp)copy();
+
+		ce.econd = econd.doInline(ids);
+		ce.e1 = e1.doInline(ids);
+		ce.e2 = e2.doInline(ids);
+		return ce;
+	}
+	
+    Expression inlineScan(InlineScanState* iss)
+	{
+		econd = econd.inlineScan(iss);
+		e1 = e1.inlineScan(iss);
+		e2 = e2.inlineScan(iss);
+		return this;
+	}
+
+    elem* 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 = cast(uint)e1.type.size();
+
+		el_setLoc(e, loc);
+		return e;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Condition.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,24 @@
+module dmd.Condition;
+
+import dmd.Loc;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class Condition
+{
+    Loc loc;
+    int inc = 0;// 0: not computed yet
+				// 1: include
+				// 2: do not include
+
+    this(Loc loc)
+	{
+		this.loc = loc;
+	}
+
+    abstract Condition syntaxCopy();
+    abstract bool include(Scope sc, ScopeDsymbol s);
+    abstract void toCBuffer(OutBuffer buf, HdrGenState* hgs);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ConditionalDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,81 @@
+module dmd.ConditionalDeclaration;
+
+import dmd.AttribDeclaration;
+import dmd.Condition;
+import dmd.Array;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class ConditionalDeclaration : AttribDeclaration
+{
+    Condition condition;
+    Array elsedecl;	// array of Dsymbol's for else block
+
+    this(Condition condition, Array decl, Array elsedecl)
+	{
+		super(decl);
+		//printf("ConditionalDeclaration::ConditionalDeclaration()\n");
+		this.condition = condition;
+		this.elsedecl = elsedecl;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+	// Decide if 'then' or 'else' code should be included
+
+    Array include(Scope sc, ScopeDsymbol sd)
+	{
+		//printf("ConditionalDeclaration::include()\n");
+		assert(condition);
+		return condition.include(sc, sd) ? decl : elsedecl;
+	}
+	
+    void addComment(ubyte* comment)
+	{
+		/* Because addComment is called by the parser, if we called
+		 * include() it would define a version before it was used.
+		 * But it's no problem to drill down to both decl and elsedecl,
+		 * so that's the workaround.
+		 */
+
+		if (comment)
+		{
+			Array d = decl;
+
+			for (int j = 0; j < 2; j++)
+			{
+				if (d)
+				{
+					for (uint i = 0; i < d.dim; i++)
+					{   
+						Dsymbol s = cast(Dsymbol)d.data[i];
+						//printf("ConditionalDeclaration::addComment %s\n", s->toChars());
+						s.addComment(comment);
+					}
+				}
+				d = elsedecl;
+			}
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ConditionalStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,65 @@
+module dmd.ConditionalStatement;
+
+import dmd.Statement;
+import dmd.Condition;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.BE;
+
+class ConditionalStatement : Statement
+{
+    Condition condition;
+    Statement ifbody;
+    Statement elsebody;
+
+    this(Loc loc, Condition condition, Statement ifbody, Statement elsebody)
+	{
+		super(loc);
+		this.condition = condition;
+		this.ifbody = ifbody;
+		this.elsebody = elsebody;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    Statements flatten(Scope sc)
+	{
+		Statement s;
+
+		if (condition.include(sc, null))
+			s = ifbody;
+		else
+			s = elsebody;
+
+		Statements a = new Statements();
+		a.push(cast(void*)s);
+
+		return a;
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ContinueStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,154 @@
+module dmd.ContinueStatement;
+
+import dmd.Statement;
+import dmd.FuncDeclaration;
+import dmd.IntegerExp;
+import dmd.ReturnStatement;
+import dmd.LabelStatement;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+import dmd.IRState;
+import dmd.BE;
+
+import dmd.backend.Util;
+import dmd.backend.BC;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+
+class ContinueStatement : Statement
+{
+    Identifier ident;
+
+    this(Loc loc, Identifier ident)
+	{
+		super(loc);
+		this.ident = ident;
+	}
+	
+    Statement syntaxCopy()
+	{
+		ContinueStatement s = new ContinueStatement(loc, ident);
+		return s;
+	}
+
+    Statement semantic(Scope sc)
+	{
+		//printf("ContinueStatement.semantic() %p\n", this);
+		if (ident)
+		{
+			Scope scx;
+			FuncDeclaration thisfunc = sc.func;
+
+			for (scx = sc; scx; scx = scx.enclosing)
+			{
+				LabelStatement ls;
+
+				if (scx.func != thisfunc)	// if in enclosing function
+				{
+					if (sc.fes)		// if this is the body of a foreach
+					{
+						for (; scx; scx = scx.enclosing)
+						{
+							ls = scx.slabel;
+							if (ls && ls.ident == ident && ls.statement == sc.fes)
+							{
+								// Replace continue ident; with return 0;
+								return new ReturnStatement(Loc(0), new IntegerExp(0));
+							}
+						}
+
+						/* Post this statement to the fes, and replace
+						 * it with a return value that caller will put into
+						 * a switch. Caller will figure out where the break
+						 * label actually is.
+						 * Case numbers start with 2, not 0, as 0 is continue
+						 * and 1 is break.
+						 */
+						Statement s;
+						sc.fes.cases.push(cast(void*)this);
+						s = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1));
+						return s;
+					}
+					break;			// can't continue to it
+				}
+
+				ls = scx.slabel;
+				if (ls && ls.ident == ident)
+				{
+					Statement s = ls.statement;
+
+					if (!s.hasContinue())
+						error("label '%s' has no continue", ident.toChars());
+					if (ls.tf != sc.tf)
+						error("cannot continue out of finally block");
+					return this;
+				}
+			}
+			error("enclosing label '%s' for continue not found", ident.toChars());
+		}
+		else if (!sc.scontinue)
+		{
+			if (sc.fes)
+			{   
+				Statement s;
+
+				// Replace continue; with return 0;
+				s = new ReturnStatement(Loc(0), new IntegerExp(0));
+				return s;
+			}
+			error("continue is not inside a loop");
+		}
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    BE blockExit()
+	{
+		return ident ? BE.BEgoto : BE.BEcontinue;
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("continue");
+		if (ident)
+		{   
+			buf.writebyte(' ');
+			buf.writestring(ident.toChars());
+		}
+		buf.writebyte(';');
+		buf.writenl();
+	}
+
+    void toIR(IRState* irs)
+	{
+		block* bcont;
+		block* b;
+		Blockx* blx = irs.blx;
+
+		//printf("ContinueStatement.toIR() %p\n", this);
+		bcont = irs.getContBlock(ident);
+		assert(bcont);
+		b = blx.curblock;
+		incUsage(irs, loc);
+
+		// Adjust exception handler scope index if in different try blocks
+		if (b.Btry != bcont.Btry)
+		{
+			//setScopeIndex(blx, b, bcont.Btry ? bcont.Btry.Bscope_index : -1);
+		}
+
+		/* Nothing more than a 'goto' to the current continue destination
+		 */
+		list_append(&b.Bsucc, bcont);
+		block_next(blx, BCgoto, null);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CppMangleState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.CppMangleState;
+
+import dmd.Array;
+import dmd.OutBuffer;
+
+struct CppMangleState
+{
+    static __gshared Array components;
+
+    int substitute(OutBuffer buf, void* p)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/CtorDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,140 @@
+module dmd.CtorDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+import dmd.AggregateDeclaration;
+import dmd.TypeFunction;
+import dmd.Type;
+import dmd.Global;
+import dmd.LINK;
+import dmd.Expression;
+import dmd.ThisExp;
+import dmd.Statement;
+import dmd.ReturnStatement;
+import dmd.CompoundStatement;
+import dmd.Argument;
+import dmd.Id;
+
+class CtorDeclaration : FuncDeclaration
+{
+	Arguments arguments;
+    int varargs;
+
+    this(Loc loc, Loc endloc, Arguments arguments, int varargs)
+	{
+		super(loc, endloc, Id.ctor, STC.STCundefined, null);
+		
+		this.arguments = arguments;
+		this.varargs = varargs;
+		//printf("CtorDeclaration(loc = %s) %s\n", loc.toChars(), toChars());
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		AggregateDeclaration ad;
+		Type tret;
+
+		//printf("CtorDeclaration.semantic() %s\n", toChars());
+		if (type)
+			return;
+
+		sc = sc.push();
+		sc.stc &= ~STCstatic;		// not a static constructor
+
+		parent = sc.parent;
+		Dsymbol parent = toParent2();
+		ad = parent.isAggregateDeclaration();
+		if (!ad || parent.isUnionDeclaration())
+		{
+			error("constructors are only for class or struct definitions");
+			tret = Type.tvoid;
+		}
+		else
+		{	
+			tret = ad.handle;
+			assert(tret);
+		}
+		type = new TypeFunction(arguments, tret, varargs, LINKd);
+
+version (STRUCTTHISREF) {
+		if (ad && ad.isStructDeclaration())
+			(cast(TypeFunction)type).isref = true;
+}
+		if (!originalType)
+			originalType = type;
+
+		sc.flags |= SCOPE.SCOPEctor;
+		type = type.semantic(loc, sc);
+		sc.flags &= ~SCOPE.SCOPEctor;
+
+		// Append:
+		//	return this;
+		// to the function body
+		if (fbody)
+		{
+			Expression e = new ThisExp(loc);
+			Statement s = new ReturnStatement(loc, e);
+			fbody = new CompoundStatement(loc, fbody, s);
+		}
+
+		FuncDeclaration.semantic(sc);
+
+		sc.pop();
+
+		// See if it's the default constructor
+		if (ad && varargs == 0 && Argument.dim(arguments) == 0)
+		{	if (ad.isStructDeclaration())
+			error("default constructor not allowed for structs");
+		else
+			ad.defaultCtor = this;
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    string kind()
+	{
+		return "constructor";
+	}
+	
+    string toChars()
+	{
+		return "this";
+	}
+	
+    bool isVirtual()
+	{
+		return false;
+	}
+	
+    bool addPreInvariant()
+	{
+		return false;
+	}
+	
+    bool addPostInvariant()
+	{
+		return (isThis() && vthis && global.params.useInvariants);
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    CtorDeclaration isCtorDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DVCondition.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,26 @@
+module dmd.DVCondition;
+
+import dmd.Condition;
+import dmd.Identifier;
+import dmd.Module;
+import dmd.Loc;
+
+class DVCondition : Condition
+{
+    uint level;
+    Identifier ident;
+    Module mod;
+
+    this(Module mod, uint level, Identifier ident)
+	{
+		super(Loc(0));
+		this.mod = mod;
+		this.level = level;
+		this.ident = ident;
+	}
+
+    Condition syntaxCopy()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DYNCAST.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,11 @@
+module dmd.DYNCAST;
+
+enum DYNCAST
+{
+    DYNCAST_OBJECT,
+    DYNCAST_EXPRESSION,
+    DYNCAST_DSYMBOL,
+    DYNCAST_TYPE,
+    DYNCAST_IDENTIFIER,
+    DYNCAST_TUPLE,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Dchar.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,271 @@
+module dmd.Dchar;
+
+import core.stdc.wchar_;
+import core.stdc.string;
+import core.stdc.ctype;
+
+version (M_UNICODE) {
+	alias wchat dchar_t;
+	
+	struct Dchar
+	{
+		static dchar_t* inc(dchar_t* p) { return p + 1; }
+		static dchar_t* dec(dchar_t* pstart, dchar_t* p) { return p - 1; }
+		static int len(const(dchar_t)* p) { return wcslen(p); }
+		static dchar_t get(dchar_t* p) { return *p; }
+		static dchar_t getprev(dchar_t* pstart, dchar_t* p) { return p[-1]; }
+		static dchar_t* put(dchar_t* p, dchar_t c) { *p = c; return p + 1; }
+		static int cmp(dchar_t* s1, dchar_t* s2)
+		{
+version (__DMC__) {
+			if (!*s1 && !*s2)	// wcscmp is broken
+				return 0;
+}
+		return wcscmp(s1, s2);
+version (disabled) {
+			return (*s1 == *s2)
+				? wcscmp(s1, s2)
+				: (cast(int)*s1 - cast(int)*s2);
+}
+		}
+		static int memcmp(const(dchar_t)*s1, const(dchar_t)* s2, int nchars) { return .memcmp(s1, s2, nchars * dchar_t.sizeof); }
+		static int isDigit(dchar_t c) { return '0' <= c && c <= '9'; }
+		static int isAlpha(dchar_t c) { return iswalpha(c); }
+		static int isUpper(dchar_t c) { return iswupper(c); }
+		static int isLower(dchar_t c) { return iswlower(c); }
+		static int isLocaleUpper(dchar_t c) { return isUpper(c); }
+		static int isLocaleLower(dchar_t c) { return isLower(c); }
+		static int toLower(dchar_t c) { return isUpper(c) ? towlower(c) : c; }
+		static int toLower(dchar_t* p) { return toLower(*p); }
+		static int toUpper(dchar_t c) { return isLower(c) ? towupper(c) : c; }
+		static dchar_t* dup(dchar_t* p) { return ._wcsdup(p); }	// BUG: out of memory?
+		
+		static dchar_t* dup(char* p)
+		{
+			assert(false);
+		}
+		
+		static dchar_t* chr(dchar_t *p, uint c) { return wcschr(p, cast(dchar_t)c); }
+		static dchar_t* rchr(dchar_t *p, uint c) { return wcsrchr(p, cast(dchar_t)c); }
+
+		static dchar_t* memchr(dchar_t* p, int c, int count)
+		{
+			assert(false);
+		}
+		
+		static dchar_t* cpy(dchar_t* s1, dchar_t* s2) { return wcscpy(s1, s2); }
+		static dchar_t* str(dchar_t* s1, dchar_t* s2) { return wcsstr(s1, s2); }
+		
+		static hash_t calcHash(const(dchar_t)* str, size_t len)
+		{
+			assert(false);
+		}
+
+		// Case insensitive versions
+		static int icmp(dchar_t* s1, dchar_t* s2) { return wcsicmp(s1, s2); }
+		static int memicmp(const(dchar_t)* s1, const(dchar_t)* s2, int nchars) { return .wcsnicmp(s1, s2, nchars); }
+		
+		static hash_t icalcHash(const(dchar_t)* str, size_t len)
+		{
+			assert(false);
+		}
+	}
+} else version (UTF8) {
+	alias char dchar_t;
+	
+	struct Dchar
+	{
+		static char mblen[256];
+
+		static dchar_t* inc(dchar_t* p) { return p + mblen[*p & 0xFF]; }
+
+		static dchar_t* dec(dchar_t* pstart, dchar_t* p)
+		{
+			assert(false);
+		}
+
+		static int len(const(dchar_t)* p) { return strlen(p); }
+
+		static int get(dchar_t* p)
+		{
+			assert(false);
+		}
+
+		static int getprev(dchar_t* pstart, dchar_t* p)
+		{
+			return *dec(pstart, p) & 0xFF;
+		}
+
+		static dchar_t* put(dchar_t* p, uint c)
+		{
+			assert(false);
+		}
+
+		static int cmp(dchar_t* s1, dchar_t* s2) { return strcmp(s1, s2); }
+
+		static int memcmp(const(dchar_t)* s1, const(dchar_t)* s2, int nchars) { return .memcmp(s1, s2, nchars); }
+
+		static int isDigit(dchar_t c) { return '0' <= c && c <= '9'; }
+
+		static int isAlpha(dchar_t c) { return c <= 0x7F ? isalpha(c) : 0; }
+
+		static int isUpper(dchar_t c) { return c <= 0x7F ? isupper(c) : 0; }
+
+		static int isLower(dchar_t c) { return c <= 0x7F ? islower(c) : 0; }
+
+		static int isLocaleUpper(dchar_t c) { return isUpper(c); }
+
+		static int isLocaleLower(dchar_t c) { return isLower(c); }
+
+		static int toLower(dchar_t c) { return isUpper(c) ? tolower(c) : c; }
+
+		static int toLower(dchar_t* p) { return toLower(*p); }
+
+		static int toUpper(dchar_t c) { return isLower(c) ? toupper(c) : c; }
+
+		static dchar_t* dup(dchar_t* p) { return .strdup(p); }	// BUG: out of memory?
+
+		static dchar_t* chr(dchar_t* p, int c) { return strchr(p, c); }
+
+		static dchar_t* rchr(dchar_t* p, int c) { return strrchr(p, c); }
+
+		static dchar_t* memchr(dchar_t* p, int c, int count)
+		{
+			return cast(dchar_t*).memchr(p, c, count);
+		}
+		
+		static dchar_t* cpy(dchar_t* s1, dchar_t* s2) { return strcpy(s1, s2); }
+		
+		static dchar_t* str(dchar_t* s1, dchar_t* s2) { return strstr(s1, s2); }
+		
+		static hash_t calcHash(const(dchar_t)* str, size_t len)
+		{
+			assert(false);
+		}
+
+		// Case insensitive versions
+		static int icmp(dchar_t* s1, dchar_t* s2) { return _mbsicmp(s1, s2); }
+		
+		static int memicmp(const(dchar_t)* s1, const(dchar_t)* s2, int nchars) { return ._mbsnicmp(s1, s2, nchars); }
+	}
+} else {
+	alias char dchar_t;
+	
+	struct Dchar
+	{
+		static dchar_t* inc(dchar_t* p) { return p + 1; }
+		
+		static dchar_t* dec(dchar_t* pstart, dchar_t* p) { return p - 1; }
+		
+		static int len(const(dchar_t)* p) { return strlen(p); }
+		
+		static int get(dchar_t* p) { return *p & 0xFF; }
+		
+		static int getprev(dchar_t* pstart, dchar_t* p) { return p[-1] & 0xFF; }
+		
+		static dchar_t* put(dchar_t* p, uint c) { *p = cast(dchar_t)c; return p + 1; }
+		
+		static int cmp(dchar_t* s1, dchar_t* s2) { return strcmp(s1, s2); }
+		
+		static int memcmp(const(dchar_t)* s1, const(dchar_t)* s2, int nchars) { return .memcmp(s1, s2, nchars); }
+		
+		static int isDigit(dchar_t c) { return '0' <= c && c <= '9'; }
+	
+version (GCC_SAFE_DMD) {
+} else {
+		static int isAlpha(dchar_t c) { return isalpha(c); }
+		
+		static int isUpper(dchar_t c) { return isupper(c); }
+		
+		static int isLower(dchar_t c) { return islower(c); }
+		
+		static int isLocaleUpper(dchar_t c) { return isupper(c); }
+		
+		static int isLocaleLower(dchar_t c) { return islower(c); }
+		
+		static int toLower(dchar_t c) { return isupper(c) ? tolower(c) : c; }
+		
+		static int toLower(dchar_t* p) { return toLower(*p); }
+		
+		static int toUpper(dchar_t c) { return islower(c) ? toupper(c) : c; }
+		
+		static dchar_t* dup(dchar_t* p) { /*return .strdup(p);*/ assert(false); }	// BUG: out of memory?
+}
+		static dchar_t* chr(dchar_t *p, int c) { return strchr(p, c); }
+		
+		static dchar_t* rchr(dchar_t *p, int c) { return strrchr(p, c); }
+		
+		static dchar_t* memchr(dchar_t *p, int c, int count)
+		{
+			return cast(dchar_t*).memchr(p, c, count);
+		}
+		
+		static dchar_t* cpy(dchar_t* s1, dchar_t* s2) { return strcpy(s1, s2); }
+		
+		static dchar_t* str(dchar_t* s1, dchar_t* s2) { return strstr(s1, s2); }
+		
+		static hash_t calcHash(const(dchar_t)* str, size_t len)
+		{
+			hash_t hash = 0;
+
+			while (1)
+			{
+				switch (len)
+				{
+					case 0:
+						return hash;
+
+					case 1:
+						hash *= 37;
+						hash += *cast(const(uint8_t)*)str;
+						return hash;
+
+					case 2:
+						hash *= 37;
+version (__I86__) {
+					hash += *cast(const(uint16_t)*)str;
+} else {
+					hash += str[0] * 256 + str[1];
+}
+					return hash;
+
+					case 3:
+					hash *= 37;
+version (__I86__) {
+					hash += (*cast(const(uint16_t)*)str << 8) +
+						(cast(const(uint8_t)*)str)[2];
+} else {
+					hash += (str[0] * 256 + str[1]) * 256 + str[2];
+}
+					return hash;
+
+					default:
+					hash *= 37;
+version (__I86__) {
+					hash += *cast(const(uint32_t)*)str;
+} else {
+					hash += ((str[0] * 256 + str[1]) * 256 + str[2]) * 256 + str[3];
+}
+					str += 4;
+					len -= 4;
+					break;
+				}
+			}
+			
+			assert(false);
+		}
+
+		// Case insensitive versions
+version (__GNUC__) {
+		static int icmp(dchar_t* s1, dchar_t* s2) { return strcasecmp(s1, s2); }
+} else {
+		static int icmp(dchar_t* s1, dchar_t* s2) { /*return stricmp(s1, s2);*/ assert(false); }
+}
+		static int memicmp(const(dchar_t)* s1, const(dchar_t)* s2, int nchars) { /*return .memicmp(s1, s2, nchars);*/ assert(false); }
+		static hash_t icalcHash(const(dchar_t)* str, size_t len)
+		{
+			assert(false);
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DebugCondition.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,70 @@
+module dmd.DebugCondition;
+
+import dmd.DVCondition;
+import dmd.Module;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Array;
+import dmd.String;
+import dmd.Global;
+
+import dmd.condition.util.findCondition;
+
+class DebugCondition : DVCondition
+{
+    static void setGlobalLevel(uint level)
+	{
+		assert(false);
+	}
+	
+    static void addGlobalIdent(const(char)* ident)
+	{
+		assert(false);
+	}
+	
+    static void addPredefinedGlobalIdent(const(char)* ident)
+	{
+		assert(false);
+	}
+
+    this(Module mod, uint level, Identifier ident)
+	{
+		super(mod, level, ident);
+	}
+
+    bool include(Scope sc, ScopeDsymbol s)
+	{
+		//printf("DebugCondition::include() level = %d, debuglevel = %d\n", level, global.params.debuglevel);
+		if (inc == 0)
+		{
+			inc = 2;
+
+			if (ident)
+			{
+				if (findCondition(mod.debugids, ident))
+					inc = 1;
+				else if (findCondition(global.params.debugids, ident))
+					inc = 1;
+				else
+				{	
+					if (!mod.debugidsNot)
+						mod.debugidsNot = new Array();
+
+					mod.debugidsNot.push(cast(void*)new String(ident.toChars()));
+				}
+			}
+			else if (level <= global.params.debuglevel || level <= mod.debuglevel)
+				inc = 1;
+		}
+
+		return (inc == 1);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DebugSymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,49 @@
+module dmd.DebugSymbol;
+
+import dmd.Dsymbol;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+
+class DebugSymbol : Dsymbol
+{
+    uint level;
+
+    this(Loc loc, Identifier ident)
+	{
+		assert(false);
+	}
+
+    this(Loc loc, uint level)
+	{
+		assert(false);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+
+    bool addMember(Scope sc, ScopeDsymbol s, int memnum)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Declaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,311 @@
+module dmd.Declaration;
+
+import dmd.Dsymbol;
+import dmd.Type;
+import dmd.PROT;
+import dmd.LINK;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.STC;
+import dmd.FuncDeclaration;
+import dmd.VarDeclaration;
+import dmd.OutBuffer;
+
+import std.stdio : writef;
+
+import core.stdc.ctype;
+import core.stdc.stdio : sprintf;
+
+string mangle(Declaration sthis)
+{
+	scope OutBuffer buf = new OutBuffer();
+
+    string id;
+    Dsymbol s = sthis;
+
+    //printf(".mangle(%s)\n", sthis.toChars());
+    do
+    {
+		//printf("mangle: s = %p, '%s', parent = %p\n", s, s.toChars(), s.parent);
+		if (s.ident)
+		{
+			FuncDeclaration fd = s.isFuncDeclaration();
+			if (s !is sthis && fd)
+			{
+				id = mangle(fd);
+				buf.prependstring(id);
+				goto L1;
+			}
+			else
+			{
+				id = s.ident.toChars();
+				int len = id.length;
+				char tmp[len.sizeof * 3 + 1];
+				buf.prependstring(id);
+				len = sprintf(tmp.ptr, "%d".ptr, len);
+				buf.prependstring(tmp[0..len]);
+			}
+		}
+		else
+			buf.prependstring("0");
+		s = s.parent;
+    } while (s);
+
+//    buf.prependstring("_D");
+L1:
+    //printf("deco = '%s'\n", sthis.type.deco ? sthis.type.deco : "null");
+    //printf("sthis.type = %s\n", sthis.type.toChars());
+    FuncDeclaration fd = sthis.isFuncDeclaration();
+    if (fd && (fd.needThis() || fd.isNested()))
+		buf.writeByte(Type.needThisPrefix());
+    if (sthis.type.deco)
+		buf.writestring(sthis.type.deco);
+    else
+    {
+debug {
+		if (!fd.inferRetType)
+			writef("%s\n", fd.toChars());
+}
+		assert(fd.inferRetType);
+    }
+
+    id = buf.extractString();
+    return id;
+}
+
+class Declaration : Dsymbol
+{
+    Type type;
+    Type originalType;		// before semantic analysis
+    STC storage_class = STC.STCundefined;
+    PROT protection = PROT.PROTundefined;
+    LINK linkage = LINK.LINKdefault;
+    int inuse;			// used to detect cycles
+
+    this(Identifier id)
+	{
+		super(id);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    uint size(Loc loc)
+	{
+		assert(false);
+	}
+	
+	/*************************************
+	 * Check to see if declaration can be modified in this context (sc).
+	 * Issue error if not.
+	 */
+    void checkModify(Loc loc, Scope sc, Type t)
+	{
+		if (sc.incontract && isParameter())
+			error(loc, "cannot modify parameter '%s' in contract", toChars());
+
+		if (isCtorinit())
+		{	
+			// It's only modifiable if inside the right constructor
+			Dsymbol s = sc.func;
+			while (true)
+			{
+				FuncDeclaration fd = null;
+				if (s)
+					fd = s.isFuncDeclaration();
+				if (fd && ((fd.isCtorDeclaration() && storage_class & STC.STCfield) || 
+					(fd.isStaticCtorDeclaration() && !(storage_class & STC.STCfield))) &&
+					fd.toParent() == toParent()
+				   )
+				{
+					VarDeclaration v = isVarDeclaration();
+					assert(v);
+					v.ctorinit = 1;
+					//printf("setting ctorinit\n");
+				}
+				else
+				{
+					if (s)
+					{   
+						s = s.toParent2();
+						continue;
+					}
+					else
+					{
+						string p = isStatic() ? "static " : "";
+						error(loc, "can only initialize %sconst %s inside %sconstructor", p, toChars(), p);
+					}
+				}
+				break;
+			}
+		}
+		else
+		{
+			VarDeclaration v = isVarDeclaration();
+			if (v && v.canassign == 0)
+			{
+				string p = null;
+				if (isConst())
+					p = "const";
+				else if (isInvariant())
+					p = "immutable";
+				else if (storage_class & STC.STCmanifest)
+					p = "enum";
+				else if (!t.isAssignable())
+					p = "struct with immutable members";
+				if (p)
+				{	
+					error(loc, "cannot modify %s", p);
+				}
+			}
+		}
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    string mangle()
+	out (result)
+	{
+		try
+		{
+			int len = result.length;
+
+			assert(len > 0);
+			//printf("mangle: '%s' => '%s'\n", toChars(), result);
+			for (int i = 0; i < len; i++)
+			{
+				assert(result[i] == '_' || result[i] == '@' || isalnum(result[i]) || result[i] & 0x80);
+			}
+		} catch {
+			writef("Incorrect mangle: '%s'\n", result);
+			assert(false);
+		}
+	}
+	body
+	{
+		//writef("Declaration.mangle(this = %p, '%s', parent = '%s', linkage = %d)\n", this, toChars(), parent ? parent.toChars() : "null", linkage);
+		if (!parent || parent.isModule() || linkage == LINK.LINKcpp) // if at global scope
+		{
+			// If it's not a D declaration, no mangling
+			switch (linkage)
+			{
+			case LINK.LINKd:
+				break;
+
+			case LINK.LINKc:
+			case LINK.LINKwindows:
+			case LINK.LINKpascal:
+				return ident.toChars();
+
+			case LINK.LINKcpp:
+version (CPP_MANGLE) {
+				return cpp_mangle(this);
+} else {
+				// Windows C++ mangling is done by C++ back end
+				return ident.toChars();
+}
+
+			case LINK.LINKdefault:
+				assert(false);
+				error("forward declaration");
+				return ident.toChars();
+
+			default:
+				writef("'%s', linkage = %d\n", toChars(), linkage);
+				assert(0);
+			}
+		}
+
+		string p = .mangle(this);
+		scope OutBuffer buf = new OutBuffer();
+		buf.writestring("_D");
+		buf.writestring(p);
+		p = buf.toChars();
+		buf.data = null;
+		//writef("Declaration.mangle(this = %p, '%s', parent = '%s', linkage = %d) = %s\n", this, toChars(), parent ? parent.toChars() : "null", linkage, p);
+		return p;
+	}
+	
+    int isStatic() { return storage_class & STC.STCstatic; }
+	
+    bool isStaticConstructor()
+	{
+		return false;
+	}
+	
+    bool isStaticDestructor()
+	{
+		return false;
+	}
+	
+    bool isDelete()
+	{
+		return false;
+	}
+	
+    bool isDataseg()
+	{
+		return false;
+	}
+	
+    bool isThreadlocal()
+	{
+		assert(false);
+	}
+	
+    bool isCodeseg()
+	{
+		return false;
+	}
+	
+    int isCtorinit()     { return storage_class & STC.STCctorinit; }
+    
+	int isFinal()        { return storage_class & STC.STCfinal; }
+    
+	bool isAbstract()     { return (storage_class & STC.STCabstract)  != 0; }
+    
+	bool isConst()        { return (storage_class & STC.STCconst) != 0; }
+    
+	int isInvariant()    { return storage_class & STC.STCinvariant; }
+    
+	int isAuto()         { return storage_class & STC.STCauto; }
+    
+	int isScope()        { return storage_class & (STC.STCscope | STC.STCauto); }
+    
+	int isSynchronized() { return storage_class & STC.STCsynchronized; }
+    
+	int isParameter()    { return storage_class & STC.STCparameter; }
+    
+	bool isDeprecated()   { return (storage_class & STC.STCdeprecated)  != 0; }
+    
+	int isOverride()     { return storage_class & STC.STCoverride; }
+
+    int isIn()    { return storage_class & STC.STCin; }
+    
+	int isOut()   { return storage_class & STC.STCout; }
+    
+	int isRef()   { return storage_class & STC.STCref; }
+
+    PROT prot()
+	{
+		return protection;
+	}
+
+    Declaration isDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DeclarationExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,291 @@
+module dmd.DeclarationExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.ExpInitializer;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.TupleDeclaration;
+import dmd.InlineScanState;
+import dmd.Dsymbol;
+import dmd.AttribDeclaration;
+import dmd.VarDeclaration;
+import dmd.Global;
+import dmd.TOK;
+import dmd.VoidInitializer;
+import dmd.Type;
+import dmd.codegen.Util;
+
+// Declaration of a symbol
+
+class DeclarationExp : Expression
+{
+	Dsymbol declaration;
+
+	this(Loc loc, Dsymbol declaration)
+	{
+		super(loc, TOK.TOKdeclaration, DeclarationExp.sizeof);
+		this.declaration = declaration;
+	}
+
+	Expression syntaxCopy()
+	{
+		return new DeclarationExp(loc, declaration.syntaxCopy(null));
+	}
+
+	Expression semantic(Scope sc)
+	{
+		if (type)
+			return this;
+
+version (LOGSEMANTIC) {
+		printf("DeclarationExp.semantic() %s\n", toChars());
+}
+
+		/* This is here to support extern(linkage) declaration,
+		 * where the extern(linkage) winds up being an AttribDeclaration
+		 * wrapper.
+		 */
+		Dsymbol s = declaration;
+
+		AttribDeclaration ad = declaration.isAttribDeclaration();
+		if (ad)
+		{
+			if (ad.decl && ad.decl.dim == 1)
+				s = cast(Dsymbol)ad.decl.data[0];
+		}
+
+		if (s.isVarDeclaration())
+		{	
+			// Do semantic() on initializer first, so:
+			//	int a = a;
+			// will be illegal.
+			declaration.semantic(sc);
+			s.parent = sc.parent;
+		}
+
+		//printf("inserting '%s' %p into sc = %p\n", s.toChars(), s, sc);
+		// Insert into both local scope and function scope.
+		// Must be unique in both.
+		if (s.ident)
+		{
+			if (!sc.insert(s))
+				error("declaration %s is already defined", s.toPrettyChars());
+			else if (sc.func)
+			{   
+				VarDeclaration v = s.isVarDeclaration();
+				if (s.isFuncDeclaration() && !sc.func.localsymtab.insert(s))
+					error("declaration %s is already defined in another scope in %s", s.toPrettyChars(), sc.func.toChars());
+				else if (!global.params.useDeprecated)
+				{	
+					// Disallow shadowing
+
+					for (Scope scx = sc.enclosing; scx && scx.func is sc.func; scx = scx.enclosing)
+					{   
+						Dsymbol s2;
+
+						if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s !is s2)
+						{
+							error("shadowing declaration %s is deprecated", s.toPrettyChars());
+						}
+					}
+				}
+			}
+		}
+		if (!s.isVarDeclaration())
+		{
+			declaration.semantic(sc);
+			s.parent = sc.parent;
+		}
+		if (!global.errors)
+		{
+			declaration.semantic2(sc);
+			if (!global.errors)
+			{
+				declaration.semantic3(sc);
+
+				if (!global.errors && global.params.useInline)
+					declaration.inlineScan();
+			}
+		}
+
+		type = Type.tvoid;
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		return true;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		declaration.toCBuffer(buf, hgs);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		//printf("DeclarationExp::toElem() %s\n", toChars());
+		elem* e = Dsymbol_toElem(declaration, irs);
+		return e;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		VarDeclaration v = declaration.isVarDeclaration();
+		if (v && v.init)
+		{	
+			ExpInitializer ie = v.init.isExpInitializer();
+			return ie && ie.exp.canThrow();
+		}
+
+		return false;
+	}
+}
+	int inlineCost(InlineCostState* ics)
+	{
+		int cost = 0;
+		VarDeclaration vd;
+
+		//printf("DeclarationExp.inlineCost()\n");
+		vd = declaration.isVarDeclaration();
+		if (vd)
+		{
+			TupleDeclaration td = vd.toAlias().isTupleDeclaration();
+			if (td)
+			{
+		static if (true) {
+				return COST_MAX;	// finish DeclarationExp.doInline
+		} else {
+				for (size_t i = 0; i < td.objects.dim; i++)
+				{
+				Object o = cast(Object)td.objects.data[i];
+				Expression eo = cast(Expression)o;
+				if (eo is null)
+					return COST_MAX;
+
+				if (eo.op != TOKdsymbol)
+					return COST_MAX;
+				}
+
+				return td.objects.dim;
+		}
+			}
+			if (!ics.hdrscan && vd.isDataseg())
+				return COST_MAX;
+
+			cost += 1;
+
+			// Scan initializer (vd.init)
+			if (vd.init)
+			{
+				ExpInitializer ie = vd.init.isExpInitializer();
+
+				if (ie)
+				{
+					cost += ie.exp.inlineCost(ics);
+				}
+			}
+		}
+
+		// These can contain functions, which when copied, get output twice.
+		if (declaration.isStructDeclaration() ||
+			declaration.isClassDeclaration() ||
+			declaration.isFuncDeclaration() ||
+			declaration.isTypedefDeclaration() ||
+			declaration.isTemplateMixin()
+		)
+			return COST_MAX;
+
+		//printf("DeclarationExp.inlineCost('%s')\n", toChars());
+		return cost;
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		DeclarationExp de = cast(DeclarationExp)copy();
+		VarDeclaration vd;
+
+		//printf("DeclarationExp.doInline(%s)\n", toChars());
+		vd = declaration.isVarDeclaration();
+		if (vd)
+		{
+	static if (false) {
+		// Need to figure this out before inlining can work for tuples
+		TupleDeclaration td = vd.toAlias().isTupleDeclaration();
+		if (td)
+		{
+			for (size_t i = 0; i < td.objects.dim; i++)
+			{   
+				DsymbolExp se = cast(DsymbolExp)td.objects.data[i];
+				assert(se.op == TOKdsymbol);
+				se.s;
+			}
+			return st.objects.dim;
+		}
+	}
+		if (vd.isStatic())
+		{
+			;
+		}
+		else
+		{
+			VarDeclaration vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init);
+			
+			///*vto = *vd;
+			memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length);
+			
+			vto.parent = ids.parent;
+			vto.csym = null;
+			vto.isym = null;
+
+			ids.from.push(cast(void*)vd);
+			ids.to.push(cast(void*)vto);
+
+			if (vd.init)
+			{
+				if (vd.init.isVoidInitializer())
+				{
+					vto.init = new VoidInitializer(vd.init.loc);
+				}
+				else
+				{
+					Expression e = vd.init.toExpression();
+					assert(e);
+					vto.init = new ExpInitializer(e.loc, e.doInline(ids));
+				}
+			}
+			de.declaration = vto;
+		}
+		}
+		/* This needs work, like DeclarationExp.toElem(), if we are
+		 * to handle TemplateMixin's. For now, we just don't inline them.
+		 */
+		return de;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		//printf("DeclarationExp.inlineScan()\n");
+		scanVar(declaration, iss);
+		return this;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DeclarationStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,92 @@
+module dmd.DeclarationStatement;
+
+import dmd.Loc;
+import dmd.ExpStatement;
+import dmd.Dsymbol;
+import dmd.Expression;
+import dmd.Statement;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.DeclarationExp;
+import dmd.TOK;
+import dmd.VarDeclaration;
+
+class DeclarationStatement : ExpStatement
+{
+    // Doing declarations as an expression, rather than a statement,
+    // makes inlining functions much easier.
+
+    this(Loc loc, Dsymbol declaration)
+	{
+		super(loc, new DeclarationExp(loc, declaration));
+	}
+	
+    this(Loc loc, Expression exp)
+	{
+		super(loc, exp);
+	}
+	
+    Statement syntaxCopy()
+	{
+		DeclarationStatement ds = new DeclarationStatement(loc, exp.syntaxCopy());
+		return ds;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		exp.toCBuffer(buf, hgs);
+	}
+	
+    void scopeCode(Scope sc, Statement* sentry, Statement* sexception, Statement* sfinally)
+	{
+		//printf("DeclarationStatement.scopeCode()\n");
+		//print();
+
+		*sentry = null;
+		*sexception = null;
+		*sfinally = null;
+
+		if (exp)
+		{
+			if (exp.op == TOK.TOKdeclaration)
+			{
+				DeclarationExp de = cast(DeclarationExp)exp;
+				VarDeclaration v = de.declaration.isVarDeclaration();
+				if (v)
+				{	
+					Expression e;
+
+					e = v.callAutoDtor(sc);
+					if (e)
+					{
+						//printf("dtor is: "); e.print();
+static if (false) {
+						if (v.type.toBasetype().ty == Tstruct)
+						{	
+							/* Need a 'gate' to turn on/off destruction,
+							 * in case v gets moved elsewhere.
+							 */
+							Identifier id = Lexer.uniqueId("__runDtor");
+							ExpInitializer ie = new ExpInitializer(loc, new IntegerExp(1));
+							VarDeclaration rd = new VarDeclaration(loc, Type.tint32, id, ie);
+							*sentry = new DeclarationStatement(loc, rd);
+							v.rundtor = rd;
+
+							/* Rewrite e as:
+							 *  rundtor && e
+							 */
+							Expression ve = new VarExp(loc, v.rundtor);
+							e = new AndAndExp(loc, ve, e);
+							e.type = Type.tbool;
+						}
+}
+						*sfinally = new ExpStatement(loc, e);
+					}
+				}
+			}
+		}
+	}
+
+    DeclarationStatement isDeclarationStatement() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DefaultInitExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,30 @@
+module dmd.DefaultInitExp;
+
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class DefaultInitExp : Expression
+{
+	TOK subop;
+
+	this(Loc loc, TOK subop, int size)
+	{
+		assert(false);
+		super(loc, subop, size);
+	}
+
+	Expression resolve(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DefaultStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,106 @@
+module dmd.DefaultStatement;
+
+import dmd.Statement;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.BE;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.Blockx;
+import dmd.backend.block;
+import dmd.backend.BC;
+
+class DefaultStatement : Statement
+{
+    Statement statement;
+version (IN_GCC) {
+    block* cblock = null;	// back end: label for the block
+}
+
+    this(Loc loc, Statement s)
+	{
+		super(loc);
+		this.statement = s;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("DefaultStatement.semantic()\n");
+		if (sc.sw)
+		{
+			if (sc.sw.sdefault)
+			{
+				error("switch statement already has a default");
+			}
+			sc.sw.sdefault = this;
+
+			if (sc.sw.tf !is sc.tf)
+				error("switch and default are in different finally blocks");
+
+			if (sc.sw.isFinal)
+				error("default statement not allowed in final switch statement");
+		}
+		else
+			error("default not in switch statement");
+		statement = statement.semantic(sc);
+		return this;
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		return statement.blockExit();
+	}
+	
+    bool comeFrom()
+	{
+		return true;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (statement)
+			statement = statement.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		Blockx* blx = irs.blx;
+		block* bcase = blx.curblock;
+		block* bdefault = irs.getDefaultBlock();
+		block_next(blx,BCgoto,bdefault);
+		list_append(&bcase.Bsucc,blx.curblock);
+		if (blx.tryblock != irs.getSwitchBlock().Btry)
+			error("default cannot be in different try block level from switch");
+		incUsage(irs, loc);
+		if (statement)
+			statement.toIR(irs);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DelegateExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,218 @@
+module dmd.DelegateExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.AggregateDeclaration;
+import dmd.UnaExp;
+import dmd.TypeDelegate;
+import dmd.FuncDeclaration;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.TY;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.PREC;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+import dmd.expression.Util;
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.Symbol;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+
+class DelegateExp : UnaExp
+{
+	FuncDeclaration func;
+	int hasOverloads;
+
+	this(Loc loc, Expression e, FuncDeclaration f, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKdelegate, DelegateExp.sizeof, e);
+		this.func = f;
+		this.hasOverloads = hasOverloads;
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("DelegateExp.semantic('%s')\n", toChars());
+	}
+		if (!type)
+		{
+			e1 = e1.semantic(sc);
+			type = new TypeDelegate(func.type);
+			type = type.semantic(loc, sc);
+			AggregateDeclaration ad = func.toParent().isAggregateDeclaration();
+			if (func.needThis())
+				e1 = getRightThis(loc, sc, ad, e1, func);
+		}
+		return this;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+	static if (false) {
+		printf("DelegateExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
+			toChars(), type.toChars(), t.toChars());
+	}
+		MATCH result;
+
+		result = type.implicitConvTo(t);
+
+		if (result == MATCHnomatch)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+			FuncDeclaration f;
+
+			t = t.toBasetype();
+			if (type.ty == Tdelegate && type.nextOf().ty == Tfunction &&
+				t.ty == Tdelegate && t.nextOf().ty == Tfunction)
+			{
+				if (func && func.overloadExactMatch(t.nextOf()))
+					result = MATCHexact;
+			}
+		}
+		return result;
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	static if (false) {
+		printf("DelegateExp.castTo(this=%s, type=%s, t=%s)\n",
+			toChars(), type.toChars(), t.toChars());
+	}
+		static string msg = "cannot form delegate due to covariant return type";
+
+		Expression e = this;
+		Type tb = t.toBasetype();
+		Type typeb = type.toBasetype();
+		if (tb != typeb)
+		{
+			// Look for delegates to functions where the functions are overloaded.
+			FuncDeclaration f;
+
+			if (typeb.ty == Tdelegate && typeb.nextOf().ty == Tfunction &&
+				tb.ty == Tdelegate && tb.nextOf().ty == Tfunction)
+			{
+				if (func)
+				{
+					f = func.overloadExactMatch(tb.nextOf());
+					if (f)
+					{   
+						int offset;
+						if (f.tintro && f.tintro.nextOf().isBaseOf(f.type.nextOf(), &offset) && offset)
+							error("%s", msg);
+						f.tookAddressOf++;
+						e = new DelegateExp(loc, e1, f);
+						e.type = t;
+						return e;
+					}
+					if (func.tintro)
+						error("%s", msg);
+				}
+			}
+			e = Expression.castTo(sc, t);
+		}
+		else
+		{	
+			int offset;
+
+			func.tookAddressOf++;
+			if (func.tintro && func.tintro.nextOf().isBaseOf(func.type.nextOf(), &offset) && offset)
+				error("%s", msg);
+			e = copy();
+			e.type = t;
+		}
+		return e;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writeByte('&');
+		if (!func.isNested())
+		{
+			expToCBuffer(buf, hgs, e1, PREC.PREC_primary);
+			buf.writeByte('.');
+		}
+		buf.writestring(func.toChars());
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	elem* 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 = addressElem(ethis, e1.type);
+
+			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
+				assert(ethis);
+				ep = el_same(&ethis);
+				ep = el_una(OPind, TYnptr, ep);
+				uint 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;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DeleteDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,65 @@
+module dmd.DeleteDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+
+class DeleteDeclaration : FuncDeclaration
+{
+	Arguments arguments;
+
+    this(Loc loc, Loc endloc, Arguments arguments)
+	{
+		assert(false);
+		super(loc, endloc, null, STC.init, null);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+
+    bool isDelete()
+	{
+		assert(false);
+	}
+	
+    bool isVirtual()
+	{
+		assert(false);
+	}
+	
+    bool addPreInvariant()
+	{
+		assert(false);
+	}
+	
+    bool addPostInvariant()
+	{
+		assert(false);
+	}
+	
+version (_DH) {
+    DeleteDeclaration isDeleteDeclaration() { return this; }
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DeleteExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,273 @@
+module dmd.DeleteExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.Type;
+import dmd.IndexExp;
+import dmd.Global;
+import dmd.VarExp;
+import dmd.Identifier;
+import dmd.StructDeclaration;
+import dmd.Lexer;
+import dmd.FuncDeclaration;
+import dmd.TypeStruct;
+import dmd.CallExp;
+import dmd.DotVarExp;
+import dmd.DeclarationExp;
+import dmd.ExpInitializer;
+import dmd.VarDeclaration;
+import dmd.TypePointer;
+import dmd.ClassDeclaration;
+import dmd.TypeClass;
+import dmd.TY;
+import dmd.TOK;
+import dmd.TypeAArray;
+import dmd.TypeSArray;
+
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.RTLSYM;
+import dmd.backend.mTY;
+import dmd.backend.Symbol;
+import dmd.backend.TYM;
+
+class DeleteExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKdelete, DeleteExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Type tb;
+
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		e1 = e1.toLvalue(sc, null);
+		type = Type.tvoid;
+
+		tb = e1.type.toBasetype();
+		switch (tb.ty)
+		{	
+			case Tclass:
+			{   
+				TypeClass tc = cast(TypeClass)tb;
+				ClassDeclaration cd = tc.sym;
+
+				if (cd.isCOMinterface())
+				{	/* Because COM classes are deleted by IUnknown.Release()
+					 */
+					error("cannot delete instance of COM interface %s", cd.toChars());
+				}
+				break;
+			}
+			case Tpointer:
+				tb = (cast(TypePointer)tb).next.toBasetype();
+				if (tb.ty == Tstruct)
+				{
+					TypeStruct ts = cast(TypeStruct)tb;
+					StructDeclaration sd = ts.sym;
+					FuncDeclaration f = sd.aggDelete;
+					FuncDeclaration fd = sd.dtor;
+
+					if (!f && !fd)
+						break;
+
+					/* Construct:
+					 *	ea = copy e1 to a tmp to do side effects only once
+					 *	eb = call destructor
+					 *	ec = call deallocator
+					 */
+					Expression ea = null;
+					Expression eb = null;
+					Expression ec = null;
+					VarDeclaration v;
+
+					if (fd && f)
+					{   
+						Identifier id = Lexer.idPool("__tmp");
+						v = new VarDeclaration(loc, e1.type, id, new ExpInitializer(loc, e1));
+						v.semantic(sc);
+						v.parent = sc.parent;
+						ea = new DeclarationExp(loc, v);
+						ea.type = v.type;
+					}
+
+					if (fd)
+					{   
+						Expression e = ea ? new VarExp(loc, v) : e1;
+						e = new DotVarExp(Loc(0), e, fd, 0);
+						eb = new CallExp(loc, e);
+						eb = eb.semantic(sc);
+					}
+
+					if (f)
+					{
+						Type tpv = Type.tvoid.pointerTo();
+						Expression e = ea ? new VarExp(loc, v) : e1.castTo(sc, tpv);
+						e = new CallExp(loc, new VarExp(loc, f), e);
+						ec = e.semantic(sc);
+					}
+					ea = combine(ea, eb);
+					ea = combine(ea, ec);
+					assert(ea);
+					return ea;
+				}
+				break;
+
+			case Tarray:
+				/* BUG: look for deleting arrays of structs with dtors.
+				 */
+				break;
+
+			default:
+				if (e1.op == TOKindex)
+				{
+					IndexExp ae = cast(IndexExp)e1;
+					Type tb1 = ae.e1.type.toBasetype();
+					if (tb1.ty == Taarray)
+						break;
+				}
+				error("cannot delete type %s", e1.type.toChars());
+				break;
+		}
+		
+		if (e1.op == TOKindex)
+		{
+			IndexExp ae = cast(IndexExp)e1;
+			Type tb1 = ae.e1.type.toBasetype();
+			if (tb1.ty == Taarray)
+			{   
+				if (!global.params.useDeprecated)
+					error("delete aa[key] deprecated, use aa.remove(key)");
+			}
+		}
+
+		return this;
+	}
+
+	Expression checkToBoolean()
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		return true;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		int rtl;
+		Type tb;
+
+		//printf("DeleteExp.toElem()\n");
+		if (e1.op == TOKindex)
+		{
+			IndexExp ae = cast(IndexExp)e1;
+			tb = ae.e1.type.toBasetype();
+			if (tb.ty == Taarray)
+			{
+				TypeAArray taa = cast(TypeAArray)tb;
+				elem* ea = ae.e1.toElem(irs);
+				elem* ekey = ae.e2.toElem(irs);
+				elem* ep;
+				elem* keyti;
+
+				if (tybasic(ekey.Ety) == TYstruct)
+				{
+					ekey = el_una(OPstrpar, TYstruct, ekey);
+					ekey.Enumbytes = ekey.E1.Enumbytes;
+					assert(ekey.Enumbytes);
+				}
+
+				Symbol *s = taa.aaGetSymbol("Del", 0);
+				keyti = taa.index.getInternalTypeInfo(null).toElem(irs);
+				ep = el_params(ekey, keyti, ea, null);
+				e = el_bin(OPcall, TYnptr, el_var(s), ep);
+				goto Lret;
+			}
+		}
+		//e1.type.print();
+		e = e1.toElem(irs);
+		tb = e1.type.toBasetype();
+		switch (tb.ty)
+		{
+			case Tarray:
+			{   
+				e = addressElem(e, e1.type);
+				rtl = RTLSYM_DELARRAYT;
+
+				/* See if we need to run destructors on the array contents
+				 */
+				elem *et = null;
+				Type tv = tb.nextOf().toBasetype();
+				while (tv.ty == Tsarray)
+				{   
+					TypeSArray ta = cast(TypeSArray)tv;
+					tv = tv.nextOf().toBasetype();
+				}
+				if (tv.ty == Tstruct)
+				{   
+					TypeStruct ts = cast(TypeStruct)tv;
+					StructDeclaration sd = ts.sym;
+					if (sd.dtor)
+						et = tb.nextOf().getTypeInfo(null).toElem(irs);
+				}
+				if (!et)				// if no destructors needed
+					et = el_long(TYnptr, 0);	// pass null for TypeInfo
+				e = el_params(et, e, null);
+				// call _d_delarray_t(e, et);
+				e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
+				goto Lret;
+			}
+			case Tclass:
+				if (e1.op == TOKvar)
+				{	
+					VarExp ve = cast(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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DivAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,118 @@
+module dmd.DivAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+import dmd.Id;
+import dmd.CommaExp;
+import dmd.RealExp;
+import dmd.AssignExp;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+import dmd.expression.Util;
+
+class DivAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKdivass, DivAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		if (e1.op == TOKslice)
+		{	// T[] -= ...
+			typeCombine(sc);
+			type = e1.type;
+			return arrayOp(sc);
+		}
+
+		e1 = e1.modifiableLvalue(sc, e1);
+		e1.checkScalar();
+		e1.checkNoBool();
+		type = e1.type;
+		typeCombine(sc);
+		e1.checkArithmetic();
+		e2.checkArithmetic();
+		if (e2.type.isimaginary())
+		{	
+			Type t1;
+			Type t2;
+
+			t1 = e1.type;
+			if (t1.isreal())
+			{   
+				// x/iv = i(-x/v)
+				// Therefore, the result is 0
+				e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
+				e2.type = t1;
+				e = new AssignExp(loc, e1, e2);
+				e.type = t1;
+				return e;
+			}
+			else if (t1.isimaginary())
+			{   
+				Expression e3;
+
+				switch (t1.ty)
+				{
+					case Timaginary32: t2 = Type.tfloat32; break;
+					case Timaginary64: t2 = Type.tfloat64; break;
+					case Timaginary80: t2 = Type.tfloat80; break;
+					default:
+						assert(0);
+				}
+				e2 = e2.castTo(sc, t2);
+				e3 = new AssignExp(loc, e1, e2);
+				e3.type = t1;
+				return e3;
+			}
+		}
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.divass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs,OPdivass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DivExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,143 @@
+module dmd.DivExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.NegExp;
+import dmd.TY;
+import dmd.Id;
+
+import dmd.expression.Div;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class DivExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKdiv, DivExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (type)
+			return this;
+
+		super.semanticp(sc);
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		typeCombine(sc);
+		if (e1.op != TOK.TOKslice && e2.op != TOK.TOKslice)
+		{	
+			e1.checkArithmetic();
+			e2.checkArithmetic();
+		}
+		if (type.isfloating())
+		{	
+			Type t1 = e1.type;
+			Type t2 = e2.type;
+
+			if (t1.isreal())
+			{
+				type = t2;
+				if (t2.isimaginary())
+				{
+					// x/iv = i(-x/v)
+					e2.type = t1;
+					Expression ee = new NegExp(loc, this);
+					ee = ee.semantic(sc);
+					return e;
+				}
+			}
+			else if (t2.isreal())
+			{
+				type = t1;
+			}
+			else if (t1.isimaginary())
+			{
+				if (t2.isimaginary()) {
+					switch (t1.ty)
+					{
+						case TY.Timaginary32:	type = Type.tfloat32;	break;
+						case TY.Timaginary64:	type = Type.tfloat64;	break;
+						case TY.Timaginary80:	type = Type.tfloat80;	break;
+						default:		assert(0);
+					}
+				} else {
+					type = t2;	// t2 is complex
+				}
+			}
+			else if (t2.isimaginary())
+			{
+				type = t1;	// t1 is complex
+			}
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("DivExp.optimize(%s)\n", toChars());
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() == 1 && e2.isConst() == 1)
+		{
+			e = Div(type, e1, e2);
+		}
+		else
+			e = this;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.div;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.div_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs,OPdiv);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DoStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,141 @@
+module dmd.DoStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.WANT;
+
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.backend.BC;
+
+class DoStatement : Statement
+{
+    Statement body_;
+    Expression condition;
+
+    this(Loc loc, Statement b, Expression c)
+	{
+		super(loc);
+		body_ = b;
+		condition = c;
+	}
+	
+    Statement syntaxCopy()
+	{
+		DoStatement s = new DoStatement(loc, body_ ? body_.syntaxCopy() : null, condition.syntaxCopy());
+		return s;
+	}
+
+    Statement semantic(Scope sc)
+	{
+		sc.noctor++;
+		if (body_)
+			body_ = body_.semanticScope(sc, this, this);
+		sc.noctor--;
+		condition = condition.semantic(sc);
+		condition = resolveProperties(sc, condition);
+		condition = condition.optimize(WANTvalue);
+
+		condition = condition.checkToBoolean();
+
+		return this;
+	}
+
+    bool hasBreak()
+	{
+		return true;
+	}
+
+    bool hasContinue()
+	{
+		return true;
+	}
+
+    bool usesEH()
+	{
+		return body_ ? body_.usesEH() : false;
+	}
+
+    BE blockExit()
+	{
+		BE result;
+
+		if (body_)
+		{	
+			result = body_.blockExit();
+			if (result == BE.BEbreak)
+				return BE.BEfallthru;
+			if (result & BE.BEcontinue)
+				result |= BE.BEfallthru;
+		}
+		else
+			result = BE.BEfallthru;
+
+		if (result & BE.BEfallthru)
+		{	
+			if (condition.canThrow())
+				result |= BE.BEthrow;
+			if (!(result & BE.BEbreak) && condition.isBool(true))
+				result &= ~BE.BEfallthru;
+		}
+		result &= ~(BE.BEbreak | BE.BEcontinue);
+
+		return result;
+	}
+
+    bool comeFrom()
+	{
+		assert(false);
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		body_ = body_ ? body_.inlineScan(iss) : null;
+		condition = condition.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		Blockx *blx = irs.blx;
+
+		IRState mystate = IRState(irs,this);
+		mystate.breakBlock = block_calloc(blx);
+		mystate.contBlock = block_calloc(blx);
+
+		block* bpre = blx.curblock;
+		block_next(blx, BCgoto, null);
+		list_append(&bpre.Bsucc, blx.curblock);
+
+		list_append(&mystate.contBlock.Bsucc, blx.curblock);
+		list_append(&mystate.contBlock.Bsucc, mystate.breakBlock);
+
+		if (body_)
+			body_.toIR(&mystate);
+		list_append(&blx.curblock.Bsucc, mystate.contBlock);
+
+		block_next(blx, BCgoto, mystate.contBlock);
+		incUsage(irs, condition.loc);
+		block_appendexp(mystate.contBlock, condition.toElem(&mystate));
+		block_next(blx, BCiftrue, mystate.breakBlock);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DocComment.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,50 @@
+module dmd.DocComment;
+
+import dmd.Array;
+import dmd.Section;
+import dmd.Macro;
+import dmd.Escape;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+
+class DocComment
+{
+    Array sections;		// Section*[]
+
+    Section summary;
+    Section copyright;
+    Section macros;
+    Macro** pmacrotable;
+    Escape** pescapetable;
+
+    this()
+	{
+		assert(false);
+	}
+
+    static DocComment parse(Scope sc, Dsymbol s, ubyte* comment)
+	{
+		assert(false);
+	}
+	
+    static void parseMacros(Escape** pescapetable, Macro** pmacrotable, ubyte* m, uint mlen)
+	{
+		assert(false);
+	}
+	
+    static void parseEscapes(Escape** pescapetable, ubyte* textstart, uint textlen)
+	{
+		assert(false);
+	}
+
+    void parseSections(ubyte* comment)
+	{
+		assert(false);
+	}
+	
+    void writeSections(Scope sc, Dsymbol s, OutBuffer buf)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DollarExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,16 @@
+module dmd.DollarExp;
+
+import dmd.IdentifierExp;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.TOK;
+import dmd.Id;
+
+class DollarExp : IdentifierExp
+{
+	this(Loc loc)
+	{
+		super(loc, Id.dollar);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DotExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.DotExp;
+
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.BinExp;
+import dmd.TOK;
+
+class DotExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DotIdExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,373 @@
+module dmd.DotIdExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.IntegerExp;
+import dmd.Type;
+import dmd.TY;
+import dmd.ScopeExp;
+import dmd.StringExp;
+import dmd.PtrExp;
+import dmd.TypePointer;
+import dmd.Dsymbol;
+import dmd.EnumMember;
+import dmd.VarDeclaration;
+import dmd.ThisExp;
+import dmd.DotVarExp;
+import dmd.VarExp;
+import dmd.CommaExp;
+import dmd.FuncDeclaration;
+import dmd.OverloadSet;
+import dmd.OverExp;
+import dmd.TypeExp;
+import dmd.TupleDeclaration;
+import dmd.ScopeDsymbol;
+import dmd.Import;
+import dmd.Id;
+import dmd.TupleExp;
+import dmd.ArrayTypes;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.TOK;
+import dmd.HdrGenState;
+import dmd.ClassDeclaration;
+import dmd.StructDeclaration;
+import dmd.AggregateDeclaration;
+import dmd.DotExp;
+import dmd.Global;
+import dmd.IdentifierExp;
+import dmd.CallExp;
+import dmd.PREC;
+
+import dmd.expression.Util;
+
+class DotIdExp : UnaExp
+{
+	Identifier ident;
+
+	this(Loc loc, Expression e, Identifier ident)
+	{
+		super(loc, TOK.TOKdot, DotIdExp.sizeof, e);
+		this.ident = ident;
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Expression eleft;
+		Expression eright;
+
+version (LOGSEMANTIC) {
+		printf("DotIdExp.semantic(this = %p, '%s')\n", this, toChars());
+		//printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op));
+}
+
+	//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
+
+static if (false) {
+		/* Don't do semantic analysis if we'll be converting
+		 * it to a string.
+		 */
+		if (ident == Id.stringof)
+		{	
+			char *s = e1.toChars();
+			e = new StringExp(loc, s, strlen(s), 'c');
+			e = e.semantic(sc);
+			return e;
+		}
+}
+
+		/* Special case: rewrite this.id and super.id
+		 * to be classtype.id and baseclasstype.id
+		 * if we have no this pointer.
+		 */
+		if ((e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper) && !hasThis(sc))
+		{
+			ClassDeclaration cd;
+			StructDeclaration sd;
+			AggregateDeclaration ad;
+
+			ad = sc.getStructClassScope();
+			if (ad)
+			{
+				cd = ad.isClassDeclaration();
+				if (cd)
+				{
+					if (e1.op == TOK.TOKthis)
+					{
+						e = typeDotIdExp(loc, cd.type, ident);
+						return e.semantic(sc);
+					}
+					else if (cd.baseClass && e1.op == TOK.TOKsuper)
+					{
+						e = typeDotIdExp(loc, cd.baseClass.type, ident);
+						return e.semantic(sc);
+					}
+				}
+				else
+				{
+					sd = ad.isStructDeclaration();
+					if (sd)
+					{
+						if (e1.op == TOK.TOKthis)
+						{
+						e = typeDotIdExp(loc, sd.type, ident);
+						return e.semantic(sc);
+						}
+					}
+				}
+			}
+		}
+
+		UnaExp.semantic(sc);
+
+		if (e1.op == TOK.TOKdotexp)
+		{
+			DotExp de = cast(DotExp)e1;
+			eleft = de.e1;
+			eright = de.e2;
+		}
+		else
+		{
+			e1 = resolveProperties(sc, e1);
+			eleft = null;
+			eright = e1;
+		}
+		
+version (DMDV2) {
+		if (e1.op == TOK.TOKtuple && ident == Id.offsetof)
+		{
+			/* 'distribute' the .offsetof to each of the tuple elements.
+			*/
+			TupleExp te = cast(TupleExp)e1;
+			Expressions exps = new Expressions();
+			exps.setDim(te.exps.dim);
+			for (int i = 0; i < exps.dim; i++)
+			{   
+				Expression ee = cast(Expression)te.exps.data[i];
+				ee = ee.semantic(sc);
+				ee = new DotIdExp(e.loc, ee, Id.offsetof);
+				exps.data[i] = cast(void*)ee;
+			}
+			e = new TupleExp(loc, exps);
+			e = e.semantic(sc);
+			return e;
+		}
+}
+
+		if (e1.op == TOK.TOKtuple && ident == Id.length)
+		{
+			TupleExp te = cast(TupleExp)e1;
+			e = new IntegerExp(loc, te.exps.dim, Type.tsize_t);
+			return e;
+		}
+
+		if (e1.op == TOK.TOKdottd)
+		{
+			error("template %s does not have property %s", e1.toChars(), ident.toChars());
+			return e1;
+		}
+
+		if (!e1.type)
+		{
+			error("expression %s does not have property %s", e1.toChars(), ident.toChars());
+			return e1;
+		}
+
+		Type t1b = e1.type.toBasetype();
+
+		if (eright.op == TOK.TOKimport)	// also used for template alias's
+		{
+			ScopeExp ie = cast(ScopeExp)eright;
+
+			/* Disable access to another module's private imports.
+			 * The check for 'is sds our current module' is because
+			 * the current module should have access to its own imports.
+			 */
+			Dsymbol s = ie.sds.search(loc, ident,
+				(ie.sds.isModule() && ie.sds != sc.module_) ? 1 : 0);
+			if (s)
+			{
+				s = s.toAlias();
+				checkDeprecated(sc, s);
+
+				EnumMember em = s.isEnumMember();
+				if (em)
+				{
+				e = em.value;
+				e = e.semantic(sc);
+				return e;
+				}
+
+				VarDeclaration v = s.isVarDeclaration();
+				if (v)
+				{
+				//printf("DotIdExp. Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
+				if (v.inuse)
+				{
+					error("circular reference to '%s'", v.toChars());
+					type = Type.tint32;
+					return this;
+				}
+				type = v.type;
+				if (v.needThis())
+				{
+					if (!eleft)
+					eleft = new ThisExp(loc);
+					e = new DotVarExp(loc, eleft, v);
+					e = e.semantic(sc);
+				}
+				else
+				{
+					e = new VarExp(loc, v);
+					if (eleft)
+					{	
+						e = new CommaExp(loc, eleft, e);
+						e.type = v.type;
+					}
+				}
+				return e.deref();
+				}
+
+				FuncDeclaration f = s.isFuncDeclaration();
+				if (f)
+				{
+					//printf("it's a function\n");
+					if (f.needThis())
+					{
+						if (!eleft)
+						eleft = new ThisExp(loc);
+						e = new DotVarExp(loc, eleft, f);
+						e = e.semantic(sc);
+					}
+					else
+					{
+						e = new VarExp(loc, f, 1);
+						if (eleft)
+						{	e = new CommaExp(loc, eleft, e);
+						e.type = f.type;
+						}
+					}
+					return e;
+				}
+version (DMDV2) {
+				OverloadSet o = s.isOverloadSet();
+				if (o)
+				{   
+					//printf("'%s' is an overload set\n", o.toChars());
+					return new OverExp(o);
+				}
+}
+
+				Type t = s.getType();
+				if (t)
+				{
+					return new TypeExp(loc, t);
+				}
+
+				TupleDeclaration tup = s.isTupleDeclaration();
+				if (tup)
+				{
+					if (eleft)
+						error("cannot have e.tuple");
+					e = new TupleExp(loc, tup);
+					e = e.semantic(sc);
+					return e;
+				}
+
+				ScopeDsymbol sds = s.isScopeDsymbol();
+				if (sds)
+				{
+					//printf("it's a ScopeDsymbol\n");
+					e = new ScopeExp(loc, sds);
+					e = e.semantic(sc);
+					if (eleft)
+						e = new DotExp(loc, eleft, e);
+					return e;
+				}
+
+				Import imp = s.isImport();
+				if (imp)
+				{
+					ScopeExp iee = new ScopeExp(loc, imp.pkg);
+					return iee.semantic(sc);
+				}
+
+				// BUG: handle other cases like in IdentifierExp.semantic()
+version (DEBUG) {
+				printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
+}
+				assert(0);
+			}
+			else if (ident is Id.stringof_)
+			{  
+				string ss = ie.toChars();
+				e = new StringExp(loc, ss, 'c');
+				e = e.semantic(sc);
+				return e;
+			}
+			error("undefined identifier %s", toChars());
+			type = Type.tvoid;
+			return this;
+		}
+		else if (t1b.ty == TY.Tpointer &&
+			 ident !is Id.init_ && ident !is Id.__sizeof &&
+			 ident !is Id.alignof_ && ident !is Id.offsetof &&
+			 ident !is Id.mangleof_ && ident !is Id.stringof_)
+		{	/* Rewrite:
+			 *   p.ident
+			 * as:
+			 *   (*p).ident
+			 */
+		e = new PtrExp(loc, e1);
+		e.type = (cast(TypePointer)t1b).next;
+		return e.type.dotExp(sc, e, ident);
+		}
+///version (DMDV2) {
+		else if (t1b.ty == TY.Tarray ||
+				 t1b.ty == TY.Tsarray ||
+			 t1b.ty == TY.Taarray)
+		{	
+			/* If ident is not a valid property, rewrite:
+			 *   e1.ident
+			 * as:
+			 *   .ident(e1)
+			 */
+			uint errors = global.errors;
+			global.gag++;
+			e = e1.type.dotExp(sc, e1, ident);
+			global.gag--;
+			if (errors != global.errors)	// if failed to find the property
+			{
+				global.errors = errors;
+				e = new DotIdExp(loc, new IdentifierExp(loc, Id.empty), ident);
+				e = new CallExp(loc, e, e1);
+			}
+			e = e.semantic(sc);
+			return e;
+		}
+///}
+		else
+		{
+			e = e1.type.dotExp(sc, e1, ident);
+			e = e.semantic(sc);
+			return e;
+		}
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		//printf("DotIdExp.toCBuffer()\n");
+		expToCBuffer(buf, hgs, e1, PREC.PREC_primary);
+		buf.writeByte('.');
+		buf.writestring(ident.toChars());
+	}
+
+	void dump(int i)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DotTemplateExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,26 @@
+module dmd.DotTemplateExp;
+
+import dmd.Expression;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.HdrGenState;
+import dmd.TemplateDeclaration;
+
+class DotTemplateExp : UnaExp
+{
+	TemplateDeclaration td;
+
+	this(Loc loc, Expression e, TemplateDeclaration td)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DotTemplateInstanceExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,42 @@
+module dmd.DotTemplateInstanceExp;
+
+import dmd.Expression;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.TemplateInstance;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class DotTemplateInstanceExp : UnaExp
+{
+	TemplateInstance ti;
+
+	this(Loc loc, Expression e, TemplateInstance ti)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e);
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DotTypeExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,48 @@
+module dmd.DotTypeExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.Dsymbol;
+import dmd.TOK;
+import dmd.PREC;
+import dmd.expression.Util;
+
+class DotTypeExp : UnaExp
+{
+	Dsymbol sym;
+
+	this(Loc loc, Expression e, Dsymbol s)
+	{
+		super(loc, TOK.TOKdottype, DotTypeExp.sizeof, e);
+		this.sym = s;
+		this.type = s.getType();
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("DotTypeExp.semantic('%s')\n", toChars());
+	}
+		UnaExp.semantic(sc);
+		return this;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		expToCBuffer(buf, hgs, e1, PREC.PREC_primary);
+		buf.writeByte('.');
+		buf.writestring(sym.toChars());
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DotVarExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,281 @@
+module dmd.DotVarExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.TupleDeclaration;
+import dmd.ArrayTypes;
+import dmd.DsymbolExp;
+import dmd.TupleExp;
+import dmd.Global;
+import dmd.Type;
+import dmd.Dsymbol;
+import dmd.AggregateDeclaration;
+import dmd.VarDeclaration;
+import dmd.WANT;
+import dmd.TY;
+import dmd.ErrorExp;
+import dmd.FuncDeclaration;
+import dmd.STC;
+import dmd.GlobalExpressions;
+import dmd.VarExp;
+import dmd.StructLiteralExp;
+import dmd.PREC;
+
+import dmd.expression.Util;
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.mTY;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+
+class DotVarExp : UnaExp
+{
+	Declaration var;
+
+	int hasOverloads;
+
+	this(Loc loc, Expression e, Declaration var, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKdotvar, DotVarExp.sizeof, e);
+		//printf("DotVarExp()\n");
+		this.var = var;
+		this.hasOverloads = hasOverloads;
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("DotVarExp.semantic('%s')\n", toChars());
+}
+		if (!type)
+		{
+			var = var.toAlias().isDeclaration();
+
+			TupleDeclaration tup = var.isTupleDeclaration();
+			if (tup)
+			{   
+				/* Replace:
+				 *	e1.tuple(a, b, c)
+				 * with:
+				 *	tuple(e1.a, e1.b, e1.c)
+				 */
+				Expressions exps = new Expressions;
+
+				exps.reserve(tup.objects.dim);
+				for (size_t i = 0; i < tup.objects.dim; i++)
+				{   
+					Object o = cast(Object)tup.objects.data[i];
+					if (auto e = cast(Expression)o)
+					{
+						if (e.op != TOK.TOKdsymbol)
+							error("%s is not a member", e.toChars());
+						else
+						{	
+							DsymbolExp ve = cast(DsymbolExp)e;
+							e = new DotVarExp(loc, e1, ve.s.isDeclaration());
+							exps.push(cast(void*)e);
+						}
+					} else {
+						error("%s is not an expression", o.toString());
+					}
+				}
+				Expression e = new TupleExp(loc, exps);
+				e = e.semantic(sc);
+				return e;
+			}
+
+			e1 = e1.semantic(sc);
+			type = var.type;
+			if (!type && global.errors)
+			{   
+				// var is goofed up, just return 0
+				return new ErrorExp();
+			}
+			assert(type);
+
+			if (!var.isFuncDeclaration())	// for functions, do checks after overload resolution
+			{
+				Type t1 = e1.type;
+				if (t1.ty == TY.Tpointer)
+					t1 = t1.nextOf();
+
+				type = type.addMod(t1.mod);
+
+				Dsymbol vparent = var.toParent();
+				AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
+				e1 = getRightThis(loc, sc, ad, e1, var);
+				if (!sc.noaccesscheck)
+					accessCheck(loc, sc, e1, var);
+
+				VarDeclaration v = var.isVarDeclaration();
+				Expression e = expandVar(WANT.WANTvalue, v);
+				if (e)
+					return e;
+			}
+		}
+		//printf("-DotVarExp.semantic('%s')\n", toChars());
+		return this;
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		//printf("DotVarExp::toLvalue(%s)\n", toChars());
+		return this;
+	}
+
+	Expression modifiableLvalue(Scope sc, Expression e)
+	{
+static if (false) {
+		printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
+		printf("e1.type = %s\n", e1.type.toChars());
+		printf("var.type = %s\n", var.type.toChars());
+}
+
+		if (var.isCtorinit())
+		{	
+			// It's only modifiable if inside the right constructor
+			Dsymbol s = sc.func;
+			while (true)
+			{
+				FuncDeclaration fd = null;
+				if (s)
+					fd = s.isFuncDeclaration();
+				if (fd && ((fd.isCtorDeclaration() && var.storage_class & STC.STCfield) ||
+					(fd.isStaticCtorDeclaration() && !(var.storage_class & STC.STCfield))) &&
+					fd.toParent() == var.toParent() && e1.op == TOK.TOKthis)
+				{
+					VarDeclaration v = var.isVarDeclaration();
+					assert(v);
+					v.ctorinit = 1;
+					//printf("setting ctorinit\n");
+				}
+				else
+				{
+					if (s)
+					{   
+						s = s.toParent2();
+						continue;
+					}
+					else
+					{
+						string p = var.isStatic() ? "static " : "";
+						error("can only initialize %sconst member %s inside %sconstructor", p, var.toChars(), p);
+					}
+				}
+				break;
+			}
+		}
+		else
+		{
+version (DMDV2) {
+			Type t1 = e1.type.toBasetype();
+
+			if (!t1.isMutable() || (t1.ty == TY.Tpointer && !t1.nextOf().isMutable()) ||
+				!var.type.isMutable() || !var.type.isAssignable() || var.storage_class & STC.STCmanifest)
+			{
+				error("cannot modify const/immutable expression %s", toChars());
+			}
+}
+		}
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("DotVarExp.optimize(result = x%x) %s\n", result, toChars());
+		e1 = e1.optimize(result);
+
+		if (e1.op == TOK.TOKvar)
+		{	
+			VarExp ve = cast(VarExp)e1;
+			VarDeclaration v = ve.var.isVarDeclaration();
+			Expression e = expandVar(result, v);
+			if (e && e.op == TOK.TOKstructliteral)
+			{   
+				StructLiteralExp sle = cast(StructLiteralExp)e;
+				VarDeclaration vf = var.isVarDeclaration();
+				if (vf)
+				{
+					e = sle.getField(type, vf.offset);
+					if (e && e !is EXP_CANT_INTERPRET)
+						return e;
+				}
+			}
+		}
+		else if (e1.op == TOK.TOKstructliteral)
+		{   
+			StructLiteralExp sle = cast(StructLiteralExp)e1;
+			VarDeclaration vf = var.isVarDeclaration();
+			if (vf)
+			{
+				Expression e = sle.getField(type, vf.offset);
+				if (e && e !is EXP_CANT_INTERPRET)
+					return e;
+			}
+		}
+
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		expToCBuffer(buf, hgs, e1, PREC.PREC_primary);
+		buf.writeByte('.');
+		buf.writestring(var.toChars());
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		// *(&e + offset)
+		//printf("DotVarExp.toElem('%s')\n", toChars());
+
+		VarDeclaration v = var.isVarDeclaration();
+		if (!v)
+		{
+			error("%s is not a field, but a %s", var.toChars(), var.kind());
+		}
+
+		elem* e = e1.toElem(irs);
+		Type tb1 = e1.type.toBasetype();
+
+		if (tb1.ty != TY.Tclass && tb1.ty != TY.Tpointer)
+			//e = el_una(OPaddr, TYnptr, e);
+			e = addressElem(e, tb1);
+
+		e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, v ? v.offset : 0));
+		e = el_una(OPER.OPind, type.totym(), e);
+		if (tybasic(e.Ety) == TYM.TYstruct)
+		{
+			e.Enumbytes = cast(uint)type.size();
+		}
+		el_setLoc(e,loc);
+
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Dsymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,862 @@
+module dmd.Dsymbol;
+
+import dmd.Loc;
+import dmd.STC;
+import dmd.Scope;
+import dmd.Lexer;
+import dmd.Module;
+import dmd.Array;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.Id;
+import dmd.Identifier;
+import dmd.TemplateInstance;
+import dmd.HdrGenState;
+import dmd.AggregateDeclaration;
+import dmd.ClassDeclaration;
+import dmd.LabelDsymbol;
+import dmd.Type;
+import dmd.PROT;
+import dmd.ArrayTypes;
+import dmd.Package;
+import dmd.EnumMember;
+import dmd.TemplateDeclaration;
+import dmd.TemplateMixin;
+import dmd.Declaration;
+import dmd.ThisDeclaration;
+import dmd.TupleDeclaration;
+import dmd.TypedefDeclaration;
+import dmd.AliasDeclaration;
+import dmd.FuncDeclaration;
+import dmd.FuncAliasDeclaration;
+import dmd.FuncLiteralDeclaration;
+import dmd.CtorDeclaration;
+import dmd.PostBlitDeclaration;
+import dmd.DtorDeclaration;
+import dmd.StaticCtorDeclaration;
+import dmd.StaticDtorDeclaration;
+import dmd.InvariantDeclaration;
+import dmd.UnitTestDeclaration;
+import dmd.NewDeclaration;
+import dmd.VarDeclaration;
+import dmd.StructDeclaration;
+import dmd.UnionDeclaration;
+import dmd.InterfaceDeclaration;
+import dmd.WithScopeSymbol;
+import dmd.ArrayScopeSymbol;
+import dmd.Import;
+import dmd.EnumDeclaration;
+import dmd.DeleteDeclaration;
+import dmd.SymbolDeclaration;
+import dmd.AttribDeclaration;
+import dmd.OverloadSet;
+import dmd.DYNCAST;
+import dmd.Global;
+import dmd.Expression;
+import dmd.TOK;
+import dmd.VarExp;
+import dmd.FuncExp;
+
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.mTYman;
+import dmd.backend.TYFL;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.LIST;
+
+import core.stdc.string : strcmp, memcpy, strlen;
+import core.stdc.stdlib : alloca;
+
+import std.stdio;
+
+// TODO: remove dependencies on these
+Expression isExpression(Object o)
+{
+    return cast(Expression)o;
+}
+
+Dsymbol isDsymbol(Object o)
+{
+    return cast(Dsymbol)o;
+}
+
+Type isType(Object o)
+{
+    return cast(Type)o;
+}
+
+Dsymbol getDsymbol(Object oarg)
+{
+	Dsymbol sa;
+    Expression ea = isExpression(oarg);
+    if (ea)
+    {   // Try to convert Expression to symbol
+		if (ea.op == TOK.TOKvar)
+			sa = (cast(VarExp)ea).var;
+		else if (ea.op == TOK.TOKfunction)
+			sa = (cast(FuncExp)ea).fd;
+		else
+			sa = null;
+    }
+    else
+    {   // Try to convert Type to symbol
+		Type ta = isType(oarg);
+		if (ta)
+			sa = ta.toDsymbol(null);
+		else
+			sa = isDsymbol(oarg);	// if already a symbol
+    }
+    return sa;
+}
+
+class Dsymbol
+{
+    Identifier ident;
+    Identifier c_ident;
+    Dsymbol parent;
+    Symbol* csym;		// symbol for code generator
+    Symbol* isym;		// import version of csym
+    ubyte* comment;	// documentation comment for this Dsymbol
+    Loc loc;			// where defined
+    Scope scope_;		// !=null means context to use for semantic()
+
+    this()
+	{
+		// do nothing
+	}
+	
+    this(Identifier ident)
+	{
+		this.ident = ident;
+	}
+
+    string toChars()
+	{
+		return ident ? ident.toChars() : "__anonymous";
+	}
+
+    string locToChars()
+	{
+		scope OutBuffer buf = new OutBuffer();
+		Module m = getModule();
+
+		if (m && m.srcfile)
+			loc.filename = m.srcfile.toChars();
+
+		return loc.toChars();
+	}
+
+    int equals(Object o)
+	{
+		assert(false);
+	}
+
+    bool isAnonymous()
+	{
+		return ident ? 0 : 1;
+	}
+
+    void error(T...)(Loc loc, string format, T t)
+	{
+		if (!global.gag)
+		{
+			string p = loc.toChars();
+			if (p.length == 0)
+				p = locToChars();
+
+			if (p.length != 0) {
+				writef("%s: ", p);
+			}
+
+			write("Error: ");
+			writef("%s %s ", kind(), toPrettyChars());
+
+			writefln(format, t);
+		}
+
+		global.errors++;
+		
+		//fatal();
+	}
+
+    void error(T...)(string format, T t)
+	{
+		//printf("Dsymbol.error()\n");
+		if (!global.gag)
+		{
+			string p = loc.toChars();
+
+			if (p.length != 0) {
+				writef("%s: ", p);
+			}
+
+			write("Error: ");
+			if (isAnonymous()) {
+				writef("%s ", kind());
+			} else {
+				writef("%s %s ", kind(), toPrettyChars());
+			}
+
+			writefln(format, t);
+		}
+		global.errors++;
+
+		//fatal();
+	}
+
+    void checkDeprecated(Loc loc, Scope sc)
+	{
+		if (!global.params.useDeprecated && isDeprecated())
+		{
+			// Don't complain if we're inside a deprecated symbol's scope
+			for (Dsymbol sp = sc.parent; sp; sp = sp.parent)
+			{   
+				if (sp.isDeprecated())
+					return;
+			}
+
+			for (; sc; sc = sc.enclosing)
+			{
+				if (sc.scopesym && sc.scopesym.isDeprecated())
+					return;
+
+				// If inside a StorageClassDeclaration that is deprecated
+				if (sc.stc & STC.STCdeprecated)
+					return;
+			}
+
+			error(loc, "is deprecated");
+		}
+	}
+	
+    Module getModule()
+	{
+		//printf("Dsymbol.getModule()\n");
+		Dsymbol s = this;
+		while (s)
+		{
+			//printf("\ts = '%s'\n", s.toChars());
+			Module m = s.isModule();
+			if (m)
+				return m;
+			s = s.parent;
+		}
+
+		return null;
+	}
+	
+    Dsymbol pastMixin()
+	{
+		 Dsymbol s = this;
+		//printf("Dsymbol::pastMixin() %s\n", toChars());
+		while (s && s.isTemplateMixin())
+			s = s.parent;
+		return s;
+	}
+	
+    Dsymbol toParent()
+	{
+		return parent ? parent.pastMixin() : null;
+	}
+
+	/**********************************
+	 * Use this instead of toParent() when looking for the
+	 * 'this' pointer of the enclosing function/class.
+	 */
+    Dsymbol toParent2()
+	{
+		Dsymbol s = parent;
+		while (s && s.isTemplateInstance())
+			s = s.parent;
+		return s;
+	}
+	
+    TemplateInstance inTemplateInstance()
+	{
+		for (Dsymbol parent = this.parent; parent; parent = parent.parent)
+		{
+			TemplateInstance ti = parent.isTemplateInstance();
+			if (ti)
+				return ti;
+		}
+
+		return null;
+	}
+
+    DYNCAST dyncast() { return DYNCAST.DYNCAST_DSYMBOL; }	// kludge for template.isSymbol()
+
+	/*************************************
+	 * Do syntax copy of an array of Dsymbol's.
+	 */
+    static Array arraySyntaxCopy(Array a)
+	{
+		Array b = null;
+		if (a)
+		{
+			b = a.copy();
+			for (int i = 0; i < b.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)b.data[i];
+
+				s = s.syntaxCopy(null);
+				b.data[i] = cast(void*)s;
+			}
+		}
+		return b;
+	}
+
+    string toPrettyChars()
+	{
+		//printf("Dsymbol.toPrettyChars() '%s'\n", toChars());
+		if (!parent) {
+			return toChars();
+		}
+
+		size_t len = 0;
+		for (Dsymbol p = this; p; p = p.parent) {
+			len += p.toChars().length + 1;
+		}
+		--len;
+
+		char* s = cast(char*)alloca(len);
+		char* q = s + len;
+
+		for (Dsymbol p = this; p; p = p.parent)
+		{
+			string t = p.toChars();
+			size_t length = t.length;
+			q -= length;
+
+			memcpy(q, t.ptr, length);
+			if (q is s)
+				break;
+			
+			q--;
+	version (TARGET_NET) {
+			if (AggregateDeclaration ad = p.isAggregateDeclaration())
+			{
+				if (ad.isNested() && p.parent && p.parent.isAggregateDeclaration())
+				{
+					*q = '/';
+					continue;
+				}
+			}
+	}
+			*q = '.';
+		}
+
+		return s[0..len].idup;
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+	/*********************************
+	 * If this symbol is really an alias for another,
+	 * return that other.
+	 */
+    Dsymbol toAlias()			// resolve real symbol
+	{
+		return this;
+	}
+	
+    bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
+	{
+		//printf("Dsymbol.addMember('%s')\n", toChars());
+		//printf("Dsymbol.addMember(this = %p, '%s' scopesym = '%s')\n", this, toChars(), sd.toChars());
+		assert(sd !is null);
+		parent = sd;
+		if (!isAnonymous())		// no name, so can't add it to symbol table
+		{
+			if (!sd.symtab.insert(this))	// if name is already defined
+			{
+				Dsymbol s2 = sd.symtab.lookup(ident);
+				if (!s2.overloadInsert(this))
+				{
+					sd.multiplyDefined(Loc(0), this, s2);
+				}
+			}
+			if (sd.isAggregateDeclaration() || sd.isEnumDeclaration())
+			{
+				if (ident is Id.__sizeof || ident is Id.alignof_ || ident is Id.mangleof_)
+					error(".%s property cannot be redefined", ident.toChars());
+			}
+			return true;
+		}
+
+		return false;
+	}
+	
+    void setScope(Scope sc)
+	{
+		//printf("Dsymbol.setScope() %p %s\n", this, toChars());
+		if (!sc.nofree)
+			sc.setNoFree();		// may need it even after semantic() finishes
+		scope_ = sc;
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+	/*************************************
+	 * Does semantic analysis on initializers and members of aggregates.
+	 */
+    void semantic2(Scope sc)
+	{
+		// Most Dsymbols have no further semantic analysis needed
+	}
+
+	/*************************************
+	 * Does semantic analysis on function bodies.
+	 */	
+    void semantic3(Scope sc)
+	{
+		// Most Dsymbols have no further semantic analysis needed
+	}
+	
+	/*************************************
+	 * Look for function inlining possibilities.
+	 */
+    void inlineScan()
+	{
+		// Most Dsymbols aren't functions
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		assert(false);
+	}
+	
+	/***************************************
+	 * Search for identifier id as a member of 'this'.
+	 * id may be a template instance.
+	 * Returns:
+	 *	symbol found, null if not
+	 */
+    Dsymbol searchX(Loc loc, Scope sc, Identifier id)
+	{
+		//printf("Dsymbol::searchX(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars());
+		Dsymbol s = toAlias();
+		Dsymbol sm;
+
+		/// HUH????
+		switch (id.dyncast())
+		{
+			case DYNCAST.DYNCAST_IDENTIFIER:
+				sm = s.search(loc, id, 0);
+				break;
+
+			case DYNCAST.DYNCAST_DSYMBOL:
+			{  
+				assert(false);	/// how can it happen?
+				// It's a template instance
+				//printf("\ttemplate instance id\n");
+				Dsymbol st = cast(Dsymbol)id;
+				TemplateInstance ti = st.isTemplateInstance();
+				id = ti.name;
+				sm = s.search(loc, id, 0);
+				if (!sm)
+				{   
+					error("template identifier %s is not a member of %s %s", id.toChars(), s.kind(), s.toChars());
+					return null;
+				}
+				sm = sm.toAlias();
+				TemplateDeclaration td = sm.isTemplateDeclaration();
+				if (!td)
+				{
+					error("%s is not a template, it is a %s", id.toChars(), sm.kind());
+					return null;
+				}
+
+				ti.tempdecl = td;
+				if (!ti.semanticRun)
+					ti.semantic(sc);
+
+				sm = ti.toAlias();
+				break;
+			}
+
+			default:
+				assert(0);
+		}
+		return sm;
+	}
+	
+    bool overloadInsert(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+version (_DH) {
+    char* toHChars()
+	{
+		assert(false);
+	}
+	
+    void toHBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+	
+    uint size(Loc loc)
+	{
+		assert(false);
+	}
+
+    int isforwardRef()
+	{
+		assert(false);
+	}
+	
+    void defineRef(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    AggregateDeclaration isThis()	// is a 'this' required to access the member
+	{
+		assert(false);
+	}
+	
+    ClassDeclaration isClassMember()	// are we a member of a class?
+	{
+		Dsymbol parent = toParent();
+		if (parent && parent.isClassDeclaration())
+			return cast(ClassDeclaration)parent;
+		return null;
+	}
+	
+    bool isExport()			// is Dsymbol exported?
+	{
+		return false;
+	}
+	
+    bool isImportedSymbol()		// is Dsymbol imported?
+	{
+		return false;
+	}
+	
+    bool isDeprecated()			// is Dsymbol deprecated?
+	{
+		return false;
+	}
+
+version (DMDV2) {
+    bool isOverloadable()
+	{
+		return false;
+	}
+}
+
+    LabelDsymbol isLabel()		// is this a LabelDsymbol?
+	{
+		return null;
+	}
+	
+    AggregateDeclaration isMember()	// is this symbol a member of an AggregateDeclaration?
+	{
+		//printf("Dsymbol::isMember() %s\n", toChars());
+		Dsymbol parent = toParent();
+		//printf("parent is %s %s\n", parent.kind(), parent.toChars());
+		return parent ? parent.isAggregateDeclaration() : null;
+	}
+
+    Type getType()			// is this a type?
+	{
+		return null;
+	}
+	
+    string mangle()
+	{
+		OutBuffer buf = new OutBuffer();
+		string id;
+
+static if (false) {
+		printf("Dsymbol::mangle() '%s'", toChars());
+		if (parent)
+			printf("  parent = %s %s", parent.kind(), parent.toChars());
+		printf("\n");
+}
+		id = ident ? ident.toChars() : toChars();
+		if (parent)
+		{
+			string p = parent.mangle();
+			if (p[0] == '_' && p[1] == 'D')
+				p =  p[2..$];
+			buf.writestring(p);
+		}
+		///buf.printf("%zu%s", id.length, id);
+		buf.printf("%d%s", id.length, id);
+		id = buf.toChars();
+		buf.data = null;
+		//printf("Dsymbol::mangle() %s = %s\n", toChars(), id);
+		return id;
+	}
+
+    bool needThis()			// need a 'this' pointer?
+	{
+		return false;
+	}
+
+    PROT prot()
+	{
+		assert(false);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)	// copy only syntax trees
+	{
+		assert(false);
+	}
+
+	/**************************************
+	 * Determine if this symbol is only one.
+	 * Returns:
+	 *	false, *ps = null: There are 2 or more symbols
+	 *	true,  *ps = null: There are zero symbols
+	 *	true,  *ps = symbol: The one and only one symbol
+	 */
+    bool oneMember(Dsymbol* ps)
+	{
+		//printf("Dsymbol::oneMember()\n");
+		*ps = this;
+		return true;
+	}
+
+	/*****************************************
+	 * Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
+	 */
+    static bool oneMembers(Array members, Dsymbol* ps)
+	{
+		//printf("Dsymbol::oneMembers() %d\n", members ? members->dim : 0);
+		Dsymbol s = null;
+
+		if (members)
+		{
+			for (int i = 0; i < members.dim; i++)
+			{   
+				Dsymbol sx = cast(Dsymbol)members.data[i];
+
+				bool x = sx.oneMember(ps);
+				//printf("\t[%d] kind %s = %d, s = %p\n", i, sx->kind(), x, *ps);
+				if (!x)
+				{
+					//printf("\tfalse 1\n");
+					assert(*ps is null);
+					return false;
+				}
+				if (*ps)
+				{
+					if (s)			// more than one symbol
+					{   
+						*ps = null;
+						//printf("\tfalse 2\n");
+						return false;
+					}
+					s = *ps;
+				}
+			}
+		}
+
+		*ps = s;		// s is the one symbol, null if none
+		//printf("\ttrue\n");
+		return true;
+	}
+	
+	/*****************************************
+	 * Is Dsymbol a variable that contains pointers?
+	 */
+    bool hasPointers()
+	{
+		//printf("Dsymbol::hasPointers() %s\n", toChars());
+		return 0;
+	}
+
+    void addLocalClass(ClassDeclarations) { }
+    void checkCtorConstInit() { }
+
+    void addComment(ubyte* comment)
+	{
+		//if (comment)
+			//printf("adding comment '%s' to symbol %p '%s'\n", comment, this, toChars());
+
+		if (this.comment is null) {
+			this.comment = comment;
+		} else {
+static if (true) {
+			if (comment !is null && strcmp(cast(char*)comment, cast(char*)this.comment) != 0)
+			{	// Concatenate the two
+				this.comment = Lexer.combineComments(this.comment, comment);
+			}
+}
+		}
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void emitDitto(Scope sc)
+	{
+		assert(false);
+	}
+
+    // Backend
+
+    Symbol* toSymbol()			// to backend symbol
+	{
+		assert(false);
+	}
+	
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		//printf("Dsymbol::toObjFile('%s')\n", toChars());
+		// ignore
+	}
+	
+    int cvMember(ubyte* p)	// emit cv debug info for member
+	{
+		assert(false);
+	}
+
+	/*********************************
+	 * Generate import symbol from symbol.
+	 */
+    Symbol* toImport()				// to backend import symbol
+	{
+		if (!isym)
+		{
+			if (!csym)
+				csym = toSymbol();
+			isym = toImport(csym);
+		}
+
+		return isym;
+	}
+	
+    static Symbol* toImport(Symbol* sym)		// to backend import symbol
+	{
+		char* id;
+		char* n;
+		Symbol* s;
+		type* t;
+
+		//printf("Dsymbol::toImport('%s')\n", sym->Sident);
+		n = sym.Sident.ptr;
+		id = cast(char*) alloca(6 + strlen(n) + 1 + (type_paramsize_i(sym.Stype)).sizeof*3 + 1);
+		if (sym.Stype.Tmangle == mTYman_std && tyfunc(sym.Stype.Tty))
+		{
+			sprintf(id, "_imp__%s@%lu", n, type_paramsize_i(sym.Stype));
+		}
+		else if (sym.Stype.Tmangle == mTYman_d)
+			sprintf(id,"_imp_%s",n);
+		else
+			sprintf(id,"_imp__%s",n);
+		t = type_alloc(TYnptr | mTYconst);
+		t.Tnext = sym.Stype;
+		t.Tnext.Tcount++;
+		t.Tmangle = mTYman_c;
+		t.Tcount++;
+		s = symbol_calloc(id);
+		s.Stype = t;
+		s.Sclass = SCextern;
+		s.Sfl = FLextern;
+		slist_add(s);
+
+		return s;
+	}
+
+    Symbol* toSymbolX(string prefix, int sclass, TYPE* t, string suffix)	// helper
+	{
+		Symbol* s;
+		char* id;
+		string n;
+		size_t nlen;
+
+		//writef("Dsymbol::toSymbolX('%s', '%s')\n", prefix, this.classinfo.name);
+		n = mangle();
+		assert(n.length != 0);
+
+		nlen = n.length;
+static if (false) {
+		if (nlen > 2 && n[0] == '_' && n[1] == 'D')
+		{
+			nlen -= 2;
+			n += 2;
+		}
+}
+		id = cast(char*) alloca(2 + nlen + size_t.sizeof * 3 + prefix.length + suffix.length + 1);
+		sprintf(id, "_D%.*s%lu%.*s%.*s", n, prefix.length, prefix, suffix);
+		
+	static if (false) {
+		if (global.params.isWindows && (type_mangle(t) == mTYman.mTYman_c || type_mangle(t) == mTYman.mTYman_std))
+			id++;			// Windows C mangling will put the '_' back in
+	}
+		s = symbol_name(id, sclass, t);
+		
+		//printf("-Dsymbol::toSymbolX() %s\n", id);
+		return s;
+	}
+
+    // Eliminate need for dynamic_cast
+    Package isPackage() { return null; }
+    Module isModule() { return null; }
+    EnumMember isEnumMember() { return null; }
+    TemplateDeclaration isTemplateDeclaration() { return null; }
+    TemplateInstance isTemplateInstance() { return null; }
+    TemplateMixin isTemplateMixin() { return null; }
+    Declaration isDeclaration() { return null; }
+    ThisDeclaration isThisDeclaration() { return null; }
+    TupleDeclaration isTupleDeclaration() { return null; }
+    TypedefDeclaration isTypedefDeclaration() { return null; }
+    AliasDeclaration isAliasDeclaration() { return null; }
+    AggregateDeclaration isAggregateDeclaration() { return null; }
+    FuncDeclaration isFuncDeclaration() { return null; }
+    FuncAliasDeclaration isFuncAliasDeclaration() { return null; }
+    FuncLiteralDeclaration isFuncLiteralDeclaration() { return null; }
+    CtorDeclaration isCtorDeclaration() { return null; }
+    PostBlitDeclaration isPostBlitDeclaration() { return null; }
+    DtorDeclaration isDtorDeclaration() { return null; }
+    StaticCtorDeclaration isStaticCtorDeclaration() { return null; }
+    StaticDtorDeclaration isStaticDtorDeclaration() { return null; }
+    InvariantDeclaration isInvariantDeclaration() { return null; }
+    UnitTestDeclaration isUnitTestDeclaration() { return null; }
+    NewDeclaration isNewDeclaration() { return null; }
+    VarDeclaration isVarDeclaration() { return null; }
+    ClassDeclaration isClassDeclaration() { return null; }
+    StructDeclaration isStructDeclaration() { return null; }
+    UnionDeclaration isUnionDeclaration() { return null; }
+    InterfaceDeclaration isInterfaceDeclaration() { return null; }
+    ScopeDsymbol isScopeDsymbol() { return null; }
+    WithScopeSymbol isWithScopeSymbol() { return null; }
+    ArrayScopeSymbol isArrayScopeSymbol() { return null; }
+    Import isImport() { return null; }
+    EnumDeclaration isEnumDeclaration() { return null; }
+version (_DH) {
+    DeleteDeclaration isDeleteDeclaration() { return null; }
+}
+    SymbolDeclaration isSymbolDeclaration() { return null; }
+    AttribDeclaration isAttribDeclaration() { return null; }
+    OverloadSet isOverloadSet() { return null; }
+version (TARGET_NET) {
+    PragmaScope isPragmaScope() { return null; }
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DsymbolExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,251 @@
+module dmd.DsymbolExp;
+
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.EnumMember;
+import dmd.VarDeclaration;
+import dmd.FuncDeclaration;
+import dmd.FuncLiteralDeclaration;
+import dmd.OverloadSet;
+import dmd.Declaration;
+import dmd.ClassDeclaration;
+import dmd.Import;
+import dmd.Package;
+import dmd.Type;
+import dmd.DotVarExp;
+import dmd.ThisExp;
+import dmd.VarExp;
+import dmd.FuncExp;
+import dmd.OverExp;
+import dmd.DotTypeExp;
+import dmd.ScopeExp;
+import dmd.Module;
+import dmd.TypeExp;
+import dmd.TupleDeclaration;
+import dmd.TupleExp;
+import dmd.TemplateInstance;
+import dmd.Global;
+import dmd.TemplateDeclaration;
+import dmd.TemplateExp;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.Dsymbol;
+import dmd.TOK;
+
+class DsymbolExp : Expression
+{
+	Dsymbol s;
+	int hasOverloads;
+
+	this(Loc loc, Dsymbol s, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKdsymbol, DsymbolExp.sizeof);
+		this.s = s;
+		this.hasOverloads = hasOverloads;
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("DsymbolExp.semantic('%s')\n", s.toChars());
+}
+
+	Lagain:
+		EnumMember em;
+		Expression e;
+		VarDeclaration v;
+		FuncDeclaration f;
+		FuncLiteralDeclaration fld;
+		OverloadSet o;
+		Declaration d;
+		ClassDeclaration cd;
+		ClassDeclaration thiscd = null;
+		Import imp;
+		Package pkg;
+		Type t;
+
+		//printf("DsymbolExp. %p '%s' is a symbol\n", this, toChars());
+		//printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
+		if (type)
+			return this;
+
+		if (!s.isFuncDeclaration())	// functions are checked after overloading
+			checkDeprecated(sc, s);
+
+		s = s.toAlias();
+		//printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
+		if (!s.isFuncDeclaration())
+			checkDeprecated(sc, s);
+
+		if (sc.func)
+			thiscd = sc.func.parent.isClassDeclaration();
+
+		// BUG: This should happen after overload resolution for functions, not before
+		if (s.needThis())
+		{
+version (DMDV2) {
+			bool cond = !s.isFuncDeclaration();
+} else {
+			bool cond = true;
+}
+			if (hasThis(sc) && cond)
+			{
+				// Supply an implicit 'this', as in
+				//	  this.ident
+				DotVarExp de = new DotVarExp(loc, new ThisExp(loc), s.isDeclaration());
+				return de.semantic(sc);
+			}
+		}
+
+		em = s.isEnumMember();
+		if (em)
+		{
+			e = em.value;
+			e = e.semantic(sc);
+			return e;
+		}
+		v = s.isVarDeclaration();
+		if (v)
+		{
+			//printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
+			if (!type)
+			{   
+				type = v.type;
+				if (!v.type)
+				{
+					error("forward reference of %s %s", v.kind(), v.toChars());
+					type = Type.terror;
+				}
+			}
+
+			e = new VarExp(loc, v);
+			e.type = type;
+			e = e.semantic(sc);
+			return e.deref();
+		}
+
+		fld = s.isFuncLiteralDeclaration();
+		if (fld)
+		{	
+			//printf("'%s' is a function literal\n", fld.toChars());
+			e = new FuncExp(loc, fld);
+			return e.semantic(sc);
+		}
+		f = s.isFuncDeclaration();
+		if (f)
+		{	
+			//printf("'%s' is a function\n", f.toChars());
+
+			if (!f.type.deco)
+			{
+				error("forward reference to %s", toChars());
+			}
+			return new VarExp(loc, f, hasOverloads);
+		}
+		o = s.isOverloadSet();
+		if (o)
+		{	
+			//printf("'%s' is an overload set\n", o.toChars());
+			return new OverExp(o);
+		}
+		cd = s.isClassDeclaration();
+		if (cd && thiscd && cd.isBaseOf(thiscd, null) && sc.func.needThis())
+		{
+			// We need to add an implicit 'this' if cd is this class or a base class.
+			DotTypeExp dte = new DotTypeExp(loc, new ThisExp(loc), s);
+			return dte.semantic(sc);
+		}
+		imp = s.isImport();
+		if (imp)
+		{
+			if (!imp.pkg)
+			{   
+				error("forward reference of import %s", imp.toChars());
+				return this;
+			}
+			ScopeExp ie = new ScopeExp(loc, imp.pkg);
+			return ie.semantic(sc);
+		}
+		pkg = s.isPackage();
+		if (pkg)
+		{
+			ScopeExp ie = new ScopeExp(loc, pkg);
+			return ie.semantic(sc);
+		}
+		Module mod = s.isModule();
+		if (mod)
+		{
+			ScopeExp ie = new ScopeExp(loc, mod);
+			return ie.semantic(sc);
+		}
+
+		t = s.getType();
+		if (t)
+		{
+			return new TypeExp(loc, t);
+		}
+
+		TupleDeclaration tup = s.isTupleDeclaration();
+		if (tup)
+		{
+			e = new TupleExp(loc, tup);
+			e = e.semantic(sc);
+			return e;
+		}
+
+		TemplateInstance ti = s.isTemplateInstance();
+		if (ti && !global.errors)
+		{   
+			if (!ti.semanticRun)
+				ti.semantic(sc);
+
+			s = ti.inst.toAlias();
+			if (!s.isTemplateInstance())
+				goto Lagain;
+
+			e = new ScopeExp(loc, ti);
+			e = e.semantic(sc);
+			return e;
+		}
+
+		TemplateDeclaration td = s.isTemplateDeclaration();
+		if (td)
+		{
+			e = new TemplateExp(loc, td);
+			e = e.semantic(sc);
+			return e;
+		}
+
+	Lerr:
+		error("%s '%s' is not a variable", s.kind(), s.toChars());
+		type = Type.terror;
+		return this;
+	}
+
+	string toChars()
+	{
+		assert(false);
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DsymbolTable.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,63 @@
+module dmd.DsymbolTable;
+
+import dmd.StringTable;
+import dmd.Dsymbol;
+import dmd.Identifier;
+import dmd.StringValue;
+
+import std.stdio;
+
+class DsymbolTable
+{
+    StringTable tab;
+
+    this()
+	{
+		tab = new StringTable;
+	}
+	
+    ~this()
+	{
+		delete tab;
+	}
+
+    // Look up Identifier. Return Dsymbol if found, NULL if not.
+    Dsymbol lookup(Identifier ident)
+	{
+debug {
+		assert(ident);
+		assert(tab);
+}
+		StringValue* sv = tab.lookup(ident.string_);
+		return (sv ? cast(Dsymbol)sv.ptrvalue : null);
+	}
+
+    // Insert Dsymbol in table. Return NULL if already there.
+    Dsymbol insert(Dsymbol s)
+	{
+		Identifier ident = s.ident;
+debug {
+		assert(ident);
+		assert(tab);
+}
+
+		return insert(ident, s);
+	}
+
+    // Look for Dsymbol in table. If there, return it. If not, insert s and return that.
+    Dsymbol update(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    Dsymbol insert(Identifier ident, Dsymbol s)	// when ident and s are not the same
+	{
+		StringValue* sv = tab.insert(ident.toChars());
+		if (sv is null) {
+			return null;		// already in table
+		}
+
+		sv.ptrvalue = cast(void*)s;
+		return s;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DtorDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,109 @@
+module dmd.DtorDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.Global;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.LINK;
+import dmd.AggregateDeclaration;
+import dmd.TypeFunction;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+import dmd.Id;
+
+class DtorDeclaration : FuncDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+		super(loc, endloc, Id.dtor, STCundefined, null);
+	}
+
+    this(Loc loc, Loc endloc, Identifier id)
+	{
+		assert(false);
+		super(loc, endloc, null, STC.init, null);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("DtorDeclaration::semantic() %s\n", toChars());
+		//printf("ident: %s, %s, %p, %p\n", ident.toChars(), Id::dtor.toChars(), ident, Id::dtor);
+		parent = sc.parent;
+		Dsymbol parent = toParent();
+		AggregateDeclaration ad = parent.isAggregateDeclaration();
+		if (!ad)
+		{
+			error("destructors are only for class/struct/union definitions, not %s %s", parent.kind(), parent.toChars());
+		}
+		else if (ident == Id.dtor)
+			ad.dtors.push(cast(void*)this);
+
+		type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
+
+		sc = sc.push();
+		sc.stc &= ~STCstatic;		// not a static destructor
+		sc.linkage = LINK.LINKd;
+
+		FuncDeclaration.semantic(sc);
+
+		sc.pop();
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		return "~this";
+	}
+	
+    bool isVirtual()
+	{
+		/* This should be FALSE so that dtor's don't get put into the vtbl[],
+		 * but doing so will require recompiling everything.
+		 */
+	version (BREAKABI) {
+		return false;
+	} else {
+		return FuncDeclaration.isVirtual();
+	}
+	}
+	
+    bool addPreInvariant()
+	{
+		return (isThis() && vthis && global.params.useInvariants);
+	}
+	
+    bool addPostInvariant()
+	{
+		return false;
+	}
+	
+    bool overloadInsert(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+
+    DtorDeclaration isDtorDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/EnumDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,416 @@
+module dmd.EnumDeclaration;
+
+import dmd.ScopeDsymbol;
+import dmd.AddExp;
+import dmd.Type;
+import dmd.CmpExp;
+import dmd.IntegerExp;
+import dmd.EqualExp;
+import dmd.TOK;
+import dmd.Id;
+import dmd.TY;
+import dmd.DsymbolTable;
+import dmd.STC;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Global;
+import dmd.Loc;
+import dmd.TypeEnum;
+import dmd.EnumMember;
+import dmd.DYNCAST;
+import dmd.WANT;
+import dmd.Id;
+import dmd.Lexer;
+
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.Util;
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.SFL;
+import dmd.backend.LIST;
+import dmd.codegen.Util;
+
+import std.stdio : writef;
+
+class EnumDeclaration : ScopeDsymbol
+{   /* enum ident : memtype { ... }
+     */
+    Type type;			// the TypeEnum
+    Type memtype;		// type of the members
+
+version (DMDV1) {
+    ulong maxval;
+    ulong minval;
+    ulong defaultval;	// default initializer
+} else {
+    Expression maxval;
+    Expression minval;
+    Expression defaultval;	// default initializer
+}
+    bool isdeprecated;
+
+    this(Loc loc, Identifier id, Type memtype)
+	{
+		super(id);
+		this.loc = loc;
+		type = new TypeEnum(this);
+		this.memtype = memtype;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		Type t;
+		Scope sce;
+
+		//writef("EnumDeclaration.semantic(sd = %p, '%s') %s\n", sc.scopesym, sc.scopesym.toChars(), toChars());
+		//writef("EnumDeclaration.semantic() %s\n", toChars());
+		if (!members)		// enum ident;
+			return;
+
+		if (!memtype && !isAnonymous())
+		{	
+			// Set memtype if we can to reduce fwd reference errors
+			memtype = Type.tint32;	// case 1)  enum ident { ... }
+		}
+
+		if (symtab)			// if already done
+		{	
+			if (!scope_)
+				return;		// semantic() already completed
+		}
+		else
+			symtab = new DsymbolTable();
+
+		Scope scx = null;
+		if (scope_)
+		{   sc = scope_;
+			scx = scope_;            // save so we don't make redundant copies
+			scope_ = null;
+		}
+
+		if (sc.stc & STC.STCdeprecated)
+			isdeprecated = true;
+
+		parent = sc.parent;
+
+		/* The separate, and distinct, cases are:
+		 *  1. enum { ... }
+		 *  2. enum : memtype { ... }
+		 *  3. enum ident { ... }
+		 *  4. enum ident : memtype { ... }
+		 */
+
+		if (memtype)
+		{
+			memtype = memtype.semantic(loc, sc);
+
+			/* Check to see if memtype is forward referenced
+			 */
+			if (memtype.ty == TY.Tenum)
+			{   EnumDeclaration sym = cast(EnumDeclaration)memtype.toDsymbol(sc);
+				if (!sym.memtype || !sym.members || !sym.symtab || sym.scope_)
+				{	
+					// memtype is forward referenced, so try again later
+					scope_ = scx ? scx : new Scope(sc);
+					scope_.setNoFree();
+					scope_.module_.addDeferredSemantic(this);
+					writef("\tdeferring %s\n", toChars());
+					return;
+				}
+			}
+static if (false) {
+		// Decided to abandon this restriction for D 2.0
+			if (!memtype.isintegral())
+			{   error("base type must be of integral type, not %s", memtype.toChars());
+				memtype = Type.tint32;
+			}
+}
+		}
+
+		type = type.semantic(loc, sc);
+		if (isAnonymous())
+			sce = sc;
+		else
+		{	sce = sc.push(this);
+		sce.parent = this;
+		}
+		if (members.dim == 0)
+		error("enum %s must have at least one member", toChars());
+		int first = 1;
+		Expression elast = null;
+		for (int i = 0; i < members.dim; i++)
+		{
+		EnumMember em = (cast(Dsymbol)members.data[i]).isEnumMember();
+		Expression e;
+
+		if (!em)
+			/* The e.semantic(sce) can insert other symbols, such as
+			 * template instances and function literals.
+			 */
+			continue;
+
+		//printf("  Enum member '%s'\n",em.toChars());
+		if (em.type)
+			em.type = em.type.semantic(em.loc, sce);
+		e = em.value;
+		if (e)
+		{
+			assert(e.dyncast() == DYNCAST.DYNCAST_EXPRESSION);
+			e = e.semantic(sce);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (memtype)
+			{
+			e = e.implicitCastTo(sce, memtype);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (!isAnonymous())
+				e = e.castTo(sce, type);
+			t = memtype;
+			}
+			else if (em.type)
+			{
+			e = e.implicitCastTo(sce, em.type);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			assert(isAnonymous());
+			t = e.type;
+			}
+			else
+			t = e.type;
+		}
+		else if (first)
+		{
+			if (memtype)
+			t = memtype;
+			else if (em.type)
+			t = em.type;
+			else
+			t = Type.tint32;
+			e = new IntegerExp(em.loc, 0, Type.tint32);
+			e = e.implicitCastTo(sce, t);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (!isAnonymous())
+			e = e.castTo(sce, type);
+		}
+		else
+		{
+			// Set value to (elast + 1).
+			// But first check that (elast != t.max)
+			assert(elast);
+			e = new EqualExp(TOK.TOKequal, em.loc, elast, t.getProperty(Loc(0), Id.max));
+			e = e.semantic(sce);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (e.toInteger())
+			error("overflow of enum value %s", elast.toChars());
+
+			// Now set e to (elast + 1)
+			e = new AddExp(em.loc, elast, new IntegerExp(em.loc, 1, Type.tint32));
+			e = e.semantic(sce);
+			e = e.castTo(sce, elast.type);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		}
+		elast = e;
+		em.value = e;
+
+		// Add to symbol table only after evaluating 'value'
+		if (isAnonymous())
+		{
+			/* Anonymous enum members get added to enclosing scope.
+			 */
+			for (Scope scxx = sce; scxx; scxx = scxx.enclosing)
+			{
+				if (scxx.scopesym)
+				{
+					if (!scxx.scopesym.symtab)
+						scxx.scopesym.symtab = new DsymbolTable();
+					em.addMember(sce, scxx.scopesym, 1);
+					break;
+				}
+			}
+		}
+		else
+			em.addMember(sc, this, 1);
+
+		/* Compute .min, .max and .default values.
+		 * If enum doesn't have a name, we can never identify the enum type,
+		 * so there is no purpose for a .min, .max or .default
+		 */
+		if (!isAnonymous())
+		{
+			if (first)
+			{	defaultval = e;
+			minval = e;
+			maxval = e;
+			}
+			else
+			{	Expression ec;
+
+			/* In order to work successfully with UDTs,
+			 * build expressions to do the comparisons,
+			 * and let the semantic analyzer and constant
+			 * folder give us the result.
+			 */
+
+			// Compute if(e < minval)
+			ec = new CmpExp(TOK.TOKlt, em.loc, e, minval);
+			ec = ec.semantic(sce);
+			ec = ec.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (ec.toInteger())
+				minval = e;
+
+			ec = new CmpExp(TOK.TOKgt, em.loc, e, maxval);
+			ec = ec.semantic(sce);
+			ec = ec.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			if (ec.toInteger())
+				maxval = e;
+			}
+		}
+		first = 0;
+		}
+		//printf("defaultval = %lld\n", defaultval);
+
+		//if (defaultval) printf("defaultval: %s %s\n", defaultval.toChars(), defaultval.type.toChars());
+		if (sc != sce)
+		sce.pop();
+		//members.print();
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    Type getType()
+	{
+		return type;
+	}
+	
+    string kind()
+	{
+		return "enum";
+	}
+	
+version (DMDV2) {
+    Dsymbol search(Loc, Identifier ident, int flags)
+	{
+		//printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident->toChars());
+		if (scope_)
+			// Try one last time to resolve this enum
+			semantic(scope_);
+
+		if (!members || !symtab || scope_)
+		{   
+			error("is forward referenced when looking for '%s'", ident.toChars());
+			//*(char*)0=0;
+			return null;
+		}
+
+		return ScopeDsymbol.search(loc, ident, flags);
+	}
+}
+    bool isDeprecated()			// is Dsymbol deprecated?
+	{
+		return isdeprecated;
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    EnumDeclaration isEnumDeclaration() { return this; }
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		//printf("EnumDeclaration::toObjFile('%s')\n", toChars());
+	version (DMDV2) {
+		if (isAnonymous())
+			return;
+	}
+
+		if (global.params.symdebug)
+			toDebug();
+
+		type.getTypeInfo(null);	// generate TypeInfo
+
+		TypeEnum tc = cast(TypeEnum)type;
+		if (!tc.sym.defaultval || type.isZeroInit(Loc(0))) {
+			;
+		} else {
+			SC scclass = SCglobal;
+			if (inTemplateInstance())
+				scclass = SCcomdat;
+
+			// Generate static initializer
+			toInitializer();
+			sinit.Sclass = scclass;
+			sinit.Sfl = FLdata;
+		version (ELFOBJ) { // Burton
+			sinit.Sseg = Segment.CDATA;
+		}
+		version (MACHOBJ) {
+			sinit.Sseg = Segment.DATA;
+		}
+		version (DMDV1) {
+			dtnbytes(&sinit.Sdt, tc.size(0), cast(char*)&tc.sym.defaultval);
+			//sinit->Sdt = tc->sym->init->toDt();
+		}
+		version (DMDV2) {
+			tc.sym.defaultval.toDt(&sinit.Sdt);
+		}
+			outdata(sinit);
+		}
+	}
+	
+    void toDebug()
+	{
+		assert(false);
+	}
+	
+    int cvMember(ubyte* p)
+	{
+		assert(false);
+	}
+
+    Symbol* sinit;
+
+    Symbol* toInitializer()
+	{
+		Symbol* s;
+		Classsym* stag;
+
+		if (!sinit)
+		{
+			stag = fake_classsym(Id.ClassInfo);
+			Identifier ident_save = ident;
+			if (!ident)
+				ident = Lexer.uniqueId("__enum");
+			s = toSymbolX("__init", SCextern, stag.Stype, "Z");
+			ident = ident_save;
+			s.Sfl = FLextern;
+			s.Sflags |= SFLnodebug;
+			slist_add(s);
+			sinit = s;
+		}
+
+		return sinit;
+	}
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/EnumMember.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,52 @@
+module dmd.EnumMember;
+
+import dmd.Dsymbol;
+import dmd.Expression;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class EnumMember : Dsymbol
+{
+    Expression value;
+    Type type;
+
+    this(Loc loc, Identifier id, Expression value, Type type)
+	{
+		super(id);
+		
+		this.value = value;
+		this.type = type;
+		this.loc = loc;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    EnumMember isEnumMember() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/EnumUtils.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,11 @@
+module dmd.EnumUtils;
+
+string BringToCurrentScope(alias enumType)()
+{
+	string s = "";
+	foreach (i, e; __traits(allMembers, enumType)) {
+		s ~= "alias " ~ enumType.stringof ~ "." ~ __traits(allMembers, enumType)[i] ~ " " ~ __traits(allMembers, enumType)[i] ~ ";\n";
+	}
+	
+	return s;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/EqualExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,237 @@
+module dmd.EqualExp;
+
+import dmd.Expression;
+import dmd.Id;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.AddrExp;
+import dmd.VarExp;
+import dmd.IntegerExp;
+import dmd.TY;
+import dmd.Token;
+import dmd.NotExp;
+import dmd.WANT;
+import dmd.GlobalExpressions;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.RTLSYM;
+
+import dmd.codegen.Util;
+
+import dmd.expression.util.arrayTypeCompatible;
+import dmd.expression.Util;
+import dmd.expression.Equal;
+
+class EqualExp : BinExp
+{
+	this(TOK op, Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, op, EqualExp.sizeof, e1, e2);
+		assert(op == TOK.TOKequal || op == TOK.TOKnotequal);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t1;
+		Type t2;
+
+		//printf("EqualExp.semantic('%s')\n", toChars());
+		if (type)
+			return this;
+
+		BinExp.semanticp(sc);
+
+		/* Before checking for operator overloading, check to see if we're
+		 * comparing the addresses of two statics. If so, we can just see
+		 * if they are the same symbol.
+		 */
+		if (e1.op == TOK.TOKaddress && e2.op == TOK.TOKaddress)
+		{	
+			AddrExp ae1 = cast(AddrExp)e1;
+			AddrExp ae2 = cast(AddrExp)e2;
+
+			if (ae1.e1.op == TOK.TOKvar && ae2.e1.op == TOK.TOKvar)
+			{   
+				VarExp ve1 = cast(VarExp)ae1.e1;
+				VarExp ve2 = cast(VarExp)ae2.e1;
+
+				if (ve1.var == ve2.var /*|| ve1.var.toSymbol() == ve2.var.toSymbol()*/)
+				{
+					// They are the same, result is 'true' for ==, 'false' for !=
+					e = new IntegerExp(loc, (op == TOK.TOKequal), Type.tboolean);
+					return e;
+				}
+			}
+		}
+
+		if (e1.type.toBasetype().ty == TY.Tclass && e2.op == TOK.TOKnull || e2.type.toBasetype().ty == TY.Tclass && e1.op == TOK.TOKnull)
+		{
+			error("use '%s' instead of '%s' when comparing with null",
+				Token.toChars(op == TOK.TOKequal ? TOK.TOKidentity : TOK.TOKnotidentity),
+				Token.toChars(op));
+		}
+
+		//if (e2.op != TOKnull)
+		{
+			e = op_overload(sc);
+			if (e)
+			{
+				if (op == TOK.TOKnotequal)
+				{
+					e = new NotExp(e.loc, e);
+					e = e.semantic(sc);
+				}
+
+				return e;
+			}
+		}
+
+		e = typeCombine(sc);
+		type = Type.tboolean;
+
+		// Special handling for array comparisons
+		if (!arrayTypeCompatible(loc, e1.type, e2.type))
+		{
+			if (e1.type != e2.type && e1.type.isfloating() && e2.type.isfloating())
+			{
+				// Cast both to complex
+				e1 = e1.castTo(sc, Type.tcomplex80);
+				e2 = e2.castTo(sc, Type.tcomplex80);
+			}
+		}
+
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
+		e1 = e1.optimize(WANTvalue | (result & WANTinterpret));
+		e2 = e2.optimize(WANTvalue | (result & WANTinterpret));
+		e = this;
+
+		Expression e1 = fromConstInitializer(result, this.e1);
+		Expression e2 = fromConstInitializer(result, this.e2);
+
+		e = Equal(op, type, e1, e2);
+		if (e is EXP_CANT_INTERPRET)
+			e = this;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.eq;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		//printf("EqualExp::toElem() %s\n", toChars());
+		elem* e;
+		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);
+		static if (true) {
+			es1 = addressElem(es1, t1);
+			es2 = addressElem(es2, t2);
+		} else {
+			es1 = el_una(OPaddr, TYnptr, es1);
+			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);
+		}
+///	static if (false) {
+///		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));
+///		}
+///	}
+		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);
+
+		version (DMDV2) {
+			ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs),
+				ea2, ea1, null);
+			rtlfunc = RTLSYM_ARRAYEQ2;
+		} else {
+			ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null);
+			rtlfunc = RTLSYM_ARRAYEQ;
+		}
+			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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ErrorExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,25 @@
+module dmd.ErrorExp;
+
+import dmd.OutBuffer;
+import dmd.IntegerExp;
+import dmd.Loc;
+import dmd.HdrGenState;
+import dmd.Type;
+
+/* Use this expression for error recovery.
+ * It should behave as a 'sink' to prevent further cascaded error messages.
+ */
+
+class ErrorExp : IntegerExp
+{
+	this()
+	{
+		super(Loc(0), 0, Type.terror);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("__error");
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Escape.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,11 @@
+module dmd.Escape;
+
+struct Escape
+{
+    const(char)* strings[256];
+
+    static const(char)* escapeChar(uint c)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ExpInitializer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,115 @@
+module dmd.ExpInitializer;
+
+import dmd.Initializer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Type;
+import dmd.SymOffExp;
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.WANT;
+import dmd.TOK;
+import dmd.StringExp;
+import dmd.TY;
+import dmd.TypeSArray;
+
+import dmd.backend.dt_t;
+
+class ExpInitializer : Initializer
+{
+    Expression exp;
+
+    this(Loc loc, Expression exp)
+	{
+		super(loc);
+		this.exp = exp;
+	}
+	
+    Initializer syntaxCopy()
+	{
+		return new ExpInitializer(loc, exp.syntaxCopy());
+	}
+	
+    Initializer semantic(Scope sc, Type t)
+	{
+		//printf("ExpInitializer.semantic(%s), type = %s\n", exp.toChars(), t.toChars());
+		exp = exp.semantic(sc);
+		exp = resolveProperties(sc, exp);
+		exp = exp.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		Type tb = t.toBasetype();
+
+		/* Look for case of initializing a static array with a too-short
+		 * string literal, such as:
+		 *	char[5] foo = "abc";
+		 * Allow this by doing an explicit cast, which will lengthen the string
+		 * literal.
+		 */
+		if (exp.op == TOK.TOKstring && tb.ty == TY.Tsarray && exp.type.ty == TY.Tsarray)
+		{	
+			StringExp se = cast(StringExp)exp;
+
+			if (!se.committed && se.type.ty == TY.Tsarray && (cast(TypeSArray)se.type).dim.toInteger() < (cast(TypeSArray)t).dim.toInteger())
+			{
+				exp = se.castTo(sc, t);
+				goto L1;
+			}
+		}
+
+		// Look for the case of statically initializing an array
+		// with a single member.
+		if (tb.ty == TY.Tsarray && !tb.nextOf().equals(exp.type.toBasetype().nextOf()) && exp.implicitConvTo(tb.nextOf()))
+		{
+			t = tb.nextOf();
+		}
+
+		exp = exp.implicitCastTo(sc, t);
+	L1:
+		exp = exp.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		//printf("-ExpInitializer.semantic(): "); exp.print();
+		return this;
+	}
+	
+    Type inferType(Scope sc)
+	{
+		//printf("ExpInitializer::inferType() %s\n", toChars());
+		exp = exp.semantic(sc);
+		exp = resolveProperties(sc, exp);
+
+		// Give error for overloaded function addresses
+		if (exp.op == TOKsymoff)
+		{   
+			SymOffExp se = cast(SymOffExp)exp;
+			if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
+				exp.error("cannot infer type from overloaded function symbol %s", exp.toChars());
+		}
+
+		Type t = exp.type;
+		if (!t)
+			t = Initializer.inferType(sc);
+
+		return t;
+	}
+	
+    Expression toExpression()
+	{
+		return exp;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    dt_t* toDt()
+	{
+		dt_t* dt = null;
+
+		exp = exp.optimize(WANT.WANTvalue);
+		exp.toDt(&dt);
+
+		return dt;
+	}
+
+    ExpInitializer isExpInitializer() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ExpStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,125 @@
+module dmd.ExpStatement;
+
+import dmd.Loc;
+import dmd.Statement;
+import dmd.AssertExp;
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.TOK;
+import dmd.DeclarationStatement;
+
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+
+class ExpStatement : Statement
+{
+    Expression exp;
+
+    this(Loc loc, Expression exp)
+	{
+		super(loc);
+		this.exp = exp;
+	}
+	
+    Statement syntaxCopy()
+	{
+		Expression e = exp ? exp.syntaxCopy() : null;
+		ExpStatement es = new ExpStatement(loc, e);
+		return es;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		if (exp)
+			exp.toCBuffer(buf, hgs);
+		buf.writeByte(';');
+		if (!hgs.FLinit.init)
+			buf.writenl();
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		if (exp)
+		{
+			//printf("ExpStatement::semantic() %s\n", exp->toChars());
+			exp = exp.semantic(sc);
+			exp = resolveProperties(sc, exp);
+			exp.checkSideEffect(0);
+			exp = exp.optimize(0);
+			if (exp.op == TOK.TOKdeclaration && !isDeclarationStatement())
+			{   
+				Statement s = new DeclarationStatement(loc, exp);
+				return s;
+			}
+			//exp = exp.optimize(isDeclarationStatement() ? WANT.WANTvalue : 0);
+		}
+		return this;
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    BE blockExit()
+	{
+		BE result = BE.BEfallthru;
+
+		if (exp)
+		{
+			if (exp.op == TOK.TOKhalt)
+				return BE.BEhalt;
+			if (exp.op == TOK.TOKassert)
+			{   	
+				AssertExp a = cast(AssertExp)exp;
+
+				if (a.e1.isBool(false))	// if it's an assert(0)
+					return BE.BEhalt;
+			}
+			if (exp.canThrow())
+				result |= BE.BEthrow;
+		}
+		return result;
+	}
+
+    int inlineCost(InlineCostState* ics)
+	{
+		return exp ? exp.inlineCost(ics) : 0;
+	}
+
+    Expression doInline(InlineDoState ids)
+	{
+	version (LOG) {
+		if (exp) printf("ExpStatement.doInline() '%s'\n", exp.toChars());
+	}
+		return exp ? exp.doInline(ids) : null;
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+	version (LOG) {
+		printf("ExpStatement.inlineScan(%s)\n", toChars());
+	}
+		if (exp)
+			exp = exp.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		Blockx* blx = irs.blx;
+
+		//printf("ExpStatement.toIR(), exp = %s\n", exp ? exp.toChars() : "");
+		incUsage(irs, loc);
+		if (exp) 
+			block_appendexp(blx.curblock, exp.toElem(irs));
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Expression.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,908 @@
+module dmd.Expression;
+
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Type;
+import dmd.WANT;
+import dmd.Scope;
+import dmd.ArrayTypes;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.MATCH;
+import dmd.IntRange;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.InterState;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.InlineScanState;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.DotIdExp;
+import dmd.TypeExp;
+import dmd.DYNCAST;
+import dmd.TY;
+import dmd.CallExp;
+import dmd.VarExp;
+import dmd.STC;
+import dmd.TemplateInstance;
+import dmd.CommaExp;
+import dmd.NullExp;
+import dmd.AddrExp;
+import dmd.ErrorExp;
+import dmd.TypeStruct;
+import dmd.CastExp;
+import dmd.Global;
+import dmd.Token;
+import dmd.TypeClass;
+import dmd.PtrExp;
+import dmd.TypeSArray;
+import dmd.TypeReference;
+import dmd.Util;
+import dmd.Complex;
+
+import dmd.backend.elem;
+import dmd.backend.dt_t;
+
+import std.stdio : writef;
+import core.stdc.stdlib : malloc;
+
+import std.conv;
+
+/* Things like:
+ *	int.size
+ *	foo.size
+ *	(foo).size
+ *	cast(foo).size
+ */
+
+Expression typeDotIdExp(Loc loc, Type type, Identifier ident)
+{
+	return new DotIdExp(loc, new TypeExp(loc, type), ident);
+}
+
+/*****************************************
+ * Determine if 'this' is available.
+ * If it is, return the FuncDeclaration that has it.
+ */
+
+FuncDeclaration hasThis(Scope sc)
+{  
+	FuncDeclaration fd;
+    FuncDeclaration fdthis;
+
+    //printf("hasThis()\n");
+    fdthis = sc.parent.isFuncDeclaration();
+    //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis.toChars() : "");
+
+    // Go upwards until we find the enclosing member function
+    fd = fdthis;
+    while (1)
+    {
+		if (!fd)
+		{
+			goto Lno;
+		}
+		if (!fd.isNested())
+			break;
+
+		Dsymbol parent = fd.parent;
+		while (parent)
+		{
+			TemplateInstance ti = parent.isTemplateInstance();
+			if (ti)
+				parent = ti.parent;
+			else
+				break;
+		}
+
+		fd = fd.parent.isFuncDeclaration();
+    }
+
+    if (!fd.isThis())
+    {  
+		//printf("test '%s'\n", fd.toChars());
+		goto Lno;
+    }
+
+    assert(fd.vthis);
+    return fd;
+
+Lno:
+    return null;		// don't have 'this' available
+}
+
+/***************************************
+ * Pull out any properties.
+ */
+
+Expression resolveProperties(Scope sc, Expression e)
+{
+    //printf("resolveProperties(%s)\n", e.toChars());
+    if (e.type)
+    {
+		Type t = e.type.toBasetype();
+
+		if (t.ty == TY.Tfunction || e.op == TOK.TOKoverloadset)
+		{
+			e = new CallExp(e.loc, e);
+			e = e.semantic(sc);
+		}
+
+		/* Look for e being a lazy parameter; rewrite as delegate call
+		 */
+		else if (e.op == TOK.TOKvar)
+		{   VarExp ve = cast(VarExp)e;
+
+			if (ve.var.storage_class & STC.STClazy)
+			{
+				e = new CallExp(e.loc, e);
+				e = e.semantic(sc);
+			}
+		}
+
+		else if (e.op == TOK.TOKdotexp)
+		{
+			e.error("expression has no value");
+		}
+    }
+    else if (e.op == TOK.TOKdottd)
+    {
+		e = new CallExp(e.loc, e);
+		e = e.semantic(sc);
+    }
+
+    return e;
+}
+
+class Expression
+{
+    Loc loc;			// file location
+    TOK op;		// handy to minimize use of dynamic_cast
+    Type type;			// !=null means that semantic() has been run
+    int size;			// # of bytes in Expression so we can copy() it
+
+    this(Loc loc, TOK op, int size)
+	{
+		this.loc = loc;
+		//writef("Expression.Expression(op = %d %s) this = %p\n", op, to!(string)(op), this);
+		this.op = op;
+		this.size = size;
+		type = null;
+	}
+
+	int equals(Object o)
+	{
+		return this is o;
+	}
+
+	/*********************************
+	 * Does *not* do a deep copy.
+	 */
+    Expression copy()	/// bad bad bad
+	{
+		Expression e;
+		if (!size)
+		{
+debug {
+			writef("No expression copy for: %s\n", toChars());
+			writef("op = %d\n", op);
+			dump(0);
+}
+			assert(0);
+		}
+		auto size = this.classinfo.init.length;
+		auto ptr = malloc(size);
+		memcpy(ptr, cast(void*)this, size);
+
+		return cast(Expression)ptr;
+	}
+	
+    Expression syntaxCopy()
+	{
+		//printf("Expression::syntaxCopy()\n");
+		//dump(0);
+		return copy();
+	}
+	
+    Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("Expression.semantic() %s\n", toChars());
+	}
+		if (type)
+			type = type.semantic(loc, sc);
+		else
+			type = Type.tvoid;
+		return this;
+	}
+	
+    Expression trySemantic(Scope sc)
+	{
+		uint errors = global.errors;
+		global.gag++;
+		Expression e = semantic(sc);
+		global.gag--;
+		if (errors != global.errors)
+		{
+			global.errors = errors;
+			e = null;
+		}
+		return e;
+	}
+
+    DYNCAST dyncast() { return DYNCAST.DYNCAST_EXPRESSION; }	// kludge for template.isExpression()
+
+    void print()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		scope OutBuffer buf = new OutBuffer();
+		HdrGenState hgs;
+	
+		toCBuffer(buf, &hgs);
+		return buf.toChars();
+	}
+	
+    void dump(int indent)
+	{
+		assert(false);
+	}
+
+    void error(T...)(string format, T t)
+	{
+		.error(loc, format, t);
+	}
+	
+    void warning(T...)(string formar, T t)
+	{
+		.warning(loc, format, t);
+	}
+
+    void rvalue()
+	{
+		if (type && type.toBasetype().ty == TY.Tvoid)
+		{	
+			error("expression %s is void and has no value", toChars());
+static if (false) {
+			dump(0);
+			halt();
+}
+			type = Type.terror;
+		}
+	}
+
+    static Expression combine(Expression e1, Expression e2)
+	{
+		if (e1)
+		{
+			if (e2)
+			{
+				e1 = new CommaExp(e1.loc, e1, e2);
+				e1.type = e2.type;
+			}
+		}
+		else
+		{
+			e1 = e2;
+		}
+
+		return e1;
+	}
+    
+	static Expressions arraySyntaxCopy(Expressions exps)
+	{
+		Expressions a = null;
+
+		if (exps)
+		{
+			a = new Expressions();
+			a.setDim(exps.dim);
+			for (int i = 0; i < a.dim; i++)
+			{   
+				Expression e = cast(Expression)exps.data[i];
+
+				e = e.syntaxCopy();
+				a.data[i] = cast(void*)e;
+			}
+		}
+		return a;
+	}
+
+    ulong toInteger()
+	{
+		assert(false);
+	}
+    
+    ulong toUInteger()
+	{
+		//printf("Expression %s\n", Token.toChars(op));
+		return cast(ulong)toInteger();
+	}
+    
+    real toReal()
+	{
+		assert(false);
+	}
+    
+    real toImaginary()
+	{
+		assert(false);
+	}
+    
+    Complex!(real) toComplex()
+	{
+		assert(false);
+	}
+    
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(Token.toChars(op));
+	}
+    
+    void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+    
+    int isLvalue()
+	{
+		assert(false);
+	}
+    
+    Expression toLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+    
+    Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		//printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type.toChars());
+
+		// See if this expression is a modifiable lvalue (i.e. not const)
+version (DMDV2) {
+		if (type && (!type.isMutable() || !type.isAssignable()))
+			error("%s is not mutable", e.toChars());
+}
+		return toLvalue(sc, e);
+	}
+    
+	/**************************************
+	 * Do an implicit cast.
+	 * Issue error if it can't be done.
+	 */
+    Expression implicitCastTo(Scope sc, Type t)
+	{
+		//printf("Expression.implicitCastTo(%s of type %s) => %s\n", toChars(), type.toChars(), t.toChars());
+
+		MATCH match = implicitConvTo(t);
+		if (match)
+		{
+			TY tyfrom = type.toBasetype().ty;
+			TY tyto = t.toBasetype().ty;
+
+version (DMDV1) {
+			if (global.params.warnings &&
+				Type.impcnvWarn[tyfrom][tyto] &&
+				op != TOKint64)
+			{
+				Expression e = optimize(WANT.WANTflags | WANT.WANTvalue);
+
+				if (e.op == TOK.TOKint64)
+				return e.implicitCastTo(sc, t);
+				if (tyfrom == Tint32 && (op == TOKadd || op == TOKmin || op == TOKand || op == TOKor || op == TOKxor))
+				{
+					/* This is really only a semi-kludge fix,
+					 * we really should look at the operands of op
+					 * and see if they are narrower types.
+					 * For example, b=b|b and b=b|7 and s=b+b should be allowed,
+					 * but b=b|i should be an error.
+					 */
+					;
+				}
+				else
+				{
+					warning("implicit conversion of expression (%s) of type %s to %s can cause loss of data", toChars(), type.toChars(), t.toChars());
+				}
+			}
+}
+version (DMDV2) {
+			if (match == MATCH.MATCHconst && t == type.constOf())
+			{
+				Expression e = copy();
+				e.type = t;
+				return e;
+			}
+}
+			return castTo(sc, t);
+		}
+
+		Expression e = optimize(WANT.WANTflags | WANT.WANTvalue);
+		if (e != this)
+			return e.implicitCastTo(sc, t);
+
+static if (false) {
+	printf("ty = %d\n", type.ty);
+	print();
+	type.print();
+	printf("to:\n");
+	t.print();
+	printf("%p %p type: %s to: %s\n", type.deco, t.deco, type.deco, t.deco);
+	//printf("%p %p %p\n", type.nextOf().arrayOf(), type, t);
+	fflush(stdout);
+}
+		if (!t.deco) {
+			/* Can happen with:
+			 *    enum E { One }
+			 *    class A
+			 *    { static void fork(EDG dg) { dg(E.One); }
+			 *	alias void delegate(E) EDG;
+			 *    }
+			 * Should eventually make it work.
+			 */
+			error("forward reference to type %s", t.toChars());
+		} else if (t.reliesOnTident()) {
+			error("forward reference to type %s", t.reliesOnTident().toChars());
+		}
+
+		error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), type.toChars(), t.toChars());
+		return castTo(sc, t);
+	}
+    
+	/*******************************************
+	 * Return !=0 if we can implicitly convert this to type t.
+	 * Don't do the actual cast.
+	 */
+    MATCH implicitConvTo(Type t)
+	{
+static if (false) {
+		printf("Expression.implicitConvTo(this=%s, type=%s, t=%s)\n",
+			toChars(), type.toChars(), t.toChars());
+}
+		//static int nest; if (++nest == 10) halt();
+		if (!type)
+		{	
+			error("%s is not an expression", toChars());
+			type = Type.terror;
+		}
+		Expression e = optimize(WANT.WANTvalue | WANT.WANTflags);
+		if (e.type == t)
+			return MATCH.MATCHexact;
+		if (e != this)
+		{	
+			//printf("\toptimized to %s of type %s\n", e.toChars(), e.type.toChars());
+			return e.implicitConvTo(t);
+		}
+		MATCH match = type.implicitConvTo(t);
+		if (match != MATCH.MATCHnomatch)
+			return match;
+
+		/* See if we can do integral narrowing conversions
+		 */
+		if (type.isintegral() && t.isintegral() &&
+		type.isTypeBasic() && t.isTypeBasic())
+		{	
+			IntRange ir = getIntRange();
+			if (ir.imax <= t.sizemask())
+				return MATCH.MATCHconvert;
+		}
+
+static if (false) {
+		Type tb = t.toBasetype();
+		if (tb.ty == Tdelegate)
+		{	
+			TypeDelegate td = cast(TypeDelegate)tb;
+			TypeFunction tf = cast(TypeFunction)td.nextOf();
+
+			if (!tf.varargs && !(tf.arguments && tf.arguments.dim))
+			{
+				match = type.implicitConvTo(tf.nextOf());
+				if (match)
+					return match;
+				if (tf.nextOf().toBasetype().ty == Tvoid)
+					return MATCH.MATCHconvert;
+			}
+		}
+}
+		return MATCH.MATCHnomatch;
+	}
+
+    IntRange getIntRange()
+	{
+		assert(false);
+	}
+	
+	/**************************************
+	 * Do an explicit cast.
+	 */
+    Expression castTo(Scope sc, Type t)
+	{
+		//printf("Expression.castTo(this=%s, t=%s)\n", toChars(), t.toChars());
+static if (false) {
+		writef("Expression.castTo(this=%s, type=%s, t=%s)\n",
+		toChars(), type.toChars(), t.toChars());
+}
+		if (type is t)
+			return this;
+		Expression e = this;
+		Type tb = t.toBasetype();
+		Type typeb = type.toBasetype();
+		if (tb != typeb)
+		{
+			// Do (type *) cast of (type [dim])
+			if (tb.ty == TY.Tpointer && typeb.ty == TY.Tsarray
+			   )
+			{
+				//printf("Converting [dim] to *\n");
+
+				if (typeb.size(loc) == 0)
+					e = new NullExp(loc);
+				else
+					e = new AddrExp(loc, e);
+			}
+			else {
+static if (false) {
+				if (tb.ty == Tdelegate && type.ty != Tdelegate)
+				{
+					TypeDelegate td = cast(TypeDelegate)tb;
+					TypeFunction tf = cast(TypeFunction)td.nextOf();
+					return toDelegate(sc, tf.nextOf());
+				}
+}
+				if (typeb.ty == TY.Tstruct)
+				{   
+					TypeStruct ts = cast(TypeStruct)typeb;
+					if (!(tb.ty == TY.Tstruct && ts.sym == (cast(TypeStruct)tb).sym) &&
+						ts.sym.aliasthis)
+					{   /* Forward the cast to our alias this member, rewrite to:
+						 *   cast(to)e1.aliasthis
+						 */
+						Expression e1 = new DotIdExp(loc, this, ts.sym.aliasthis.ident);
+						Expression e2 = new CastExp(loc, e1, tb);
+						e2 = e2.semantic(sc);
+						return e2;
+					}
+				}
+				else if (typeb.ty == TY.Tclass)
+				{   
+					TypeClass ts = cast(TypeClass)typeb;
+					if (tb.ty != TY.Tclass && ts.sym.aliasthis)
+					{   /* Forward the cast to our alias this member, rewrite to:
+						 *   cast(to)e1.aliasthis
+						 */
+						Expression e1 = new DotIdExp(loc, this, ts.sym.aliasthis.ident);
+						Expression e2 = new CastExp(loc, e1, tb);
+						e2 = e2.semantic(sc);
+						return e2;
+					}
+				}
+				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;
+	}
+    
+	/************************************
+	 * Detect cases where pointers to the stack can 'escape' the
+	 * lifetime of the stack frame.
+	 */
+    void checkEscape()
+	{
+	}
+    
+    void checkScalar()
+	{
+		if (!type.isscalar())
+			error("'%s' is not a scalar, it is a %s", toChars(), type.toChars());
+
+		rvalue();
+	}
+
+    void checkNoBool()
+	{
+		if (type.toBasetype().ty == TY.Tbool)
+			error("operation not allowed on bool '%s'", toChars());
+	}
+    
+    Expression checkIntegral()
+	{
+		if (!type.isintegral())
+		{	
+			error("'%s' is not of integral type, it is a %s", toChars(), type.toChars());
+			return new ErrorExp();
+		}
+
+		rvalue();
+		return this;
+	}
+    
+    Expression checkArithmetic()
+	{
+		if (!type.isintegral() && !type.isfloating())
+		{	
+			error("'%s' is not of arithmetic type, it is a %s", toChars(), type.toChars());
+			return new ErrorExp();
+		}
+
+		rvalue();
+		return this;
+	}
+    
+    void checkDeprecated(Scope sc, Dsymbol s)
+	{
+		s.checkDeprecated(loc, sc);
+	}
+    
+    void checkPurity(Scope sc, FuncDeclaration f)
+	{
+static if (true) {
+		if (sc.func)
+		{
+			FuncDeclaration outerfunc = sc.func;
+			while (outerfunc.toParent2() && outerfunc.toParent2().isFuncDeclaration())
+			{
+				outerfunc = outerfunc.toParent2().isFuncDeclaration();
+			}
+			if (outerfunc.isPure()  && !sc.intypeof && (!f.isNested() && !f.isPure()))
+				error("pure function '%s' cannot call impure function '%s'\n",
+				sc.func.toChars(), f.toChars());
+		}
+} else {
+		if (sc.func && sc.func.isPure() && !sc.intypeof && !f.isPure())
+		error("pure function '%s' cannot call impure function '%s'\n",
+			sc.func.toChars(), .toChars());
+}
+	}
+    
+	/*****************************
+	 * Check that expression can be tested for true or false.
+	 */
+    Expression checkToBoolean()
+	{
+		// Default is 'yes' - do nothing
+
+debug {
+		if (!type)
+			dump(0);
+}
+
+		if (!type.checkBoolean())
+		{
+			error("expression %s of type %s does not have a boolean value", toChars(), type.toChars());
+		}
+
+		return this;
+	}
+    
+    Expression checkToPointer()
+	{
+		Expression e;
+		Type tb;
+
+		//printf("Expression::checkToPointer()\n");
+		e = this;
+
+		// If C static array, convert to pointer
+		tb = type.toBasetype();
+		if (tb.ty == Tsarray)
+		{	
+			TypeSArray ts = cast(TypeSArray)tb;
+			if (ts.size(loc) == 0)
+				e = new NullExp(loc);
+			else
+				e = new AddrExp(loc, this);
+			e.type = ts.next.pointerTo();
+		}
+		return e;
+	}
+    
+    Expression addressOf(Scope sc)
+	{
+		//printf("Expression::addressOf()\n");
+		Expression e = toLvalue(sc, null);
+		e = new AddrExp(loc, e);
+		e.type = type.pointerTo();
+		return e;
+	}
+    
+	/******************************
+	 * If this is a reference, dereference it.
+	 */
+    Expression deref()
+	{
+		//printf("Expression::deref()\n");
+		if (type.ty == TY.Treference)
+		{	
+			Expression e = new PtrExp(loc, this);
+			e.type = (cast(TypeReference)type).next;
+			return e;
+		}
+		return this;
+	}
+    
+	/***********************************
+	 * Do integral promotions (convertchk).
+	 * Don't convert <array of> to <pointer to>
+	 */
+    Expression integralPromotions(Scope sc)
+	{
+		Expression e = this;
+
+		//printf("integralPromotions %s %s\n", e.toChars(), e.type.toChars());
+		switch (type.toBasetype().ty)
+		{
+			case TY.Tvoid:
+				error("void has no value");
+				break;
+
+			case TY.Tint8:
+			case TY.Tuns8:
+			case TY.Tint16:
+			case TY.Tuns16:
+			case TY.Tbit:
+			case TY.Tbool:
+			case TY.Tchar:
+			case TY.Twchar:
+				e = e.castTo(sc, Type.tint32);
+				break;
+
+			case TY.Tdchar:
+				e = e.castTo(sc, Type.tuns32);
+				break;
+			default:
+				break;	///
+		}
+		return e;
+	}
+    
+    Expression toDelegate(Scope sc, Type t)
+	{
+		assert(false);
+	}
+    
+    void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+    
+    Expression optimize(int result)
+	{
+		//printf("Expression.optimize(result = x%x) %s\n", result, toChars());
+		return this;
+	}
+    
+    Expression interpret(InterState istate)
+	{
+		assert(false);
+	}
+
+    int isConst()
+	{
+		//printf("Expression::isConst(): %s\n", toChars());
+		return 0;
+	}
+    
+	/********************************
+	 * Does this expression statically evaluate to a boolean TRUE or FALSE?
+	 */
+    bool isBool(bool result)
+	{
+		return false;
+	}
+    
+    int isBit()
+	{
+		assert(false);
+	}
+
+	/********************************
+	 * Check for expressions that have no use.
+	 * Input:
+	 *	flag	0 not going to use the result, so issue error message if no
+	 *		  side effects
+	 *		1 the result of the expression is used, but still check
+	 *		  for useless subexpressions
+	 *		2 do not issue error messages, just return !=0 if expression
+	 *		  has side effects
+	 */
+    bool checkSideEffect(int flag)
+	{
+		if (flag == 0)
+		{	
+			if (op == TOKimport)
+				error("%s has no effect", toChars());
+			else
+				error("%s has no effect in expression (%s)",
+
+			Token.toChars(op), toChars());
+		}
+
+		return false;
+	}
+    
+    bool canThrow()
+	{
+version (DMDV2) {
+    return false;
+} else {
+    return true;
+}
+	}
+    
+    int inlineCost(InlineCostState* ics)
+	{
+		return 1;
+	}
+    
+    Expression doInline(InlineDoState ids)
+	{
+		//printf("Expression.doInline(%s): %s\n", Token.toChars(op), toChars());
+		return copy();
+	}
+    
+    Expression inlineScan(InlineScanState* iss)
+	{
+		return this;
+	}
+	
+	/***********************************
+	 * Determine if operands of binary op can be reversed
+	 * to fit operator overload.
+	 */
+    
+    // For operator overloading
+    bool isCommutative()
+	{
+		return false;	// default is no reverse
+	}
+    
+	/***********************************
+	 * Get Identifier for operator overload.
+	 */	 
+    Identifier opId()
+	{
+		assert(false);
+	}
+    
+	/***********************************
+	 * Get Identifier for reverse operator overload,
+	 * null if not supported for this operator.
+	 */
+    Identifier opId_r()
+	{
+		return null;
+	}
+    
+    // For array ops
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+    
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+    
+    // Back end
+    elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+    
+    dt_t** toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/File.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,396 @@
+module dmd.File;
+
+import dmd.FileName;
+import dmd.Array;
+import dmd.Util;
+
+import core.stdc.stdlib;
+import core.sys.windows.windows;
+
+import std.string : toStringz;
+
+class File
+{
+    int ref_;					// != 0 if this is a reference to someone else's buffer
+    ubyte* buffer;				// data for our file
+    uint len;					// amount of data in buffer[]
+    void* touchtime;			// system time to use for file
+
+    FileName name;				// name of our file
+
+    this(string n)
+	{
+		name = new FileName(n);
+	}
+
+    this(FileName n)
+	{
+		name = n;
+	}
+
+    ~this()
+	{
+		if (buffer !is null) {
+			if (ref_ == 0) {
+				free(buffer);
+			} else {
+version (_WIN32) {
+				if (ref_ == 2) {
+					UnmapViewOfFile(buffer);
+				}
+}
+			}
+		}
+
+		if (touchtime !is null) {
+			free(touchtime);
+		}
+	}
+
+    void mark()
+	{
+		///mem.mark(buffer);
+		///mem.mark(touchtime);
+		///mem.mark(name);
+	}
+
+    string toChars()
+	{
+		return name.toChars();
+	}
+
+    /* Read file, return !=0 if error
+     */
+
+    int read()
+	{
+version (POSIX) {
+		int result = 0;
+
+		string name = this.name.toChars();
+
+		//printf("File::read('%s')\n",name);
+		int fd = open(name, O_RDONLY);
+		if (fd == -1) {
+			result = errno;
+			//printf("\topen error, errno = %d\n", errno);
+			goto err1;
+		}
+
+		if (ref_ == 0) {
+			free(buffer);
+		}
+
+		ref_ = 0;       // we own the buffer now
+
+		//printf("\tfile opened\n");
+		stat buf;
+		if (fstat(fd, &buf)) {
+			printf("\tfstat error, errno = %d\n", errno);
+			goto err2;
+		}
+
+		off_t size = buf.st_size;
+		buffer = cast(ubyte*)malloc(size + 2);
+		if (buffer is null) {
+			printf("\tmalloc error, errno = %d\n", errno);
+			goto err2;
+		}
+
+		ssize_t numread = .read(fd, buffer, size);
+		if (numread != size) {
+			printf("\tread error, errno = %d\n",errno);
+			goto err2;
+		}
+
+		if (touchtime !is null) {
+			memcpy(touchtime, &buf, buf.sizeof);
+		}
+
+		if (close(fd) == -1) {
+			printf("\tclose error, errno = %d\n",errno);
+			goto err;
+		}
+
+		len = size;
+
+		// Always store a wchar ^Z past end of buffer so scanner has a sentinel
+		buffer[size] = 0;		// ^Z is obsolete, use 0
+		buffer[size + 1] = 0;
+
+		return 0;
+
+	err2:
+		close(fd);
+
+	err:
+		free(buffer);
+		buffer = null;
+		len = 0;
+
+	err1:
+		result = 1;
+		return result;
+} else version (_WIN32) {
+		DWORD size;
+		DWORD numread;
+		HANDLE h;
+		int result = 0;
+
+		string name = this.name.toChars();
+		//std.stdio.writeln("Open file ", name);
+
+		h = CreateFileA(toStringz(name), GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init);
+		if (h == INVALID_HANDLE_VALUE) {
+			goto err1;
+		}
+
+		if (!ref_) {
+			free(buffer);
+		}
+		ref_ = 0;
+
+		size = GetFileSize(h, null);
+		buffer = cast(ubyte*) malloc(size + 2);
+		if (!buffer)
+			goto err2;
+
+		if (ReadFile(h, buffer, size, &numread, null) != TRUE)
+			goto err2;
+
+		if (numread != size)
+			goto err2;
+
+		if (touchtime) {
+			if (!GetFileTime(h, null, null, &(cast(WIN32_FIND_DATA*)touchtime).ftLastWriteTime))
+				goto err2;
+		}
+
+		if (!CloseHandle(h))
+			goto err;
+
+		len = size;
+
+		// Always store a wchar ^Z past end of buffer so scanner has a sentinel
+		buffer[size] = 0;		// ^Z is obsolete, use 0
+		buffer[size + 1] = 0;
+		return 0;
+
+	err2:
+		CloseHandle(h);
+	err:
+		free(buffer);
+		buffer = null;
+		len = 0;
+
+	err1:
+		result = 1;
+		return result;
+} else {
+		static assert(0);
+}
+	}
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void readv()
+	{
+		if (read())
+			error("Error reading file '%s'\n",name.toChars());
+	}
+
+    /* Read file, return !=0 if error
+     */
+
+    int mmread()
+	{
+		assert(false);
+	}
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void mmreadv()
+	{
+		assert(false);
+	}
+
+    /* Write file, return !=0 if error
+     */
+
+	/*********************************************
+	 * Write a file.
+	 * Returns:
+	 *	0	success
+	 */
+    int write()
+	{
+version (POSIX) {
+		assert(false);
+		/+
+		int fd;
+		ssize_t numwritten;
+		char *name;
+
+		name = this->name->toChars();
+		fd = open(name, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+		if (fd == -1)
+		goto err;
+
+		numwritten = ::write(fd, buffer, len);
+		if (len != numwritten)
+		goto err2;
+		
+		if (close(fd) == -1)
+		goto err;
+
+		if (touchtime)
+		{   struct utimbuf ubuf;
+
+			ubuf.actime = ((struct stat *)touchtime)->st_atime;
+			ubuf.modtime = ((struct stat *)touchtime)->st_mtime;
+		if (utime(name, &ubuf))
+			goto err;
+		}
+		return 0;
+
+	err2:
+		close(fd);
+		::remove(name);
+	err:
+		return 1;
+		+/
+} else version (_WIN32) {
+		HANDLE h;
+		DWORD numwritten;
+
+		const(char)* name = toStringz(this.name.toChars());
+		h = CreateFileA(name, GENERIC_WRITE, 0, null, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, null);
+		if (h == INVALID_HANDLE_VALUE)
+			goto err;
+
+		if (WriteFile(h, buffer, len, &numwritten, null) != TRUE)
+			goto err2;
+
+		if (len != numwritten)
+			goto err2;
+		
+		if (touchtime) {
+			SetFileTime(h, null, null, &(cast(WIN32_FIND_DATA*)touchtime).ftLastWriteTime);
+		}
+		if (!CloseHandle(h))
+			goto err;
+		return 0;
+
+	err2:
+		CloseHandle(h);
+		DeleteFileA(name);
+	err:
+		return 1;
+} else {
+		static assert(false);
+}
+	}
+
+    /* Write file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void writev()
+	{
+		if (write()) {
+			error("Error writing file '%s'\n", name.toChars());
+		}
+	}
+
+    /* Return !=0 if file exists.
+     *	0:	file doesn't exist
+     *	1:	normal file
+     *	2:	directory
+     */
+
+    /* Append to file, return !=0 if error
+     */
+
+    int append()
+	{
+		assert(false);
+	}
+
+    /* Append to file, either succeed or fail
+     * with error message & exit.
+     */
+
+    void appendv()
+	{
+		assert(false);
+	}
+
+    /* Return !=0 if file exists.
+     *	0:	file doesn't exist
+     *	1:	normal file
+     *	2:	directory
+     */
+
+    int exists()
+	{
+		assert(false);
+	}
+
+    /* Given wildcard filespec, return an array of
+     * matching File's.
+     */
+
+    static Array match(char*)
+	{
+		assert(false);
+	}
+
+    static Array match(FileName *)
+	{
+		assert(false);
+	}
+
+    // Compare file times.
+    // Return	<0	this < f
+    //		=0	this == f
+    //		>0	this > f
+    int compareTime(File f)
+	{
+		assert(false);
+	}
+
+    // Read system file statistics
+    void stat()
+	{
+		assert(false);
+	}
+
+    /* Set buffer
+     */
+
+    void setbuffer(void* buffer, uint len)
+    {
+		this.buffer = cast(ubyte*)buffer;
+		this.len = len;
+    }
+
+    void checkoffset(size_t offset, size_t nbytes)
+	{
+		assert(false);
+	}
+
+    void remove()		// delete file
+	{
+version (POSIX) {
+		.remove(this.name.toChars());
+} else version (_WIN32) {
+		DeleteFileA(toStringz(this.name.toChars()));
+} else {
+		assert(0);
+}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FileExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,29 @@
+module dmd.FileExp;
+
+import dmd.Expression;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class FileExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FileInitExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,27 @@
+module dmd.FileInitExp;
+
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.DefaultInitExp;
+import dmd.TOK;
+
+class FileInitExp : DefaultInitExp
+{
+	this(Loc loc)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression resolve(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FileName.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,535 @@
+module dmd.FileName;
+
+import dmd.String;
+import dmd.Array;
+import dmd.OutBuffer;
+import dmd.File;
+
+import core.stdc.stdlib : malloc, alloca;
+import core.stdc.string : memcpy, strlen;
+import core.stdc.ctype : isspace;
+
+import std.contracts : assumeUnique;
+import std.string : cmp, icmp;
+import std.file : mkdirRecurse;
+
+import core.sys.windows.windows;
+
+class FileName : String
+{
+    this(string str)
+	{
+		super(str);
+	}
+
+    this(string path, string name)
+	{
+		super(combine(path, name));
+	}
+
+    hash_t hashCode()
+	{
+version (_WIN32) {
+		// We need a different hashCode because it must be case-insensitive
+		size_t len = str.length;
+		hash_t hash = 0;
+		ubyte* s = cast(ubyte*)str.ptr;
+
+		for (;;)
+		{
+			switch (len)
+			{
+				case 0:
+					return hash;
+
+				case 1:
+					hash *= 37;
+					hash += *(cast(ubyte*)s) | 0x20;
+					return hash;
+
+				case 2:
+					hash *= 37;
+					hash += *(cast(ushort*)s) | 0x2020;
+					return hash;
+
+				case 3:
+					hash *= 37;
+					hash += (*cast(ushort*)s) << 8 +
+						((cast(ubyte*)s)[2]) | 0x202020;
+					break;
+
+				default:
+					hash *= 37;
+					hash += (*cast(int*)s) | 0x20202020;
+					s += 4;
+					len -= 4;
+					break;
+			}
+		}
+} else {
+		// darwin HFS is case insensitive, though...
+		return super.hashCode();
+}
+	}
+
+    bool opEquals(Object obj)
+	{
+		return opCmp(obj) == 0;
+	}
+
+    static int equals(string name1, string name2)
+	{
+		return compare(name1, name2) == 0;
+	}
+
+    int opCmp(Object obj)
+	{
+		return compare(str, (cast(FileName)obj).str);
+	}
+
+    static int compare(string name1, string name2)
+	{
+version (_WIN32) {
+    return icmp(name1, name2);
+} else {
+    return cmp(name1, name2);
+}
+	}
+
+    static bool absolute(string name)
+	{
+version (_WIN32) {
+		return (*name == '\\') ||
+			(*name == '/')  ||
+			(*name && name[1] == ':');
+} else version (POSIX) {
+		return (*name == '/');
+} else {
+    static assert(false);
+}
+	}
+
+	/********************************
+	 * Return filename extension (read-only).
+	 * Points past '.' of extension.
+	 * If there isn't one, return NULL.
+	 */
+    static string ext(string str)
+	{
+		foreach_reverse (i, c; str)
+		{
+			switch (c)
+			{
+				case '.':
+					return str[i+1..$];
+version (POSIX) {
+				case '/':
+					return null;
+}
+version (_WIN32) {
+				case '\\':
+				case ':':
+				case '/':
+					return null;
+
+}				default:
+					break;
+			}
+		}
+		
+		return null;
+	}
+
+    string ext()
+	{
+		return ext(str);
+	}
+	
+	/********************************
+	 * Return filename with extension removed.
+	 */
+
+    static string removeExt(string str)
+	{
+		string e = ext(str);
+		if (e !is null)
+		{
+			size_t len = (e.ptr - str.ptr - 1);
+			return str[0..len];
+		}
+
+		return str;
+	}
+	
+	/********************************
+	 * Return filename name excluding path (read-only).
+	 */
+
+    static string name(string str)
+	{
+		foreach_reverse(i, c; str)
+		{
+			switch (c)
+			{
+version (POSIX) {
+				case '/':
+				   return str[i+1..$];
+}
+version (_WIN32) {
+				case '/':
+				case '\\':
+					return str[i+1..$];
+				case ':':
+					/* The ':' is a drive letter only if it is the second
+					 * character or the last character,
+					 * otherwise it is an ADS (Alternate Data Stream) separator.
+					 * Consider ADS separators as part of the file name.
+					 */
+					if (i == 1 || i == str.length - 1)
+						return str[i+1..$];
+}
+				default:
+					break;
+			}
+		}
+
+		return str;
+	}
+
+    string name()
+	{
+		return name(str);
+	}
+	
+	/**************************************
+	 * Return path portion of str.
+	 * Path will does not include trailing path separator.
+	 */
+
+    static string path(string str)
+	{
+		auto n = name(str).ptr;
+
+		if (n > str.ptr)
+		{
+			auto p = n - 1;
+version (POSIX) {
+			if (*p == '/')
+				n--;
+} else version (_WIN32) {
+			if (*p == '\\' || *p == '/')
+				n--;
+} else {
+			static assert(false);
+}
+		}
+
+		size_t pathlen = n - str.ptr;
+		return str[0..pathlen];
+	}
+	
+	/**************************************
+	 * Replace filename portion of path.
+	 */
+	
+    static string replaceName(string path, string name)
+	{
+		if (absolute(name))
+			return name;
+
+		string n = FileName.name(path);
+		if (n is path)
+			return name;
+
+		size_t pathlen = n.ptr - path.ptr;
+		size_t namelen = name.length;
+
+		char* f = cast(char*)malloc(pathlen + 1 + namelen + 1);
+		memcpy(f, path.ptr, pathlen);
+version (POSIX) {
+		if (path[pathlen - 1] != '/')
+		{
+			f[pathlen] = '/';
+			pathlen++;
+		}
+} else version (_WIN32) {
+		if (path[pathlen - 1] != '\\' &&
+			path[pathlen - 1] != '/' &&
+			path[pathlen - 1] != ':')
+		{
+			f[pathlen] = '\\';
+			pathlen++;
+		}
+} else {
+		static assert(false);
+}
+		memcpy(f + pathlen, name.ptr, namelen + 1);
+		
+		return assumeUnique(f[0..pathlen+namelen]);
+	}
+
+    static string combine(string path, string name)
+	{
+		size_t pathlen;
+		size_t namelen;
+
+		if (path.length == 0)
+			return name;
+
+		pathlen = path.length;
+		namelen = name.length;
+
+		char* f = cast(char*)malloc(pathlen + 1 + namelen + 1);
+
+		memcpy(f, path.ptr, pathlen);
+
+version (POSIX) {
+		if (path[pathlen - 1] != '/')
+		{
+			f[pathlen] = '/';
+			pathlen++;
+		}
+} else version (_WIN32) {
+		if (path[pathlen - 1] != '\\' && 
+			path[pathlen - 1] != '/'  &&
+			path[pathlen - 1] != ':')
+		{
+			f[pathlen] = '\\';
+			pathlen++;
+		}
+} else {
+		static assert(0);
+}
+		memcpy(f + pathlen, name.ptr, namelen + 1);
+
+		return assumeUnique(f[0..pathlen+namelen]);
+	}
+	
+    static string[] splitPath(const(char)[] spath)
+	{
+		char c = 0;				// unnecessary initializer is for VC /W4
+
+		scope OutBuffer buf = new OutBuffer();
+		string[] array;
+		
+		if (spath !is null)
+		{
+			const(char)* p = spath.ptr;
+			int len = spath.length;
+			do
+			{
+				char instring = 0;
+
+				while (len > 0 && isspace(*p))	{	// skip leading whitespace
+					p++;
+					--len;
+				}
+				
+				buf.reserve(len + 1);	// guess size of path
+				for (; len; p++, len--)
+				{
+					c = *p;
+					switch (c)
+					{
+						case '"':
+							instring ^= 1;	// toggle inside/outside of string
+							continue;
+
+	version (MACINTOSH) {
+						case ',':
+	}
+	version (_WIN32) {
+						case ';':
+	}
+	version (POSIX) {
+						case ':':
+	}
+							p++;
+							break;		// note that ; cannot appear as part
+										// of a path, quotes won't protect it
+
+						case 0x1A:		// ^Z means end of file
+						//case 0:
+							break;
+
+						case '\r':
+							continue;	// ignore carriage returns
+
+	version (POSIX) {
+						case '~':
+							buf.writestring(getenv("HOME"));
+							continue;
+	}
+
+	version (disabled) {
+						case ' ':
+						case '\t':		// tabs in filenames?
+							if (!instring)	// if not in string
+								break;	// treat as end of path
+	}
+						default:
+						buf.writeByte(c);
+						continue;
+					}
+					break;
+				}
+				if (buf.offset)		// if path is not empty
+				{
+					//buf.writeByte(0);	// to asciiz
+					array ~= buf.extractString();
+				}
+			} while (len > 0);
+		}
+		
+		return array;
+	}
+	
+    static FileName defaultExt(string name, string ext)
+	{
+		string e = FileName.ext(name);
+		if (e !is null) {
+			// if already has an extension
+			return new FileName(name);
+		}
+
+		size_t len = name.length;
+		size_t extlen = ext.length;
+		char* s = cast(char*)malloc(len + 1 + extlen + 1);
+		memcpy(s, name.ptr, len);
+		s[len] = '.';
+		memcpy(s + len + 1, ext.ptr, extlen + 1);
+
+		return new FileName(assumeUnique(s[0..len+1+extlen]));
+	}
+
+    static FileName forceExt(string name, string ext)
+	{
+		string e = FileName.ext(name);
+		if (e !is null)				// if already has an extension
+		{
+			size_t len = e.ptr - name.ptr;
+			size_t extlen = ext.length;
+
+			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]));
+		}
+
+		return defaultExt(name, ext);	// doesn't have one
+	}
+	
+	/******************************
+	 * Return true if extensions match.
+	 */
+	
+    bool equalsExt(string ext)
+	{
+		string e = FileName.ext();
+		if (e.length == 0 && ext.length == 0)
+			return true;
+
+		if (e.length == 0 || ext.length == 0)
+			return false;
+
+version (POSIX) {
+		return cmp(e,ext) == 0;
+} else version (_WIN32) {
+		return icmp(e,ext) == 0;
+} else {
+		static assert(0);
+}
+	}
+	
+	/*************************************
+	 * Copy file from this to to.
+	 */
+
+    void CopyTo(FileName to)
+	{
+		scope File file = new File(this);
+
+version (_WIN32) {
+		file.touchtime = malloc(WIN32_FIND_DATA.sizeof);	// keep same file time
+} else version (POSIX) {
+		file.touchtime = malloc(stat.sizeof); // keep same file time
+} else {
+		static assert(0);
+}
+		file.readv();
+		file.name = to;
+		file.writev();
+	}
+	
+	/*************************************
+	 * Search Path for file.
+	 * Input:
+	 *	cwd	if true, search current directory before searching path
+	 */
+
+    static string searchPath(Array path, string name, bool cwd)
+	{
+		if (absolute(name)) {
+			return exists(name) ? name : null;
+		}
+		
+		if (cwd) {
+			if (exists(name)) {
+				return name;
+			}
+		}
+		
+		if (path !is null) {
+			foreach (i; 0..path.dim)
+			{
+				String p = cast(String)path.data[i];
+				string n = combine(p.str, name);
+
+				if (exists(n))
+					return n;
+			}
+		}
+		
+		return null;
+	}
+	
+    static int exists(string name)
+	{
+version (POSIX) {
+		stat st;
+
+		if (stat(name, &st) < 0)
+			return 0;
+		if (S_ISDIR(st.st_mode))
+			return 2;
+		return 1;
+} else version (_WIN32) {
+		HANDLE h = CreateFileA(toStringz(name), GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init);	///
+		if (h == INVALID_HANDLE_VALUE) {
+			return 0;
+		}
+		
+		CloseHandle(h);
+
+		DWORD dw = GetFileAttributesA(name.ptr);	/// CARE!
+		if (dw == -1L) {
+			assert(false);
+			return 0;
+		} else if (dw & FILE_ATTRIBUTE_DIRECTORY) {
+			return 2;
+		} else {
+			return 1;
+		}
+} else {
+		static assert(0);
+}
+	}
+	
+    static void ensurePathExists(string path)
+	{
+		try {
+			mkdirRecurse(path);
+		} catch {
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ForStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,251 @@
+module dmd.ForStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.WANT;
+import dmd.ScopeDsymbol;
+import dmd.IRState;
+import dmd.BE;
+
+import dmd.backend.Blockx;
+import dmd.backend.block;
+import dmd.backend.Util;
+import dmd.backend.BC;
+
+class ForStatement : Statement
+{
+    Statement init;
+    Expression condition;
+    Expression increment;
+    Statement body_;
+
+    this(Loc loc, Statement init, Expression condition, Expression increment, Statement body_)
+	{
+		super(loc);
+		
+		this.init = init;
+		this.condition = condition;
+		this.increment = increment;
+		this.body_ = body_;
+	}
+
+    Statement syntaxCopy()
+	{
+		Statement i = null;
+		if (init)
+			i = init.syntaxCopy();
+		Expression c = null;
+		if (condition)
+			c = condition.syntaxCopy();
+		Expression inc = null;
+		if (increment)
+			inc = increment.syntaxCopy();
+		ForStatement s = new ForStatement(loc, i, c, inc, body_.syntaxCopy());
+		return s;
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		ScopeDsymbol sym = new ScopeDsymbol();
+		sym.parent = sc.scopesym;
+		sc = sc.push(sym);
+		if (init)
+			init = init.semantic(sc);
+		sc.noctor++;
+		if (condition)
+		{
+			condition = condition.semantic(sc);
+			condition = resolveProperties(sc, condition);
+			condition = condition.optimize(WANTvalue);
+			condition = condition.checkToBoolean();
+		}
+		if (increment)
+		{
+			increment = increment.semantic(sc);
+			increment = resolveProperties(sc, increment);
+		}
+
+		sc.sbreak = this;
+		sc.scontinue = this;
+		if (body_)
+			body_ = body_.semantic(sc);
+		sc.noctor--;
+
+		sc.pop();
+		return this;
+	}
+	
+    void scopeCode(Scope sc, Statement* sentry, Statement* sexception, Statement* sfinally)
+	{
+		//printf("ForStatement::scopeCode()\n");
+		//print();
+		if (init)
+			init.scopeCode(sc, sentry, sexception, sfinally);
+		else
+			Statement.scopeCode(sc, sentry, sexception, sfinally);
+	}
+	
+    bool hasBreak()
+	{
+		//printf("ForStatement.hasBreak()\n");
+		return true;
+	}
+	
+    bool hasContinue()
+	{
+		return true;
+	}
+	
+    bool usesEH()
+	{
+		return (init && init.usesEH()) || body_.usesEH();
+	}
+	
+    BE blockExit()
+	{
+		BE result = BE.BEfallthru;
+
+		if (init)
+		{	
+			result = init.blockExit();
+			if (!(result & BE.BEfallthru))
+				return result;
+		}
+		if (condition)
+		{	
+			if (condition.canThrow())
+				result |= BE.BEthrow;
+			if (condition.isBool(true))
+				result &= ~BE.BEfallthru;
+			else if (condition.isBool(false))
+				return result;
+		}
+		else
+			result &= ~BE.BEfallthru;	// the body must do the exiting
+		if (body_)
+		{	
+			int r = body_.blockExit();
+			if (r & (BE.BEbreak | BE.BEgoto))
+				result |= BE.BEfallthru;
+			result |= r & ~(BE.BEfallthru | BE.BEbreak | BE.BEcontinue);
+		}
+		if (increment && increment.canThrow())
+			result |= BE.BEthrow;
+		return result;
+	}
+	
+    bool comeFrom()
+	{
+		//printf("ForStatement.comeFrom()\n");
+		if (body_)
+		{	
+			bool result = body_.comeFrom();
+			//printf("result = %d\n", result);
+			return result;
+		}
+		return false;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("for (");
+		if (init)
+		{
+			hgs.FLinit.init++;
+			init.toCBuffer(buf, hgs);
+			hgs.FLinit.init--;
+		}
+		else
+			buf.writebyte(';');
+		if (condition)
+		{   buf.writebyte(' ');
+			condition.toCBuffer(buf, hgs);
+		}
+		buf.writebyte(';');
+		if (increment)
+		{   
+			buf.writebyte(' ');
+			increment.toCBuffer(buf, hgs);
+		}
+		buf.writebyte(')');
+		buf.writenl();
+		buf.writebyte('{');
+		buf.writenl();
+		body_.toCBuffer(buf, hgs);
+		buf.writebyte('}');
+		buf.writenl();
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (init)
+			init = init.inlineScan(iss);
+		if (condition)
+			condition = condition.inlineScan(iss);
+		if (increment)
+			increment = increment.inlineScan(iss);
+		if (body_)
+			body_ = body_.inlineScan(iss);
+		return this;
+	}
+	
+    void toIR(IRState* irs)
+	{
+		Blockx* blx = irs.blx;
+
+		IRState mystate = IRState(irs,this);
+		mystate.breakBlock = block_calloc(blx);
+		mystate.contBlock = block_calloc(blx);
+
+		if (init)
+			init.toIR(&mystate);
+		block* bpre = blx.curblock;
+		block_next(blx,BCgoto,null);
+		block* bcond = blx.curblock;
+		list_append(&bpre.Bsucc, bcond);
+		list_append(&mystate.contBlock.Bsucc, bcond);
+		if (condition)
+		{
+			incUsage(irs, condition.loc);
+			block_appendexp(bcond, condition.toElem(&mystate));
+			block_next(blx,BCiftrue,null);
+			list_append(&bcond.Bsucc, blx.curblock);
+			list_append(&bcond.Bsucc, mystate.breakBlock);
+		}
+		else
+		{
+			/* No conditional, it's a straight goto
+			 */
+			block_next(blx,BCgoto,null);
+			list_append(&bcond.Bsucc, blx.curblock);
+		}
+
+		if (body_)
+			body_.toIR(&mystate);
+		/* End of the body goes to the continue block
+		 */
+		list_append(&blx.curblock.Bsucc, mystate.contBlock);
+		block_next(blx, BCgoto, mystate.contBlock);
+
+		if (increment)
+		{
+			incUsage(irs, increment.loc);
+			block_appendexp(mystate.contBlock, increment.toElem(&mystate));
+		}
+
+		/* The 'break' block follows the for statement.
+		 */
+		block_next(blx,BCgoto, mystate.breakBlock);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ForeachRangeStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,224 @@
+module dmd.ForeachRangeStatement;
+
+import dmd.Statement;
+import dmd.TOK;
+import dmd.Argument;
+import dmd.Expression;
+import dmd.Statement;
+import dmd.VarDeclaration;
+import dmd.Scope;
+import dmd.ExpInitializer;
+import dmd.Identifier;
+import dmd.Lexer;
+import dmd.ArrayTypes;
+import dmd.DeclarationStatement;
+import dmd.CompoundDeclarationStatement;
+import dmd.DeclarationExp;
+import dmd.PostExp;
+import dmd.VarExp;
+import dmd.ForStatement;
+import dmd.IntegerExp;
+import dmd.AddAssignExp;
+import dmd.CmpExp;
+import dmd.IRState;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.AddExp;
+import dmd.WANT;
+import dmd.ScopeDsymbol;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.Loc;
+import dmd.BE;
+
+class ForeachRangeStatement : Statement
+{
+    TOK op;		// TOK.TOKforeach or TOK.TOKforeach_reverse
+    Argument arg;		// loop index variable
+    Expression lwr;
+    Expression upr;
+    Statement body_;
+
+    VarDeclaration key = null;
+
+    this(Loc loc, TOK op, Argument arg, Expression lwr, Expression upr, Statement body_)
+	{
+		super(loc);
+		this.op = op;
+		this.arg = arg;
+		this.lwr = lwr;
+		this.upr = upr;
+		this.body_ = body_;
+	}
+	
+    Statement syntaxCopy()
+	{
+		ForeachRangeStatement s = new ForeachRangeStatement(loc, op,
+			arg.syntaxCopy(),
+			lwr.syntaxCopy(),
+			upr.syntaxCopy(),
+			body_ ? body_.syntaxCopy() : null);
+
+		return s;
+	}
+
+    Statement semantic(Scope sc)
+	{
+		//printf("ForeachRangeStatement.semantic() %p\n", this);
+		ScopeDsymbol sym;
+		Statement s = this;
+
+		lwr = lwr.semantic(sc);
+		lwr = resolveProperties(sc, lwr);
+		lwr = lwr.optimize(WANTvalue);
+		if (!lwr.type)
+		{
+			error("invalid range lower bound %s", lwr.toChars());
+			return this;
+		}
+
+		upr = upr.semantic(sc);
+		upr = resolveProperties(sc, upr);
+		upr = upr.optimize(WANTvalue);
+		if (!upr.type)
+		{
+			error("invalid range upper bound %s", upr.toChars());
+			return this;
+		}
+
+		if (arg.type)
+		{
+			arg.type = arg.type.semantic(loc, sc);
+			lwr = lwr.implicitCastTo(sc, arg.type);
+			upr = upr.implicitCastTo(sc, arg.type);
+		}
+		else
+		{
+			/* Must infer types from lwr and upr
+			 */
+			scope AddExp ea = new AddExp(loc, lwr, upr);
+			ea.typeCombine(sc);
+			arg.type = ea.type.mutableOf();
+			lwr = ea.e1;
+			upr = ea.e2;
+		}
+	static if (true) {
+		/* Convert to a for loop:
+		 *	foreach (key; lwr .. upr) =>
+		 *	for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
+		 *
+		 *	foreach_reverse (key; lwr .. upr) =>
+		 *	for (auto tmp = lwr, auto key = upr; key-- > tmp;)
+		 */
+
+		ExpInitializer ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
+		key = new VarDeclaration(loc, arg.type, arg.ident, ie);
+
+		Identifier id = Lexer.uniqueId("__limit");
+		ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
+		VarDeclaration tmp = new VarDeclaration(loc, arg.type, id, ie);
+
+		Statements cs = new Statements();
+		// Keep order of evaluation as lwr, then upr
+		if (op == TOKforeach)
+		{
+			cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+			cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+		}
+		else
+		{
+			cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+			cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+		}
+		Statement forinit = new CompoundDeclarationStatement(loc, cs);
+
+		Expression cond;
+		if (op == TOKforeach_reverse)
+		{	// key-- > tmp
+			cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
+			cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
+		}
+		else
+			// key < tmp
+			cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
+
+		Expression increment = null;
+		if (op == TOKforeach)
+			// key += 1
+			increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
+
+		ForStatement fs = new ForStatement(loc, forinit, cond, increment, body_);
+		s = fs.semantic(sc);
+		return s;
+	} else {
+		if (!arg.type.isscalar())
+			error("%s is not a scalar type", arg.type.toChars());
+
+		sym = new ScopeDsymbol();
+		sym.parent = sc.scopesym;
+		sc = sc.push(sym);
+
+		sc.noctor++;
+
+		key = new VarDeclaration(loc, arg.type, arg.ident, null);
+		DeclarationExp de = new DeclarationExp(loc, key);
+		de.semantic(sc);
+
+		if (key.storage_class)
+			error("foreach range: key cannot have storage class");
+
+		sc.sbreak = this;
+		sc.scontinue = this;
+		body_ = body_.semantic(sc);
+
+		sc.noctor--;
+		sc.pop();
+		return s;
+	}
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool hasContinue()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    bool comeFrom()
+	{
+		assert(false);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+	
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ForeachStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,826 @@
+module dmd.ForeachStatement;
+
+import dmd.Statement;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.LINK;
+import dmd.ArrayTypes;
+import dmd.Expression;
+import dmd.VarDeclaration;
+import dmd.FuncDeclaration;
+import dmd.Array;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.InlineScanState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.ScopeDsymbol;
+import dmd.TypeAArray;
+import dmd.Type;
+import dmd.CallExp;
+import dmd.WANT;
+import dmd.TY;
+import dmd.TypeTuple;
+import dmd.TupleExp;
+import dmd.Global;
+import dmd.Initializer;
+import dmd.ExpInitializer;
+import dmd.IntegerExp;
+import dmd.ExpStatement;
+import dmd.DeclarationExp;
+import dmd.Dsymbol;
+import dmd.BreakStatement;
+import dmd.DefaultStatement;
+import dmd.CaseStatement;
+import dmd.SwitchStatement;
+import dmd.VarExp;
+import dmd.AliasDeclaration;
+import dmd.CompoundStatement;
+import dmd.ScopeStatement;
+import dmd.UnrolledLoopStatement;
+import dmd.Identifier;
+import dmd.Lexer;
+import dmd.DeclarationStatement;
+import dmd.CompoundDeclarationStatement;
+import dmd.AggregateDeclaration;
+import dmd.TypeClass;
+import dmd.NotExp;
+import dmd.TypeStruct;
+import dmd.FuncLiteralDeclaration;
+import dmd.IdentifierExp;
+import dmd.TypeFunction;
+import dmd.GotoStatement;
+import dmd.FuncExp;
+import dmd.ReturnStatement;
+import dmd.IndexExp;
+import dmd.ForStatement;
+import dmd.SliceExp;
+import dmd.DotIdExp;
+import dmd.PostExp;
+import dmd.AddAssignExp;
+import dmd.CmpExp;
+import dmd.Id;
+import dmd.Argument;
+import dmd.STC;
+
+import dmd.expression.Util;
+
+import core.stdc.stdio;
+
+class ForeachStatement : Statement
+{
+    TOK op;		// TOKforeach or TOKforeach_reverse
+    Arguments arguments;	// array of Argument*'s
+    Expression aggr;
+    Statement body_;
+
+    VarDeclaration key;
+    VarDeclaration value;
+
+    FuncDeclaration func;	// function we're lexically in
+
+    Array cases;	// put breaks, continues, gotos and returns here
+    Array gotos;	// forward referenced goto's go here
+
+    this(Loc loc, TOK op, Arguments arguments, Expression aggr, Statement body_)
+	{
+		super(loc);
+		
+		this.op = op;
+		this.arguments = arguments;
+		this.aggr = aggr;
+		this.body_ = body_;
+		
+		gotos = new Array();
+		cases = new Array();
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("ForeachStatement.semantic() %p\n", this);
+		ScopeDsymbol sym;
+		Statement s = this;
+		size_t dim = arguments.dim;
+		TypeAArray taa = null;
+
+		Type tn = null;
+		Type tnv = null;
+
+		func = sc.func;
+		if (func.fes)
+			func = func.fes.func;
+
+		aggr = aggr.semantic(sc);
+		aggr = resolveProperties(sc, aggr);
+		aggr = aggr.optimize(WANT.WANTvalue);
+		if (!aggr.type)
+		{
+			error("invalid foreach aggregate %s", aggr.toChars());
+			return this;
+		}
+
+		inferApplyArgTypes(op, arguments, aggr);
+
+		/* Check for inference errors
+		 */
+		if (dim != arguments.dim)
+		{
+			//printf("dim = %d, arguments.dim = %d\n", dim, arguments.dim);
+			error("cannot uniquely infer foreach argument types");
+			return this;
+		}
+
+		Type tab = aggr.type.toBasetype();
+
+		if (tab.ty == TY.Ttuple)	// don't generate new scope for tuple loops
+		{
+			if (dim < 1 || dim > 2)
+			{
+				error("only one (value) or two (key,value) arguments for tuple foreach");
+				return s;
+			}
+
+			TypeTuple tuple = cast(TypeTuple)tab;
+			Statements statements = new Statements();
+			//printf("aggr: op = %d, %s\n", aggr.op, aggr.toChars());
+			size_t n;
+			TupleExp te = null;
+			if (aggr.op == TOK.TOKtuple)	// expression tuple
+			{   
+				te = cast(TupleExp)aggr;
+				n = te.exps.dim;
+			}
+			else if (aggr.op == TOK.TOKtype)	// type tuple
+			{
+				n = Argument.dim(tuple.arguments);
+			}
+			else
+				assert(0);
+
+			for (size_t j = 0; j < n; j++)
+			{   
+				size_t k = (op == TOK.TOKforeach) ? j : n - 1 - j;
+				Expression e;
+				Type t;
+				if (te)
+					e = cast(Expression)te.exps.data[k];
+				else
+					t = Argument.getNth(tuple.arguments, k).type;
+
+				Argument arg = cast(Argument)arguments.data[0];
+				Statements st = new Statements();
+
+				if (dim == 2)
+				{   
+					// Declare key
+					if (arg.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
+						error("no storage class for key %s", arg.ident.toChars());
+					TY keyty = arg.type.ty;
+					if (keyty != TY.Tint32 && keyty != TY.Tuns32)
+					{
+						if (global.params.isX86_64)
+						{
+							if (keyty != TY.Tint64 && keyty != TY.Tuns64)
+								error("foreach: key type must be int or uint, long or ulong, not %s", arg.type.toChars());
+						}
+						else
+							error("foreach: key type must be int or uint, not %s", arg.type.toChars());
+					}
+					Initializer ie = new ExpInitializer(Loc(0), new IntegerExp(k));
+					VarDeclaration var = new VarDeclaration(loc, arg.type, arg.ident, ie);
+					var.storage_class |= STC.STCmanifest;
+					DeclarationExp de = new DeclarationExp(loc, var);
+					st.push(cast(void*)new ExpStatement(loc, de));
+					arg = cast(Argument)arguments.data[1];	// value
+				}
+				// Declare value
+				if (arg.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
+					error("no storage class for value %s", arg.ident.toChars());
+				Dsymbol var;
+				if (te)
+				{
+					Type tb = e.type.toBasetype();
+					if ((tb.ty == TY.Tfunction || tb.ty == TY.Tsarray) && e.op == TOK.TOKvar)
+					{   
+						VarExp ve = cast(VarExp)e;
+						var = new AliasDeclaration(loc, arg.ident, ve.var);
+					}
+					else
+					{
+						arg.type = e.type;
+						Initializer ie = new ExpInitializer(Loc(0), e);
+						VarDeclaration v = new VarDeclaration(loc, arg.type, arg.ident, ie);
+						if (e.isConst())
+							v.storage_class |= STC.STCconst;
+
+						var = v;
+					}
+				}
+				else
+				{
+					var = new AliasDeclaration(loc, arg.ident, t);
+				}
+
+				DeclarationExp de = new DeclarationExp(loc, var);
+				st.push(cast(void*)new ExpStatement(loc, de));
+
+				st.push(cast(void*)body_.syntaxCopy());
+				s = new CompoundStatement(loc, st);
+				s = new ScopeStatement(loc, s);
+				statements.push(cast(void*)s);
+			}
+
+			s = new UnrolledLoopStatement(loc, statements);
+			s = s.semantic(sc);
+			return s;
+		}
+
+		sym = new ScopeDsymbol();
+		sym.parent = sc.scopesym;
+		sc = sc.push(sym);
+
+		sc.noctor++;
+
+		switch (tab.ty)
+		{
+			case TY.Tarray:
+			case TY.Tsarray:
+				if (!checkForArgTypes())
+					return this;
+
+				if (dim < 1 || dim > 2)
+				{
+					error("only one or two arguments for array foreach");
+					break;
+				}
+
+				/* Look for special case of parsing char types out of char type
+				 * array.
+				 */
+				tn = tab.nextOf().toBasetype();
+				if (tn.ty == TY.Tchar || tn.ty == TY.Twchar || tn.ty == TY.Tdchar)
+				{	
+					Argument arg;
+
+					int i = (dim == 1) ? 0 : 1;	// index of value
+					arg = cast(Argument)arguments.data[i];
+					arg.type = arg.type.semantic(loc, sc);
+					tnv = arg.type.toBasetype();
+					if (tnv.ty != tn.ty && (tnv.ty == TY.Tchar || tnv.ty == TY.Twchar || tnv.ty == TY.Tdchar))
+					{
+						if (arg.storageClass & STC.STCref)
+							error("foreach: value of UTF conversion cannot be ref");
+						if (dim == 2)
+						{	
+							arg = cast(Argument)arguments.data[0];
+							if (arg.storageClass & STC.STCref)
+								error("foreach: key cannot be ref");
+						}
+						goto Lapply;
+					}
+				}
+
+				for (size_t i = 0; i < dim; i++)
+				{	
+					// Declare args
+					Argument arg = cast(Argument)arguments.data[i];
+					Type argtype = arg.type.semantic(loc, sc);
+					VarDeclaration var = new VarDeclaration(loc, argtype, arg.ident, null);
+					var.storage_class |= STC.STCforeach;
+					var.storage_class |= arg.storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STC_TYPECTOR);
+					if (var.storage_class & (STC.STCref | STC.STCout))
+						var.storage_class |= STC.STCnodtor;
+					
+					if (dim == 2 && i == 0)
+					{   
+						key = var;
+						//var.storage_class |= STCfinal;
+					}
+					else
+					{
+						value = var;
+						/* Reference to immutable data should be marked as const
+						 */
+						if (var.storage_class & STC.STCref && !tn.isMutable())
+						{
+							var.storage_class |= STC.STCconst;
+						}
+					}
+static if (false) {
+					DeclarationExp de = new DeclarationExp(loc, var);
+					de.semantic(sc);
+}
+				}
+
+static if (true) {
+			{
+				 /* Convert to a ForStatement
+				  *   foreach (key, value; a) body =>
+				  *   for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
+				  *   { T value = tmp[k]; body }
+				  *
+				  *   foreach_reverse (key, value; a) body =>
+				  *   for (T[] tmp = a[], size_t key = tmp.length; key--; )
+				  *   { T value = tmp[k]; body }
+				  */
+				Identifier id = Lexer.uniqueId("__aggr");
+				ExpInitializer ie = new ExpInitializer(loc, new SliceExp(loc, aggr, null, null));
+				VarDeclaration tmp = new VarDeclaration(loc, aggr.type.nextOf().arrayOf(), id, ie);
+
+				Expression tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id.length);
+
+				if (!key)
+				{
+					Identifier id2 = Lexer.uniqueId("__key");
+					key = new VarDeclaration(loc, Type.tsize_t, id2, null);
+				}
+
+				if (op == TOK.TOKforeach_reverse)
+					key.init = new ExpInitializer(loc, tmp_length);
+				else
+					key.init = new ExpInitializer(loc, new IntegerExp(0));
+
+				Statements cs = new Statements();
+				cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+				cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+				Statement forinit = new CompoundDeclarationStatement(loc, cs);
+
+				Expression cond;
+				if (op == TOK.TOKforeach_reverse)
+					// key--
+					cond = new PostExp(TOK.TOKminusminus, loc, new VarExp(loc, key));
+				else
+					// key < tmp.length
+					cond = new CmpExp(TOK.TOKlt, loc, new VarExp(loc, key), tmp_length);
+
+				Expression increment = null;
+				if (op == TOK.TOKforeach)
+					// key += 1
+					increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
+
+				// T value = tmp[key];
+				value.init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
+				Statement ds = new DeclarationStatement(loc, new DeclarationExp(loc, value));
+
+				body_ = new CompoundStatement(loc, ds, body_);
+
+				ForStatement fs = new ForStatement(loc, forinit, cond, increment, body_);
+				s = fs.semantic(sc);
+				break;
+			}
+} else {
+			if (tab.nextOf().implicitConvTo(value.type) < MATCH.MATCHconst)
+			{
+				if (aggr.op == TOK.TOKstring)
+					aggr = aggr.implicitCastTo(sc, value.type.arrayOf());
+				else
+					error("foreach: %s is not an array of %s",
+					tab.toChars(), value.type.toChars());
+				}
+
+				if (key)
+				{
+					if (key.type.ty != Tint32 && key.type.ty != Tuns32)
+					{
+						if (global.params.isX86_64)
+						{
+						if (key.type.ty != Tint64 && key.type.ty != Tuns64)
+							error("foreach: key type must be int or uint, long or ulong, not %s", key.type.toChars());
+						}
+						else
+						error("foreach: key type must be int or uint, not %s", key.type.toChars());
+					}
+
+					if (key.storage_class & (STCout | STCref))
+						error("foreach: key cannot be out or ref");
+				}
+
+				sc.sbreak = this;
+				sc.scontinue = this;
+				body_ = body_.semantic(sc);
+				break;
+}
+
+			case TY.Taarray:
+				if (!checkForArgTypes())
+					return this;
+
+				taa = cast(TypeAArray)tab;
+				if (dim < 1 || dim > 2)
+				{
+					error("only one or two arguments for associative array foreach");
+					break;
+				}
+				if (op == TOK.TOKforeach_reverse)
+				{
+					error("no reverse iteration on associative arrays");
+				}
+				goto Lapply;
+
+			case TY.Tclass:
+			case TY.Tstruct:
+version (DMDV2) {
+			{   /* Look for range iteration, i.e. the properties
+				 * .empty, .next, .retreat, .head and .rear
+				 *    foreach (e; aggr) { ... }
+				 * translates to:
+				 *    for (auto __r = aggr[]; !__r.empty; __r.next)
+				 *    {   auto e = __r.head;
+				 *        ...
+				 *    }
+				 */
+				if (dim != 1)	// only one argument allowed with ranges
+				goto Lapply;
+
+				AggregateDeclaration ad = (tab.ty == TY.Tclass)
+					? cast(AggregateDeclaration)(cast(TypeClass)tab).sym
+					: cast(AggregateDeclaration)(cast(TypeStruct)tab).sym;
+
+				Identifier idhead;
+				Identifier idnext;
+				if (op == TOK.TOKforeach)
+				{	
+					idhead = Id.Fhead;
+					idnext = Id.Fnext;
+				}
+				else
+				{	
+					idhead = Id.Ftoe;
+					idnext = Id.Fretreat;
+				}
+
+				Dsymbol shead = search_function(ad, idhead);
+				if (!shead)
+					goto Lapply;
+
+				/* Generate a temporary __r and initialize it with the aggregate.
+				 */
+				Identifier id = Identifier.generateId("__r");
+				Expression rinit = new SliceExp(loc, aggr, null, null);
+				rinit = rinit.trySemantic(sc);
+				if (!rinit)			// if application of [] failed
+					rinit = aggr;
+
+				VarDeclaration r = new VarDeclaration(loc, null, id, new ExpInitializer(loc, rinit));
+
+		//	    r.semantic(sc);
+		//printf("r: %s, init: %s\n", r.toChars(), r.init.toChars());
+				Statement init = new DeclarationStatement(loc, r);
+		//printf("init: %s\n", init.toChars());
+
+				// !__r.empty
+				Expression e = new VarExp(loc, r);
+				e = new DotIdExp(loc, e, Id.Fempty);
+				Expression condition = new NotExp(loc, e);
+
+				// __r.next
+				e = new VarExp(loc, r);
+				Expression increment = new DotIdExp(loc, e, idnext);
+
+				/* Declaration statement for e:
+				 *    auto e = __r.idhead;
+				 */
+				e = new VarExp(loc, r);
+				Expression einit = new DotIdExp(loc, e, idhead);
+		//	    einit = einit.semantic(sc);
+				Argument arg = cast(Argument)arguments.data[0];
+				VarDeclaration ve = new VarDeclaration(loc, arg.type, arg.ident, new ExpInitializer(loc, einit));
+				ve.storage_class |= STC.STCforeach;
+				ve.storage_class |= arg.storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STC_TYPECTOR);
+
+				DeclarationExp de = new DeclarationExp(loc, ve);
+
+				Statement body2 = new CompoundStatement(loc, new DeclarationStatement(loc, de), this.body_);
+				s = new ForStatement(loc, init, condition, increment, body2);
+
+	static if (false) {
+				printf("init: %s\n", init.toChars());
+				printf("condition: %s\n", condition.toChars());
+				printf("increment: %s\n", increment.toChars());
+				printf("body: %s\n", body2.toChars());
+	}
+				s = s.semantic(sc);
+				break;
+			}
+}
+			case TY.Tdelegate:
+			Lapply:
+			{   
+				FuncDeclaration fdapply;
+				Arguments args;
+				Expression ec;
+				Expression e;
+				FuncLiteralDeclaration fld;
+				Argument a;
+				Type t;
+				Expression flde;
+				Identifier id;
+				Type tret;
+
+				if (!checkForArgTypes())
+				{	
+					body_ = body_.semantic(sc);
+					return this;
+				}
+
+				tret = func.type.nextOf();
+
+				// Need a variable to hold value from any return statements in body.
+				if (!sc.func.vresult && tret && tret != Type.tvoid)
+				{	
+					VarDeclaration v = new VarDeclaration(loc, tret, Id.result, null);
+					v.noauto = true;
+					v.semantic(sc);
+					if (!sc.insert(v))
+						assert(0);
+
+					v.parent = sc.func;
+					sc.func.vresult = v;
+				}
+
+				/* Turn body into the function literal:
+				 *	int delegate(ref T arg) { body }
+				 */
+				args = new Arguments();
+				for (size_t i = 0; i < dim; i++)
+				{
+					Argument arg = cast(Argument)arguments.data[i];
+
+					arg.type = arg.type.semantic(loc, sc);
+					if (arg.storageClass & STC.STCref)
+						id = arg.ident;
+					else
+					{   // Make a copy of the ref argument so it isn't
+						// a reference.
+						VarDeclaration v;
+						Initializer ie;
+
+						id = Lexer.uniqueId("__applyArg", i);
+
+						ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id));
+						v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie);
+						s = new DeclarationStatement(Loc(0), v);
+						body_ = new CompoundStatement(loc, s, body_);
+					}
+					a = new Argument(STC.STCref, arg.type, id, null);
+					args.push(cast(void*)a);
+				}
+				t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd);
+				fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this);
+				fld.fbody = body_;
+				flde = new FuncExp(loc, fld);
+				flde = flde.semantic(sc);
+				fld.tookAddressOf = 0;
+
+				// Resolve any forward referenced goto's
+				for (int i = 0; i < gotos.dim; i++)
+				{	
+					CompoundStatement cs = cast(CompoundStatement)gotos.data[i];
+					GotoStatement gs = cast(GotoStatement)cs.statements.data[0];
+
+					if (!gs.label.statement)
+					{   
+						// 'Promote' it to this scope, and replace with a return
+						cases.push(cast(void*)gs);
+						s = new ReturnStatement(Loc(0), new IntegerExp(cases.dim + 1));
+						cs.statements.data[0] = cast(void*)s;
+					}
+				}
+
+				if (tab.ty == TY.Taarray)
+				{
+					// Check types
+					Argument arg = cast(Argument)arguments.data[0];
+					if (dim == 2)
+					{
+						if (arg.storageClass & STC.STCref)
+							error("foreach: index cannot be ref");
+						if (!arg.type.equals(taa.index))
+							error("foreach: index must be type %s, not %s", taa.index.toChars(), arg.type.toChars());
+
+						arg = cast(Argument)arguments.data[1];
+					}
+					if (!arg.type.equals(taa.nextOf()))
+						error("foreach: value must be type %s, not %s", taa.nextOf().toChars(), arg.type.toChars());
+
+					/* Call:
+					 *	_aaApply(aggr, keysize, flde)
+					 */
+					if (dim == 2)
+						fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply2");
+					else
+						fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply");
+
+					ec = new VarExp(Loc(0), fdapply);
+					Expressions exps = new Expressions();
+					exps.push(cast(void*)aggr);
+					size_t keysize = cast(uint)taa.index.size();
+					keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
+					exps.push(cast(void*)new IntegerExp(Loc(0), keysize, Type.tsize_t));
+					exps.push(cast(void*)flde);
+					e = new CallExp(loc, ec, exps);
+					e.type = Type.tindex;	// don't run semantic() on e
+				}
+				else if (tab.ty == TY.Tarray || tab.ty == TY.Tsarray)
+				{
+					/* Call:
+					 *	_aApply(aggr, flde)
+					 */
+					static char fntab[9][3] =
+					[ "cc","cw","cd",
+					  "wc","cc","wd",
+					  "dc","dw","dd"
+					];
+					char fdname[7+1+2+ dim.sizeof*3 + 1];
+					int flag;
+
+					switch (tn.ty)
+					{
+						case TY.Tchar:		flag = 0; break;
+						case TY.Twchar:		flag = 3; break;
+						case TY.Tdchar:		flag = 6; break;
+					}
+					switch (tnv.ty)
+					{
+						case TY.Tchar:		flag += 0; break;
+						case TY.Twchar:	flag += 1; break;
+						case TY.Tdchar:	flag += 2; break;
+					}
+					string r = (op == TOK.TOKforeach_reverse) ? "R" : "";
+					int j = sprintf(fdname.ptr, "_aApply%*.s%.*s%ld".ptr, r, 2, fntab[flag].ptr, dim);
+					assert(j < fdname.sizeof);
+					fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup);
+
+					ec = new VarExp(Loc(0), fdapply);
+					Expressions exps = new Expressions();
+					if (tab.ty == TY.Tsarray)
+					   aggr = aggr.castTo(sc, tn.arrayOf());
+					exps.push(cast(void*)aggr);
+					exps.push(cast(void*)flde);
+					e = new CallExp(loc, ec, exps);
+					e.type = Type.tindex;	// don't run semantic() on e
+				}
+				else if (tab.ty == TY.Tdelegate)
+				{
+					/* Call:
+					 *	aggr(flde)
+					 */
+					Expressions exps = new Expressions();
+					exps.push(cast(void*)flde);
+					e = new CallExp(loc, aggr, exps);
+					e = e.semantic(sc);
+					if (e.type != Type.tint32)
+						error("opApply() function for %s must return an int", tab.toChars());
+				}
+				else
+				{
+					assert(tab.ty == TY.Tstruct || tab.ty == TY.Tclass);
+					Identifier idapply = (op == TOK.TOKforeach_reverse)
+							? Id.applyReverse : Id.apply;
+					Dsymbol sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply);
+					Expressions exps = new Expressions();
+static if (false) {
+					TemplateDeclaration td;
+					if (sapply && (td = sapply.isTemplateDeclaration()) !is null)
+					{   
+						/* Call:
+						 *	aggr.apply!(fld)()
+						 */
+						TemplateInstance ti = new TemplateInstance(loc, idapply);
+						Objects tiargs = new Objects();
+						tiargs.push(cast(void*)fld);
+						ti.tiargs = tiargs;
+						ec = new DotTemplateInstanceExp(loc, aggr, ti);
+					}
+					else
+					{
+						/* Call:
+						 *	aggr.apply(flde)
+						 */
+						ec = new DotIdExp(loc, aggr, idapply);
+						exps.push(cast(void*)flde);
+					}
+} else {
+					ec = new DotIdExp(loc, aggr, idapply);
+					exps.push(cast(void*)flde);
+}
+					e = new CallExp(loc, ec, exps);
+					e = e.semantic(sc);
+					if (e.type != Type.tint32) {
+						error("opApply() function for %s must return an int", tab.toChars());
+					}
+				}
+
+				if (!cases.dim)
+				{
+					// Easy case, a clean exit from the loop
+					s = new ExpStatement(loc, e);
+				}
+				else
+				{	// Construct a switch statement around the return value
+					// of the apply function.
+					Statements a2 = new Statements();
+
+					// default: break; takes care of cases 0 and 1
+					s = new BreakStatement(Loc(0), null);
+					s = new DefaultStatement(Loc(0), s);
+					a2.push(cast(void*)s);
+
+					// cases 2...
+					for (int i = 0; i < cases.dim; i++)
+					{
+						s = cast(Statement)cases.data[i];
+						s = new CaseStatement(Loc(0), new IntegerExp(i + 2), s);
+						a2.push(cast(void*)s);
+					}
+
+					s = new CompoundStatement(loc, a2);
+					s = new SwitchStatement(loc, e, s, false);
+					s = s.semantic(sc);
+				}
+				break;
+			}
+
+			default:
+				error("foreach: %s is not an aggregate type", aggr.type.toChars());
+				s = null;	// error recovery
+				break;
+		}
+
+		sc.noctor--;
+		sc.pop();
+		return s;
+	}
+	
+    bool checkForArgTypes()
+	{
+		bool result = true;
+
+		for (size_t i = 0; i < arguments.dim; i++)
+		{	
+			Argument arg = cast(Argument)arguments.data[i];
+			if (!arg.type)
+			{
+				error("cannot infer type for %s", arg.ident.toChars());
+				arg.type = Type.terror;
+				result = false;
+			}
+		}
+		return result;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool hasContinue()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    bool comeFrom()
+	{
+		assert(false);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer uf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		aggr = aggr.inlineScan(iss);
+		if (body_)
+			body_ = body_.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FuncAliasDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,33 @@
+module dmd.FuncAliasDeclaration;
+
+import dmd.FuncDeclaration;
+
+import dmd.backend.Symbol;
+import dmd.backend.Symbol;
+
+import dmd.Loc;
+import dmd.STC;
+
+class FuncAliasDeclaration : FuncDeclaration
+{
+    FuncDeclaration funcalias;
+
+    this(FuncDeclaration funcalias)
+	{
+		super(funcalias.loc, funcalias.endloc, funcalias.ident, funcalias.storage_class, funcalias.type);
+		assert(funcalias !is this);
+		this.funcalias = funcalias;
+	}
+
+    FuncAliasDeclaration isFuncAliasDeclaration() { return this; }
+	
+    string kind()
+	{
+		return "function alias";
+	}
+	
+    Symbol* toSymbol()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FuncDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3248 @@
+module dmd.FuncDeclaration;
+
+import dmd.Declaration;
+import dmd.DotIdExp;
+import dmd.TryFinallyStatement;
+import dmd.StaticDtorDeclaration;
+import dmd.PeelStatement;
+import dmd.SynchronizedStatement;
+import dmd.TOK;
+import dmd.SymOffExp;
+import dmd.AssignExp;
+import dmd.ExpInitializer;
+import dmd.BE;
+import dmd.Id;
+import dmd.StringExp;
+import dmd.DsymbolExp;
+import dmd.HaltExp;
+import dmd.CommaExp;
+import dmd.ReturnStatement;
+import dmd.IntegerExp;
+import dmd.ExpStatement;
+import dmd.CSX;
+import dmd.CompoundStatement;
+import dmd.LabelStatement;
+import dmd.ThisExp;
+import dmd.SuperExp;
+import dmd.IdentifierExp;
+import dmd.AssertExp;
+import dmd.CallExp;
+import dmd.RET;
+import dmd.VarExp;
+import dmd.TupleDeclaration;
+import dmd.ThisDeclaration;
+import dmd.TypeTuple;
+import dmd.TemplateInstance;
+import dmd.ScopeDsymbol;
+import dmd.AliasDeclaration;
+import dmd.MOD;
+import dmd.PROT;
+import dmd.Lexer;
+import dmd.LINK;
+import dmd.CtorDeclaration;
+import dmd.Global;
+import dmd.DtorDeclaration;
+import dmd.InvariantDeclaration;
+import dmd.TY;
+import dmd.PtrExp;
+import dmd.DeclarationExp;
+import dmd.InlineDoState;
+import dmd.Argument;
+import dmd.StructDeclaration;
+import dmd.ClassDeclaration;
+import dmd.InterfaceDeclaration;
+import dmd.Array;
+import dmd.Statement;
+import dmd.Identifier;
+import dmd.VarDeclaration;
+import dmd.LabelDsymbol;
+import dmd.DsymbolTable;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.ILS;
+import dmd.ForeachStatement;
+import dmd.Type;
+import dmd.BUILTIN;
+import dmd.TypeFunction;
+import dmd.Expression;
+import dmd.STC;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.MATCH;
+import dmd.AggregateDeclaration;
+import dmd.InterState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.Util;
+import dmd.BaseClass;
+import dmd.Module;
+import dmd.ILS;
+import dmd.InlineCostState;
+
+import dmd.expression.Util;
+
+import dmd.declaration.Match;
+
+import dmd.backend.Symbol;
+import dmd.backend.func_t;
+import dmd.backend.Util;
+import dmd.backend.glue;
+import dmd.backend.SC;
+import dmd.backend.F;
+import dmd.backend.Cstate;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+import dmd.backend.TYFL;
+import dmd.backend.TYPE;
+import dmd.backend.SFL;
+import dmd.backend.mTY;
+import dmd.backend.FL;
+import dmd.backend.REG;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Config;
+import dmd.backend.BC;
+import dmd.backend.elem;
+import dmd.backend.targ_types;
+import dmd.backend.mTYman;
+import dmd.backend.RTLSYM;
+import dmd.backend.LIST;
+
+import core.stdc.stdio;
+import core.stdc.string;
+
+import std.string;
+
+class FuncDeclaration : Declaration
+{
+    Array fthrows;			// Array of Type's of exceptions (not used)
+    Statement frequire;
+    Statement fensure;
+    Statement fbody;
+
+    Identifier outId;			// identifier for out statement
+    VarDeclaration vresult;		// variable corresponding to outId
+    LabelDsymbol returnLabel;		// where the return goes
+
+    DsymbolTable localsymtab;		// used to prevent symbols in different
+					// scopes from having the same name
+    VarDeclaration vthis;		// 'this' parameter (member and nested)
+    VarDeclaration v_arguments;	// '_arguments' parameter
+version (IN_GCC) {
+    VarDeclaration v_argptr;	        // '_argptr' variable
+}
+    Dsymbols parameters;		// Array of VarDeclaration's for parameters
+    DsymbolTable labtab;		// statement label symbol table
+    Declaration overnext;		// next in overload list
+    Loc endloc;				// location of closing curly bracket
+    int vtblIndex = -1;			// for member functions, index into vtbl[]
+    int naked;				// !=0 if naked
+    int inlineAsm;			// !=0 if has inline assembler
+    ILS inlineStatus = ILS.ILSuninitialized;
+    int inlineNest;			// !=0 if nested inline
+    int cantInterpret;			// !=0 if cannot interpret function
+    int semanticRun;			// 1 semantic() run
+					// 2 semantic2() run
+					// 3 semantic3() started
+					// 4 semantic3() done
+					// 5 toObjFile() run
+					// this function's 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
+					// of the 'introducing' function
+					// this one is overriding
+    int inferRetType;			// !=0 if return type is to be inferred
+
+    // Things that should really go into Scope
+    int hasReturnExp;			// 1 if there's a return exp; statement
+					// 2 if there's a throw statement
+					// 4 if there's an assert(0)
+					// 8 if there's inline asm
+
+    // Support for NRVO (named return value optimization)
+    bool nrvo_can = true;			// !=0 means we can do it
+    VarDeclaration nrvo_var;		// variable to replace with shidden
+    Symbol* shidden;			// hidden pointer passed to function
+
+version (DMDV2) {
+    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
+}
+
+    this(Loc loc, Loc endloc, Identifier id, STC storage_class, Type type)
+	{
+		super(id);
+
+		//printf("FuncDeclaration(id = '%s', type = %p)\n", id.toChars(), type);
+		//printf("storage_class = x%x\n", storage_class);
+		this.storage_class = storage_class;
+		this.type = type;
+		this.loc = loc;
+		this.endloc = endloc;
+
+		/* The type given for "infer the return type" is a TypeFunction with
+		 * null for the return type.
+		 */
+		inferRetType = (type && type.nextOf() is null);
+
+		closureVars = new Dsymbols();
+
+version (DMDV2) {
+		builtin = BUILTIN.BUILTINunknown;
+}
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		FuncDeclaration f;
+
+		//printf("FuncDeclaration::syntaxCopy('%s')\n", toChars());
+		if (s)
+			f = cast(FuncDeclaration)s;
+		else
+			f = new FuncDeclaration(loc, endloc, ident, storage_class, type.syntaxCopy());
+
+		f.outId = outId;
+		f.frequire = frequire ? frequire.syntaxCopy() : null;
+		f.fensure  = fensure  ? fensure.syntaxCopy()  : null;
+		f.fbody    = fbody    ? fbody.syntaxCopy()    : null;
+		assert(!fthrows); // deprecated
+
+		return f;
+	}
+	
+	// Do the semantic analysis on the external interface to the function.
+    void semantic(Scope sc)
+	{
+		TypeFunction f;
+		StructDeclaration sd;
+		ClassDeclaration cd;
+		InterfaceDeclaration id;
+		Dsymbol pd;
+
+static if (false) {
+		printf("FuncDeclaration.semantic(sc = %p, this = %p, '%s', linkage = %d)\n", sc, this, toPrettyChars(), sc.linkage);
+		if (isFuncLiteralDeclaration())
+			printf("\tFuncLiteralDeclaration()\n");
+		printf("sc.parent = %s, parent = %s\n", sc.parent.toChars(), parent ? parent.toChars() : "");
+		printf("type: %p, %s\n", type, type.toChars());
+}
+
+		if (semanticRun && isFuncLiteralDeclaration())
+		{
+		/* Member functions that have return types that are
+		 * forward references can have semantic() run more than
+		 * once on them.
+		 * See test\interface2.d, test20
+		 */
+		return;
+		}
+		assert(semanticRun <= 1);
+		semanticRun = 1;
+
+		storage_class |= sc.stc & ~STC.STCref;
+		//printf("function storage_class = x%x\n", storage_class);
+
+		if (!originalType)
+		originalType = type;
+		if (!type.deco)
+		{
+		/* Apply const and invariant storage class
+		 * to the function type
+		 */
+		type = type.semantic(loc, sc);
+		STC stc = storage_class;
+		if (type.isInvariant())
+			stc |= STC.STCimmutable;
+		if (type.isConst())
+			stc |= STC.STCconst;
+		if (type.isShared() || storage_class & STC.STCsynchronized)
+			stc |= STC.STCshared;
+		switch (stc & STC.STC_TYPECTOR)
+		{
+			case STC.STCimmutable:
+			case STC.STCimmutable | STC.STCconst:
+			case STC.STCimmutable | STC.STCconst | STC.STCshared:
+			case STC.STCimmutable | STC.STCshared:
+			// Don't use toInvariant(), as that will do a merge()
+			type = type.makeInvariant();
+			type.deco = type.merge().deco;
+			break;
+
+			case STC.STCconst:
+			type = type.makeConst();
+			type.deco = type.merge().deco;
+			break;
+
+			case STC.STCshared | STC.STCconst:
+			type = type.makeSharedConst();
+			type.deco = type.merge().deco;
+			break;
+
+			case STC.STCshared:
+			type = type.makeShared();
+			type.deco = type.merge().deco;
+			break;
+
+			case STC.STCundefined:
+			break;
+
+			default:
+			assert(0);
+		}
+		}
+		//type.print();
+		if (type.ty != TY.Tfunction)
+		{
+		error("%s must be a function", toChars());
+		return;
+		}
+		f = cast(TypeFunction)type;
+		size_t nparams = Argument.dim(f.parameters);
+
+		linkage = sc.linkage;
+	//    if (!parent)
+		{
+		//parent = sc.scopesym;
+		parent = sc.parent;
+		}
+		protection = sc.protection;
+		Dsymbol parent = toParent();
+
+		if (storage_class & STC.STCscope)
+		error("functions cannot be scope");
+
+		if (isAbstract() && !isVirtual())
+		error("non-virtual functions cannot be abstract");
+
+		if ((f.isConst() || f.isInvariant()) && !isThis())
+		error("without 'this' cannot be const/immutable");
+
+		if (isAbstract() && isFinal())
+		error("cannot be both final and abstract");
+static if (false) {
+		if (isAbstract() && fbody)
+		error("abstract functions cannot have bodies");
+}
+
+static if (false) {
+		if (isStaticConstructor() || isStaticDestructor())
+		{
+		if (!isStatic() || type.nextOf().ty != Tvoid)
+			error("static constructors / destructors must be static void");
+		if (f.arguments && f.arguments.dim)
+			error("static constructors / destructors must have empty parameter list");
+		// BUG: check for invalid storage classes
+		}
+}
+
+version (IN_GCC) {
+		AggregateDeclaration ad;
+
+		ad = parent.isAggregateDeclaration();
+		if (ad)
+			ad.methods.push(cast(void*)this);
+}
+		sd = parent.isStructDeclaration();
+		if (sd)
+		{
+		if (isCtorDeclaration())
+		{
+			return;
+		}
+static if (false) {
+		// Verify no constructors, destructors, etc.
+		if (isCtorDeclaration()
+			//||isDtorDeclaration()
+			//|| isInvariantDeclaration()
+			//|| isUnitTestDeclaration()
+		   )
+		{
+			error("special member functions not allowed for %ss", sd.kind());
+		}
+
+		if (!sd.inv)
+			sd.inv = isInvariantDeclaration();
+
+		if (!sd.aggNew)
+			sd.aggNew = isNewDeclaration();
+
+		if (isDelete())
+		{
+			if (sd.aggDelete)
+			error("multiple delete's for struct %s", sd.toChars());
+			sd.aggDelete = cast(DeleteDeclaration)this;
+		}
+}
+		}
+
+		id = parent.isInterfaceDeclaration();
+		if (id)
+		{
+		storage_class |= STC.STCabstract;
+
+		if (isCtorDeclaration() ||
+///static if (DMDV2) {
+			isPostBlitDeclaration() ||
+///}
+			isDtorDeclaration() ||
+			isInvariantDeclaration() ||
+			isUnitTestDeclaration() || isNewDeclaration() || isDelete())
+			error("special function not allowed in interface %s", id.toChars());
+		if (fbody)
+			error("function body is not abstract in interface %s", id.toChars());
+		}
+
+		/* Template member functions aren't virtual:
+		 *   interface TestInterface { void tpl(T)(); }
+		 * and so won't work in interfaces
+		 */
+		if ((pd = toParent()) !is null &&
+		pd.isTemplateInstance() &&
+		(pd = toParent2()) !is null &&
+		(id = pd.isInterfaceDeclaration()) !is null)
+		{
+		error("template member function not allowed in interface %s", id.toChars());
+		}
+
+		cd = parent.isClassDeclaration();
+		if (cd)
+		{	int vi;
+		CtorDeclaration ctor;
+		DtorDeclaration dtor;
+		InvariantDeclaration inv;
+
+		if (isCtorDeclaration())
+		{
+	//	    ctor = cast(CtorDeclaration)this;
+	//	    if (!cd.ctor)
+	//		cd.ctor = ctor;
+			return;
+		}
+
+static if (false) {
+		dtor = isDtorDeclaration();
+		if (dtor)
+		{
+			if (cd.dtor)
+			error("multiple destructors for class %s", cd.toChars());
+			cd.dtor = dtor;
+		}
+
+		inv = isInvariantDeclaration();
+		if (inv)
+		{
+			cd.inv = inv;
+		}
+
+		if (isNewDeclaration())
+		{
+			if (!cd.aggNew)
+				cd.aggNew = cast(NewDeclaration)this;
+		}
+
+		if (isDelete())
+		{
+			if (cd.aggDelete)
+			error("multiple delete's for class %s", cd.toChars());
+			cd.aggDelete = cast(DeleteDeclaration)this;
+		}
+}
+
+		if (storage_class & STC.STCabstract)
+			cd.isabstract = true;
+
+		// if static function, do not put in vtbl[]
+		if (!isVirtual())
+		{
+			//printf("\tnot virtual\n");
+			goto Ldone;
+		}
+
+		// Find index of existing function in vtbl[] to override
+		vi = findVtblIndex(cd.vtbl, cd.baseClass ? cd.baseClass.vtbl.dim : 0);
+		switch (vi)
+		{
+			case -1:
+			/* Didn't find one, so
+			 * This is an 'introducing' function which gets a new
+			 * slot in the vtbl[].
+			 */
+
+			// Verify this doesn't override previous final function
+			if (cd.baseClass)
+			{   
+				Dsymbol s = cd.baseClass.search(loc, ident, 0);
+				if (s)
+				{
+				FuncDeclaration ff = s.isFuncDeclaration();
+				ff = ff.overloadExactMatch(type);
+				if (ff && ff.isFinal() && ff.prot() != PROT.PROTprivate)
+					error("cannot override final function %s", ff.toPrettyChars());
+				}
+			}
+
+			if (isFinal())
+			{
+				if (isOverride())
+				error("does not override any function");
+				cd.vtblFinal.push(cast(void*)this);
+			}
+			else
+			{
+				// Append to end of vtbl[]
+				//printf("\tintroducing function\n");
+				introducing = 1;
+				vi = cd.vtbl.dim;
+				cd.vtbl.push(cast(void*)this);
+				vtblIndex = vi;
+			}
+			break;
+
+			case -2:	// can't determine because of fwd refs
+			cd.sizeok = 2;	// can't finish due to forward reference
+			return;
+
+			default:
+			{   
+				FuncDeclaration fdv = cast(FuncDeclaration)cd.vtbl.data[vi];
+			// This function is covariant with fdv
+			if (fdv.isFinal())
+				error("cannot override final function %s", fdv.toPrettyChars());
+
+version (DMDV2) {
+			if (!isOverride())
+				warning(loc, "overrides base class function %s, but is not marked with 'override'", fdv.toPrettyChars());
+}
+
+			if (fdv.toParent() == parent)
+			{
+				// If both are mixins, then error.
+				// If either is not, the one that is not overrides
+				// the other.
+				if (fdv.parent.isClassDeclaration())
+				break;
+				if (!this.parent.isClassDeclaration()
+///static if (!BREAKABI) {
+				&& !isDtorDeclaration()
+///}
+///version (DMDV2) {
+				&& !isPostBlitDeclaration()
+///}
+				)
+				error("multiple overrides of same function");
+			}
+			cd.vtbl.data[vi] = cast(void*)this;
+			vtblIndex = vi;
+
+			/* This works by whenever this function is called,
+			 * it actually returns tintro, which gets dynamically
+			 * cast to type. But we know that tintro is a base
+			 * of type, so we could optimize it by not doing a
+			 * dynamic cast, but just subtracting the isBaseOf()
+			 * offset if the value is != null.
+			 */
+
+			if (fdv.tintro)
+				tintro = fdv.tintro;
+			else if (!type.equals(fdv.type))
+			{
+				/* Only need to have a tintro if the vptr
+				 * offsets differ
+				 */
+				int offset;
+				if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset))
+				{
+				tintro = fdv.type;
+				}
+			}
+			break;
+			}
+		}
+
+		/* Go through all the interface bases.
+		 * If this function is covariant with any members of those interface
+		 * functions, set the tintro.
+		 */
+		for (int i = 0; i < cd.interfaces_dim; i++)
+		{
+			BaseClass b = cd.interfaces[i];
+			vi = findVtblIndex(b.base.vtbl, b.base.vtbl.dim);
+			switch (vi)
+			{
+			case -1:
+				break;
+
+			case -2:
+				cd.sizeok = 2;	// can't finish due to forward reference
+				return;
+
+			default:
+			{   FuncDeclaration fdv = cast(FuncDeclaration)b.base.vtbl.data[vi];
+				Type ti = null;
+
+				if (fdv.tintro)
+				ti = fdv.tintro;
+				else if (!type.equals(fdv.type))
+				{
+				/* Only need to have a tintro if the vptr
+				 * offsets differ
+				 */
+				int offset;
+				if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset))
+				{
+					ti = fdv.type;
+static if (false) {
+					if (offset)
+					ti = fdv.type;
+					else if (type.nextOf().ty == Tclass)
+					{   
+						ClassDeclaration cdn = (cast(TypeClass)type.nextOf()).sym;
+						if (cdn && cdn.sizeok != 1)
+							ti = fdv.type;
+						}
+}
+					}
+				}
+				if (ti)
+				{
+				if (tintro && !tintro.equals(ti))
+				{
+					error("incompatible covariant types %s and %s", tintro.toChars(), ti.toChars());
+				}
+				tintro = ti;
+				}
+				goto L2;
+			}
+			}
+		}
+
+		if (introducing && isOverride())
+		{
+			error("does not override any function");
+		}
+
+		L2: ;
+		}
+		else if (isOverride() && !parent.isTemplateInstance())
+		error("override only applies to class member functions");
+
+		/* Do not allow template instances to add virtual functions
+		 * to a class.
+		 */
+		if (isVirtual())
+		{
+		TemplateInstance ti = parent.isTemplateInstance();
+		if (ti)
+		{
+			// Take care of nested templates
+			while (1)
+			{
+			TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
+			if (!ti2)
+				break;
+			ti = ti2;
+			}
+
+			// If it's a member template
+			ClassDeclaration cdd = ti.tempdecl.isClassMember();
+			if (cdd)
+			{
+				error("cannot use template to add virtual function to class '%s'", cdd.toChars());
+			}
+		}
+		}
+
+		if (isMain())
+		{
+		// Check parameters to see if they are either () or (char[][] args)
+		switch (nparams)
+		{
+			case 0:
+			break;
+
+			case 1:
+			{
+			Argument arg0 = Argument.getNth(f.parameters, 0);
+			if (arg0.type.ty != TY.Tarray ||
+				arg0.type.nextOf().ty != TY.Tarray ||
+				arg0.type.nextOf().nextOf().ty != TY.Tchar ||
+				arg0.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
+				goto Lmainerr;
+			break;
+			}
+
+			default:
+			goto Lmainerr;
+		}
+
+		if (f.nextOf().ty != TY.Tint32 && f.nextOf().ty != TY.Tvoid)
+			error("must return int or void, not %s", f.nextOf().toChars());
+		if (f.varargs)
+		{
+		Lmainerr:
+			error("parameters must be main() or main(char[][] args)");
+		}
+		}
+
+		if (ident == Id.assign && (sd || cd))
+		{	// Disallow identity assignment operator.
+
+		// opAssign(...)
+		if (nparams == 0)
+		{   if (f.varargs == 1)
+			goto Lassignerr;
+		}
+		else
+		{
+			Argument arg0 = Argument.getNth(f.parameters, 0);
+			Type t0 = arg0.type.toBasetype();
+			Type tb = sd ? sd.type : cd.type;
+			if (arg0.type.implicitConvTo(tb) ||
+			(sd && t0.ty == TY.Tpointer && t0.nextOf().implicitConvTo(tb))
+			   )
+			{
+			if (nparams == 1)
+				goto Lassignerr;
+			Argument arg1 = Argument.getNth(f.parameters, 1);
+			if (arg1.defaultArg)
+				goto Lassignerr;
+			}
+		}
+		}
+
+	Ldone:
+		/* Save scope for possible later use (if we need the
+		 * function internals)
+		 */
+		scope_ = new Scope(sc);
+		scope_.setNoFree();
+		return;
+
+	Lassignerr:
+		if (sd)
+		{
+		sd.hasIdentityAssign = 1;	// don't need to generate it
+		goto Ldone;
+		}
+		error("identity assignment operator overload is illegal");
+	}
+	
+    void semantic2(Scope sc)
+	{
+	}
+
+	// Do the semantic analysis on the internals of the function.
+    void semantic3(Scope sc)
+	{
+		TypeFunction f;
+		VarDeclaration argptr = null;
+		VarDeclaration _arguments = null;
+
+		if (!parent)
+		{
+		if (global.errors)
+			return;
+		//printf("FuncDeclaration.semantic3(%s '%s', sc = %p)\n", kind(), toChars(), sc);
+		assert(0);
+		}
+		//printf("FuncDeclaration.semantic3('%s.%s', sc = %p, loc = %s)\n", parent.toChars(), toChars(), sc, loc.toChars());
+		//fflush(stdout);
+		//printf("storage class = x%x %x\n", sc.stc, storage_class);
+		//{ static int x; if (++x == 2) *(char*)0=0; }
+		//printf("\tlinkage = %d\n", sc.linkage);
+
+		//printf(" sc.incontract = %d\n", sc.incontract);
+		if (semanticRun >= 3)
+		return;
+		semanticRun = 3;
+
+		if (!type || type.ty != TY.Tfunction)
+		return;
+		f = cast(TypeFunction)(type);
+
+		// Check the 'throws' clause
+		if (fthrows)
+		{
+		for (int i = 0; i < fthrows.dim; i++)
+		{
+			Type t = cast(Type)fthrows.data[i];
+
+			t = t.semantic(loc, sc);
+			if (!t.isClassHandle())
+			error("can only throw classes, not %s", t.toChars());
+		}
+		}
+
+		if (fbody || frequire)
+		{
+		/* Symbol table into which we place parameters and nested functions,
+		 * solely to diagnose name collisions.
+		 */
+		localsymtab = new DsymbolTable();
+
+		// Establish function scope
+		ScopeDsymbol ss = new ScopeDsymbol();
+		ss.parent = sc.scopesym;
+		Scope sc2 = sc.push(ss);
+		sc2.func = this;
+		sc2.parent = this;
+		sc2.callSuper = 0;
+		sc2.sbreak = null;
+		sc2.scontinue = null;
+		sc2.sw = null;
+		sc2.fes = fes;
+		sc2.linkage = LINK.LINKd;
+		sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref);
+		sc2.protection = PROT.PROTpublic;
+		sc2.explicitProtection = 0;
+		sc2.structalign = 8;
+		sc2.incontract = 0;
+		sc2.tf = null;
+		sc2.noctor = 0;
+
+		// Declare 'this'
+		AggregateDeclaration ad = isThis();
+		if (ad)
+		{   VarDeclaration v;
+
+			if (isFuncLiteralDeclaration() && isNested())
+			{
+			error("literals cannot be class members");
+			return;
+			}
+			else
+			{
+			assert(!isNested());	// can't be both member and nested
+			assert(ad.handle);
+			Type thandle = ad.handle;
+version (STRUCTTHISREF) {
+			thandle = thandle.addMod(type.mod);
+			thandle = thandle.addStorageClass(storage_class);
+			if (isPure())
+				thandle = thandle.addMod(MOD.MODconst);
+} else {
+			if (storage_class & STC.STCconst || type.isConst())
+			{
+				assert(0); // BUG: shared not handled
+				if (thandle.ty == TY.Tclass)
+				thandle = thandle.constOf();
+				else
+				{	assert(thandle.ty == TY.Tpointer);
+				thandle = thandle.nextOf().constOf().pointerTo();
+				}
+			}
+			else if (storage_class & STC.STCimmutable || type.isInvariant())
+			{
+				if (thandle.ty == TY.Tclass)
+				thandle = thandle.invariantOf();
+				else
+				{	assert(thandle.ty == TY.Tpointer);
+				thandle = thandle.nextOf().invariantOf().pointerTo();
+				}
+			}
+			else if (storage_class & STC.STCshared || type.isShared())
+			{
+				assert(0);  // not implemented
+			}
+}
+			v = new ThisDeclaration(loc, thandle);
+			v.storage_class |= STC.STCparameter;
+version (STRUCTTHISREF) {
+			if (thandle.ty == TY.Tstruct)
+				v.storage_class |= STC.STCref;
+}
+			v.semantic(sc2);
+			if (!sc2.insert(v))
+				assert(0);
+			v.parent = this;
+			vthis = v;
+			}
+		}
+		else if (isNested())
+		{
+			/* The 'this' for a nested function is the link to the
+			 * enclosing function's stack frame.
+			 * Note that nested functions and member functions are disjoint.
+			 */
+			VarDeclaration v = new ThisDeclaration(loc, Type.tvoid.pointerTo());
+			v.storage_class |= STC.STCparameter;
+			v.semantic(sc2);
+			if (!sc2.insert(v))
+			assert(0);
+			v.parent = this;
+			vthis = v;
+		}
+
+		// Declare hidden variable _arguments[] and _argptr
+		if (f.varargs == 1)
+		{
+version (TARGET_NET) {
+			varArgs(sc2, f, argptr, _arguments);
+} else {
+			Type t;
+
+			if (f.linkage == LINK.LINKd)
+			{	
+				// Declare _arguments[]
+version (BREAKABI) {
+				v_arguments = new VarDeclaration(Loc(0), Type.typeinfotypelist.type, Id._arguments_typeinfo, null);
+				v_arguments.storage_class = STCparameter;
+				v_arguments.semantic(sc2);
+				sc2.insert(v_arguments);
+				v_arguments.parent = this;
+
+				//t = Type.typeinfo.type.constOf().arrayOf();
+				t = Type.typeinfo.type.arrayOf();
+				_arguments = new VarDeclaration(Loc(0), t, Id._arguments, null);
+				_arguments.semantic(sc2);
+				sc2.insert(_arguments);
+				_arguments.parent = this;
+} else {
+				t = Type.typeinfo.type.arrayOf();
+				v_arguments = new VarDeclaration(Loc(0), t, Id._arguments, null);
+				v_arguments.storage_class = STC.STCparameter | STC.STCin;
+				v_arguments.semantic(sc2);
+				sc2.insert(v_arguments);
+				v_arguments.parent = this;
+	}
+				}
+				if (f.linkage == LINK.LINKd || (parameters && parameters.dim))
+				{	// Declare _argptr
+version (IN_GCC) {
+				t = d_gcc_builtin_va_list_d_type;
+} else {
+				t = Type.tvoid.pointerTo();
+}
+				argptr = new VarDeclaration(Loc(0), t, Id._argptr, null);
+				argptr.semantic(sc2);
+				sc2.insert(argptr);
+				argptr.parent = this;
+			}
+}
+		}
+
+		// Propagate storage class from tuple parameters to their element-parameters.
+		if (f.parameters)
+		{
+			for (size_t i = 0; i < f.parameters.dim; i++)
+			{	Argument arg = cast(Argument)f.parameters.data[i];
+
+			//printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars());
+			if (arg.type.ty == TY.Ttuple)
+			{   TypeTuple t = cast(TypeTuple)arg.type;
+				size_t dim = Argument.dim(t.arguments);
+				for (size_t j = 0; j < dim; j++)
+				{	Argument narg = Argument.getNth(t.arguments, j);
+				narg.storageClass = arg.storageClass;
+				}
+			}
+			}
+		}
+
+		/* Declare all the function parameters as variables
+		 * and install them in parameters[]
+		 */
+		size_t nparams = Argument.dim(f.parameters);
+		if (nparams)
+		{   /* parameters[] has all the tuples removed, as the back end
+			 * doesn't know about tuples
+			 */
+			parameters = new Dsymbols();
+			parameters.reserve(nparams);
+			for (size_t i = 0; i < nparams; i++)
+			{
+			Argument arg = Argument.getNth(f.parameters, i);
+			Identifier id = arg.ident;
+			if (!id)
+			{
+				/* Generate identifier for un-named parameter,
+				 * because we need it later on.
+				 */
+				arg.ident = id = Identifier.generateId("_param_", i);
+			}
+			Type vtype = arg.type;
+			if (isPure())
+				vtype = vtype.addMod(MOD.MODconst);
+			VarDeclaration v = new VarDeclaration(loc, vtype, id, null);
+			//printf("declaring parameter %s of type %s\n", v.toChars(), v.type.toChars());
+			v.storage_class |= STC.STCparameter;
+			if (f.varargs == 2 && i + 1 == nparams)
+				v.storage_class |= STC.STCvariadic;
+			v.storage_class |= arg.storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy | STC.STCfinal | STC.STC_TYPECTOR | STC.STCnodtor);
+			v.semantic(sc2);
+			if (!sc2.insert(v))
+				error("parameter %s.%s is already defined", toChars(), v.toChars());
+			else
+				parameters.push(cast(void*)v);
+			localsymtab.insert(v);
+			v.parent = this;
+			}
+		}
+
+		// Declare the tuple symbols and put them in the symbol table,
+		// but not in parameters[].
+		if (f.parameters)
+		{
+			for (size_t i = 0; i < f.parameters.dim; i++)
+			{	Argument arg = cast(Argument)f.parameters.data[i];
+
+			if (!arg.ident)
+				continue;			// never used, so ignore
+			if (arg.type.ty == TY.Ttuple)
+			{   TypeTuple t = cast(TypeTuple)arg.type;
+				size_t dim = Argument.dim(t.arguments);
+				Objects exps = new Objects();
+				exps.setDim(dim);
+				for (size_t j = 0; j < dim; j++)
+				{	Argument narg = Argument.getNth(t.arguments, j);
+				assert(narg.ident);
+				VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration();
+				assert(v);
+				Expression e = new VarExp(v.loc, v);
+				exps.data[j] = cast(void*)e;
+				}
+				assert(arg.ident);
+				TupleDeclaration v = new TupleDeclaration(loc, arg.ident, exps);
+				//printf("declaring tuple %s\n", v.toChars());
+				v.isexp = 1;
+				if (!sc2.insert(v))
+				error("parameter %s.%s is already defined", toChars(), v.toChars());
+				localsymtab.insert(v);
+				v.parent = this;
+			}
+			}
+		}
+
+		/* Do the semantic analysis on the [in] preconditions and
+		 * [out] postconditions.
+		 */
+		sc2.incontract++;
+
+		if (frequire)
+		{   /* frequire is composed of the [in] contracts
+			 */
+			// BUG: need to error if accessing out parameters
+			// BUG: need to treat parameters as const
+			// BUG: need to disallow returns and throws
+			// BUG: verify that all in and ref parameters are read
+			frequire = frequire.semantic(sc2);
+			labtab = null;		// so body can't refer to labels
+		}
+
+		if (fensure || addPostInvariant())
+		{   /* fensure is composed of the [out] contracts
+			 */
+			ScopeDsymbol sym = new ScopeDsymbol();
+			sym.parent = sc2.scopesym;
+			sc2 = sc2.push(sym);
+
+			assert(type.nextOf());
+			if (type.nextOf().ty == TY.Tvoid)
+			{
+			if (outId)
+				error("void functions have no result");
+			}
+			else
+			{
+			if (!outId)
+				outId = Id.result;		// provide a default
+			}
+
+			if (outId)
+			{	// Declare result variable
+			VarDeclaration v;
+			Loc loc = this.loc;
+
+			if (fensure)
+				loc = fensure.loc;
+
+			v = new VarDeclaration(loc, type.nextOf(), outId, null);
+			v.noauto = true;
+version (DMDV2) {
+			if (f.isref)
+			{
+				v.storage_class |= STC.STCref | STC.STCforeach;
+			}
+}
+			sc2.incontract--;
+			v.semantic(sc2);
+			sc2.incontract++;
+			if (!sc2.insert(v))
+				error("out result %s is already defined", v.toChars());
+			v.parent = this;
+			vresult = v;
+
+			// vresult gets initialized with the function return value
+			// in ReturnStatement.semantic()
+			}
+
+			// BUG: need to treat parameters as const
+			// BUG: need to disallow returns and throws
+			if (fensure)
+			{	fensure = fensure.semantic(sc2);
+			labtab = null;		// so body can't refer to labels
+			}
+
+			if (!global.params.useOut)
+			{	fensure = null;		// discard
+			vresult = null;
+			}
+
+			// Postcondition invariant
+			if (addPostInvariant())
+			{
+			Expression e = null;
+			if (isCtorDeclaration())
+			{
+				// Call invariant directly only if it exists
+				InvariantDeclaration inv = ad.inv;
+				ClassDeclaration cd = ad.isClassDeclaration();
+
+				while (!inv && cd)
+				{
+				cd = cd.baseClass;
+				if (!cd)
+					break;
+				inv = cd.inv;
+				}
+				if (inv)
+				{
+				e = new DsymbolExp(Loc(0), inv);
+				e = new CallExp(Loc(0), e);
+				e = e.semantic(sc2);
+				}
+			}
+			else
+			{   // Call invariant virtually
+				Expression v = new ThisExp(Loc(0));
+				v.type = vthis.type;
+version (STRUCTTHISREF) {
+				if (ad.isStructDeclaration())
+				v = v.addressOf(sc);
+}
+				e = new AssertExp(Loc(0), v);
+			}
+			if (e)
+			{
+				ExpStatement s = new ExpStatement(Loc(0), e);
+				if (fensure)
+				fensure = new CompoundStatement(Loc(0), s, fensure);
+				else
+				fensure = s;
+			}
+			}
+
+			if (fensure)
+			{	returnLabel = new LabelDsymbol(Id.returnLabel);
+			LabelStatement ls = new LabelStatement(Loc(0), Id.returnLabel, fensure);
+			ls.isReturnLabel = 1;
+			returnLabel.statement = ls;
+			}
+			sc2 = sc2.pop();
+		}
+
+		sc2.incontract--;
+		
+		if (fbody)
+		{   ClassDeclaration cd = isClassMember();
+
+			/* If this is a class constructor
+			 */
+			if (isCtorDeclaration() && cd)
+			{
+			for (int i = 0; i < cd.fields.dim; i++)
+			{   VarDeclaration v = cast(VarDeclaration)cd.fields.data[i];
+
+				v.ctorinit = 0;
+			}
+			}
+
+			if (inferRetType || f.retStyle() != RET.RETstack)
+			nrvo_can = 0;
+
+			fbody = fbody.semantic(sc2);
+			if (!fbody)
+			fbody = new CompoundStatement(Loc(0), new Statements());
+
+			if (inferRetType)
+			{	// If no return type inferred yet, then infer a void
+			if (!type.nextOf())
+			{
+				(cast(TypeFunction)type).next = Type.tvoid;
+				type = type.semantic(loc, sc);
+			}
+			f = cast(TypeFunction)type;
+			}
+			
+			if (isStaticCtorDeclaration())
+			{	
+				/* It's a static constructor. Ensure that all
+				 * ctor consts were initialized.
+				 */
+
+			Dsymbol p = toParent();
+			ScopeDsymbol add = p.isScopeDsymbol();
+			if (!add)
+			{
+				error("static constructor can only be member of struct/class/module, not %s %s", p.kind(), p.toChars());
+			}
+			else
+			{
+				for (int i = 0; i < add.members.dim; i++)
+				{   Dsymbol s = cast(Dsymbol)add.members.data[i];
+
+				s.checkCtorConstInit();
+				}
+			}
+			}
+
+			if (isCtorDeclaration() && cd)
+			{
+				//printf("callSuper = x%x\n", sc2.callSuper);
+
+				// Verify that all the ctorinit fields got initialized
+				if (!(sc2.callSuper & CSX.CSXthis_ctor))
+				{
+					for (int i = 0; i < cd.fields.dim; i++)
+					{   VarDeclaration v = cast(VarDeclaration)cd.fields.data[i];
+
+					if (v.ctorinit == 0 && v.isCtorinit())
+						error("missing initializer for final field %s", v.toChars());
+					}
+				}
+
+				if (!(sc2.callSuper & CSX.CSXany_ctor) &&
+					cd.baseClass && cd.baseClass.ctor)
+				{
+					sc2.callSuper = 0;
+
+					// Insert implicit super() at start of fbody
+					Expression e1 = new SuperExp(Loc(0));
+					Expression e = new CallExp(Loc(0), e1);
+
+					e = e.trySemantic(sc2);
+					if (!e)
+					error("no match for implicit super() call in constructor");
+					else
+					{
+					Statement s = new ExpStatement(Loc(0), e);
+					fbody = new CompoundStatement(Loc(0), s, fbody);
+					}
+				}
+				}
+				else if (fes)
+				{	// For foreach(){} body, append a return 0;
+				Expression e = new IntegerExp(0);
+				Statement s = new ReturnStatement(Loc(0), e);
+				fbody = new CompoundStatement(Loc(0), fbody, s);
+				assert(!returnLabel);
+				}
+				else if (!hasReturnExp && type.nextOf().ty != TY.Tvoid)
+				error("expected to return a value of type %s", type.nextOf().toChars());
+				else if (!inlineAsm)
+				{
+version (DMDV2) {
+				BE blockexit = fbody ? fbody.blockExit() : BE.BEfallthru;
+				if (f.isnothrow && blockexit & BE.BEthrow)
+					error("'%s' is nothrow yet may throw", toChars());
+
+				int offend = blockexit & BE.BEfallthru;
+}
+				if (type.nextOf().ty == TY.Tvoid)
+				{
+					if (offend && isMain())
+					{	// Add a return 0; statement
+					Statement s = new ReturnStatement(Loc(0), new IntegerExp(0));
+					fbody = new CompoundStatement(Loc(0), fbody, s);
+					}
+				}
+				else
+				{
+					if (offend)
+					{   
+						Expression e;
+version (DMDV1) {
+						warning(loc, "no return exp; or assert(0); at end of function");
+} else {
+						error("no return exp; or assert(0); at end of function");
+}
+						if (global.params.useAssert &&
+							!global.params.useInline)
+						{   /* Add an assert(0, msg); where the missing return
+							 * should be.
+							 */
+							e = new AssertExp(
+							  endloc,
+							  new IntegerExp(0),
+							  new StringExp(loc, "missing return expression")
+							);
+						}
+						else
+							e = new HaltExp(endloc);
+
+						e = new CommaExp(Loc(0), e, type.nextOf().defaultInit(Loc(0)));
+						e = e.semantic(sc2);
+						Statement s = new ExpStatement(Loc(0), e);
+						fbody = new CompoundStatement(Loc(0), fbody, s);
+					}
+				}
+			}
+		}
+
+		{
+			Statements a = new Statements();
+
+			// Merge in initialization of 'out' parameters
+			if (parameters)
+			{	for (size_t i = 0; i < parameters.dim; i++)
+			{
+				VarDeclaration v = cast(VarDeclaration)parameters.data[i];
+				if (v.storage_class & STC.STCout)
+				{
+				assert(v.init);
+				ExpInitializer ie = v.init.isExpInitializer();
+				assert(ie);
+				a.push(cast(void*)new ExpStatement(Loc(0), ie.exp));
+				}
+			}
+			}
+
+			if (argptr)
+			{	// Initialize _argptr to point past non-variadic arg
+version (IN_GCC) {
+			// Handled in FuncDeclaration.toObjFile
+			v_argptr = argptr;
+			v_argptr.init = new VoidInitializer(loc);
+} else {
+			Expression e1;
+			Expression e;
+			Type t = argptr.type;
+			VarDeclaration p;
+			uint offset;
+
+			e1 = new VarExp(Loc(0), argptr);
+			if (parameters && parameters.dim)
+				p = cast(VarDeclaration)parameters.data[parameters.dim - 1];
+			else
+				p = v_arguments;		// last parameter is _arguments[]
+			offset = cast(uint)p.type.size();	///
+			offset = (offset + 3) & ~3;	// assume stack aligns on 4
+			e = new SymOffExp(Loc(0), p, offset);
+			e = new AssignExp(Loc(0), e1, e);
+			e.type = t;
+			a.push(cast(void*)new ExpStatement(Loc(0), e));
+}
+			}
+
+			if (_arguments)
+			{
+			/* Advance to elements[] member of TypeInfo_Tuple with:
+			 *  _arguments = v_arguments.elements;
+			 */
+			Expression e = new VarExp(Loc(0), v_arguments);
+			e = new DotIdExp(Loc(0), e, Id.elements);
+			Expression e1 = new VarExp(Loc(0), _arguments);
+			e = new AssignExp(Loc(0), e1, e);
+			e.op = TOK.TOKconstruct;
+			e = e.semantic(sc2);
+			a.push(cast(void*)new ExpStatement(Loc(0), e));
+			}
+
+			// Merge contracts together with body into one compound statement
+
+version (_DH) {
+			if (frequire && global.params.useIn)
+			{	frequire.incontract = 1;
+			a.push(frequire);
+			}
+} else {
+			if (frequire && global.params.useIn)
+			a.push(cast(void*)frequire);
+}
+
+			// Precondition invariant
+			if (addPreInvariant())
+			{
+			Expression e = null;
+			if (isDtorDeclaration())
+			{
+				// Call invariant directly only if it exists
+				InvariantDeclaration inv = ad.inv;
+				ClassDeclaration cd = ad.isClassDeclaration();
+
+				while (!inv && cd)
+				{
+				cd = cd.baseClass;
+				if (!cd)
+					break;
+				inv = cd.inv;
+				}
+				if (inv)
+				{
+				e = new DsymbolExp(Loc(0), inv);
+				e = new CallExp(Loc(0), e);
+				e = e.semantic(sc2);
+				}
+			}
+			else
+			{   // Call invariant virtually
+				Expression v = new ThisExp(Loc(0));
+				v.type = vthis.type;
+version (STRUCTTHISREF) {
+				if (ad.isStructDeclaration())
+					v = v.addressOf(sc);
+}
+				Expression se = new StringExp(Loc(0), "null this");
+				se = se.semantic(sc);
+				se.type = Type.tchar.arrayOf();
+				e = new AssertExp(loc, v, se);
+			}
+			if (e)
+			{
+				ExpStatement s = new ExpStatement(Loc(0), e);
+				a.push(cast(void*)s);
+			}
+			}
+
+			if (fbody)
+			a.push(cast(void*)fbody);
+
+			if (fensure)
+			{
+			a.push(cast(void*)returnLabel.statement);
+
+			if (type.nextOf().ty != TY.Tvoid)
+			{
+				// Create: return vresult;
+				assert(vresult);
+				Expression e = new VarExp(Loc(0), vresult);
+				if (tintro)
+				{	e = e.implicitCastTo(sc, tintro.nextOf());
+				e = e.semantic(sc);
+				}
+				ReturnStatement s = new ReturnStatement(Loc(0), e);
+				a.push(cast(void*)s);
+			}
+			}
+
+			fbody = new CompoundStatement(Loc(0), a);
+version (DMDV2) {
+			/* Append destructor calls for parameters as finally blocks.
+			 */
+			if (parameters)
+			{	for (size_t i = 0; i < parameters.dim; i++)
+			{
+				VarDeclaration v = cast(VarDeclaration)parameters.data[i];
+
+				if (v.storage_class & (STC.STCref | STC.STCout))
+				continue;
+
+				/* Don't do this for static arrays, since static
+				 * arrays are called by reference. Remove this
+				 * when we change them to call by value.
+				 */
+				if (v.type.toBasetype().ty == TY.Tsarray)
+				continue;
+
+				Expression e = v.callAutoDtor(sc);
+				if (e)
+				{	Statement s = new ExpStatement(Loc(0), e);
+				s = s.semantic(sc);
+				if (fbody.blockExit() == BE.BEfallthru)
+					fbody = new CompoundStatement(Loc(0), fbody, s);
+				else
+					fbody = new TryFinallyStatement(Loc(0), fbody, s);
+				}
+			}
+			}
+}
+
+static if (true) {
+			if (isSynchronized())
+			{	/* Wrap the entire function body in a synchronized statement
+				 */
+				ClassDeclaration cd = parent.isClassDeclaration();
+				if (cd)
+				{
+///version (TARGET_WINDOS) {
+					if (/*config.flags2 & CFG2.CFG2seh &&*/	// always on for WINDOS
+					!isStatic() && !fbody.usesEH())
+					{
+						/* The back end uses the "jmonitor" hack for syncing;
+						 * no need to do the sync at this level.
+						 */
+					}
+					else
+///}
+					{
+						Expression vsync;
+						if (isStatic())
+						{   
+							// The monitor is in the ClassInfo
+							vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id.classinfo_);
+						}
+						else
+						{   // 'this' is the monitor
+							vsync = new VarExp(loc, vthis);
+						}
+						fbody = new PeelStatement(fbody);	// don't redo semantic()
+						fbody = new SynchronizedStatement(loc, vsync, fbody);
+						fbody = fbody.semantic(sc2);
+					}
+				}
+				else
+				{
+					error("synchronized function %s must be a member of a class", toChars());
+				}
+			}
+}
+		}
+
+		sc2.callSuper = 0;
+		sc2.pop();
+		}
+		semanticRun = 4;
+	}
+	
+    // called from semantic3
+    void varArgs(Scope sc, TypeFunction, ref VarDeclaration, ref VarDeclaration)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    void bodyToCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+	/****************************************************
+	 * Determine if 'this' overrides fd.
+	 * Return true if it does.
+	 */
+    bool overrides(FuncDeclaration fd)
+	{
+		bool result = false;
+
+		if (fd.ident == ident)
+		{
+			int cov = type.covariant(fd.type);
+			if (cov)
+			{   
+				ClassDeclaration cd1 = toParent().isClassDeclaration();
+				ClassDeclaration cd2 = fd.toParent().isClassDeclaration();
+
+				if (cd1 && cd2 && cd2.isBaseOf(cd1, null))
+					result = true;
+			}
+		}
+		return result;
+	}
+	
+	/*************************************************
+	 * Find index of function in vtbl[0..dim] that
+	 * this function overrides.
+	 * Returns:
+	 *	-1	didn't find one
+	 *	-2	can't determine because of forward references
+	 */
+    int findVtblIndex(Array vtbl, int dim)
+	{
+		for (int vi = 0; vi < dim; vi++)
+		{
+			FuncDeclaration fdv = (cast(Dsymbol)vtbl.data[vi]).isFuncDeclaration();
+			if (fdv && fdv.ident is ident)
+			{
+				int cov = type.covariant(fdv.type);
+				//printf("\tbaseclass cov = %d\n", cov);
+				switch (cov)
+				{
+					case 0:		// types are distinct
+						break;
+
+					case 1:
+						return vi;
+
+					case 2:
+						//type.print();
+						//fdv.type.print();
+						//printf("%s %s\n", type.deco, fdv.type.deco);
+						error("of type %s overrides but is not covariant with %s of type %s",
+						type.toChars(), fdv.toPrettyChars(), fdv.type.toChars());
+						break;
+
+					case 3:
+						return -2;	// forward references
+				}
+			}
+		}
+		return -1;
+	}
+
+	/****************************************************
+	 * Overload this FuncDeclaration with the new one f.
+	 * Return !=0 if successful; i.e. no conflict.
+	 */
+    bool overloadInsert(Dsymbol s)
+	{
+		FuncDeclaration f;
+		AliasDeclaration a;
+
+		//writef("FuncDeclaration.overloadInsert(%s)\n", s.toChars());
+		a = s.isAliasDeclaration();
+		if (a)
+		{
+			if (overnext)
+				return overnext.overloadInsert(a);
+
+			if (!a.aliassym && a.type.ty != TY.Tident && a.type.ty != TY.Tinstance)
+			{
+				//writef("\ta = '%s'\n", a.type.toChars());
+				return false;
+			}
+			overnext = a;
+			//printf("\ttrue: no conflict\n");
+			return true;
+		}
+		f = s.isFuncDeclaration();
+		if (!f)
+			return false;
+
+static if (false) {
+		/* Disable this check because:
+		 *	const void foo();
+		 * semantic() isn't run yet on foo(), so the const hasn't been
+		 * applied yet.
+		 */
+		if (type)
+		{   
+			printf("type = %s\n", type.toChars());
+			printf("f.type = %s\n", f.type.toChars());
+		}
+		if (type && f.type &&	// can be null for overloaded constructors
+		f.type.covariant(type) &&
+		f.type.mod == type.mod &&
+		!isFuncAliasDeclaration())
+		{
+			//printf("\tfalse: conflict %s\n", kind());
+			return false;
+		}
+}
+
+		if (overnext)
+			return overnext.overloadInsert(f);
+		overnext = f;
+		//printf("\ttrue: no conflict\n");
+		return true;
+	}
+	
+    FuncDeclaration overloadExactMatch(Type t)
+	{
+		Param1 p;
+		p.t = t;
+		p.f = null;
+		overloadApply(this, &p.fp1);
+		return p.f;
+	}
+	
+    FuncDeclaration overloadResolve(Loc loc, Expression ethis, Expressions arguments, int flags = 0)
+	{
+		TypeFunction tf;
+		Match m;
+
+static if (false) {
+		printf("FuncDeclaration.overloadResolve('%s')\n", toChars());
+		if (arguments)
+		{   
+			int i;
+
+			for (i = 0; i < arguments.dim; i++)
+			{   
+				Expression arg;
+
+				arg = cast(Expression)arguments.data[i];
+				assert(arg.type);
+				printf("\t%s: ", arg.toChars());
+				arg.type.print();
+			}
+		}
+}
+
+		m.last = MATCH.MATCHnomatch;
+		overloadResolveX(&m, this, ethis, arguments);
+
+		if (m.count == 1)		// exactly one match
+		{
+			return m.lastf;
+		}
+		else
+		{
+			scope OutBuffer buf = new OutBuffer();
+
+			buf.writeByte('(');
+			if (arguments)
+			{
+				HdrGenState hgs;
+
+				argExpTypesToCBuffer(buf, arguments, &hgs);
+				buf.writeByte(')');
+				if (ethis)
+					ethis.type.modToBuffer(buf);
+			}
+			else
+				buf.writeByte(')');
+
+			if (m.last == MATCH.MATCHnomatch)
+			{
+				if (flags & 1)		// if do not print error messages
+					return null;		// no match
+
+				tf = cast(TypeFunction)type;
+
+				scope OutBuffer buf2 = new OutBuffer();
+				tf.modToBuffer(buf2);
+
+				//printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco);
+				error(loc, "%s%s is not callable using argument types %s",
+				Argument.argsTypesToChars(tf.parameters, tf.varargs),
+				buf2.toChars(),
+				buf.toChars());
+				return m.anyf;		// as long as it's not a FuncAliasDeclaration
+			}
+			else
+			{
+static if (true) {
+				TypeFunction t1 = cast(TypeFunction)m.lastf.type;
+				TypeFunction t2 = cast(TypeFunction)m.nextf.type;
+
+				error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s",
+					buf.toChars(),
+					m.lastf.toPrettyChars(), Argument.argsTypesToChars(t1.parameters, t1.varargs),
+					m.nextf.toPrettyChars(), Argument.argsTypesToChars(t2.parameters, t2.varargs));
+} else {
+				error(loc, "overloads %s and %s both match argument list for %s",
+					m.lastf.type.toChars(),
+					m.nextf.type.toChars(),
+					m.lastf.toChars());
+}
+				return m.lastf;
+			}
+		}
+	}
+	
+	/*************************************
+	 * Determine partial specialization order of 'this' vs g.
+	 * This is very similar to TemplateDeclaration.leastAsSpecialized().
+	 * Returns:
+	 *	match	'this' is at least as specialized as g
+	 *	0	g is more specialized than 'this'
+	 */
+    MATCH leastAsSpecialized(FuncDeclaration g)
+	{
+	version (LOG_LEASTAS) {
+		printf("%s.leastAsSpecialized(%s)\n", toChars(), g.toChars());
+	}
+
+		/* This works by calling g() with f()'s parameters, and
+		 * if that is possible, then f() is at least as specialized
+		 * as g() is.
+		 */
+
+		TypeFunction tf = cast(TypeFunction)type;
+		TypeFunction tg = cast(TypeFunction)g.type;
+		size_t nfparams = Argument.dim(tf.parameters);
+		size_t ngparams = Argument.dim(tg.parameters);
+		MATCH match = MATCHexact;
+
+		/* If both functions have a 'this' pointer, and the mods are not
+		 * the same and g's is not const, then this is less specialized.
+		 */
+		if (needThis() && g.needThis())
+		{
+			if (tf.mod != tg.mod)
+			{
+				if (tg.mod == MODconst)
+					match = MATCHconst;
+				else
+					return MATCHnomatch;
+			}
+		}
+
+		/* Create a dummy array of arguments out of the parameters to f()
+		 */
+		scope Expressions args = new Expressions();
+		args.setDim(nfparams);
+		for (int u = 0; u < nfparams; u++)
+		{
+			Argument p = Argument.getNth(tf.parameters, u);
+			Expression e;
+			if (p.storageClass & (STCref | STCout))
+			{
+				e = new IdentifierExp(Loc(0), p.ident);
+				e.type = p.type;
+			}
+			else
+				e = p.type.defaultInit(Loc(0));
+
+			args.data[u] = cast(void*)e;
+		}
+
+		MATCH m = cast(MATCH) tg.callMatch(null, args);
+		if (m)
+		{
+			/* A variadic parameter list is less specialized than a
+			 * non-variadic one.
+			 */
+			if (tf.varargs && !tg.varargs)
+				goto L1;	// less specialized
+
+	version (LOG_LEASTAS) {
+			printf("  matches %d, so is least as specialized\n", m);
+	}
+			return m;
+		}
+	  L1:
+	version (LOG_LEASTAS) {
+		printf("  doesn't match, so is not as specialized\n");
+	}
+		return MATCHnomatch;
+	}
+	
+	/********************************
+	 * Labels are in a separate scope, one per function.
+	 */
+    LabelDsymbol searchLabel(Identifier ident)
+	{
+		Dsymbol s;
+
+		if (!labtab)
+			labtab = new DsymbolTable();	// guess we need one
+
+		s = labtab.lookup(ident);
+		if (!s)
+		{
+			s = new LabelDsymbol(ident);
+			labtab.insert(s);
+		}
+
+		return cast(LabelDsymbol)s;
+	}
+	
+	/****************************************
+	 * If non-static member function that has a 'this' pointer,
+	 * return the aggregate it is a member of.
+	 * Otherwise, return null.
+	 */
+    AggregateDeclaration isThis()
+	{
+		AggregateDeclaration ad = null;
+
+		//printf("+FuncDeclaration.isThis() '%s'\n", toChars());
+		if ((storage_class & STC.STCstatic) == 0)
+		{
+			ad = isMember2();
+		}
+		//printf("-FuncDeclaration.isThis() %p\n", ad);
+		return ad;
+	}
+	
+    AggregateDeclaration isMember2()
+	{
+		AggregateDeclaration ad = null;
+
+		//printf("+FuncDeclaration.isMember2() '%s'\n", toChars());
+		for (Dsymbol s = this; s; s = s.parent)
+		{
+		//printf("\ts = '%s', parent = '%s', kind = %s\n", s.toChars(), s.parent.toChars(), s.parent.kind());
+			ad = s.isMember();
+			if (ad)
+			{   //printf("test4\n");
+					break;
+			}
+			if (!s.parent || (!s.parent.isTemplateInstance()))
+			{   //printf("test5\n");
+					break;
+			}
+		}
+		//printf("-FuncDeclaration.isMember2() %p\n", ad);
+		return ad;
+	}
+	
+	/*****************************************
+	 * Determine lexical level difference from 'this' to nested function 'fd'.
+	 * Error if this cannot call fd.
+	 * Returns:
+	 *	0	same level
+	 *	-1	increase nesting by 1 (fd is nested within 'this')
+	 *	>0	decrease nesting by number
+	 */
+    int getLevel(Loc loc, FuncDeclaration fd)	// lexical nesting level difference
+	{
+		int level;
+		Dsymbol s;
+		Dsymbol fdparent;
+
+		//printf("FuncDeclaration.getLevel(fd = '%s')\n", fd.toChars());
+		fdparent = fd.toParent2();
+		if (fdparent == this)
+			return -1;
+		s = this;
+		level = 0;
+		while (fd != s && fdparent != s.toParent2())
+		{
+			//printf("\ts = '%s'\n", s.toChars());
+			FuncDeclaration thisfd = s.isFuncDeclaration();
+			if (thisfd)
+			{   
+				if (!thisfd.isNested() && !thisfd.vthis)
+					goto Lerr;
+			}
+			else
+			{
+				AggregateDeclaration thiscd = s.isAggregateDeclaration();
+				if (thiscd)
+				{	
+					if (!thiscd.isNested())
+						goto Lerr;
+				}
+				else
+					goto Lerr;
+			}
+
+			s = s.toParent2();
+			assert(s);
+			level++;
+		}
+		return level;
+
+	Lerr:
+		error(loc, "cannot access frame of function %s", fd.toChars());
+		return 1;
+	}
+
+    void appendExp(Expression e)
+	{
+		assert(false);
+	}
+
+    void appendState(Statement s)
+	{
+		assert(false);
+	}
+
+    string mangle()
+	out (result)
+	{
+		assert(result.length > 0);
+	}
+	body
+	{
+		if (isMain()) {
+			return "_Dmain";
+		}
+
+		if (isWinMain() || isDllMain() || ident == Id.tls_get_addr)
+			return ident.toChars();
+
+		assert(this);
+
+		return Declaration.mangle();
+	}
+	
+    string toPrettyChars()
+	{
+		if (isMain())
+			return "D main";
+		else
+			return Dsymbol.toPrettyChars();
+	}
+	
+    int isMain()
+	{
+		return ident is Id.main && linkage != LINK.LINKc && !isMember() && !isNested();
+	}
+	
+    int isWinMain()
+	{
+		//printf("FuncDeclaration::isWinMain() %s\n", toChars());
+static if (false) {
+		int x = ident == Id.WinMain &&
+		linkage != LINK.LINKc && !isMember();
+		printf("%s\n", x ? "yes" : "no");
+		return x;
+} else {
+		return ident == Id.WinMain && linkage != LINK.LINKc && !isMember();
+}
+	}
+
+    int isDllMain()
+	{
+		return ident == Id.DllMain && linkage != LINK.LINKc && !isMember();
+	}
+
+	/**********************************
+	 * Determine if function is a builtin one that we can
+	 * evaluate at compile time.
+	 */
+    BUILTIN isBuiltin()
+	{
+		static string FeZe = "FNaNbeZe";	// pure nothrow real function(real)
+
+		//printf("FuncDeclaration::isBuiltin() %s\n", toChars());
+		if (builtin == BUILTIN.BUILTINunknown)
+		{
+			builtin = BUILTIN.BUILTINnot;
+			if (parent && parent.isModule())
+			{
+				// If it's in the std.math package
+				if (parent.ident == Id.math && parent.parent && parent.parent.ident == Id.std && !parent.parent.parent)
+				{
+					//printf("deco = %s\n", type.deco);
+					if (type.deco == FeZe)
+					{
+						if (ident == Id.sin)
+							builtin = BUILTIN.BUILTINsin;
+						else if (ident == Id.cos)
+							builtin = BUILTIN.BUILTINcos;
+						else if (ident == Id.tan)
+							builtin = BUILTIN.BUILTINtan;
+						else if (ident == Id._sqrt)
+							builtin = BUILTIN.BUILTINsqrt;
+						else if (ident == Id.fabs)
+							builtin = BUILTIN.BUILTINfabs;
+						//printf("builtin = %d\n", builtin);
+					}
+					// if float or double versions
+					else if (type.deco == "FNaNbdZd" || type.deco == "FNaNbfZf")
+					{
+						if (ident == Id._sqrt)
+							builtin = BUILTIN.BUILTINsqrt;
+					}
+				}
+			}
+		}
+
+		return builtin;
+	}
+	
+    bool isExport()
+	{
+		return protection == PROT.PROTexport;
+	}
+	
+    bool isImportedSymbol()
+	{
+		//printf("isImportedSymbol()\n");
+		//printf("protection = %d\n", protection);
+		return (protection == PROT.PROTexport) && !fbody;
+	}
+	
+    bool isAbstract()
+	{
+		return (storage_class & STC.STCabstract) != 0;
+	}
+	
+    bool isCodeseg()
+	{
+		assert(false);
+	}
+	
+    bool isOverloadable()
+	{
+		assert(false);
+	}
+	
+    bool isPure()
+	{
+		//printf("FuncDeclaration::isPure() '%s'\n", toChars());
+		assert(type.ty == TY.Tfunction);
+		return (cast(TypeFunction)this.type).ispure;
+	}
+	
+    bool isNested()
+	{
+		//if (!toParent())
+		//printf("FuncDeclaration.isNested('%s') parent=%p\n", toChars(), parent);
+		//printf("\ttoParent2() = '%s'\n", toParent2().toChars());
+		return ((storage_class & STC.STCstatic) == 0) &&
+		   (toParent2().isFuncDeclaration() !is null);
+	}
+	
+    bool needThis()
+	{
+		//printf("FuncDeclaration.needThis() '%s'\n", toChars());
+		bool needThis = isThis() !is null;
+
+		//printf("\t%d\n", i);
+		if (!needThis) {
+			if (auto fa = isFuncAliasDeclaration()) {
+				needThis = fa.funcalias.needThis();
+			}
+		}
+
+		return needThis;
+	}
+	
+    bool isVirtual()
+	{
+static if (false) {
+		printf("FuncDeclaration.isVirtual(%s)\n", toChars());
+		printf("isMember:%p isStatic:%d private:%d ctor:%d !Dlinkage:%d\n", isMember(), isStatic(), protection == PROT.PROTprivate, isCtorDeclaration(), linkage != LINK.LINKd);
+		printf("result is %d\n",
+		isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration());
+}
+		return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration();
+	}
+	
+    int isFinal()
+	{
+		ClassDeclaration cd;
+static if (false) {
+		printf("FuncDeclaration.isFinal(%s)\n", toChars());
+		printf("%p %d %d %d %d\n", isMember(), isStatic(), protection == PROT.PROTprivate, isCtorDeclaration(), linkage != LINK.LINKd);
+		printf("result is %d\n",
+		isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && (cd = toParent().isClassDeclaration()) !is null && cd.storage_class & STC.STCfinal);
+}
+		return isMember() && (Declaration.isFinal() || ((cd = toParent().isClassDeclaration()) !is null && cd.storage_class & STC.STCfinal));
+	}
+	
+    bool addPreInvariant()
+	{
+		AggregateDeclaration ad = isThis();
+		return (ad &&
+			//ad.isClassDeclaration() &&
+			global.params.useInvariants &&
+			(protection == PROT.PROTpublic || protection == PROT.PROTexport) &&
+			!naked &&
+			ident !is Id.cpctor);
+	}
+	
+    bool addPostInvariant()
+	{
+		AggregateDeclaration ad = isThis();
+		return (ad && ad.inv && 
+			//ad.isClassDeclaration() &&
+			global.params.useInvariants &&
+			(protection == PROT.PROTpublic || protection == PROT.PROTexport) &&
+			!naked &&
+			ident !is Id.cpctor);
+	}
+	
+    Expression interpret(InterState* istate, Expressions arguments, Expression thisexp = null)
+	{
+		assert(false);
+	}
+	
+    void inlineScan()
+	{
+		InlineScanState iss;
+
+	version (LOG) {
+		printf("FuncDeclaration.inlineScan('%s')\n", toChars());
+	}
+		///memset(&iss, 0, sizeof(iss));
+		iss.fd = this;
+		if (fbody)
+		{
+			inlineNest++;
+			fbody = fbody.inlineScan(&iss);
+			inlineNest--;
+		}
+	}
+	
+    int canInline(int hasthis, int hdrscan = 0)
+	{
+		int cost;
+
+//	#define CANINLINE_LOG 0
+
+	version (CANINLINE_LOG) {
+		printf("FuncDeclaration.canInline(hasthis = %d, '%s')\n", hasthis, toChars());
+	}
+
+		if (needThis() && !hasthis)
+			return 0;
+
+		if (inlineNest || (semanticRun < 3 && !hdrscan))
+		{
+	version (CANINLINE_LOG) {
+			printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
+	}
+			return 0;
+		}
+
+		switch (inlineStatus)
+		{
+			case ILS.ILSyes:
+		version (CANINLINE_LOG) {
+				printf("\t1: yes %s\n", toChars());
+		}
+				return 1;
+
+			case ILS.ILSno:
+		version (CANINLINE_LOG) {
+				printf("\t1: no %s\n", toChars());
+		}
+				return 0;
+
+			case ILS.ILSuninitialized:
+				break;
+
+			default:
+				assert(0);
+		}
+
+		if (type)
+		{	
+			assert(type.ty == Tfunction);
+			TypeFunction tf = cast(TypeFunction)type;
+			if (tf.varargs == 1)	// no variadic parameter lists
+				goto Lno;
+
+			/* Don't inline a function that returns non-void, but has
+			 * no return expression.
+			 */
+			if (tf.next && tf.next.ty != Tvoid &&
+				!(hasReturnExp & 1) &&
+				!hdrscan)
+					goto Lno;
+		}
+		else
+		{	
+			CtorDeclaration ctor = isCtorDeclaration();
+			if (ctor && ctor.varargs == 1)
+				goto Lno;
+		}
+
+		if (
+			!fbody ||
+			!hdrscan &&
+		(
+///	static if (false) {
+///		isCtorDeclaration() ||	// cannot because need to convert:
+///					//	return;
+///					// to:
+///					//	return this;
+///	}
+		isSynchronized() ||
+		isImportedSymbol() ||
+///	version (DMDV2) {
+		closureVars.dim ||	// no nested references to this frame
+///	} else {
+///		nestedFrameRef ||	// no nested references to this frame
+///	}
+		(isVirtual() && !isFinal())
+		   ))
+		{
+			goto Lno;
+		}
+
+		/* If any parameters are Tsarray's (which are passed by reference)
+		 * or out parameters (also passed by reference), don't do inlining.
+		 */
+		if (parameters)
+		{
+			for (int i = 0; i < parameters.dim; i++)
+			{
+				VarDeclaration v = cast(VarDeclaration)parameters.data[i];
+				if (v.isOut() || v.isRef() || v.type.toBasetype().ty == Tsarray)
+					goto Lno;
+			}
+		}
+
+		InlineCostState ics;
+		///memset(&ics, 0, sizeof(ics));
+		ics.hasthis = hasthis;
+		ics.fd = this;
+		ics.hdrscan = hdrscan;
+		cost = fbody.inlineCost(&ics);
+	version (CANINLINE_LOG) {
+		printf("cost = %d\n", cost);
+	}
+		if (cost >= COST_MAX)
+			goto Lno;
+
+		if (!hdrscan)    // Don't scan recursively for header content scan
+			inlineScan();
+
+	Lyes:
+		if (!hdrscan)    // Don't modify inlineStatus for header content scan
+			inlineStatus = ILS.ILSyes;
+	version (CANINLINE_LOG) {
+		printf("\t2: yes %s\n", toChars());
+	}
+		return 1;
+
+	Lno:
+		if (!hdrscan)    // Don't modify inlineStatus for header content scan
+			inlineStatus = ILS.ILSno;
+	version (CANINLINE_LOG) {
+		printf("\t2: no %s\n", toChars());
+	}
+		return 0;
+	}
+
+    Expression doInline(InlineScanState* iss, Expression ethis, Array arguments)
+	{
+		InlineDoState ids = new InlineDoState();
+		DeclarationExp de;
+		Expression e = null;
+
+	version (LOG) {
+		printf("FuncDeclaration.doInline('%s')\n", toChars());
+	}
+
+		///memset(&ids, 0, sizeof(ids));
+		ids.parent = iss.fd;
+
+		// Set up vthis
+		if (ethis)
+		{
+			VarDeclaration vthis;
+			ExpInitializer ei;
+			VarExp ve;
+
+		version (STRUCTTHISREF) {
+			if (ethis.type.ty == Tpointer)
+			{   
+				Type t = ethis.type.nextOf();
+				ethis = new PtrExp(ethis.loc, ethis);
+				ethis.type = t;
+			}
+			ei = new ExpInitializer(ethis.loc, ethis);
+
+			vthis = new VarDeclaration(ethis.loc, ethis.type, Id.This, ei);
+			if (ethis.type.ty != Tclass)
+				vthis.storage_class = STCref;
+			else
+				vthis.storage_class = STCin;
+		} else {
+			if (ethis.type.ty != Tclass && ethis.type.ty != Tpointer)
+			{
+				ethis = ethis.addressOf(null);
+			}
+
+			ei = new ExpInitializer(ethis.loc, ethis);
+
+			vthis = new VarDeclaration(ethis.loc, ethis.type, Id.This, ei);
+			vthis.storage_class = STCin;
+		}
+			vthis.linkage = LINKd;
+			vthis.parent = iss.fd;
+
+			ve = new VarExp(vthis.loc, vthis);
+			ve.type = vthis.type;
+
+			ei.exp = new AssignExp(vthis.loc, ve, ethis);
+			ei.exp.type = ve.type;
+		version (STRUCTTHISREF) {
+			if (ethis.type.ty != Tclass)
+			{   
+				/* This is a reference initialization, not a simple assignment.
+				 */
+				ei.exp.op = TOKconstruct;
+			}
+		}
+
+			ids.vthis = vthis;
+		}
+
+		// Set up parameters
+		if (ethis)
+		{
+			e = new DeclarationExp(Loc(0), ids.vthis);
+			e.type = Type.tvoid;
+		}
+
+		if (arguments && arguments.dim)
+		{
+			assert(parameters.dim == arguments.dim);
+
+			for (int i = 0; i < arguments.dim; i++)
+			{
+				VarDeclaration vfrom = cast(VarDeclaration)parameters.data[i];
+				VarDeclaration vto;
+				Expression arg = cast(Expression)arguments.data[i];
+				ExpInitializer ei;
+				VarExp ve;
+
+				ei = new ExpInitializer(arg.loc, arg);
+
+				vto = new VarDeclaration(vfrom.loc, vfrom.type, vfrom.ident, ei);
+				vto.storage_class |= vfrom.storage_class & (STCin | STCout | STClazy | STCref);
+				vto.linkage = vfrom.linkage;
+				vto.parent = iss.fd;
+				//printf("vto = '%s', vto.storage_class = x%x\n", vto.toChars(), vto.storage_class);
+				//printf("vto.parent = '%s'\n", iss.fd.toChars());
+
+				ve = new VarExp(vto.loc, vto);
+				//ve.type = vto.type;
+				ve.type = arg.type;
+
+				ei.exp = new AssignExp(vto.loc, ve, arg);
+				ei.exp.type = ve.type;
+		//ve.type.print();
+		//arg.type.print();
+		//ei.exp.print();
+
+				ids.from.push(cast(void*)vfrom);
+				ids.to.push(cast(void*)vto);
+
+				de = new DeclarationExp(Loc(0), vto);
+				de.type = Type.tvoid;
+
+				e = Expression.combine(e, de);
+			}
+		}
+
+		inlineNest++;
+		Expression eb = fbody.doInline(ids);
+		inlineNest--;
+	//eb.type.print();
+	//eb.print();
+	//eb.dump(0);
+		return Expression.combine(e, eb);
+	}
+
+    string kind()
+	{
+		return "function";
+	}
+
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+	
+    FuncDeclaration isUnique()
+	{
+		assert(false);
+	}
+	
+	/*******************************
+	 * Look at all the variables in this function that are referenced
+	 * by nested functions, and determine if a closure needs to be
+	 * created for them.
+	 */
+    bool needsClosure()
+	{
+		/* Need a closure for all the closureVars[] if any of the
+		 * closureVars[] are accessed by a
+		 * function that escapes the scope of this function.
+		 * We take the conservative approach and decide that any function that:
+		 * 1) is a virtual function
+		 * 2) has its address taken
+		 * 3) has a parent that escapes
+		 *
+		 * Note that since a non-virtual function can be called by
+		 * a virtual one, if that non-virtual function accesses a closure
+		 * var, the closure still has to be taken. Hence, we check for isThis()
+		 * instead of isVirtual(). (thanks to David Friedman)
+		 */
+
+		//printf("FuncDeclaration.needsClosure() %s\n", toChars());
+		for (int i = 0; i < closureVars.dim; i++)
+		{	
+			VarDeclaration v = cast(VarDeclaration)closureVars.data[i];
+			assert(v.isVarDeclaration());
+			//printf("\tv = %s\n", v.toChars());
+
+			for (int j = 0; j < v.nestedrefs.dim; j++)
+			{   FuncDeclaration f = cast(FuncDeclaration)v.nestedrefs.data[j];
+				assert(f != this);
+
+				//printf("\t\tf = %s, %d, %p, %d\n", f.toChars(), f.isVirtual(), f.isThis(), f.tookAddressOf);
+				if (f.isThis() || f.tookAddressOf)
+					goto Lyes;	// assume f escapes this function's scope
+
+				// Look to see if any parents of f that are below this escape
+				for (Dsymbol s = f.parent; s && s !is this; s = s.parent)
+				{
+					f = s.isFuncDeclaration();
+					if (f && (f.isThis() || f.tookAddressOf)) {
+						goto Lyes;
+					}
+				}
+			}
+		}
+		return false;
+
+	Lyes:
+		//printf("\tneeds closure\n");
+		return true;
+	}
+	
+    static FuncDeclaration genCfunc(Type treturn, string name)
+	{
+		return genCfunc(treturn, Lexer.idPool(name));
+	}
+	
+	/**********************************
+	 * Generate a FuncDeclaration for a runtime library function.
+	 */
+    static FuncDeclaration genCfunc(Type treturn, Identifier id)
+	{
+		FuncDeclaration fd;
+		TypeFunction tf;
+		Dsymbol s;
+		static DsymbolTable st = null;
+
+		//printf("genCfunc(name = '%s')\n", id.toChars());
+		//printf("treturn\n\t"); treturn.print();
+
+		// See if already in table
+		if (!st)
+			st = new DsymbolTable();
+
+		s = st.lookup(id);
+		if (s)
+		{
+			fd = s.isFuncDeclaration();
+			assert(fd);
+			assert(fd.type.nextOf().equals(treturn));
+		}
+		else
+		{
+			tf = new TypeFunction(null, treturn, 0, LINK.LINKc);
+			fd = new FuncDeclaration(Loc(0), Loc(0), id, STCstatic, tf);
+			fd.protection = PROT.PROTpublic;
+			fd.linkage = LINK.LINKc;
+
+			st.insert(fd);
+		}
+		return fd;
+	}
+	
+    Symbol* toSymbol()
+	{
+		if (!csym)
+		{
+			Symbol* s;
+			TYPE* t;
+			string id;
+
+static if (false) {
+			id = ident.toChars();
+} else {
+			id = mangle();
+}
+			//writef("FuncDeclaration.toSymbol(%s %s)\n", kind(), toChars());
+			//writef("\tid = '%s'\n", id);
+			//writef("\ttype = %s\n", type.toChars());
+			s = symbol_calloc(toStringz(id));
+			slist_add(s);
+
+			{
+				s.prettyIdent = toStringz(toPrettyChars());
+				s.Sclass = SC.SCglobal;
+				symbol_func(s);
+				func_t* f = s.Sfunc;
+				if (isVirtual())
+					f.Fflags |= F.Fvirtual;
+				else if (isMember2())
+					f.Fflags |= F.Fstatic;
+				f.Fstartline.Slinnum = loc.linnum;
+				f.Fstartline.Sfilename = cast(char*)toStringz(loc.filename);
+				if (endloc.linnum)
+				{	
+					f.Fendline.Slinnum = endloc.linnum;
+					f.Fendline.Sfilename = cast(char*)toStringz(endloc.filename);
+				}
+				else
+				{	
+					f.Fendline.Slinnum = loc.linnum;
+					f.Fendline.Sfilename = cast(char*)toStringz(loc.filename);
+				}
+				t = type.toCtype();
+			}
+
+			mangle_t msave = t.Tmangle;
+			if (isMain())
+			{
+				t.Tty = TYM.TYnfunc;
+				t.Tmangle = mTYman.mTYman_c;
+			}
+			else
+			{
+				switch (linkage)
+				{
+				case LINK.LINKwindows:
+					t.Tmangle = mTYman.mTYman_std;
+					break;
+
+				case LINK.LINKpascal:
+					t.Tty = TYM.TYnpfunc;
+					t.Tmangle = mTYman.mTYman_pas;
+					break;
+
+				case LINK.LINKc:
+					t.Tmangle = mTYman.mTYman_c;
+					break;
+
+				case LINK.LINKd:
+					t.Tmangle = mTYman.mTYman_d;
+					break;
+
+				case LINK.LINKcpp:
+				{   t.Tmangle = mTYman.mTYman_cpp;
+		version (TARGET_WINDOS) {
+					if (isThis())
+						t.Tty = TYM.TYmfunc;
+		}
+					s.Sflags |= SFL.SFLpublic;
+					Dsymbol parent = toParent();
+					ClassDeclaration cd = parent.isClassDeclaration();
+					if (cd)
+					{
+						.type* tt = cd.type.toCtype();
+						s.Sscope = tt.Tnext.Ttag;
+					}
+					break;
+				}
+				default:
+					writef("linkage = %d\n", linkage);
+					assert(0);
+				}
+			}
+			if (msave)
+				assert(msave == t.Tmangle);
+			//printf("Tty = %x, mangle = x%x\n", t.Tty, t.Tmangle);
+			t.Tcount++;
+			s.Stype = t;
+				//s.Sfielddef = this;
+
+			csym = s;
+		}
+		return csym;
+	}
+	
+    Symbol* toThunkSymbol(int offset)	// thunk version
+	{
+		Symbol *sthunk;
+
+		toSymbol();
+
+	static if (false) {
+		char *id;
+		char *n;
+		type *t;
+
+		n = sym.Sident;
+		id = cast(char*) alloca(8 + 5 + strlen(n) + 1);
+		sprintf(id, "_thunk%d__%s", offset, n);
+		s = symbol_calloc(id);
+		slist_add(s);
+		s.Stype = csym.Stype;
+		s.Stype.Tcount++;
+	}
+		sthunk = symbol_generate(SCstatic, csym.Stype);
+		sthunk.Sflags |= SFLimplem;
+		cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0);
+		return sthunk;
+	}
+	
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		Symbol* s;
+		func_t* f;
+		Symbol* senter;
+		Symbol* sexit;
+		
+		FuncDeclaration func = this;
+		ClassDeclaration cd = func.parent.isClassDeclaration();
+		int reverse;
+		int i;
+		int has_arguments;
+
+		//printf("FuncDeclaration.toObjFile(%p, %s.%s)\n", func, parent.toChars(), func.toChars());
+static if (false) {
+		//printf("line = %d\n",func.getWhere() / LINEINC);
+		EEcontext ee = env.getEEcontext();
+		if (ee.EEcompile == 2)
+		{
+			if (ee.EElinnum < (func.getWhere() / LINEINC) ||
+				ee.EElinnum > (func.endwhere / LINEINC)
+			)
+			return;		// don't compile this function
+			ee.EEfunc = func.toSymbol();
+		}
+}
+
+		if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
+		{	
+			obj_append(this);
+			return;
+		}
+
+		if (semanticRun >= 5)	// if toObjFile() already run
+			return;
+
+		semanticRun = 5;
+
+		if (!func.fbody)
+		{
+			return;
+		}
+
+		if (func.isUnitTestDeclaration() && !global.params.useUnitTests)
+			return;
+
+		if (global.params.verbose)
+			writef("function  %s\n",func.toChars());
+
+		s = func.toSymbol();
+		f = s.Sfunc;
+
+version (TARGET_OSX) {
+		s.Sclass = SC.SCcomdat;
+} else {
+		s.Sclass = SC.SCglobal;
+}
+
+		for (Dsymbol p = parent; p; p = p.parent)
+		{
+			if (p.isTemplateInstance())
+			{
+				s.Sclass = SC.SCcomdat;
+				break;
+			}
+		}
+
+		if (isNested())
+		{
+		//	if (!(config.flags3 & CFG3pic))
+		//	    s.Sclass = SCstatic;
+			f.Fflags3 |= F3.Fnested;
+		}
+		else
+		{
+			const(char)* libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname;
+
+			// Pull in RTL startup code
+			if (func.isMain())
+			{   objextdef("_main");
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+				obj_ehsections();	// initialize exception handling sections
+} else {
+				objextdef("__acrtused_con");
+}
+				obj_includelib(libname);
+				s.Sclass = SC.SCglobal;
+			}
+			else if (strcmp(s.Sident.ptr, "main".ptr) == 0 && linkage == LINK.LINKc)
+				s.Sclass = SC.SCglobal;
+
+			else if (func.isWinMain())
+			{
+				objextdef("__acrtused");
+				obj_includelib(libname);
+				s.Sclass = SC.SCglobal;
+			}
+
+			// Pull in RTL startup code
+			else if (func.isDllMain())
+			{
+				objextdef("__acrtused_dll");
+				obj_includelib(libname);
+				s.Sclass = SC.SCglobal;
+			}
+		}
+
+		cstate.CSpsymtab = &f.Flocsym;
+
+		// Find module m for this function
+		Module m = null;
+		for (Dsymbol p = parent; p; p = p.parent)
+		{
+			m = p.isModule();
+			if (m)
+				break;
+		}
+
+		IRState irs = IRState(m, func);
+		Array deferToObj = new Array();			// write these to OBJ file later
+		irs.deferToObj = deferToObj;
+
+		TypeFunction tf;
+		RET retmethod;
+		Symbol* shidden = null;
+		Symbol* sthis = null;
+		tym_t tyf;
+
+		tyf = tybasic(s.Stype.Tty);
+		//printf("linkage = %d, tyf = x%x\n", linkage, tyf);
+		reverse = tyrevfunc(s.Stype.Tty);
+
+		assert(func.type.ty == TY.Tfunction);
+		tf = cast(TypeFunction)(func.type);
+		has_arguments = (tf.linkage == LINK.LINKd) && (tf.varargs == 1);
+		retmethod = tf.retStyle();
+		if (retmethod == RET.RETstack)
+		{
+			// If function returns a struct, put a pointer to that
+			// as the first argument
+			.type* thidden = tf.next.pointerTo().toCtype();
+			char hiddenparam[5+4+1];
+			static int hiddenparami;    // how many we've generated so far
+
+			sprintf(hiddenparam.ptr, "__HID%d".ptr, ++hiddenparami);
+			shidden = symbol_name(hiddenparam.ptr, SC.SCparameter, thidden);
+			shidden.Sflags |= SFL.SFLtrue | SFL.SFLfree;
+			
+version (DMDV1) {
+			bool nestedref = func.nrvo_can && func.nrvo_var && func.nrvo_var.nestedref;
+} else {
+			bool nestedref = func.nrvo_can && func.nrvo_var && (func.nrvo_var.nestedrefs.dim != 0);
+}
+			if (nestedref) {
+				type_setcv(&shidden.Stype, shidden.Stype.Tty | mTY.mTYvolatile);
+			}
+
+			irs.shidden = shidden;
+			this.shidden = shidden;
+		}
+
+		if (vthis)
+		{
+			assert(!vthis.csym);
+			sthis = vthis.toSymbol();
+			irs.sthis = sthis;
+			if (!(f.Fflags3 & F3.Fnested))
+				f.Fflags3 |= F3.Fmember;
+		}
+
+		Symbol** params;
+		uint pi;
+
+		// Estimate number of parameters, pi
+		pi = (v_arguments !is null);
+		if (parameters)
+			pi += parameters.dim;
+
+		// Allow extra 2 for sthis and shidden
+		params = cast(Symbol**)alloca((pi + 2) * (Symbol*).sizeof);
+
+		// Get the actual number of parameters, pi, and fill in the params[]
+		pi = 0;
+		if (v_arguments)
+		{
+			params[pi] = v_arguments.toSymbol();
+			pi += 1;
+		}
+		if (parameters)
+		{
+			for (i = 0; i < parameters.dim; i++)
+			{   
+				VarDeclaration v = cast(VarDeclaration)parameters.data[i];
+debug {
+				if (v.csym)
+					writef("parameter '%s'\n", v.toChars());
+}
+				assert(!v.csym);
+				params[pi + i] = v.toSymbol();
+			}
+			pi += i;
+		}
+
+		if (reverse)
+		{	
+			// Reverse params[] entries
+			for (i = 0; i < pi/2; i++)
+			{   
+				Symbol* sptmp = params[i];
+				params[i] = params[pi - 1 - i];
+				params[pi - 1 - i] = sptmp;
+			}
+		}
+
+		if (shidden)
+		{
+static if (false) {
+			// shidden becomes last parameter
+			params[pi] = shidden;
+} else {
+			// shidden becomes first parameter
+			memmove(params + 1, params, pi * (*params).sizeof);
+			params[0] = shidden;
+}
+			pi++;
+		}
+
+
+		if (sthis)
+		{
+static if (false) {
+			// sthis becomes last parameter
+			params[pi] = sthis;
+} else {
+			// sthis becomes first parameter
+			memmove(params + 1, params, pi * (*params).sizeof);
+			params[0] = sthis;
+}
+			pi++;
+		}
+
+		if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
+			linkage != LINK.LINKd && shidden && sthis)
+		{
+			/* swap shidden and sthis
+			 */
+			Symbol* sp = params[0];
+			params[0] = params[1];
+			params[1] = sp;
+		}
+
+		for (i = 0; i < pi; i++)
+		{	
+			Symbol *sp = params[i];
+			sp.Sclass = SC.SCparameter;
+			sp.Sflags &= ~SFL.SFLspill;
+			sp.Sfl = FL.FLpara;
+			symbol_add(sp);
+		}
+
+		// First parameter goes in register
+		if (pi)
+		{
+			Symbol* sp = params[0];
+			if ((tyf == TYM.TYjfunc || tyf == TYM.TYmfunc) && type_jparam(sp.Stype))
+			{   
+				sp.Sclass = SC.SCfastpar;
+				sp.Spreg = (tyf == TYM.TYjfunc) ? REG.AX : REG.CX;
+				sp.Sfl = FL.FLauto;
+				//printf("'%s' is SCfastpar\n",sp.Sident);
+			}
+		}
+
+		if (func.fbody)
+		{  
+			block* b;
+			Blockx bx;
+			Statement sbody;
+
+			localgot = null;
+
+			sbody = func.fbody;
+			///memset(&bx, 0, (bx).sizeof);
+			bx.startblock = block_calloc();
+			bx.curblock = bx.startblock;
+			bx.funcsym = s;
+			bx.scope_index = -1;
+			bx.classdec = cd;
+			bx.member = func;
+			bx.module_ = getModule();
+			irs.blx = &bx;
+
+			buildClosure(&irs);
+
+static if (false) {
+			if (func.isSynchronized())
+			{
+				if (cd)
+				{	
+					elem *esync;
+					if (func.isStatic())
+					{   // monitor is in ClassInfo
+						esync = el_ptr(cd.toSymbol());
+					}
+					else
+					{   // 'this' is the monitor
+						esync = el_var(sthis);
+					}
+
+					if (func.isStatic() || sbody.usesEH() ||
+						!(config.flags2 & CFG2.CFG2seh))
+					{   // BUG: what if frequire or fensure uses EH?
+
+						sbody = new SynchronizedStatement(func.loc, esync, sbody);
+					}
+					else
+					{
+		version (TARGET_WINDOS) {
+						if (config.flags2 & CFG2.CFG2seh)
+						{
+							/* The "jmonitor" uses an optimized exception handling frame
+							 * which is a little shorter than the more general EH frame.
+							 * It isn't strictly necessary.
+							 */
+							s.Sfunc.Fflags3 |= Fjmonitor;
+						}
+			}
+						el_free(esync);
+					}
+				}
+				else
+				{
+					error("synchronized function %s must be a member of a class", func.toChars());
+				}
+			}
+} else version (TARGET_WINDOS) {
+			if (func.isSynchronized() && cd && config.flags2 & CFG2.CFG2seh &&
+				!func.isStatic() && !sbody.usesEH())
+			{
+				/* The "jmonitor" hack uses an optimized exception handling frame
+				 * which is a little shorter than the more general EH frame.
+				 */
+				s.Sfunc.Fflags3 |= F3.Fjmonitor;
+			}
+}
+
+			sbody.toIR(&irs);
+			bx.curblock.BC = BC.BCret;
+
+			f.Fstartblock = bx.startblock;
+		//	einit = el_combine(einit,bx.init);
+
+			if (isCtorDeclaration())
+			{
+				assert(sthis);
+				for (b = f.Fstartblock; b; b = b.Bnext)
+				{
+					if (b.BC == BC.BCret)
+					{
+						b.BC = BC.BCretexp;
+						b.Belem = el_combine(b.Belem, el_var(sthis));
+					}
+				}
+			} 
+		}
+
+		// If static constructor
+		if (isStaticConstructor())
+		{
+			elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			ector = el_combine(ector, e);
+		}
+
+		// If static destructor
+		if (isStaticDestructor())
+		{
+			elem* e;
+
+version (STATICCTOR) {
+			e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_FATEXIT]), el_ptr(s));
+			ector = el_combine(ector, e);
+			dtorcount++;
+} else {
+			StaticDtorDeclaration f2 = isStaticDtorDeclaration();
+			assert(f2);
+			if (f2.vgate)
+			{   
+				/* Increment destructor's vgate at construction time
+				 */
+				ectorgates.push(cast(void*)f2);
+			}
+
+			e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			edtor = el_combine(e, edtor);
+}
+		}
+
+		// If unit test
+		if (isUnitTestDeclaration())
+		{
+			elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s));
+			etest = el_combine(etest, e);
+		}
+
+		if (global.errors)
+			return;
+
+		writefunc(s);
+		
+		if (isExport()) {
+			obj_export(s, Poffset);
+		}
+
+		for (i = 0; i < irs.deferToObj.dim; i++)
+		{
+			Dsymbol ss = cast(Dsymbol)irs.deferToObj.data[i];
+			ss.toObjFile(0);
+		}
+
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+		// A hack to get a pointer to this function put in the .dtors segment
+		if (ident && ident.toChars() == "_STD") {
+			obj_staticdtor(s);
+		}
+}
+version (DMDV2) {
+		if (irs.startaddress) 
+		{
+			writef("Setting start address\n");
+			obj_startaddress(irs.startaddress);
+		}
+}
+	}
+	
+    int cvMember(ubyte* p)
+	{
+		assert(false);
+	}
+	
+	/*************************************
+	 * 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.
+	 */
+    void buildClosure(IRState* irs)
+	{
+		if (needsClosure())
+		{   
+			// Generate closure on the heap
+			// BUG: doesn't capture variadic arguments passed to this function
+
+		version (DMDV2) {
+			/* BUG: doesn't handle destructors for the local variables.
+			 * The way to do it is to make the closure variables the fields
+			 * of a class object:
+			 *    class Closure
+			 *    {   vtbl[]
+			 *	  monitor
+			 *	  ptr to destructor
+			 *	  sthis
+			 *	  ... closure variables ...
+			 *	  ~this() { call destructor }
+			 *    }
+			 */
+		}
+			//printf("FuncDeclaration.buildClosure()\n");
+			Symbol* sclosure;
+			sclosure = symbol_name("__closptr".ptr, SC.SCauto, Type.tvoidptr.toCtype());
+			sclosure.Sflags |= SFL.SFLtrue | SFL.SFLfree;
+			symbol_add(sclosure);
+			irs.sclosure = sclosure;
+
+			uint offset = PTRSIZE;	// leave room for previous sthis
+			for (int i = 0; i < closureVars.dim; i++)
+			{   
+				VarDeclaration v = cast(VarDeclaration)closureVars.data[i];
+				assert(v.isVarDeclaration());
+
+		version (DMDV2) {
+				if (v.needsAutoDtor())
+					v.error("has scoped destruction, cannot build closure");
+		}
+				/* Align and allocate space for v in the closure
+				 * just like AggregateDeclaration.addField() does.
+				 */
+				uint memsize;
+				uint memalignsize;
+				uint xalign;
+///		version (DMDV2) {
+				if (v.storage_class & STC.STClazy)
+				{
+					/* Lazy variables are really delegates,
+					 * so give same answers that TypeDelegate would
+					 */
+					memsize = PTRSIZE * 2;
+					memalignsize = memsize;
+					xalign = global.structalign;
+				}
+				else
+///		}
+				{
+					memsize = cast(uint)v.type.size();
+					memalignsize = v.type.alignsize();
+					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(TYM.TYint, offset);
+			e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[RTLSYM.RTLSYM_ALLOCMEMORY]), e);
+
+			// Assign block of memory to sclosure
+			//    sclosure = allocmemory(sz);
+			e = el_bin(OPER.OPeq, TYM.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(TYM.TYnptr, 0);
+			elem *ex = el_una(OPER.OPind, TYM.TYnptr, el_var(sclosure));
+			ex = el_bin(OPER.OPeq, TYM.TYnptr, ex, ethis);
+			e = el_combine(e, ex);
+
+			// Copy function parameters into closure
+			for (int i = 0; i < closureVars.dim; i++)
+			{   VarDeclaration v = cast(VarDeclaration)closureVars.data[i];
+
+				if (!v.isParameter())
+					continue;
+				TYM tym = v.type.totym();
+				if (v.type.toBasetype().ty == TY.Tsarray || v.isOut() || v.isRef())
+					tym = TYM.TYnptr;	// reference parameters are just pointers
+///		version (DMDV2) {
+				else if (v.storage_class & STC.STClazy)
+					tym = TYM.TYdelegate;
+///		}
+				ex = el_bin(OPER.OPadd, TYM.TYnptr, el_var(sclosure), el_long(TYM.TYint, v.offset));
+				ex = el_una(OPER.OPind, tym, ex);
+				if (ex.Ety == TYM.TYstruct)
+				{   
+					ex.Enumbytes = cast(uint)v.type.size();
+					ex = el_bin(OPER.OPstreq, tym, ex, el_var(v.toSymbol()));
+					ex.Enumbytes = cast(uint)v.type.size();
+				}
+				else
+				{
+					ex = el_bin(OPER.OPeq, tym, ex, el_var(v.toSymbol()));
+				}
+
+				e = el_combine(e, ex);
+			}
+
+			block_appendexp(irs.blx.curblock, e);
+		}
+	}
+
+    FuncDeclaration isFuncDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FuncExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,126 @@
+module dmd.FuncExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.FuncLiteralDeclaration;
+import dmd.TOK;
+import dmd.TypeFunction;
+import dmd.TypeDelegate;
+import dmd.TY;
+import dmd.Type;
+import dmd.Global;
+
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.TYM;
+import dmd.backend.Symbol;
+
+class FuncExp : Expression
+{
+	FuncLiteralDeclaration fd;
+
+	this(Loc loc, FuncLiteralDeclaration fd)
+	{
+		super(loc, TOK.TOKfunction, FuncExp.sizeof);
+		this.fd = fd;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("FuncExp.semantic(%s)\n", toChars());
+}
+		if (!type)
+		{
+			fd.semantic(sc);
+
+			//fd.parent = sc.parent;
+			if (global.errors)
+			{
+			}
+			else
+			{
+				fd.semantic2(sc);
+				if (!global.errors ||
+					// need to infer return type
+					(fd.type && fd.type.ty == TY.Tfunction && !fd.type.nextOf()))
+				{
+					fd.semantic3(sc);
+
+					if (!global.errors && global.params.useInline)
+						fd.inlineScan();
+				}
+			}
+
+			// need to infer return type
+			if (global.errors && fd.type && fd.type.ty == TY.Tfunction && !fd.type.nextOf())
+				(cast(TypeFunction)fd.type).next = Type.terror;
+
+			// Type is a "delegate to" or "pointer to" the function literal
+			if (fd.isNested())
+			{
+				type = new TypeDelegate(fd.type);
+				type = type.semantic(loc, sc);
+			}
+			else
+			{
+				type = fd.type.pointerTo();
+			}
+
+			fd.tookAddressOf++;
+		}
+
+		return this;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	elem* 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(TYM.TYullong, ethis, e);
+		}
+
+		irs.deferToObj.push(cast(void*)fd);
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/FuncLiteralDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,65 @@
+module dmd.FuncLiteralDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.Type;
+import dmd.ForeachStatement;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Dsymbol;
+import dmd.STC;
+import dmd.Lexer;
+
+class FuncLiteralDeclaration : FuncDeclaration
+{
+    TOK tok;			// TOKfunction or TOKdelegate
+
+    this(Loc loc, Loc endloc, Type type, TOK tok, ForeachStatement fes)
+	{
+		super(loc, endloc, null, STC.STCundefined, type);
+		
+		string id;
+
+		if (fes)
+			id = "__foreachbody";
+		else if (tok == TOK.TOKdelegate)
+			id = "__dgliteral";
+		else
+			id = "__funcliteral";
+
+		this.ident = Lexer.uniqueId(id);
+		this.tok = tok;
+		this.fes = fes;
+
+		//printf("FuncLiteralDeclaration() id = '%s', type = '%s'\n", this->ident->toChars(), type->toChars());
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    bool isNested()
+	{
+		//printf("FuncLiteralDeclaration::isNested() '%s'\n", toChars());
+		return (tok == TOK.TOKdelegate);
+	}
+	
+    bool isVirtual()
+	{
+		return false;
+	}
+
+    FuncLiteralDeclaration isFuncLiteralDeclaration() { return this; }
+
+    string kind()
+	{
+		return (tok == TOKdelegate) ? "delegate" : "function";
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Global.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,52 @@
+module dmd.Global;
+
+import dmd.Array;
+import dmd.Param;
+
+class Global
+{
+    string mars_ext = "d";
+    string sym_ext	= "d";
+	
+version (TARGET_WINDOS) {
+    string obj_ext = "obj";
+} else version (XXX) {	// TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+    string obj_ext = "o";
+} else version (TARGET_NET) {
+} else {
+	static assert (false);
+}
+
+version (TARGET_WINDOS) {
+    string lib_ext = "lib";
+} else version (XXX) {	// TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+	string lib_ext = "a";
+} else version (TARGET_NET) {
+} else {
+	static assert (false);
+}
+    string doc_ext	= "html";;	// for Ddoc generated files
+    string ddoc_ext	= "ddoc";;	// for Ddoc macro include files
+    string hdr_ext	= "di";	// for D 'header' import files
+    string copyright= "Copyright (c) 1999-2009 by Digital Mars";
+    string written	= "written by Walter Bright";
+///version (TARGET_NET) {
+///    "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
+///}
+	
+    string[] path;	// Array of char*'s which form the import lookup path
+    string[] filePath;	// Array of char*'s which form the file import lookup path
+    int structalign = 8;
+    string version_ = "v2.032";
+
+    Param params;
+    uint errors;	// number of errors reported so far
+    uint gag;	// !=0 means gag reporting of errors
+	
+	this()
+	{
+		params.versionids = new Array();
+	}
+}
+
+Global global;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/GlobalExpressions.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,31 @@
+module dmd.GlobalExpressions;
+
+import dmd.Expression;
+import dmd.TOK;
+import dmd.Loc;
+
+Expression EXP_CANT_INTERPRET;
+Expression EXP_CONTINUE_INTERPRET;
+Expression EXP_BREAK_INTERPRET;
+Expression EXP_GOTO_INTERPRET;
+Expression EXP_VOID_INTERPRET;
+
+void* castToVoid(int i)
+{
+	return cast(void*)i;
+}
+
+static this()
+{
+	//EXP_CANT_INTERPRET = new Expression(Loc(0), TOK.init, 0);
+	//EXP_CONTINUE_INTERPRET = new Expression(Loc(0), TOK.init, 0);
+	//EXP_BREAK_INTERPRET = new Expression(Loc(0), TOK.init, 0);
+	//EXP_GOTO_INTERPRET = new Expression(Loc(0), TOK.init, 0);
+	//EXP_VOID_INTERPRET = new Expression(Loc(0), TOK.init, 0);
+	
+	EXP_CANT_INTERPRET = cast(Expression)castToVoid(1);
+	EXP_CONTINUE_INTERPRET = cast(Expression)castToVoid(2);
+	EXP_BREAK_INTERPRET = cast(Expression)castToVoid(3);
+	EXP_GOTO_INTERPRET = cast(Expression)castToVoid(4);
+	EXP_VOID_INTERPRET = cast(Expression)castToVoid(5);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/GotoCaseStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,54 @@
+module dmd.GotoCaseStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.CaseStatement;
+import dmd.IRState;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.BE;
+
+class GotoCaseStatement : Statement
+{
+    Expression exp;		// NULL, or which case to goto
+    CaseStatement cs;		// case statement it resolves to
+
+    this(Loc loc, Expression exp)
+	{
+		assert(false);
+		super(loc);
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/GotoDefaultStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,53 @@
+module dmd.GotoDefaultStatement;
+
+import dmd.Statement;
+import dmd.SwitchStatement;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.IRState;
+import dmd.BE;
+
+class GotoDefaultStatement : Statement
+{
+    SwitchStatement sw;
+
+    this(Loc loc)
+	{
+		assert(false);
+		super(loc);
+	}
+
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    BE blockExit()
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    void toIR(IRState *irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/GotoStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,133 @@
+module dmd.GotoStatement;
+
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Statement;
+import dmd.Identifier;
+import dmd.CompoundStatement;
+import dmd.LabelDsymbol;
+import dmd.TryFinallyStatement;
+import dmd.FuncDeclaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BE;
+
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.BC;
+
+class GotoStatement : Statement
+{
+    Identifier ident;
+    LabelDsymbol label = null;
+    TryFinallyStatement tf = null;
+
+    this(Loc loc, Identifier ident)
+	{
+		super(loc);
+		this.ident = ident;
+	}
+	
+    Statement syntaxCopy()
+	{
+		GotoStatement s = new GotoStatement(loc, ident);
+		return s;
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		FuncDeclaration fd = sc.parent.isFuncDeclaration();
+
+		//printf("GotoStatement.semantic()\n");
+		tf = sc.tf;
+		label = fd.searchLabel(ident);
+		if (!label.statement && sc.fes)
+		{
+			/* Either the goto label is forward referenced or it
+			 * is in the function that the enclosing foreach is in.
+			 * Can't know yet, so wrap the goto in a compound statement
+			 * so we can patch it later, and add it to a 'look at this later'
+			 * list.
+			 */
+			Statements a = new Statements();
+			Statement s;
+
+			a.push(cast(void*)this);
+			s = new CompoundStatement(loc, a);
+			sc.fes.gotos.push(cast(void*)s);		// 'look at this later' list
+			return s;
+		}
+
+		if (label.statement && label.statement.tf != sc.tf)
+			error("cannot goto in or out of finally block");
+		return this;
+	}
+
+    BE blockExit()
+	{
+		//printf("GotoStatement.blockExit(%p)\n", this);
+		return BE.BEgoto;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    void toIR(IRState* irs)
+	{
+		block* b;
+		block* bdest;
+		Blockx* blx = irs.blx;
+
+		if (!label.statement)
+		{	
+			error("label %s is undefined", label.toChars());
+			return;
+		}
+		if (tf !is label.statement.tf)
+			error("cannot goto forward out of or into finally block");
+
+		bdest = labelToBlock(loc, blx, label);
+		if (!bdest)
+			return;
+		b = blx.curblock;
+		incUsage(irs, loc);
+
+		// Adjust exception handler scope index if in different try blocks
+		if (b.Btry != bdest.Btry)
+		{
+			// Check that bdest is in an enclosing try block
+			for (block* bt = b.Btry; bt != bdest.Btry; bt = bt.Btry)
+			{
+				if (!bt)
+				{
+					//printf("b.Btry = %p, bdest.Btry = %p\n", b.Btry, bdest.Btry);
+					error("cannot goto into try block");
+					break;
+				}
+			}
+
+			//setScopeIndex(blx, b, bdest.Btry ? bdest.Btry.Bscope_index : -1);
+		}
+
+		list_append(&b.Bsucc,bdest);
+		block_next(blx,BCgoto,null);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("goto ");
+		buf.writestring(ident.toChars());
+		buf.writebyte(';');
+		buf.writenl();
+	}
+	
+    GotoStatement isGotoStatement() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/HaltExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,55 @@
+module dmd.HaltExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.Type;
+import dmd.HdrGenState;
+import dmd.Loc;
+import dmd.TOK;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+
+class HaltExp : Expression
+{
+	this(Loc loc)
+	{
+		super(loc, TOK.TOKhalt, HaltExp.sizeof);
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("HaltExp.semantic()\n");
+}
+		type = Type.tvoid;
+		return this;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("halt");
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		return true;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e;
+
+		e = el_calloc();
+		e.Ety = TYvoid;
+		e.Eoper = OPhalt;
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/HdrGenState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,24 @@
+module dmd.HdrGenState;
+
+struct HdrGenState
+{
+    int hdrgen;		// 1 if generating header file
+    int ddoc;		// 1 if generating Ddoc file
+    int console;	// 1 if writing to console
+    int tpltMember;
+    int inCallExp;
+    int inPtrExp;
+    int inSlcExp;
+    int inDotExp;
+    int inBinExp;
+    int inArrExp;
+    int emitInst;
+    
+	struct FLinit_
+    {
+        int init;
+        int decl;
+    }
+	
+	FLinit_ FLinit;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ILS.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,8 @@
+module dmd.ILS;
+
+enum ILS
+{
+    ILSuninitialized,	// not computed yet
+    ILSno,		// cannot inline
+    ILSyes,		// can inline
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IRState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,171 @@
+module dmd.IRState;
+
+import dmd.Statement;
+import dmd.Module;
+import dmd.Dsymbol;
+import dmd.Identifier;
+import dmd.Array;
+import dmd.FuncDeclaration;
+import dmd.Global;
+import dmd.Loc;
+
+import dmd.backend.Symbol;
+import dmd.backend.Blockx;
+import dmd.backend.block;
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+
+struct IRState
+{
+    IRState* prev;
+    Statement statement;
+    Module m;			// module
+    Dsymbol symbol;
+    Identifier ident;
+    Symbol* shidden;		// hidden parameter to function
+    Symbol* sthis;		// 'this' parameter to function (member and nested)
+    Symbol* sclosure;		// pointer to closure instance
+    Blockx* blx;
+    Array deferToObj;		// array of Dsymbol's to run toObjFile(int multiobj) on later
+    elem* ehidden;		// transmit hidden pointer to CallExp::toElem()
+    Symbol* startaddress;
+
+    block* breakBlock;
+    block* contBlock;
+    block* switchBlock;
+    block* defaultBlock;
+
+    this(IRState* irs, Statement s)
+	{
+	    prev = irs;
+		statement = s;
+		if (irs)
+		{
+			m = irs.m;
+			shidden = irs.shidden;
+			sclosure = irs.sclosure;
+			sthis = irs.sthis;
+			blx = irs.blx;
+			deferToObj = irs.deferToObj;
+		}
+	}
+	
+    this(IRState* irs, Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    this(Module m, Dsymbol s)
+	{
+		this.m = m;
+		symbol = s;
+	}
+
+    block* getBreakBlock(Identifier ident)
+	{
+		for (IRState* bc = &this; bc; bc = bc.prev)
+		{
+			if (ident)
+			{
+				if (bc.prev && bc.prev.ident == ident)
+					return bc.breakBlock;
+			}
+			else if (bc.breakBlock)
+				return bc.breakBlock;
+		}
+		return null;
+	}
+	
+    block* getContBlock(Identifier ident)
+	{
+		IRState* bc;
+
+		for (bc = &this; bc; bc = bc.prev)
+		{
+			if (ident)
+			{
+				if (bc.prev && bc.prev.ident == ident)
+					return bc.contBlock;
+			}
+			else if (bc.contBlock)
+				return bc.contBlock;
+		}
+		return null;
+	}
+	
+    block* getSwitchBlock()
+	{
+		for (IRState* bc = &this; bc; bc = bc.prev)
+		{
+			if (bc.switchBlock)
+				return bc.switchBlock;
+		}
+		return null;
+	}
+	
+    block* getDefaultBlock()
+	{
+		for (IRState* bc = &this; bc; bc = bc.prev)
+		{
+			if (bc.defaultBlock)
+				return bc.defaultBlock;
+		}
+		return null;
+	}
+	
+    FuncDeclaration getFunc()
+	{
+		IRState* bc;
+		for (bc = &this; bc.prev; bc = bc.prev)
+		{
+		}
+		return cast(FuncDeclaration)(bc.symbol);
+	}
+}
+
+/*********************************************
+ * Produce elem which increments the usage count for a particular line.
+ * Used to implement -cov switch (coverage analysis).
+ */
+
+elem *incUsageElem(IRState *irs, Loc loc)
+{
+    uint linnum = loc.linnum;
+
+    if (!irs.blx.module_.cov || !linnum || loc.filename != irs.blx.module_.srcfile.toChars())
+		return null;
+
+    //printf("cov = %p, covb = %p, linnum = %u\n", irs->blx->module->cov, irs->blx->module->covb, p, linnum);
+
+    linnum--;		// from 1-based to 0-based
+
+    /* Set bit in covb[] indicating this is a valid code line number
+     */
+    uint* p = irs.blx.module_.covb;
+    if (p)	// covb can be NULL if it has already been written out to its .obj file
+    {
+		p += linnum / ((*p).sizeof * 8);
+		*p |= 1 << (linnum & ((*p).sizeof * 8 - 1));
+    }
+
+    elem* e;
+    e = el_ptr(irs.blx.module_.cov);
+    e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYuint, linnum * 4));
+    e = el_una(OPER.OPind, TYM.TYuint, e);
+    e = el_bin(OPER.OPaddass, TYM.TYuint, e, el_long(TYM.TYuint, 1));
+
+    return e;
+}
+
+/**************************************
+ * Add in code to increment usage count for linnum.
+ */
+void incUsage(IRState* irs, Loc loc)
+{
+    if (global.params.cov && loc.linnum)
+    {
+		block_appendexp(irs.blx.curblock, incUsageElem(irs, loc));
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Id.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,456 @@
+module dmd.Id;
+
+import dmd.Identifier;
+import dmd.Lexer;
+
+struct Id
+{
+    static Identifier IUnknown;
+    static Identifier Object_;
+    static Identifier object;
+    static Identifier max;
+    static Identifier min;
+    static Identifier This;
+    static Identifier ctor;
+    static Identifier dtor;
+    static Identifier cpctor;
+    static Identifier _postblit;
+    static Identifier classInvariant;
+    static Identifier unitTest;
+    static Identifier init_;
+    static Identifier size;
+    static Identifier __sizeof;
+    static Identifier alignof_;
+    static Identifier mangleof_;
+    static Identifier stringof_;
+    static Identifier tupleof_;
+    static Identifier length;
+    static Identifier remove;
+    static Identifier ptr;
+    static Identifier funcptr;
+    static Identifier dollar;
+    static Identifier offset;
+    static Identifier offsetof;
+    static Identifier ModuleInfo;
+    static Identifier ClassInfo;
+    static Identifier classinfo_;
+    static Identifier typeinfo_;
+    static Identifier outer;
+    static Identifier Exception;
+    static Identifier Throwable;
+    static Identifier withSym;
+    static Identifier result;
+    static Identifier returnLabel;
+    static Identifier delegate_;
+    static Identifier line;
+    static Identifier empty;
+    static Identifier p;
+    static Identifier coverage;
+    static Identifier __vptr;
+    static Identifier __monitor;
+    static Identifier system;
+    static Identifier TypeInfo;
+    static Identifier TypeInfo_Class;
+    static Identifier TypeInfo_Interface;
+    static Identifier TypeInfo_Struct;
+    static Identifier TypeInfo_Enum;
+    static Identifier TypeInfo_Typedef;
+    static Identifier TypeInfo_Pointer;
+    static Identifier TypeInfo_Array;
+    static Identifier TypeInfo_StaticArray;
+    static Identifier TypeInfo_AssociativeArray;
+    static Identifier TypeInfo_Function;
+    static Identifier TypeInfo_Delegate;
+    static Identifier TypeInfo_Tuple;
+    static Identifier TypeInfo_Const;
+    static Identifier TypeInfo_Invariant;
+    static Identifier TypeInfo_Shared;
+    static Identifier elements;
+    static Identifier _arguments_typeinfo;
+    static Identifier _arguments;
+    static Identifier _argptr;
+    static Identifier _match;
+    static Identifier destroy;
+    static Identifier postblit;
+    static Identifier LINE;
+    static Identifier FILE;
+    static Identifier DATE;
+    static Identifier TIME;
+    static Identifier TIMESTAMP;
+    static Identifier VENDOR;
+    static Identifier VERSIONX;
+    static Identifier EOFX;
+    static Identifier nan;
+    static Identifier infinity;
+    static Identifier dig;
+    static Identifier epsilon;
+    static Identifier mant_dig;
+    static Identifier max_10_exp;
+    static Identifier max_exp;
+    static Identifier min_10_exp;
+    static Identifier min_exp;
+    static Identifier re;
+    static Identifier im;
+    static Identifier C;
+    static Identifier D;
+    static Identifier Windows;
+    static Identifier Pascal;
+    static Identifier System;
+    static Identifier exit;
+    static Identifier success;
+    static Identifier failure;
+    static Identifier keys;
+    static Identifier values;
+    static Identifier rehash;
+    static Identifier sort;
+    static Identifier reverse;
+    static Identifier dup;
+    static Identifier idup;
+    static Identifier property;
+    static Identifier ___out;
+    static Identifier ___in;
+    static Identifier __int;
+    static Identifier __dollar;
+    static Identifier __LOCAL_SIZE;
+    static Identifier uadd;
+    static Identifier neg;
+    static Identifier com;
+    static Identifier add;
+    static Identifier add_r;
+    static Identifier sub;
+    static Identifier sub_r;
+    static Identifier mul;
+    static Identifier mul_r;
+    static Identifier div;
+    static Identifier div_r;
+    static Identifier mod;
+    static Identifier mod_r;
+    static Identifier eq;
+    static Identifier cmp;
+    static Identifier iand;
+    static Identifier iand_r;
+    static Identifier ior;
+    static Identifier ior_r;
+    static Identifier ixor;
+    static Identifier ixor_r;
+    static Identifier shl;
+    static Identifier shl_r;
+    static Identifier shr;
+    static Identifier shr_r;
+    static Identifier ushr;
+    static Identifier ushr_r;
+    static Identifier cat;
+    static Identifier cat_r;
+    static Identifier assign;
+    static Identifier addass;
+    static Identifier subass;
+    static Identifier mulass;
+    static Identifier divass;
+    static Identifier modass;
+    static Identifier andass;
+    static Identifier orass;
+    static Identifier xorass;
+    static Identifier shlass;
+    static Identifier shrass;
+    static Identifier ushrass;
+    static Identifier catass;
+    static Identifier postinc;
+    static Identifier postdec;
+    static Identifier index;
+    static Identifier indexass;
+    static Identifier slice;
+    static Identifier sliceass;
+    static Identifier call;
+    static Identifier cast_;
+    static Identifier match;
+    static Identifier next;
+    static Identifier opIn;
+    static Identifier opIn_r;
+    static Identifier opStar;
+    static Identifier opDot;
+    static Identifier opImplicitCast;
+    static Identifier classNew;
+    static Identifier classDelete;
+    static Identifier apply;
+    static Identifier applyReverse;
+    static Identifier Fempty;
+    static Identifier Fhead;
+    static Identifier Ftoe;
+    static Identifier Fnext;
+    static Identifier Fretreat;
+    static Identifier adDup;
+    static Identifier adReverse;
+    static Identifier aaLen;
+    static Identifier aaKeys;
+    static Identifier aaValues;
+    static Identifier aaRehash;
+    static Identifier monitorenter;
+    static Identifier monitorexit;
+    static Identifier criticalenter;
+    static Identifier criticalexit;
+    static Identifier GNU_asm;
+    static Identifier lib;
+    static Identifier msg;
+    static Identifier startaddress;
+    static Identifier tohash;
+    static Identifier tostring;
+    static Identifier getmembers;
+    static Identifier alloca;
+    static Identifier main;
+    static Identifier WinMain;
+    static Identifier DllMain;
+    static Identifier tls_get_addr;
+    static Identifier std;
+    static Identifier math;
+    static Identifier sin;
+    static Identifier cos;
+    static Identifier tan;
+    static Identifier _sqrt;
+    static Identifier fabs;
+    static Identifier isAbstractClass;
+    static Identifier isArithmetic;
+    static Identifier isAssociativeArray;
+    static Identifier isFinalClass;
+    static Identifier isFloating;
+    static Identifier isIntegral;
+    static Identifier isScalar;
+    static Identifier isStaticArray;
+    static Identifier isUnsigned;
+    static Identifier isVirtualFunction;
+    static Identifier isAbstractFunction;
+    static Identifier isFinalFunction;
+    static Identifier hasMember;
+    static Identifier getMember;
+    static Identifier getVirtualFunctions;
+    static Identifier classInstanceSize;
+    static Identifier allMembers;
+    static Identifier derivedMembers;
+    static Identifier isSame;
+    static Identifier compiles;
+
+    static void initialize()
+	{
+		IUnknown = Lexer.idPool("IUnknown");
+		Object_ = Lexer.idPool("Object");
+		object = Lexer.idPool("object");
+		max = Lexer.idPool("max");
+		min = Lexer.idPool("min");
+		This = Lexer.idPool("this");
+		ctor = Lexer.idPool("__ctor");
+		dtor = Lexer.idPool("__dtor");
+		cpctor = Lexer.idPool("__cpctor");
+		_postblit = Lexer.idPool("__postblit");
+		classInvariant = Lexer.idPool("__invariant");
+		unitTest = Lexer.idPool("__unitTest");
+		init_ = Lexer.idPool("init");
+		size = Lexer.idPool("size");
+		__sizeof = Lexer.idPool("sizeof");
+		alignof_ = Lexer.idPool("alignof");
+		mangleof_ = Lexer.idPool("mangleof");
+		stringof_ = Lexer.idPool("stringof");
+		tupleof_ = Lexer.idPool("tupleof");
+		length = Lexer.idPool("length");
+		remove = Lexer.idPool("remove");
+		ptr = Lexer.idPool("ptr");
+		funcptr = Lexer.idPool("funcptr");
+		dollar = Lexer.idPool("__dollar");
+		offset = Lexer.idPool("offset");
+		offsetof = Lexer.idPool("offsetof");
+		ModuleInfo = Lexer.idPool("ModuleInfo");
+		ClassInfo = Lexer.idPool("ClassInfo");
+		classinfo_ = Lexer.idPool("classinfo");
+		typeinfo_ = Lexer.idPool("typeinfo");
+		outer = Lexer.idPool("outer");
+		Exception = Lexer.idPool("Exception");
+		Throwable = Lexer.idPool("Throwable");
+		withSym = Lexer.idPool("__withSym");
+		result = Lexer.idPool("__result");
+		returnLabel = Lexer.idPool("__returnLabel");
+		delegate_ = Lexer.idPool("delegate");
+		line = Lexer.idPool("line");
+		empty = Lexer.idPool("");
+		p = Lexer.idPool("p");
+		coverage = Lexer.idPool("__coverage");
+		__vptr = Lexer.idPool("__vptr");
+		__monitor = Lexer.idPool("__monitor");
+		system = Lexer.idPool("system");
+		TypeInfo = Lexer.idPool("TypeInfo");
+		TypeInfo_Class = Lexer.idPool("TypeInfo_Class");
+		TypeInfo_Interface = Lexer.idPool("TypeInfo_Interface");
+		TypeInfo_Struct = Lexer.idPool("TypeInfo_Struct");
+		TypeInfo_Enum = Lexer.idPool("TypeInfo_Enum");
+		TypeInfo_Typedef = Lexer.idPool("TypeInfo_Typedef");
+		TypeInfo_Pointer = Lexer.idPool("TypeInfo_Pointer");
+		TypeInfo_Array = Lexer.idPool("TypeInfo_Array");
+		TypeInfo_StaticArray = Lexer.idPool("TypeInfo_StaticArray");
+		TypeInfo_AssociativeArray = Lexer.idPool("TypeInfo_AssociativeArray");
+		TypeInfo_Function = Lexer.idPool("TypeInfo_Function");
+		TypeInfo_Delegate = Lexer.idPool("TypeInfo_Delegate");
+		TypeInfo_Tuple = Lexer.idPool("TypeInfo_Tuple");
+		TypeInfo_Const = Lexer.idPool("TypeInfo_Const");
+		TypeInfo_Invariant = Lexer.idPool("TypeInfo_Invariant");
+		TypeInfo_Shared = Lexer.idPool("TypeInfo_Shared");
+		elements = Lexer.idPool("elements");
+		_arguments_typeinfo = Lexer.idPool("_arguments_typeinfo");
+		_arguments = Lexer.idPool("_arguments");
+		_argptr = Lexer.idPool("_argptr");
+		_match = Lexer.idPool("_match");
+		destroy = Lexer.idPool("destroy");
+		postblit = Lexer.idPool("postblit");
+		LINE = Lexer.idPool("__LINE__");
+		FILE = Lexer.idPool("__FILE__");
+		DATE = Lexer.idPool("__DATE__");
+		TIME = Lexer.idPool("__TIME__");
+		TIMESTAMP = Lexer.idPool("__TIMESTAMP__");
+		VENDOR = Lexer.idPool("__VENDOR__");
+		VERSIONX = Lexer.idPool("__VERSION__");
+		EOFX = Lexer.idPool("__EOF__");
+		nan = Lexer.idPool("nan");
+		infinity = Lexer.idPool("infinity");
+		dig = Lexer.idPool("dig");
+		epsilon = Lexer.idPool("epsilon");
+		mant_dig = Lexer.idPool("mant_dig");
+		max_10_exp = Lexer.idPool("max_10_exp");
+		max_exp = Lexer.idPool("max_exp");
+		min_10_exp = Lexer.idPool("min_10_exp");
+		min_exp = Lexer.idPool("min_exp");
+		re = Lexer.idPool("re");
+		im = Lexer.idPool("im");
+		C = Lexer.idPool("C");
+		D = Lexer.idPool("D");
+		Windows = Lexer.idPool("Windows");
+		Pascal = Lexer.idPool("Pascal");
+		System = Lexer.idPool("System");
+		exit = Lexer.idPool("exit");
+		success = Lexer.idPool("success");
+		failure = Lexer.idPool("failure");
+		keys = Lexer.idPool("keys");
+		values = Lexer.idPool("values");
+		rehash = Lexer.idPool("rehash");
+		sort = Lexer.idPool("sort");
+		reverse = Lexer.idPool("reverse");
+		dup = Lexer.idPool("dup");
+		idup = Lexer.idPool("idup");
+		property = Lexer.idPool("property");
+		___out = Lexer.idPool("out");
+		___in = Lexer.idPool("in");
+		__int = Lexer.idPool("int");
+		__dollar = Lexer.idPool("$");
+		__LOCAL_SIZE = Lexer.idPool("__LOCAL_SIZE");
+		uadd = Lexer.idPool("opPos");
+		neg = Lexer.idPool("opNeg");
+		com = Lexer.idPool("opCom");
+		add = Lexer.idPool("opAdd");
+		add_r = Lexer.idPool("opAdd_r");
+		sub = Lexer.idPool("opSub");
+		sub_r = Lexer.idPool("opSub_r");
+		mul = Lexer.idPool("opMul");
+		mul_r = Lexer.idPool("opMul_r");
+		div = Lexer.idPool("opDiv");
+		div_r = Lexer.idPool("opDiv_r");
+		mod = Lexer.idPool("opMod");
+		mod_r = Lexer.idPool("opMod_r");
+		eq = Lexer.idPool("opEquals");
+		cmp = Lexer.idPool("opCmp");
+		iand = Lexer.idPool("opAnd");
+		iand_r = Lexer.idPool("opAnd_r");
+		ior = Lexer.idPool("opOr");
+		ior_r = Lexer.idPool("opOr_r");
+		ixor = Lexer.idPool("opXor");
+		ixor_r = Lexer.idPool("opXor_r");
+		shl = Lexer.idPool("opShl");
+		shl_r = Lexer.idPool("opShl_r");
+		shr = Lexer.idPool("opShr");
+		shr_r = Lexer.idPool("opShr_r");
+		ushr = Lexer.idPool("opUShr");
+		ushr_r = Lexer.idPool("opUShr_r");
+		cat = Lexer.idPool("opCat");
+		cat_r = Lexer.idPool("opCat_r");
+		assign = Lexer.idPool("opAssign");
+		addass = Lexer.idPool("opAddAssign");
+		subass = Lexer.idPool("opSubAssign");
+		mulass = Lexer.idPool("opMulAssign");
+		divass = Lexer.idPool("opDivAssign");
+		modass = Lexer.idPool("opModAssign");
+		andass = Lexer.idPool("opAndAssign");
+		orass = Lexer.idPool("opOrAssign");
+		xorass = Lexer.idPool("opXorAssign");
+		shlass = Lexer.idPool("opShlAssign");
+		shrass = Lexer.idPool("opShrAssign");
+		ushrass = Lexer.idPool("opUShrAssign");
+		catass = Lexer.idPool("opCatAssign");
+		postinc = Lexer.idPool("opPostInc");
+		postdec = Lexer.idPool("opPostDec");
+		index = Lexer.idPool("opIndex");
+		indexass = Lexer.idPool("opIndexAssign");
+		slice = Lexer.idPool("opSlice");
+		sliceass = Lexer.idPool("opSliceAssign");
+		call = Lexer.idPool("opCall");
+		cast_ = Lexer.idPool("opCast");
+		match = Lexer.idPool("opMatch");
+		next = Lexer.idPool("opNext");
+		opIn = Lexer.idPool("opIn");
+		opIn_r = Lexer.idPool("opIn_r");
+		opStar = Lexer.idPool("opStar");
+		opDot = Lexer.idPool("opDot");
+		opImplicitCast = Lexer.idPool("opImplicitCast");
+		classNew = Lexer.idPool("new");
+		classDelete = Lexer.idPool("delete");
+		apply = Lexer.idPool("opApply");
+		applyReverse = Lexer.idPool("opApplyReverse");
+		Fempty = Lexer.idPool("empty");
+		Fhead = Lexer.idPool("front");
+		Ftoe = Lexer.idPool("back");
+		Fnext = Lexer.idPool("popFront");
+		Fretreat = Lexer.idPool("popBack");
+		adDup = Lexer.idPool("_adDupT");
+		adReverse = Lexer.idPool("_adReverse");
+		aaLen = Lexer.idPool("_aaLen");
+		aaKeys = Lexer.idPool("_aaKeys");
+		aaValues = Lexer.idPool("_aaValues");
+		aaRehash = Lexer.idPool("_aaRehash");
+		monitorenter = Lexer.idPool("_d_monitorenter");
+		monitorexit = Lexer.idPool("_d_monitorexit");
+		criticalenter = Lexer.idPool("_d_criticalenter");
+		criticalexit = Lexer.idPool("_d_criticalexit");
+		GNU_asm = Lexer.idPool("GNU_asm");
+		lib = Lexer.idPool("lib");
+		msg = Lexer.idPool("msg");
+		startaddress = Lexer.idPool("startaddress");
+		tohash = Lexer.idPool("toHash");
+		tostring = Lexer.idPool("toString");
+		getmembers = Lexer.idPool("getMembers");
+		alloca = Lexer.idPool("alloca");
+		main = Lexer.idPool("main");
+		WinMain = Lexer.idPool("WinMain");
+		DllMain = Lexer.idPool("DllMain");
+		tls_get_addr = Lexer.idPool("___tls_get_addr");
+		std = Lexer.idPool("std");
+		math = Lexer.idPool("math");
+		sin = Lexer.idPool("sin");
+		cos = Lexer.idPool("cos");
+		tan = Lexer.idPool("tan");
+		_sqrt = Lexer.idPool("sqrt");
+		fabs = Lexer.idPool("fabs");
+		isAbstractClass = Lexer.idPool("isAbstractClass");
+		isArithmetic = Lexer.idPool("isArithmetic");
+		isAssociativeArray = Lexer.idPool("isAssociativeArray");
+		isFinalClass = Lexer.idPool("isFinalClass");
+		isFloating = Lexer.idPool("isFloating");
+		isIntegral = Lexer.idPool("isIntegral");
+		isScalar = Lexer.idPool("isScalar");
+		isStaticArray = Lexer.idPool("isStaticArray");
+		isUnsigned = Lexer.idPool("isUnsigned");
+		isVirtualFunction = Lexer.idPool("isVirtualFunction");
+		isAbstractFunction = Lexer.idPool("isAbstractFunction");
+		isFinalFunction = Lexer.idPool("isFinalFunction");
+		hasMember = Lexer.idPool("hasMember");
+		getMember = Lexer.idPool("getMember");
+		getVirtualFunctions = Lexer.idPool("getVirtualFunctions");
+		classInstanceSize = Lexer.idPool("classInstanceSize");
+		allMembers = Lexer.idPool("allMembers");
+		derivedMembers = Lexer.idPool("derivedMembers");
+		isSame = Lexer.idPool("isSame");
+		compiles = Lexer.idPool("compiles");
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Identifier.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,79 @@
+module dmd.Identifier;
+
+import dmd.TOK;
+import dmd.DYNCAST;
+import dmd.Lexer;
+import dmd.OutBuffer;
+
+import std.stdio : writef;
+
+class Identifier
+{
+    TOK value;
+    string string_;
+
+    this(string string_, TOK value)
+	{
+		this.string_ = string_;
+		this.value = value;
+	}
+	
+    int equals(Object o)
+	{
+		return this is o || string_ == (cast(Identifier)o).toChars();		/// hack
+	}
+	
+    hash_t hashCode()
+	{
+		assert(false);
+	}
+	
+    int compare(Object o)
+	{
+		assert(false);
+	}
+	
+    void print()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		return string_;
+	}
+	
+version (_DH) {
+    char* toHChars()
+	{
+		assert(false);
+	}
+}
+    string toHChars2()
+	{
+		assert(false);
+	}
+	
+    DYNCAST dyncast()
+	{
+		return DYNCAST.DYNCAST_IDENTIFIER;
+	}
+
+	// BUG: these are redundant with Lexer::uniqueId()
+    static Identifier generateId(string prefix)
+	{
+		static size_t i;
+		return generateId(prefix, ++i);
+	}
+	
+    static Identifier generateId(string prefix, size_t i)
+	{
+		scope OutBuffer buf = new OutBuffer();
+
+		buf.writestring(prefix);
+		buf.printf("%d", i);	///<!
+
+		string id = buf.extractString();
+		return Lexer.idPool(id);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IdentifierExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,171 @@
+module dmd.IdentifierExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.TY;
+import dmd.TypePointer;
+import dmd.FuncDeclaration;
+import dmd.TemplateInstance;
+import dmd.TemplateDeclaration;
+import dmd.TemplateExp;
+import dmd.DsymbolExp;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.WithScopeSymbol;
+import dmd.VarExp;
+import dmd.DotIdExp;
+import dmd.Type;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class IdentifierExp : Expression
+{
+	Identifier ident;
+
+	Declaration var;
+
+	this(Loc loc, Identifier ident)
+	{
+		super(loc, TOK.TOKidentifier, IdentifierExp.sizeof);
+		this.ident = ident;
+	}
+
+	this(Loc loc, Declaration var)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Dsymbol s;
+		Dsymbol scopesym;
+
+version (LOGSEMANTIC) {
+		printf("IdentifierExp.semantic('%s')\n", ident.toChars());
+}
+		s = sc.search(loc, ident, &scopesym);
+		if (s)
+		{	
+			Expression e;
+			WithScopeSymbol withsym;
+
+			/* See if the symbol was a member of an enclosing 'with'
+			 */
+			withsym = scopesym.isWithScopeSymbol();
+			if (withsym)
+			{
+version (DMDV2) {
+				/* Disallow shadowing
+				 */
+				// First find the scope of the with
+				Scope scwith = sc;
+				while (scwith.scopesym !is scopesym)
+				{	
+					scwith = scwith.enclosing;
+					assert(scwith);
+				}
+
+				// Look at enclosing scopes for symbols with the same name,
+				// in the same function
+				for (Scope scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
+				{   
+					Dsymbol s2;
+
+					if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s !is s2)
+					{
+						error("with symbol %s is shadowing local symbol %s", s.toPrettyChars(), s2.toPrettyChars());
+					}
+				}
+}
+				s = s.toAlias();
+
+				// Same as wthis.ident
+				if (s.needThis() || s.isTemplateDeclaration())
+				{
+					e = new VarExp(loc, withsym.withstate.wthis);
+					e = new DotIdExp(loc, e, ident);
+				}
+				else
+				{	
+					Type t = withsym.withstate.wthis.type;
+					if (t.ty == TY.Tpointer)
+						t = (cast(TypePointer)t).next;
+					e = typeDotIdExp(loc, t, ident);
+				}
+			}
+			else
+			{
+				/* If f is really a function template,
+				 * then replace f with the function template declaration.
+				 */
+				FuncDeclaration f = s.isFuncDeclaration();
+				if (f && f.parent)
+				{   
+					TemplateInstance ti = f.parent.isTemplateInstance();
+
+					if (ti && !ti.isTemplateMixin() &&
+						(ti.name == f.ident || ti.toAlias().ident == f.ident) &&
+						ti.tempdecl && ti.tempdecl.onemember)
+					{
+						TemplateDeclaration tempdecl = ti.tempdecl;
+
+						if (tempdecl.overroot)         // if not start of overloaded list of TemplateDeclaration's
+							tempdecl = tempdecl.overroot; // then get the start
+
+						e = new TemplateExp(loc, tempdecl);
+						e = e.semantic(sc);
+
+						return e;
+					}
+				}
+
+				// Haven't done overload resolution yet, so pass 1
+				e = new DsymbolExp(loc, s, 1);
+			}
+
+			return e.semantic(sc);
+		}
+
+		error("undefined identifier %s", ident.toChars());
+		type = Type.terror;
+		return this;
+	}
+
+	string toChars()
+	{
+		return ident.toChars();
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		if (hgs.hdrgen)
+			buf.writestring(ident.toHChars2());
+		else
+			buf.writestring(ident.toChars());
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+static if (false) {
+		tym = tybasic(e1.ET.Tty);
+		if (!(tyscalar(tym) || tym == TYM.TYstruct || tym == TYM.TYarray && e.Eoper == TOK.TOKaddr))
+			synerr(EM_lvalue);	// lvalue expected
+}
+		return this;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IdentityExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,130 @@
+module dmd.IdentityExp;
+
+import dmd.Expression;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.WANT;
+import dmd.TY;
+import dmd.expression.Identity;
+
+import dmd.backend.elem;
+import dmd.backend.TYM;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+
+class IdentityExp : BinExp
+{
+	this(TOK op, Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, op, IdentityExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		 if (type)
+			return this;
+
+		BinExp.semanticp(sc);
+		type = Type.tboolean;
+		typeCombine(sc);
+
+		if (e1.type != e2.type && e1.type.isfloating() && e2.type.isfloating())
+		{
+			// Cast both to complex
+			e1 = e1.castTo(sc, Type.tcomplex80);
+			e2 = e2.castTo(sc, Type.tcomplex80);
+		}
+
+		return this;
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("IdentityExp.optimize(result = %d) %s\n", result, toChars());
+		e1 = e1.optimize(WANT.WANTvalue | (result & WANT.WANTinterpret));
+		e2 = e2.optimize(WANT.WANTvalue | (result & WANT.WANTinterpret));
+		e = this;
+
+		if ((this.e1.isConst() && this.e2.isConst()) || (this.e1.op == TOK.TOKnull && this.e2.op == TOK.TOKnull))
+		{
+			e = Identity(op, type, this.e1, this.e2);
+		}
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e;
+		OPER eop;
+		Type t1 = e1.type.toBasetype();
+		Type t2 = e2.type.toBasetype();
+
+		switch (op)
+		{
+			case TOK.TOKidentity:		eop = OPER.OPeqeq;	break;
+			case TOK.TOKnotidentity:	eop = OPER.OPne;	break;
+			default:
+				dump(0);
+				assert(0);
+		}
+
+		//printf("IdentityExp.toElem() %s\n", toChars());
+
+		if (t1.ty == 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(TYM.TYint, t1.size());
+			e = el_bin(OPER.OPmemcmp, TYM.TYint, e, ecount);
+			e = el_bin(eop, TYM.TYint, e, el_long(TYM.TYint, 0));
+			el_setLoc(e,loc);
+		}
+		else if ((t1.ty == TY.Tarray || t1.ty == TY.Tsarray) && (t2.ty == TY.Tarray || t2.ty == 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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IfStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,311 @@
+module dmd.IfStatement;
+
+import dmd.Statement;
+import dmd.Argument;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.VarDeclaration;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.WANT;
+import dmd.ScopeDsymbol;
+import dmd.Type;
+import dmd.CondExp;
+import dmd.AndAndExp;
+import dmd.OrOrExp;
+import dmd.AssignExp;
+import dmd.VarExp;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.BC;
+
+class IfStatement : Statement
+{
+    Argument arg;
+    Expression condition;
+    Statement ifbody;
+    Statement elsebody;
+
+    VarDeclaration match;	// for MatchExpression results
+
+    this(Loc loc, Argument arg, Expression condition, Statement ifbody, Statement elsebody)
+	{
+		super(loc);
+		this.arg = arg;
+		this.condition = condition;
+		this.ifbody = ifbody;
+		this.elsebody = elsebody;
+	}
+		
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		condition = condition.semantic(sc);
+		condition = resolveProperties(sc, condition);
+		condition = condition.checkToBoolean();
+
+		// If we can short-circuit evaluate the if statement, don't do the
+		// semantic analysis of the skipped code.
+		// This feature allows a limited form of conditional compilation.
+		condition = condition.optimize(WANT.WANTflags);
+
+		// Evaluate at runtime
+		uint cs0 = sc.callSuper;
+		uint cs1;
+
+		Scope scd;
+		if (arg)
+		{	
+			/* Declare arg, which we will set to be the
+			 * result of condition.
+			 */
+			ScopeDsymbol sym = new ScopeDsymbol();
+			sym.parent = sc.scopesym;
+			scd = sc.push(sym);
+
+			Type t = arg.type ? arg.type : condition.type;
+			match = new VarDeclaration(loc, t, arg.ident, null);
+			match.noauto = true;
+			match.semantic(scd);
+			if (!scd.insert(match))
+				assert(0);
+
+			match.parent = sc.func;
+
+			/* Generate:
+			 *  (arg = condition)
+			 */
+			VarExp v = new VarExp(Loc(0), match);
+			condition = new AssignExp(loc, v, condition);
+			condition = condition.semantic(scd);
+		}
+		else
+			scd = sc.push();
+
+		ifbody = ifbody.semantic(scd);
+		scd.pop();
+
+		cs1 = sc.callSuper;
+		sc.callSuper = cs0;
+		if (elsebody)
+			elsebody = elsebody.semanticScope(sc, null, null);
+
+		sc.mergeCallSuper(loc, cs1);
+
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		//printf("IfStatement::blockExit(%p)\n", this);
+
+		BE result = BE.BEnone;
+		if (condition.canThrow())
+			result |= BE.BEthrow;
+		if (condition.isBool(true))
+		{
+			if (ifbody)
+				result |= ifbody.blockExit();
+			else
+				result |= BE.BEfallthru;
+		}
+		else if (condition.isBool(false))
+		{
+			if (elsebody)
+				result |= elsebody.blockExit();
+			else
+				result |= BE.BEfallthru;
+		}
+		else
+		{
+			if (ifbody)
+				result |= ifbody.blockExit();
+			else
+				result |= BE.BEfallthru;
+
+			if (elsebody)
+				result |= elsebody.blockExit();
+			else
+				result |= BE.BEfallthru;
+		}
+
+		//printf("IfStatement::blockExit(%p) = x%x\n", this, result);
+		return result;
+	}
+	
+    IfStatement isIfStatement() { return this; }
+
+    int inlineCost(InlineCostState* ics)
+	{
+		int cost;
+
+		/* Can't declare variables inside ?: expressions, so
+		 * we cannot inline if a variable is declared.
+		 */
+		if (arg)
+			return COST_MAX;
+
+		cost = condition.inlineCost(ics);
+
+		/* Specifically allow:
+		 *	if (condition)
+		 *	    return exp1;
+		 *	else
+		 *	    return exp2;
+		 * Otherwise, we can't handle return statements nested in if's.
+		 */
+
+		if (elsebody && ifbody &&
+			ifbody.isReturnStatement() &&
+			elsebody.isReturnStatement())
+		{
+			cost += ifbody.inlineCost(ics);
+			cost += elsebody.inlineCost(ics);
+			//printf("cost = %d\n", cost);
+		}
+		else
+		{
+			ics.nested += 1;
+			if (ifbody)
+				cost += ifbody.inlineCost(ics);
+			if (elsebody)
+				cost += elsebody.inlineCost(ics);
+			ics.nested -= 1;
+		}
+		return cost;
+	}
+	
+    Expression doInline(InlineDoState ids)
+	{
+		Expression econd;
+		Expression e1;
+		Expression e2;
+		Expression e;
+
+		assert(!arg);
+		econd = condition.doInline(ids);
+		assert(econd);
+		if (ifbody)
+			e1 = ifbody.doInline(ids);
+		else
+			e1 = null;
+		if (elsebody)
+			e2 = elsebody.doInline(ids);
+		else
+			e2 = null;
+		if (e1 && e2)
+		{
+			e = new CondExp(econd.loc, econd, e1, e2);
+			e.type = e1.type;
+		}
+		else if (e1)
+		{
+			e = new AndAndExp(econd.loc, econd, e1);
+			e.type = Type.tvoid;
+		}
+		else if (e2)
+		{
+			e = new OrOrExp(econd.loc, econd, e2);
+			e.type = Type.tvoid;
+		}
+		else
+		{
+			e = econd;
+		}
+		return e;
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		condition = condition.inlineScan(iss);
+		if (ifbody)
+			ifbody = ifbody.inlineScan(iss);
+		if (elsebody)
+			elsebody = elsebody.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		elem* e;
+		Blockx* blx = irs.blx;
+
+		//printf("IfStatement::toIR('%s')\n", condition.toChars());
+
+		IRState mystate = IRState(irs, this);
+
+		// bexit is the block that gets control after this IfStatement is done
+		block* bexit = mystate.breakBlock ? mystate.breakBlock : block_calloc();
+
+		incUsage(irs, loc);
+static if (false) {
+		if (match)
+		{	
+			/* Generate:
+			 *  if (match = RTLSYM_IFMATCH(string, pattern)) ...
+			 */
+			assert(condition.op == TOK.TOKmatch);
+			e = matchexp_toelem(cast(MatchExp)condition, &mystate, RTLSYM.RTLSYM_IFMATCH);
+			Symbol *s = match.toSymbol();
+			symbol_add(s);
+			e = el_bin(OPeq, TYnptr, el_var(s), e);
+		}
+		else
+		{
+			e = condition.toElem(&mystate);
+		}
+} else {
+			e = condition.toElem(&mystate);
+}
+		block_appendexp(blx.curblock, e);
+		block* bcond = blx.curblock;
+		block_next(blx, BC.BCiftrue, null);
+
+		list_append(&bcond.Bsucc, blx.curblock);
+		if (ifbody)
+			ifbody.toIR(&mystate);
+
+		list_append(&blx.curblock.Bsucc, bexit);
+
+		if (elsebody)
+		{
+			block_next(blx, BC.BCgoto, null);
+			list_append(&bcond.Bsucc, blx.curblock);
+			elsebody.toIR(&mystate);
+			list_append(&blx.curblock.Bsucc, bexit);
+		}
+		else
+			list_append(&bcond.Bsucc, bexit);
+
+		block_next(blx, BC.BCgoto, bexit);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Import.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,339 @@
+module dmd.Import;
+
+import dmd.Dsymbol;
+import dmd.Array;
+import dmd.DsymbolTable;
+import dmd.PROT;
+import dmd.Identifier;
+import dmd.Module;
+import dmd.Package;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.TypeIdentifier;
+import dmd.AliasDeclaration;
+import dmd.ScopeDsymbol;
+import dmd.StorageClassDeclaration;
+import dmd.STC;
+import dmd.ProtDeclaration;
+import dmd.Global;
+
+import std.stdio;
+
+void escapePath(OutBuffer buf, string fname)
+{
+    foreach (char c; fname)
+    {
+		switch (c)
+		{
+			case '(':
+			case ')':
+			case '\\':
+				buf.writebyte('\\');
+			default:
+				buf.writebyte(*fname);
+				break;
+		}
+    }
+}
+
+class Import : Dsymbol
+{
+    Array packages;		// array of Identifier's representing packages
+    Identifier id;		// module Identifier
+    Identifier aliasId;
+    int isstatic;		// !=0 if static import
+
+    // Pairs of alias=name to bind into current namespace
+    Array names;
+    Array aliases;
+
+    Array aliasdecls;		// AliasDeclarations for names/aliases
+
+    Module mod;
+    Package pkg;		// leftmost package/module
+
+    this(Loc loc, Array packages, Identifier id, Identifier aliasId, int isstatic)
+	{
+		super(id);
+		
+		names = new Array();
+		aliases = new Array();
+		aliasdecls = new Array();
+		
+		assert(id);
+		this.loc = loc;
+		this.packages = packages;
+		this.id = id;
+		this.aliasId = aliasId;
+		this.isstatic = isstatic;
+
+		if (aliasId)
+			this.ident = aliasId;
+		// Kludge to change Import identifier to first package
+		else if (packages && packages.dim)
+			this.ident = cast(Identifier)packages.data[0];
+	}
+    
+	void addAlias(Identifier name, Identifier alias_)
+	{
+		if (isstatic)
+			error("cannot have an import bind list");
+
+		if (!aliasId)
+			this.ident = null;	// make it an anonymous import
+
+		names.push(cast(void*)name);
+		aliases.push(cast(void*)alias_);
+	}
+
+    string kind()
+	{
+		return isstatic ? "static import" : "import";
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)	// copy only syntax trees
+	{
+		assert(false);
+	}
+	
+    void load(Scope sc)
+	{
+		DsymbolTable dst;
+		Dsymbol s;
+
+		//writef("Import::load('%s')\n", toChars());
+
+		// See if existing module
+		dst = Package.resolve(packages, null, &pkg);
+
+		s = dst.lookup(id);
+		if (s)
+		{
+version (TARGET_NET) {
+			mod = cast(Module)s;
+} else {
+			if (s.isModule())
+				mod = cast(Module)s;
+			else
+				error("package and module have the same name");
+}
+		}
+		
+		if (!mod)
+		{
+			// Load module
+			mod = Module.load(loc, packages, id);
+			dst.insert(id, mod);		// id may be different from mod->ident,
+							// if so then insert alias
+			if (!mod.importedFrom)
+				mod.importedFrom = sc ? sc.module_.importedFrom : Module.rootModule;
+		}
+
+		if (!pkg)
+			pkg = mod;
+
+		//writef("-Import::load('%s'), pkg = %p\n", toChars(), pkg);
+	}
+	
+    void semantic(Scope sc)
+	{
+		//writef("Import.semantic('%s')\n", toChars());
+
+		load(sc);
+		
+		if (mod)
+		{
+static if (false) {
+			if (mod.loc.linnum != 0)
+			{   /* If the line number is not 0, then this is not
+				 * a 'root' module, i.e. it was not specified on the command line.
+				 */
+				mod.importedFrom = sc.module_.importedFrom;
+				assert(mod.importedFrom);
+			}
+}
+
+			// Modules need a list of each imported module
+			//printf("%s imports %s\n", sc.module.toChars(), mod.toChars());
+			sc.module_.aimports.push(cast(void*)mod);
+
+			if (!isstatic && !aliasId && !names.dim)
+			{
+				/* Default to private importing
+				 */
+				PROT prot = sc.protection;
+				if (!sc.explicitProtection)
+					prot = PROT.PROTprivate;
+
+				sc.scopesym.importScope(mod, prot);
+			}
+
+			mod.semantic();
+
+			if (mod.needmoduleinfo)
+				sc.module_.needmoduleinfo = 1;
+
+			sc = sc.push(mod);
+			for (size_t i = 0; i < aliasdecls.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)aliasdecls.data[i];
+
+				//writef("\tImport alias semantic('%s')\n", s.toChars());
+				if (!mod.search(loc, cast(Identifier)names.data[i], 0))
+				error("%s not found", (cast(Identifier)names.data[i]).toChars());
+
+				s.semantic(sc);
+			}
+			sc = sc.pop();
+		}
+
+		if (global.params.moduleDeps !is null)
+		{
+		/* The grammar of the file is:
+		 *	ImportDeclaration
+		 *	    .= BasicImportDeclaration [ " : " ImportBindList ] [ " . "
+		 *	ModuleAliasIdentifier ] "\n"
+		 *
+		 *	BasicImportDeclaration
+		 *	    .= ModuleFullyQualifiedName " (" FilePath ") : " Protection
+		 *		" [ " static" ] : " ModuleFullyQualifiedName " (" FilePath ")"
+		 *
+		 *	FilePath
+		 *	    - any string with '(', ')' and '\' escaped with the '\' character
+		 */
+
+		OutBuffer ob = global.params.moduleDeps;
+
+		ob.writestring(sc.module_.toPrettyChars());
+		ob.writestring(" (");
+		escapePath(ob, sc.module_.srcfile.toChars());
+		ob.writestring(") : ");
+
+		ProtDeclaration.protectionToCBuffer(ob, sc.protection);
+		if (isstatic)
+			StorageClassDeclaration.stcToCBuffer(ob, STC.STCstatic);
+		ob.writestring(": ");
+
+		if (packages)
+		{
+			for (size_t i = 0; i < packages.dim; i++)
+			{
+			Identifier pid = cast(Identifier)packages.data[i];
+			ob.printf("%s.", pid.toChars());
+			}
+		}
+
+		ob.writestring(id.toChars());
+		ob.writestring(" (");
+		if (mod)
+			escapePath(ob, mod.srcfile.toChars());
+		else
+			ob.writestring("???");
+		ob.writebyte(')');
+
+		for (size_t i = 0; i < names.dim; i++)
+		{
+			if (i == 0)
+			ob.writebyte(':');
+			else
+			ob.writebyte(',');
+
+			Identifier name = cast(Identifier)names.data[i];
+			Identifier alias_ = cast(Identifier)aliases.data[i];
+
+			if (!alias_)
+			{
+				ob.printf("%s", name.toChars());
+				alias_ = name;
+			}
+			else
+				ob.printf("%s=%s", alias_.toChars(), name.toChars());
+		}
+
+		if (aliasId)
+			ob.printf(" . %s", aliasId.toChars());
+
+		ob.writenl();
+		}
+
+		//printf("-Import.semantic('%s'), pkg = %p\n", toChars(), pkg);
+	}
+	
+    void semantic2(Scope sc)
+	{
+		//printf("Import::semantic2('%s')\n", toChars());
+		mod.semantic2();
+		if (mod.needmoduleinfo)
+			sc.module_.needmoduleinfo = 1;
+	}
+	
+    Dsymbol toAlias()
+	{
+		if (aliasId)
+			return mod;
+		return this;
+	}
+	
+	/*****************************
+	 * Add import to sd's symbol table.
+	 */
+    bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
+	{
+		bool result = false;
+
+		if (names.dim == 0)
+			return Dsymbol.addMember(sc, sd, memnum);
+
+		if (aliasId)
+			result = Dsymbol.addMember(sc, sd, memnum);
+
+		/* Instead of adding the import to sd's symbol table,
+		 * add each of the alias=name pairs
+		 */
+		for (size_t i = 0; i < names.dim; i++)
+		{
+			Identifier name = cast(Identifier)names.data[i];
+			Identifier alias_ = cast(Identifier)aliases.data[i];
+
+			if (!alias_)
+				alias_ = name;
+
+			TypeIdentifier tname = new TypeIdentifier(loc, name);
+			AliasDeclaration ad = new AliasDeclaration(loc, alias_, tname);
+			result |= ad.addMember(sc, sd, memnum);
+
+			aliasdecls.push(cast(void*)ad);
+		}
+
+		return result;
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		//printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
+
+		if (!pkg)
+		{	
+			load(null);
+			mod.semantic();
+		}
+
+		// Forward it to the package/module
+		return pkg.search(loc, ident, flags);
+	}
+	
+    bool overloadInsert(Dsymbol s)
+	{
+		// Allow multiple imports of the same name
+		return s.isImport() !is null;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Import isImport() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,46 @@
+module dmd.InExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+
+import dmd.backend.elem;
+
+class InExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		assert(false);
+	}
+
+	Identifier opId_r()
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IndexExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,427 @@
+module dmd.IndexExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.VarDeclaration;
+import dmd.InlineDoState;
+import dmd.Type;
+import dmd.ScopeDsymbol;
+import dmd.TY;
+import dmd.ArrayScopeSymbol;
+import dmd.TypeNext;
+import dmd.TypeSArray;
+import dmd.TypeAArray;
+import dmd.UnaExp;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.TupleExp;
+import dmd.TypeTuple;
+import dmd.Argument;
+import dmd.TypeExp;
+import dmd.VarExp;
+import dmd.STC;
+import dmd.GlobalExpressions;
+import dmd.ExpInitializer;
+import dmd.Global;
+
+import dmd.expression.util.arrayTypeCompatible;
+import dmd.expression.Util;
+import dmd.expression.Index;
+
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.OPER;
+import dmd.backend.mTY;
+import dmd.backend.TYM;
+
+import core.stdc.string;
+
+class IndexExp : BinExp
+{
+	VarDeclaration lengthVar;
+	int modifiable = 0;	// assume it is an rvalue
+
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKindex, IndexExp.sizeof, e1, e2);
+		//printf("IndexExp.IndexExp('%s')\n", toChars());
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		BinExp b;
+		UnaExp u;
+		Type t1;
+		ScopeDsymbol sym;
+
+	version (LOGSEMANTIC) {
+		printf("IndexExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			return this;
+		if (!e1.type)
+			e1 = e1.semantic(sc);
+		assert(e1.type);		// semantic() should already be run on it
+		e = this;
+
+		// Note that unlike C we do not implement the int[ptr]
+
+		t1 = e1.type.toBasetype();
+
+		if (t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Ttuple)
+		{	
+			// Create scope for 'length' variable
+			sym = new ArrayScopeSymbol(sc, this);
+			sym.loc = loc;
+			sym.parent = sc.scopesym;
+			sc = sc.push(sym);
+		}
+
+		e2 = e2.semantic(sc);
+		if (!e2.type)
+		{
+			error("%s has no value", e2.toChars());
+			e2.type = Type.terror;
+		}
+		e2 = resolveProperties(sc, e2);
+
+		if (t1.ty == Tsarray || t1.ty == Tarray || t1.ty == Ttuple)
+			sc = sc.pop();
+
+		switch (t1.ty)
+		{
+			case Tpointer:
+			case Tarray:
+				e2 = e2.implicitCastTo(sc, Type.tsize_t);
+				e.type = (cast(TypeNext)t1).next;
+				break;
+
+			case Tsarray:
+			{
+				e2 = e2.implicitCastTo(sc, Type.tsize_t);
+
+				TypeSArray tsa = cast(TypeSArray)t1;
+
+		static if (false) {
+				// Don't do now, because it might be short-circuit evaluated
+				// Do compile time array bounds checking if possible
+				e2 = e2.optimize(WANTvalue);
+				if (e2.op == TOKint64)
+				{
+					ulong index = e2.toInteger();
+					ulong length = tsa.dim.toInteger();
+					if (index < 0 || index >= length)
+						error("array index [%lld] is outside array bounds [0 .. %lld]", index, length);
+				}
+		}
+				e.type = t1.nextOf();
+				break;
+			}
+
+			case Taarray:
+			{   
+				TypeAArray taa = cast(TypeAArray)t1;
+				if (!arrayTypeCompatible(e2.loc, e2.type, taa.index))
+				{
+					e2 = e2.implicitCastTo(sc, taa.index);	// type checking
+				}
+				type = taa.next;
+				break;
+			}
+
+			case Ttuple:
+			{
+				e2 = e2.implicitCastTo(sc, Type.tsize_t);
+				e2 = e2.optimize(WANTvalue | WANTinterpret);
+				ulong index = e2.toUInteger();
+				size_t length;
+				TupleExp te;
+				TypeTuple tup;
+
+				if (e1.op == TOKtuple)
+				{	
+					te = cast(TupleExp)e1;
+					length = te.exps.dim;
+				}
+				else if (e1.op == TOKtype)
+				{
+					tup = cast(TypeTuple)t1;
+					length = Argument.dim(tup.arguments);
+				}
+				else
+					assert(0);
+
+				if (index < length)
+				{
+					if (e1.op == TOKtuple)
+						e = cast(Expression)te.exps.data[cast(size_t)index];
+					else
+						e = new TypeExp(e1.loc, Argument.getNth(tup.arguments, cast(size_t)index).type);
+				}
+				else
+				{
+					error("array index [%ju] is outside array bounds [0 .. %zu]", index, length);
+					e = e1;
+				}
+				break;
+			}
+
+			default:
+				error("%s must be an array or pointer type, not %s", e1.toChars(), e1.type.toChars());
+				type = Type.tint32;
+				break;
+		}
+
+		return e;
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		//    if (type && type.toBasetype().ty == Tvoid)
+		//		error("voids have no value");
+		return this;
+	}
+
+	Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		//printf("IndexExp::modifiableLvalue(%s)\n", toChars());
+		modifiable = 1;
+		if (e1.op == TOKstring)
+			error("string literals are immutable");
+		if (type && !type.isMutable())
+			error("%s isn't mutable", e.toChars());
+		if (e1.type.toBasetype().ty == Taarray)
+			e1 = e1.modifiableLvalue(sc, e1);
+		return toLvalue(sc, e);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("IndexExp::optimize(result = %d) %s\n", result, toChars());
+		Expression e1 = this.e1.optimize(WANTvalue | (result & WANTinterpret));
+		e1 = fromConstInitializer(result, e1);
+		if (this.e1.op == TOKvar)
+		{	
+			VarExp ve = cast(VarExp)this.e1;
+			if (ve.var.storage_class & STCmanifest)
+			{   
+				/* We generally don't want to have more than one copy of an
+				 * array literal, but if it's an enum we have to because the
+				 * enum isn't stored elsewhere. See Bugzilla 2559
+				 */
+				this.e1 = e1;
+			}
+		}
+
+		e2 = e2.optimize(WANTvalue | (result & WANTinterpret));
+		e = Index(type, e1, e2);
+		if (e is EXP_CANT_INTERPRET)
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		IndexExp are = cast(IndexExp)copy();
+
+		are.e1 = e1.doInline(ids);
+
+		if (lengthVar)
+		{	//printf("lengthVar\n");
+			VarDeclaration vd = lengthVar;
+			ExpInitializer ie;
+			ExpInitializer ieto;
+			VarDeclaration vto;
+
+			vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init);
+			///*vto = *vd;
+			memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length);
+			vto.parent = ids.parent;
+			vto.csym = null;
+			vto.isym = null;
+
+			ids.from.push(cast(void*)vd);
+			ids.to.push(cast(void*)vto);
+
+			if (vd.init)
+			{
+				ie = vd.init.isExpInitializer();
+				assert(ie);
+				ieto = new ExpInitializer(ie.loc, ie.exp.doInline(ids));
+				vto.init = ieto;
+			}
+
+			are.lengthVar = vto;
+		}
+		are.e2 = e2.doInline(ids);
+		return are;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		elem* n1 = e1.toElem(irs);
+		elem* n2;
+		elem* eb = null;
+		Type t1;
+
+		//printf("IndexExp.toElem() %s\n", toChars());
+		t1 = e1.type.toBasetype();
+		if (t1.ty == Taarray)
+		{
+			// set to:
+			//	*aaGet(aa, keyti, valuesize, index);
+
+			TypeAArray taa = cast(TypeAArray)t1;
+			elem* keyti;
+			elem* ep;
+			int vsize = cast(int)taa.next.size();
+			elem* valuesize;
+			Symbol* s;
+
+			// n2 becomes the index, also known as the key
+			n2 = e2.toElem(irs);
+			if (tybasic(n2.Ety) == TYstruct || tybasic(n2.Ety) == TYarray)
+			{
+				n2 = el_una(OPstrpar, TYstruct, n2);
+				n2.Enumbytes = n2.E1.Enumbytes;
+				//printf("numbytes = %d\n", n2.Enumbytes);
+				assert(n2.Enumbytes);
+			}
+			valuesize = el_long(TYuint, vsize);	// BUG: should be TYsize_t
+			//printf("valuesize: "); elem_print(valuesize);
+			if (modifiable)
+			{
+				n1 = el_una(OPaddr, TYnptr, n1);
+				s = taa.aaGetSymbol("Get", 1);
+			}
+			else
+			{
+				s = taa.aaGetSymbol("GetRvalue", 1);
+			}
+			//printf("taa.index = %s\n", taa.index.toChars());
+			keyti = taa.index.getInternalTypeInfo(null).toElem(irs);
+			//keyti = taa.index.getTypeInfo(null).toElem(irs);
+			//printf("keyti:\n");
+			//elem_print(keyti);
+			ep = el_params(n2, valuesize, keyti, n1, null);
+			e = el_bin(OPcall, TYnptr, el_var(s), ep);
+			if (global.params.useArrayBounds)
+			{
+				elem* n;
+				elem* ea;
+
+				n = el_same(&e);
+
+				// Construct: ((e || ModuleAssert(line)),n)
+				Symbol* sassert;
+
+				sassert = irs.blx.module_.toModuleArray();
+				ea = el_bin(OPcall,TYvoid,el_var(sassert),
+				el_long(TYint, loc.linnum));
+				e = el_bin(OPoror,TYvoid,e,ea);
+				e = el_bin(OPcomma, TYnptr, e, n);
+			}
+			e = el_una(OPind, type.totym(), e);
+			if (tybasic(e.Ety) == TYstruct)
+				e.Enumbytes = cast(uint)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 = cast(TypeSArray)t1;
+					ulong 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 = cast(uint)type.size();
+				}
+			}
+
+			eb = el_combine(einit, eb);
+			e = el_combine(eb, e);
+		}
+
+		el_setLoc(e,loc);
+
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Initializer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,67 @@
+module dmd.Initializer;
+
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Type;
+import dmd.ArrayTypes;
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.VoidInitializer;
+import dmd.StructInitializer;
+import dmd.ArrayInitializer;
+import dmd.ExpInitializer;
+
+import dmd.backend.dt_t;
+
+class Initializer
+{
+    Loc loc;
+
+    this(Loc loc)
+	{
+		this.loc = loc;
+	}
+	
+    Initializer syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Initializer semantic(Scope sc, Type t)
+	{
+		assert(false);
+	}
+	
+    Type inferType(Scope sc)
+	{
+		assert(false);
+	}
+	
+    abstract Expression toExpression();
+    
+	abstract void toCBuffer(OutBuffer buf, HdrGenState* hgs);
+    
+	string toChars()
+	{
+		assert(false);
+	}
+
+    static Initializers arraySyntaxCopy(Initializers *ai)
+	{
+		assert(false);
+	}
+
+    dt_t* toDt()
+	{
+		assert(false);
+	}
+
+    VoidInitializer isVoidInitializer() { return null; }
+	
+    StructInitializer isStructInitializer()  { return null; }
+    
+	ArrayInitializer isArrayInitializer()  { return null; }
+    
+	ExpInitializer isExpInitializer()  { return null; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InlineCostState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,31 @@
+module dmd.InlineCostState;
+
+import dmd.FuncDeclaration;
+import dmd.Array;
+import dmd.Expression;
+
+struct InlineCostState
+{
+    int nested;
+    int hasthis;
+    int hdrscan;    // !=0 if inline scan for 'header' content
+    FuncDeclaration fd;
+}
+
+const int COST_MAX = 250;
+
+int arrayInlineCost(InlineCostState* ics, Array arguments)
+{
+	int cost = 0;
+
+    if (arguments)
+    {
+		for (int i = 0; i < arguments.dim; i++)
+		{   
+			Expression e = cast(Expression)arguments.data[i];
+			if (e)
+				cost += e.inlineCost(ics);
+		}
+    }
+    return cost;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InlineDoState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,48 @@
+module dmd.InlineDoState;
+
+import dmd.Array;
+import dmd.Dsymbol;
+import dmd.VarDeclaration;
+import dmd.Expression;
+import dmd.ArrayTypes;
+
+class InlineDoState
+{
+    VarDeclaration vthis;
+    Array from;		// old Dsymbols
+    Array to;		// parallel array of new Dsymbols
+    Dsymbol parent;	// new parent
+	
+	this()
+	{
+		from = new Array();
+		to = new Array();
+	}
+}
+
+/******************************
+ * Perform doInline() on an array of Expressions.
+ */
+
+Expressions arrayExpressiondoInline(Expressions a, InlineDoState ids)
+{   
+	Expressions newa = null;
+
+    if (a)
+    {
+		newa = new Expressions();
+		newa.setDim(a.dim);
+
+		for (int i = 0; i < a.dim; i++)
+		{   
+			Expression e = cast(Expression)a.data[i];
+
+			if (e)
+			{
+				e = e.doInline(ids);
+				newa.data[i] = cast(void*)e;
+			}
+		}
+    }
+    return newa;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InlineScanState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,97 @@
+module dmd.InlineScanState;
+
+import dmd.FuncDeclaration;
+import dmd.ExpInitializer;
+import dmd.Dsymbol;
+import dmd.InlineScanState;
+import dmd.TupleDeclaration;
+import dmd.VarDeclaration;
+import dmd.Type;
+import dmd.TypeStruct;
+import dmd.StructDeclaration;
+import dmd.Array;
+import dmd.Expression;
+import dmd.DsymbolExp;
+import dmd.TOK;
+import dmd.TY;
+
+struct InlineScanState
+{
+    FuncDeclaration fd;	// function being scanned
+}
+
+void scanVar(Dsymbol s, InlineScanState* iss)
+{
+    VarDeclaration vd = s.isVarDeclaration();
+    if (vd)
+    {
+		TupleDeclaration td = vd.toAlias().isTupleDeclaration();
+		if (td)
+		{
+			for (size_t i = 0; i < td.objects.dim; i++)
+			{   
+				DsymbolExp se = cast(DsymbolExp)td.objects.data[i];
+				assert(se.op == TOKdsymbol);
+				scanVar(se.s, iss);
+			}
+		}
+		else
+		{
+			// Scan initializer (vd.init)
+			if (vd.init)
+			{
+				ExpInitializer ie = vd.init.isExpInitializer();
+
+				if (ie)
+				{
+		version (DMDV2) {
+					if (vd.type)
+					{	
+						Type tb = vd.type.toBasetype();
+						if (tb.ty == Tstruct)
+						{   
+							StructDeclaration sd = (cast(TypeStruct)tb).sym;
+							if (sd.cpctor)
+							{
+								/* The problem here is that if the initializer is a
+								 * function call that returns a struct S with a cpctor:
+								 *   S s = foo();
+								 * the postblit is done by the return statement in foo()
+								 * in s2ir.c, the intermediate code generator.
+								 * But, if foo() is inlined and now the code looks like:
+								 *   S s = x;
+								 * the postblit is not there, because such assignments
+								 * are rewritten as s.cpctor(&x) by the front end.
+								 * So, the inlining won't get the postblit called.
+								 * Work around by not inlining these cases.
+								 * A proper fix would be to move all the postblit
+								 * additions to the front end.
+								 */
+								return;
+							}
+						}
+					}
+		}
+					ie.exp = ie.exp.inlineScan(iss);
+				}
+			}
+		}
+    }
+}
+
+void arrayInlineScan(InlineScanState* iss, Array arguments)
+{
+    if (arguments)
+    {
+		for (int i = 0; i < arguments.dim; i++)
+		{   
+			Expression e = cast(Expression)arguments.data[i];
+
+			if (e)
+			{
+				e = e.inlineScan(iss);
+				arguments.data[i] = cast(void*)e;
+			}
+		}
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IntRange.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,7 @@
+module dmd.IntRange;
+
+struct IntRange
+{
+	ulong imin;
+    ulong imax;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IntegerExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,549 @@
+module dmd.IntegerExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.TY;
+import dmd.TypeEnum;
+import dmd.TypeTypedef;
+import dmd.Global;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.Complex;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+
+import core.stdc.ctype : isprint;
+
+class IntegerExp : Expression
+{
+	ulong value;
+
+	this(Loc loc, ulong value, Type type)
+	{
+		super(loc, TOK.TOKint64, IntegerExp.sizeof);
+		
+		//printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type.toChars() : "");
+		if (type && !type.isscalar())
+		{
+			//printf("%s, loc = %d\n", toChars(), loc.linnum);
+			error("integral constant must be scalar type, not %s", type.toChars());
+			type = Type.terror;
+		}
+		this.type = type;
+		this.value = value;
+	}
+
+	this(ulong value)
+	{
+		super(Loc(0), TOK.TOKint64, IntegerExp.sizeof);
+		this.type = Type.tint32;
+		this.value = value;
+	}
+
+	int equals(Object o)
+	{
+		IntegerExp ne;
+
+		if (this == o ||
+			((cast(Expression)o).op == TOKint64 &&
+			((ne = cast(IntegerExp)o), type.toHeadMutable().equals(ne.type.toHeadMutable())) &&
+			value == ne.value)
+		  )
+			return 1;
+
+		return 0;
+	}
+
+	Expression semantic(Scope sc)
+	{
+		if (!type)
+		{
+			// Determine what the type of this number is
+			ulong number = value;
+
+			if (number & 0x8000000000000000)
+				type = Type.tuns64;
+			else if (number & 0xFFFFFFFF80000000)
+				type = Type.tint64;
+			else
+				type = Type.tint32;
+		}
+		else
+		{	if (!type.deco)
+				type = type.semantic(loc, sc);
+		}
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+static if (true) {
+		return Expression.toChars();
+} else {
+		static char buffer[value.sizeof * 3 + 1];
+		int len = sprintf(buffer.ptr, "%jd", value);
+		return buffer[0..len].idup;
+}
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	ulong toInteger()
+	{
+		Type t;
+
+		t = type;
+		while (t)
+		{
+			switch (t.ty)
+			{
+				case TY.Tbit:
+				case TY.Tbool:	value = (value != 0);		break;
+				case TY.Tint8:	value = cast(byte)  value;	break;
+				case TY.Tchar:
+				case TY.Tuns8:	value = cast(ubyte) value;	break;
+				case TY.Tint16:	value = cast(short) value;	break;
+				case TY.Twchar:
+				case TY.Tuns16:	value = cast(ushort)value;	break;
+				case TY.Tint32:	value = cast(int)   value;	break;
+				case TY.Tdchar:
+				case TY.Tuns32:	value = cast(uint)  value;	break;
+				case TY.Tint64:	value = cast(long)  value;	break;
+				case TY.Tuns64:	value = cast(ulong) value;	break;
+				case TY.Tpointer:
+						if (PTRSIZE == 4)
+							value = cast(uint) value;
+						else if (PTRSIZE == 8)
+							value = cast(ulong) value;
+						else
+							assert(0);
+						break;
+
+				case TY.Tenum:
+				{
+					TypeEnum te = cast(TypeEnum)t;
+					t = te.sym.memtype;
+					continue;
+				}
+
+				case TY.Ttypedef:
+				{
+					TypeTypedef tt = cast(TypeTypedef)t;
+					t = tt.sym.basetype;
+					continue;
+				}
+
+				default:
+					/* This can happen if errors, such as
+					 * the type is painted on like in fromConstInitializer().
+					 */
+					if (!global.errors)
+					{   
+						///type.print();
+						assert(0);
+					}
+					break;
+			}
+			break;
+		}
+		return value;
+	}
+
+	real toReal()
+	{
+		Type t;
+
+		toInteger();
+		t = type.toBasetype();
+		if (t.ty == Tuns64)
+			return cast(real)cast(ulong)value;
+		else
+			return cast(real)cast(long)value;
+	}
+
+	real toImaginary()
+	{
+		assert(false);
+	}
+
+	Complex!(real) toComplex()
+	{
+		assert(false);
+	}
+
+	int isConst()
+	{
+		return 1;
+	}
+
+	bool isBool(bool result)
+	{
+		return result ? value != 0 : value == 0;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+static if (false) {
+		printf("IntegerExp.implicitConvTo(this=%s, type=%s, t=%s)\n",
+		toChars(), type.toChars(), t.toChars());
+}
+
+		MATCH m = type.implicitConvTo(t);
+		if (m >= MATCH.MATCHconst)
+			return m;
+
+		TY ty = type.toBasetype().ty;
+		TY toty = t.toBasetype().ty;
+
+		if (m == MATCH.MATCHnomatch && t.ty == TY.Tenum)
+			goto Lno;
+
+		switch (ty)
+		{
+			case TY.Tbit:
+			case TY.Tbool:
+				value &= 1;
+				ty = TY.Tint32;
+				break;
+
+			case TY.Tint8:
+				value = cast(byte)value;
+				ty = TY.Tint32;
+				break;
+
+			case TY.Tchar:
+			case TY.Tuns8:
+				value &= 0xFF;
+				ty = TY.Tint32;
+				break;
+
+			case TY.Tint16:
+				value = cast(short)value;
+				ty = TY.Tint32;
+				break;
+
+			case TY.Tuns16:
+			case TY.Twchar:
+				value &= 0xFFFF;
+				ty = TY.Tint32;
+				break;
+
+			case TY.Tint32:
+				value = cast(int)value;
+				break;
+
+			case TY.Tuns32:
+			case TY.Tdchar:
+				value &= 0xFFFFFFFF;
+				ty = TY.Tuns32;
+				break;
+
+			default:
+				break;
+		}
+
+		// Only allow conversion if no change in value
+		switch (toty)
+		{
+			case TY.Tbit:
+			case TY.Tbool:
+				if ((value & 1) != value)
+					goto Lno;
+				goto Lyes;
+
+			case TY.Tint8:
+				if (cast(byte)value != value)
+					goto Lno;
+				goto Lyes;
+
+			case TY.Tchar:
+			case TY.Tuns8:
+				//printf("value = %llu %llu\n", (dinteger_t)(unsigned char)value, value);
+				if (cast(ubyte)value != value)
+					goto Lno;
+				goto Lyes;
+
+			case TY.Tint16:
+				if (cast(short)value != value)
+					goto Lno;
+				goto Lyes;
+
+			case TY.Tuns16:
+				if (cast(ushort)value != value)
+				goto Lno;
+				goto Lyes;
+
+			case TY.Tint32:
+				if (ty == TY.Tuns32) {
+					;
+				}
+				else if (cast(int)value != value) {
+					goto Lno;
+				}
+				goto Lyes;
+
+			case TY.Tuns32:
+				if (ty == TY.Tint32) {
+				} else if (cast(uint)value != value) {
+					goto Lno;
+				}
+				goto Lyes;
+
+			case TY.Tdchar:
+				if (value > 0x10FFFF) {
+					goto Lno;
+				}
+				goto Lyes;
+
+			case TY.Twchar:
+				if (cast(ushort)value != value) {
+					goto Lno;
+				}
+				goto Lyes;
+
+			case TY.Tfloat32:
+			{
+				/*volatile*/ float f;	///
+				if (type.isunsigned()) {
+					f = cast(float)value;
+					if (f != value) {
+						goto Lno;
+					}
+				} else {
+					f = cast(float)cast(long)value;
+					if (f != cast(long)value) {
+						goto Lno;
+					}
+				}
+				goto Lyes;
+			}
+
+			case TY.Tfloat64:
+			{
+				/*volatile*/ double f;	///
+				if (type.isunsigned()) {
+					f = cast(double)value;
+					if (f != value)
+						goto Lno;
+				} else {
+					f = cast(double)cast(long)value;
+					if (f != cast(long)value)
+						goto Lno;
+				}
+				goto Lyes;
+			}
+
+			case TY.Tfloat80:
+			{
+				/*volatile*/ real f;	///
+				if (type.isunsigned()) {
+					f = cast(real)value;
+					if (f != value)
+						goto Lno;
+				} else {
+					f = cast(real)cast(long)value;
+					if (f != cast(long)value)
+						goto Lno;
+				}
+				goto Lyes;
+			}
+
+			case TY.Tpointer:
+		//printf("type = %s\n", type.toBasetype().toChars());
+		//printf("t = %s\n", t.toBasetype().toChars());
+				if (ty == TY.Tpointer && type.toBasetype().nextOf().ty == t.toBasetype().nextOf().ty)
+				{
+					/* Allow things like:
+					 *	const char* P = cast(char *)3;
+					 *	char* q = P;
+					 */
+					goto Lyes;
+				}
+				break;
+				
+			default:
+				break;	///
+		}
+
+		return Expression.implicitConvTo(t);
+
+	Lyes:
+		//printf("MATCHconvert\n");
+		return MATCH.MATCHconvert;
+
+	Lno:
+		//printf("MATCHnomatch\n");
+		return MATCH.MATCHnomatch;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		long v = toInteger();
+
+		if (type)
+		{	
+			Type t = type;
+
+		  L1:
+			switch (t.ty)
+			{
+				case TY.Tenum:
+				{   
+					TypeEnum te = cast(TypeEnum)t;
+					buf.printf("cast(%s)", te.sym.toChars());
+					t = te.sym.memtype;
+					goto L1;
+				}
+
+				case TY.Ttypedef:
+				{	
+					TypeTypedef tt = cast(TypeTypedef)t;
+					buf.printf("cast(%s)", tt.sym.toChars());
+					t = tt.sym.basetype;
+					goto L1;
+				}
+
+				case TY.Twchar:	// BUG: need to cast(wchar)
+				case TY.Tdchar:	// BUG: need to cast(dchar)
+					if (cast(ulong)v > 0xFF)
+					{
+						 buf.printf("'\\U%08x'", v);
+						 break;
+					}
+				case TY.Tchar:
+					if (v == '\'')
+						buf.writestring("'\\''");
+					else if (isprint(cast(int)v) && v != '\\')
+						buf.printf("'%c'", cast(int)v);
+					else
+						buf.printf("'\\x%02x'", cast(int)v);
+					break;
+
+				case TY.Tint8:
+					buf.writestring("cast(byte)");
+					goto L2;
+
+				case TY.Tint16:
+					buf.writestring("cast(short)");
+					goto L2;
+
+				case TY.Tint32:
+				L2:
+					buf.printf("%d", cast(int)v);
+					break;
+
+				case TY.Tuns8:
+					buf.writestring("cast(ubyte)");
+					goto L3;
+
+				case TY.Tuns16:
+					buf.writestring("cast(ushort)");
+					goto L3;
+
+				case TY.Tuns32:
+				L3:
+					buf.printf("%du", cast(uint)v);
+					break;
+
+				case TY.Tint64:
+					buf.printf("%jdL", v);
+					break;
+
+				case TY.Tuns64:
+				L4:
+					buf.printf("%juLU", v);
+					break;
+
+				case TY.Tbit:
+				case TY.Tbool:
+					buf.writestring(v ? "true" : "false");
+					break;
+
+				case TY.Tpointer:
+					buf.writestring("cast(");
+					buf.writestring(t.toChars());
+					buf.writeByte(')');
+					if (PTRSIZE == 4)
+						goto L3;
+					else if (PTRSIZE == 8)
+						goto L4;
+					else
+						assert(0);
+
+				default:
+					/* This can happen if errors, such as
+					 * the type is painted on like in fromConstInitializer().
+					 */
+					if (!global.errors)
+					{
+						debug {
+							writef("%s\n", t.toChars());
+						}
+						assert(0);
+					}
+					break;
+			}
+		}
+		else if (v & 0x8000000000000000L)
+			buf.printf("0x%jx", v);
+		else
+			buf.printf("%jd", v);
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		if (!e)
+			e = this;
+		else if (!loc.filename)
+			loc = e.loc;
+		e.error("constant %s is not an lvalue", e.toChars());
+		return this;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e = el_long(type.totym(), value);
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		//printf("IntegerExp.toDt() %d\n", op);
+		uint sz = cast(uint)type.size();
+		if (value == 0)
+			pdt = dtnzeros(pdt, sz);
+		else
+			pdt = dtnbytes(pdt, sz, cast(char*)&value);
+
+		return pdt;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InterState.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,16 @@
+module dmd.InterState;
+
+import dmd.FuncDeclaration;
+import dmd.ArrayTypes;
+import dmd.Expression;
+import dmd.Statement;
+
+struct InterState
+{
+    InterState* caller;		// calling function's InterState
+    FuncDeclaration fd;	// function being interpreted
+    Dsymbols vars;		// variables used in this function
+    Statement start;		// if !=NULL, start execution at this statement
+    Statement gotoTarget;	// target of EXP_GOTO_INTERPRET result
+    Expression localThis;	// value of 'this', or NULL if none
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InterfaceDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,511 @@
+module dmd.InterfaceDeclaration;
+
+import dmd.ClassDeclaration;
+import dmd.Loc;
+import dmd.DsymbolTable;
+import dmd.STC;
+import dmd.Type;
+import dmd.TY;
+import dmd.LINK;
+import dmd.Argument;
+import dmd.Util;
+import dmd.TypeTuple;
+import dmd.PROT;
+import dmd.TypeClass;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.Global;
+import dmd.BaseClass;
+import dmd.Id;
+
+import dmd.backend.Symbol;
+import dmd.backend.TYM;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.LIST;
+import dmd.backend.SFL;
+
+class InterfaceDeclaration : ClassDeclaration
+{
+version (DMDV2) {
+    bool cpp;				// true if this is a C++ interface
+}
+    this(Loc loc, Identifier id, BaseClasses baseclasses)
+	{
+		super(loc, id, baseclasses);
+		
+		if (id is Id.IUnknown)	// IUnknown is the root of all COM interfaces
+		{
+			com = true;
+			cpp = true;		// IUnknown is also a C++ interface
+		}
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		int i;
+
+		//printf("InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
+		if (inuse)
+			return;
+
+		if (!sc)
+			sc = scope_;
+		if (!parent && sc.parent && !sc.parent.isModule())
+		parent = sc.parent;
+
+		type = type.semantic(loc, sc);
+		handle = type;
+
+		if (!members)			// if forward reference
+		{	
+			//printf("\tinterface '%s' is forward referenced\n", toChars());
+			return;
+		}
+		if (symtab)			// if already done
+		{	
+			if (!scope_)
+				return;
+		}
+		else
+		symtab = new DsymbolTable();
+
+		Scope scx = null;
+		if (scope_)
+		{	
+			sc = scope_;
+			scx = scope_;		// save so we don't make redundant copies
+			scope_ = null;
+		}
+
+		if (sc.stc & STC.STCdeprecated)
+		{
+			isdeprecated = true;
+		}
+
+		// Expand any tuples in baseclasses[]
+		for (i = 0; i < baseclasses.dim; )
+		{	
+			BaseClass b = cast(BaseClass)baseclasses.data[0];
+			b.type = b.type.semantic(loc, sc);
+			Type tb = b.type.toBasetype();
+
+			if (tb.ty == TY.Ttuple)
+			{   TypeTuple tup = cast(TypeTuple)tb;
+				PROT protection = b.protection;
+				baseclasses.remove(i);
+				size_t dim = Argument.dim(tup.arguments);
+				for (size_t j = 0; j < dim; j++)
+				{	Argument arg = Argument.getNth(tup.arguments, j);
+				b = new BaseClass(arg.type, protection);
+				baseclasses.insert(i + j, cast(void*)b);
+				}
+			}
+			else
+				i++;
+		}
+
+		if (!baseclasses.dim && sc.linkage == LINK.LINKcpp)
+		cpp = 1;
+
+		// Check for errors, handle forward references
+		for (i = 0; i < baseclasses.dim; )
+		{	
+			TypeClass tc;
+			BaseClass b;
+			Type tb;
+
+			b = cast(BaseClass)baseclasses.data[i];
+			b.type = b.type.semantic(loc, sc);
+			tb = b.type.toBasetype();
+			if (tb.ty == TY.Tclass)
+				tc = cast(TypeClass)tb;
+			else
+				tc = null;
+			if (!tc || !tc.sym.isInterfaceDeclaration())
+			{
+				error("base type must be interface, not %s", b.type.toChars());
+				baseclasses.remove(i);
+				continue;
+			}
+			else
+			{
+				// Check for duplicate interfaces
+				for (size_t j = 0; j < i; j++)
+				{
+					BaseClass b2 = cast(BaseClass)baseclasses.data[j];
+					if (b2.base is tc.sym)
+						error("inherits from duplicate interface %s", b2.base.toChars());
+				}
+
+				b.base = tc.sym;
+				if (b.base == this || isBaseOf2(b.base))
+				{
+					error("circular inheritance of interface");
+					baseclasses.remove(i);
+					continue;
+				}
+				if (!b.base.symtab)
+				{   
+					// Try to resolve forward reference
+					if (sc.mustsemantic && b.base.scope_)
+						b.base.semantic(null);
+				}
+				if (!b.base.symtab || b.base.scope_ || b.base.inuse)
+				{
+					//error("forward reference of base class %s", baseClass.toChars());
+					// Forward reference of base, try again later
+					//printf("\ttry later, forward reference of base %s\n", b.base.toChars());
+					scope_ = scx ? scx : new Scope(sc);
+					scope_.setNoFree();
+					scope_.module_.addDeferredSemantic(this);
+					return;
+				}
+			}
+static if (false) {
+			// Inherit const/invariant from base class
+			storage_class |= b.base.storage_class & STC.STC_TYPECTOR;
+}
+			i++;
+		}
+
+		interfaces_dim = baseclasses.dim;
+		interfaces = cast(BaseClass*)baseclasses.data;
+
+		interfaceSemantic(sc);
+
+		if (vtblOffset())
+		vtbl.push(cast(void*)this);		// leave room at vtbl[0] for classinfo
+
+		// Cat together the vtbl[]'s from base interfaces
+		for (i = 0; i < interfaces_dim; i++)
+		{	
+			BaseClass b = interfaces[i];
+
+			// Skip if b has already appeared
+			for (int k = 0; k < i; k++)
+			{
+				if (b == interfaces[i])
+				goto Lcontinue;
+			}
+
+			// Copy vtbl[] from base class
+			if (b.base.vtblOffset())
+			{   int d = b.base.vtbl.dim;
+				if (d > 1)
+				{
+				vtbl.reserve(d - 1);
+				for (int j = 1; j < d; j++)
+					vtbl.push(b.base.vtbl.data[j]);
+				}
+			}
+			else
+			{
+				vtbl.append(b.base.vtbl);
+			}
+
+			  Lcontinue:
+			;
+		}
+
+		protection = sc.protection;
+		storage_class |= sc.stc & STC.STC_TYPECTOR;
+
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.addMember(sc, this, 1);
+		}
+
+		sc = sc.push(this);
+		sc.stc &= ~(STC.STCfinal | STC.STCauto | STC.STCscope | STC.STCstatic |
+					 STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCtls | STC.STCgshared);
+		sc.stc |= storage_class & STC.STC_TYPECTOR;
+		sc.parent = this;
+		if (isCOMinterface())
+		sc.linkage = LINK.LINKwindows;
+		else if (isCPPinterface())
+		sc.linkage = LINK.LINKcpp;
+		sc.structalign = 8;
+		structalign = sc.structalign;
+		sc.offset = PTRSIZE * 2;
+		inuse++;
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.semantic(sc);
+		}
+		inuse--;
+		//members.print();
+		sc.pop();
+		//printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
+	}
+	
+    bool isBaseOf(ClassDeclaration cd, int* poffset)
+	{
+		uint j;
+
+		//printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars());
+		assert(!baseClass);
+		for (j = 0; j < cd.interfaces_dim; j++)
+		{
+			BaseClass b = cd.interfaces[j];
+
+			//printf("\tbase %s\n", b.base.toChars());
+			if (this == b.base)
+			{
+				//printf("\tfound at offset %d\n", b.offset);
+				if (poffset)
+				{	
+					*poffset = b.offset;
+					if (j && cd.isInterfaceDeclaration())
+						*poffset = OFFSET_RUNTIME;
+				}
+				return true;
+			}
+			if (isBaseOf(b, poffset))
+			{   
+				if (j && poffset && cd.isInterfaceDeclaration())
+					*poffset = OFFSET_RUNTIME;
+				return true;
+			}
+		}
+
+		if (cd.baseClass && isBaseOf(cd.baseClass, poffset))
+		return true;
+
+		if (poffset)
+			*poffset = 0;
+		return false;
+	}
+	
+    bool isBaseOf(BaseClass bc, int* poffset)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+	/****************************************
+	 * Determine if slot 0 of the vtbl[] is reserved for something else.
+	 * For class objects, yes, this is where the ClassInfo ptr goes.
+	 * For COM interfaces, no.
+	 * For non-COM interfaces, yes, this is where the Interface ptr goes.
+	 */
+    int vtblOffset()
+	{
+		if (isCOMinterface() || isCPPinterface())
+			return 0;
+		return 1;
+	}
+	
+version (DMDV2) {
+    bool isCPPinterface()
+	{
+		return cpp;
+	}
+}
+    bool isCOMinterface()
+	{
+		return com;
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		uint i;
+		uint offset;
+		Symbol* sinit;
+		SC scclass;
+
+		//printf("InterfaceDeclaration.toObjFile('%s')\n", toChars());
+
+		if (!members)
+			return;
+
+		if (global.params.symdebug)
+			toDebug();
+
+		scclass = SCglobal;
+		if (inTemplateInstance())
+			scclass = SCcomdat;
+
+		// Put out the members
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol member;
+
+			member = cast(Dsymbol)members.data[i];
+			if (!member.isFuncDeclaration())
+				member.toObjFile(0);
+		}
+
+		// Generate C symbols
+		toSymbol();
+
+		//////////////////////////////////////////////
+
+		// Put out the TypeInfo
+		type.getTypeInfo(null);
+		type.vtinfo.toObjFile(multiobj);
+
+		//////////////////////////////////////////////
+
+		// Put out the ClassInfo
+		csym.Sclass = scclass;
+		csym.Sfl = FLdata;
+
+		/* The layout is:
+		   {
+			void **vptr;
+			monitor_t monitor;
+			byte[] initializer;		// static initialization data
+			char[] name;		// class name
+			void *[] vtbl;
+			Interface[] interfaces;
+			Object *base;		// base class
+			void *destructor;
+			void *invariant;		// class invariant
+			uint flags;
+			void *deallocator;
+			OffsetTypeInfo[] offTi;
+			void *defaultConstructor;
+	#if DMDV2
+			const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
+	#endif
+			TypeInfo typeinfo;
+		   }
+		 */
+		dt_t *dt = null;
+
+		if (classinfo)
+			dtxoff(&dt, classinfo.toVtblSymbol(), 0, TYnptr); // vtbl for ClassInfo
+		else
+			dtdword(&dt, 0);		// BUG: should be an assert()
+		dtdword(&dt, 0);			// monitor
+
+		// initializer[]
+		dtdword(&dt, 0);			// size
+		dtdword(&dt, 0);			// initializer
+
+		// name[]
+		string name = toPrettyChars();
+		size_t namelen = name.length;
+		dtdword(&dt, namelen);
+		dtabytes(&dt, TYnptr, 0, namelen + 1, toStringz(name));
+
+		// vtbl[]
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);
+
+		// vtblInterfaces.data[]
+		dtdword(&dt, vtblInterfaces.dim);
+		if (vtblInterfaces.dim)
+		{
+			if (classinfo)
+				assert(classinfo.structsize == CLASSINFO_SIZE);
+			offset = CLASSINFO_SIZE;
+			dtxoff(&dt, csym, offset, TYnptr);	// (*)
+		}
+		else
+			dtdword(&dt, 0);
+
+		// base
+		assert(!baseClass);
+		dtdword(&dt, 0);
+
+		// dtor
+		dtdword(&dt, 0);
+
+		// invariant
+		dtdword(&dt, 0);
+
+		// flags
+		dtdword(&dt, 4 | isCOMinterface() | 32);
+
+		// deallocator
+		dtdword(&dt, 0);
+
+		// offTi[]
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);		// null for now, fix later
+
+		// defaultConstructor
+		dtdword(&dt, 0);
+
+	version (DMDV2) {
+		// xgetMembers
+		dtdword(&dt, 0);
+	}
+
+		dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr);	// typeinfo
+
+		//////////////////////////////////////////////
+
+		// Put out vtblInterfaces.data[]. Must immediately follow csym, because
+		// of the fixup (*)
+
+		offset += vtblInterfaces.dim * (4 * PTRSIZE);
+		for (i = 0; i < vtblInterfaces.dim; i++)
+		{	
+			BaseClass b = cast(BaseClass)vtblInterfaces.data[i];
+			ClassDeclaration id = b.base;
+
+			// ClassInfo
+			dtxoff(&dt, id.toSymbol(), 0, TYnptr);
+
+			// vtbl[]
+			dtdword(&dt, 0);
+			dtdword(&dt, 0);
+
+			// this offset
+			dtdword(&dt, b.offset);
+		}
+
+		csym.Sdt = dt;
+	version (ELFOBJ) {
+		csym.Sseg = CDATA;
+	}
+	version (MACHOBJ) {
+		csym.Sseg = DATA;
+	}
+		outdata(csym);
+		if (isExport())
+			obj_export(csym,0);
+	}
+
+	/*************************************
+	 * Create the "InterfaceInfo" symbol
+	 */
+    Symbol* toSymbol()
+	{
+		if (!csym)
+		{
+			Symbol *s;
+
+			if (!scc)
+				scc = fake_classsym(Id.ClassInfo);
+
+			s = toSymbolX("__Interface", SCextern, scc.Stype, "Z");
+			s.Sfl = FLextern;
+			s.Sflags |= SFLnodebug;
+			csym = s;
+			slist_add(s);
+		}
+		return csym;
+	}
+
+    InterfaceDeclaration isInterfaceDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/InvariantDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,90 @@
+module dmd.InvariantDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.Id;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.LINK;
+import dmd.STC;
+import dmd.TypeFunction;
+import dmd.Type;
+import dmd.AggregateDeclaration;
+
+class InvariantDeclaration : FuncDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+		super(loc, endloc, Id.classInvariant, STCundefined, null);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(!s);
+		InvariantDeclaration id = new InvariantDeclaration(loc, endloc);
+		FuncDeclaration.syntaxCopy(id);
+		return id;
+	}
+
+    void semantic(Scope sc)
+	{
+		AggregateDeclaration ad;
+		Type tret;
+
+		parent = sc.parent;
+		Dsymbol parent = toParent();
+		ad = parent.isAggregateDeclaration();
+		if (!ad)
+		{
+			error("invariants are only for struct/union/class definitions");
+			return;
+		}
+		else if (ad.inv && ad.inv != this)
+		{
+			error("more than one invariant for %s", ad.toChars());
+		}
+		ad.inv = this;
+		type = new TypeFunction(null, Type.tvoid, false, LINKd);
+
+		sc = sc.push();
+		sc.stc &= ~STCstatic;		// not a static invariant
+		sc.incontract++;
+		sc.linkage = LINK.LINKd;
+
+		FuncDeclaration.semantic(sc);
+
+		sc.pop();
+	}
+
+    bool isVirtual()
+	{
+		return false;
+	}
+
+    bool addPreInvariant()
+	{
+		return false;
+	}
+
+    bool addPostInvariant()
+	{
+		return false;
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		if (hgs.hdrgen)
+			return;
+		buf.writestring("invariant");
+		bodyToCBuffer(buf, hgs);
+	}
+
+    InvariantDeclaration isInvariantDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/IsExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,323 @@
+module dmd.IsExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.Type;
+import dmd.TOK;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TY;
+import dmd.TypeEnum;
+import dmd.STC;
+import dmd.TypeClass;
+import dmd.TemplateParameter;
+import dmd.BaseClass;
+import dmd.ClassDeclaration;
+import dmd.TypeStruct;
+import dmd.TypeTypedef;
+import dmd.IntegerExp;
+import dmd.AliasDeclaration;
+import dmd.Dsymbol;
+import dmd.TypeTuple;
+import dmd.TypeDelegate;
+import dmd.Declaration;
+import dmd.TypeFunction;
+import dmd.MATCH;
+import dmd.TypePointer;
+import dmd.Argument;
+
+class IsExp : Expression
+{
+	/* is(targ id tok tspec)
+     * is(targ id == tok2)
+     */
+    Type targ;
+    Identifier id;	// can be null
+    TOK tok;	// ':' or '=='
+    Type tspec;	// can be null
+    TOK tok2;	// 'struct', 'union', 'typedef', etc.
+    TemplateParameters parameters;
+
+	this(Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters parameters)
+	{
+		super(loc, TOK.TOKis, IsExp.sizeof);
+		
+		this.targ = targ;
+		this.id = id;
+		this.tok = tok;
+		this.tspec = tspec;
+		this.tok2 = tok2;
+		this.parameters = parameters;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Type tded;
+
+		/* is(targ id tok tspec)
+		 * is(targ id == tok2)
+		 */
+
+		//printf("IsExp.semantic(%s)\n", toChars());
+		if (id && !(sc.flags & SCOPE.SCOPEstaticif))
+			error("can only declare type aliases within static if conditionals");
+
+		Type t = targ.trySemantic(loc, sc);
+		if (!t)
+			goto Lno;			// errors, so condition is false
+		targ = t;
+		if (tok2 != TOK.TOKreserved)
+		{
+			switch (tok2)
+			{
+				case TOKtypedef:
+					if (targ.ty != Ttypedef)
+						goto Lno;
+					tded = (cast(TypeTypedef)targ).sym.basetype;
+					break;
+
+				case TOKstruct:
+					if (targ.ty != Tstruct)
+						goto Lno;
+					if ((cast(TypeStruct)targ).sym.isUnionDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKunion:
+					if (targ.ty != Tstruct)
+						goto Lno;
+					if (!(cast(TypeStruct)targ).sym.isUnionDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKclass:
+					if (targ.ty != Tclass)
+						goto Lno;
+					if ((cast(TypeClass)targ).sym.isInterfaceDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKinterface:
+					if (targ.ty != Tclass)
+						goto Lno;
+					if (!(cast(TypeClass)targ).sym.isInterfaceDeclaration())
+						goto Lno;
+					tded = targ;
+					break;
+		version (DMDV2) {
+				case TOKconst:
+					if (!targ.isConst())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKinvariant:
+				case TOKimmutable:
+					if (!targ.isInvariant())
+						goto Lno;
+					tded = targ;
+					break;
+
+				case TOKshared:
+					if (!targ.isShared())
+						goto Lno;
+					tded = targ;
+					break;
+		}
+
+				case TOKsuper:
+					// If class or interface, get the base class and interfaces
+					if (targ.ty != Tclass)
+						goto Lno;
+					else
+					{   ClassDeclaration cd = (cast(TypeClass)targ).sym;
+						Arguments args = new Arguments;
+						args.reserve(cd.baseclasses.dim);
+						for (size_t i = 0; i < cd.baseclasses.dim; i++)
+						{	
+							BaseClass b = cast(BaseClass)cd.baseclasses.data[i];
+							args.push(cast(void*)new Argument(STCin, b.type, null, null));
+						}
+						tded = new TypeTuple(args);
+					}
+					break;
+
+				case TOKenum:
+					if (targ.ty != Tenum)
+						goto Lno;
+					tded = (cast(TypeEnum)targ).sym.memtype;
+					break;
+
+				case TOKdelegate:
+					if (targ.ty != Tdelegate)
+						goto Lno;
+					tded = (cast(TypeDelegate)targ).next;	// the underlying function type
+					break;
+
+				case TOKfunction:
+				{
+					if (targ.ty != Tfunction)
+						goto Lno;
+					tded = targ;
+
+					/* Generate tuple from function parameter types.
+					 */
+					assert(tded.ty == Tfunction);
+					Arguments params = (cast(TypeFunction)tded).parameters;
+					size_t dim = Argument.dim(params);
+					Arguments args = new Arguments;
+					args.reserve(dim);
+					for (size_t i = 0; i < dim; i++)
+					{   
+						Argument arg = Argument.getNth(params, i);
+						assert(arg && arg.type);
+						args.push(cast(void*)new Argument(arg.storageClass, arg.type, null, null));
+					}
+					tded = new TypeTuple(args);
+					break;
+				}
+				
+				case TOKreturn:
+					/* Get the 'return type' for the function,
+					 * delegate, or pointer to function.
+					 */
+					if (targ.ty == Tfunction)
+						tded = (cast(TypeFunction)targ).next;
+					else if (targ.ty == Tdelegate)
+					{   tded = (cast(TypeDelegate)targ).next;
+						tded = (cast(TypeFunction)tded).next;
+					}
+					else if (targ.ty == Tpointer &&
+						 (cast(TypePointer)targ).next.ty == Tfunction)
+					{   tded = (cast(TypePointer)targ).next;
+						tded = (cast(TypeFunction)tded).next;
+					}
+					else
+						goto Lno;
+					break;
+
+				default:
+					assert(0);
+			}
+			goto Lyes;
+		}
+		else if (id && tspec)
+		{
+			/* Evaluate to true if targ matches tspec.
+			 * If true, declare id as an alias for the specialized type.
+			 */
+
+			MATCH m;
+			assert(parameters && parameters.dim);
+
+			scope Objects dedtypes = new Objects();
+			dedtypes.setDim(parameters.dim);
+			dedtypes.zero();
+
+			m = targ.deduceType(null, tspec, parameters, dedtypes);
+			if (m == MATCHnomatch ||
+				(m != MATCHexact && tok == TOKequal))
+			{
+				goto Lno;
+			}
+			else
+			{
+				tded = cast(Type)dedtypes.data[0];
+				if (!tded)
+				tded = targ;
+
+				scope Objects tiargs = new Objects();
+				tiargs.setDim(1);
+				tiargs.data[0] = cast(void*)targ;
+
+				/* Declare trailing parameters
+				 */
+				for (int i = 1; i < parameters.dim; i++)
+				{	
+					TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+					Declaration s = null;
+
+					m = tp.matchArg(sc, tiargs, i, parameters, dedtypes, &s);
+					if (m == MATCHnomatch)
+						goto Lno;
+					s.semantic(sc);
+					if (!sc.insert(s))
+						error("declaration %s is already defined", s.toChars());
+		static if (false) {
+					Object o = cast(Object)dedtypes.data[i];
+					Dsymbol s = TemplateDeclaration.declareParameter(loc, sc, tp, o);
+		}
+					if (sc.sd)
+						s.addMember(sc, sc.sd, 1);
+				}
+
+				goto Lyes;
+			}
+		}
+		else if (id)
+		{
+			/* Declare id as an alias for type targ. Evaluate to true
+			 */
+			tded = targ;
+			goto Lyes;
+		}
+		else if (tspec)
+		{
+			/* Evaluate to true if targ matches tspec
+			 * is(targ == tspec)
+			 * is(targ : tspec)
+			 */
+			tspec = tspec.semantic(loc, sc);
+			//printf("targ  = %s\n", targ.toChars());
+			//printf("tspec = %s\n", tspec.toChars());
+			if (tok == TOKcolon)
+			{   
+				if (targ.implicitConvTo(tspec))
+					goto Lyes;
+				else
+					goto Lno;
+			}
+			else /* == */
+			{   
+				if (targ.equals(tspec))
+					goto Lyes;
+				else
+					goto Lno;
+			}
+		}
+
+	Lyes:
+		if (id)
+		{
+			Dsymbol s = new AliasDeclaration(loc, id, tded);
+			s.semantic(sc);
+			if (!sc.insert(s))
+				error("declaration %s is already defined", s.toChars());
+			if (sc.sd)
+				s.addMember(sc, sc.sd, 1);
+		}
+	//printf("Lyes\n");
+		return new IntegerExp(loc, 1, Type.tbool);
+
+	Lno:
+	//printf("Lno\n");
+		return new IntegerExp(loc, 0, Type.tbool);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Keyword.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,9 @@
+module dmd.Keyword;
+
+import dmd.TOK;
+
+struct Keyword
+{
+	string name;
+    TOK value;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/LINK.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.LINK;
+
+enum LINK
+{
+    LINKdefault,
+    LINKd,
+    LINKc,
+    LINKcpp,
+    LINKwindows,
+    LINKpascal,
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(LINK));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/LabelDsymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,24 @@
+module dmd.LabelDsymbol;
+
+import dmd.Dsymbol;
+import dmd.LabelStatement;
+import dmd.Identifier;
+
+class LabelDsymbol : Dsymbol
+{
+    LabelStatement statement;
+
+version (IN_GCC) {
+    uint asmLabelNum;       // GCC-specific
+}
+
+    this(Identifier ident)
+	{
+		super(ident);
+	}
+	
+    LabelDsymbol isLabel()
+	{
+		return this;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/LabelStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,153 @@
+module dmd.LabelStatement;
+
+import dmd.Statement;
+import dmd.Identifier;
+import dmd.TryFinallyStatement;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.ExpStatement;
+import dmd.ArrayTypes;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.InlineScanState;
+import dmd.LabelDsymbol;
+import dmd.FuncDeclaration;
+import dmd.CSX;
+import dmd.IRState;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.BE;
+
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.backend.BC;
+
+class LabelStatement : Statement
+{
+    Identifier ident;
+    Statement statement;
+    TryFinallyStatement tf = null;
+    block* lblock = null;		// back end
+    int isReturnLabel = 0;
+
+    this(Loc loc, Identifier ident, Statement statement)
+	{
+		super(loc);
+		this.ident = ident;
+		this.statement = statement;
+	}
+
+    Statement syntaxCopy()
+	{
+		LabelStatement s = new LabelStatement(loc, ident, statement.syntaxCopy());
+		return s;
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		LabelDsymbol ls;
+		FuncDeclaration fd = sc.parent.isFuncDeclaration();
+
+		//printf("LabelStatement.semantic()\n");
+		ls = fd.searchLabel(ident);
+		if (ls.statement)
+			error("Label '%s' already defined", ls.toChars());
+		else
+			ls.statement = this;
+		tf = sc.tf;
+		sc = sc.push();
+		sc.scopesym = sc.enclosing.scopesym;
+		sc.callSuper |= CSXlabel;
+		sc.slabel = this;
+		if (statement)
+			statement = statement.semantic(sc);
+		sc.pop();
+		return this;
+	}
+
+    Statements flatten(Scope sc)
+	{
+		Statements a = null;
+
+		if (statement)
+		{
+			a = statement.flatten(sc);
+			if (a)
+			{
+				if (!a.dim)
+					a.push(cast(void*)new ExpStatement(loc, null));
+
+				Statement s = cast(Statement)a.data[0];
+
+				s = new LabelStatement(loc, ident, s);
+				a.data[0] = cast(void*)s;
+			}
+		}
+
+		return a;
+	}
+	
+    bool usesEH()
+	{
+		return statement ? statement.usesEH() : false;
+	}
+	
+    BE blockExit()
+	{
+		//printf("LabelStatement.blockExit(%p)\n", this);
+		return statement ? statement.blockExit() : BE.BEfallthru;
+	}
+	
+    bool comeFrom()
+	{
+		//printf("LabelStatement.comeFrom()\n");
+		return true;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(ident.toChars());
+		buf.writebyte(':');
+		buf.writenl();
+		if (statement)
+			statement.toCBuffer(buf, hgs);
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (statement)
+			statement = statement.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		//printf("LabelStatement.toIR() %p, statement = %p\n", this, statement);
+		Blockx* blx = irs.blx;
+		block* bc = blx.curblock;
+		IRState mystate = IRState(irs,this);
+		mystate.ident = ident;
+
+		if (lblock)
+		{
+			// We had made a guess about which tryblock the label is in.
+			// Error if we guessed wrong.
+			// BUG: should fix this
+			if (lblock.Btry != blx.tryblock)
+				error("cannot goto forward into different try block level");
+		}
+		else
+			lblock = block_calloc(blx);
+
+		block_next(blx,BCgoto,lblock);
+		list_append(&bc.Bsucc,blx.curblock);
+		if (statement)
+			statement.toIR(&mystate);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Lexer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,2425 @@
+module dmd.Lexer;
+
+import dmd.StringTable;
+import dmd.OutBuffer;
+import dmd.Token;
+import dmd.Loc;
+import dmd.Module;
+import dmd.Identifier;
+import dmd.TOK;
+import dmd.Keyword;
+import dmd.StringValue;
+import dmd.Global;
+import dmd.Util;
+import dmd.Id;
+import dmd.Dchar;
+import dmd.Utf;
+
+import std.stdio : writeln;
+
+import core.stdc.ctype;
+import core.stdc.stdlib;
+import core.stdc.string;
+import core.stdc.stdio;
+import core.stdc.time;
+import core.stdc.errno;
+
+enum LS = 0x2028;	// UTF line separator
+enum PS = 0x2029;	// UTF paragraph separator
+
+extern (C) extern
+{
+	__gshared char* __locale_decpoint;
+}
+
+int isUniAlpha(uint u)
+{
+	assert(false);
+}
+
+class Lexer
+{
+    static StringTable stringtable;
+    static OutBuffer stringbuffer;
+    static Token* freelist;
+
+    Loc loc;			// for error messages
+
+    ubyte* base;	// pointer to start of buffer
+    ubyte* end;		// past end of buffer
+    ubyte* p;		// current character
+    Token token;
+    Module mod;
+    int doDocComment;		// collect doc comment information
+    int anyToken;		// !=0 means seen at least one token
+    int commentToken;		// !=0 means comments are TOKcomment's
+	
+	static this()
+	{
+		stringtable = new StringTable();
+		stringbuffer = new OutBuffer();
+	}
+	
+	static ~this()
+	{
+		delete stringtable;
+	}
+
+    this(Module mod, ubyte* base, uint begoffset, uint endoffset, int doDocComment, int commentToken)
+	{
+		loc = Loc(mod, 1);
+		
+		memset(&token,0,token.sizeof);
+		this.base = base;
+		this.end  = base + endoffset;
+		p = base + begoffset;
+		this.mod = mod;
+		this.doDocComment = doDocComment;
+		this.anyToken = 0;
+		this.commentToken = commentToken;
+		//initKeywords();
+
+		/* If first line starts with '#!', ignore the line
+		 */
+
+		if (p[0] == '#' && p[1] =='!')
+		{
+			p += 2;
+			while (1)
+			{  
+				ubyte c = *p;
+				switch (c)
+				{
+				case '\n':
+					p++;
+					break;
+
+				case '\r':
+					p++;
+					if (*p == '\n')
+					p++;
+					break;
+
+				case 0:
+				case 0x1A:
+					break;
+
+				default:
+					if (c & 0x80)
+					{
+						uint u = decodeUTF();
+						if (u == PS || u == LS)
+							break;
+					}
+					p++;
+					continue;
+				}
+				break;
+			}
+			loc.linnum = 2;
+		}
+	}
+
+version (DMDV2) {
+	static Keyword[] keywords =
+	[
+	//    {	"",		TOK	},
+
+		{	"this",		TOK.TOKthis		},
+		{	"super",	TOK.TOKsuper	},
+		{	"assert",	TOK.TOKassert	},
+		{	"null",		TOK.TOKnull		},
+		{	"true",		TOK.TOKtrue		},
+		{	"false",	TOK.TOKfalse	},
+		{	"cast",		TOK.TOKcast		},
+		{	"new",		TOK.TOKnew		},
+		{	"delete",	TOK.TOKdelete	},
+		{	"throw",	TOK.TOKthrow	},
+		{	"module",	TOK.TOKmodule	},
+		{	"pragma",	TOK.TOKpragma	},
+		{	"typeof",	TOK.TOKtypeof	},
+		{	"typeid",	TOK.TOKtypeid	},
+
+		{	"template",	TOK.TOKtemplate	},
+
+		{	"void",		TOK.TOKvoid		},
+		{	"byte",		TOK.TOKint8		},
+		{	"ubyte",	TOK.TOKuns8		},
+		{	"short",	TOK.TOKint16	},
+		{	"ushort",	TOK.TOKuns16	},
+		{	"int",		TOK.TOKint32	},
+		{	"uint",		TOK.TOKuns32	},
+		{	"long",		TOK.TOKint64	},
+		{	"ulong",	TOK.TOKuns64	},
+		{	"cent",		TOK.TOKcent,	},
+		{	"ucent",	TOK.TOKucent,	},
+		{	"float",	TOK.TOKfloat32	},
+		{	"double",	TOK.TOKfloat64	},
+		{	"real",		TOK.TOKfloat80	},
+
+		{	"bool",		TOK.TOKbool		},
+		{	"char",		TOK.TOKchar		},
+		{	"wchar",	TOK.TOKwchar	},
+		{	"dchar",	TOK.TOKdchar	},
+
+		{	"ifloat",	TOK.TOKimaginary32	},
+		{	"idouble",	TOK.TOKimaginary64	},
+		{	"ireal",	TOK.TOKimaginary80	},
+
+		{	"cfloat",	TOK.TOKcomplex32	},
+		{	"cdouble",	TOK.TOKcomplex64	},
+		{	"creal",	TOK.TOKcomplex80	},
+
+		{	"delegate",	TOK.TOKdelegate	},
+		{	"function",	TOK.TOKfunction	},
+
+		{	"is",		TOK.TOKis		},
+		{	"if",		TOK.TOKif		},
+		{	"else",		TOK.TOKelse		},
+		{	"while",	TOK.TOKwhile	},
+		{	"for",		TOK.TOKfor		},
+		{	"do",		TOK.TOKdo		},
+		{	"switch",	TOK.TOKswitch	},
+		{	"case",		TOK.TOKcase		},
+		{	"default",	TOK.TOKdefault	},
+		{	"break",	TOK.TOKbreak	},
+		{	"continue",	TOK.TOKcontinue	},
+		{	"synchronized",	TOK.TOKsynchronized	},
+		{	"return",	TOK.TOKreturn	},
+		{	"goto",		TOK.TOKgoto		},
+		{	"try",		TOK.TOKtry		},
+		{	"catch",	TOK.TOKcatch	},
+		{	"finally",	TOK.TOKfinally	},
+		{	"with",		TOK.TOKwith		},
+		{	"asm",		TOK.TOKasm		},
+		{	"foreach",	TOK.TOKforeach	},
+		{	"foreach_reverse",	TOK.TOKforeach_reverse	},
+		{	"scope",	TOK.TOKscope	},
+
+		{	"struct",	TOK.TOKstruct	},
+		{	"class",	TOK.TOKclass	},
+		{	"interface",	TOK.TOKinterface	},
+		{	"union",	TOK.TOKunion	},
+		{	"enum",		TOK.TOKenum		},
+		{	"import",	TOK.TOKimport	},
+		{	"mixin",	TOK.TOKmixin	},
+		{	"static",	TOK.TOKstatic	},
+		{	"final",	TOK.TOKfinal	},
+		{	"const",	TOK.TOKconst	},
+		{	"typedef",	TOK.TOKtypedef	},
+		{	"alias",	TOK.TOKalias	},
+		{	"override",	TOK.TOKoverride	},
+		{	"abstract",	TOK.TOKabstract	},
+		{	"volatile",	TOK.TOKvolatile	},
+		{	"debug",	TOK.TOKdebug	},
+		{	"deprecated",	TOK.TOKdeprecated	},
+		{	"in",		TOK.TOKin		},
+		{	"out",		TOK.TOKout		},
+		{	"inout",	TOK.TOKinout	},
+		{	"lazy",		TOK.TOKlazy		},
+		{	"auto",		TOK.TOKauto		},
+
+		{	"align",	TOK.TOKalign	},
+		{	"extern",	TOK.TOKextern	},
+		{	"private",	TOK.TOKprivate	},
+		{	"package",	TOK.TOKpackage	},
+		{	"protected",	TOK.TOKprotected	},
+		{	"public",	TOK.TOKpublic	},
+		{	"export",	TOK.TOKexport	},
+
+		{	"body",		TOK.TOKbody		},
+		{	"invariant",	TOK.TOKinvariant	},
+		{	"unittest",	TOK.TOKunittest	},
+		{	"version",	TOK.TOKversion	},
+		//{	"manifest",	TOK.TOKmanifest	},
+
+		// Added after 1.0
+		{	"ref",		TOK.TOKref		},
+		{	"macro",	TOK.TOKmacro	},
+		{	"pure",		TOK.TOKpure		},
+		{	"nothrow",	TOK.TOKnothrow	},
+		{	"__thread",	TOK.TOKtls		},
+		{	"__gshared",	TOK.TOKgshared	},
+		{	"__traits",	TOK.TOKtraits	},
+		{	"__overloadset", TOK.TOKoverloadset	},
+		{	"__FILE__",	TOK.TOKfile		},
+		{	"__LINE__",	TOK.TOKline		},
+		{	"shared",	TOK.TOKshared	},
+		{	"immutable",	TOK.TOKimmutable	},
+	];
+} else {
+	static Keyword[] keywords =
+	[
+	//    {	"",		TOK	},
+
+		{	"this",		TOK.TOKthis		},
+		{	"super",	TOK.TOKsuper	},
+		{	"assert",	TOK.TOKassert	},
+		{	"null",		TOK.TOKnull		},
+		{	"true",		TOK.TOKtrue		},
+		{	"false",	TOK.TOKfalse	},
+		{	"cast",		TOK.TOKcast		},
+		{	"new",		TOK.TOKnew		},
+		{	"delete",	TOK.TOKdelete	},
+		{	"throw",	TOK.TOKthrow	},
+		{	"module",	TOK.TOKmodule	},
+		{	"pragma",	TOK.TOKpragma	},
+		{	"typeof",	TOK.TOKtypeof	},
+		{	"typeid",	TOK.TOKtypeid	},
+
+		{	"template",	TOK.TOKtemplate	},
+
+		{	"void",		TOK.TOKvoid		},
+		{	"byte",		TOK.TOKint8		},
+		{	"ubyte",	TOK.TOKuns8		},
+		{	"short",	TOK.TOKint16	},
+		{	"ushort",	TOK.TOKuns16	},
+		{	"int",		TOK.TOKint32	},
+		{	"uint",		TOK.TOKuns32	},
+		{	"long",		TOK.TOKint64	},
+		{	"ulong",	TOK.TOKuns64	},
+		{	"cent",		TOK.TOKcent,	},
+		{	"ucent",	TOK.TOKucent,	},
+		{	"float",	TOK.TOKfloat32	},
+		{	"double",	TOK.TOKfloat64	},
+		{	"real",		TOK.TOKfloat80	},
+
+		{	"bool",		TOK.TOKbool		},
+		{	"char",		TOK.TOKchar		},
+		{	"wchar",	TOK.TOKwchar	},
+		{	"dchar",	TOK.TOKdchar	},
+
+		{	"ifloat",	TOK.TOKimaginary32	},
+		{	"idouble",	TOK.TOKimaginary64	},
+		{	"ireal",	TOK.TOKimaginary80	},
+
+		{	"cfloat",	TOK.TOKcomplex32	},
+		{	"cdouble",	TOK.TOKcomplex64	},
+		{	"creal",	TOK.TOKcomplex80	},
+
+		{	"delegate",	TOK.TOKdelegate	},
+		{	"function",	TOK.TOKfunction	},
+
+		{	"is",		TOK.TOKis		},
+		{	"if",		TOK.TOKif		},
+		{	"else",		TOK.TOKelse		},
+		{	"while",	TOK.TOKwhile	},
+		{	"for",		TOK.TOKfor		},
+		{	"do",		TOK.TOKdo		},
+		{	"switch",	TOK.TOKswitch	},
+		{	"case",		TOK.TOKcase		},
+		{	"default",	TOK.TOKdefault	},
+		{	"break",	TOK.TOKbreak	},
+		{	"continue",	TOK.TOKcontinue	},
+		{	"synchronized",	TOK.TOKsynchronized	},
+		{	"return",	TOK.TOKreturn	},
+		{	"goto",		TOK.TOKgoto		},
+		{	"try",		TOK.TOKtry		},
+		{	"catch",	TOK.TOKcatch	},
+		{	"finally",	TOK.TOKfinally	},
+		{	"with",		TOK.TOKwith		},
+		{	"asm",		TOK.TOKasm		},
+		{	"foreach",	TOK.TOKforeach	},
+		{	"foreach_reverse",	TOK.TOKforeach_reverse	},
+		{	"scope",	TOK.TOKscope	},
+
+		{	"struct",	TOK.TOKstruct	},
+		{	"class",	TOK.TOKclass	},
+		{	"interface",	TOK.TOKinterface	},
+		{	"union",	TOK.TOKunion	},
+		{	"enum",		TOK.TOKenum		},
+		{	"import",	TOK.TOKimport	},
+		{	"mixin",	TOK.TOKmixin	},
+		{	"static",	TOK.TOKstatic	},
+		{	"final",	TOK.TOKfinal	},
+		{	"const",	TOK.TOKconst	},
+		{	"typedef",	TOK.TOKtypedef	},
+		{	"alias",	TOK.TOKalias	},
+		{	"override",	TOK.TOKoverride	},
+		{	"abstract",	TOK.TOKabstract	},
+		{	"volatile",	TOK.TOKvolatile	},
+		{	"debug",	TOK.TOKdebug	},
+		{	"deprecated",	TOK.TOKdeprecated	},
+		{	"in",		TOK.TOKin		},
+		{	"out",		TOK.TOKout		},
+		{	"inout",	TOK.TOKinout	},
+		{	"lazy",		TOK.TOKlazy		},
+		{	"auto",		TOK.TOKauto		},
+
+		{	"align",	TOK.TOKalign	},
+		{	"extern",	TOK.TOKextern	},
+		{	"private",	TOK.TOKprivate	},
+		{	"package",	TOK.TOKpackage	},
+		{	"protected",	TOK.TOKprotected	},
+		{	"public",	TOK.TOKpublic	},
+		{	"export",	TOK.TOKexport	},
+
+		{	"body",		TOK.TOKbody		},
+		{	"invariant",	TOK.TOKinvariant	},
+		{	"unittest",	TOK.TOKunittest	},
+		{	"version",	TOK.TOKversion	},
+		//{	"manifest",	TOK.TOKmanifest	},
+
+		// Added after 1.0
+		{	"ref",		TOK.TOKref		},
+		{	"macro",	TOK.TOKmacro	},
+	];
+}
+
+	static ubyte cmtable[256];
+	enum CMoctal =	0x1;
+	enum  CMhex =	0x2;
+	enum  CMidchar =	0x4;
+	
+	ubyte isoctal (ubyte c) { return cmtable[c] & CMoctal; }
+	ubyte ishex   (ubyte c) { return cmtable[c] & CMhex; }
+	ubyte isidchar(ubyte c) { return cmtable[c] & CMidchar; }
+
+	static void cmtable_init()
+	{
+		for (uint c = 0; c < cmtable.length; c++)
+		{
+			if ('0' <= c && c <= '7')
+				cmtable[c] |= CMoctal;
+			if (isdigit(c) || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F'))
+				cmtable[c] |= CMhex;
+			if (isalnum(c) || c == '_')
+				cmtable[c] |= CMidchar;
+		}
+	}
+
+    static void initKeywords()
+	{
+		uint nkeywords = keywords.length;
+
+		if (global.params.Dversion == 1)
+			nkeywords -= 2;
+
+		cmtable_init();
+		
+		for (uint u = 0; u < nkeywords; u++)
+		{
+			//printf("keyword[%d] = '%s'\n",u, keywords[u].name);
+			string s = keywords[u].name;
+			TOK v = keywords[u].value;
+			StringValue* sv = stringtable.insert(s);
+			sv.ptrvalue = cast(void*) new Identifier(sv.lstring.string_, v);
+
+			//printf("tochars[%d] = '%s'\n",v, s);
+			Token.tochars[v] = s;
+		}
+
+		Token.tochars[TOK.TOKeof]		= "EOF";
+		Token.tochars[TOK.TOKlcurly]		= "{";
+		Token.tochars[TOK.TOKrcurly]		= "}";
+		Token.tochars[TOK.TOKlparen]		= "(";
+		Token.tochars[TOK.TOKrparen]		= ")";
+		Token.tochars[TOK.TOKlbracket]		= "[";
+		Token.tochars[TOK.TOKrbracket]		= "]";
+		Token.tochars[TOK.TOKsemicolon]	= ";";
+		Token.tochars[TOK.TOKcolon]		= ":";
+		Token.tochars[TOK.TOKcomma]		= ",";
+		Token.tochars[TOK.TOKdot]		= ".";
+		Token.tochars[TOK.TOKxor]		= "^";
+		Token.tochars[TOK.TOKxorass]		= "^=";
+		Token.tochars[TOK.TOKassign]		= "=";
+		Token.tochars[TOK.TOKconstruct]	= "=";
+version (DMDV2) {
+		Token.tochars[TOK.TOKblit]		= "=";
+}
+		Token.tochars[TOK.TOKlt]		= "<";
+		Token.tochars[TOK.TOKgt]		= ">";
+		Token.tochars[TOK.TOKle]		= "<=";
+		Token.tochars[TOK.TOKge]		= ">=";
+		Token.tochars[TOK.TOKequal]		= "==";
+		Token.tochars[TOK.TOKnotequal]		= "!=";
+		Token.tochars[TOK.TOKnotidentity]	= "!is";
+		Token.tochars[TOK.TOKtobool]		= "!!";
+
+		Token.tochars[TOK.TOKunord]		= "!<>=";
+		Token.tochars[TOK.TOKue]		= "!<>";
+		Token.tochars[TOK.TOKlg]		= "<>";
+		Token.tochars[TOK.TOKleg]		= "<>=";
+		Token.tochars[TOK.TOKule]		= "!>";
+		Token.tochars[TOK.TOKul]		= "!>=";
+		Token.tochars[TOK.TOKuge]		= "!<";
+		Token.tochars[TOK.TOKug]		= "!<=";
+
+		Token.tochars[TOK.TOKnot]		= "!";
+		Token.tochars[TOK.TOKtobool]		= "!!";
+		Token.tochars[TOK.TOKshl]		= "<<";
+		Token.tochars[TOK.TOKshr]		= ">>";
+		Token.tochars[TOK.TOKushr]		= ">>>";
+		Token.tochars[TOK.TOKadd]		= "+";
+		Token.tochars[TOK.TOKmin]		= "-";
+		Token.tochars[TOK.TOKmul]		= "*";
+		Token.tochars[TOK.TOKdiv]		= "/";
+		Token.tochars[TOK.TOKmod]		= "%";
+		Token.tochars[TOK.TOKslice]		= "..";
+		Token.tochars[TOK.TOKdotdotdot]	= "...";
+		Token.tochars[TOK.TOKand]		= "&";
+		Token.tochars[TOK.TOKandand]		= "&&";
+		Token.tochars[TOK.TOKor]		= "|";
+		Token.tochars[TOK.TOKoror]		= "||";
+		Token.tochars[TOK.TOKarray]		= "[]";
+		Token.tochars[TOK.TOKindex]		= "[i]";
+		Token.tochars[TOK.TOKaddress]		= "&";
+		Token.tochars[TOK.TOKstar]		= "*";
+		Token.tochars[TOK.TOKtilde]		= "~";
+		Token.tochars[TOK.TOKdollar]		= "$";
+		Token.tochars[TOK.TOKcast]		= "cast";
+		Token.tochars[TOK.TOKplusplus]		= "++";
+		Token.tochars[TOK.TOKminusminus]	= "--";
+		Token.tochars[TOK.TOKtype]		= "type";
+		Token.tochars[TOK.TOKquestion]		= "?";
+		Token.tochars[TOK.TOKneg]		= "-";
+		Token.tochars[TOK.TOKuadd]		= "+";
+		Token.tochars[TOK.TOKvar]		= "var";
+		Token.tochars[TOK.TOKaddass]		= "+=";
+		Token.tochars[TOK.TOKminass]		= "-=";
+		Token.tochars[TOK.TOKmulass]		= "*=";
+		Token.tochars[TOK.TOKdivass]		= "/=";
+		Token.tochars[TOK.TOKmodass]		= "%=";
+		Token.tochars[TOK.TOKshlass]		= "<<=";
+		Token.tochars[TOK.TOKshrass]		= ">>=";
+		Token.tochars[TOK.TOKushrass]		= ">>>=";
+		Token.tochars[TOK.TOKandass]		= "&=";
+		Token.tochars[TOK.TOKorass]		= "|=";
+		Token.tochars[TOK.TOKcatass]		= "~=";
+		Token.tochars[TOK.TOKcat]		= "~";
+		Token.tochars[TOK.TOKcall]		= "call";
+		Token.tochars[TOK.TOKidentity]		= "is";
+		Token.tochars[TOK.TOKnotidentity]	= "!is";
+
+		Token.tochars[TOK.TOKorass]		= "|=";
+		Token.tochars[TOK.TOKidentifier]	= "identifier";
+		Token.tochars[TOK.TOKat]		= "@";
+
+		 // For debugging
+		Token.tochars[TOK.TOKdotexp]		= "dotexp";
+		Token.tochars[TOK.TOKdotti]		= "dotti";
+		Token.tochars[TOK.TOKdotvar]		= "dotvar";
+		Token.tochars[TOK.TOKdottype]		= "dottype";
+		Token.tochars[TOK.TOKsymoff]		= "symoff";
+		Token.tochars[TOK.TOKarraylength]	= "arraylength";
+		Token.tochars[TOK.TOKarrayliteral]	= "arrayliteral";
+		Token.tochars[TOK.TOKassocarrayliteral] = "assocarrayliteral";
+		Token.tochars[TOK.TOKstructliteral]	= "structliteral";
+		Token.tochars[TOK.TOKstring]		= "string";
+		Token.tochars[TOK.TOKdsymbol]		= "symbol";
+		Token.tochars[TOK.TOKtuple]		= "tuple";
+		Token.tochars[TOK.TOKdeclaration]	= "declaration";
+		Token.tochars[TOK.TOKdottd]		= "dottd";
+		Token.tochars[TOK.TOKon_scope_exit]	= "scope(exit)";
+		Token.tochars[TOK.TOKon_scope_success]	= "scope(success)";
+		Token.tochars[TOK.TOKon_scope_failure]	= "scope(failure)";
+	}
+
+    static Identifier idPool(string s)
+	{
+		StringValue* sv = stringtable.update(s);
+		Identifier id = cast(Identifier) sv.ptrvalue;
+		if (id is null)
+		{
+			id = new Identifier(sv.lstring.string_, TOK.TOKidentifier);
+			sv.ptrvalue = cast(void*)id;
+		}
+
+		return id;
+	}
+
+    static Identifier uniqueId(string s)
+	{
+		static int num;
+		return uniqueId(s, ++num);
+	}
+
+	/*********************************************
+	 * Create a unique identifier using the prefix s.
+	 */
+    static Identifier uniqueId(string s, int num)
+	{
+		char buffer[32];
+		size_t slen = s.length;
+
+		assert(slen + num.sizeof * 3 + 1 <= buffer.sizeof);
+		int len = sprintf(buffer.ptr, "%.*s%d", s, num);
+
+		return idPool(buffer[0..len].idup);
+	}
+
+    TOK nextToken()
+	{
+		Token *t;
+
+		if (token.next)
+		{
+			t = token.next;
+			memcpy(&token, t, Token.sizeof);
+			t.next = freelist;
+			freelist = t;
+		}
+		else
+		{
+			scan(&token);
+		}
+
+		//token.print();
+		return token.value;
+	}
+
+	/***********************
+	 * Look ahead at next token's value.
+	 */
+    TOK peekNext()
+	{
+		return peek(&token).value;
+	}
+
+    TOK peekNext2()
+	{
+		assert(false);
+	}
+
+    void scan(Token* t)
+	{
+		uint lastLine = loc.linnum;
+		uint linnum;
+
+		t.blockComment = null;
+		t.lineComment = null;
+		while (1)
+		{
+			t.ptr = p;
+			//printf("p = %p, *p = '%c'\n",p,*p);
+			switch (*p)
+			{
+				case 0:
+				case 0x1A:
+				t.value = TOK.TOKeof;			// end of file
+				return;
+
+				case ' ':
+				case '\t':
+				case '\v':
+				case '\f':
+				p++;
+				continue;			// skip white space
+
+				case '\r':
+				p++;
+				if (*p != '\n')			// if CR stands by itself
+					loc.linnum++;
+				continue;			// skip white space
+
+				case '\n':
+				p++;
+				loc.linnum++;
+				continue;			// skip white space
+
+				case '0':  	case '1':   case '2':   case '3':   case '4':
+				case '5':  	case '6':   case '7':   case '8':   case '9':
+				t.value = number(t);
+				return;
+
+version (CSTRINGS) {
+				case '\'':
+				t.value = charConstant(t, 0);
+				return;
+
+				case '"':
+				t.value = stringConstant(t,0);
+				return;
+
+				case 'l':
+				case 'L':
+				if (p[1] == '\'')
+				{
+					p++;
+					t.value = charConstant(t, 1);
+					return;
+				}
+				else if (p[1] == '"')
+				{
+					p++;
+					t.value = stringConstant(t, 1);
+					return;
+				}
+} else {
+				case '\'':
+				t.value = charConstant(t,0);
+				return;
+
+				case 'r':
+				if (p[1] != '"')
+					goto case_ident;
+				p++;
+				case '`':
+				t.value = wysiwygStringConstant(t, *p);
+				return;
+
+				case 'x':
+				if (p[1] != '"')
+					goto case_ident;
+				p++;
+				t.value = hexStringConstant(t);
+				return;
+
+version (DMDV2) {
+				case 'q':
+				if (p[1] == '"')
+				{
+					p++;
+					t.value = delimitedStringConstant(t);
+					return;
+				}
+				else if (p[1] == '{')
+				{
+					p++;
+					t.value = tokenStringConstant(t);
+					return;
+				}
+				else
+					goto case_ident;
+}
+
+				case '"':
+				t.value = escapeStringConstant(t,0);
+				return;
+version (TEXTUAL_ASSEMBLY_OUT) {
+} else {
+				case '\\':			// escaped string literal
+				{	uint c;
+				ubyte* pstart = p;
+
+				stringbuffer.reset();
+				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);
+				char* cc = cast(char*)malloc(stringbuffer.offset);
+				memcpy(cc, stringbuffer.data, stringbuffer.offset);
+				t.ustring = cc;
+				t.postfix = 0;
+				t.value = TOK.TOKstring;
+				if (!global.params.useDeprecated)
+					error("Escape String literal %.*s is deprecated, use double quoted string literal \"%.*s\" instead", p - pstart, pstart, p - pstart, pstart);
+				return;
+				}
+}
+				case 'l':
+				case 'L':
+}
+				case 'a':  	case 'b':   case 'c':   case 'd':   case 'e':
+				case 'f':  	case 'g':   case 'h':   case 'i':   case 'j':
+				case 'k':  	            case 'm':   case 'n':   case 'o':
+version (DMDV2) {
+				case 'p':  	/*case 'q': case 'r':*/ case 's':   case 't':
+} else {
+				case 'p':  	case 'q': /*case 'r':*/ case 's':   case 't':
+}
+				case 'u':  	case 'v':   case 'w': /*case 'x':*/ case 'y':
+				case 'z':
+				case 'A':  	case 'B':   case 'C':   case 'D':   case 'E':
+				case 'F':  	case 'G':   case 'H':   case 'I':   case 'J':
+				case 'K':  	            case 'M':   case 'N':   case 'O':
+				case 'P':  	case 'Q':   case 'R':   case 'S':   case 'T':
+				case 'U':  	case 'V':   case 'W':   case 'X':   case 'Y':
+				case 'Z':
+				case '_':
+				case_ident:
+				{   ubyte c;
+				StringValue *sv;
+				Identifier id;
+
+				do
+				{
+					c = *++p;
+				} while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF())));
+				sv = stringtable.update((cast(immutable(char)*)t.ptr)[0.. p - t.ptr]);	///
+				id = cast(Identifier) sv.ptrvalue;
+				if (id is null)
+				{   id = new Identifier(sv.lstring.string_, TOK.TOKidentifier);
+					sv.ptrvalue = cast(void*)id;
+				}
+				t.ident = id;
+				t.value = cast(TOK) id.value;
+				anyToken = 1;
+				if (*t.ptr == '_')	// if special identifier token
+				{
+					static char date[11+1];
+					static char time[8+1];
+					static char timestamp[24+1];
+
+					if (!date[0])	// lazy evaluation
+					{   time_t tm;
+					char *p;
+
+					.time(&tm);
+					p = ctime(&tm);
+					assert(p);
+					sprintf(date.ptr, "%.6s %.4s", p + 4, p + 20);
+					sprintf(time.ptr, "%.8s", p + 11);
+					sprintf(timestamp.ptr, "%.24s", p);
+					}
+
+///version (DMDV1) {
+///					if (mod && id == Id.FILE)
+///					{
+///					t.ustring = cast(ubyte*)(loc.filename ? loc.filename : mod.ident.toChars());
+///					goto Lstr;
+///					}
+///					else if (mod && id == Id.LINE)
+///					{
+///					t.value = TOK.TOKint64v;
+///					t.uns64value = loc.linnum;
+///					}
+///					else
+///}
+					if (id == Id.DATE)
+					{
+					t.ustring = date.ptr;
+					goto Lstr;
+					}
+					else if (id == Id.TIME)
+					{
+					t.ustring = time.ptr;
+					goto Lstr;
+					}
+					else if (id == Id.VENDOR)
+					{
+					t.ustring = "Digital Mars D".ptr;
+					goto Lstr;
+					}
+					else if (id == Id.TIMESTAMP)
+					{
+					t.ustring = timestamp.ptr;
+					 Lstr:
+					t.value = TOK.TOKstring;
+					 Llen:
+					t.postfix = 0;
+					t.len = strlen(cast(char*)t.ustring);
+					}
+					else if (id == Id.VERSIONX)
+					{
+						uint major = 0;
+						uint minor = 0;
+
+						foreach (char cc; global.version_[1..$])
+						{
+							if (isdigit(cc))
+								minor = minor * 10 + cc - '0';
+							else if (cc == '.')
+							{
+								major = minor;
+								minor = 0;
+							}
+							else
+								break;
+						}
+						t.value = TOK.TOKint64v;
+						t.uns64value = major * 1000 + minor;
+					}
+///version (DMDV2) {
+					else if (id == Id.EOFX)
+					{
+					t.value = TOK.TOKeof;
+					// Advance scanner to end of file
+					while (!(*p == 0 || *p == 0x1A))
+						p++;
+					}
+///}
+				}
+				//printf("t.value = %d\n",t.value);
+				return;
+				}
+
+				case '/':
+				p++;
+				switch (*p)
+				{
+					case '=':
+						p++;
+						t.value = TOK.TOKdivass;
+						return;
+
+					case '*':
+						p++;
+						linnum = loc.linnum;
+						while (1)
+						{
+							while (1)
+							{
+								ubyte c = *p;
+								switch (c)
+								{
+									case '/':
+									break;
+
+									case '\n':
+									loc.linnum++;
+									p++;
+									continue;
+
+									case '\r':
+									p++;
+									if (*p != '\n')
+										loc.linnum++;
+									continue;
+
+									case 0:
+									case 0x1A:
+									error("unterminated /* */ comment");
+									p = end;
+									t.value = TOK.TOKeof;
+									return;
+
+									default:
+									if (c & 0x80)
+									{   uint u = decodeUTF();
+										if (u == PS || u == LS)
+										loc.linnum++;
+									}
+									p++;
+									continue;
+								}
+								break;
+							}
+							p++;
+							if (p[-2] == '*' && p - 3 != t.ptr)
+							break;
+						}
+						if (commentToken)
+						{
+							t.value = TOK.TOKcomment;
+							return;
+						}
+						else if (doDocComment && t.ptr[2] == '*' && p - 4 != t.ptr)
+						{   // if /** but not /**/
+							getDocComment(t, lastLine == linnum);
+						}
+						continue;
+
+					case '/':		// do // style comments
+						linnum = loc.linnum;
+						while (1)
+						{   ubyte c = *++p;
+							switch (c)
+							{
+							case '\n':
+								break;
+
+							case '\r':
+								if (p[1] == '\n')
+								p++;
+								break;
+
+							case 0:
+							case 0x1A:
+								if (commentToken)
+								{
+								p = end;
+								t.value = TOK.TOKcomment;
+								return;
+								}
+								if (doDocComment && t.ptr[2] == '/')
+								getDocComment(t, lastLine == linnum);
+								p = end;
+								t.value = TOK.TOKeof;
+								return;
+
+							default:
+								if (c & 0x80)
+								{   uint u = decodeUTF();
+								if (u == PS || u == LS)
+									break;
+								}
+								continue;
+							}
+							break;
+						}
+
+						if (commentToken)
+						{
+							p++;
+							loc.linnum++;
+							t.value = TOK.TOKcomment;
+							return;
+						}
+						if (doDocComment && t.ptr[2] == '/')
+							getDocComment(t, lastLine == linnum);
+
+						p++;
+						loc.linnum++;
+						continue;
+
+					case '+':
+					{
+						int nest;
+
+						linnum = loc.linnum;
+						p++;
+						nest = 1;
+						while (1)
+						{   ubyte c = *p;
+							switch (c)
+							{
+							case '/':
+								p++;
+								if (*p == '+')
+								{
+								p++;
+								nest++;
+								}
+								continue;
+
+							case '+':
+								p++;
+								if (*p == '/')
+								{
+								p++;
+								if (--nest == 0)
+									break;
+								}
+								continue;
+
+							case '\r':
+								p++;
+								if (*p != '\n')
+								loc.linnum++;
+								continue;
+
+							case '\n':
+								loc.linnum++;
+								p++;
+								continue;
+
+							case 0:
+							case 0x1A:
+								error("unterminated /+ +/ comment");
+								p = end;
+								t.value = TOK.TOKeof;
+								return;
+
+							default:
+								if (c & 0x80)
+								{   uint u = decodeUTF();
+								if (u == PS || u == LS)
+									loc.linnum++;
+								}
+								p++;
+								continue;
+							}
+							break;
+						}
+						if (commentToken)
+						{
+							t.value = TOK.TOKcomment;
+							return;
+						}
+						if (doDocComment && t.ptr[2] == '+' && p - 4 != t.ptr)
+						{   // if /++ but not /++/
+							getDocComment(t, lastLine == linnum);
+						}
+						continue;
+					}
+					
+					default:
+						break;	///
+				}
+				t.value = TOK.TOKdiv;
+				return;
+
+				case '.':
+				p++;
+				if (isdigit(*p))
+				{   /* Note that we don't allow ._1 and ._ as being
+					 * valid floating point numbers.
+					 */
+					p--;
+					t.value = inreal(t);
+				}
+				else if (p[0] == '.')
+				{
+					if (p[1] == '.')
+					{   p += 2;
+					t.value = TOK.TOKdotdotdot;
+					}
+					else
+					{   p++;
+					t.value = TOK.TOKslice;
+					}
+				}
+				else
+					t.value = TOK.TOKdot;
+				return;
+
+				case '&':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKandass;
+				}
+				else if (*p == '&')
+				{   p++;
+					t.value = TOK.TOKandand;
+				}
+				else
+					t.value = TOK.TOKand;
+				return;
+
+				case '|':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKorass;
+				}
+				else if (*p == '|')
+				{   p++;
+					t.value = TOK.TOKoror;
+				}
+				else
+					t.value = TOK.TOKor;
+				return;
+
+				case '-':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKminass;
+				}
+///		#if 0
+///				else if (*p == '>')
+///				{   p++;
+///					t.value = TOK.TOKarrow;
+///				}
+///		#endif
+				else if (*p == '-')
+				{   p++;
+					t.value = TOK.TOKminusminus;
+				}
+				else
+					t.value = TOK.TOKmin;
+				return;
+
+				case '+':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKaddass;
+				}
+				else if (*p == '+')
+				{   p++;
+					t.value = TOK.TOKplusplus;
+				}
+				else
+					t.value = TOK.TOKadd;
+				return;
+
+				case '<':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKle;			// <=
+				}
+				else if (*p == '<')
+				{   p++;
+					if (*p == '=')
+					{   p++;
+					t.value = TOK.TOKshlass;		// <<=
+					}
+					else
+					t.value = TOK.TOKshl;		// <<
+				}
+				else if (*p == '>')
+				{   p++;
+					if (*p == '=')
+					{   p++;
+					t.value = TOK.TOKleg;		// <>=
+					}
+					else
+					t.value = TOK.TOKlg;		// <>
+				}
+				else
+					t.value = TOK.TOKlt;			// <
+				return;
+
+				case '>':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKge;			// >=
+				}
+				else if (*p == '>')
+				{   p++;
+					if (*p == '=')
+					{   p++;
+					t.value = TOK.TOKshrass;		// >>=
+					}
+					else if (*p == '>')
+					{	p++;
+					if (*p == '=')
+					{   p++;
+						t.value = TOK.TOKushrass;	// >>>=
+					}
+					else
+						t.value = TOK.TOKushr;		// >>>
+					}
+					else
+					t.value = TOK.TOKshr;		// >>
+				}
+				else
+					t.value = TOK.TOKgt;			// >
+				return;
+
+				case '!':
+				p++;
+				if (*p == '=')
+				{   p++;
+					if (*p == '=' && global.params.Dversion == 1)
+					{	p++;
+					t.value = TOK.TOKnotidentity;	// !==
+					}
+					else
+					t.value = TOK.TOKnotequal;		// !=
+				}
+				else if (*p == '<')
+				{   p++;
+					if (*p == '>')
+					{	p++;
+					if (*p == '=')
+					{   p++;
+						t.value = TOK.TOKunord; // !<>=
+					}
+					else
+						t.value = TOK.TOKue;	// !<>
+					}
+					else if (*p == '=')
+					{	p++;
+					t.value = TOK.TOKug;	// !<=
+					}
+					else
+					t.value = TOK.TOKuge;	// !<
+				}
+				else if (*p == '>')
+				{   p++;
+					if (*p == '=')
+					{	p++;
+					t.value = TOK.TOKul;	// !>=
+					}
+					else
+					t.value = TOK.TOKule;	// !>
+				}
+				else
+					t.value = TOK.TOKnot;		// !
+				return;
+
+				case '=':
+				p++;
+				if (*p == '=')
+				{   p++;
+					if (*p == '=' && global.params.Dversion == 1)
+					{	p++;
+					t.value = TOK.TOKidentity;		// ===
+					}
+					else
+					t.value = TOK.TOKequal;		// ==
+				}
+				else
+					t.value = TOK.TOKassign;		// =
+				return;
+
+				case '~':
+				p++;
+				if (*p == '=')
+				{   p++;
+					t.value = TOK.TOKcatass;		// ~=
+				}
+				else
+					t.value = TOK.TOKtilde;		// ~
+				return;
+/*
+		#define SINGLE(c,tok) case c: p++; t.value = tok; return;
+
+				SINGLE('(',	TOKlparen)
+				SINGLE(')', TOKrparen)
+				SINGLE('[', TOKlbracket)
+				SINGLE(']', TOKrbracket)
+				SINGLE('{', TOKlcurly)
+				SINGLE('}', TOKrcurly)
+				SINGLE('?', TOKquestion)
+				SINGLE(',', TOKcomma)
+				SINGLE(';', TOKsemicolon)
+				SINGLE(':', TOKcolon)
+				SINGLE('$', TOKdollar)
+				SINGLE('@', TOKat)
+
+		#undef SINGLE
+
+		#define DOUBLE(c1,tok1,c2,tok2)		\
+				case c1:			\
+				p++;			\
+				if (*p == c2)		\
+				{   p++;		\
+					t.value = tok2;	\
+				}			\
+				else			\
+					t.value = tok1;	\
+				return;
+
+				DOUBLE('*', TOKmul, '=', TOKmulass)
+				DOUBLE('%', TOKmod, '=', TOKmodass)
+				DOUBLE('^', TOKxor, '=', TOKxorass)
+
+		#undef DOUBLE
+*/
+
+				case '(': p++; t.value = TOK.TOKlparen; return;
+				case ')': p++; t.value = TOK.TOKrparen; return;
+				case '[': p++; t.value = TOK.TOKlbracket; return;
+				case ']': p++; t.value = TOK.TOKrbracket; return;
+				case '{': p++; t.value = TOK.TOKlcurly; return;
+				case '}': p++; t.value = TOK.TOKrcurly; return;
+				case '?': p++; t.value = TOK.TOKquestion; return;
+				case ',': p++; t.value = TOK.TOKcomma; return;
+				case ';': p++; t.value = TOK.TOKsemicolon; return;
+				case ':': p++; t.value = TOK.TOKcolon; return;
+				case '$': p++; t.value = TOK.TOKdollar; return;
+				case '@': p++; t.value = TOK.TOKat; return;
+
+				case '*':
+					p++;
+					if (*p == '=') {
+						p++;
+						t.value = TOK.TOKmulass;
+					} else {
+						t.value = TOK.TOKmul;
+					}
+					return;
+					
+				case '%':
+					p++;
+					if (*p == '=') {
+						p++;
+						t.value = TOK.TOKmodass;
+					} else {
+						t.value = TOK.TOKmod;
+					}
+					return;
+					
+				case '^':
+					p++;
+					if (*p == '=') {
+						p++;
+						t.value = TOK.TOKxorass;
+					} else {
+						t.value = TOK.TOKxor;
+					}
+					return;
+
+				case '#':
+				p++;
+				pragma_();
+				continue;
+
+				default:
+				{	ubyte c = *p;
+
+				if (c & 0x80)
+				{   uint u = decodeUTF();
+
+					// Check for start of unicode identifier
+					if (isUniAlpha(u))
+					goto case_ident;
+
+					if (u == PS || u == LS)
+					{
+					loc.linnum++;
+					p++;
+					continue;
+					}
+				}
+				if (isprint(c))
+					error("unsupported char '%c'", c);
+				else
+					error("unsupported char 0x%02x", c);
+				p++;
+				continue;
+				}
+			}
+		}
+	}
+
+    Token* peek(Token* ct)
+	{
+		Token* t;
+
+		if (ct.next)
+			t = ct.next;
+		else
+		{
+			t = new Token();
+			scan(t);
+			t.next = null;
+			ct.next = t;
+		}
+		return t;
+	}
+
+    Token* peekPastParen(Token* tk)
+	{
+		//printf("peekPastParen()\n");
+		int parens = 1;
+		int curlynest = 0;
+		while (1)
+		{
+			tk = peek(tk);
+			//tk.print();
+			switch (tk.value)
+			{
+				case TOK.TOKlparen:
+				parens++;
+				continue;
+
+				case TOK.TOKrparen:
+				--parens;
+				if (parens)
+					continue;
+				tk = peek(tk);
+				break;
+
+				case TOK.TOKlcurly:
+				curlynest++;
+				continue;
+
+				case TOK.TOKrcurly:
+				if (--curlynest >= 0)
+					continue;
+				break;
+
+				case TOK.TOKsemicolon:
+				if (curlynest)
+					continue;
+				break;
+
+				case TOK.TOKeof:
+				break;
+
+				default:
+				continue;
+			}
+			return tk;
+		}
+	}
+
+	/*******************************************
+	 * Parse escape sequence.
+	 */
+    uint escapeSequence()
+	{
+		uint c = *p;
+
+	version (TEXTUAL_ASSEMBLY_OUT) {
+		return c;
+	}
+		int n;
+		int ndigits;
+
+		switch (c)
+		{
+			case '\'':
+			case '"':
+			case '?':
+			case '\\':
+			Lconsume:
+				p++;
+				break;
+
+			case 'a':	c = 7;		goto Lconsume;
+			case 'b':	c = 8;		goto Lconsume;
+			case 'f':	c = 12;		goto Lconsume;
+			case 'n':	c = 10;		goto Lconsume;
+			case 'r':	c = 13;		goto Lconsume;
+			case 't':	c = 9;		goto Lconsume;
+			case 'v':	c = 11;		goto Lconsume;
+
+			case 'u':
+				ndigits = 4;
+				goto Lhex;
+			case 'U':
+				ndigits = 8;
+				goto Lhex;
+			case 'x':
+				ndigits = 2;
+			Lhex:
+				p++;
+				c = *p;
+				if (ishex(cast(ubyte)c))
+				{   
+					uint v;
+
+					n = 0;
+					v = 0;
+					while (1)
+					{
+					if (isdigit(c))
+						c -= '0';
+					else if (islower(c))
+						c -= 'a' - 10;
+					else
+						c -= 'A' - 10;
+					v = v * 16 + c;
+					c = *++p;
+					if (++n == ndigits)
+						break;
+					if (!ishex(cast(ubyte)c))
+					{   error("escape hex sequence has %d hex digits instead of %d", n, ndigits);
+						break;
+					}
+					}
+					if (ndigits != 2 && !utf_isValidDchar(v))
+					{	error("invalid UTF character \\U%08x", v);
+					v = '?';	// recover with valid UTF character
+					}
+					c = v;
+				}
+				else
+					error("undefined escape hex sequence \\%c\n",c);
+				break;
+
+			case '&':			// named character entity
+				for (ubyte* idstart = ++p; true; p++)
+				{
+					switch (*p)
+					{
+					case ';':
+						c = HtmlNamedEntity(idstart, p - idstart);
+						if (c == ~0)
+						{   
+							error("unnamed character entity &%s;", idstart[0..(p - idstart)]);
+							c = ' ';
+						}
+						p++;
+						break;
+
+					default:
+						if (isalpha(*p) ||
+						(p != idstart + 1 && isdigit(*p)))
+						continue;
+						error("unterminated named entity");
+						break;
+					}
+					break;
+				}
+				break;
+
+			case 0:
+			case 0x1A:			// end of file
+				c = '\\';
+				break;
+
+			default:
+				if (isoctal(cast(ubyte)c))
+				{   
+					uint v;
+
+					n = 0;
+					v = 0;
+					do
+					{
+					v = v * 8 + (c - '0');
+					c = *++p;
+					} while (++n < 3 && isoctal(cast(ubyte)c));
+					c = v;
+					if (c > 0xFF)
+					error("0%03o is larger than a byte", c);
+				}
+				else
+					error("undefined escape sequence \\%c\n",c);
+				break;
+		}
+		return c;
+	}
+
+    TOK wysiwygStringConstant(Token* t, int tc)
+	{
+		assert(false);
+	}
+
+    TOK hexStringConstant(Token* t)
+	{
+		assert(false);
+	}
+
+version (DMDV2) {
+    TOK delimitedStringConstant(Token* t)
+	{
+		assert(false);
+	}
+
+    TOK tokenStringConstant(Token* t)
+	{
+		assert(false);
+	}
+}
+    TOK escapeStringConstant(Token* t, int wide)
+	{
+		uint c;
+		Loc start = loc;
+
+		p++;
+		stringbuffer.reset();
+		while (true)
+		{
+			c = *p++;
+			switch (c)
+			{
+		version (TEXTUAL_ASSEMBLY_OUT) {
+		} else {
+				case '\\':
+					switch (*p)
+					{
+						case 'u':
+						case 'U':
+						case '&':
+						c = escapeSequence();
+						stringbuffer.writeUTF8(c);
+						continue;
+
+						default:
+						c = escapeSequence();
+						break;
+					}
+					break;
+		}
+				case '\n':
+					loc.linnum++;
+					break;
+
+				case '\r':
+					if (*p == '\n')
+						continue;	// ignore
+					c = '\n';	// treat EndOfLine as \n character
+					loc.linnum++;
+					break;
+
+				case '"':
+					t.len = stringbuffer.offset;
+					stringbuffer.writeByte(0);
+					char* tmp = cast(char*)malloc(stringbuffer.offset);
+					memcpy(tmp, stringbuffer.data, stringbuffer.offset);
+					t.ustring = tmp;
+					stringPostfix(t);
+					return TOK.TOKstring;
+
+				case 0:
+				case 0x1A:
+					p--;
+					error("unterminated string constant starting at %s", start.toChars());
+					t.ustring = "".ptr;
+					t.len = 0;
+					t.postfix = 0;
+					return TOK.TOKstring;
+
+				default:
+					if (c & 0x80)
+					{
+						p--;
+						c = decodeUTF();
+						if (c == LS || c == PS)
+						{	c = '\n';
+						loc.linnum++;
+						}
+						p++;
+						stringbuffer.writeUTF8(c);
+						continue;
+					}
+					break;
+			}
+			stringbuffer.writeByte(c);
+		}
+		
+		assert(false);
+	}
+
+    TOK charConstant(Token* t, int wide)
+	{
+		uint c;
+		TOK tk = TOKcharv;
+
+		//printf("Lexer.charConstant\n");
+		p++;
+		c = *p++;
+		switch (c)
+		{
+		version (TEXTUAL_ASSEMBLY_OUT) {
+		} else {
+			case '\\':
+				switch (*p)
+				{
+				case 'u':
+					t.uns64value = escapeSequence();
+					tk = TOKwcharv;
+					break;
+
+				case 'U':
+				case '&':
+					t.uns64value = escapeSequence();
+					tk = TOKdcharv;
+					break;
+
+				default:
+					t.uns64value = escapeSequence();
+					break;
+				}
+				break;
+		}
+			case '\n':
+			L1:
+				loc.linnum++;
+			case '\r':
+			case 0:
+			case 0x1A:
+			case '\'':
+				error("unterminated character constant");
+				return tk;
+
+			default:
+				if (c & 0x80)
+				{
+					p--;
+					c = decodeUTF();
+					p++;
+					if (c == LS || c == PS)
+						goto L1;
+					if (c < 0xD800 || (c >= 0xE000 && c < 0xFFFE))
+						tk = TOKwcharv;
+					else
+						tk = TOKdcharv;
+				}
+				t.uns64value = c;
+				break;
+		}
+
+		if (*p != '\'')
+		{	
+			error("unterminated character constant");
+			return tk;
+		}
+		p++;
+		return tk;
+	}
+
+	/***************************************
+	 * Get postfix of string literal.
+	 */
+    void stringPostfix(Token* t)
+	{
+		switch (*p)
+		{
+			case 'c':
+			case 'w':
+			case 'd':
+				t.postfix = *p;
+				p++;
+				break;
+
+			default:
+				t.postfix = 0;
+				break;
+		}
+	}
+
+    uint wchar_(uint u)
+	{
+		assert(false);
+	}
+	
+	/**************************************
+	 * Read in a number.
+	 * If it's an integer, store it in tok.TKutok.Vlong.
+	 *	integers can be decimal, octal or hex
+	 *	Handle the suffixes U, UL, LU, L, etc.
+	 * If it's double, store it in tok.TKutok.Vdouble.
+	 * Returns:
+	 *	TKnum
+	 *	TKdouble,...
+	 */
+
+    TOK number(Token* t)
+	{
+		// We use a state machine to collect numbers
+		enum STATE { STATE_initial, STATE_0, STATE_decimal, STATE_octal, STATE_octale,
+		STATE_hex, STATE_binary, STATE_hex0, STATE_binary0,
+		STATE_hexh, STATE_error };
+		STATE state;
+
+		enum FLAGS
+		{
+			FLAGS_undefined = 0,
+			FLAGS_decimal  = 1,		// decimal
+			FLAGS_unsigned = 2,		// u or U suffix
+			FLAGS_long     = 4,		// l or L suffix
+		};
+		
+		FLAGS flags = FLAGS.FLAGS_decimal;
+
+		int i;
+		int base;
+		uint c;
+		ubyte *start;
+		TOK result;
+
+		//printf("Lexer.number()\n");
+		state = STATE.STATE_initial;
+		base = 0;
+		stringbuffer.reset();
+		start = p;
+		while (1)
+		{
+		c = *p;
+		switch (state)
+		{
+			case STATE.STATE_initial:		// opening state
+			if (c == '0')
+				state = STATE.STATE_0;
+			else
+				state = STATE.STATE_decimal;
+			break;
+
+			case STATE.STATE_0:
+			flags = (flags & ~FLAGS.FLAGS_decimal);
+			switch (c)
+			{
+version (ZEROH) {
+				case 'H':			// 0h
+				case 'h':
+				goto hexh;
+}
+				case 'X':
+				case 'x':
+				state = STATE.STATE_hex0;
+				break;
+
+				case '.':
+				if (p[1] == '.')	// .. is a separate token
+					goto done;
+				case 'i':
+				case 'f':
+				case 'F':
+				goto real_;
+version (ZEROH) {
+				case 'E':
+				case 'e':
+				goto case_hex;
+}
+				case 'B':
+				case 'b':
+				state = STATE.STATE_binary0;
+				break;
+
+				case '0': case '1': case '2': case '3':
+				case '4': case '5': case '6': case '7':
+				state = STATE.STATE_octal;
+				break;
+
+version (ZEROH) {
+				case '8': case '9': case 'A':
+				case 'C': case 'D': case 'F':
+				case 'a': case 'c': case 'd': case 'f':
+				case_hex:
+				state = STATE.STATE_hexh;
+				break;
+}
+				case '_':
+				state = STATE.STATE_octal;
+				p++;
+				continue;
+
+				case 'L':
+				if (p[1] == 'i')
+					goto real_;
+				goto done;
+
+				default:
+				goto done;
+			}
+			break;
+
+			case STATE.STATE_decimal:		// reading decimal number
+			if (!isdigit(c))
+			{
+version (ZEROH) {
+				if (ishex(c)
+				|| c == 'H' || c == 'h'
+				   )
+				goto hexh;
+}
+				if (c == '_')		// ignore embedded _
+				{	p++;
+				continue;
+				}
+				if (c == '.' && p[1] != '.')
+				goto real_;
+				else if (c == 'i' || c == 'f' || c == 'F' ||
+					 c == 'e' || c == 'E')
+				{
+			real_:	// It's a real number. Back up and rescan as a real
+				p = start;
+				return inreal(t);
+				}
+				else if (c == 'L' && p[1] == 'i')
+				goto real_;
+				goto done;
+			}
+			break;
+
+			case STATE.STATE_hex0:		// reading hex number
+			case STATE.STATE_hex:
+			if (! ishex(cast(ubyte)c))
+			{
+				if (c == '_')		// ignore embedded _
+				{	p++;
+				continue;
+				}
+				if (c == '.' && p[1] != '.')
+				goto real_;
+				if (c == 'P' || c == 'p' || c == 'i')
+				goto real_;
+				if (state == STATE.STATE_hex0)
+				error("Hex digit expected, not '%c'", c);
+				goto done;
+			}
+			state = STATE.STATE_hex;
+			break;
+
+version (ZEROH) {
+			hexh:
+			state = STATE.STATE_hexh;
+			case STATE.STATE_hexh:		// parse numbers like 0FFh
+			if (!ishex(c))
+			{
+				if (c == 'H' || c == 'h')
+				{
+				p++;
+				base = 16;
+				goto done;
+				}
+				else
+				{
+				// Check for something like 1E3 or 0E24
+				if (memchr(cast(char*)stringbuffer.data, 'E', stringbuffer.offset) ||
+					memchr(cast(char*)stringbuffer.data, 'e', stringbuffer.offset))
+					goto real_;
+				error("Hex digit expected, not '%c'", c);
+				goto done;
+				}
+			}
+			break;
+}
+
+			case STATE.STATE_octal:		// reading octal number
+			case STATE.STATE_octale:		// reading octal number with non-octal digits
+			if (!isoctal(cast(ubyte)c))
+			{
+version (ZEROH) {
+				if (ishex(c)
+				|| c == 'H' || c == 'h'
+				   )
+				goto hexh;
+}
+				if (c == '_')		// ignore embedded _
+				{	p++;
+				continue;
+				}
+				if (c == '.' && p[1] != '.')
+				goto real_;
+				if (c == 'i')
+				goto real_;
+				if (isdigit(c))
+				{
+				state = STATE.STATE_octale;
+				}
+				else
+				goto done;
+			}
+			break;
+
+			case STATE.STATE_binary0:		// starting binary number
+			case STATE.STATE_binary:		// reading binary number
+			if (c != '0' && c != '1')
+			{
+version (ZEROH) {
+				if (ishex(c)
+				|| c == 'H' || c == 'h'
+				   )
+				goto hexh;
+}
+				if (c == '_')		// ignore embedded _
+				{	p++;
+				continue;
+				}
+				if (state == STATE.STATE_binary0)
+				{	error("binary digit expected");
+				state = STATE.STATE_error;
+				break;
+				}
+				else
+				goto done;
+			}
+			state = STATE.STATE_binary;
+			break;
+
+			case STATE.STATE_error:		// for error recovery
+			if (!isdigit(c))	// scan until non-digit
+				goto done;
+			break;
+
+			default:
+			assert(0);
+		}
+		stringbuffer.writeByte(c);
+		p++;
+		}
+	done:
+		stringbuffer.writeByte(0);		// terminate string
+		if (state == STATE.STATE_octale)
+		error("Octal digit expected");
+
+		ulong n;			// unsigned >=64 bit integer type
+
+		if (stringbuffer.offset == 2 && (state == STATE.STATE_decimal || state == STATE.STATE_0))
+		n = stringbuffer.data[0] - '0';
+		else
+		{
+		// Convert string to integer
+version (__DMC__) {
+		errno = 0;
+		n = strtoull(cast(char*)stringbuffer.data,null,base);
+		if (errno == ERANGE)
+			error("integer overflow");
+} else {
+		// Not everybody implements strtoull()
+		char* p = cast(char*)stringbuffer.data;
+		int r = 10, d;
+
+		if (*p == '0')
+		{
+			if (p[1] == 'x' || p[1] == 'X')
+			p += 2, r = 16;
+			else if (p[1] == 'b' || p[1] == 'B')
+			p += 2, r = 2;
+			else if (isdigit(p[1]))
+			p += 1, r = 8;
+		}
+
+		n = 0;
+		while (1)
+		{
+			if (*p >= '0' && *p <= '9')
+			d = *p - '0';
+			else if (*p >= 'a' && *p <= 'z')
+			d = *p - 'a' + 10;
+			else if (*p >= 'A' && *p <= 'Z')
+			d = *p - 'A' + 10;
+			else
+			break;
+			if (d >= r)
+			break;
+			ulong n2 = n * r;
+			//printf("n2 / r = %llx, n = %llx\n", n2/r, n);
+			if (n2 / r != n || n2 + d < n)
+			{
+			error ("integer overflow");
+			break;
+			}
+
+			n = n2 + d;
+			p++;
+		}
+}
+		if (n.sizeof > 8 &&
+			n > 0xFFFFFFFFFFFFFFFF)	// if n needs more than 64 bits
+			error("integer overflow");
+		}
+
+		// Parse trailing 'u', 'U', 'l' or 'L' in any combination
+		while (1)
+		{   FLAGS f;
+
+		switch (*p)
+		{   case 'U':
+			case 'u':
+			f = FLAGS.FLAGS_unsigned;
+			goto L1;
+
+			case 'l':
+			if (1 || !global.params.useDeprecated)
+				error("'l' suffix is deprecated, use 'L' instead");
+			case 'L':
+			f = FLAGS.FLAGS_long;
+			L1:
+			p++;
+			if (flags & f)
+				error("unrecognized token");
+			flags = (flags | f);
+			continue;
+			default:
+			break;
+		}
+		break;
+		}
+
+		switch (flags)
+		{
+		case FLAGS.FLAGS_undefined:
+			/* Octal or Hexadecimal constant.
+			 * First that fits: int, uint, long, ulong
+			 */
+			if (n & 0x8000000000000000)
+				result = TOK.TOKuns64v;
+			else if (n & 0xFFFFFFFF00000000)
+				result = TOK.TOKint64v;
+			else if (n & 0x80000000)
+				result = TOK.TOKuns32v;
+			else
+				result = TOK.TOKint32v;
+			break;
+
+		case FLAGS.FLAGS_decimal:
+			/* First that fits: int, long, long long
+			 */
+			if (n & 0x8000000000000000)
+			{	    error("signed integer overflow");
+				result = TOK.TOKuns64v;
+			}
+			else if (n & 0xFFFFFFFF80000000)
+				result = TOK.TOKint64v;
+			else
+				result = TOK.TOKint32v;
+			break;
+
+		case FLAGS.FLAGS_unsigned:
+		case FLAGS.FLAGS_decimal | FLAGS.FLAGS_unsigned:
+			/* First that fits: uint, ulong
+			 */
+			if (n & 0xFFFFFFFF00000000)
+				result = TOK.TOKuns64v;
+			else
+				result = TOK.TOKuns32v;
+			break;
+
+		case FLAGS.FLAGS_decimal | FLAGS.FLAGS_long:
+			if (n & 0x8000000000000000)
+			{	    error("signed integer overflow");
+				result = TOK.TOKuns64v;
+			}
+			else
+				result = TOK.TOKint64v;
+			break;
+
+		case FLAGS.FLAGS_long:
+			if (n & 0x8000000000000000)
+				result = TOK.TOKuns64v;
+			else
+				result = TOK.TOKint64v;
+			break;
+
+		case FLAGS.FLAGS_unsigned | FLAGS.FLAGS_long:
+		case FLAGS.FLAGS_decimal | FLAGS.FLAGS_unsigned | FLAGS.FLAGS_long:
+			result = TOK.TOKuns64v;
+			break;
+
+		default:
+debug {
+			printf("%x\n",flags);
+}
+			assert(0);
+		}
+		t.uns64value = n;
+		return result;
+	}
+
+	/**************************************
+	 * Read in characters, converting them to real.
+	 * Bugs:
+	 *	Exponent overflow not detected.
+	 *	Too much requested precision is not detected.
+	 */
+    TOK inreal(Token* t)
+	in
+	{
+		assert(*p == '.' || isdigit(*p));
+	}
+	out (result)
+	{
+		switch (result)
+		{
+			case TOKfloat32v:
+			case TOKfloat64v:
+			case TOKfloat80v:
+			case TOKimaginary32v:
+			case TOKimaginary64v:
+			case TOKimaginary80v:
+				break;
+
+			default:
+				assert(0);
+		}
+	}
+	body
+	{
+		int dblstate;
+		uint c;
+		char hex;			// is this a hexadecimal-floating-constant?
+		TOK result;
+
+		//printf("Lexer.inreal()\n");
+		stringbuffer.reset();
+		dblstate = 0;
+		hex = 0;
+	Lnext:
+		while (true)
+		{
+			// Get next char from input
+			c = *p++;
+			//printf("dblstate = %d, c = '%c'\n", dblstate, c);
+			while (true)
+			{
+				switch (dblstate)
+				{
+					case 0:			// opening state
+						if (c == '0')
+						dblstate = 9;
+						else if (c == '.')
+						dblstate = 3;
+						else
+						dblstate = 1;
+						break;
+
+					case 9:
+						dblstate = 1;
+						if (c == 'X' || c == 'x')
+						{	
+							hex++;
+							break;
+						}
+					case 1:			// digits to left of .
+					case 3:			// digits to right of .
+					case 7:			// continuing exponent digits
+						if (!isdigit(c) && !(hex && isxdigit(c)))
+						{
+							if (c == '_')
+								goto Lnext;	// ignore embedded '_'
+							dblstate++;
+							continue;
+						}
+						break;
+
+					case 2:			// no more digits to left of .
+						if (c == '.')
+						{   
+							dblstate++;
+							break;
+						}
+					case 4:			// no more digits to right of .
+						if ((c == 'E' || c == 'e') ||
+							hex && (c == 'P' || c == 'p'))
+						{   
+							dblstate = 5;
+							hex = 0;	// exponent is always decimal
+							break;
+						}
+						if (hex)
+							error("binary-exponent-part required");
+						goto done;
+
+					case 5:			// looking immediately to right of E
+						dblstate++;
+						if (c == '-' || c == '+')
+							break;
+					case 6:			// 1st exponent digit expected
+						if (!isdigit(c))
+							error("exponent expected");
+						dblstate++;
+						break;
+
+					case 8:			// past end of exponent digits
+						goto done;
+				}
+				break;
+			}
+			stringbuffer.writeByte(c);
+		}
+	done:
+		p--;
+
+		stringbuffer.writeByte(0);
+
+	version (_WIN32) { /// && __DMC__
+		char* save = __locale_decpoint;
+		__locale_decpoint = cast(char*)".".ptr;
+	}
+		t.float80value = strtold(cast(char*)stringbuffer.data, null);
+
+		errno = 0;
+		switch (*p)
+		{
+		case 'F':
+		case 'f':
+			strtof(cast(char*)stringbuffer.data, null);
+			result = TOKfloat32v;
+			p++;
+			break;
+
+		default:
+			strtod(cast(char*)stringbuffer.data, null);
+			result = TOKfloat64v;
+			break;
+
+		case 'l':
+			if (!global.params.useDeprecated)
+				error("'l' suffix is deprecated, use 'L' instead");
+		case 'L':
+			result = TOKfloat80v;
+			p++;
+			break;
+		}
+		if (*p == 'i' || *p == 'I')
+		{
+			if (!global.params.useDeprecated && *p == 'I')
+				error("'I' suffix is deprecated, use 'i' instead");
+			p++;
+			switch (result)
+			{
+				case TOKfloat32v:
+					result = TOKimaginary32v;
+					break;
+				case TOKfloat64v:
+					result = TOKimaginary64v;
+					break;
+				case TOKfloat80v:
+					result = TOKimaginary80v;
+					break;
+			}
+		}
+		
+	version (_WIN32) { ///&& __DMC__
+		__locale_decpoint = save;
+	}
+		if (errno == ERANGE)
+			error("number is not representable");
+
+		return result;
+	}
+
+	void error(T...)(string format, T t)
+	{
+		error(this.loc, format, t);
+	}
+
+    void error(T...)(Loc loc, string format, T t)
+	{
+		if (mod && !global.gag)
+		{
+			string p = loc.toChars();
+			if (p.length != 0)
+				writef("%s: ", p);
+
+			writefln(format, t);
+
+			if (global.errors >= 20)	// moderate blizzard of cascading messages
+				fatal();
+		}
+
+		global.errors++;
+	}
+	
+    void pragma_()
+	{
+		assert(false);
+	}
+
+    uint decodeUTF()
+	{
+		assert(false);
+	}
+
+    void getDocComment(Token* t, uint lineComment)
+	{
+		assert(false);
+	}
+
+    static bool isValidIdentifier(string p)
+	{
+		if (p.length == 0) {
+			return false;
+		}
+
+		if (p[0] >= '0' && p[0] <= '9') {		// beware of isdigit() on signed chars
+			return false;
+		}
+
+		size_t idx = 0;
+		while (idx < p.length)
+		{
+			dchar dc;
+
+			if (utf_decodeChar(p, &idx, &dc) !is null) {
+				return false;
+			}
+
+			if (!((dc >= 0x80 && isUniAlpha(dc)) || isalnum(dc) || dc == '_')) {
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	/// TODO: reimplement based on strings
+    static ubyte* combineComments(ubyte* c1, ubyte* c2)
+	{
+		//printf("Lexer.combineComments('%s', '%s')\n", c1, c2);
+
+		ubyte* c = c2;
+
+		if (c1)
+		{
+			c = c1;
+			if (c2)
+			{
+				size_t len1 = strlen(cast(char*)c1);
+				size_t len2 = strlen(cast(char*)c2);
+
+				c = cast(ubyte*)malloc(len1 + 1 + len2 + 1);
+				memcpy(c, c1, len1);
+				if (len1 && c1[len1 - 1] != '\n')
+				{
+					c[len1] = '\n';
+					len1++;
+				}
+				memcpy(c + len1, c2, len2);
+				c[len1 + len2] = 0;
+			}
+		}
+
+		return c;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Library.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,980 @@
+module dmd.Library;
+
+import dmd.File;
+import dmd.Array;
+import dmd.StringTable;
+import dmd.OutBuffer;
+import dmd.ObjModule;
+import dmd.String;
+import dmd.Global;
+import dmd.File;
+import dmd.FileName;
+import dmd.Util;
+import dmd.StringValue;
+import dmd.String;
+
+import core.stdc.string;
+import core.stdc.stdlib;
+
+import std.string;
+
+align(1)
+struct LibHeader
+{
+	ubyte  recTyp;      // 0xF0
+	ushort pagesize;
+	int    lSymSeek;
+	ushort ndicpages;
+	ubyte  flags;
+}
+
+align(1)
+struct Libheader
+{
+	ubyte recTyp;
+	ushort recLen;
+	int trailerPosn;
+	ushort ndicpages;
+	ubyte flags;
+	char[6] filler;
+}
+
+struct ObjSymbol
+{
+    string name;
+    ObjModule* om;
+}
+
+/**************************
+ * Record types:
+ */
+
+enum HASHMOD = 0x25;
+enum BUCKETPAGE = 512;
+enum BUCKETSIZE = (BUCKETPAGE - HASHMOD - 1);
+
+/+
+#define RHEADR	0x6E
+#define REGINT	0x70
+#define REDATA	0x72
+#define RIDATA	0x74
+#define OVLDEF	0x76
+#define ENDREC	0x78
+#define BLKDEF	0x7A
+#define BLKEND	0x7C
+#define DEBSYM	0x7E
++/
+enum THEADR	= 0x80;
+enum LHEADR	= 0x82;
+/+#define PEDATA	0x84
+#define PIDATA	0x86
++/
+enum COMENT = 0x88;
+enum MODEND = 0x8A;
+enum M386END = 0x8B;	/* 32 bit module end record */
+/+
+#define EXTDEF	0x8C
+#define TYPDEF	0x8E
++/
+enum PUBDEF	= 0x90;
+enum PUB386	= 0x91;
+/+
+#define LOCSYM	0x92
+#define LINNUM	0x94
++/
+enum LNAMES	= 0x96;
+/+
+#define SEGDEF	0x98
+#define GRPDEF	0x9A
+#define FIXUPP	0x9C
+/*#define (none)	0x9E	*/
+#define LEDATA	0xA0
+#define LIDATA	0xA2
+#define LIBHED	0xA4
+#define LIBNAM	0xA6
+#define LIBLOC	0xA8
+#define LIBDIC	0xAA
+#define COMDEF	0xB0
+#define LEXTDEF	0xB4
+#define LPUBDEF	0xB6
+#define LCOMDEF	0xB8
+#define CEXTDEF	0xBC
++/
+enum COMDAT = 0xC2;
+/+#define LINSYM	0xC4
++/
+enum ALIAS = 0xC6;
+enum LLNAMES = 0xCA;
+
+
+enum LIBIDMAX = (512 - 0x25 - 3 - 4);	// max size that will fit in dictionary
+
+extern (C) extern char* strdup(const(char)* ptr);
+
+static uint parseName(ubyte** pp, char* name)
+{
+    ubyte* p = *pp;
+    uint len = *p++;
+
+    if (len == 0xFF && *p == 0)  // if long name
+    {
+        len = p[1] & 0xFF;
+        len |= cast(uint)p[2] << 8;
+	p += 3;
+        assert(len <= LIBIDMAX);
+    }
+
+    memcpy(name, p, len);
+    name[len] = 0;
+    *pp = p + len;
+	
+	return len;
+}
+
+static ushort parseIdx(ubyte** pp)
+{
+    ubyte* p = *pp;
+    ubyte c = *p++;
+
+    ushort idx = cast(ushort)((0x80 & c) ? ((0x7F & c) << 8) + *p++ : c);
+    *pp = p;
+    return idx;
+}
+
+extern (C) int D_NameCompare(const(void*) a, const(void*) b)
+{
+	ObjSymbol** p1 = cast(ObjSymbol**)a;
+	ObjSymbol** p2 = cast(ObjSymbol**)b;
+	
+    return cmp((*p1).name, (*p2).name);
+}
+
+/*******************************************
+ * Write a single entry into dictionary.
+ * Returns:
+ *	0	failure
+ */
+ 
+extern (C) extern uint _rotl(uint value, int shift);
+extern (C) extern uint _rotr(uint value, int shift);
+
+static int EnterDict(ubyte* bucketsP, ushort ndicpages, ubyte* entry, uint entrylen)
+{
+    ushort	uStartIndex;
+    ushort	uStep;
+    ushort	uStartPage;
+    ushort	uPageStep;
+    ushort	uIndex;
+    ushort	uPage;
+    ushort	n;
+    uint u;
+    uint nbytes;
+    ubyte* aP;
+    ubyte* zP;
+
+    aP = entry;
+    zP = aP + entrylen;		// point at last char in identifier
+
+    uStartPage	= 0;
+    uPageStep	= 0;
+    uStartIndex	= 0;
+    uStep	= 0;
+
+    u = entrylen;
+    while ( u-- )
+    {
+		uStartPage  = cast(ushort)_rotl( uStartPage,  2 ) ^ ( *aP   | 0x20 );
+		uStep       = cast(ushort)_rotr( uStep,	  2 ) ^ ( *aP++ | 0x20 );
+		uStartIndex = cast(ushort)_rotr( uStartIndex, 2 ) ^ ( *zP   | 0x20 );
+		uPageStep   = cast(ushort)_rotl( uPageStep,	  2 ) ^ ( *zP-- | 0x20 );
+    }
+
+    uStartPage %= ndicpages;
+    uPageStep  %= ndicpages;
+    if ( uPageStep == 0 )
+		uPageStep++;
+    uStartIndex %= HASHMOD;
+    uStep	%= HASHMOD;
+    if ( uStep == 0 )
+		uStep++;
+
+    uPage = uStartPage;
+    uIndex = uStartIndex;
+
+    // number of bytes in entry
+    nbytes = 1 + entrylen + 2;
+    if (entrylen > 255)
+		nbytes += 2;
+
+    while (1)
+    {
+		aP = &bucketsP[uPage * BUCKETPAGE];
+		uStartIndex = uIndex;
+		while (1)
+		{
+			if ( 0 == aP[ uIndex ] )
+			{
+				// n = next available position in this page
+				n = aP[ HASHMOD ] << 1;
+				assert(n > HASHMOD);
+
+				// if off end of this page
+				if (n + nbytes > BUCKETPAGE )
+				{   aP[ HASHMOD ] = 0xFF;
+					break;			// next page
+				}
+				else
+				{
+					aP[ uIndex ] = cast(ubyte)(n >> 1);
+					memcpy( (aP + n), entry, nbytes );
+					aP[ HASHMOD ] += (nbytes + 1) >> 1;
+					if (aP[HASHMOD] == 0)
+					aP[HASHMOD] = 0xFF;
+					return 1;
+				}
+			}
+			uIndex += uStep;
+			uIndex %= 0x25;
+			/*if (uIndex > 0x25)
+			uIndex -= 0x25;*/
+			if( uIndex == uStartIndex )
+				break;
+		}
+		uPage += uPageStep;
+		if (uPage >= ndicpages)
+			uPage -= ndicpages;
+		if( uPage == uStartPage )
+			break;
+    }
+
+    return 0;
+}
+
+class Library
+{
+    File libfile;
+    Array objmodules;	// ObjModule[]
+    Array objsymbols;	// ObjSymbol[]
+
+    StringTable tab;
+
+    this()
+	{
+		libfile = null;
+		
+		objmodules = new Array();
+		objsymbols = new Array();
+		tab = new StringTable();
+	}
+
+	/***********************************
+	 * Set the library file name based on the output directory
+	 * and the filename.
+	 * Add default library file name extension.
+	 */
+    void setFilename(string dir, string filename)
+	{
+		string arg = filename;
+		if (arg.length == 0)
+		{   
+			// Generate lib file name from first obj name
+			string n = (cast(String)global.params.objfiles.data[0]).str;
+
+			n = FileName.name(n);
+			FileName fn = FileName.forceExt(n, global.lib_ext);
+			arg = fn.toChars();
+		}
+		if (!FileName.absolute(arg))
+			arg = FileName.combine(dir, arg);
+
+		FileName libfilename = FileName.defaultExt(arg, global.lib_ext);
+		libfile = new File(libfilename);
+	}
+
+	/***************************************
+	 * Add object module or library to the library.
+	 * Examine the buffer to see which it is.
+	 * If the buffer is null, use module_name as the file name
+	 * and load the file.
+	 */
+    void addObject(string module_name, void *buf, size_t buflen)
+	{
+	version (LOG) {
+		printf("Library.addObject(%s)\n", module_name ? module_name : "");
+	}
+		if (!buf)
+		{
+			assert(module_name);
+			scope FileName f = new FileName(module_name);
+			scope File file = new File(f);
+			file.readv();
+			buf = file.buffer;
+			buflen = file.len;
+			file.ref_ = 1;
+		}
+
+		uint g_page_size;
+		ubyte* pstart = cast(ubyte*)buf;
+		int islibrary = 0;
+
+		/* See if it's an OMF library.
+		 * Don't go by file extension.
+		 */
+
+		/* Determine if it is an OMF library, an OMF object module,
+		 * or something else.
+		 */
+		if (buflen < LibHeader.sizeof)
+		{
+		  Lcorrupt:
+			error("corrupt object module");
+		}
+		LibHeader* lh = cast(LibHeader*)buf;
+		if (lh.recTyp == 0xF0)
+		{	/* OMF library
+			 * The modules are all at buf[g_page_size .. lh.lSymSeek]
+			 */
+			islibrary = 1;
+			g_page_size = lh.pagesize + 3;
+			buf = cast(void*)(pstart + g_page_size);
+			if (lh.lSymSeek > buflen ||
+				g_page_size > buflen)
+				goto Lcorrupt;
+			buflen = lh.lSymSeek - g_page_size;
+		}
+		else if (lh.recTyp == '!' && memcmp(lh, "!<arch>\n".ptr, 8) == 0)
+		{
+			error("COFF libraries not supported");
+			return;
+		}
+		else
+		{	
+			// Not a library, assume OMF object module
+			g_page_size = 16;
+		}
+
+		/* Split up the buffer buf[0..buflen] into multiple object modules,
+		 * each aligned on a g_page_size boundary.
+		 */
+
+		ObjModule* om = null;
+		int first_module	= 1;
+
+		ubyte* p = cast(ubyte*)buf;
+		ubyte* pend = p + buflen;
+		ubyte* pnext;
+		for (; p < pend; p = pnext)		// for each OMF record
+		{
+			if (p + 3 >= pend)
+				goto Lcorrupt;
+			ubyte recTyp = *p;
+			ushort recLen = *cast(ushort*)(p + 1);
+			pnext = p + 3 + recLen;
+			if (pnext > pend)
+				goto Lcorrupt;
+			recLen--;                          /* forget the checksum */
+
+			switch (recTyp)
+			{
+				case LHEADR :
+				case THEADR :
+					if (!om)
+					{   
+						char name[LIBIDMAX + 1];
+						om = new ObjModule();
+						om.flags = 0;
+						om.base = p;
+						p += 3;
+						parseName(&p, name.ptr);
+						if (first_module && module_name && !islibrary)
+						{	
+							// Remove path and extension
+							string fname = FileName.name(module_name);
+							string ext = FileName.ext(fname);
+							if (ext.length != 0) {
+								fname = fname[0..$-ext.length-1];
+							}
+
+							om.name = fname;
+						}
+						else
+						{	
+							/* Use THEADR name as module name,
+							 * removing path and extension.
+							 */
+							string fname = FileName.name(fromStringz(name.ptr));
+							string ext = FileName.ext(fname);
+							if (ext.length != 0) {
+								fname = fname[0..$-ext.length-1];
+							}
+							
+							om.name = fname;
+							om.flags |= MFtheadr;
+						}
+						if (strcmp(name.ptr, "C".ptr) == 0)	   // old C compilers did this
+						{	
+							om.flags |= MFgentheadr;  // generate our own THEADR
+							om.base = pnext;	   // skip past THEADR
+						}
+						objmodules.push(cast(void*)om);
+						first_module = 0;
+					}
+					break;
+
+				case MODEND :
+				case M386END:
+					if (om)
+					{   
+						om.page = cast(ushort)((om.base - pstart) / g_page_size);
+						om.length = pnext - om.base;
+						om = null;
+					}
+					// Round up to next page
+					uint t = pnext - pstart;
+					t = (t + g_page_size - 1) & ~cast(uint)(g_page_size - 1);
+					pnext = pstart + t;
+					break;
+				
+				default:
+					// ignore 
+					;
+			}
+		}
+
+		if (om)
+			goto Lcorrupt;		// missing MODEND record
+	}
+
+    void addLibrary(void *buf, size_t buflen)
+	{
+		assert(false);
+	}
+
+    void write()
+	{
+		if (global.params.verbose)
+			writef("library   %s\n", libfile.name.toChars());
+
+		scope OutBuffer libbuf = new OutBuffer();
+		WriteLibToBuffer(libbuf);
+
+		// Transfer image to file
+		libfile.setbuffer(libbuf.data, libbuf.offset);
+		libbuf.extractData();
+
+		string p = FileName.path(libfile.name.toChars());
+		FileName.ensurePathExists(p);
+
+		libfile.writev();
+	}
+
+  private:
+    void addSymbol(ObjModule* om, string name, int pickAny = 0)
+	{
+	version (LOG) {
+		printf("Library.addSymbol(%s, %s, %d)\n", om.name, name, pickAny);
+	}
+		StringValue* s = tab.insert(name);
+		if (!s)
+		{	
+			// already in table
+			if (!pickAny)
+			{   
+				s = tab.lookup(name);
+				assert(s);
+				ObjSymbol* os = cast(ObjSymbol*)s.ptrvalue;
+				error("multiple definition of %s: %s and %s: %s",
+				om.name, name, os.om.name, os.name);
+			}
+		}
+		else
+		{
+			ObjSymbol* os = new ObjSymbol();
+			os.name = name;
+			os.om = om;
+			s.ptrvalue = cast(void*)os;
+
+			objsymbols.push(os);
+		}
+	}
+	
+    void scanObjModule(ObjModule* om)
+	{
+		int easyomf;
+		uint u;
+		ubyte result = 0;
+		char name[LIBIDMAX + 1];
+
+		scope Array names = new Array();
+		names.push(null);		// don't use index 0
+
+		assert(om);
+		easyomf = 0;				// assume not EASY-OMF
+		ubyte* pend = om.base + om.length;
+
+		ubyte* pnext;
+		for (ubyte* p = om.base; 1; p = pnext)
+		{
+			assert(p < pend);
+			ubyte recTyp = *p++;
+			ushort recLen = *cast(ushort*)p;
+			p += 2;
+			pnext = p + recLen;
+			recLen--;				// forget the checksum
+
+			switch (recTyp)
+			{
+				case LNAMES:
+				case LLNAMES:
+					while (p + 1 < pnext)
+					{
+						uint len = parseName(&p, name.ptr);
+						names.push(cast(void*)new String(name[0..len].idup));
+					}
+					break;
+
+				case PUBDEF:
+					if (easyomf)
+						recTyp = PUB386;		// convert to MS format
+				case PUB386:
+					if (!(parseIdx(&p) | parseIdx(&p)))
+						p += 2;			// skip seg, grp, frame
+					while (p + 1 < pnext)
+					{
+						uint len = parseName(&p, name.ptr);
+						p += (recTyp == PUBDEF) ? 2 : 4;	// skip offset
+						parseIdx(&p);				// skip type index
+						addSymbol(om, name[0..len].idup);
+					}
+					break;
+
+				case COMDAT:
+					if (easyomf)
+						recTyp = COMDAT+1;		// convert to MS format
+					case COMDAT+1:
+					int pickAny = 0;
+
+					if (*p++ & 5)		// if continuation or local comdat
+						break;
+
+					ubyte attr = *p++;
+					if (attr & 0xF0)	// attr: if multiple instances allowed
+						pickAny = 1;
+					p++;			// align
+
+					p += 2;			// enum data offset
+					if (recTyp == COMDAT+1)
+						p += 2;			// enum data offset
+
+					parseIdx(&p);			// type index
+
+					if ((attr & 0x0F) == 0)	// if explicit allocation
+					{   parseIdx(&p);		// base group
+						parseIdx(&p);		// base segment
+					}
+
+					uint idx = parseIdx(&p);	// public name index
+					if( idx == 0 || idx >= names.dim)
+					{
+						//debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames));
+						error("corrupt COMDAT");
+						return;
+					}
+
+					//printf("[s] name='%s'\n",name);
+					addSymbol(om, (cast(String)names.data[idx]).str, pickAny);
+					break;
+
+				case ALIAS:
+					while (p + 1 < pnext)
+					{
+						uint len = parseName(&p, name.ptr);
+						addSymbol(om, name[0..len].idup);
+						parseName(&p, name.ptr);
+					}
+					break;
+
+				case MODEND:
+				case M386END:
+					result = 1;
+					goto Ret;
+
+				case COMENT:
+					// Recognize Phar Lap EASY-OMF format
+					{   
+						static ubyte[7] omfstr = [0x80,0xAA,'8','0','3','8','6'];
+
+						if (recLen == omfstr.sizeof)
+						{
+							for (uint i = 0; i < omfstr.sizeof; i++)
+								if (*p++ != omfstr[i])
+									goto L1;
+							easyomf = 1;
+							break;
+							L1:	;
+						}
+					}
+					// Recognize .IMPDEF Import Definition Records
+					{   
+						static ubyte[3] omfstr = [0, 0xA0, 1];
+
+						if (recLen >= 7)
+						{
+							p++;
+							for (uint i = 1; i < omfstr.sizeof; i++)
+								if (*p++ != omfstr[i])
+									goto L2;
+							p++;		// skip OrdFlag field
+							uint len = parseName(&p, name.ptr);
+							addSymbol(om, name[0..len].idup);
+							break;
+							L2:	;
+						}
+					}
+					break;
+
+				default:
+					// ignore 
+					;
+			}
+		}
+
+	Ret:
+		;
+		///for (u = 1; u < names.dim; u++)
+		///	free(names.data[u]);
+	}
+	
+	/***********************************
+	 * Calculates number of pages needed for dictionary
+	 * Returns:
+	 *	number of pages
+	 */
+    ushort numDictPages(uint padding)
+	{
+		ushort	ndicpages;
+		ushort	bucksForHash;
+		ushort	bucksForSize;
+		uint symSize = 0;
+
+		for (int i = 0; i < objsymbols.dim; i++)
+		{	
+			ObjSymbol* s = cast(ObjSymbol*)objsymbols.data[i];
+			symSize += ( s.name.length + 4 ) & ~1;
+		}
+
+		for (int i = 0; i < objmodules.dim; i++)
+		{	
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+			size_t len = om.name.length;
+			if (len > 0xFF)
+				len += 2;			// Digital Mars long name extension
+			symSize += ( len + 4 + 1 ) & ~1;
+		}
+
+		bucksForHash = cast(ushort)((objsymbols.dim + objmodules.dim + HASHMOD - 3) / (HASHMOD - 2));
+		bucksForSize = cast(ushort)((symSize + BUCKETSIZE - padding - padding - 1) / (BUCKETSIZE - padding));
+
+		ndicpages = (bucksForHash > bucksForSize ) ? bucksForHash : bucksForSize;
+		//printf("ndicpages = %u\n",ndicpages);
+
+		// Find prime number greater than ndicpages
+		static uint[] primes =
+		[ 1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,
+		  47,53,59,61,67,71,73,79,83,89,97,101,103,
+		  107,109,113,127,131,137,139,149,151,157,
+		  163,167,173,179,181,191,193,197,199,211,
+		  223,227,229,233,239,241,251,257,263,269,
+		  271,277,281,283,293,307,311,313,317,331,
+		  337,347,349,353,359,367,373,379,383,389,
+		  397,401,409,419,421,431,433,439,443,449,
+		  457,461,463,467,479,487,491,499,503,509,
+		  //521,523,541,547,
+		  0
+		];
+
+		for (int i = 0; 1; i++)
+		{
+			if ( primes[i] == 0 )
+			{   
+				// Quick and easy way is out.
+				// Now try and find first prime number > ndicpages
+				uint prime;
+
+				for (prime = (ndicpages + 1) | 1; 1; prime += 2)
+				{   // Determine if prime is prime
+					for (uint u = 3; u < prime / 2; u += 2)
+					{
+						if ((prime / u) * u == prime)
+							goto L1;
+					}
+					break;
+
+					L1: ;
+				}
+				ndicpages = cast(ushort)prime;
+				break;
+			}
+
+			if (primes[i] > ndicpages)
+			{
+				ndicpages = cast(ushort)primes[i];
+				break;
+			}
+		}
+
+		return ndicpages;
+	}
+	
+	/*******************************************
+	 * Write the module and symbol names to the dictionary.
+	 * Returns:
+	 *	0	failure
+	 */
+    int FillDict(ubyte* bucketsP, ushort ndicpages)
+	{
+		ubyte entry[4 + LIBIDMAX + 2 + 1];
+
+		//printf("FillDict()\n");
+
+		// Add each of the module names
+		for (int i = 0; i < objmodules.dim; i++)
+		{	
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+			ushort n = cast(ushort)om.name.length;
+			if (n > 255)
+			{   
+				entry[0] = 0xFF;
+				entry[1] = 0;
+				*cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1);
+				memcpy(entry.ptr + 4, om.name.ptr, n);
+				n += 3;
+			}
+			else
+			{   
+				entry[ 0 ] = cast(ubyte)(1 + n);
+				memcpy(entry.ptr + 1, om.name.ptr, n );
+			}
+			entry[ n + 1 ] = '!';
+			*(cast(ushort*)( n + 2 + entry.ptr )) = om.page;
+			if ( n & 1 )
+				entry[ n + 2 + 2 ] = 0;
+			if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n + 1 ) )
+				return 0;
+		}
+
+		// Sort the symbols
+		qsort( objsymbols.data, objsymbols.dim, 4, /*(cmpfunc_t)*/&D_NameCompare );
+
+		// Add each of the symbols
+		for (int i = 0; i < objsymbols.dim; i++)
+		{	
+			ObjSymbol* os = cast(ObjSymbol*)objsymbols.data[i];
+
+			ushort n = cast(ushort)os.name.length;
+			if (n > 255)
+			{   
+				entry[0] = 0xFF;
+				entry[1] = 0;
+				*cast(ushort*)(entry.ptr + 2) = n;
+				memcpy(entry.ptr + 4, os.name.ptr, n);
+				n += 3;
+			}
+			else
+			{   
+				entry[ 0 ] = cast(ubyte)n;
+				memcpy( entry.ptr + 1, os.name.ptr, n );
+			}
+			*(cast(ushort*)( n + 1 + entry.ptr )) = os.om.page;
+			if ( (n & 1) == 0 )
+				entry[ n + 3] = 0;
+			if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n ) )
+			{
+				return 0;
+			}
+		}
+
+		return 1;
+	}
+	
+	/**********************************************
+	 * Create and write library to libbuf.
+	 * The library consists of:
+	 *	library header
+	 *	object modules...
+	 *	dictionary header
+	 *	dictionary pages...
+	 */
+    void WriteLibToBuffer(OutBuffer libbuf)
+	{
+		/* Scan each of the object modules for symbols
+		 * to go into the dictionary
+		 */
+		for (int i = 0; i < objmodules.dim; i++)
+		{   
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+			scanObjModule(om);
+		}
+
+		uint g_page_size = 16;
+
+		/* Calculate page size so that the number of pages
+		 * fits in 16 bits. This is because object modules
+		 * are indexed by page number, stored as an unsigned short.
+		 */
+		while (1)
+		{
+		  Lagain:
+	version (LOG) {
+			printf("g_page_size = %d\n", g_page_size);
+	}
+			uint offset = g_page_size;
+
+			for (int i = 0; i < objmodules.dim; i++)
+			{   
+				ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+				uint page = offset / g_page_size;
+				if (page > 0xFFFF)
+				{
+					// Page size is too small, double it and try again
+					g_page_size *= 2;
+					goto Lagain;
+				}
+
+				// Write out the object module m
+				if (om.flags & MFgentheadr)		// if generate THEADR record
+				{
+					size_t size = om.name.length;
+					assert(size <= LIBIDMAX);
+
+					offset += size + 5;
+					//offset += om.length - (size + 5);
+					offset += om.length;
+				}
+				else
+					offset += om.length;
+
+				// Round the size of the file up to the next page size
+				// by filling with 0s
+				uint n = (g_page_size - 1) & offset;
+				if (n)
+					offset += g_page_size - n;
+			}
+			break;
+		}
+
+
+		/* Leave one page of 0s at start as a dummy library header.
+		 * Fill it in later with the real data.
+		 */
+		libbuf.fill0(g_page_size);
+
+		/* Write each object module into the library
+		 */
+		for (int i = 0; i < objmodules.dim; i++)
+		{	
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+			uint page = libbuf.offset / g_page_size;
+			assert(page <= 0xFFFF);
+			om.page = cast(ushort)page;
+
+			// Write out the object module om
+			if (om.flags & MFgentheadr)		// if generate THEADR record
+			{
+				uint size = om.name.length;
+				ubyte header[4 + LIBIDMAX + 1];
+
+				header [0] = THEADR;
+				header [1] = cast(ubyte)(2 + size);
+				header [2] = 0;
+				header [3] = cast(ubyte)size;
+				assert(size <= 0xFF - 2);
+
+				memcpy(4 + header.ptr, om.name.ptr, size);
+
+				// Compute and store record checksum
+				uint n = size + 4;
+				ubyte checksum = 0;
+				ubyte* p = header.ptr;
+				while (n--)
+				{	
+					checksum -= *p;
+					p++;
+				}
+				*p = checksum;
+
+				libbuf.write(header.ptr, size + 5);
+				//libbuf.write(om.base, om.length - (size + 5));
+				libbuf.write(om.base, om.length);
+			}
+			else
+				libbuf.write(om.base, om.length);
+
+			// Round the size of the file up to the next page size
+			// by filling with 0s
+			uint n = (g_page_size - 1) & libbuf.offset;
+			if (n)
+				libbuf.fill0(g_page_size - n);
+		}
+
+		// File offset of start of dictionary
+		uint offset = libbuf.offset;
+
+		// Write dictionary header, then round it to a BUCKETPAGE boundary
+		ushort size = (BUCKETPAGE - (cast(short)offset + 3)) & (BUCKETPAGE - 1);
+		libbuf.writeByte(0xF1);
+		libbuf.writeword(size);
+		libbuf.fill0(size);
+
+		// Create dictionary
+		ubyte* bucketsP = null;
+		ushort ndicpages;
+		ushort padding = 32;
+		for (;;)
+		{
+			ndicpages = numDictPages(padding);
+
+		version (LOG) {
+			printf("ndicpages = %d\n", ndicpages);
+		}
+			// Allocate dictionary
+			if (bucketsP)
+				bucketsP = cast(ubyte*)realloc(bucketsP, ndicpages * BUCKETPAGE);
+			else
+				bucketsP = cast(ubyte*)malloc(ndicpages * BUCKETPAGE);
+			assert(bucketsP);
+			memset(bucketsP, 0, ndicpages * BUCKETPAGE);
+			for (uint u = 0; u < ndicpages; u++)
+			{
+				// 'next available' slot
+				bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1;
+			}
+
+			if (FillDict(bucketsP, ndicpages)) 
+				break;
+			padding += 16;      // try again with more margins
+		}
+
+		// Write dictionary
+		libbuf.write(bucketsP, ndicpages * BUCKETPAGE);
+		if (bucketsP)
+		free(bucketsP);
+
+		// Create library header
+		Libheader libHeader;
+		memset(&libHeader, 0, Libheader.sizeof);
+		libHeader.recTyp = 0xF0;
+		libHeader.recLen  = 0x0D;
+		libHeader.trailerPosn = offset + (3 + size);
+		libHeader.recLen = cast(ushort)(g_page_size - 3);
+		libHeader.ndicpages = ndicpages;
+		libHeader.flags = 1;		// always case sensitive
+
+		// Write library header at start of buffer
+		memcpy(libbuf.data, &libHeader, libHeader.sizeof);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Library__.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,976 @@
+module dmd.Library;
+
+import dmd.File;
+import dmd.Array;
+import dmd.StringTable;
+import dmd.OutBuffer;
+import dmd.ObjModule;
+import dmd.String;
+import dmd.Global;
+import dmd.File;
+import dmd.FileName;
+import dmd.Util;
+import dmd.StringValue;
+import dmd.String;
+
+import core.stdc.string;
+import core.stdc.stdlib;
+
+align(1)
+struct LibHeader
+{
+	ubyte  recTyp;      // 0xF0
+	ushort pagesize;
+	int    lSymSeek;
+	ushort ndicpages;
+	ubyte  flags;
+}
+
+align(1)
+struct Libheader
+{
+	ubyte recTyp;
+	ushort recLen;
+	int trailerPosn;
+	ushort ndicpages;
+	ubyte flags;
+	char[6] filler;
+}
+
+struct ObjSymbol
+{
+    const(char)* name;
+    ObjModule* om;
+}
+
+/**************************
+ * Record types:
+ */
+
+enum HASHMOD = 0x25;
+enum BUCKETPAGE = 512;
+enum BUCKETSIZE = (BUCKETPAGE - HASHMOD - 1);
+
+/+
+#define RHEADR	0x6E
+#define REGINT	0x70
+#define REDATA	0x72
+#define RIDATA	0x74
+#define OVLDEF	0x76
+#define ENDREC	0x78
+#define BLKDEF	0x7A
+#define BLKEND	0x7C
+#define DEBSYM	0x7E
++/
+enum THEADR	= 0x80;
+enum LHEADR	= 0x82;
+/+#define PEDATA	0x84
+#define PIDATA	0x86
++/
+enum COMENT = 0x88;
+enum MODEND = 0x8A;
+enum M386END = 0x8B;	/* 32 bit module end record */
+/+
+#define EXTDEF	0x8C
+#define TYPDEF	0x8E
++/
+enum PUBDEF	= 0x90;
+enum PUB386	= 0x91;
+/+
+#define LOCSYM	0x92
+#define LINNUM	0x94
++/
+enum LNAMES	= 0x96;
+/+
+#define SEGDEF	0x98
+#define GRPDEF	0x9A
+#define FIXUPP	0x9C
+/*#define (none)	0x9E	*/
+#define LEDATA	0xA0
+#define LIDATA	0xA2
+#define LIBHED	0xA4
+#define LIBNAM	0xA6
+#define LIBLOC	0xA8
+#define LIBDIC	0xAA
+#define COMDEF	0xB0
+#define LEXTDEF	0xB4
+#define LPUBDEF	0xB6
+#define LCOMDEF	0xB8
+#define CEXTDEF	0xBC
++/
+enum COMDAT = 0xC2;
+/+#define LINSYM	0xC4
++/
+enum ALIAS = 0xC6;
+enum LLNAMES = 0xCA;
+
+
+enum LIBIDMAX = (512 - 0x25 - 3 - 4);	// max size that will fit in dictionary
+
+extern (C) extern char* strdup(const(char)* ptr);
+
+static void parseName(ubyte** pp, char* name)
+{
+    ubyte* p = *pp;
+    uint len = *p++;
+
+    if (len == 0xFF && *p == 0)  // if long name
+    {
+        len = p[1] & 0xFF;
+        len |= cast(uint)p[2] << 8;
+	p += 3;
+        assert(len <= LIBIDMAX);
+    }
+
+    memcpy(name, p, len);
+    name[len] = 0;
+    *pp = p + len;
+}
+
+static ushort parseIdx(ubyte** pp)
+{
+    ubyte* p = *pp;
+    ubyte c = *p++;
+
+    ushort idx = cast(ushort)((0x80 & c) ? ((0x7F & c) << 8) + *p++ : c);
+    *pp = p;
+    return idx;
+}
+
+extern (C) int D_NameCompare(const(void*) a, const(void*) b)
+{
+	ObjSymbol** p1 = cast(ObjSymbol**)a;
+	ObjSymbol** p2 = cast(ObjSymbol**)b;
+	
+    return strcmp((*p1).name, (*p2).name);
+}
+
+/*******************************************
+ * Write a single entry into dictionary.
+ * Returns:
+ *	0	failure
+ */
+ 
+extern (C) extern uint _rotl(uint value, int shift);
+extern (C) extern uint _rotr(uint value, int shift);
+
+static int EnterDict(ubyte* bucketsP, ushort ndicpages, ubyte* entry, uint entrylen)
+{
+    ushort	uStartIndex;
+    ushort	uStep;
+    ushort	uStartPage;
+    ushort	uPageStep;
+    ushort	uIndex;
+    ushort	uPage;
+    ushort	n;
+    uint u;
+    uint nbytes;
+    ubyte* aP;
+    ubyte* zP;
+
+    aP = entry;
+    zP = aP + entrylen;		// point at last char in identifier
+
+    uStartPage	= 0;
+    uPageStep	= 0;
+    uStartIndex	= 0;
+    uStep	= 0;
+
+    u = entrylen;
+    while ( u-- )
+    {
+		uStartPage  = cast(ushort)_rotl( uStartPage,  2 ) ^ ( *aP   | 0x20 );
+		uStep       = cast(ushort)_rotr( uStep,	  2 ) ^ ( *aP++ | 0x20 );
+		uStartIndex = cast(ushort)_rotr( uStartIndex, 2 ) ^ ( *zP   | 0x20 );
+		uPageStep   = cast(ushort)_rotl( uPageStep,	  2 ) ^ ( *zP-- | 0x20 );
+    }
+
+    uStartPage %= ndicpages;
+    uPageStep  %= ndicpages;
+    if ( uPageStep == 0 )
+		uPageStep++;
+    uStartIndex %= HASHMOD;
+    uStep	%= HASHMOD;
+    if ( uStep == 0 )
+		uStep++;
+
+    uPage = uStartPage;
+    uIndex = uStartIndex;
+
+    // number of bytes in entry
+    nbytes = 1 + entrylen + 2;
+    if (entrylen > 255)
+		nbytes += 2;
+
+    while (1)
+    {
+		aP = &bucketsP[uPage * BUCKETPAGE];
+		uStartIndex = uIndex;
+		while (1)
+		{
+			if ( 0 == aP[ uIndex ] )
+			{
+				// n = next available position in this page
+				n = aP[ HASHMOD ] << 1;
+				assert(n > HASHMOD);
+
+				// if off end of this page
+				if (n + nbytes > BUCKETPAGE )
+				{   aP[ HASHMOD ] = 0xFF;
+					break;			// next page
+				}
+				else
+				{
+					aP[ uIndex ] = cast(ubyte)(n >> 1);
+					memcpy( (aP + n), entry, nbytes );
+					aP[ HASHMOD ] += (nbytes + 1) >> 1;
+					if (aP[HASHMOD] == 0)
+					aP[HASHMOD] = 0xFF;
+					return 1;
+				}
+			}
+			uIndex += uStep;
+			uIndex %= 0x25;
+			/*if (uIndex > 0x25)
+			uIndex -= 0x25;*/
+			if( uIndex == uStartIndex )
+				break;
+		}
+		uPage += uPageStep;
+		if (uPage >= ndicpages)
+			uPage -= ndicpages;
+		if( uPage == uStartPage )
+			break;
+    }
+
+    return 0;
+}
+
+class Library
+{
+    File libfile;
+    Array objmodules;	// ObjModule[]
+    Array objsymbols;	// ObjSymbol[]
+
+    StringTable tab;
+
+    this()
+	{
+		libfile = null;
+		
+		objmodules = new Array();
+		objsymbols = new Array();
+		tab = new StringTable();
+	}
+
+	/***********************************
+	 * Set the library file name based on the output directory
+	 * and the filename.
+	 * Add default library file name extension.
+	 */
+    void setFilename(string dir, string filename)
+	{
+		string arg = filename;
+		if (arg.length == 0)
+		{   
+			// Generate lib file name from first obj name
+			string n = (cast(String)global.params.objfiles.data[0]).str;
+
+			n = FileName.name(n);
+			FileName fn = FileName.forceExt(n, global.lib_ext);
+			arg = fn.toChars();
+		}
+		if (!FileName.absolute(arg))
+			arg = FileName.combine(dir, arg);
+
+		FileName libfilename = FileName.defaultExt(arg, global.lib_ext);
+		libfile = new File(libfilename);
+	}
+
+	/***************************************
+	 * Add object module or library to the library.
+	 * Examine the buffer to see which it is.
+	 * If the buffer is null, use module_name as the file name
+	 * and load the file.
+	 */
+    void addObject(string module_name, void *buf, size_t buflen)
+	{
+	version (LOG) {
+		printf("Library.addObject(%s)\n", module_name ? module_name : "");
+	}
+		if (!buf)
+		{
+			assert(module_name);
+			scope FileName f = new FileName(module_name);
+			scope File file = new File(f);
+			file.readv();
+			buf = file.buffer;
+			buflen = file.len;
+			file.ref_ = 1;
+		}
+
+		uint g_page_size;
+		ubyte* pstart = cast(ubyte*)buf;
+		int islibrary = 0;
+
+		/* See if it's an OMF library.
+		 * Don't go by file extension.
+		 */
+
+		/* Determine if it is an OMF library, an OMF object module,
+		 * or something else.
+		 */
+		if (buflen < LibHeader.sizeof)
+		{
+		  Lcorrupt:
+			error("corrupt object module");
+		}
+		LibHeader* lh = cast(LibHeader*)buf;
+		if (lh.recTyp == 0xF0)
+		{	/* OMF library
+			 * The modules are all at buf[g_page_size .. lh.lSymSeek]
+			 */
+			islibrary = 1;
+			g_page_size = lh.pagesize + 3;
+			buf = cast(void*)(pstart + g_page_size);
+			if (lh.lSymSeek > buflen ||
+				g_page_size > buflen)
+				goto Lcorrupt;
+			buflen = lh.lSymSeek - g_page_size;
+		}
+		else if (lh.recTyp == '!' && memcmp(lh, "!<arch>\n".ptr, 8) == 0)
+		{
+			error("COFF libraries not supported");
+			return;
+		}
+		else
+		{	
+			// Not a library, assume OMF object module
+			g_page_size = 16;
+		}
+
+		/* Split up the buffer buf[0..buflen] into multiple object modules,
+		 * each aligned on a g_page_size boundary.
+		 */
+
+		ObjModule* om = null;
+		int first_module	= 1;
+
+		ubyte* p = cast(ubyte*)buf;
+		ubyte* pend = p + buflen;
+		ubyte* pnext;
+		for (; p < pend; p = pnext)		// for each OMF record
+		{
+			if (p + 3 >= pend)
+				goto Lcorrupt;
+			ubyte recTyp = *p;
+			ushort recLen = *cast(ushort*)(p + 1);
+			pnext = p + 3 + recLen;
+			if (pnext > pend)
+				goto Lcorrupt;
+			recLen--;                          /* forget the checksum */
+
+			switch (recTyp)
+			{
+				case LHEADR :
+				case THEADR :
+					if (!om)
+					{   
+						char name[LIBIDMAX + 1];
+						om = new ObjModule();
+						om.flags = 0;
+						om.base = p;
+						p += 3;
+						parseName(&p, name.ptr);
+						if (first_module && module_name && !islibrary)
+						{	
+							// Remove path and extension
+							string fname = FileName.name(module_name);
+							string ext = FileName.ext(fname);
+							if (ext.length != 0) {
+								fname = fname[0..$-ext.length-1];
+							}
+
+							om.name = toStringz(fname);
+						}
+						else
+						{	
+							/* Use THEADR name as module name,
+							 * removing path and extension.
+							 */
+							string fname = FileName.name(fromStringz(name.ptr));
+							string ext = FileName.ext(fname);
+							if (ext.length != 0) {
+								fname = fname[0..$-ext.length-1];
+							}
+							
+							om.name = toStringz(fname);
+							om.flags |= MFtheadr;
+						}
+						if (strcmp(name.ptr, "C".ptr) == 0)	   // old C compilers did this
+						{	
+							om.flags |= MFgentheadr;  // generate our own THEADR
+							om.base = pnext;	   // skip past THEADR
+						}
+						objmodules.push(cast(void*)om);
+						first_module = 0;
+					}
+					break;
+
+				case MODEND :
+				case M386END:
+					if (om)
+					{   
+						om.page = cast(ushort)((om.base - pstart) / g_page_size);
+						om.length = pnext - om.base;
+						om = null;
+					}
+					// Round up to next page
+					uint t = pnext - pstart;
+					t = (t + g_page_size - 1) & ~cast(uint)(g_page_size - 1);
+					pnext = pstart + t;
+					break;
+				
+				default:
+					// ignore 
+					;
+			}
+		}
+
+		if (om)
+			goto Lcorrupt;		// missing MODEND record
+	}
+
+    void addLibrary(void *buf, size_t buflen)
+	{
+		assert(false);
+	}
+
+    void write()
+	{
+		if (global.params.verbose)
+			writef("library   %s\n", libfile.name.toChars());
+
+		scope OutBuffer libbuf = new OutBuffer();
+		WriteLibToBuffer(libbuf);
+
+		// Transfer image to file
+		libfile.setbuffer(libbuf.data, libbuf.offset);
+		libbuf.extractData();
+
+		string p = FileName.path(libfile.name.toChars());
+		FileName.ensurePathExists(p);
+
+		libfile.writev();
+	}
+
+  private:
+    void addSymbol(ObjModule* om, const(char)* name, int pickAny = 0)
+	{
+	version (LOG) {
+		printf("Library.addSymbol(%s, %s, %d)\n", om.name, name, pickAny);
+	}
+		StringValue *s = tab.insert(fromStringz(name));
+		if (!s)
+		{	// already in table
+			if (!pickAny)
+			{   
+				s = tab.lookup(fromStringz(name));
+				assert(s);
+				ObjSymbol* os = cast(ObjSymbol*)s.ptrvalue;
+				error("multiple definition of %s: %s and %s: %s",
+				om.name, name, os.om.name, os.name);
+			}
+		}
+		else
+		{
+			ObjSymbol* os = new ObjSymbol();
+			os.name = strdup(name);
+			os.om = om;
+			s.ptrvalue = cast(void*)os;
+
+			objsymbols.push(cast(void*)os);
+		}
+	}
+	
+    void scanObjModule(ObjModule* om)
+	{
+		int easyomf;
+		uint u;
+		ubyte result = 0;
+		char name[LIBIDMAX + 1];
+
+		scope Array names = new Array();
+		names.push(null);		// don't use index 0
+
+		assert(om);
+		easyomf = 0;				// assume not EASY-OMF
+		ubyte* pend = om.base + om.length;
+
+		ubyte* pnext;
+		for (ubyte* p = om.base; 1; p = pnext)
+		{
+			assert(p < pend);
+			ubyte recTyp = *p++;
+			ushort recLen = *cast(ushort*)p;
+			p += 2;
+			pnext = p + recLen;
+			recLen--;				// forget the checksum
+
+			switch (recTyp)
+			{
+				case LNAMES:
+				case LLNAMES:
+					while (p + 1 < pnext)
+					{
+						parseName(&p, name.ptr);
+						names.push(strdup(name.ptr));
+					}
+					break;
+
+				case PUBDEF:
+					if (easyomf)
+						recTyp = PUB386;		// convert to MS format
+				case PUB386:
+					if (!(parseIdx(&p) | parseIdx(&p)))
+						p += 2;			// skip seg, grp, frame
+					while (p + 1 < pnext)
+					{
+						parseName(&p, name.ptr);
+						p += (recTyp == PUBDEF) ? 2 : 4;	// skip offset
+						parseIdx(&p);				// skip type index
+						addSymbol(om, name.ptr);
+					}
+					break;
+
+				case COMDAT:
+					if (easyomf)
+						recTyp = COMDAT+1;		// convert to MS format
+					case COMDAT+1:
+					int pickAny = 0;
+
+					if (*p++ & 5)		// if continuation or local comdat
+						break;
+
+					ubyte attr = *p++;
+					if (attr & 0xF0)	// attr: if multiple instances allowed
+						pickAny = 1;
+					p++;			// align
+
+					p += 2;			// enum data offset
+					if (recTyp == COMDAT+1)
+						p += 2;			// enum data offset
+
+					parseIdx(&p);			// type index
+
+					if ((attr & 0x0F) == 0)	// if explicit allocation
+					{   parseIdx(&p);		// base group
+						parseIdx(&p);		// base segment
+					}
+
+					uint idx = parseIdx(&p);	// public name index
+					if( idx == 0 || idx >= names.dim)
+					{
+						//debug(printf("[s] name idx=%d, uCntNames=%d\n", idx, uCntNames));
+						error("corrupt COMDAT");
+						return;
+					}
+
+					//printf("[s] name='%s'\n",name);
+					addSymbol(om, cast(const(char)*)names.data[idx], pickAny);
+					break;
+
+				case ALIAS:
+					while (p + 1 < pnext)
+					{
+						parseName(&p, name.ptr);
+						addSymbol(om, name.ptr);
+						parseName(&p, name.ptr);
+					}
+					break;
+
+				case MODEND:
+				case M386END:
+					result = 1;
+					goto Ret;
+
+				case COMENT:
+					// Recognize Phar Lap EASY-OMF format
+					{   
+						static ubyte[7] omfstr = [0x80,0xAA,'8','0','3','8','6'];
+
+						if (recLen == omfstr.sizeof)
+						{
+							for (uint i = 0; i < omfstr.sizeof; i++)
+								if (*p++ != omfstr[i])
+									goto L1;
+							easyomf = 1;
+							break;
+							L1:	;
+						}
+					}
+					// Recognize .IMPDEF Import Definition Records
+					{   
+						static ubyte[3] omfstr = [0, 0xA0, 1];
+
+						if (recLen >= 7)
+						{
+							p++;
+							for (uint i = 1; i < omfstr.sizeof; i++)
+								if (*p++ != omfstr[i])
+									goto L2;
+							p++;		// skip OrdFlag field
+							parseName(&p, name.ptr);
+							addSymbol(om, name.ptr);
+							break;
+							L2:	;
+						}
+					}
+					break;
+
+				default:
+					// ignore 
+					;
+			}
+		}
+
+	Ret:
+		;
+		///for (u = 1; u < names.dim; u++)
+		///	free(names.data[u]);
+	}
+	
+	/***********************************
+	 * Calculates number of pages needed for dictionary
+	 * Returns:
+	 *	number of pages
+	 */
+    ushort numDictPages(uint padding)
+	{
+		ushort	ndicpages;
+		ushort	bucksForHash;
+		ushort	bucksForSize;
+		uint symSize = 0;
+
+		for (int i = 0; i < objsymbols.dim; i++)
+		{	
+			ObjSymbol* s = cast(ObjSymbol*)objsymbols.data[i];
+			symSize += ( strlen(s.name) + 4 ) & ~1;
+		}
+
+		for (int i = 0; i < objmodules.dim; i++)
+		{	
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+			size_t len = strlen(om.name);
+			if (len > 0xFF)
+				len += 2;			// Digital Mars long name extension
+			symSize += ( len + 4 + 1 ) & ~1;
+		}
+
+		bucksForHash = cast(ushort)((objsymbols.dim + objmodules.dim + HASHMOD - 3) / (HASHMOD - 2));
+		bucksForSize = cast(ushort)((symSize + BUCKETSIZE - padding - padding - 1) / (BUCKETSIZE - padding));
+
+		ndicpages = (bucksForHash > bucksForSize ) ? bucksForHash : bucksForSize;
+		//printf("ndicpages = %u\n",ndicpages);
+
+		// Find prime number greater than ndicpages
+		static uint[] primes =
+		[ 1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,
+		  47,53,59,61,67,71,73,79,83,89,97,101,103,
+		  107,109,113,127,131,137,139,149,151,157,
+		  163,167,173,179,181,191,193,197,199,211,
+		  223,227,229,233,239,241,251,257,263,269,
+		  271,277,281,283,293,307,311,313,317,331,
+		  337,347,349,353,359,367,373,379,383,389,
+		  397,401,409,419,421,431,433,439,443,449,
+		  457,461,463,467,479,487,491,499,503,509,
+		  //521,523,541,547,
+		  0
+		];
+
+		for (int i = 0; 1; i++)
+		{
+			if ( primes[i] == 0 )
+			{   
+				// Quick and easy way is out.
+				// Now try and find first prime number > ndicpages
+				uint prime;
+
+				for (prime = (ndicpages + 1) | 1; 1; prime += 2)
+				{   // Determine if prime is prime
+					for (uint u = 3; u < prime / 2; u += 2)
+					{
+						if ((prime / u) * u == prime)
+							goto L1;
+					}
+					break;
+
+					L1: ;
+				}
+				ndicpages = cast(ushort)prime;
+				break;
+			}
+
+			if (primes[i] > ndicpages)
+			{
+				ndicpages = cast(ushort)primes[i];
+				break;
+			}
+		}
+
+		return ndicpages;
+	}
+	
+	/*******************************************
+	 * Write the module and symbol names to the dictionary.
+	 * Returns:
+	 *	0	failure
+	 */
+    int FillDict(ubyte* bucketsP, ushort ndicpages)
+	{
+		ubyte entry[4 + LIBIDMAX + 2 + 1];
+
+		//printf("FillDict()\n");
+
+		// Add each of the module names
+		for (int i = 0; i < objmodules.dim; i++)
+		{	
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+			ushort n = cast(ushort)strlen(om.name);
+			if (n > 255)
+			{   
+				entry[0] = 0xFF;
+				entry[1] = 0;
+				*cast(ushort*)(entry.ptr + 2) = cast(ushort)(n + 1);
+				memcpy(entry.ptr + 4, om.name, n);
+				n += 3;
+			}
+			else
+			{   
+				entry[ 0 ] = cast(ubyte)(1 + n);
+				memcpy(entry.ptr + 1, om.name, n );
+			}
+			
+			entry[ n + 1 ] = '!';
+			*(cast(ushort*)( n + 2 + entry.ptr )) = om.page;
+			if ( n & 1 )
+				entry[ n + 2 + 2 ] = 0;
+			if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n + 1 ) )
+				return 0;
+		}
+
+		// Sort the symbols
+		qsort( objsymbols.data, objsymbols.dim, 4, /*(cmpfunc_t)*/&D_NameCompare );
+
+		// Add each of the symbols
+		for (int i = 0; i < objsymbols.dim; i++)
+		{	
+			ObjSymbol* os = cast(ObjSymbol*)objsymbols.data[i];
+
+			ushort n = cast(ushort)strlen(os.name);
+			if (n > 255)
+			{   
+				entry[0] = 0xFF;
+				entry[1] = 0;
+				*cast(ushort*)(entry.ptr + 2) = n;
+				memcpy(entry.ptr + 4, os.name, n);
+				n += 3;
+			}
+			else
+			{   
+				entry[ 0 ] = cast(ubyte)n;
+				memcpy( entry.ptr + 1, os.name, n );
+			}
+			*(cast(ushort*)( n + 1 + entry.ptr )) = os.om.page;
+			if ( (n & 1) == 0 )
+				entry[ n + 3] = 0;
+			if ( !EnterDict( bucketsP, ndicpages, entry.ptr, n ) )
+			{
+				return 0;
+			}
+		}
+
+		return 1;
+	}
+	
+	/**********************************************
+	 * Create and write library to libbuf.
+	 * The library consists of:
+	 *	library header
+	 *	object modules...
+	 *	dictionary header
+	 *	dictionary pages...
+	 */
+    void WriteLibToBuffer(OutBuffer libbuf)
+	{
+		/* Scan each of the object modules for symbols
+		 * to go into the dictionary
+		 */
+		for (int i = 0; i < objmodules.dim; i++)
+		{   
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+			scanObjModule(om);
+		}
+
+		uint g_page_size = 16;
+
+		/* Calculate page size so that the number of pages
+		 * fits in 16 bits. This is because object modules
+		 * are indexed by page number, stored as an unsigned short.
+		 */
+		while (1)
+		{
+		  Lagain:
+	version (LOG) {
+			printf("g_page_size = %d\n", g_page_size);
+	}
+			uint offset = g_page_size;
+
+			for (int i = 0; i < objmodules.dim; i++)
+			{   
+				ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+				uint page = offset / g_page_size;
+				if (page > 0xFFFF)
+				{
+					// Page size is too small, double it and try again
+					g_page_size *= 2;
+					goto Lagain;
+				}
+
+				// Write out the object module m
+				if (om.flags & MFgentheadr)		// if generate THEADR record
+				{
+					size_t size = strlen(om.name);
+					assert(size <= LIBIDMAX);
+
+					offset += size + 5;
+					//offset += om.length - (size + 5);
+					offset += om.length;
+				}
+				else
+					offset += om.length;
+
+				// Round the size of the file up to the next page size
+				// by filling with 0s
+				uint n = (g_page_size - 1) & offset;
+				if (n)
+					offset += g_page_size - n;
+			}
+			break;
+		}
+
+
+		/* Leave one page of 0s at start as a dummy library header.
+		 * Fill it in later with the real data.
+		 */
+		libbuf.fill0(g_page_size);
+
+		/* Write each object module into the library
+		 */
+		for (int i = 0; i < objmodules.dim; i++)
+		{	
+			ObjModule* om = cast(ObjModule*)objmodules.data[i];
+
+			uint page = libbuf.offset / g_page_size;
+			assert(page <= 0xFFFF);
+			om.page = cast(ushort)page;
+
+			// Write out the object module om
+			if (om.flags & MFgentheadr)		// if generate THEADR record
+			{
+				uint size = strlen(om.name);
+				ubyte header[4 + LIBIDMAX + 1];
+
+				header [0] = THEADR;
+				header [1] = cast(ubyte)(2 + size);
+				header [2] = 0;
+				header [3] = cast(ubyte)size;
+				assert(size <= 0xFF - 2);
+
+				memcpy(4 + header.ptr, om.name, size);
+
+				// Compute and store record checksum
+				uint n = size + 4;
+				ubyte checksum = 0;
+				ubyte* p = header.ptr;
+				while (n--)
+				{	
+					checksum -= *p;
+					p++;
+				}
+				*p = checksum;
+
+				libbuf.write(header.ptr, size + 5);
+				//libbuf.write(om.base, om.length - (size + 5));
+				libbuf.write(om.base, om.length);
+			}
+			else
+				libbuf.write(om.base, om.length);
+
+			// Round the size of the file up to the next page size
+			// by filling with 0s
+			uint n = (g_page_size - 1) & libbuf.offset;
+			if (n)
+				libbuf.fill0(g_page_size - n);
+		}
+
+		// File offset of start of dictionary
+		uint offset = libbuf.offset;
+
+		// Write dictionary header, then round it to a BUCKETPAGE boundary
+		ushort size = (BUCKETPAGE - (cast(short)offset + 3)) & (BUCKETPAGE - 1);
+		libbuf.writeByte(0xF1);
+		libbuf.writeword(size);
+		libbuf.fill0(size);
+
+		// Create dictionary
+		ubyte* bucketsP = null;
+		ushort ndicpages;
+		ushort padding = 32;
+		for (;;)
+		{
+			ndicpages = numDictPages(padding);
+
+		version (LOG) {
+			printf("ndicpages = %d\n", ndicpages);
+		}
+			// Allocate dictionary
+			if (bucketsP)
+				bucketsP = cast(ubyte*)realloc(bucketsP, ndicpages * BUCKETPAGE);
+			else
+				bucketsP = cast(ubyte*)malloc(ndicpages * BUCKETPAGE);
+			assert(bucketsP);
+			memset(bucketsP, 0, ndicpages * BUCKETPAGE);
+			for (uint u = 0; u < ndicpages; u++)
+			{
+				// 'next available' slot
+				bucketsP[u * BUCKETPAGE + HASHMOD] = (HASHMOD + 1) >> 1;
+			}
+
+			if (FillDict(bucketsP, ndicpages)) 
+				break;
+			padding += 16;      // try again with more margins
+		}
+
+		// Write dictionary
+		libbuf.write(bucketsP, ndicpages * BUCKETPAGE);
+		if (bucketsP)
+			free(bucketsP);
+
+		// Create library header
+		Libheader libHeader;
+		memset(&libHeader, 0, Libheader.sizeof);
+		libHeader.recTyp = 0xF0;
+		libHeader.recLen  = 0x0D;
+		libHeader.trailerPosn = offset + (3 + size);
+		libHeader.recLen = cast(ushort)(g_page_size - 3);
+		libHeader.ndicpages = ndicpages;
+		libHeader.flags = 1;		// always case sensitive
+
+		// Write library header at start of buffer
+		memcpy(libbuf.data, &libHeader, libHeader.sizeof);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/LineInitExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,26 @@
+module dmd.LineInitExp;
+
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.DefaultInitExp;
+import dmd.TOK;
+
+class LineInitExp : DefaultInitExp
+{
+	this(Loc loc)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression resolve(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/LinkDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,75 @@
+module dmd.LinkDeclaration;
+
+import dmd.AttribDeclaration;
+import dmd.LINK;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.Array;
+
+class LinkDeclaration : AttribDeclaration
+{
+    LINK linkage;
+
+    this(LINK p, Array decl)
+	{
+		super(decl);
+		//printf("LinkDeclaration(linkage = %d, decl = %p)\n", p, decl);
+		linkage = p;
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+
+    void setScope(Scope sc)
+	{
+		//printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl);
+		if (decl)
+		{
+			setScopeNewSc(sc, sc.stc, linkage, sc.protection, sc.explicitProtection, sc.structalign);
+		}
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
+		if (decl)
+		{
+			semanticNewSc(sc, sc.stc, linkage, sc.protection, sc.explicitProtection, sc.structalign);
+		}
+	}
+	
+    void semantic3(Scope sc)
+	{
+		//printf("LinkDeclaration::semantic3(linkage = %d, decl = %p)\n", linkage, decl);
+		if (decl)
+		{	
+			LINK linkage_save = sc.linkage;
+
+			sc.linkage = linkage;
+			for (uint i = 0; i < decl.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)decl.data[i];
+				s.semantic3(sc);
+			}
+			sc.linkage = linkage_save;
+		}
+		else
+		{
+			sc.linkage = linkage;
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Loc.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,43 @@
+module dmd.Loc;
+
+import dmd.Module;
+import dmd.OutBuffer;
+
+struct Loc
+{
+    string filename;
+    uint linnum;
+
+    this(int x)
+    {
+		linnum = x;
+		filename = null;
+    }
+
+    this(Module mod, uint linnum)
+	{
+		this.linnum = linnum;
+		this.filename = mod ? mod.srcfile.toChars() : null;
+	}
+
+    string toChars()
+	{
+		scope OutBuffer buf = new OutBuffer();
+
+		if (filename !is null) {
+			buf.printf("%s", filename);
+		}
+
+		if (linnum) {
+			buf.printf("(%d)", linnum);
+			buf.writeByte(0);
+		}
+
+		return buf.extractString();
+	}
+
+    bool equals(ref const(Loc) loc)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Lstring.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,73 @@
+module dmd.Lstring;
+
+import dmd.Dchar;
+
+struct Lstring
+{
+    immutable(dchar_t)[] string_;
+
+    static Lstring zero;	// 0 length string
+
+    // No constructors because we want to be able to statically
+    // initialize Lstring's, and Lstrings are of variable size.
+
+version (M_UNICODE) {
+    ///#define LSTRING(p,length) { length, L##p }
+} else {
+    ///#define LSTRING(p,length) { length, p }
+}
+
+///#if __GNUC__
+///    #define LSTRING_EMPTY() { 0 }
+///#else
+///    #define LSTRING_EMPTY() LSTRING("", 0)
+///#endif
+
+    static Lstring* ctor(const(dchar_t)* p) { return ctor(p, Dchar.len(p)); }
+    
+	static Lstring* ctor(const(dchar_t)* p, uint length)
+	{
+		assert(false);
+	}
+	
+    static uint size(uint length) { return Lstring.sizeof + (length + 1) * dchar_t.sizeof; }
+	
+    static Lstring* alloc(uint length)
+	{
+		assert(false);
+	}
+	
+    Lstring* clone()
+	{
+		assert(false);
+	}
+
+    uint len() { return string_.length; }
+
+    const(dchar_t)[] toDchars() { return string_; }
+
+    hash_t hash() { return Dchar.calcHash(string_.ptr, string_.length); }
+    hash_t ihash() { return Dchar.icalcHash(string_.ptr, string_.length); }
+
+    static int cmp(const(Lstring)* s1, const(Lstring)* s2)
+    {
+		int c = s2.string_.length - s1.string_.length;
+		return c ? c : Dchar.memcmp(s1.string_.ptr, s2.string_.ptr, s1.string_.length);
+    }
+
+    static int icmp(const(Lstring)* s1, const(Lstring)* s2)
+    {
+		int c = s2.string_.length - s1.string_.length;
+		return c ? c : Dchar.memicmp(s1.string_.ptr, s2.string_.ptr, s1.string_.length);
+    }
+
+    Lstring* append(const(Lstring)* s)
+	{
+		assert(false);
+	}
+	
+    Lstring* substring(int start, int end)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/MATCH.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,24 @@
+module dmd.MATCH;
+
+version (DMDV2) {
+	enum MATCH
+	{
+		MATCHnomatch,	// no match
+		MATCHconvert,	// match with conversions
+
+		MATCHconst,		// match with conversion to const
+
+		MATCHexact		// exact match
+	}
+} else {
+	enum MATCH
+	{
+		MATCHnomatch,	// no match
+		MATCHconvert,	// match with conversions
+
+		MATCHexact		// exact match
+	}
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(MATCH));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/MOD.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,12 @@
+module dmd.MOD;
+
+enum MOD
+{
+	MODundefined = 0,
+	MODconst = 1,	// type is const
+	MODshared = 2,	// type is shared
+	MODinvariant = 4,	// type is invariant
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(MOD));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Macro.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,5 @@
+module dmd.Macro;
+
+struct Macro	/// ???
+{
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/MinAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,93 @@
+module dmd.MinAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TY;
+import dmd.TOK;
+import dmd.Id;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class MinAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKminass, MinAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (type)
+			return this;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		if (e1.op == TOKslice)
+		{	// T[] -= ...
+			typeCombine(sc);
+			type = e1.type;
+			return arrayOp(sc);
+		}
+
+		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);
+			if (type.isreal() || type.isimaginary())
+			{
+				assert(e2.type.isfloating());
+				e2 = e2.castTo(sc, e1.type);
+			}
+			e = this;
+		}
+		return e;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.subass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs,OPminass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/MinExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,179 @@
+module dmd.MinExp;
+
+import dmd.Expression;
+import dmd.TY;
+import dmd.ErrorExp;
+import dmd.Identifier;
+import dmd.IntegerExp;
+import dmd.DivExp;
+import dmd.Type;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Id;
+import dmd.expression.Min;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class MinExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKmin, MinExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t1;
+		Type t2;
+
+version (LOGSEMANTIC) {
+		printf("MinExp.semantic('%s')\n", toChars());
+}
+		if (type)
+			return this;
+
+		super.semanticp(sc);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		e = this;
+		t1 = e1.type.toBasetype();
+		t2 = e2.type.toBasetype();
+		if (t1.ty == TY.Tpointer)
+		{
+			if (t2.ty == TY.Tpointer)
+			{   // Need to divide the result by the stride
+				// Replace (ptr - ptr) with (ptr - ptr) / stride
+				long stride;
+				Expression ee;
+
+				typeCombine(sc);		// make sure pointer types are compatible
+				type = Type.tptrdiff_t;
+				stride = t2.nextOf().size();
+				if (stride == 0)
+				{
+					ee = new IntegerExp(loc, 0, Type.tptrdiff_t);
+				}
+				else
+				{
+					ee = new DivExp(loc, this, new IntegerExp(Loc(0), stride, Type.tptrdiff_t));
+					ee.type = Type.tptrdiff_t;
+				}
+				return ee;
+			}
+			else if (t2.isintegral())
+				e = scaleFactor(sc);
+			else
+			{   
+				error("incompatible types for minus");
+				return new ErrorExp();
+			}
+		}
+		else if (t2.ty == TY.Tpointer)
+		{
+			type = e2.type;
+			error("can't subtract pointer from %s", e1.type.toChars());
+			return new ErrorExp();
+		}
+		else
+		{
+			typeCombine(sc);
+			t1 = e1.type.toBasetype();
+			t2 = e2.type.toBasetype();
+			if ((t1.isreal() && t2.isimaginary()) ||
+				(t1.isimaginary() && t2.isreal()))
+			{
+				switch (type.ty)
+				{
+					case TY.Tfloat32:
+					case TY.Timaginary32:
+						type = Type.tcomplex32;
+						break;
+
+					case TY.Tfloat64:
+					case TY.Timaginary64:
+						type = Type.tcomplex64;
+						break;
+
+					case TY.Tfloat80:
+					case TY.Timaginary80:
+						type = Type.tcomplex80;
+						break;
+
+					default:
+						assert(0);
+				}
+			}
+		}
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() && e2.isConst())
+		{
+			if (e2.op == TOK.TOKsymoff)
+				return this;
+			e = Min(type, e1, e2);
+		}
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.sub;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.sub_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		Type tb1 = e1.type.toBasetype();
+		Type tb2 = e2.type.toBasetype();
+
+		if ((tb1.ty == TY.Tarray || tb1.ty == TY.Tsarray) && (tb2.ty == TY.Tarray || tb2.ty == TY.Tsarray))
+		{
+			error("Array operation %s not implemented", toChars());
+			return el_long(type.totym(), 0);	// error recovery
+		}
+
+		return toElemBin(irs, OPER.OPmin);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ModAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,53 @@
+module dmd.ModAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+
+import dmd.backend.elem;
+
+class ModAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		assert(false);
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ModExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,150 @@
+module dmd.ModExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Id;
+import dmd.ErrorExp;
+
+import dmd.expression.Util;
+import dmd.expression.Mod;
+import dmd.backend.RTLSYM;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class ModExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKmod, ModExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (type)
+			return this;
+
+		BinExp.semanticp(sc);
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		typeCombine(sc);
+		if (e1.op != TOKslice && e2.op != TOKslice)
+		{	
+			e1.checkArithmetic();
+			e2.checkArithmetic();
+		}
+		if (type.isfloating())
+		{	
+			type = e1.type;
+			if (e2.type.iscomplex())
+			{   
+				error("cannot perform modulo complex arithmetic");
+				return new ErrorExp();
+			}
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() == 1 && e2.isConst() == 1)
+		{
+			e = Mod(type, e1, e2);
+		}
+		else
+			e = this;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.mod;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.mod_r;
+	}
+
+	elem* 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);
+
+	static if (false) { // 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
+		{
+			e = el_bin(OPmod,tym,e1,e2);
+			el_setLoc(e,loc);
+		}
+	} else {
+		e = el_bin(OPmod,tym,e1,e2);
+		el_setLoc(e,loc);
+	}
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Module.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1564 @@
+module dmd.Module;
+
+import dmd.Package;
+import dmd.DsymbolTable;
+import dmd.backend.TYM;
+import dmd.Array;
+import dmd.StaticDtorDeclaration;
+import dmd.Scope;
+import dmd.Id;
+import dmd.Import;
+import dmd.ClassDeclaration;
+import dmd.ModuleDeclaration;
+import dmd.File;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.ModuleInfoDeclaration;
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.Macro;
+import dmd.Escape;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.FileName;
+import dmd.Global;
+import dmd.Parser;
+import dmd.Lexer;
+import dmd.Util;
+import dmd.String;
+import dmd.ScopeDsymbol;
+import dmd.Type;
+import dmd.backend.TYPE;
+import dmd.backend.Cstate;
+import dmd.backend.OPER;
+import dmd.backend.REG;
+import dmd.backend.Symbol;
+import dmd.backend.elem;
+import dmd.backend.mTYman;
+import dmd.backend.Util;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.backend.TF;
+import dmd.backend.RTLSYM;
+import dmd.backend.BC;
+import dmd.backend.block;
+import dmd.backend.targ_types;
+import dmd.backend.dt_t;
+import dmd.backend.TYM;
+import dmd.backend.Util;
+import dmd.backend.Classsym;
+import dmd.backend.glue;
+import dmd.backend.LIST;
+import dmd.codegen.Util;
+
+import core.stdc.string;
+import core.stdc.stdlib;
+
+uint readwordLE(ushort* p)
+{
+version (__I86__) {
+    return *p;
+} else {
+    return ((cast(ubyte*)p)[1] << 8) | (cast(ubyte*)p)[0];
+}
+}
+
+uint readwordBE(ushort* p)
+{
+    return ((cast(ubyte*)p)[0] << 8) | (cast(ubyte*)p)[1];
+}
+
+uint readlongLE(uint* p)
+{
+version (__I86__) {
+    return *p;
+} else {
+    return (cast(ubyte*)p)[0] |
+	((cast(ubyte*)p)[1] << 8) |
+	((cast(ubyte*)p)[2] << 16) |
+	((cast(ubyte*)p)[3] << 24);
+}
+}
+
+uint readlongBE(uint* p)
+{
+    return (cast(ubyte*)p)[3] |
+	((cast(ubyte*)p)[2] << 8) |
+	((cast(ubyte*)p)[1] << 16) |
+	((cast(ubyte*)p)[0] << 24);
+}
+
+/* Segments	*/
+enum Segment {
+	CODE = 1,	/* code segment			*/
+	DATA = 2,	/* initialized data		*/
+	CDATA = 3,	/* constant data		*/
+	UDATA = 4,	/* uninitialized data		*/
+	UNKNOWN	= -1,	/* unknown segment		*/
+}
+
+struct seg_data 
+{
+    int              SDseg;		// omf file segment index
+    targ_size_t		 SDoffset;	// starting offset for data
+
+    bool isfarseg;
+    int seg;				// segment number
+    int lnameidx;			// lname idx of segment name
+    int classidx;			// lname idx of class name
+    uint attr;			// segment attribute
+    targ_size_t origsize;		// original size
+    int seek;				// seek position in output file
+}
+
+extern (C) extern __gshared seg_data** SegData;
+
+ref targ_size_t Offset(Segment seg) {
+	return SegData[seg].SDoffset;
+}
+
+ref targ_size_t Doffset() {
+	return SegData[Segment.DATA].SDoffset;
+}
+
+ref targ_size_t CDoffset() {
+	return SegData[Segment.CDATA].SDoffset;
+}
+
+ref targ_size_t UDoffset() {
+	return SegData[Segment.UDATA].SDoffset;
+}
+
+enum CF {
+	CFes	        = 1,	// generate an ES: segment override for this instr
+	CFjmp16	        =  2,	// need 16 bit jump offset (long branch)
+	CFtarg	        =  4,	// this code is the target of a jump
+	CFseg	        =  8,	// get segment of immediate value
+	CFoff	       = 0x10,	// get offset of immediate value
+	CFss	       = 0x20,	// generate an SS: segment override (not with
+			// CFes at the same time, though!)
+	CFpsw	       = 0x40,	// we need the flags result after this instruction
+	CFopsize       = 0x80,	// prefix with operand size
+	CFaddrsize    = 0x100, 	// prefix with address size
+	CFds	      = 0x200,	// need DS override (not with es, ss, or cs )	
+	CFcs	      = 0x400,	// need CS override
+	CFfs	      = 0x800,	// need FS override
+	CFgs	= (CFcs | CFfs),	// need GS override
+	CFwait      = 0x1000,	// If I32 it indicates when to output a WAIT
+	CFselfrel   = 0x2000, 	// if self-relative
+	CFunambig   = 0x4000,    	// indicates cannot be accessed by other addressing
+				// modes
+	CFtarg2	    = 0x8000,	// like CFtarg, but we can't optimize this away
+	CFvolatile  = 0x10000,	// volatile reference, do not schedule
+	CFclassinit = 0x20000,	// class init code
+
+	CFSEG	= (CFes | CFss | CFds | CFcs | CFfs | CFgs),
+	CFPREFIX = (CFSEG | CFopsize | CFaddrsize),
+}
+
+class Module : Package
+{
+    static Module rootModule;
+    static DsymbolTable modules;	// symbol table of all modules
+    static Array amodules;		// array of all modules
+    static Array deferred;	// deferred Dsymbol's needing semantic() run on them
+    static uint dprogress;	// progress resolving the deferred list
+
+    static void init()
+	{
+		modules = new DsymbolTable();
+		amodules = new Array();
+		deferred = new Array();
+	}
+
+    static ClassDeclaration moduleinfo;
+
+
+    string arg;	// original argument name
+    ModuleDeclaration md; // if !null, the contents of the ModuleDeclaration declaration
+    File srcfile;	// input source file
+    File objfile;	// output .obj file
+    File hdrfile;	// 'header' file
+    File symfile;	// output symbol file
+    File docfile;	// output documentation file
+    uint errors;	// if any errors in file
+    uint numlines;	// number of lines in source file
+    int isHtml;		// if it is an HTML file
+    int isDocFile;	// if it is a documentation input file, not D source
+    int needmoduleinfo; /// TODO: change to bool
+version (IN_GCC) {
+    int strictlyneedmoduleinfo;
+}
+
+    int selfimports;		// 0: don't know, 1: does not, 2: does
+    int selfImports()		// returns !=0 if module imports itself
+	{
+		assert(false);
+	}
+
+    int insearch;
+    Identifier searchCacheIdent;
+    Dsymbol searchCacheSymbol;	// cached value of search
+    int searchCacheFlags;	// cached flags
+
+    int semanticstarted;	// has semantic() been started?
+    int semanticRun;		// has semantic() been done?
+    int root;			// != 0 if this is a 'root' module,
+				// i.e. a module that will be taken all the
+				// way to an object file
+    Module importedFrom;	// module from command line we're imported from,
+				// i.e. a module that will be taken all the
+				// way to an object file
+
+    Array decldefs;		// top level declarations for this Module
+
+    Array aimports;		// all imported modules
+
+    ModuleInfoDeclaration vmoduleinfo;
+
+    uint debuglevel;	// debug level
+    Array debugids;		// debug identifiers
+    Array debugidsNot;		// forward referenced debug identifiers
+
+    uint versionlevel;	// version level
+    Array versionids;		// version identifiers
+    Array versionidsNot;	// forward referenced version identifiers
+
+    Macro macrotable;		// document comment macros
+    Escape escapetable;	// document comment escapes
+    bool safe;			// TRUE if module is marked as 'safe'
+
+    this(string filename, Identifier ident, int doDocComment, int doHdrGen)
+	{
+		super(ident);
+		FileName objfilename;
+		
+		aimports = new Array();
+
+	    //writef("Module.Module(filename = '%s', ident = '%s')\n", filename, ident.toChars());
+		this.arg = filename;
+
+		FileName srcfilename = FileName.defaultExt(filename, global.mars_ext);
+		if (!srcfilename.equalsExt(global.mars_ext) &&
+			!srcfilename.equalsExt(global.hdr_ext) &&
+			!srcfilename.equalsExt("dd"))
+		{
+			if (srcfilename.equalsExt("html") ||
+				srcfilename.equalsExt("htm")  ||
+				srcfilename.equalsExt("xhtml"))
+			{
+				if (!global.params.useDeprecated)
+					error("html source files is deprecated %s", srcfilename.toChars());
+				isHtml = 1;
+			}
+			else
+			{
+				error("source file name '%s' must have .%s extension", srcfilename.toChars(), global.mars_ext);
+				fatal();
+			}
+		}
+
+		string argobj;
+		if (global.params.objname)
+			argobj = global.params.objname;
+		else if (global.params.preservePaths)
+			argobj = filename;
+		else
+			argobj = FileName.name(filename);
+		if (!FileName.absolute(argobj))
+		{
+			argobj = FileName.combine(global.params.objdir, argobj);
+		}
+
+		if (global.params.objname)
+			objfilename = new FileName(argobj);
+		else
+			objfilename = FileName.forceExt(argobj, global.obj_ext);
+
+		FileName symfilename = FileName.forceExt(filename, global.sym_ext);
+
+		srcfile = new File(srcfilename);
+
+		if (doDocComment) {
+			setDocfile();
+		}
+
+		if (doHdrGen) {
+			setHdrfile();
+		}
+
+		objfile = new File(objfilename);
+		symfile = new File(symfilename);
+	}
+
+    static Module load(Loc loc, Array packages, Identifier ident)
+	{
+		Module m;
+		string filename;
+
+		//writef("Module.load(ident = '%s')\n", ident.toChars());
+
+		// Build module filename by turning:
+		//	foo.bar.baz
+		// into:
+		//	foo\bar\baz
+		filename = ident.toChars();
+		if (packages && packages.dim)
+		{
+			scope OutBuffer buf = new OutBuffer();
+			int i;
+
+			for (i = 0; i < packages.dim; i++)
+			{   
+				Identifier pid = cast(Identifier)packages.data[i];
+
+				buf.writestring(pid.toChars());
+version (_WIN32) {
+				buf.writeByte('\\');
+} else {
+				buf.writeByte('/');
+}
+			}
+			buf.writestring(filename);
+			filename = buf.extractString();
+		}
+
+		m = new Module(filename, ident, 0, 0);
+		m.loc = loc;
+
+		/* Search along global.path for .di file, then .d file.
+		 */
+		string result = null;
+		FileName fdi = FileName.forceExt(filename, global.hdr_ext);
+		FileName fd  = FileName.forceExt(filename, global.mars_ext);
+		string sdi = fdi.toChars();
+		string sd  = fd.toChars();
+		
+		if (FileName.exists(sdi)) {
+			result = sdi;
+		} else if (FileName.exists(sd)) {
+			result = sd;
+		} else if (FileName.absolute(filename)) {
+			;
+		}
+		else
+		{
+			foreach (p; global.path)
+			{
+				string n = FileName.combine(p, sdi);
+
+				if (FileName.exists(n))
+				{
+					result = n;
+					break;
+				}
+
+				n = FileName.combine(p, sd);
+				if (FileName.exists(n))
+				{
+					result = n;
+					break;
+				}
+			}
+		}
+
+		if (result)
+			m.srcfile = new File(result);
+
+		if (global.params.verbose)
+		{
+			writef("import    ");
+			if (packages)
+			{
+				for (size_t i = 0; i < packages.dim; i++)
+				{   
+					Identifier pid = cast(Identifier)packages.data[i];
+					writef("%s.", pid.toChars());
+				}
+			}
+			writef("%s\t(%s)\n", ident.toChars(), m.srcfile.toChars());
+		}
+
+		m.read(loc);
+		m.parse();
+
+version (IN_GCC) {
+		d_gcc_magic_module(m);
+}
+
+		return m;
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		return "module";
+	}
+	
+    void setDocfile()	// set docfile member
+	{
+		assert(false);
+	}
+	
+    void read(Loc loc)	// read file
+	{
+		//writef("Module.read('%s') file '%s'\n", toChars(), srcfile.toChars());
+		if (srcfile.read())
+		{
+			error(loc, "cannot read file '%s'", srcfile.toChars());
+			fatal();
+		}
+	}
+	
+version (IN_GCC) {
+    void parse(bool dump_source = false)	// syntactic parse
+	{
+		assert(false);
+	}
+} else {
+    void parse()	// syntactic parse
+	{
+		uint le;
+		uint bom;
+
+		//printf("Module.parse()\n");
+
+		string srcname = srcfile.name.toChars();
+		//printf("Module.parse(srcname = '%s')\n", srcname);
+
+		ubyte* buf = srcfile.buffer;
+		uint buflen = srcfile.len;
+
+		if (buflen >= 2)
+		{
+		/* Convert all non-UTF-8 formats to UTF-8.
+		 * BOM : http://www.unicode.org/faq/utf_bom.html
+		 * 00 00 FE FF	UTF-32BE, big-endian
+		 * FF FE 00 00	UTF-32LE, little-endian
+		 * FE FF	UTF-16BE, big-endian
+		 * FF FE	UTF-16LE, little-endian
+		 * EF BB BF	UTF-8
+		 */
+
+		bom = 1;		// assume there's a BOM
+		if (buf[0] == 0xFF && buf[1] == 0xFE)
+		{
+			if (buflen >= 4 && buf[2] == 0 && buf[3] == 0)
+			{	// UTF-32LE
+			le = 1;
+
+			Lutf32:
+			OutBuffer dbuf;
+			uint* pu = cast(uint*)buf;
+			uint* pumax = &pu[buflen / 4];
+
+			if (buflen & 3)
+			{   error("odd length of UTF-32 char source %u", buflen);
+				fatal();
+			}
+
+			dbuf.reserve(buflen / 4);
+			for (pu += bom; pu < pumax; pu++)
+			{  
+				uint u = le ? readlongLE(pu) : readlongBE(pu);
+				if (u & ~0x7F)
+				{
+					if (u > 0x10FFFF)
+					{   error("UTF-32 value %08x greater than 0x10FFFF", u);
+						fatal();
+					}
+					dbuf.writeUTF8(u);
+				}
+				else
+					dbuf.writeByte(u);
+			}
+			dbuf.writeByte(0);		// add 0 as sentinel for scanner
+			buflen = dbuf.offset - 1;	// don't include sentinel in count
+			buf = cast(ubyte*) dbuf.extractData();
+			}
+			else
+			{   
+				// UTF-16LE (X86)
+				// Convert it to UTF-8
+				le = 1;
+
+				Lutf16:
+				OutBuffer dbuf;
+				ushort* pu = cast(ushort*)(buf);
+				ushort *pumax = &pu[buflen / 2];
+
+				if (buflen & 1)
+				{   error("odd length of UTF-16 char source %u", buflen);
+					fatal();
+				}
+
+				dbuf.reserve(buflen / 2);
+				for (pu += bom; pu < pumax; pu++)
+				{
+					uint u = le ? readwordLE(pu) : readwordBE(pu);
+					if (u & ~0x7F)
+					{
+						if (u >= 0xD800 && u <= 0xDBFF)
+						{   uint u2;
+
+							if (++pu > pumax)
+							{   error("surrogate UTF-16 high value %04x at EOF", u);
+							fatal();
+							}
+							u2 = le ? readwordLE(pu) : readwordBE(pu);
+							if (u2 < 0xDC00 || u2 > 0xDFFF)
+							{   error("surrogate UTF-16 low value %04x out of range", u2);
+							fatal();
+							}
+							u = (u - 0xD7C0) << 10;
+							u |= (u2 - 0xDC00);
+						}
+						else if (u >= 0xDC00 && u <= 0xDFFF)
+						{
+							error("unpaired surrogate UTF-16 value %04x", u);
+							fatal();
+						}
+						else if (u == 0xFFFE || u == 0xFFFF)
+						{
+							error("illegal UTF-16 value %04x", u);
+							fatal();
+						}
+						dbuf.writeUTF8(u);
+					}
+					else
+						dbuf.writeByte(u);
+				}
+				dbuf.writeByte(0);		// add 0 as sentinel for scanner
+				buflen = dbuf.offset - 1;	// don't include sentinel in count
+				buf = cast(ubyte*) dbuf.extractData();
+			}
+		}
+		else if (buf[0] == 0xFE && buf[1] == 0xFF)
+		{   // UTF-16BE
+			le = 0;
+			goto Lutf16;
+		}
+		else if (buflen >= 4 && buf[0] == 0 && buf[1] == 0 && buf[2] == 0xFE && buf[3] == 0xFF)
+		{   // UTF-32BE
+			le = 0;
+			goto Lutf32;
+		}
+		else if (buflen >= 3 && buf[0] == 0xEF && buf[1] == 0xBB && buf[2] == 0xBF)
+		{   // UTF-8
+
+			buf += 3;
+			buflen -= 3;
+		}
+		else
+		{
+			/* There is no BOM. Make use of Arcane Jill's insight that
+			 * the first char of D source must be ASCII to
+			 * figure out the encoding.
+			 */
+
+			bom = 0;
+			if (buflen >= 4)
+			{   if (buf[1] == 0 && buf[2] == 0 && buf[3] == 0)
+			{   // UTF-32LE
+				le = 1;
+				goto Lutf32;
+			}
+			else if (buf[0] == 0 && buf[1] == 0 && buf[2] == 0)
+			{   // UTF-32BE
+				le = 0;
+				goto Lutf32;
+			}
+			}
+			if (buflen >= 2)
+			{
+			if (buf[1] == 0)
+			{   // UTF-16LE
+				le = 1;
+				goto Lutf16;
+			}
+			else if (buf[0] == 0)
+			{   // UTF-16BE
+				le = 0;
+				goto Lutf16;
+			}
+			}
+
+			// It's UTF-8
+			if (buf[0] >= 0x80)
+			{	error("source file must start with BOM or ASCII character, not \\x%02X", buf[0]);
+			fatal();
+			}
+		}
+		}
+
+version (IN_GCC) {
+		// dump utf-8 encoded source 
+		if (dump_source)
+		{	// %% srcname could contain a path ...
+			d_gcc_dump_source(srcname, "utf-8", buf, buflen);
+		}
+}
+
+		/* If it starts with the string "Ddoc", then it's a documentation
+		 * source file.
+		 */
+		if (buflen >= 4 && memcmp(buf, "Ddoc".ptr, 4) == 0)
+		{
+		comment = buf + 4;
+		isDocFile = 1;
+		if (!docfile)
+			setDocfile();
+		return;
+		}
+		if (isHtml)
+		{
+			assert(false);
+			///OutBuffer dbuf = new OutBuffer();
+			///Html h = new Html(srcname, buf, buflen);
+			///h.extractCode(dbuf);
+			///buf = dbuf.data;
+			///buflen = dbuf.offset;
+
+version (IN_GCC) {
+			// dump extracted source
+			///if (dump_source)
+			///	d_gcc_dump_source(srcname, "d.utf-8", buf, buflen);
+}
+		}
+
+		Parser p = new Parser(this, buf, buflen, docfile !is null);
+		p.nextToken();
+		members = p.parseModule();
+		md = p.md;
+		numlines = p.loc.linnum;
+
+		DsymbolTable dst;
+
+		if (md !is null)
+		{
+			this.ident = md.id;
+			this.safe = md.safe;
+			dst = super.resolve(md.packages, &this.parent, null);
+		}
+		else
+		{
+			dst = modules;
+
+			/* Check to see if module name is a valid identifier
+			 */
+			if (!Lexer.isValidIdentifier(this.ident.toChars()))
+				error("has non-identifier characters in filename, use module declaration instead");
+			}
+			
+			// Update global list of modules
+			if (!dst.insert(this))
+			{
+				if (md)
+					error(loc, "is in multiple packages %s", md.toChars());
+				else
+					error(loc, "is in multiple defined");
+			}
+			else
+			{
+				amodules.push(cast(void*)this);
+			}
+		}
+	}
+
+    void semantic()	// semantic analysis
+	{
+		int i;
+
+		if (semanticstarted)
+			return;
+
+		//printf("+Module.semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
+		semanticstarted = 1;
+
+		// Note that modules get their own scope, from scratch.
+		// This is so regardless of where in the syntax a module
+		// gets imported, it is unaffected by context.
+		Scope sc = Scope.createGlobal(this);	// create root scope
+
+		//printf("Module = %p, linkage = %d\n", sc.scopesym, sc.linkage);
+
+		// Add import of "object" if this module isn't "object"
+		if (ident !is Id.object)
+		{
+			Import im = new Import(Loc(0), null, Id.object, null, 0);
+			members.shift(cast(void*)im);
+		}
+
+		// Add all symbols into module's symbol table
+		symtab = new DsymbolTable();
+		for (i = 0; i < members.dim; i++)
+		{	
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.addMember(null, sc.scopesym, 1);
+		}
+
+		/* Set scope for the symbols so that if we forward reference
+		 * a symbol, it can possibly be resolved on the spot.
+		 * If this works out well, it can be extended to all modules
+		 * before any semantic() on any of them.
+		 */
+		for (i = 0; i < members.dim; i++)
+		{	
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.setScope(sc);
+		}
+
+		// Pass 1 semantic routines: do public side of the definition
+		for (i = 0; i < members.dim; i++)
+		{	
+			Dsymbol s = cast(Dsymbol)members.data[i];
+
+			//writef("\tModule('%s'): '%s'.semantic()\n", toChars(), s.toChars());
+			s.semantic(sc);
+			runDeferredSemantic();
+		}
+
+		sc = sc.pop();
+		sc.pop();		// 2 pops because Scope.createGlobal() created 2
+		semanticRun = semanticstarted;
+		//printf("-Module.semantic(this = %p, '%s'): parent = %p\n", this, toChars(), parent);
+	}
+	
+    void semantic2()	// pass 2 semantic analysis
+	{
+		if (deferred.dim)
+		{
+			for (int i = 0; i < deferred.dim; i++)
+			{
+				Dsymbol sd = cast(Dsymbol)deferred.data[i];
+
+				sd.error("unable to resolve forward reference in definition");
+			}
+			return;
+		}
+		//printf("Module.semantic2('%s'): parent = %p\n", toChars(), parent);
+		if (semanticstarted >= 2)
+			return;
+		assert(semanticstarted == 1);
+		semanticstarted = 2;
+
+		// Note that modules get their own scope, from scratch.
+		// This is so regardless of where in the syntax a module
+		// gets imported, it is unaffected by context.
+		Scope sc = Scope.createGlobal(this);	// create root scope
+		//printf("Module = %p\n", sc.scopesym);
+
+		// Pass 2 semantic routines: do initializers and function bodies
+		for (int i = 0; i < members.dim; i++)
+		{	
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			s.semantic2(sc);
+		}
+
+		sc = sc.pop();
+		sc.pop();
+		semanticRun = semanticstarted;
+		//printf("-Module.semantic2('%s'): parent = %p\n", toChars(), parent);
+	}
+	
+    void semantic3()	// pass 3 semantic analysis
+	{
+		//printf("Module.semantic3('%s'): parent = %p\n", toChars(), parent);
+		if (semanticstarted >= 3)
+			return;
+		assert(semanticstarted == 2);
+		semanticstarted = 3;
+
+		// Note that modules get their own scope, from scratch.
+		// This is so regardless of where in the syntax a module
+		// gets imported, it is unaffected by context.
+		Scope sc = Scope.createGlobal(this);	// create root scope
+		//printf("Module = %p\n", sc.scopesym);
+
+		// Pass 3 semantic routines: do initializers and function bodies
+		for (int i = 0; i < members.dim; i++)
+		{	
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			//printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
+			s.semantic3(sc);
+		}
+
+		sc = sc.pop();
+		sc.pop();
+		semanticRun = semanticstarted;
+	}
+	
+    void inlineScan()	// scan for functions to inline
+	{
+		int i;
+
+		if (semanticstarted >= 4)
+			return;
+
+		assert(semanticstarted == 3);
+		semanticstarted = 4;
+
+		// Note that modules get their own scope, from scratch.
+		// This is so regardless of where in the syntax a module
+		// gets imported, it is unaffected by context.
+		//printf("Module = %p\n", sc.scopesym);
+
+		for (i = 0; i < members.dim; i++)
+		{	
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			//if (global.params.verbose)
+				//printf("inline scan symbol %s\n", s.toChars());
+			s.inlineScan();
+		}
+
+		semanticRun = semanticstarted;
+	}
+	
+    void setHdrfile()	// set hdrfile member
+	{
+		FileName hdrfilename;
+		string arghdr;
+
+		if (global.params.hdrname)
+			arghdr = global.params.hdrname;
+		else if (global.params.preservePaths)
+			arghdr = arg;
+		else
+			arghdr = FileName.name(arg);
+		if (!FileName.absolute(arghdr))
+		{	
+			//FileName.ensurePathExists(global.params.hdrdir);
+			arghdr = FileName.combine(global.params.hdrdir, arghdr);
+		}
+		if (global.params.hdrname)
+			hdrfilename = new FileName(arghdr);
+		else
+			hdrfilename = FileName.forceExt(arghdr, global.hdr_ext);
+
+		if (hdrfilename.str == srcfile.name.str)
+		{   
+			error("Source file and 'header' file have same name '%s'", srcfile.name.str);
+			fatal();
+		}
+
+		hdrfile = new File(hdrfilename);
+	}
+	
+version (_DH) {
+    void genhdrfile()  // generate D import file
+	{
+		assert(false);
+	}
+}
+	
+	/**************************************
+	 * Generate .obj file for Module.
+	 */
+    void genobjfile(int multiobj)
+	{
+		//EEcontext *ee = env.getEEcontext();
+
+		//printf("Module.genobjfile(multiobj = %d) %s\n", multiobj, toChars());
+
+		lastmname = srcfile.toChars();	/// global mutation
+
+		obj_initfile(toStringz(lastmname), null, toStringz(toPrettyChars()));
+
+		eictor = null;
+		ictorlocalgot = null;
+		ector = null;
+		ectorgates.setDim(0);
+		edtor = null;
+		etest = null;
+		dtorcount = 0;
+
+		if (doppelganger)
+		{
+			/* Generate a reference to the moduleinfo, so the module constructors
+			 * and destructors get linked in.
+			 */
+			Module m = cast(Module)aimports.data[0];
+			assert(m);
+			if (m.sictor || m.sctor || m.sdtor)
+			{
+				Symbol* s = m.toSymbol();
+				//objextern(s);
+				//if (!s.Sxtrnnum) objextdef(s.Sident);
+				if (!s.Sxtrnnum)
+				{
+					//printf("%s\n", s.Sident);
+static if (false) {
+					/* This should work, but causes optlink to fail in common/newlib.asm */
+					objextdef(s.Sident);
+} else {
+	version (XXX) {///ELFOBJ || MACHOBJ
+				int nbytes = reftoident(DATA, Offset(DATA), s, 0, CFoff);
+				Offset(DATA) += nbytes;
+	} else {
+				int nbytes = reftoident(Segment.DATA, Doffset, s, 0, CF.CFoff);
+				Doffset() += nbytes;
+	}
+}
+				}
+			}
+		}
+
+		if (global.params.cov)
+		{
+			/* Create coverage identifier:
+			 *  private uint[numlines] __coverage;
+			 */
+			cov = symbol_calloc("__coverage");
+			cov.Stype = type_fake(TYM.TYint);
+			cov.Stype.Tmangle = mTYman.mTYman_c;
+			cov.Stype.Tcount++;
+			cov.Sclass = SC.SCstatic;
+			cov.Sfl = FL.FLdata;
+version (ELFOBJ_OR_MACHOBJ) {
+			cov.Sseg = Segment.UDATA;
+}
+			dtnzeros(&cov.Sdt, 4 * numlines);
+			outdata(cov);
+			slist_add(cov);
+
+			covb = cast(uint*)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
+			 *	bit[numlines] __bcoverage;
+			 */
+			Symbol* bcov = symbol_calloc("__bcoverage");
+			bcov.Stype = type_fake(TYM.TYuint);
+			bcov.Stype.Tcount++;
+			bcov.Sclass = SC.SCstatic;
+			bcov.Sfl = FL.FLdata;
+version (ELFOBJ_OR_MACHOBJ) {
+			bcov.Sseg = Segment.DATA;
+}
+			dtnbytes(&bcov.Sdt, (numlines + 32) / 32 * (*covb).sizeof, cast(char*)covb);
+			outdata(bcov);
+
+			free(covb);
+			covb = null;
+
+			/* Generate:
+			 *  _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename);
+			 * and prepend it to the static constructor.
+			 */
+
+			/* t will be the type of the functions generated:
+			 *	extern (C) void func();
+			 */
+			type* t = type_alloc(TYM.TYnfunc);
+			t.Tflags |= TF.TFprototype | TF.TFfixed;
+			t.Tmangle = mTYman.mTYman_c;
+			t.Tnext = tsvoid;
+			tsvoid.Tcount++;
+
+			sictor = toSymbolX("__modictor", SC.SCglobal, t, "FZv");
+			cstate.CSpsymtab = &sictor.Sfunc.Flocsym;
+			localgot = ictorlocalgot;
+			elem* e;
+
+			e = el_params(el_ptr(cov), el_long(TYM.TYuint, numlines),
+					  el_ptr(bcov), el_long(TYM.TYuint, numlines),
+					  toEfilename(),
+					  null);
+			e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_DCOVER]), e);
+			eictor = el_combine(e, eictor);
+			ictorlocalgot = localgot;
+		}
+
+		// If coverage / static constructor / destructor / unittest calls
+		if (eictor || ector || ectorgates.dim || edtor || etest)
+		{
+			/* t will be the type of the functions generated:
+			 *	extern (C) void func();
+			 */
+			type* t = type_alloc(TYM.TYnfunc);
+			t.Tflags |= TF.TFprototype | TF.TFfixed;
+			t.Tmangle = mTYman.mTYman_c;
+			t.Tnext = tsvoid;
+			tsvoid.Tcount++;
+
+			static string moddeco = "FZv";
+
+			if (eictor)
+			{
+				localgot = ictorlocalgot;
+
+				block* b = block_calloc();
+				b.BC = BC.BCret;
+				b.Belem = eictor;
+				sictor.Sfunc.Fstartblock = b;
+				writefunc(sictor);
+			}
+
+			if (ector || ectorgates.dim)
+			{
+				localgot = null;
+				sctor = toSymbolX("__modctor", SC.SCglobal, t, moddeco);
+				cstate.CSpsymtab = &sctor.Sfunc.Flocsym;
+
+				for (int i = 0; i < ectorgates.dim; i++)
+				{	
+					StaticDtorDeclaration f = cast(StaticDtorDeclaration)ectorgates.data[i];
+
+					Symbol* s = f.vgate.toSymbol();
+					elem* e = el_var(s);
+					e = el_bin(OPER.OPaddass, TYM.TYint, e, el_long(TYM.TYint, 1));
+					ector = el_combine(ector, e);
+				}
+
+				block* b = block_calloc();
+				b.BC = BC.BCret;
+				b.Belem = ector;
+				sctor.Sfunc.Fstartblock = b;
+				writefunc(sctor);
+version (STATICCTOR) {
+				obj_staticctor(sctor, dtorcount, 1);
+}
+			}
+
+			if (edtor)
+			{
+				localgot = null;
+				sdtor = toSymbolX("__moddtor", SC.SCglobal, t, moddeco);
+
+				block* b = block_calloc();
+				b.BC = BC.BCret;
+				b.Belem = edtor;
+				sdtor.Sfunc.Fstartblock = b;
+				writefunc(sdtor);
+			}
+
+			if (etest)
+			{
+				localgot = null;
+				stest = toSymbolX("__modtest", SC.SCglobal, t, moddeco);
+
+				block* b = block_calloc();
+				b.BC = BC.BCret;
+				b.Belem = etest;
+				stest.Sfunc.Fstartblock = b;
+				writefunc(stest);
+			}
+
+			if (doppelganger)
+				genmoduleinfo();
+		}
+
+		if (doppelganger)
+		{
+			obj_termfile();
+			return;
+		}
+
+		if (global.params.multiobj)
+		{	/* This is necessary because the main .obj for this module is written
+			 * first, but determining whether marray or massert are needed is done
+			 * possibly later in the doppelganger modules.
+			 * Another way to fix it is do the main one last.
+			 */
+			toModuleAssert();
+			toModuleArray();
+		}
+
+		// If module assert
+		for (int i = 0; i < 2; i++)
+		{
+			Symbol* ma = i ? marray : massert;
+
+			if (ma)
+			{
+				elem* elinnum;
+				elem* efilename;
+
+				localgot = null;
+
+				// Call dassert(filename, line)
+				// Get sole parameter, linnum
+				{
+					Symbol* sp;
+
+					sp = symbol_calloc("linnum".ptr);
+					sp.Stype = type_fake(TYM.TYint);
+					sp.Stype.Tcount++;
+					sp.Sclass = SC.SCfastpar;
+					sp.Spreg = REG.AX;
+					sp.Sflags &= ~SFL.SFLspill;
+					sp.Sfl = FL.FLpara;	// FLauto?
+					cstate.CSpsymtab = &ma.Sfunc.Flocsym;
+					symbol_add(sp);
+
+					elinnum = el_var(sp);
+				}
+
+				efilename = toEmodulename();
+
+				elem *e = el_var(rtlsym[i ? RTLSYM.RTLSYM_DARRAY : RTLSYM.RTLSYM_DASSERT]);
+				e = el_bin(OPER.OPcall, TYM.TYvoid, e, el_param(elinnum, efilename));
+
+				block* b = block_calloc();
+				b.BC = BC.BCret;
+				b.Belem = e;
+				ma.Sfunc.Fstartblock = b;
+				ma.Sclass = SC.SCglobal;
+				ma.Sfl = 0;
+				writefunc(ma);
+			}
+		}
+
+static if (true) {
+		// Always generate module info, because of templates and -cov
+		if (1 || needModuleInfo())
+			genmoduleinfo();
+		}
+		
+		obj_termfile();
+	}
+	
+    void gensymfile()
+	{
+		assert(false);
+	}
+	
+    void gendocfile()
+	{
+		assert(false);
+	}
+	
+	/**********************************
+	 * Determine if we need to generate an instance of ModuleInfo
+	 * for this Module.
+	 */
+    bool needModuleInfo()
+	{
+		return needmoduleinfo || global.params.cov;
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		/* Since modules can be circularly referenced,
+		 * need to stop infinite recursive searches.
+		 */
+
+		//printf("%s Module.search('%s', flags = %d) insearch = %d\n", toChars(), ident.toChars(), flags, insearch);
+		Dsymbol s;
+		if (insearch)
+			s = null;
+		else if (searchCacheIdent is ident && searchCacheFlags == flags)
+			s = searchCacheSymbol;
+		else
+		{
+			insearch = 1;
+			s = ScopeDsymbol.search(loc, ident, flags);
+			insearch = 0;
+
+			searchCacheIdent = ident;
+			searchCacheSymbol = s;
+			searchCacheFlags = flags;
+		}
+		return s;
+	}
+	
+    void deleteObjFile()
+	{
+		if (global.params.obj)
+			objfile.remove();
+		if (docfile)
+			docfile.remove();
+	}
+
+    void addDeferredSemantic(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+	/******************************************
+	 * Run semantic() on deferred symbols.
+	 */
+
+    void runDeferredSemantic()
+	{
+		size_t len;
+
+		static int nested;
+		if (nested)
+		return;
+		//if (deferred.dim) printf("+Module.runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
+		nested++;
+
+		do
+		{
+			dprogress = 0;
+			len = deferred.dim;
+			if (!len)
+				break;
+
+			Dsymbol *todo;
+			Dsymbol tmp;
+			if (len == 1)
+			{
+				todo = &tmp;
+			}
+			else
+			{
+				todo = cast(Dsymbol*)alloca(len * (Dsymbol*).sizeof);
+				assert(todo);
+			}
+			memcpy(todo, deferred.data, len * (Dsymbol*).sizeof);
+			deferred.setDim(0);
+
+			for (int i = 0; i < len; i++)
+			{
+				Dsymbol s = todo[i];
+
+				s.semantic(null);
+				//printf("deferred: %s, parent = %s\n", s.toChars(), s.parent.toChars());
+			}
+			//printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress);
+		} while (deferred.dim < len || dprogress);	// while making progress
+		nested--;
+		//printf("-Module.runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim);
+	}
+	
+    int imports(Module m)
+	{
+		assert(false);
+	}
+
+    // Back end
+
+    int doppelganger;		// sub-module
+    Symbol* cov;		// private uint[] __coverage;
+    uint* 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
+
+    Symbol* sfilename;		// symbol for filename
+
+    Symbol* massert;		// module assert function
+    Symbol* toModuleAssert()	// get module assert function
+	{
+		if (!massert)
+		{
+			type* t;
+
+			t = type_alloc(TYjfunc);
+			t.Tflags |= TFprototype | TFfixed;
+			t.Tmangle = mTYman_d;
+			t.Tnext = tsvoid;
+			tsvoid.Tcount++;
+
+			massert = toSymbolX("__assert", SCextern, t, "FiZv");
+			massert.Sfl = FLextern;
+			massert.Sflags |= SFLnodebug;
+			slist_add(massert);
+		}
+		return massert;
+	}
+
+    Symbol* marray;		// module array bounds function
+
+	Symbol* toModuleArray()	// get module array bounds function
+	{
+		if (!marray)
+		{
+			type* t;
+
+			t = type_alloc(TYjfunc);
+			t.Tflags |= TFprototype | TFfixed;
+			t.Tmangle = mTYman_d;
+			t.Tnext = tsvoid;
+			tsvoid.Tcount++;
+
+			marray = toSymbolX("__array", SCextern, t, "Z");
+			marray.Sfl = FLextern;
+			marray.Sflags |= SFLnodebug;
+			slist_add(marray);
+		}
+		return marray;
+	}
+
+    static Symbol* gencritsec()
+	{
+		assert(false);
+	}
+	
+    elem* toEfilename()
+	{
+		elem* efilename;
+
+		if (!sfilename)
+		{
+			dt_t* dt = null;
+
+			string id = srcfile.toChars();
+			int len = id.length;
+			dtdword(&dt, len);
+			dtabytes(&dt,TYnptr, 0, len + 1, toStringz(id));
+
+			sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
+			sfilename.Sdt = dt;
+			sfilename.Sfl = FLdata;
+		version (ELFOBJ) {
+			sfilename.Sseg = Segment.CDATA;
+		}
+		version (MACHOBJ) {
+			// Because of PIC and CDATA being in the _TEXT segment, cannot
+			// have pointers in CDATA
+			sfilename.Sseg = Segment.DATA;
+		}
+			outdata(sfilename);
+		}
+
+		efilename = el_var(sfilename);
+		return efilename;
+	}
+	
+	/**************************************
+	 * Generate elem that is a pointer to the module file name.
+	 */
+    elem* toEmodulename()
+	{
+		elem *efilename;
+
+		// Get filename
+		if (needModuleInfo())
+		{   
+			/* Class ModuleInfo is defined in std.moduleinfo.
+			 * The first member is the name of it, char name[],
+			 * which will be at offset 8.
+			 */
+
+			Symbol* si = toSymbol();
+		static if (true) {
+			// Use this instead so -fPIC will work
+			efilename = el_ptr(si);
+			efilename = el_bin(OPadd, TYnptr, efilename, el_long(TYuint, 8));
+			efilename = el_una(OPind, TYdarray, efilename);
+		} else {
+			efilename = el_var(si);
+			efilename.Ety = TYdarray;
+			efilename.EV.sp.Voffset += 8;
+		}
+		}
+		else // generate our own filename
+		{
+			efilename = toEfilename();
+		}
+		return efilename;
+	}
+
+	/*************************************
+	 * Create the "ModuleInfo" symbol
+	 */
+    Symbol* toSymbol()
+	{
+		if (!csym)
+		{
+			Symbol* s;
+			static Classsym* scc;
+
+			if (!scc) {
+				scc = fake_classsym(Id.ClassInfo);
+			}
+
+			s = toSymbolX("__ModuleInfo", SC.SCextern, scc.Stype, "Z");
+			s.Sfl = FL.FLextern;
+			s.Sflags |= SFL.SFLnodebug;
+			csym = s;
+			slist_add(s);
+		}
+		return csym;
+	}
+
+	// Put out instance of ModuleInfo for this Module
+    void genmoduleinfo()
+	{
+		//printf("Module.genmoduleinfo() %s\n", toChars());
+
+		Symbol* msym = toSymbol();
+
+		//dumpSymbol(msym);
+		
+		uint offset;
+	version (DMDV2) {
+		uint sizeof_ModuleInfo = 18 * PTRSIZE;
+	} else {
+		uint sizeof_ModuleInfo = 14 * PTRSIZE;
+	}
+
+		//////////////////////////////////////////////
+
+		csym.Sclass = SC.SCglobal;
+
+		csym.Sfl = FL.FLdata;
+
+		/* The layout is:
+		   {
+			void **vptr;
+			monitor_t monitor;
+			char[] name;		// class name
+			ModuleInfo importedModules[];
+			ClassInfo localClasses[];
+			uint flags;			// initialization state
+			void *ctor;
+			void *dtor;
+			void *unitTest;
+			const(MemberInfo[]) function(string) xgetMembers;	// module getMembers() function
+			void *ictor;
+			void*[4] reserved;
+		   }
+		 */
+		dt_t* dt = null;
+
+		if (moduleinfo)
+			dtxoff(&dt, moduleinfo.toVtblSymbol(), 0, TYM.TYnptr); // vtbl for ModuleInfo
+		else
+		{	
+			//printf("moduleinfo is null\n");
+			dtdword(&dt, 0);		// BUG: should be an assert()
+		}
+		dtdword(&dt, 0);			// monitor
+
+		// name[]
+		string name = toPrettyChars();
+		size_t namelen = name.length;
+		dtdword(&dt, namelen);
+		dtabytes(&dt, TYM.TYnptr, 0, namelen + 1, toStringz(name));
+
+		ClassDeclarations aclasses = new ClassDeclarations();
+
+		//printf("members.dim = %d\n", members.dim);
+		for (int i = 0; i < members.dim; i++)
+		{	
+			Dsymbol member = cast(Dsymbol)members.data[i];
+
+			//printf("\tmember '%s'\n", member.toChars());
+			member.addLocalClass(aclasses);
+		}
+
+		// importedModules[]
+		int aimports_dim = aimports.dim;
+		for (int i = 0; i < aimports.dim; i++)
+		{	
+			Module m = cast(Module)aimports.data[i];
+			if (!m.needModuleInfo())
+				aimports_dim--;
+		}
+
+		dtdword(&dt, aimports_dim);
+		if (aimports_dim)
+			dtxoff(&dt, csym, sizeof_ModuleInfo, TYM.TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		// localClasses[]
+		dtdword(&dt, aclasses.dim);
+		if (aclasses.dim)
+			dtxoff(&dt, csym, sizeof_ModuleInfo + aimports_dim * PTRSIZE, TYM.TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		if (needmoduleinfo)
+			dtdword(&dt, 8|0);		// flags (4 means MIstandalone)
+		else
+			dtdword(&dt, 8|4);		// flags (4 means MIstandalone)
+
+		if (sctor)
+			dtxoff(&dt, sctor, 0, TYM.TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		if (sdtor)
+			dtxoff(&dt, sdtor, 0, TYM.TYnptr);
+		else
+			dtdword(&dt, 0);
+
+		if (stest)
+			dtxoff(&dt, stest, 0, TYM.TYnptr);
+		else
+			dtdword(&dt, 0);
+
+///	version (DMDV2) {
+		FuncDeclaration sgetmembers = findGetMembers();
+		if (sgetmembers)
+			dtxoff(&dt, sgetmembers.toSymbol(), 0, TYM.TYnptr);
+		else
+///	}
+			dtdword(&dt, 0);			// xgetMembers
+
+		if (sictor)
+			dtxoff(&dt, sictor, 0, TYM.TYnptr);
+		else
+			dtdword(&dt, 0);
+
+	version (DMDV2) {
+		// void*[4] reserved;
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);
+		dtdword(&dt, 0);
+	}
+		//////////////////////////////////////////////
+
+		for (int i = 0; i < aimports.dim; i++)
+		{	
+			Module m = cast(Module)aimports.data[i];
+
+			if (m.needModuleInfo())
+			{   
+				Symbol* s = m.toSymbol();
+
+				/* Weak references don't pull objects in from the library,
+				 * they resolve to 0 if not pulled in by something else.
+				 * Don't pull in a module just because it was imported.
+				 */
+	version (OMFOBJ) {// Optlink crashes with weak symbols at EIP 41AFE7, 402000
+	} else {
+				s.Sflags |= SFL.SFLweak;
+	}
+				dtxoff(&dt, s, 0, TYM.TYnptr);
+			}
+		}
+
+		for (int i = 0; i < aclasses.dim; i++)
+		{
+			ClassDeclaration cd = cast(ClassDeclaration)aclasses.data[i];
+			dtxoff(&dt, cd.toSymbol(), 0, TYM.TYnptr);
+		}
+
+		csym.Sdt = dt;
+	version (ELFOBJ_OR_MACHOBJ) {
+		// Cannot be CONST because the startup code sets flag bits in it
+		csym.Sseg = Segment.DATA;
+	}
+
+		outdata(csym);
+
+		//////////////////////////////////////////////
+
+		obj_moduleinfo(msym);
+	}
+
+    Module isModule() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ModuleDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,23 @@
+module dmd.ModuleDeclaration;
+
+import dmd.Identifier;
+import dmd.Array;
+
+class ModuleDeclaration
+{
+    Identifier id;
+    Array packages;		// array of Identifier's representing packages
+    bool safe;
+
+    this(Array packages, Identifier id, bool safe)
+	{
+		this.packages = packages;
+		this.id = id;
+		this.safe = safe;
+	}
+
+    string toChars()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ModuleInfoDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,40 @@
+module dmd.ModuleInfoDeclaration;
+
+import dmd.VarDeclaration;
+import dmd.Module;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.Loc;
+
+import dmd.backend.Symbol;
+
+class ModuleInfoDeclaration : VarDeclaration
+{
+    Module mod;
+
+    this(Module mod)
+	{
+		assert(false);
+		super(Loc(0), null, null, null);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+    void emitComment(Scope *sc)
+	{
+		assert(false);
+	}
+
+    Symbol* toSymbol()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/MulAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,110 @@
+module dmd.MulAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Id;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.expression.Util;
+
+class MulAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKmulass, MulAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		if (e1.op == TOKslice)
+		{	// T[] -= ...
+			typeCombine(sc);
+			type = e1.type;
+			return arrayOp(sc);
+		}
+
+		e1 = e1.modifiableLvalue(sc, e1);
+		e1.checkScalar();
+		e1.checkNoBool();
+		type = e1.type;
+		typeCombine(sc);
+		e1.checkArithmetic();
+		e2.checkArithmetic();
+		if (e2.type.isfloating())
+		{	
+			Type t1;
+			Type t2;
+
+			t1 = e1.type;
+			t2 = e2.type;
+			if (t1.isreal())
+			{
+				if (t2.isimaginary() || t2.iscomplex())
+				{
+					e2 = e2.castTo(sc, t1);
+				}
+			}
+			else if (t1.isimaginary())
+			{
+				if (t2.isimaginary() || t2.iscomplex())
+				{
+					switch (t1.ty)
+					{
+						case Timaginary32: t2 = Type.tfloat32; break;
+						case Timaginary64: t2 = Type.tfloat64; break;
+						case Timaginary80: t2 = Type.tfloat80; break;
+						default:
+							assert(0);
+					}
+					e2 = e2.castTo(sc, t2);
+				}
+			}
+		}
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.mulass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs,OPmulass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/MulExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,148 @@
+module dmd.MulExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.NegExp;
+import dmd.Loc;
+import dmd.Id;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+
+import dmd.expression.Util;
+import dmd.expression.Mul;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class MulExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKmul, MulExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+	static if (false) {
+		printf("MulExp.semantic() %s\n", toChars());
+	}
+		if (type)
+		{
+			return this;
+		}
+
+		BinExp.semanticp(sc);
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		typeCombine(sc);
+		if (e1.op != TOKslice && e2.op != TOKslice)
+		{	
+			e1.checkArithmetic();
+			e2.checkArithmetic();
+		}
+		if (type.isfloating())
+		{	
+			Type t1 = e1.type;
+			Type t2 = e2.type;
+
+			if (t1.isreal())
+			{
+				type = t2;
+			}
+			else if (t2.isreal())
+			{
+				type = t1;
+			}
+			else if (t1.isimaginary())
+			{
+				if (t2.isimaginary())
+				{
+					switch (t1.ty)
+					{
+						case Timaginary32:	type = Type.tfloat32;	break;
+						case Timaginary64:	type = Type.tfloat64;	break;
+						case Timaginary80:	type = Type.tfloat80;	break;
+						default:		assert(0);
+					}
+
+					// iy * iv = -yv
+					e1.type = type;
+					e2.type = type;
+					Expression ee = new NegExp(loc, this);
+					ee = ee.semantic(sc);
+					return ee;
+				}
+				else
+					type = t2;	// t2 is complex
+			}
+			else if (t2.isimaginary())
+			{
+				type = t1;	// t1 is complex
+			}
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("MulExp.optimize(result = %d) %s\n", result, toChars());
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() == 1 && e2.isConst() == 1)
+		{
+			e = Mul(type, e1, e2);
+		}
+		else
+			e = this;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.mul;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.mul_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs,OPmul);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/NegExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,93 @@
+module dmd.NegExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+
+import dmd.expression.Neg;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class NegExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOKneg, NegExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+	version (LOGSEMANTIC) {
+		printf("NegExp::semantic('%s')\n", toChars());
+	}
+		if (!type)
+		{
+			UnaExp.semantic(sc);
+			e1 = resolveProperties(sc, e1);
+			e = op_overload(sc);
+			if (e)
+				return e;
+
+			e1.checkNoBool();
+			if (e1.op != TOKslice)
+				e1.checkArithmetic();
+
+			type = e1.type;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		if (e1.isConst() == 1)
+		{
+			e = Neg(type, e1);
+		}
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem *e = el_una(OPneg, type.totym(), e1.toElem(irs));
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/NewAnonClassExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,52 @@
+module dmd.NewAnonClassExp;
+
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.ClassDeclaration;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+
+class NewAnonClassExp : Expression
+{
+	/* thisexp.new(newargs) class baseclasses { } (arguments)
+     */
+    Expression thisexp;	// if !NULL, 'this' for class being allocated
+    Expressions newargs;	// Array of Expression's to call new operator
+    ClassDeclaration cd;	// class being instantiated
+    Expressions arguments;	// Array of Expression's to call class constructor
+
+	this(Loc loc, Expression thisexp, Expressions newargs, ClassDeclaration cd, Expressions arguments)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState hgs)
+	{
+		assert(false);
+	}
+
+	bool canThrow()
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/NewDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,59 @@
+module dmd.NewDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.ArrayTypes;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+
+class NewDeclaration : FuncDeclaration
+{
+	Arguments arguments;
+    int varargs;
+
+    this(Loc loc, Loc endloc, Arguments arguments, int varargs)
+	{
+		assert(false);
+		super(loc, loc, null, STC.init, null);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    string kind()
+	{
+		assert(false);
+	}
+
+    bool isVirtual()
+	{
+		assert(false);
+	}
+
+    bool addPreInvariant()
+	{
+		assert(false);
+	}
+
+    bool addPostInvariant()
+	{
+		assert(false);
+	}
+
+    NewDeclaration isNewDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/NewExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,762 @@
+module dmd.NewExp;
+
+import dmd.Expression;
+import dmd.NewDeclaration;
+import dmd.CtorDeclaration;
+import dmd.ClassDeclaration;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+import dmd.TY;
+import dmd.TypeFunction;
+import dmd.TypeClass;
+import dmd.TypeStruct;
+import dmd.StructDeclaration;
+import dmd.FuncDeclaration;
+import dmd.TypeDArray;
+import dmd.Dsymbol;
+import dmd.ThisExp;
+import dmd.DotIdExp;
+import dmd.Id;
+import dmd.WANT;
+import dmd.Global;
+import dmd.IntegerExp;
+import dmd.TypePointer;
+
+import dmd.backend.elem;
+import dmd.backend.TYM;
+import dmd.backend.SC;
+import dmd.backend.TYPE;
+import dmd.backend.TYM;
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.RTLSYM;
+import dmd.expression.Util;
+import dmd.codegen.Util;
+
+import std.string : toStringz;
+
+class NewExp : Expression
+{
+	/* thisexp.new(newargs) newtype(arguments)
+     */
+    Expression thisexp;	// if !null, 'this' for class being allocated
+    Expressions newargs;	// Array of Expression's to call new operator
+    Type newtype;
+    Expressions arguments;	// Array of Expression's
+
+    CtorDeclaration member;	// constructor function
+    NewDeclaration allocator;	// allocator function
+    int onstack;		// allocate on stack
+
+	this(Loc loc, Expression thisexp, Expressions newargs, Type newtype, Expressions arguments)
+	{
+		super(loc, TOK.TOKnew, NewExp.sizeof);
+		this.thisexp = thisexp;
+		this.newargs = newargs;
+		this.newtype = newtype;
+		this.arguments = arguments;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		int i;
+		Type tb;
+		ClassDeclaration cdthis = null;
+
+	version (LOGSEMANTIC) {
+		printf("NewExp.semantic() %s\n", toChars());
+		if (thisexp)
+		printf("\tthisexp = %s\n", thisexp.toChars());
+		printf("\tnewtype: %s\n", newtype.toChars());
+	}
+		if (type)			// if semantic() already run
+			return this;
+
+	Lagain:
+		if (thisexp)
+		{	
+			thisexp = thisexp.semantic(sc);
+			cdthis = thisexp.type.isClassHandle();
+			if (cdthis)
+			{
+				sc = sc.push(cdthis);
+				type = newtype.semantic(loc, sc);
+				sc = sc.pop();
+			}
+			else
+			{
+				error("'this' for nested class must be a class type, not %s", thisexp.type.toChars());
+				type = newtype.semantic(loc, sc);
+			}
+		}
+		else
+			type = newtype.semantic(loc, sc);
+		newtype = type;		// in case type gets cast to something else
+		tb = type.toBasetype();
+		//printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
+
+		arrayExpressionSemantic(newargs, sc);
+		preFunctionArguments(loc, sc, newargs);
+		arrayExpressionSemantic(arguments, sc);
+		preFunctionArguments(loc, sc, arguments);
+
+		if (thisexp && tb.ty != Tclass)
+			error("e.new is only for allocating nested classes, not %s", tb.toChars());
+
+		if (tb.ty == Tclass)
+		{	
+			TypeFunction tf;
+
+			TypeClass tc = cast(TypeClass)tb;
+			ClassDeclaration cd = tc.sym.isClassDeclaration();
+			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());
+				for (int j = 0; j < cd.vtbl.dim; j++)
+				{	
+					FuncDeclaration fd = (cast(Dsymbol)cd.vtbl.data[j]).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.
+				 * Ensure we have the right one.
+				 */
+				Dsymbol s = cd.toParent2();
+				ClassDeclaration cdn = s.isClassDeclaration();
+				FuncDeclaration fdn = s.isFuncDeclaration();
+
+				//printf("cd isNested, cdn = %s\n", cdn ? cdn.toChars() : "null");
+				if (cdn)
+				{
+					if (!cdthis)
+					{
+						// Supply an implicit 'this' and try again
+						thisexp = new ThisExp(loc);
+						for (Dsymbol sp = sc.parent; 1; sp = sp.parent)
+						{	
+							if (!sp)
+							{
+								error("outer class %s 'this' needed to 'new' nested class %s", cdn.toChars(), cd.toChars());
+								break;
+							}
+							ClassDeclaration cdp = sp.isClassDeclaration();
+							if (!cdp)
+								continue;
+							if (cdp == cdn || cdn.isBaseOf(cdp, null))
+								break;
+							// Add a '.outer' and try again
+							thisexp = new DotIdExp(loc, thisexp, Id.outer);
+						}
+						if (!global.errors)
+							goto Lagain;
+					}
+					if (cdthis)
+					{
+						//printf("cdthis = %s\n", cdthis.toChars());
+						if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
+						error("'this' for nested class must be of type %s, not %s", cdn.toChars(), thisexp.type.toChars());
+					}
+					else
+					{
+			static if (false) {
+						for (Dsymbol *sf = sc.func; 1; sf= sf.toParent2().isFuncDeclaration())
+						{
+							if (!sf)
+							{
+								error("outer class %s 'this' needed to 'new' nested class %s", cdn.toChars(), cd.toChars());
+								break;
+							}
+							printf("sf = %s\n", sf.toChars());
+							AggregateDeclaration *ad = sf.isThis();
+							if (ad && (ad == cdn || cdn.isBaseOf(ad.isClassDeclaration(), null)))
+								break;
+						}
+			}
+					}
+				}
+	///static if (true) {
+				else if (thisexp)
+					error("e.new is only for allocating nested classes");
+				else if (fdn)
+				{
+					// make sure the parent context fdn of cd is reachable from sc
+					for (Dsymbol sp = sc.parent; 1; sp = sp.parent)
+					{
+						if (fdn is sp)
+							break;
+						FuncDeclaration fsp = sp ? sp.isFuncDeclaration() : null;
+						if (!sp || (fsp && fsp.isStatic()))
+						{
+						error("outer function context of %s is needed to 'new' nested class %s", fdn.toPrettyChars(), cd.toPrettyChars());
+						break;
+						}
+					}
+				}
+	///} else {
+	///			else if (fdn)
+	///			{	
+	///				/* The nested class cd is nested inside a function,
+	///				 * we'll let getEthis() look for errors.
+	///				 */
+	///				//printf("nested class %s is nested inside function %s, we're in %s\n", cd.toChars(), fdn.toChars(), sc.func.toChars());
+	///				if (thisexp)
+	///					// Because thisexp cannot be a function frame pointer
+	///					error("e.new is only for allocating nested classes");
+	///			}
+	///}
+				else
+					assert(0);
+			}
+			else if (thisexp)
+				error("e.new is only for allocating nested classes");
+
+			FuncDeclaration f = null;
+			if (cd.ctor)
+				f = resolveFuncCall(sc, loc, cd.ctor, null, null, arguments, 0);
+			if (f)
+			{
+				checkDeprecated(sc, f);
+				member = f.isCtorDeclaration();
+				assert(member);
+
+				cd.accessCheck(loc, sc, member);
+
+				tf = cast(TypeFunction)f.type;
+
+				if (!arguments)
+					arguments = new Expressions();
+				functionArguments(loc, sc, tf, arguments);
+			}
+			else
+			{
+				if (arguments && arguments.dim)
+					error("no constructor for %s", cd.toChars());
+			}
+
+			if (cd.aggNew)
+			{
+				// Prepend the size argument to newargs[]
+				Expression e = new IntegerExp(loc, cd.size(loc), Type.tsize_t);
+				if (!newargs)
+					newargs = new Expressions();
+				newargs.shift(cast(void*)e);
+
+				f = cd.aggNew.overloadResolve(loc, null, newargs);
+				allocator = f.isNewDeclaration();
+				assert(allocator);
+
+				tf = cast(TypeFunction)f.type;
+				functionArguments(loc, sc, tf, newargs);
+			}
+			else
+			{
+				if (newargs && newargs.dim)
+					error("no allocator for %s", cd.toChars());
+			}
+		}
+		else if (tb.ty == Tstruct)
+		{
+			TypeStruct ts = cast(TypeStruct)tb;
+			StructDeclaration sd = ts.sym;
+			TypeFunction tf;
+
+			FuncDeclaration f = null;
+			if (sd.ctor)
+				f = resolveFuncCall(sc, loc, sd.ctor, null, null, arguments, 0);
+			if (f)
+			{
+				checkDeprecated(sc, f);
+				member = f.isCtorDeclaration();
+				assert(member);
+
+				sd.accessCheck(loc, sc, member);
+
+				tf = cast(TypeFunction)f.type;
+		//	    type = tf.next;
+
+				if (!arguments)
+					arguments = new Expressions();
+				functionArguments(loc, sc, tf, arguments);
+			}
+			else
+			{
+				if (arguments && arguments.dim)
+					error("no constructor for %s", sd.toChars());
+			}
+
+			if (sd.aggNew)
+			{
+				// Prepend the uint size argument to newargs[]
+				Expression e = new IntegerExp(loc, sd.size(loc), Type.tuns32);
+				if (!newargs)
+					newargs = new Expressions();
+				newargs.shift(cast(void*)e);
+
+				f = sd.aggNew.overloadResolve(loc, null, newargs);
+				allocator = f.isNewDeclaration();
+				assert(allocator);
+
+				tf = cast(TypeFunction)f.type;
+				functionArguments(loc, sc, tf, newargs);
+		static if (false) {
+				e = new VarExp(loc, f);
+				e = new CallExp(loc, e, newargs);
+				e = e.semantic(sc);
+				e.type = type.pointerTo();
+				return e;
+		}
+			}
+			else
+			{
+				if (newargs && newargs.dim)
+				error("no allocator for %s", sd.toChars());
+			}
+
+			type = type.pointerTo();
+		}
+		else if (tb.ty == Tarray && (arguments && arguments.dim))
+		{
+			for (size_t j = 0; j < arguments.dim; j++)
+			{
+				if (tb.ty != Tarray)
+				{	
+					error("too many arguments for array");
+					arguments.dim = i;
+					break;
+				}
+
+				Expression arg = cast(Expression)arguments.data[j];
+				arg = resolveProperties(sc, arg);
+				arg = arg.implicitCastTo(sc, Type.tsize_t);
+				arg = arg.optimize(WANTvalue);
+				if (arg.op == TOKint64 && cast(long)arg.toInteger() < 0)
+					error("negative array index %s", arg.toChars());
+				arguments.data[j] = cast(void*) arg;
+				tb = (cast(TypeDArray)tb).next.toBasetype();
+			}
+		}
+		else if (tb.isscalar())
+		{
+			if (arguments && arguments.dim)
+				error("no constructor for %s", type.toChars());
+
+			type = type.pointerTo();
+		}
+		else
+		{
+			error("new can only create structs, dynamic arrays or class objects, not %s's", type.toChars());
+			type = type.pointerTo();
+		}
+
+	//printf("NewExp: '%s'\n", toChars());
+	//printf("NewExp:type '%s'\n", type.toChars());
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		if (thisexp)
+			thisexp = thisexp.optimize(WANTvalue);
+
+		// Optimize parameters
+		if (newargs)
+		{
+			for (size_t i = 0; i < newargs.dim; i++)
+			{   
+				Expression e = cast(Expression)newargs.data[i];
+
+				e = e.optimize(WANTvalue);
+				newargs.data[i] = cast(void*)e;
+			}
+		}
+
+		if (arguments)
+		{
+			for (size_t i = 0; i < arguments.dim; i++)
+			{   
+				Expression e = cast(Expression)arguments.data[i];
+
+				e = e.optimize(WANTvalue);
+				arguments.data[i] = cast(void*)e;
+			}
+		}
+		return this;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		Type t;
+		Type ectype;
+
+		//printf("NewExp.toElem() %s\n", toChars());
+		t = type.toBasetype();
+		//printf("\ttype = %s\n", t.toChars());
+		//if (member)
+		//printf("\tmember = %s\n", member.toChars());
+		if (t.ty == Tclass)
+		{
+			Symbol* csym;
+
+			t = newtype.toBasetype();
+			assert(t.ty == Tclass);
+			TypeClass tclass = cast(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(toStringz(tclass.sym.toChars()));
+					s.Sclass = SCstruct;
+					s.Sstruct = struct_calloc();
+					s.Sstruct.Sflags |= 0;
+					s.Sstruct.Salignsize = tclass.sym.alignsize;
+					s.Sstruct.Sstructalign = cast(ubyte)tclass.sym.structalign;
+					s.Sstruct.Sstructsize = tclass.sym.structsize;
+
+					.type* tc = type_alloc(TYstruct);
+					tc.Ttag = cast(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));
+
+				if (!cd.vthis)
+				{
+					error("forward reference to %s", cd.toChars());
+				}
+				else
+				{
+					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;
+				 */
+				ey = setEthis(loc, irs, ey, cd);
+			}
+
+			if (member)
+				// Call constructor
+				ez = callfunc(loc, irs, 1, type, ez, ectype, member, member.type, null, arguments);
+
+			e = el_combine(ex, ey);
+			e = el_combine(e, ez);
+		}
+		else if (t.ty == Tpointer && t.nextOf().toBasetype().ty == Tstruct)
+		{
+			Symbol* csym;
+
+			t = newtype.toBasetype();
+			assert(t.ty == Tstruct);
+			TypeStruct tclass = cast(TypeStruct)t;
+			StructDeclaration cd = tclass.sym;
+
+			/* Things to do:
+			 * 1) ex: call allocator
+			 * 2) ey: set vthis for nested classes
+			 * 3) ez: call constructor
+			 */
+
+			elem* ex = null;
+			elem* ey = null;
+			elem* ez = null;
+
+			if (allocator)
+			{   
+				elem *ei;
+				Symbol *si;
+
+				ex = el_var(allocator.toSymbol());
+				ex = callfunc(loc, irs, 1, type, ex, allocator.type,
+					allocator, allocator.type, null, newargs);
+
+				si = tclass.sym.toInitializer();
+				ei = el_var(si);
+
+				if (cd.isNested())
+				{
+					ey = el_same(&ex);
+					ez = el_copytree(ey);
+				}
+				else if (member)
+					ez = el_same(&ex);
+
+				if (!member)
+				{	
+					/* Statically intialize with default initializer
+					 */
+					ex = el_una(OPind, TYstruct, ex);
+					ex = el_bin(OPstreq, TYnptr, ex, ei);
+					ex.Enumbytes = cd.size(loc);
+					ex = el_una(OPaddr, TYnptr, ex);
+				}
+				ectype = tclass;
+			}
+			else
+			{
+				ulong elemsize = cd.size(loc);
+
+				// call _d_newarrayT(ti, 1)
+				e = el_long(TYsize_t, 1);
+				e = el_param(e, type.getTypeInfo(null).toElem(irs));
+
+				int rtl = t.isZeroInit(Loc(0)) ? RTLSYM_NEWARRAYT : RTLSYM_NEWARRAYIT;
+				e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
+
+				// The new functions return an array, so convert to a pointer
+				// ex . (unsigned)(e >> 32)
+				e = el_bin(OPshr, TYdarray, e, el_long(TYint, 32));
+				ex = el_una(OP64_32, TYnptr, e);
+
+				ectype = null;
+
+				if (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 (cd.isNested())
+			{   
+				/* Initialize cd.vthis:
+				 *	*(ey + cd.vthis.offset) = this;
+				 */
+				ey = setEthis(loc, irs, ey, cd);
+			}
+
+			if (member)
+			{   
+				// Call constructor
+				ez = callfunc(loc, irs, 1, type, ez, ectype, member, member.type, null, arguments);
+		version (STRUCTTHISREF) {
+				/* Structs return a ref, which gets automatically dereferenced.
+				 * But we want a pointer to the instance.
+				 */
+				ez = el_una(OPaddr, TYnptr, ez);
+		}
+			}
+
+			e = el_combine(ex, ey);
+			e = el_combine(e, ez);
+		}
+		else if (t.ty == Tarray)
+		{
+			TypeDArray tda = cast(TypeDArray)t;
+
+			assert(arguments && arguments.dim >= 1);
+			if (arguments.dim == 1)
+			{   
+				// Single dimension array allocations
+				Expression arg = cast(Expression)arguments.data[0];	// gives array length
+				e = arg.toElem(irs);
+				ulong elemsize = tda.next.size();
+
+				// call _d_newT(ti, arg)
+				e = el_param(e, type.getTypeInfo(null).toElem(irs));
+				int rtl = tda.next.isZeroInit(Loc(0)) ? 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 = cast(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(Loc(0)) ? RTLSYM_NEWARRAYMT : RTLSYM_NEWARRAYMIT;
+				e = el_bin(OPcall,TYdarray,el_var(rtlsym[rtl]),e);
+			}
+		}
+		else if (t.ty == Tpointer)
+		{
+			TypePointer tp = cast(TypePointer)t;
+			ulong elemsize = tp.next.size();
+			Expression di = tp.next.defaultInit(Loc(0));
+			ulong disize = di.type.size();
+
+			// call _d_newarrayT(ti, 1)
+			e = el_long(TYsize_t, 1);
+			e = el_param(e, type.getTypeInfo(null).toElem(irs));
+
+			int rtl = tp.next.isZeroInit(Loc(0)) ? 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;
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+version (DMDV2) {
+	bool canThrow()
+	{
+		return 1;
+	}
+}
+	
+	//int inlineCost(InlineCostState *ics);
+
+	Expression doInline(InlineDoState ids)
+	{
+		//printf("NewExp.doInline(): %s\n", toChars());
+		NewExp ne = cast(NewExp)copy();
+
+		if (thisexp)
+			ne.thisexp = thisexp.doInline(ids);
+		ne.newargs = arrayExpressiondoInline(ne.newargs, ids);
+		ne.arguments = arrayExpressiondoInline(ne.arguments, ids);
+		return ne;
+	}
+	
+	//Expression inlineScan(InlineScanState *iss);
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/NotExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,63 @@
+module dmd.NotExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Type;
+
+import dmd.expression.Not;
+
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class NotExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKnot, NotExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		e1 = e1.checkToBoolean();
+		type = Type.tboolean;
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		if (e1.isConst() == 1)
+			e = Not(type, e1);
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e = el_una(OPnot, type.totym(), e1.toElem(irs));
+		el_setLoc(e,loc);
+		return e;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/NullExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,154 @@
+module dmd.NullExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.TY;
+import dmd.TypeTypedef;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+
+class NullExp : Expression
+{
+	ubyte committed;
+
+	this(Loc loc)
+	{
+		super(loc, TOK.TOKnull, NullExp.sizeof);
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("NullExp.semantic('%s')\n", toChars());
+}
+		// null is the same as (void*)0
+		if (!type)
+			type = Type.tvoid.pointerTo();
+
+		return this;
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	int isConst()
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("null");
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+static if (false) {
+		printf("NullExp.implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n",
+		toChars(), type.toChars(), t.toChars(), committed);
+}
+		if (this.type.equals(t))
+			return MATCH.MATCHexact;
+
+		/* Allow implicit conversions from invariant to mutable|const,
+		 * and mutable to invariant. It works because, after all, a null
+		 * doesn't actually point to anything.
+		 */
+		if (t.invariantOf().equals(type.invariantOf()))
+			return MATCH.MATCHconst;
+
+		// null implicitly converts to any pointer type or dynamic array
+		if (type.ty == TY.Tpointer && type.nextOf().ty == TY.Tvoid)
+		{
+			if (t.ty == TY.Ttypedef)
+				t = (cast(TypeTypedef)t).sym.basetype;
+			if (t.ty == TY.Tpointer || t.ty == TY.Tarray ||
+				t.ty == TY.Taarray  || t.ty == TY.Tclass ||
+				t.ty == TY.Tdelegate)
+			{
+				return committed ? MATCH.MATCHconvert : MATCH.MATCHexact;
+			}
+		}
+
+		return Expression.implicitConvTo(t);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		NullExp e;
+		Type tb;
+
+		//printf("NullExp::castTo(t = %p)\n", t);
+		if (type is t)
+		{
+			committed = 1;
+			return this;
+		}
+
+		e = cast(NullExp)copy();
+		e.committed = 1;
+		tb = t.toBasetype();
+		e.type = type.toBasetype();
+
+		if (tb !is e.type)
+		{
+			// null implicitly converts to any pointer type or dynamic array
+			if (e.type.ty == TY.Tpointer && e.type.nextOf().ty == TY.Tvoid &&
+				(tb.ty == TY.Tpointer || tb.ty == TY.Tarray || tb.ty == TY.Taarray ||
+				 tb.ty == TY.Tdelegate))
+			{
+static if (false) {
+				if (tb.ty == TY.Tdelegate)
+				{   
+					TypeDelegate td = cast(TypeDelegate)tb;
+					TypeFunction tf = cast(TypeFunction)td.nextOf();
+
+					if (!tf.varargs && !(tf.arguments && tf.arguments.dim))
+					{
+						return Expression.castTo(sc, t);
+					}
+				}
+}
+			}
+			else
+			{
+				return e.Expression.castTo(sc, t);
+			}
+		}
+		e.type = t;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return el_long(type.totym(), 0);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(type);
+		return dtnzeros(pdt, cast(uint)type.size());
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ObjModule.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,13 @@
+module dmd.ObjModule;
+
+struct ObjModule
+{
+	ubyte* base;			// where are we holding it in memory
+    uint length;			// in bytes
+    ushort page;			// page module starts in output file
+    ubyte flags;
+    string name;				// module name
+}
+
+enum MFgentheadr = 1;	// generate THEADR record
+enum MFtheadr = 2;	// module name comes from THEADR record
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OnScopeStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,114 @@
+module dmd.OnScopeStatement;
+
+import dmd.Statement;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.BE;
+import dmd.Identifier;
+import dmd.ExpInitializer;
+import dmd.IntegerExp;
+import dmd.VarDeclaration;
+import dmd.Type;
+import dmd.AssignExp;
+import dmd.VarExp;
+import dmd.NotExp;
+import dmd.IfStatement;
+import dmd.DeclarationStatement;
+import dmd.ExpStatement;
+import dmd.Expression;
+import dmd.Lexer;
+
+class OnScopeStatement : Statement
+{
+    TOK tok;
+    Statement statement;
+
+    this(Loc loc, TOK tok, Statement statement)
+	{
+		super(loc);
+		
+		this.tok = tok;
+		this.statement = statement;
+	}
+
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+
+    BE blockExit()
+	{
+		// At this point, this statement is just an empty placeholder
+		return BE.BEfallthru;
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement semantic(Scope sc)
+	{
+		/* semantic is called on results of scopeCode() */
+		return this;
+	}
+
+    bool usesEH()
+	{
+		assert(false);
+	}
+
+    void scopeCode(Scope sc, Statement* sentry, Statement* sexception, Statement* sfinally)
+	{
+		//printf("OnScopeStatement::scopeCode()\n");
+		//print();
+		*sentry = null;
+		*sexception = null;
+		*sfinally = null;
+		switch (tok)
+		{
+			case TOKon_scope_exit:
+				*sfinally = statement;
+				break;
+
+			case TOKon_scope_failure:
+				*sexception = statement;
+				break;
+
+			case TOKon_scope_success:
+			{
+				/* Create:
+				 *	sentry:   int x = 0;
+				 *	sexception:    x = 1;
+				 *	sfinally: if (!x) statement;
+				 */
+				Identifier id = Lexer.uniqueId("__os");
+
+				ExpInitializer ie = new ExpInitializer(loc, new IntegerExp(0));
+				VarDeclaration v = new VarDeclaration(loc, Type.tint32, id, ie);
+				*sentry = new DeclarationStatement(loc, v);
+
+				Expression e = new IntegerExp(1);
+				e = new AssignExp(Loc(0), new VarExp(Loc(0), v), e);
+				*sexception = new ExpStatement(Loc(0), e);
+
+				e = new VarExp(Loc(0), v);
+				e = new NotExp(Loc(0), e);
+				*sfinally = new IfStatement(Loc(0), null, e, statement, null);
+
+				break;
+			}
+
+			default:
+				assert(0);
+		}
+	}
+
+    void toIR(IRState* irs)
+	{
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Optimize.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,100 @@
+module dmd.Optimize;
+
+import dmd.Expression;
+import dmd.TOK;
+import dmd.VarExp;
+import dmd.VarDeclaration;
+import dmd.STC;
+import dmd.AssignExp;
+import dmd.Type;
+import dmd.WANT;
+import dmd.TY;
+
+/*************************************
+ * If variable has a const initializer,
+ * return that initializer.
+ */
+
+Expression expandVar(int result, VarDeclaration v)
+{
+    //printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v.toChars() : "null");
+
+    Expression e = null;
+    if (!v)
+	return e;
+
+    if (v.isConst() || v.isInvariant() || v.storage_class & STC.STCmanifest)
+    {
+	if (!v.type)
+	{
+	    //error("ICE");
+	    return e;
+	}
+
+	Type tb = v.type.toBasetype();
+	if (result & WANT.WANTinterpret ||
+	    v.storage_class & STC.STCmanifest ||
+	    (tb.ty != TY.Tsarray && tb.ty != TY.Tstruct)
+	   )
+	{
+	    if (v.init)
+	    {
+		if (v.inuse)
+		{   if (v.storage_class & STC.STCmanifest)
+			v.error("recursive initialization of constant");
+		    goto L1;
+		}
+		Expression ei = v.init.toExpression();
+		if (!ei)
+		    goto L1;
+		if (ei.op == TOK.TOKconstruct || ei.op == TOK.TOKblit)
+		{   AssignExp ae = cast(AssignExp)ei;
+		    ei = ae.e2;
+		    if (ei.isConst() != 1 && ei.op != TOK.TOKstring)
+			goto L1;
+		    if (ei.type != v.type)
+			goto L1;
+		}
+		if (v.scope_)
+		{
+		    v.inuse++;
+		    e = ei.syntaxCopy();
+		    e = e.semantic(v.scope_);
+		    e = e.implicitCastTo(v.scope_, v.type);
+		    // enabling this line causes test22 in test suite to fail
+		    //ei.type = e.type;
+		    v.scope_ = null;
+		    v.inuse--;
+		}
+		else if (!ei.type)
+		{
+		    goto L1;
+		}
+		else
+		    // Should remove the copy() operation by
+		    // making all mods to expressions copy-on-write
+		    e = ei.copy();
+	    }
+	    else
+	    {
+static if (true) {
+		goto L1;
+} else {
+		// BUG: what if const is initialized in constructor?
+		e = v.type.defaultInit();
+		e.loc = e1.loc;
+}
+	    }
+	    if (e.type != v.type)
+	    {
+		e = e.castTo(null, v.type);
+	    }
+	    v.inuse++;
+	    e = e.optimize(result);
+	    v.inuse--;
+	}
+    }
+L1:
+    //if (e) printf("\te = %s, e.type = %s\n", e.toChars(), e.type.toChars());
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OrAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,54 @@
+module dmd.OrAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Id;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+
+class OrAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKorass, OrAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		return commonSemanticAssignIntegral(sc);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.orass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPorass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,133 @@
+module dmd.OrExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.TY;
+import dmd.Id;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+
+import dmd.expression.Or;
+
+class OrExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKor, OrExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+
+			if (e)
+				return e;
+
+			if (e1.type.toBasetype().ty == TY.Tbool && e2.type.toBasetype().ty == TY.Tbool)
+			{
+				type = e1.type;
+				e = this;
+			}
+			else
+			{
+				typeCombine(sc);
+				if (e1.op != TOK.TOKslice && e2.op != TOK.TOKslice)
+				{
+					e1.checkIntegral();
+					e2.checkIntegral();
+				}
+			}
+		}
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+
+		if (e1.isConst() == 1 && e2.isConst() == 1)
+			e = Or(type, e1, e2);
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+		MATCH result = Expression.implicitConvTo(t);
+
+		if (result == MATCH.MATCHnomatch)
+		{
+			MATCH m1 = e1.implicitConvTo(t);
+			MATCH m2 = e2.implicitConvTo(t);
+
+			// Pick the worst match
+			result = (m1 < m2) ? m1 : m2;
+		}
+
+		return result;
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.ior;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.ior_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPER.OPor);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OrOrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,128 @@
+module dmd.OrOrExp;
+
+import dmd.BinExp;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.TOK;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.TY;
+import dmd.WANT;
+import dmd.IntegerExp;
+import dmd.Type;
+import dmd.CommaExp;
+import dmd.Global;
+import dmd.BoolExp;
+
+import dmd.expression.Util;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+
+class OrOrExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKoror, OrOrExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		uint cs1;
+
+		// same as for AndAnd
+		e1 = e1.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		e1 = e1.checkToPointer();
+		e1 = e1.checkToBoolean();
+		cs1 = sc.callSuper;
+
+		if (sc.flags & SCOPE.SCOPEstaticif)
+		{
+			/* If in static if, don't evaluate e2 if we don't have to.
+			 */
+			e1 = e1.optimize(WANTflags);
+			if (e1.isBool(true))
+			{
+				return new IntegerExp(loc, 1, Type.tboolean);
+			}
+		}
+
+		e2 = e2.semantic(sc);
+		sc.mergeCallSuper(loc, cs1);
+		e2 = resolveProperties(sc, e2);
+		e2 = e2.checkToPointer();
+
+		type = Type.tboolean;
+		if (e2.type.ty == Tvoid)
+			type = Type.tvoid;
+		if (e2.op == TOKtype || e2.op == TOKimport)
+			error("%s is not an expression", e2.toChars());
+		return this;
+	}
+
+    Expression checkToBoolean()
+	{
+		e2 = e2.checkToBoolean();
+		return this;
+	}
+	
+    int isBit()
+	{
+		assert(false);
+	}
+	
+    Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(WANTflags | (result & WANTinterpret));
+		e = this;
+		if (e1.isBool(true))
+		{	
+			// Replace with (e1, 1)
+			e = new CommaExp(loc, e1, new IntegerExp(loc, 1, type));
+			e.type = type;
+			e = e.optimize(result);
+		}
+		else
+		{
+			e2 = e2.optimize(WANTflags | (result & WANTinterpret));
+			if (result && e2.type.toBasetype().ty == Tvoid && !global.errors)
+				error("void has no value");
+			if (e1.isConst())
+			{
+				if (e2.isConst())
+				{	
+					int n1 = e1.isBool(1);
+					int n2 = e2.isBool(1);
+
+					e = new IntegerExp(loc, n1 || n2, type);
+				}
+				else if (e1.isBool(false))
+					e = new BoolExp(loc, e2, type);
+			}
+		}
+		return e;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+    elem* 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;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OutBuffer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,285 @@
+module dmd.OutBuffer;
+
+import std.stdarg;
+import std.contracts;
+
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class OutBuffer
+{
+    ubyte* data;
+    uint offset;
+    uint size;
+
+    this()
+	{
+		// do nothing
+	}
+
+    final void* extractData()
+	{
+		void* p = cast(void*)data;
+
+		data = null;
+		offset = 0;
+		size = 0;
+
+		return p;
+	}
+
+    void mark()
+	{
+		assert(false);
+	}
+
+    final void reserve(uint nbytes)
+	{
+		//printf("OutBuffer::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes);
+		if (size - offset < nbytes)
+		{
+			size = (offset + nbytes) * 2;
+			data = cast(ubyte*)realloc(data, size);
+		}
+	}
+	
+    final void setsize(uint size)
+	{
+		assert(false);
+	}
+	
+    final void reset()
+	{
+		offset = 0;
+	}
+	
+    final void write(const(void)* data, uint nbytes)
+	{
+		reserve(nbytes);
+		memcpy(this.data + offset, data, nbytes);
+		offset += nbytes;
+	}
+	
+    final void writebstring(ubyte* string_)
+	{
+		assert(false);
+	}
+	
+    final void writestring(const(char)[] string_)
+	{
+		write(string_.ptr , string_.length);
+	}
+	
+    final void writedstring(const(char)* string_)
+	{
+		assert(false);
+	}
+	
+    final void writedstring(const(wchar)* string_)
+	{
+		assert(false);
+	}
+	
+    final void prependstring(const(char)[] string_)
+	{
+		uint len = string_.length;
+		reserve(len);
+		memmove(data + len, data, offset);
+		memcpy(data, string_.ptr, len);
+		offset += len;
+	}
+	
+    final void writenl()			// write newline
+	{
+		assert(false);
+	}
+	
+    final void writeByte(uint b)
+	{
+		reserve(1);
+		this.data[offset] = cast(ubyte)b;
+		offset++;
+	}
+	
+    final void writebyte(uint b) { writeByte(b); }
+    
+	final void writeUTF8(uint b)
+	{
+		reserve(6);
+		if (b <= 0x7F)
+		{
+			this.data[offset] = cast(ubyte)b;
+			offset++;
+		}
+		else if (b <= 0x7FF)
+		{
+			this.data[offset + 0] = cast(ubyte)((b >> 6) | 0xC0);
+			this.data[offset + 1] = cast(ubyte)((b & 0x3F) | 0x80);
+			offset += 2;
+		}
+		else if (b <= 0xFFFF)
+		{
+			this.data[offset + 0] = cast(ubyte)((b >> 12) | 0xE0);
+			this.data[offset + 1] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80);
+			this.data[offset + 2] = cast(ubyte)((b & 0x3F) | 0x80);
+			offset += 3;
+		}
+		else if (b <= 0x1FFFFF)
+		{
+			this.data[offset + 0] = cast(ubyte)((b >> 18) | 0xF0);
+			this.data[offset + 1] = cast(ubyte)(((b >> 12) & 0x3F) | 0x80);
+			this.data[offset + 2] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80);
+			this.data[offset + 3] = cast(ubyte)((b & 0x3F) | 0x80);
+			offset += 4;
+		}
+		else if (b <= 0x3FFFFFF)
+		{
+			this.data[offset + 0] = cast(ubyte)((b >> 24) | 0xF8);
+			this.data[offset + 1] = cast(ubyte)(((b >> 18) & 0x3F) | 0x80);
+			this.data[offset + 2] = cast(ubyte)(((b >> 12) & 0x3F) | 0x80);
+			this.data[offset + 3] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80);
+			this.data[offset + 4] = cast(ubyte)((b & 0x3F) | 0x80);
+			offset += 5;
+		}
+		else if (b <= 0x7FFFFFFF)
+		{
+			this.data[offset + 0] = cast(ubyte)((b >> 30) | 0xFC);
+			this.data[offset + 1] = cast(ubyte)(((b >> 24) & 0x3F) | 0x80);
+			this.data[offset + 2] = cast(ubyte)(((b >> 18) & 0x3F) | 0x80);
+			this.data[offset + 3] = cast(ubyte)(((b >> 12) & 0x3F) | 0x80);
+			this.data[offset + 4] = cast(ubyte)(((b >> 6) & 0x3F) | 0x80);
+			this.data[offset + 5] = cast(ubyte)((b & 0x3F) | 0x80);
+			offset += 6;
+		}
+		else
+			assert(0);
+	}
+	
+    final void writedchar(uint b)
+	{
+		assert(false);
+	}
+	
+    final void prependbyte(uint b)
+	{
+		assert(false);
+	}
+
+    final void writeword(uint w)
+	{
+		reserve(2);
+		*cast(ushort*)(this.data + offset) = cast(ushort)w;
+		offset += 2;
+	}
+	
+    final void writeUTF16(uint w)
+	{
+		reserve(4);
+		if (w <= 0xFFFF)
+		{
+			*cast(ushort*)(this.data + offset) = cast(ushort)w;
+			offset += 2;
+		}
+		else if (w <= 0x10FFFF)
+		{
+			*cast(ushort*)(this.data + offset) = cast(ushort)((w >> 10) + 0xD7C0);
+			*cast(ushort*)(this.data + offset + 2) = cast(ushort)((w & 0x3FF) | 0xDC00);
+			offset += 4;
+		}
+		else
+			assert(0);
+	}
+	
+    final void write4(uint w)
+	{
+		assert(false);
+	}
+	
+    final void write(OutBuffer buf)
+	{
+		if (buf)
+		{	
+			reserve(buf.offset);
+			memcpy(data + offset, buf.data, buf.offset);
+			offset += buf.offset;
+		}
+	}
+	
+    final void write(Object obj)
+	{
+		assert(false);
+	}
+	
+    final void fill0(uint nbytes)
+	{
+		reserve(nbytes);
+		memset(data + offset, 0, nbytes);
+		offset += nbytes;
+	}
+	
+    final void align_(uint size)
+	{
+		assert(false);
+	}
+	
+	void vprintf(const(char)* format, va_list args)
+	{
+		assert(false);
+	}
+
+	void printf(T...)(string format, T t)
+	{
+		string s = std.string.format(format, t);
+		writestring(s);
+	}
+
+version (M_UNICODE) {
+///    void vprintf(const uint short *format, va_list args);
+///    void printf(const uint short *format, ...);
+}
+    final void bracket(char left, char right)
+	{
+		assert(false);
+	}
+	
+    final uint bracket(uint i, const(char)* left, uint j, const(char)* right)
+	{
+		assert(false);
+	}
+	
+    final void spread(uint offset, uint nbytes)
+	{
+		assert(false);
+	}
+	
+    final uint insert(uint offset, const(void)* data, uint nbytes)
+	{
+		assert(false);
+	}
+	
+    final void remove(uint offset, uint nbytes)
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		return getString().idup;
+	}
+
+    final string extractString()
+	{
+		char[] s = getString();
+		data = null;
+		offset = 0;
+		size = 0;
+
+		return assumeUnique(s);
+	}
+
+	final char[] getString()
+	{
+		char* s = cast(char*)data;
+		return s[0..offset];
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OverExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,29 @@
+module dmd.OverExp;
+
+import dmd.Expression;
+import dmd.OverloadSet;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.TOK;
+
+class OverExp : Expression
+{
+	OverloadSet vars;
+
+	this(OverloadSet s)
+	{
+		assert(false);
+		super(Loc(0), TOK.init, 0);
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/OverloadSet.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,26 @@
+module dmd.OverloadSet;
+
+import dmd.Dsymbol;
+import dmd.ArrayTypes;
+
+class OverloadSet : Dsymbol
+{
+    Dsymbols a;		// array of Dsymbols
+
+    this()
+	{
+		assert(false);
+	}
+	
+    void push(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    OverloadSet isOverloadSet() { return this; }
+
+    string kind()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PREC.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,31 @@
+module dmd.PREC;
+
+import dmd.TOK;
+
+/**********************************
+ * Set operator precedence for each operator.
+ */
+
+// Operator precedence - greater values are higher precedence
+
+enum PREC
+{
+    PREC_zero,
+    PREC_expr,
+    PREC_assign,
+    PREC_cond,
+    PREC_oror,
+    PREC_andand,
+    PREC_or,
+    PREC_xor,
+    PREC_and,
+    PREC_equal,
+    PREC_rel,
+    PREC_shift,
+    PREC_add,
+    PREC_mul,
+    PREC_unary,
+    PREC_primary,
+}
+
+PREC precedence[TOK.TOKMAX];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PROT.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,12 @@
+module dmd.PROT;
+
+enum PROT
+{
+    PROTundefined,
+    PROTnone,		// no access
+    PROTprivate,
+    PROTpackage,
+    PROTprotected,
+    PROTpublic,
+    PROTexport,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Package.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,75 @@
+module dmd.Package;
+
+import dmd.ScopeDsymbol;
+import dmd.Identifier;
+import dmd.Array;
+import dmd.DsymbolTable;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.Module;
+import dmd.Util;
+
+class Package : ScopeDsymbol
+{
+    this(Identifier ident)
+	{
+		super(ident);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+
+    static DsymbolTable resolve(Array packages, Dsymbol* pparent, Package* ppkg)
+	{
+		DsymbolTable dst = Module.modules;
+		Dsymbol parent = null;
+
+		//printf("Package::resolve()\n");
+		if (ppkg)
+			*ppkg = null;
+
+		if (packages)
+		{
+			for (int i = 0; i < packages.dim; i++)
+			{   
+				Identifier pid = cast(Identifier)packages.data[i];
+				Dsymbol p = dst.lookup(pid);
+				if (!p)
+				{
+					p = new Package(pid);
+					dst.insert(p);
+					p.parent = parent;
+					(cast(ScopeDsymbol)p).symtab = new DsymbolTable();
+				}
+				else
+				{
+					assert(p.isPackage());
+version (TARGET_NET) {		//dot net needs modules and packages with same name
+} else {
+					if (p.isModule())
+					{   
+						p.error("module and package have the same name");
+						fatal();
+						break;
+					}
+}
+				}
+				parent = p;
+				dst = (cast(Package)p).symtab;
+				if (ppkg && !*ppkg)
+					*ppkg = cast(Package)p;
+			}
+			if (pparent)
+			{
+				*pparent = parent;
+			}
+		}
+		return dst;
+	}
+
+    Package isPackage() { return this; }
+
+    void semantic(Scope sc) { }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Param.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,100 @@
+module dmd.Param;
+
+import dmd.Array;
+import dmd.OutBuffer;
+
+// Put command line switches in here
+struct Param
+{
+    bool obj;		// write object file
+    bool link;		// perform link
+    bool lib;		// write library file instead of object file(s)
+    bool multiobj;	// break one object file into multiple ones
+    bool oneobj;	// write one object file instead of multiple ones
+    bool trace;		// insert profiling hooks
+    bool quiet;		// suppress non-error messages
+    bool verbose;	// verbose compile
+    bool vtls;		// identify thread local variables
+    byte symdebug;	// insert debug symbolic information
+    bool optimize;	// run optimizer
+    bool cpu;		// target CPU
+    bool isX86_64;	// generate X86_64 bit code
+    bool isLinux;	// generate code for linux
+    bool isOSX;		// generate code for Mac OSX
+    bool isWindows;	// generate code for Windows
+    bool isFreeBSD;	// generate code for FreeBSD
+    bool isSolaris;	// generate code for Solaris
+    bool scheduler;	// which scheduler to use
+    bool useDeprecated;	// allow use of deprecated features
+    bool useAssert;	// generate runtime code for assert()'s
+    bool useInvariants;	// generate class invariant checks
+    bool useIn;		// generate precondition checks
+    bool useOut;	// generate postcondition checks
+    bool useArrayBounds; // generate array bounds checks
+    bool useSwitchError; // check for switches without a default
+    bool useUnitTests;	// generate unittest code
+    bool useInline;	// inline expand functions
+    bool release;	// build release version
+    bool preservePaths;	// !=0 means don't strip path from source file
+    bool warnings;	// enable warnings
+    bool pic;		// generate position-independent-code for shared libs
+    bool cov;		// generate code coverage data
+    bool nofloat;	// code should not pull in floating point support
+    byte Dversion;	// D version number
+    bool ignoreUnsupportedPragmas;	// rather than error on them
+    bool safe;		// enforce safe memory model
+
+    string argv0;	// program name
+    Array imppath;	// array of char*'s of where to look for import modules
+    Array fileImppath;	// array of char*'s of where to look for file import modules
+    string objdir;	// .obj/.lib file output directory
+    string objname;	// .obj file output name
+    string libname;	// .lib file output name
+
+    bool doDocComments;	// process embedded documentation comments
+    string docdir;	// write documentation file to docdir directory
+    string docname;	// write documentation file to docname
+    Array ddocfiles;	// macro include files for Ddoc
+
+    bool doHdrGeneration;	// process embedded documentation comments
+    string hdrdir;		// write 'header' file to docdir directory
+    string hdrname;		// write 'header' file to docname
+
+    uint debuglevel;	// debug level
+    Array debugids;		// debug identifiers
+
+    uint versionlevel;	// version level
+    Array versionids;		// version identifiers
+
+    bool dump_source;
+
+    const(char)* defaultlibname;	// default library for non-debug builds
+    const(char)* debuglibname;	// default library for debug builds
+
+    const(char)* xmlname;	// filename for XML output
+
+    string moduleDepsFile;	// filename for deps output
+    OutBuffer moduleDeps;	// contents to be written to deps file
+
+    // Hidden debug switches
+    bool debuga;
+    bool debugb;
+    bool debugc;
+    bool debugf;
+    bool debugr;
+    bool debugw;
+    bool debugx;
+    bool debugy;
+
+    bool run;		// run resulting executable
+    size_t runargs_length;
+    string[] runargs;	// arguments for executable
+
+    // Linker stuff
+    Array objfiles;
+    Array linkswitches;
+    Array libfiles;
+    string deffile;
+    string resfile;
+    string exefile;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ParseStatementFlags.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,9 @@
+module dmd.ParseStatementFlags;
+
+enum ParseStatementFlags
+{
+    PSsemi = 1,		// empty ';' statements are allowed
+    PSscope = 2,	// start a new scope
+    PScurly = 4,	// { } statement is required
+    PScurlyscope = 8,	// { } starts a new scope
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Parser.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,5951 @@
+module dmd.Parser;
+
+import dmd.Lexer;
+import dmd.PostBlitDeclaration;
+import dmd.FileInitExp;
+import dmd.LineInitExp;
+import dmd.EnumMember;
+import dmd.CtorDeclaration;
+import dmd.ShlAssignExp;
+import dmd.ShrAssignExp;
+import dmd.UshrAssignExp;
+import dmd.CatAssignExp;
+import dmd.StaticIfCondition;
+import dmd.TraitsExp;
+import dmd.BaseClass;
+import dmd.AssignExp;
+import dmd.TemplateInstance;
+import dmd.NewExp;
+import dmd.ArrayExp;
+import dmd.DotTemplateInstanceExp;
+import dmd.ClassDeclaration;
+import dmd.NewAnonClassExp;
+import dmd.InterfaceDeclaration;
+import dmd.StructDeclaration;
+import dmd.UnionDeclaration;
+import dmd.AnonDeclaration;
+import dmd.StructInitializer;
+import dmd.ArrayInitializer;
+import dmd.ExpInitializer;
+import dmd.TemplateAliasParameter;
+import dmd.TemplateTupleParameter;
+import dmd.TemplateThisParameter;
+import dmd.TemplateValueParameter;
+import dmd.VoidInitializer;
+import dmd.VersionCondition;
+import dmd.DotIdExp;
+import dmd.DebugCondition;
+import dmd.PostExp;
+import dmd.CallExp;
+import dmd.SliceExp;
+import dmd.FuncExp;
+import dmd.AssocArrayLiteralExp;
+import dmd.ArrayLiteralExp;
+import dmd.IsExp;
+import dmd.FuncLiteralDeclaration;
+import dmd.AssertExp;
+import dmd.CompileExp;
+import dmd.FileExp;
+import dmd.TemplateParameter;
+import dmd.TemplateTypeParameter;
+import dmd.TypeidExp;
+import dmd.StringExp;
+import dmd.ScopeExp;
+import dmd.IdentifierExp;
+import dmd.DollarExp;
+import dmd.ThisExp;
+import dmd.SuperExp;
+import dmd.NullExp;
+import dmd.RealExp;
+import dmd.TypeExp;
+import dmd.AddrExp;
+import dmd.MOD;
+import dmd.IntegerExp;
+import dmd.CastExp;
+import dmd.PtrExp;
+import dmd.NegExp;
+import dmd.XorAssignExp;
+import dmd.OrAssignExp;
+import dmd.UAddExp;
+import dmd.NotExp;
+import dmd.ComExp;
+import dmd.DeleteExp;
+import dmd.MulAssignExp;
+import dmd.ModAssignExp;
+import dmd.MinAssignExp;
+import dmd.DivAssignExp;
+import dmd.AndAssignExp;
+import dmd.AddAssignExp;
+import dmd.ModuleDeclaration;
+import dmd.CaseRangeStatement;
+import dmd.CommaExp;
+import dmd.XorExp;
+import dmd.CondExp;
+import dmd.CmpExp;
+import dmd.InExp;
+import dmd.OrOrExp;
+import dmd.OrExp;
+import dmd.AddExp;
+import dmd.MinExp;
+import dmd.CatExp;
+import dmd.AndAndExp;
+import dmd.EqualExp;
+import dmd.ShlExp;
+import dmd.ShrExp;
+import dmd.DivExp;
+import dmd.MulExp;
+import dmd.ModExp;
+import dmd.UshrExp;
+import dmd.IdentityExp;
+import dmd.AndExp;
+import dmd.Id;
+import dmd.LabelStatement;
+import dmd.ExpStatement;
+import dmd.StaticAssertStatement;
+import dmd.DeclarationStatement;
+import dmd.ScopeStatement;
+import dmd.PragmaStatement;
+import dmd.WhileStatement;
+import dmd.DoStatement;
+import dmd.ForStatement;
+import dmd.OnScopeStatement;
+import dmd.IfStatement;
+import dmd.SwitchStatement;
+import dmd.CaseStatement;
+import dmd.DefaultStatement;
+import dmd.GotoDefaultStatement;
+import dmd.GotoCaseStatement;
+import dmd.GotoStatement;
+import dmd.SynchronizedStatement;
+import dmd.WithStatement;
+import dmd.Catch;
+import dmd.TryCatchStatement;
+import dmd.TryFinallyStatement;
+import dmd.ThrowStatement;
+import dmd.VolatileStatement;
+import dmd.ReturnStatement;
+import dmd.BreakStatement;
+import dmd.ContinueStatement;
+import dmd.AsmStatement;
+import dmd.TypeReturn;
+import dmd.TypeTypeof;
+import dmd.ForeachRangeStatement;
+import dmd.ForeachStatement;
+import dmd.CompileStatement;
+import dmd.CompoundStatement;
+import dmd.ConditionalStatement;
+import dmd.CompoundDeclarationStatement;
+import dmd.Argument;
+import dmd.ParseStatementFlags;
+import dmd.TypeNext;
+import dmd.TypeInstance;
+import dmd.TypePointer;
+import dmd.TypeDArray;
+import dmd.TypeAArray;
+import dmd.TypeSlice;
+import dmd.TypeSArray;
+import dmd.TemplateInstance;
+import dmd.TypeIdentifier;
+import dmd.VarDeclaration;
+import dmd.TypeFunction;
+import dmd.TypeDelegate;
+import dmd.TY;
+import dmd.LinkDeclaration;
+import dmd.Declaration;
+import dmd.AggregateDeclaration;
+import dmd.TypedefDeclaration;
+import dmd.AliasDeclaration;
+import dmd.LINK;
+import dmd.Loc;
+import dmd.Module;
+import dmd.Array;
+import dmd.Expression;
+import dmd.TemplateDeclaration;
+import dmd.ArrayTypes;
+import dmd.Dsymbol;
+import dmd.StaticAssert;
+import dmd.TypeQualified;
+import dmd.Condition;
+import dmd.PostBlitDeclaration;
+import dmd.DtorDeclaration;
+import dmd.ConditionalDeclaration;
+import dmd.StaticCtorDeclaration;
+import dmd.StaticDtorDeclaration;
+import dmd.InvariantDeclaration;
+import dmd.UnitTestDeclaration;
+import dmd.NewDeclaration;
+import dmd.DeleteDeclaration;
+import dmd.EnumDeclaration;
+import dmd.Import;
+import dmd.Type;
+import dmd.Identifier;
+import dmd.FuncDeclaration;
+import dmd.Statement;
+import dmd.Initializer;
+import dmd.Token;
+import dmd.TOK;
+import dmd.ParseStatementFlags;
+import dmd.PROT;
+import dmd.STC;
+import dmd.Util;
+import dmd.CompileDeclaration;
+import dmd.StaticIfDeclaration;
+import dmd.StorageClassDeclaration;
+import dmd.LinkDeclaration;
+import dmd.ProtDeclaration;
+import dmd.AlignDeclaration;
+import dmd.PragmaDeclaration;
+import dmd.DebugSymbol;
+import dmd.VersionSymbol;
+import dmd.AliasThis;
+import dmd.Global;
+
+import core.stdc.string : memcpy;
+import core.stdc.stdlib : malloc;
+
+import std.contracts;
+
+class Parser : Lexer
+{
+    ModuleDeclaration md;
+    LINK linkage;
+    Loc endloc;			// set to location of last right curly
+    int inBrackets;		// inside [] of array index or slice
+
+    this(Module module_, ubyte* base, uint length, int doDocComment)
+	{
+		super(module_, base, 0, length, doDocComment, 0);
+		//printf("Parser.Parser()\n");
+		linkage = LINK.LINKd;
+		//nextToken();		// start up the scanner
+	}
+	
+    Array parseModule()
+	{
+		Array decldefs;
+
+		// ModuleDeclation leads off
+		if (token.value == TOK.TOKmodule)
+		{
+			ubyte* comment = token.blockComment;
+			bool safe = false;
+
+			nextToken();
+version (DMDV2) {
+			if (token.value == TOK.TOKlparen)
+			{
+				nextToken();
+				if (token.value != TOK.TOKidentifier)
+				{
+					error("module (system) identifier expected");
+					goto Lerr;
+				}
+				Identifier id = token.ident;
+
+				if (id is Id.system)
+					safe = true;
+				else
+					error("(safe) expected, not %s", id.toChars());
+				nextToken();
+				check(TOK.TOKrparen);
+			}
+}
+
+			if (token.value != TOK.TOKidentifier)
+			{
+				error("Identifier expected following module");
+				goto Lerr;
+			}
+			else
+			{
+				Array a = null;
+				Identifier id = token.ident;
+				while (nextToken() == TOK.TOKdot)
+				{
+					if (!a)
+						a = new Array();
+					a.push(cast(void*)id);
+					nextToken();
+					if (token.value != TOK.TOKidentifier)
+					{   error("Identifier expected following package");
+						goto Lerr;
+					}
+					id = token.ident;
+				}
+
+				md = new ModuleDeclaration(a, id, safe);
+
+				if (token.value != TOK.TOKsemicolon)
+					error("';' expected following module declaration instead of %s", token.toChars());
+
+				nextToken();
+				addComment(mod, comment);
+			}
+		}
+
+		decldefs = parseDeclDefs(0);
+		if (token.value != TOK.TOKeof)
+		{
+			error("unrecognized declaration");
+			goto Lerr;
+		}
+
+		return decldefs;
+
+	Lerr:
+		while (token.value != TOK.TOKsemicolon && token.value != TOK.TOKeof)
+			nextToken();
+
+		nextToken();
+		return new Array();
+	}
+	
+    Array parseDeclDefs(int once)
+	{
+		Dsymbol s;
+		Array decldefs;
+		Array a;
+		Array aelse;
+		PROT prot;
+		STC stc;
+		STC storageClass;
+		Condition  condition;
+		ubyte* comment;
+
+		//printf("Parser.parseDeclDefs()\n");
+		decldefs = new Array();
+		do
+		{
+		comment = token.blockComment;
+		storageClass = STC.STCundefined;
+		switch (token.value)
+		{
+			case TOK.TOKenum:
+			{	/* Determine if this is a manifest constant declaration,
+			 * or a conventional enum.
+			 */
+			Token *t = peek(&token);
+			if (t.value == TOK.TOKlcurly || t.value == TOK.TOKcolon)
+				s = parseEnum();
+			else if (t.value != TOK.TOKidentifier)
+				goto Ldeclaration;
+			else
+			{
+				t = peek(t);
+				if (t.value == TOK.TOKlcurly || t.value == TOK.TOKcolon ||
+				t.value == TOK.TOKsemicolon)
+				s = parseEnum();
+				else
+				goto Ldeclaration;
+			}
+			break;
+			}
+
+			case TOK.TOKstruct:
+			case TOK.TOKunion:
+			case TOK.TOKclass:
+			case TOK.TOKinterface:
+			s = parseAggregate();
+			break;
+
+			case TOK.TOKimport:
+			s = parseImport(decldefs, 0);
+			break;
+
+			case TOK.TOKtemplate:
+			s = cast(Dsymbol)parseTemplateDeclaration();
+			break;
+
+			case TOK.TOKmixin:
+			{	Loc loc = this.loc;
+			if (peek(&token).value == TOK.TOKlparen)
+			{   // mixin(string)
+				nextToken();
+				check(TOK.TOKlparen, "mixin");
+				Expression e = parseAssignExp();
+				check(TOK.TOKrparen);
+				check(TOK.TOKsemicolon);
+				s = new CompileDeclaration(loc, e);
+				break;
+			}
+			s = parseMixin();
+			break;
+			}
+
+			case TOK.TOKwchar: case TOK.TOKdchar:
+			case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar:
+			case TOK.TOKint8: case TOK.TOKuns8:
+			case TOK.TOKint16: case TOK.TOKuns16:
+			case TOK.TOKint32: case TOK.TOKuns32:
+			case TOK.TOKint64: case TOK.TOKuns64:
+			case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80:
+			case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80:
+			case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80:
+			case TOK.TOKvoid:
+			case TOK.TOKalias:
+			case TOK.TOKtypedef:
+			case TOK.TOKidentifier:
+			case TOK.TOKtypeof:
+			case TOK.TOKdot:
+			Ldeclaration:
+			a = parseDeclarations(STC.STCundefined);
+			decldefs.append(a);
+			continue;
+
+			case TOK.TOKthis:
+			s = parseCtor();
+			break;
+
+static if (false) { // dead end, use this(this){} instead
+			case TOK.TOKassign:
+			s = parsePostBlit();
+			break;
+}
+			case TOK.TOKtilde:
+			s = parseDtor();
+			break;
+
+			case TOK.TOKinvariant:
+			{	Token *t;
+			t = peek(&token);
+			if (t.value == TOK.TOKlparen)
+			{
+				if (peek(t).value == TOK.TOKrparen)
+				// invariant() forms start of class invariant
+				s = parseInvariant();
+				else
+				// invariant(type)
+				goto Ldeclaration;
+			}
+			else
+			{
+				stc = STC.STCimmutable;
+				goto Lstc;
+			}
+			break;
+			}
+
+			case TOK.TOKunittest:
+			s = parseUnitTest();
+			break;
+
+			case TOK.TOKnew:
+			s = parseNew();
+			break;
+
+			case TOK.TOKdelete:
+			s = parseDelete();
+			break;
+
+			case TOK.TOKeof:
+			case TOK.TOKrcurly:
+			return decldefs;
+
+			case TOK.TOKstatic:
+			nextToken();
+			if (token.value == TOK.TOKthis)
+				s = parseStaticCtor();
+			else if (token.value == TOK.TOKtilde)
+				s = parseStaticDtor();
+			else if (token.value == TOK.TOKassert)
+				s = parseStaticAssert();
+			else if (token.value == TOK.TOKif)
+			{   condition = parseStaticIfCondition();
+				a = parseBlock();
+				aelse = null;
+				if (token.value == TOK.TOKelse)
+				{   nextToken();
+				aelse = parseBlock();
+				}
+				s = new StaticIfDeclaration(condition, a, aelse);
+				break;
+			}
+			else if (token.value == TOK.TOKimport)
+			{
+				s = parseImport(decldefs, 1);
+			}
+			else
+			{   stc = STC.STCstatic;
+				goto Lstc2;
+			}
+			break;
+
+			case TOK.TOKconst:
+			if (peek(&token).value == TOK.TOKlparen)
+				goto Ldeclaration;
+			stc = STC.STCconst;
+			goto Lstc;
+
+			case TOK.TOKimmutable:
+			if (peek(&token).value == TOK.TOKlparen)
+				goto Ldeclaration;
+			stc = STC.STCimmutable;
+			goto Lstc;
+
+			case TOK.TOKshared:
+			if (peek(&token).value == TOK.TOKlparen)
+				goto Ldeclaration;
+			stc = STC.STCshared;
+			goto Lstc;
+
+			case TOK.TOKfinal:	  stc = STC.STCfinal;	 goto Lstc;
+			case TOK.TOKauto:	  stc = STC.STCauto;	 goto Lstc;
+			case TOK.TOKscope:	  stc = STC.STCscope;	 goto Lstc;
+			case TOK.TOKoverride:	  stc = STC.STCoverride;	 goto Lstc;
+			case TOK.TOKabstract:	  stc = STC.STCabstract;	 goto Lstc;
+			case TOK.TOKsynchronized: stc = STC.STCsynchronized; goto Lstc;
+			case TOK.TOKdeprecated:   stc = STC.STCdeprecated;	 goto Lstc;
+version (DMDV2) {
+			case TOK.TOKnothrow:      stc = STC.STCnothrow;	 goto Lstc;
+			case TOK.TOKpure:         stc = STC.STCpure;	 goto Lstc;
+			case TOK.TOKref:          stc = STC.STCref;          goto Lstc;
+			case TOK.TOKtls:          stc = STC.STCtls;		 goto Lstc;
+			case TOK.TOKgshared:      
+				stc = STC.STCgshared;	 goto Lstc;
+			//case TOK.TOKmanifest:	  stc = STC.STCmanifest;	 goto Lstc;
+}
+
+			Lstc:
+			if (storageClass & stc)
+				error("redundant storage class %s", Token.toChars(token.value));
+			composeStorageClass(storageClass | stc);
+			nextToken();
+			Lstc2:
+			storageClass |= stc;
+			switch (token.value)
+			{
+				case TOK.TOKconst:
+				case TOK.TOKinvariant:
+				case TOK.TOKimmutable:
+				case TOK.TOKshared:
+				// If followed by a (, it is not a storage class
+				if (peek(&token).value == TOK.TOKlparen)
+					break;
+				if (token.value == TOK.TOKconst)
+					stc = STC.STCconst;
+				else if (token.value == TOK.TOKshared)
+					stc = STC.STCshared;
+				else
+					stc = STC.STCimmutable;
+				goto Lstc;
+				case TOK.TOKfinal:	  stc = STC.STCfinal;	 goto Lstc;
+				case TOK.TOKauto:	  stc = STC.STCauto;	 goto Lstc;
+				case TOK.TOKscope:	  stc = STC.STCscope;	 goto Lstc;
+				case TOK.TOKoverride:	  stc = STC.STCoverride;	 goto Lstc;
+				case TOK.TOKabstract:	  stc = STC.STCabstract;	 goto Lstc;
+				case TOK.TOKsynchronized: stc = STC.STCsynchronized; goto Lstc;
+				case TOK.TOKdeprecated:   stc = STC.STCdeprecated;	 goto Lstc;
+				case TOK.TOKnothrow:      stc = STC.STCnothrow;	 goto Lstc;
+				case TOK.TOKpure:         stc = STC.STCpure;	 goto Lstc;
+				case TOK.TOKref:          stc = STC.STCref;          goto Lstc;
+				case TOK.TOKtls:          stc = STC.STCtls;		 goto Lstc;
+				case TOK.TOKgshared:      stc = STC.STCgshared;	 goto Lstc;
+				//case TOK.TOKmanifest:	  stc = STC.STCmanifest;	 goto Lstc;
+				default:
+				break;
+			}
+
+			/* Look for auto initializers:
+			 *	storage_class identifier = initializer;
+			 */
+			if (token.value == TOK.TOKidentifier &&
+				peek(&token).value == TOK.TOKassign)
+			{
+				a = parseAutoDeclarations(storageClass, comment);
+				decldefs.append(a);
+				continue;
+			}
+
+			/* Look for return type inference for template functions.
+			 */
+			Token *tk;
+			if (token.value == TOK.TOKidentifier &&
+				(tk = peek(&token)).value == TOK.TOKlparen &&
+				skipParens(tk, &tk) &&
+				(peek(tk).value == TOK.TOKlparen ||
+				 peek(tk).value == TOK.TOKlcurly)
+			   )
+			{
+				a = parseDeclarations(storageClass);
+				decldefs.append(a);
+				continue;
+			}
+			a = parseBlock();
+			s = new StorageClassDeclaration(storageClass, a);
+			break;
+
+			case TOK.TOKextern:
+				if (peek(&token).value != TOK.TOKlparen)
+				{   
+					stc = STC.STCextern;
+					goto Lstc;
+				}
+				{
+					LINK linksave = linkage;
+					linkage = parseLinkage();
+					a = parseBlock();
+					s = new LinkDeclaration(linkage, a);
+					linkage = linksave;
+					break;
+				}
+
+			case TOK.TOKprivate:	prot = PROT.PROTprivate;	goto Lprot;
+			case TOK.TOKpackage:	prot = PROT.PROTpackage;	goto Lprot;
+			case TOK.TOKprotected:	prot = PROT.PROTprotected;	goto Lprot;
+			case TOK.TOKpublic:		prot = PROT.PROTpublic;		goto Lprot;
+			case TOK.TOKexport:		prot = PROT.PROTexport;		goto Lprot;
+				Lprot:
+				nextToken();
+				switch (token.value)
+				{
+					case TOK.TOKprivate:
+					case TOK.TOKpackage:
+					case TOK.TOKprotected:
+					case TOK.TOKpublic:
+					case TOK.TOKexport:
+						error("redundant protection attribute");
+						break;
+					default:
+						break;
+				}
+				a = parseBlock();
+				s = new ProtDeclaration(prot, a);
+				break;
+
+			case TOK.TOKalign:
+			{	uint n;
+
+			s = null;
+			nextToken();
+			if (token.value == TOK.TOKlparen)
+			{
+				nextToken();
+				if (token.value == TOK.TOKint32v)
+				n = cast(uint)token.uns64value;
+				else
+				{	error("integer expected, not %s", token.toChars());
+				n = 1;
+				}
+				nextToken();
+				check(TOK.TOKrparen);
+			}
+			else
+				n = global.structalign;		// default
+
+			a = parseBlock();
+			s = new AlignDeclaration(n, a);
+			break;
+			}
+
+			case TOK.TOKpragma:
+			{	Identifier ident;
+			Expressions args = null;
+
+			nextToken();
+			check(TOK.TOKlparen);
+			if (token.value != TOK.TOKidentifier)
+			{   error("pragma(identifier expected");
+				goto Lerror;
+			}
+			ident = token.ident;
+			nextToken();
+			if (token.value == TOK.TOKcomma && peekNext() != TOK.TOKrparen)
+				args = parseArguments();	// pragma(identifier, args...)
+			else
+				check(TOK.TOKrparen);		// pragma(identifier)
+
+			if (token.value == TOK.TOKsemicolon)
+				a = null;
+			else
+				a = parseBlock();
+			s = new PragmaDeclaration(loc, ident, args, a);
+			break;
+			}
+
+			case TOK.TOKdebug:
+			nextToken();
+			if (token.value == TOK.TOKassign)
+			{
+				nextToken();
+				if (token.value == TOK.TOKidentifier)
+				s = new DebugSymbol(loc, token.ident);
+				else if (token.value == TOK.TOKint32v)
+				s = new DebugSymbol(loc, cast(uint)token.uns64value);
+				else
+				{	error("identifier or integer expected, not %s", token.toChars());
+				s = null;
+				}
+				nextToken();
+				if (token.value != TOK.TOKsemicolon)
+				error("semicolon expected");
+				nextToken();
+				break;
+			}
+
+			condition = parseDebugCondition();
+			goto Lcondition;
+
+			case TOK.TOKversion:
+			nextToken();
+			if (token.value == TOK.TOKassign)
+			{
+				nextToken();
+				if (token.value == TOK.TOKidentifier)
+				s = new VersionSymbol(loc, token.ident);
+				else if (token.value == TOK.TOKint32v)
+				s = new VersionSymbol(loc, cast(uint)token.uns64value);
+				else
+				{	error("identifier or integer expected, not %s", token.toChars());
+				s = null;
+				}
+				nextToken();
+				if (token.value != TOK.TOKsemicolon)
+				error("semicolon expected");
+				nextToken();
+				break;
+			}
+			condition = parseVersionCondition();
+			goto Lcondition;
+
+			Lcondition:
+			a = parseBlock();
+			aelse = null;
+			if (token.value == TOK.TOKelse)
+			{   nextToken();
+				aelse = parseBlock();
+			}
+			s = new ConditionalDeclaration(condition, a, aelse);
+			break;
+
+			case TOK.TOKsemicolon:		// empty declaration
+			nextToken();
+			continue;
+
+			default:
+			error("Declaration expected, not '%s'",token.toChars());
+			Lerror:
+			while (token.value != TOK.TOKsemicolon && token.value != TOK.TOKeof)
+				nextToken();
+			nextToken();
+			s = null;
+			continue;
+		}
+		if (s)
+		{   decldefs.push(cast(void*)s);
+			addComment(s, comment);
+		}
+		} while (!once);
+		return decldefs;
+	}
+	
+	/*****************************************
+	 * Parse auto declarations of the form:
+	 *   storageClass ident = init, ident = init, ... ;
+	 * and return the array of them.
+	 * Starts with token on the first ident.
+	 * Ends with scanner past closing ';'
+	 */
+version (DMDV2) {
+    Array parseAutoDeclarations(STC storageClass, ubyte* comment)
+	{
+		Array a = new Array;
+
+		while (true)
+		{
+			Identifier ident = token.ident;
+			nextToken();		// skip over ident
+			assert(token.value == TOKassign);
+			nextToken();		// skip over '='
+			Initializer init = parseInitializer();
+			VarDeclaration v = new VarDeclaration(loc, null, ident, init);
+			v.storage_class = storageClass;
+			a.push(cast(void*)v);
+			if (token.value == TOKsemicolon)
+			{
+				nextToken();
+				addComment(v, comment);
+			}
+			else if (token.value == TOKcomma)
+			{
+				nextToken();
+				if (token.value == TOKidentifier &&
+					peek(&token).value == TOKassign)
+				{
+					addComment(v, comment);
+					continue;
+				}
+				else
+					error("Identifier expected following comma");
+			}
+			else
+				error("semicolon expected following auto declaration, not '%s'", token.toChars());
+			break;
+		}
+		return a;
+	}
+}
+	/********************************************
+	 * Parse declarations after an align, protection, or extern decl.
+	 */
+    Array parseBlock()
+	{
+		Array a = null;
+		Dsymbol ss;
+
+		//printf("parseBlock()\n");
+		switch (token.value)
+		{
+		case TOK.TOKsemicolon:
+			error("declaration expected following attribute, not ';'");
+			nextToken();
+			break;
+
+		case TOK.TOKeof:
+			error("declaration expected following attribute, not EOF");
+			break;
+
+		case TOK.TOKlcurly:
+			nextToken();
+			a = parseDeclDefs(0);
+			if (token.value != TOK.TOKrcurly)
+			{   /* { */
+				error("matching '}' expected, not %s", token.toChars());
+			}
+			else
+				nextToken();
+			break;
+
+		case TOK.TOKcolon:
+			nextToken();
+static if (false) {
+			a = null;
+} else {
+			a = parseDeclDefs(0);	// grab declarations up to closing curly bracket
+}
+			break;
+
+		default:
+			a = parseDeclDefs(1);
+			break;
+		}
+		return a;
+	}
+	
+    void composeStorageClass(STC stc)
+	{
+		STC u = stc;
+		u &= STC.STCconst | STC.STCimmutable | STC.STCmanifest;
+		if (u & (u - 1))
+			error("conflicting storage class %s", Token.toChars(token.value));
+
+		u = stc;
+		u &= STC.STCgshared | STC.STCshared | STC.STCtls;
+		if (u & (u - 1))
+			error("conflicting storage class %s", Token.toChars(token.value));
+	}
+	
+	/**************************************
+	 * Parse constraint.
+	 * Constraint is of the form:
+	 *	if ( ConstraintExpression )
+	 */
+version (DMDV2) {
+    Expression parseConstraint()
+	{
+		Expression e = null;
+
+		if (token.value == TOKif)
+		{
+			nextToken();	// skip over 'if'
+			check(TOKlparen);
+			e = parseExpression();
+			check(TOKrparen);
+		}
+		return e;
+	}
+}
+	/**************************************
+	 * Parse a TemplateDeclaration.
+	 */
+    TemplateDeclaration parseTemplateDeclaration()
+	{
+		TemplateDeclaration tempdecl;
+		Identifier id;
+		TemplateParameters tpl;
+		Array decldefs;
+		Expression constraint = null;
+		Loc loc = this.loc;
+
+		nextToken();
+		if (token.value != TOKidentifier)
+		{   
+			error("TemplateIdentifier expected following template");
+			goto Lerr;
+		}
+		id = token.ident;
+		nextToken();
+		tpl = parseTemplateParameterList();
+		if (!tpl)
+			goto Lerr;
+
+		constraint = parseConstraint();
+
+		if (token.value != TOKlcurly)
+		{	
+			error("members of template declaration expected");
+			goto Lerr;
+		}
+		else
+		{
+			nextToken();
+			decldefs = parseDeclDefs(0);
+			if (token.value != TOKrcurly)
+			{   
+				error("template member expected");
+				goto Lerr;
+			}
+			nextToken();
+		}
+
+		tempdecl = new TemplateDeclaration(loc, id, tpl, constraint, decldefs);
+		return tempdecl;
+
+	Lerr:
+		return null;
+	}
+	
+	/******************************************
+	 * Parse template parameter list.
+	 * Input:
+	 *	flag	0: parsing "( list )"
+	 *		1: parsing non-empty "list )"
+	 */
+    TemplateParameters parseTemplateParameterList(int flag = 0)
+	{
+		TemplateParameters tpl = new TemplateParameters();
+
+		if (!flag && token.value != TOKlparen)
+		{   
+			error("parenthesized TemplateParameterList expected following TemplateIdentifier");
+			goto Lerr;
+		}
+		nextToken();
+
+		// Get array of TemplateParameters
+		if (flag || token.value != TOKrparen)
+		{	
+			int isvariadic = 0;
+
+			while (true)
+			{   
+				TemplateParameter tp;
+				Identifier tp_ident = null;
+				Type tp_spectype = null;
+				Type tp_valtype = null;
+				Type tp_defaulttype = null;
+				Expression tp_specvalue = null;
+				Expression tp_defaultvalue = null;
+				Token* t;
+
+				// Get TemplateParameter
+
+				// First, look ahead to see if it is a TypeParameter or a ValueParameter
+				t = peek(&token);
+				if (token.value == TOKalias)
+				{	
+					// AliasParameter
+					nextToken();
+					Type spectype = null;
+					if (isDeclaration(&token, 2, TOKreserved, null))
+					{
+						spectype = parseType(&tp_ident);
+					}
+					else
+					{
+						if (token.value != TOKidentifier)
+						{
+							error("identifier expected for template alias parameter");
+							goto Lerr;
+						}
+						tp_ident = token.ident;
+						nextToken();
+					}
+					Object spec = null;
+					if (token.value == TOKcolon)	// : Type
+					{
+						nextToken();
+						if (isDeclaration(&token, 0, TOKreserved, null))
+							spec = parseType();
+						else
+						spec = parseCondExp();
+					}
+					Object def = null;
+					if (token.value == TOKassign)	// = Type
+					{
+						nextToken();
+						if (isDeclaration(&token, 0, TOKreserved, null))
+							def = parseType();
+						else
+							def = parseCondExp();
+					}
+					tp = new TemplateAliasParameter(loc, tp_ident, spectype, spec, def);
+				}
+				else if (t.value == TOKcolon || t.value == TOKassign ||
+					 t.value == TOKcomma || t.value == TOKrparen)
+				{	// TypeParameter
+					if (token.value != TOKidentifier)
+					{   error("identifier expected for template type parameter");
+						goto Lerr;
+					}
+					tp_ident = token.ident;
+					nextToken();
+					if (token.value == TOKcolon)	// : Type
+					{
+						nextToken();
+						tp_spectype = parseType();
+					}
+					if (token.value == TOKassign)	// = Type
+					{
+						nextToken();
+						tp_defaulttype = parseType();
+					}
+					tp = new TemplateTypeParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
+				}
+				else if (token.value == TOKidentifier && t.value == TOKdotdotdot)
+				{	// ident...
+					if (isvariadic)
+						error("variadic template parameter must be last");
+					isvariadic = 1;
+					tp_ident = token.ident;
+					nextToken();
+					nextToken();
+					tp = new TemplateTupleParameter(loc, tp_ident);
+				}
+///		version (DMDV2) {
+				else if (token.value == TOKthis)
+				{	// ThisParameter
+					nextToken();
+					if (token.value != TOKidentifier)
+					{   error("identifier expected for template this parameter");
+						goto Lerr;
+					}
+					tp_ident = token.ident;
+					nextToken();
+					if (token.value == TOKcolon)	// : Type
+					{
+						nextToken();
+						tp_spectype = parseType();
+					}
+					if (token.value == TOKassign)	// = Type
+					{
+						nextToken();
+						tp_defaulttype = parseType();
+					}
+					tp = new TemplateThisParameter(loc, tp_ident, tp_spectype, tp_defaulttype);
+				}
+///		}
+				else
+				{	// ValueParameter
+					tp_valtype = parseType(&tp_ident);
+					if (!tp_ident)
+					{
+						error("identifier expected for template value parameter");
+						tp_ident = new Identifier("error", TOKidentifier);
+					}
+					if (token.value == TOKcolon)	// : CondExpression
+					{
+						nextToken();
+						tp_specvalue = parseCondExp();
+					}
+					if (token.value == TOKassign)	// = CondExpression
+					{
+						nextToken();
+						tp_defaultvalue = parseDefaultInitExp();
+					}
+					tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue);
+				}
+				tpl.push(cast(void*)tp);
+				if (token.value != TOKcomma)
+					break;
+				nextToken();
+			}
+		}
+		check(TOKrparen);
+
+	Lerr:
+		return tpl;
+	}
+	
+    Dsymbol parseMixin()
+	{
+		assert(false);
+	}
+	
+	/******************************************
+	 * Parse template argument list.
+	 * Input:
+	 * 	current token is opening '('
+	 * Output:
+	 *	current token is one after closing ')'
+	 */
+    Objects parseTemplateArgumentList()
+	{
+		//printf("Parser.parseTemplateArgumentList()\n");
+		if (token.value != TOKlparen && token.value != TOKlcurly)
+		{   
+			error("!(TemplateArgumentList) expected following TemplateIdentifier");
+			return new Objects();
+		}
+		return parseTemplateArgumentList2();
+	}
+	
+    Objects parseTemplateArgumentList2()
+	{
+		//printf("Parser.parseTemplateArgumentList2()\n");
+		Objects tiargs = new Objects();
+		TOK endtok = TOKrparen;
+		nextToken();
+
+		// Get TemplateArgumentList
+		if (token.value != endtok)
+		{
+			while (1)
+			{
+				// See if it is an Expression or a Type
+				if (isDeclaration(&token, 0, TOKreserved, null))
+				{	// Template argument is a type
+					Type ta = parseType();
+					tiargs.push(cast(void*)ta);
+				}
+				else
+				{	// Template argument is an expression
+					Expression ea = parseAssignExp();
+
+					if (ea.op == TOKfunction)
+					{   
+						FuncLiteralDeclaration fd = (cast(FuncExp)ea).fd;
+						if (fd.type.ty == Tfunction)
+						{
+							TypeFunction tf = cast(TypeFunction)fd.type;
+							/* If there are parameters that consist of only an identifier,
+							 * rather than assuming the identifier is a type, as we would
+							 * for regular function declarations, assume the identifier
+							 * is the parameter name, and we're building a template with
+							 * a deduced type.
+							 */
+							TemplateParameters tpl = null;
+							for (int i = 0; i < tf.parameters.dim; i++)
+							{   
+								Argument param = cast(Argument)tf.parameters.data[i];
+								if (param.ident is null &&
+									param.type &&
+									param.type.ty == Tident &&
+									(cast(TypeIdentifier)param.type).idents.dim == 0
+								   )
+								{
+									/* Switch parameter type to parameter identifier,
+									 * parameterize with template type parameter _T
+									 */
+									TypeIdentifier pt = cast(TypeIdentifier)param.type;
+									param.ident = pt.ident;
+									Identifier id = Lexer.uniqueId("__T");
+									param.type = new TypeIdentifier(pt.loc, id);
+									TemplateParameter tp = new TemplateTypeParameter(fd.loc, id, null, null);
+									if (!tpl)
+										tpl = new TemplateParameters();
+									tpl.push(cast(void*)tp);
+								}
+							}
+
+							if (tpl)
+							{   
+								// Wrap a template around function fd
+								Array decldefs = new Array();
+								decldefs.push(cast(void*)fd);
+								TemplateDeclaration tempdecl = new TemplateDeclaration(fd.loc, fd.ident, tpl, null, decldefs);
+								tempdecl.literal = 1;	// it's a template 'literal'
+								tiargs.push(cast(void*)tempdecl);
+								goto L1;
+							}
+						}
+					}
+
+					tiargs.push(cast(void*)ea);
+				}
+			 L1:
+				if (token.value != TOKcomma)
+					break;
+				nextToken();
+			}
+		}
+		check(endtok, "template argument list");
+		return tiargs;
+	}
+	
+    Objects parseTemplateArgument()
+	{
+		assert(false);
+	}
+	
+	/**********************************
+	 * Parse a static assertion.
+	 */
+    StaticAssert parseStaticAssert()
+	{
+		Loc loc = this.loc;
+		Expression exp;
+		Expression msg = null;
+
+		//printf("parseStaticAssert()\n");
+		nextToken();
+		check(TOK.TOKlparen);
+		exp = parseAssignExp();
+		if (token.value == TOK.TOKcomma)
+		{	
+			nextToken();
+			msg = parseAssignExp();
+		}
+
+		check(TOK.TOKrparen);
+		check(TOK.TOKsemicolon);
+	
+		return new StaticAssert(loc, exp, msg);
+	}
+	
+    TypeQualified parseTypeof()
+	{
+		TypeQualified t;
+		Loc loc = this.loc;
+
+		nextToken();
+		check(TOK.TOKlparen);
+		if (token.value == TOK.TOKreturn)	// typeof(return)
+		{
+			nextToken();
+			t = new TypeReturn(loc);
+		}
+		else
+		{	
+			Expression exp = parseExpression();	// typeof(expression)
+			t = new TypeTypeof(loc, exp);
+		}
+		check(TOK.TOKrparen);
+		return t;
+	}
+	
+	/***********************************
+	 * Parse extern (linkage)
+	 * The parser is on the 'extern' token.
+	 */
+    LINK parseLinkage()
+	{
+		LINK link = LINK.LINKdefault;
+		nextToken();
+		assert(token.value == TOK.TOKlparen);
+		nextToken();
+		if (token.value == TOK.TOKidentifier)
+		{   
+			Identifier id = token.ident;
+
+			nextToken();
+			if (id == Id.Windows)
+				link = LINK.LINKwindows;
+			else if (id == Id.Pascal)
+				link = LINK.LINKpascal;
+			else if (id == Id.D)
+				link = LINK.LINKd;
+			else if (id == Id.C)
+			{
+				link = LINK.LINKc;
+				if (token.value == TOK.TOKplusplus)
+				{   
+					link = LINK.LINKcpp;
+					nextToken();
+				}
+			}
+			else if (id == Id.System)
+			{
+version (_WIN32) {
+				link = LINK.LINKwindows;
+} else {
+				link = LINK.LINKc;
+}
+			}
+			else
+			{
+				error("valid linkage identifiers are D, C, C++, Pascal, Windows, System");
+				link = LINK.LINKd;
+			}
+		}
+		else
+		{
+			link = LINK.LINKd;		// default
+		}
+		check(TOK.TOKrparen);
+
+		return link;
+	}
+
+
+	/**************************************
+	 * Parse a debug conditional
+	 */	
+    Condition parseDebugCondition()
+	{
+		Condition c;
+
+		if (token.value == TOK.TOKlparen)
+		{
+			nextToken();
+			uint level = 1;
+			Identifier id = null;
+
+			if (token.value == TOK.TOKidentifier)
+				id = token.ident;
+			else if (token.value == TOK.TOKint32v)
+				level = cast(uint)token.uns64value;
+			else
+				error("identifier or integer expected, not %s", token.toChars());
+
+			nextToken();
+			check(TOK.TOKrparen);
+
+			c = new DebugCondition(mod, level, id);
+		}
+		else
+			c = new DebugCondition(mod, 1, null);
+
+		return c;
+	}
+	
+	/**************************************
+	 * Parse a version conditional
+	 */
+    Condition parseVersionCondition()
+	{
+		Condition c;
+		uint level = 1;
+		Identifier id = null;
+
+		if (token.value == TOK.TOKlparen)
+		{
+			nextToken();
+			if (token.value == TOK.TOKidentifier)
+				id = token.ident;
+			else if (token.value == TOK.TOKint32v)
+				level = cast(uint)token.uns64value;
+			else {
+version (DMDV2) {
+				/* Allow:
+				 *    version (unittest)
+				 * even though unittest is a keyword
+				 */
+				if (token.value == TOK.TOKunittest)
+					id = Lexer.idPool(Token.toChars(TOK.TOKunittest));
+				else
+					error("identifier or integer expected, not %s", token.toChars());
+			} else {
+				error("identifier or integer expected, not %s", token.toChars());
+}
+			}
+			nextToken();
+			check(TOK.TOKrparen);
+		}
+		else
+		   error("(condition) expected following version");
+
+		c = new VersionCondition(mod, level, id);
+
+		return c;
+	}
+
+	/***********************************************
+	 *	static if (expression)
+	 *	    body
+	 *	else
+	 *	    body
+	 */
+    Condition parseStaticIfCondition()
+	{
+		Expression exp;
+		Condition condition;
+		Array aif;
+		Array aelse;
+		Loc loc = this.loc;
+
+		nextToken();
+		if (token.value == TOKlparen)
+		{
+			nextToken();
+			exp = parseAssignExp();
+			check(TOKrparen);
+		}
+		else
+		{   
+			error("(expression) expected following static if");
+			exp = null;
+		}
+		condition = new StaticIfCondition(loc, exp);
+		return condition;
+	}
+	
+	/*****************************************
+	 * Parse a constructor definition:
+	 *	this(parameters) { body }
+	 * or postblit:
+	 *	this(this) { body }
+	 * or constructor template:
+	 *	this(templateparameters)(parameters) { body }
+	 * Current token is 'this'.
+	 */
+	
+    Dsymbol parseCtor()
+	{
+		Loc loc = this.loc;
+
+		nextToken();
+		if (token.value == TOK.TOKlparen && peek(&token).value == TOK.TOKthis)
+		{	// this(this) { ... }
+			nextToken();
+			nextToken();
+			check(TOK.TOKrparen);
+			PostBlitDeclaration f = new PostBlitDeclaration(loc, Loc(0));
+			parseContracts(f);
+			return f;
+		}
+
+		/* Look ahead to see if:
+		 *   this(...)(...)
+		 * which is a constructor template
+		 */
+		TemplateParameters tpl = null;
+		if (token.value == TOK.TOKlparen && peekPastParen(&token).value == TOK.TOKlparen)
+		{	tpl = parseTemplateParameterList();
+
+			int varargs;
+			Arguments arguments = parseParameters(&varargs);
+
+			Expression constraint = null;
+			if (tpl)
+				constraint = parseConstraint();
+
+			CtorDeclaration f = new CtorDeclaration(loc, Loc(0), arguments, varargs);
+			parseContracts(f);
+
+			// Wrap a template around it
+			Array decldefs = new Array();
+			decldefs.push(cast(void*)f);
+			TemplateDeclaration tempdecl =
+				new TemplateDeclaration(loc, f.ident, tpl, constraint, decldefs);
+			return tempdecl;
+		}
+
+		/* Just a regular constructor
+		 */
+		int varargs;
+		Arguments arguments = parseParameters(&varargs);
+		CtorDeclaration f = new CtorDeclaration(loc, Loc(0), arguments, varargs);
+		parseContracts(f);
+		return f;
+	}
+	
+    PostBlitDeclaration parsePostBlit()
+	{
+		assert(false);
+	}
+	
+	/*****************************************
+	 * Parse a destructor definition:
+	 *	~this() { body }
+	 * Current token is '~'.
+	 */
+    DtorDeclaration parseDtor()
+	{
+		DtorDeclaration f;
+		Loc loc = this.loc;
+
+		nextToken();
+		check(TOKthis);
+		check(TOKlparen);
+		check(TOKrparen);
+
+		f = new DtorDeclaration(loc, Loc(0));
+		parseContracts(f);
+		return f;
+	}
+	
+	/*****************************************
+	 * Parse a static constructor definition:
+	 *	static this() { body }
+	 * Current token is 'this'.
+	 */
+    StaticCtorDeclaration parseStaticCtor()
+	{
+		StaticCtorDeclaration f;
+		Loc loc = this.loc;
+
+		nextToken();
+		check(TOKlparen);
+		check(TOKrparen);
+
+		f = new StaticCtorDeclaration(loc, Loc(0));
+		parseContracts(f);
+		return f;
+	}
+	
+	/*****************************************
+	 * Parse a static destructor definition:
+	 *	static ~this() { body }
+	 * Current token is '~'.
+	 */
+    StaticDtorDeclaration parseStaticDtor()
+	{
+		StaticDtorDeclaration f;
+		Loc loc = this.loc;
+
+		nextToken();
+		check(TOKthis);
+		check(TOKlparen);
+		check(TOKrparen);
+
+		f = new StaticDtorDeclaration(loc, Loc(0));
+		parseContracts(f);
+		return f;
+	}
+	
+	/*****************************************
+	 * Parse an invariant definition:
+	 *	invariant() { body }
+	 * Current token is 'invariant'.
+	 */
+    InvariantDeclaration parseInvariant()
+	{
+		InvariantDeclaration f;
+		Loc loc = this.loc;
+
+		nextToken();
+		if (token.value == TOKlparen)	// optional ()
+		{
+			nextToken();
+			check(TOKrparen);
+		}
+
+		f = new InvariantDeclaration(loc, Loc(0));
+		f.fbody = parseStatement(ParseStatementFlags.PScurly);
+		return f;
+	}
+	
+	/*****************************************
+	 * Parse a unittest definition:
+	 *	unittest { body }
+	 * Current token is 'unittest'.
+	 */
+    UnitTestDeclaration parseUnitTest()
+	{
+		Loc loc = this.loc;
+
+		nextToken();
+
+		UnitTestDeclaration f = new UnitTestDeclaration(loc, this.loc);
+		f.fbody = parseStatement(ParseStatementFlags.PScurly);
+
+		return f;
+	}
+	
+    NewDeclaration parseNew()
+	{
+		assert(false);
+	}
+	
+    DeleteDeclaration parseDelete()
+	{
+		assert(false);
+	}
+	
+    Arguments parseParameters(int* pvarargs)
+	{
+		Arguments arguments = new Arguments();
+		int varargs = 0;
+		int hasdefault = 0;
+
+		check(TOK.TOKlparen);
+		while (1)
+		{   Type *tb;
+		Identifier ai = null;
+		Type at;
+		Argument a;
+		STC storageClass = STC.STCundefined;
+		STC stc;
+		Expression ae;
+
+		for ( ;1; nextToken())
+		{
+			switch (token.value)
+			{
+			case TOK.TOKrparen:
+				break;
+
+			case TOK.TOKdotdotdot:
+				varargs = 1;
+				nextToken();
+				break;
+
+			case TOK.TOKconst:
+				if (peek(&token).value == TOK.TOKlparen)
+				goto Ldefault;
+				stc = STC.STCconst;
+				goto L2;
+
+			case TOK.TOKinvariant:
+			case TOK.TOKimmutable:
+				if (peek(&token).value == TOK.TOKlparen)
+				goto Ldefault;
+				stc = STC.STCimmutable;
+				goto L2;
+
+			case TOK.TOKshared:
+				if (peek(&token).value == TOK.TOKlparen)
+				goto Ldefault;
+				stc = STC.STCshared;
+				goto L2;
+
+			case TOK.TOKin:	   stc = STC.STCin;		goto L2;
+			case TOK.TOKout:	   stc = STC.STCout;	goto L2;
+			case TOK.TOKinout:
+			case TOK.TOKref:	   stc = STC.STCref;	goto L2;
+			case TOK.TOKlazy:	   stc = STC.STClazy;	goto L2;
+			case TOK.TOKscope:	   stc = STC.STCscope;	goto L2;
+			case TOK.TOKfinal:	   stc = STC.STCfinal;	goto L2;
+			L2:
+				if (storageClass & stc ||
+				(storageClass & STC.STCin && stc & (STC.STCconst | STC.STCscope)) ||
+				(stc & STC.STCin && storageClass & (STC.STCconst | STC.STCscope))
+				   )
+				error("redundant storage class %s", Token.toChars(token.value));
+				storageClass |= stc;
+				composeStorageClass(storageClass);
+				continue;
+
+static if (false) {
+			case TOK.TOKstatic:	   stc = STC.STCstatic;		goto L2;
+			case TOK.TOKauto:   storageClass = STC.STCauto;		goto L4;
+			case TOK.TOKalias:  storageClass = STC.STCalias;	goto L4;
+			L4:
+				nextToken();
+				if (token.value == TOK.TOKidentifier)
+				{	ai = token.ident;
+				nextToken();
+				}
+				else
+				ai = null;
+				at = null;		// no type
+				ae = null;		// no default argument
+				if (token.value == TOK.TOKassign)	// = defaultArg
+				{   nextToken();
+				ae = parseDefaultInitExp();
+				hasdefault = 1;
+				}
+				else
+				{   if (hasdefault)
+					error("default argument expected for alias %s",
+						ai ? ai.toChars() : "");
+				}
+				goto L3;
+}
+
+			default:
+			Ldefault:
+				stc = (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy));
+				if (stc & (stc - 1))	// if stc is not a power of 2
+				error("incompatible parameter storage classes");
+				if ((storageClass & (STC.STCconst | STC.STCout)) == (STC.STCconst | STC.STCout))
+				error("out cannot be const");
+				if ((storageClass & (STC.STCimmutable | STC.STCout)) == (STC.STCimmutable | STC.STCout))
+				error("out cannot be immutable");
+				if ((storageClass & STC.STCscope) &&
+				(storageClass & (STC.STCref | STC.STCout)))
+				error("scope cannot be ref or out");
+				at = parseType(&ai);
+				ae = null;
+				if (token.value == TOK.TOKassign)	// = defaultArg
+				{   nextToken();
+				ae = parseDefaultInitExp();
+				hasdefault = 1;
+				}
+				else
+				{   if (hasdefault)
+					error("default argument expected for %s",
+						ai ? ai.toChars() : at.toChars());
+				}
+				if (token.value == TOK.TOKdotdotdot)
+				{   /* This is:
+				 *	at ai ...
+				 */
+
+				if (storageClass & (STC.STCout | STC.STCref))
+					error("variadic argument cannot be out or ref");
+				varargs = 2;
+				a = new Argument(storageClass, at, ai, ae);
+				arguments.push(cast(void*)a);
+				nextToken();
+				break;
+				}
+			L3:
+				a = new Argument(storageClass, at, ai, ae);
+				arguments.push(cast(void*)a);
+				if (token.value == TOK.TOKcomma)
+				{   nextToken();
+				goto L1;
+				}
+				break;
+			}
+			break;
+		}
+		break;
+
+		L1:	;
+		}
+		check(TOK.TOKrparen);
+		*pvarargs = varargs;
+		return arguments;
+	}
+	
+    EnumDeclaration parseEnum()
+	{
+		EnumDeclaration e;
+		Identifier id;
+		Type memtype;
+		Loc loc = this.loc;
+
+		//printf("Parser.parseEnum()\n");
+		nextToken();
+		if (token.value == TOK.TOKidentifier)
+		{
+			id = token.ident;
+			nextToken();
+		}
+		else
+			id = null;
+
+		if (token.value == TOK.TOKcolon)
+		{
+			nextToken();
+			memtype = parseBasicType();
+			memtype = parseDeclarator(memtype, null, null);
+		}
+		else
+			memtype = null;
+
+		e = new EnumDeclaration(loc, id, memtype);
+		if (token.value == TOK.TOKsemicolon && id)
+			nextToken();
+		else if (token.value == TOK.TOKlcurly)
+		{
+			//printf("enum definition\n");
+			e.members = new Array();
+			nextToken();
+			ubyte* comment = token.blockComment;
+			while (token.value != TOK.TOKrcurly)
+			{
+				/* Can take the following forms:
+				 *	1. ident
+				 *	2. ident = value
+				 *	3. type ident = value
+				 */
+
+				loc = this.loc;
+
+				Type type = null;
+				Identifier ident;
+				Token* tp = peek(&token);
+				if (token.value == TOK.TOKidentifier &&
+					(tp.value == TOK.TOKassign || tp.value == TOK.TOKcomma || tp.value == TOK.TOKrcurly))
+				{
+					ident = token.ident;
+					type = null;
+					nextToken();
+				}
+				else
+				{
+					type = parseType(&ident, null);
+					if (id || memtype)
+						error("type only allowed if anonymous enum and no enum type");
+				}
+
+				Expression value;
+				if (token.value == TOK.TOKassign)
+				{
+					nextToken();
+					value = parseAssignExp();
+				}
+				else
+				{	
+					value = null;
+					if (type)
+						error("if type, there must be an initializer");
+				}
+
+				EnumMember em = new EnumMember(loc, ident, value, type);
+				e.members.push(cast(void*)em);
+
+				if (token.value == TOK.TOKrcurly) {
+					;
+				} else {
+					addComment(em, comment);
+					comment = null;
+					check(TOK.TOKcomma);
+				}
+				addComment(em, comment);
+				comment = token.blockComment;
+			}
+			nextToken();
+		}
+		else
+			error("enum declaration is invalid");
+
+		//printf("-parseEnum() %s\n", e.toChars());
+		return e;
+	}
+	
+    Dsymbol parseAggregate()
+	{
+		AggregateDeclaration a = null;
+		int anon = 0;
+		TOK tok;
+		Identifier id;
+		TemplateParameters tpl = null;
+		Expression constraint = null;
+
+		//printf("Parser.parseAggregate()\n");
+		tok = token.value;
+		nextToken();
+		if (token.value != TOK.TOKidentifier)
+		{
+			id = null;
+		}
+		else
+		{
+			id = token.ident;
+			nextToken();
+
+			if (token.value == TOK.TOKlparen)
+			{   
+				// Class template declaration.
+
+				// Gather template parameter list
+				tpl = parseTemplateParameterList();
+				constraint = parseConstraint();
+			}
+		}
+
+		Loc loc = this.loc;
+		switch (tok)
+		{	case TOK.TOKclass:
+		case TOK.TOKinterface:
+		{
+			if (!id)
+			error("anonymous classes not allowed");
+
+			// Collect base class(es)
+			BaseClasses baseclasses = null;
+			if (token.value == TOK.TOKcolon)
+			{
+				nextToken();
+				baseclasses = parseBaseClasses();
+
+				if (token.value != TOK.TOKlcurly)
+					error("members expected");
+			}
+
+			if (tok == TOK.TOKclass)
+				a = new ClassDeclaration(loc, id, baseclasses);
+			else
+				a = new InterfaceDeclaration(loc, id, baseclasses);
+			break;
+		}
+
+		case TOK.TOKstruct:
+			if (id)
+			a = new StructDeclaration(loc, id);
+			else
+			anon = 1;
+			break;
+
+		case TOK.TOKunion:
+			if (id)
+			a = new UnionDeclaration(loc, id);
+			else
+			anon = 2;
+			break;
+
+		default:
+			assert(0);
+			break;
+		}
+		if (a && token.value == TOK.TOKsemicolon)
+		{ 	nextToken();
+		}
+		else if (token.value == TOK.TOKlcurly)
+		{
+		//printf("aggregate definition\n");
+		nextToken();
+		Array decl = parseDeclDefs(0);
+		if (token.value != TOK.TOKrcurly)
+			error("} expected following member declarations in aggregate");
+		nextToken();
+		if (anon)
+		{
+			/* Anonymous structs/unions are more like attributes.
+			 */
+			return new AnonDeclaration(loc, anon - 1, decl);
+		}
+		else
+			a.members = decl;
+		}
+		else
+		{
+		error("{ } expected following aggregate declaration");
+		a = new StructDeclaration(loc, null);
+		}
+
+		if (tpl)
+		{	// Wrap a template around the aggregate declaration
+
+		Array decldefs = new Array();
+		decldefs.push(cast(void*)a);
+		TemplateDeclaration tempdecl =
+			new TemplateDeclaration(loc, id, tpl, constraint, decldefs);
+		return tempdecl;
+		}
+
+		return a;
+	}
+	
+    BaseClasses parseBaseClasses()
+	{
+		BaseClasses baseclasses = new BaseClasses();
+
+		for (; 1; nextToken())
+		{
+			PROT protection = PROT.PROTpublic;
+			switch (token.value)
+			{
+				case TOK.TOKprivate:
+					protection = PROT.PROTprivate;
+					nextToken();
+					break;
+				case TOK.TOKpackage:
+					protection = PROT.PROTpackage;
+					nextToken();
+					break;
+				case TOK.TOKprotected:
+					protection = PROT.PROTprotected;
+					nextToken();
+					break;
+				case TOK.TOKpublic:
+					protection = PROT.PROTpublic;
+					nextToken();
+					break;
+				default:
+					break;	///
+			}
+			if (token.value == TOK.TOKidentifier)
+			{
+				BaseClass b = new BaseClass(parseBasicType(), protection);
+				baseclasses.push(cast(void*)b);
+				if (token.value != TOK.TOKcomma)
+					break;
+			}
+			else
+			{
+				error("base classes expected instead of %s", token.toChars());
+				return null;
+			}
+		}
+		return baseclasses;
+	}
+	
+    Import parseImport(Array decldefs, int isstatic)
+	{
+		Import s;
+		Identifier id;
+		Identifier aliasid = null;
+		Array a;
+		Loc loc;
+
+		//printf("Parser.parseImport()\n");
+		do
+		{
+		 L1:
+			nextToken();
+			if (token.value != TOK.TOKidentifier)
+			{   
+				error("Identifier expected following import");
+				break;
+			}
+
+			loc = this.loc;
+			a = null;
+			id = token.ident;
+			nextToken();
+			if (!aliasid && token.value == TOK.TOKassign)
+			{
+				aliasid = id;
+				goto L1;
+			}
+			while (token.value == TOK.TOKdot)
+			{
+				if (!a)
+					a = new Array();
+				a.push(cast(void*)id);
+				nextToken();
+				if (token.value != TOK.TOKidentifier)
+				{   
+					error("identifier expected following package");
+					break;
+				}
+				id = token.ident;
+				nextToken();
+			}
+
+			s = new Import(loc, a, id, aliasid, isstatic);
+			decldefs.push(cast(void*)s);
+
+			/* Look for
+			 *	: alias=name, alias=name;
+			 * syntax.
+			 */
+			if (token.value == TOK.TOKcolon)
+			{
+				do
+				{	
+					Identifier name;
+
+					nextToken();
+					if (token.value != TOK.TOKidentifier)
+					{   
+						error("Identifier expected following :");
+						break;
+					}
+					Identifier alias_ = token.ident;
+					nextToken();
+					if (token.value == TOK.TOKassign)
+					{
+						nextToken();
+						if (token.value != TOK.TOKidentifier)
+						{   
+							error("Identifier expected following %s=", alias_.toChars());
+							break;
+						}
+						name = token.ident;
+						nextToken();
+					}
+					else
+					{   
+						name = alias_;
+						alias_ = null;
+					}
+					s.addAlias(name, alias_);
+				} while (token.value == TOK.TOKcomma);
+
+				break;	// no comma-separated imports of this form
+			}
+
+			aliasid = null;
+
+		} while (token.value == TOK.TOKcomma);
+
+		if (token.value == TOK.TOKsemicolon)
+			nextToken();
+		else
+		{
+			error("';' expected");
+			nextToken();
+		}
+
+		return null;
+	}
+	
+    Type parseType(Identifier* pident = null, TemplateParameters* tpl = null)
+	{
+		Type t;
+
+		/* Take care of the storage class prefixes that
+		 * serve as type attributes:
+		 *  const shared, shared const, const, invariant, shared
+		 */
+		if (token.value == TOK.TOKconst && peekNext() == TOK.TOKshared && peekNext2() != TOK.TOKlparen ||
+			token.value == TOK.TOKshared && peekNext() == TOK.TOKconst && peekNext2() != TOK.TOKlparen)
+		{
+			nextToken();
+			nextToken();
+			/* shared const type
+			 */
+			t = parseType(pident, tpl);
+			t = t.makeSharedConst();
+			return t;
+		}
+		else if (token.value == TOK.TOKconst && peekNext() != TOK.TOKlparen)
+		{
+			nextToken();
+			/* const type
+			 */
+			t = parseType(pident, tpl);
+			t = t.makeConst();
+			return t;
+		}
+		else if ((token.value == TOK.TOKinvariant || token.value == TOK.TOKimmutable) &&
+				 peekNext() != TOK.TOKlparen)
+		{
+			nextToken();
+			/* invariant type
+			 */
+			t = parseType(pident, tpl);
+			t = t.makeInvariant();
+			return t;
+		}
+		else if (token.value == TOK.TOKshared && peekNext() != TOK.TOKlparen)
+		{
+			nextToken();
+			/* shared type
+			 */
+			t = parseType(pident, tpl);
+			t = t.makeShared();
+			return t;
+		}
+		else
+			t = parseBasicType();	
+		t = parseDeclarator(t, pident, tpl);
+		return t;
+	}
+	
+    Type parseBasicType()
+	{
+		Type t;
+		Identifier id;
+		TypeQualified tid;
+
+		//printf("parseBasicType()\n");
+		switch (token.value)
+		{
+			case TOK.TOKvoid:	 t = Type.tvoid;  goto LabelX;
+			case TOK.TOKint8:	 t = Type.tint8;  goto LabelX;
+			case TOK.TOKuns8:	 t = Type.tuns8;  goto LabelX;
+			case TOK.TOKint16:	 t = Type.tint16; goto LabelX;
+			case TOK.TOKuns16:	 t = Type.tuns16; goto LabelX;
+			case TOK.TOKint32:	 t = Type.tint32; goto LabelX;
+			case TOK.TOKuns32:	 t = Type.tuns32; goto LabelX;
+			case TOK.TOKint64:	 t = Type.tint64; goto LabelX;
+			case TOK.TOKuns64:	 t = Type.tuns64; goto LabelX;
+			case TOK.TOKfloat32: t = Type.tfloat32; goto LabelX;
+			case TOK.TOKfloat64: t = Type.tfloat64; goto LabelX;
+			case TOK.TOKfloat80: t = Type.tfloat80; goto LabelX;
+			case TOK.TOKimaginary32: t = Type.timaginary32; goto LabelX;
+			case TOK.TOKimaginary64: t = Type.timaginary64; goto LabelX;
+			case TOK.TOKimaginary80: t = Type.timaginary80; goto LabelX;
+			case TOK.TOKcomplex32: t = Type.tcomplex32; goto LabelX;
+			case TOK.TOKcomplex64: t = Type.tcomplex64; goto LabelX;
+			case TOK.TOKcomplex80: t = Type.tcomplex80; goto LabelX;
+			case TOK.TOKbit:	 t = Type.tbit;     goto LabelX;
+			case TOK.TOKbool:	 t = Type.tbool;    goto LabelX;
+			case TOK.TOKchar:	 t = Type.tchar;    goto LabelX;
+			case TOK.TOKwchar:	 t = Type.twchar; goto LabelX;
+			case TOK.TOKdchar:	 t = Type.tdchar; goto LabelX;
+			LabelX:
+				nextToken();
+				break;
+
+		case TOK.TOKidentifier:
+			id = token.ident;
+			nextToken();
+			if (token.value == TOK.TOKnot)
+			{	// ident!(template_arguments)
+			TemplateInstance tempinst = new TemplateInstance(loc, id);
+			nextToken();
+			if (token.value == TOK.TOKlparen)
+				// ident!(template_arguments)
+				tempinst.tiargs = parseTemplateArgumentList();
+			else
+				// ident!template_argument
+				tempinst.tiargs = parseTemplateArgument();
+			tid = new TypeInstance(loc, tempinst);
+			goto Lident2;
+			}
+		Lident:
+			tid = new TypeIdentifier(loc, id);
+		Lident2:
+			while (token.value == TOK.TOKdot)
+			{	nextToken();
+			if (token.value != TOK.TOKidentifier)
+			{   error("identifier expected following '.' instead of '%s'", token.toChars());
+				break;
+			}
+			id = token.ident;
+			nextToken();
+			if (token.value == TOK.TOKnot)
+			{
+				TemplateInstance tempinst = new TemplateInstance(loc, id);
+				nextToken();
+				if (token.value == TOK.TOKlparen)
+				// ident!(template_arguments)
+				tempinst.tiargs = parseTemplateArgumentList();
+				else
+				// ident!template_argument
+				tempinst.tiargs = parseTemplateArgument();
+				tid.addIdent(cast(Identifier)tempinst);
+			}
+			else
+				tid.addIdent(id);
+			}
+			t = tid;
+			break;
+
+		case TOK.TOKdot:
+			// Leading . as in .foo
+			id = Id.empty;
+			goto Lident;
+
+		case TOK.TOKtypeof:
+			// typeof(expression)
+			tid = parseTypeof();
+			goto Lident2;
+
+		case TOK.TOKconst:
+			// const(type)
+			nextToken();
+			check(TOK.TOKlparen);
+			t = parseType();
+			check(TOK.TOKrparen);
+			if (t.isShared())
+			t = t.makeSharedConst();
+			else
+			t = t.makeConst();
+			break;
+
+		case TOK.TOKinvariant:
+		case TOK.TOKimmutable:
+			// invariant(type)
+			nextToken();
+			check(TOK.TOKlparen);
+			t = parseType();
+			check(TOK.TOKrparen);
+			t = t.makeInvariant();
+			break;
+
+		case TOK.TOKshared:
+			// shared(type)
+			nextToken();
+			check(TOK.TOKlparen);
+			t = parseType();
+			check(TOK.TOKrparen);
+			if (t.isConst())
+			t = t.makeSharedConst();
+			else
+			t = t.makeShared();
+			break;
+
+		default:
+			error("basic type expected, not %s", token.toChars());
+			t = Type.tint32;
+			break;
+		}
+		return t;
+	}
+	
+    Type parseBasicType2(Type t)
+	{
+		//printf("parseBasicType2()\n");
+		while (1)
+		{
+		switch (token.value)
+		{
+			case TOK.TOKmul:
+			t = new TypePointer(t);
+			nextToken();
+			continue;
+
+			case TOK.TOKlbracket:
+			// Handle []. Make sure things like
+			//     int[3][1] a;
+			// is (array[1] of array[3] of int)
+			nextToken();
+			if (token.value == TOK.TOKrbracket)
+			{
+				t = new TypeDArray(t);			// []
+				nextToken();
+			}
+			else if (isDeclaration(&token, 0, TOK.TOKrbracket, null))
+			{   // It's an associative array declaration
+
+				//printf("it's an associative array\n");
+				Type index = parseType();		// [ type ]
+				t = new TypeAArray(t, index);
+				check(TOK.TOKrbracket);
+			}
+			else
+			{
+				//printf("it's type[expression]\n");
+				inBrackets++;
+				Expression e = parseExpression();		// [ expression ]
+				if (token.value == TOK.TOKslice)
+				{
+				nextToken();
+				Expression e2 = parseExpression();	// [ exp .. exp ]
+				t = new TypeSlice(t, e, e2);
+				}
+				else
+				t = new TypeSArray(t,e);
+				inBrackets--;
+				check(TOK.TOKrbracket);
+			}
+			continue;
+
+			case TOK.TOKdelegate:
+			case TOK.TOKfunction:
+			{	// Handle delegate declaration:
+			//	t delegate(parameter list) nothrow pure
+			//	t function(parameter list) nothrow pure
+			Arguments arguments;
+			int varargs;
+			bool ispure = false;
+			bool isnothrow = false;
+			TOK save = token.value;
+
+			nextToken();
+			arguments = parseParameters(&varargs);
+			while (1)
+			{   // Postfixes
+				if (token.value == TOK.TOKpure)
+				ispure = true;
+				else if (token.value == TOK.TOKnothrow)
+				isnothrow = true;
+				else
+				break;
+				nextToken();
+			}
+			TypeFunction tf = new TypeFunction(arguments, t, varargs, linkage);
+			tf.ispure = ispure;
+			tf.isnothrow = isnothrow;
+			if (save == TOK.TOKdelegate)
+				t = new TypeDelegate(tf);
+			else
+				t = new TypePointer(tf);	// pointer to function
+			continue;
+			}
+
+			default:
+			return t;
+		}
+		assert(0);
+		}
+		assert(0);
+		return null;
+	}
+	
+    Type parseDeclarator(Type t, Identifier* pident, TemplateParameters* tpl = null)
+	{
+		Type ts;
+
+		//printf("parseDeclarator(tpl = %p)\n", tpl);
+		t = parseBasicType2(t);
+
+		switch (token.value)
+		{
+
+		case TOK.TOKidentifier:
+			if (pident)
+			*pident = token.ident;
+			else
+			error("unexpected identifer '%s' in declarator", token.ident.toChars());
+			ts = t;
+			nextToken();
+			break;
+
+		case TOK.TOKlparen:
+			/* Parse things with parentheses around the identifier, like:
+			 *	int (*ident[3])[]
+			 * although the D style would be:
+			 *	int[]*[3] ident
+			 */
+			nextToken();
+			ts = parseDeclarator(t, pident);
+			check(TOK.TOKrparen);
+			break;
+
+		default:
+			ts = t;
+			break;
+		}
+
+		// parse DeclaratorSuffixes
+		while (1)
+		{
+		switch (token.value)
+		{
+version (CARRAYDECL) {
+			/* Support C style array syntax:
+			 *   int ident[]
+			 * as opposed to D-style:
+			 *   int[] ident
+			 */
+			case TOK.TOKlbracket:
+			{	// This is the old C-style post [] syntax.
+			TypeNext ta;
+			nextToken();
+			if (token.value == TOK.TOKrbracket)
+			{   // It's a dynamic array
+				ta = new TypeDArray(t);		// []
+				nextToken();
+			}
+			else if (isDeclaration(&token, 0, TOK.TOKrbracket, null))
+			{   // It's an associative array
+
+				//printf("it's an associative array\n");
+				Type index = parseType();		// [ type ]
+				check(TOK.TOKrbracket);
+				ta = new TypeAArray(t, index);
+			}
+			else
+			{
+				//printf("It's a static array\n");
+				Expression e = parseExpression();	// [ expression ]
+				ta = new TypeSArray(t, e);
+				check(TOK.TOKrbracket);
+			}
+
+			/* Insert ta into
+			 *   ts . ... . t
+			 * so that
+			 *   ts . ... . ta . t
+			 */
+			Type* pt;
+			for (pt = &ts; *pt !is t; pt = &(cast(TypeNext)*pt).next) {
+				;
+			}
+			*pt = ta;
+			continue;
+			}
+}
+			case TOK.TOKlparen:
+			{
+			if (tpl)
+			{
+				/* Look ahead to see if this is (...)(...),
+				 * i.e. a function template declaration
+				 */
+				if (peekPastParen(&token).value == TOK.TOKlparen)
+				{
+				//printf("function template declaration\n");
+
+				// Gather template parameter list
+				*tpl = parseTemplateParameterList();
+				}
+			}
+
+			int varargs;
+			Arguments arguments = parseParameters(&varargs);
+			Type tf = new TypeFunction(arguments, t, varargs, linkage);
+
+			/* Parse const/invariant/nothrow/pure postfix
+			 */
+			while (1)
+			{
+				switch (token.value)
+				{
+					case TOK.TOKconst:
+						if (tf.isShared())
+						tf = tf.makeSharedConst();
+						else
+						tf = tf.makeConst();
+						nextToken();
+						continue;
+
+					case TOK.TOKinvariant:
+					case TOK.TOKimmutable:
+						tf = tf.makeInvariant();
+						nextToken();
+						continue;
+
+					case TOK.TOKshared:
+						if (tf.isConst())
+						tf = tf.makeSharedConst();
+						else
+						tf = tf.makeShared();
+						nextToken();
+						continue;
+
+					case TOK.TOKnothrow:
+						(cast(TypeFunction)tf).isnothrow = 1;
+						nextToken();
+						continue;
+
+					case TOK.TOKpure:
+						(cast(TypeFunction)tf).ispure = 1;
+						nextToken();
+						continue;
+
+					case TOK.TOKat:
+						nextToken();
+						if (token.value != TOK.TOKidentifier)
+						{   error("attribute identifier expected");
+						nextToken();
+						continue;
+						}
+						Identifier id = token.ident;
+						if (id is Id.property)
+						(cast(TypeFunction)tf).ispure = 1;
+						else
+						error("valid attribute identifiers are property, not %s", id.toChars());
+						nextToken();
+						continue;
+					default:
+						break;	///
+				}
+				break;
+			}
+
+			/* Insert tf into
+			 *   ts . ... . t
+			 * so that
+			 *   ts . ... . tf . t
+			 */
+			Type* pt;
+			for (pt = &ts; *pt !is t; pt = &(cast(TypeNext)*pt).next) {
+				;
+			}
+			*pt = tf;
+			break;
+			}
+			
+			default:
+				break;	///
+		}
+		break;
+		}
+
+		return ts;
+	}
+	
+    Array parseDeclarations(STC storage_class)
+	{
+		STC stc;
+		Type ts;
+		Type t;
+		Type tfirst;
+		Identifier ident;
+		Array a;
+		TOK tok = TOK.TOKreserved;
+		ubyte* comment = token.blockComment;
+		LINK link = linkage;
+
+		//printf("parseDeclarations() %s\n", token.toChars());
+		if (storage_class)
+		{	ts = null;		// infer type
+		goto L2;
+		}
+
+		switch (token.value)
+		{
+			case TOK.TOKalias:
+				/* Look for:
+				 *   alias identifier this;
+				 */
+				tok = token.value;
+				nextToken();
+				if (token.value == TOK.TOKidentifier && peek(&token).value == TOK.TOKthis)
+				{
+				AliasThis s = new AliasThis(this.loc, token.ident);
+				nextToken();
+				check(TOK.TOKthis);
+				check(TOK.TOKsemicolon);
+				a = new Array();
+				a.push(cast(void*)s);
+				addComment(s, comment);
+				return a;
+				}
+				break;
+			case TOK.TOKtypedef:
+				tok = token.value;
+				nextToken();
+				break;
+			default:
+				break;
+		}
+
+		storage_class = STC.STCundefined;
+		while (1)
+		{
+		switch (token.value)
+		{
+			case TOK.TOKconst:
+			if (peek(&token).value == TOK.TOKlparen)
+				break;		// const as type constructor
+			stc = STC.STCconst;		// const as storage class
+			goto L1;
+
+			case TOK.TOKinvariant:
+			case TOK.TOKimmutable:
+			if (peek(&token).value == TOK.TOKlparen)
+				break;
+			stc = STC.STCimmutable;
+			goto L1;
+
+			case TOK.TOKshared:
+			if (peek(&token).value == TOK.TOKlparen)
+				break;
+			stc = STC.STCshared;
+			goto L1;
+
+			case TOK.TOKstatic:	stc = STC.STCstatic;	 goto L1;
+			case TOK.TOKfinal:	stc = STC.STCfinal;		 goto L1;
+			case TOK.TOKauto:	stc = STC.STCauto;		 goto L1;
+			case TOK.TOKscope:	stc = STC.STCscope;		 goto L1;
+			case TOK.TOKoverride:	stc = STC.STCoverride;	 goto L1;
+			case TOK.TOKabstract:	stc = STC.STCabstract;	 goto L1;
+			case TOK.TOKsynchronized: stc = STC.STCsynchronized; goto L1;
+			case TOK.TOKdeprecated: stc = STC.STCdeprecated;	 goto L1;
+version (DMDV2) {
+			case TOK.TOKnothrow:    stc = STC.STCnothrow;	 goto L1;
+			case TOK.TOKpure:       stc = STC.STCpure;		 goto L1;
+			case TOK.TOKref:        stc = STC.STCref;            goto L1;
+			case TOK.TOKtls:        stc = STC.STCtls;		 goto L1;
+			case TOK.TOKgshared:    stc = STC.STCgshared;	 goto L1;
+			case TOK.TOKenum:	stc = STC.STCmanifest;	 goto L1;
+}
+			L1:
+			if (storage_class & stc)
+				error("redundant storage class '%s'", token.toChars());
+			storage_class = (storage_class | stc);
+			composeStorageClass(storage_class);
+			nextToken();
+			continue;
+
+			case TOK.TOKextern:
+			if (peek(&token).value != TOK.TOKlparen)
+			{   stc = STC.STCextern;
+				goto L1;
+			}
+
+			link = parseLinkage();
+			continue;
+
+			default:
+			break;
+		}
+		break;
+		}
+
+		/* Look for auto initializers:
+		 *	storage_class identifier = initializer;
+		 */
+		if (storage_class &&
+		token.value == TOK.TOKidentifier &&
+		peek(&token).value == TOK.TOKassign)
+		{
+		return parseAutoDeclarations(storage_class, comment);
+		}
+
+		if (token.value == TOK.TOKclass)
+		{
+		AggregateDeclaration s = cast(AggregateDeclaration)parseAggregate();
+		s.storage_class |= storage_class;
+		a = new Array();
+		a.push(cast(void*)s);
+		addComment(s, comment);
+		return a;
+		}
+
+		/* Look for return type inference for template functions.
+		 */
+		{
+		Token *tk;
+		if (storage_class &&
+		token.value == TOK.TOKidentifier &&
+		(tk = peek(&token)).value == TOK.TOKlparen &&
+		skipParens(tk, &tk) &&
+		peek(tk).value == TOK.TOKlparen)
+		{
+		ts = null;
+		}
+		else
+		{
+		ts = parseBasicType();
+		ts = parseBasicType2(ts);
+		}
+		}
+
+	L2:
+		tfirst = null;
+		a = new Array();
+
+		while (1)
+		{
+		Loc loc = this.loc;
+		TemplateParameters tpl = null;
+
+		ident = null;
+		t = parseDeclarator(ts, &ident, &tpl);
+		assert(t);
+		if (!tfirst)
+			tfirst = t;
+		else if (t != tfirst)
+			error("multiple declarations must have the same type, not %s and %s",
+			tfirst.toChars(), t.toChars());
+		if (!ident)
+			error("no identifier for declarator %s", t.toChars());
+
+		if (tok == TOK.TOKtypedef || tok == TOK.TOKalias)
+		{   Declaration v;
+			Initializer init = null;
+
+			if (token.value == TOK.TOKassign)
+			{
+			nextToken();
+			init = parseInitializer();
+			}
+			if (tok == TOK.TOKtypedef)
+			v = new TypedefDeclaration(loc, ident, t, init);
+			else
+			{	if (init)
+				error("alias cannot have initializer");
+			v = new AliasDeclaration(loc, ident, t);
+			}
+			v.storage_class = storage_class;
+			if (link == linkage)
+			a.push(cast(void*)v);
+			else
+			{
+			Array ax = new Array();
+			ax.push(cast(void*)v);
+			Dsymbol s = new LinkDeclaration(link, ax);
+			a.push(cast(void*)s);
+			}
+			switch (token.value)
+			{   case TOK.TOKsemicolon:
+				nextToken();
+				addComment(v, comment);
+				break;
+
+			case TOK.TOKcomma:
+				nextToken();
+				addComment(v, comment);
+				continue;
+
+			default:
+				error("semicolon expected to close %s declaration", Token.toChars(tok));
+				break;
+			}
+		}
+		else if (t.ty == TY.Tfunction)
+		{
+			TypeFunction tf = cast(TypeFunction)t;
+			Expression constraint = null;
+static if (false) {
+			if (Argument.isTPL(tf.parameters))
+			{
+			if (!tpl)
+				tpl = new TemplateParameters();
+			}
+}
+			FuncDeclaration f =
+			new FuncDeclaration(loc, Loc(0), ident, storage_class, t);
+			addComment(f, comment);
+			if (tpl)
+			constraint = parseConstraint();
+			parseContracts(f);
+			addComment(f, null);
+			Dsymbol s;
+			if (link == linkage)
+			{
+			s = f;
+			}
+			else
+			{
+			Array ax = new Array();
+			ax.push(cast(void*)f);
+			s = new LinkDeclaration(link, ax);
+			}
+			/* A template parameter list means it's a function template
+			 */
+			if (tpl)
+			{
+			// Wrap a template around the function declaration
+			Array decldefs = new Array();
+			decldefs.push(cast(void*)s);
+			TemplateDeclaration tempdecl =
+				new TemplateDeclaration(loc, s.ident, tpl, constraint, decldefs);
+			s = tempdecl;
+			}
+			addComment(s, comment);
+			a.push(cast(void*)s);
+		}
+		else
+		{
+			Initializer init = null;
+			if (token.value == TOK.TOKassign)
+			{
+			nextToken();
+			init = parseInitializer();
+			}
+
+			VarDeclaration v = new VarDeclaration(loc, t, ident, init);
+			v.storage_class = storage_class;
+			if (link == linkage)
+			a.push(cast(void*)v);
+			else
+			{
+			Array ax = new Array();
+			ax.push(cast(void*)v);
+			Dsymbol s = new LinkDeclaration(link, ax);
+			a.push(cast(void*)s);
+			}
+			switch (token.value)
+			{   case TOK.TOKsemicolon:
+				nextToken();
+				addComment(v, comment);
+				break;
+
+			case TOK.TOKcomma:
+				nextToken();
+				addComment(v, comment);
+				continue;
+
+			default:
+				error("semicolon expected, not '%s'", token.toChars());
+				break;
+			}
+		}
+		break;
+		}
+		return a;
+	}
+	
+    void parseContracts(FuncDeclaration f)
+	{
+		Type tb;
+		LINK linksave = linkage;
+
+		// The following is irrelevant, as it is overridden by sc.linkage in
+		// TypeFunction.semantic
+		linkage = LINK.LINKd;		// nested functions have D linkage
+	L1:
+		switch (token.value)
+		{
+		case TOK.TOKlcurly:
+			if (f.frequire || f.fensure)
+			error("missing body { ... } after in or out");
+			f.fbody = parseStatement(ParseStatementFlags.PSsemi);
+			f.endloc = endloc;
+			break;
+
+		case TOK.TOKbody:
+			nextToken();
+			f.fbody = parseStatement(ParseStatementFlags.PScurly);
+			f.endloc = endloc;
+			break;
+
+		case TOK.TOKsemicolon:
+			if (f.frequire || f.fensure)
+			error("missing body { ... } after in or out");
+			nextToken();
+			break;
+
+static if (false) {	// Do we want this for function declarations, so we can do:
+		// int x, y, foo(), z;
+		case TOK.TOKcomma:
+			nextToken();
+			continue;
+}
+
+static if (false) { // Dumped feature
+		case TOK.TOKthrow:
+			if (!f.fthrows)
+			f.fthrows = new Array();
+			nextToken();
+			check(TOK.TOKlparen);
+			while (1)
+			{
+			tb = parseBasicType();
+			f.fthrows.push(tb);
+			if (token.value == TOK.TOKcomma)
+			{   nextToken();
+				continue;
+			}
+			break;
+			}
+			check(TOK.TOKrparen);
+			goto L1;
+}
+
+		case TOK.TOKin:
+			nextToken();
+			if (f.frequire)
+			error("redundant 'in' statement");
+			f.frequire = parseStatement(ParseStatementFlags.PScurly | ParseStatementFlags.PSscope);
+			goto L1;
+
+		case TOK.TOKout:
+			// parse: out (identifier) { statement }
+			nextToken();
+			if (token.value != TOK.TOKlcurly)
+			{
+			check(TOK.TOKlparen);
+			if (token.value != TOK.TOKidentifier)	   
+				error("(identifier) following 'out' expected, not %s", token.toChars());
+			f.outId = token.ident;
+			nextToken();
+			check(TOK.TOKrparen);
+			}
+			if (f.fensure)
+			error("redundant 'out' statement");
+			f.fensure = parseStatement(ParseStatementFlags.PScurly | ParseStatementFlags.PSscope);
+			goto L1;
+
+		default:
+			error("semicolon expected following function declaration");
+			break;
+		}
+		linkage = linksave;
+	}
+	
+    Statement parseStatement(ParseStatementFlags flags)
+	{
+		Statement s;
+		Token* t;
+		Condition condition;
+		Statement ifbody;
+		Statement elsebody;
+		bool isfinal;
+		Loc loc = this.loc;
+
+		//printf("parseStatement()\n");
+
+		if (flags & ParseStatementFlags.PScurly && token.value != TOK.TOKlcurly)
+			error("statement expected to be { }, not %s", token.toChars());
+
+		switch (token.value)
+		{
+		case TOK.TOKidentifier:
+			/* A leading identifier can be a declaration, label, or expression.
+			 * The easiest case to check first is label:
+			 */
+			t = peek(&token);
+			if (t.value == TOK.TOKcolon)
+			{	// It's a label
+
+			Identifier ident = token.ident;
+			nextToken();
+			nextToken();
+			s = parseStatement(ParseStatementFlags.PSsemi);
+			s = new LabelStatement(loc, ident, s);
+			break;
+			}
+			// fallthrough to TOK.TOKdot
+		case TOK.TOKdot:
+		case TOK.TOKtypeof:
+			if (isDeclaration(&token, 2, TOK.TOKreserved, null))
+			goto Ldeclaration;
+			else
+			goto Lexp;
+			break;
+
+		case TOK.TOKassert:
+		case TOK.TOKthis:
+		case TOK.TOKsuper:
+		case TOK.TOKint32v:
+		case TOK.TOKuns32v:
+		case TOK.TOKint64v:
+		case TOK.TOKuns64v:
+		case TOK.TOKfloat32v:
+		case TOK.TOKfloat64v:
+		case TOK.TOKfloat80v:
+		case TOK.TOKimaginary32v:
+		case TOK.TOKimaginary64v:
+		case TOK.TOKimaginary80v:
+		case TOK.TOKcharv:
+		case TOK.TOKwcharv:
+		case TOK.TOKdcharv:
+		case TOK.TOKnull:
+		case TOK.TOKtrue:
+		case TOK.TOKfalse:
+		case TOK.TOKstring:
+		case TOK.TOKlparen:
+		case TOK.TOKcast:
+		case TOK.TOKmul:
+		case TOK.TOKmin:
+		case TOK.TOKadd:
+		case TOK.TOKplusplus:
+		case TOK.TOKminusminus:
+		case TOK.TOKnew:
+		case TOK.TOKdelete:
+		case TOK.TOKdelegate:
+		case TOK.TOKfunction:
+		case TOK.TOKtypeid:
+		case TOK.TOKis:
+		case TOK.TOKlbracket:
+version (DMDV2) {
+		case TOK.TOKtraits:
+		case TOK.TOKfile:
+		case TOK.TOKline:
+}
+		Lexp:
+		{   Expression exp;
+
+			exp = parseExpression();
+			check(TOK.TOKsemicolon, "statement");
+			s = new ExpStatement(loc, exp);
+			break;
+		}
+
+		case TOK.TOKstatic:
+		{   // Look ahead to see if it's static assert() or static if()
+			Token *tt;
+
+			tt = peek(&token);
+			if (tt.value == TOK.TOKassert)
+			{
+				nextToken();
+				s = new StaticAssertStatement(parseStaticAssert());
+				break;
+			}
+			if (tt.value == TOK.TOKif)
+			{
+				nextToken();
+				condition = parseStaticIfCondition();
+				goto Lcondition;
+			}
+			goto Ldeclaration;
+		}
+
+		case TOK.TOKfinal:
+			if (peekNext() == TOK.TOKswitch)
+			{
+			nextToken();
+			isfinal = true;
+			goto Lswitch;
+			}
+			goto Ldeclaration;
+
+		case TOK.TOKwchar: case TOK.TOKdchar:
+		case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar:
+		case TOK.TOKint8: case TOK.TOKuns8:
+		case TOK.TOKint16: case TOK.TOKuns16:
+		case TOK.TOKint32: case TOK.TOKuns32:
+		case TOK.TOKint64: case TOK.TOKuns64:
+		case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80:
+		case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80:
+		case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80:
+		case TOK.TOKvoid:
+		case TOK.TOKtypedef:
+		case TOK.TOKalias:
+		case TOK.TOKconst:
+		case TOK.TOKauto:
+		case TOK.TOKextern:
+		case TOK.TOKinvariant:
+version (DMDV2) {
+		case TOK.TOKimmutable:
+		case TOK.TOKshared:
+		case TOK.TOKnothrow:
+		case TOK.TOKpure:
+		case TOK.TOKtls:
+		case TOK.TOKgshared:
+}
+	//	case TOK.TOKtypeof:
+		Ldeclaration:
+		{   Array a;
+
+			a = parseDeclarations(STC.STCundefined);
+			if (a.dim > 1)
+			{
+			Statements as = new Statements();
+			as.reserve(a.dim);
+			for (int i = 0; i < a.dim; i++)
+			{
+				Dsymbol d = cast(Dsymbol)a.data[i];
+				s = new DeclarationStatement(loc, d);
+				as.push(cast(void*)s);
+			}
+			s = new CompoundDeclarationStatement(loc, as);
+			}
+			else if (a.dim == 1)
+			{
+				Dsymbol d = cast(Dsymbol)a.data[0];
+			s = new DeclarationStatement(loc, d);
+			}
+			else
+			assert(0);
+			if (flags & ParseStatementFlags.PSscope)
+			s = new ScopeStatement(loc, s);
+			break;
+		}
+
+		case TOK.TOKstruct:
+		case TOK.TOKunion:
+		case TOK.TOKclass:
+		case TOK.TOKinterface:
+		{   Dsymbol d;
+
+			d = parseAggregate();
+			s = new DeclarationStatement(loc, d);
+			break;
+		}
+
+		case TOK.TOKenum:
+		{   /* Determine if this is a manifest constant declaration,
+			 * or a conventional enum.
+			 */
+			Dsymbol d;
+			Token* tt = peek(&token);
+			if (tt.value == TOK.TOKlcurly || tt.value == TOK.TOKcolon)
+			d = parseEnum();
+			else if (tt.value != TOK.TOKidentifier)
+			goto Ldeclaration;
+			else
+			{
+			tt = peek(tt);
+			if (tt.value == TOK.TOKlcurly || tt.value == TOK.TOKcolon ||
+				tt.value == TOK.TOKsemicolon)
+				d = parseEnum();
+			else
+				goto Ldeclaration;
+			}
+			s = new DeclarationStatement(loc, d);
+			break;
+		}
+
+		case TOK.TOKmixin:
+		{   t = peek(&token);
+			if (t.value == TOK.TOKlparen)
+			{	// mixin(string)
+			nextToken();
+			check(TOK.TOKlparen, "mixin");
+			Expression e = parseAssignExp();
+			check(TOK.TOKrparen);
+			check(TOK.TOKsemicolon);
+			s = new CompileStatement(loc, e);
+			break;
+			}
+			Dsymbol d = parseMixin();
+			s = new DeclarationStatement(loc, d);
+			break;
+		}
+
+		case TOK.TOKlcurly:
+		{   Statements statements;
+
+			nextToken();
+			statements = new Statements();
+			while (token.value != TOK.TOKrcurly)
+			{
+			statements.push(cast(void*)parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope));
+			}
+			endloc = this.loc;
+			s = new CompoundStatement(loc, statements);
+			if (flags & (ParseStatementFlags.PSscope | ParseStatementFlags.PScurlyscope))
+			s = new ScopeStatement(loc, s);
+			nextToken();
+			break;
+		}
+
+		case TOK.TOKwhile:
+		{   Expression condition2;
+			Statement body_;
+
+			nextToken();
+			check(TOK.TOKlparen);
+			condition2 = parseExpression();
+			check(TOK.TOKrparen);
+			body_ = parseStatement(ParseStatementFlags.PSscope);
+			s = new WhileStatement(loc, condition2, body_);
+			break;
+		}
+
+		case TOK.TOKsemicolon:
+			if (!(flags & ParseStatementFlags.PSsemi))
+			error("use '{ }' for an empty statement, not a ';'");
+			nextToken();
+			s = new ExpStatement(loc, null);
+			break;
+
+		case TOK.TOKdo:
+		{   Statement body_;
+			Expression condition2;
+
+			nextToken();
+			body_ = parseStatement(ParseStatementFlags.PSscope);
+			check(TOK.TOKwhile);
+			check(TOK.TOKlparen);
+			condition2 = parseExpression();
+			check(TOK.TOKrparen);
+			s = new DoStatement(loc, body_, condition2);
+			break;
+		}
+
+		case TOK.TOKfor:
+		{
+			Statement init;
+			Expression condition2;
+			Expression increment;
+			Statement body_;
+
+			nextToken();
+			check(TOK.TOKlparen);
+			if (token.value == TOK.TOKsemicolon)
+			{	init = null;
+			nextToken();
+			}
+			else
+			{	init = parseStatement(cast(ParseStatementFlags)0);
+			}
+			if (token.value == TOK.TOKsemicolon)
+			{
+			condition2 = null;
+			nextToken();
+			}
+			else
+			{
+			condition2 = parseExpression();
+			check(TOK.TOKsemicolon, "for condition");
+			}
+			if (token.value == TOK.TOKrparen)
+			{	increment = null;
+			nextToken();
+			}
+			else
+			{	increment = parseExpression();
+			check(TOK.TOKrparen);
+			}
+			body_ = parseStatement(ParseStatementFlags.PSscope);
+			s = new ForStatement(loc, init, condition2, increment, body_);
+			if (init)
+			s = new ScopeStatement(loc, s);
+			break;
+		}
+
+		case TOK.TOKforeach:
+		case TOK.TOKforeach_reverse:
+		{
+			TOK op = token.value;
+			Arguments arguments;
+
+			Statement d;
+			Statement body_;
+			Expression aggr;
+
+			nextToken();
+			check(TOK.TOKlparen);
+
+			arguments = new Arguments();
+
+			while (1)
+			{
+			Type tb;
+			Identifier ai = null;
+			Type at;
+			STC storageClass = STC.STCundefined;
+			Argument a;
+
+			if (token.value == TOK.TOKinout || token.value == TOK.TOKref)
+			{   storageClass = STC.STCref;
+				nextToken();
+			}
+			if (token.value == TOK.TOKidentifier)
+			{
+				Token *tt = peek(&token);
+				if (tt.value == TOK.TOKcomma || tt.value == TOK.TOKsemicolon)
+				{	ai = token.ident;
+				at = null;		// infer argument type
+				nextToken();
+				goto Larg;
+				}
+			}
+			at = parseType(&ai);
+			if (!ai)
+				error("no identifier for declarator %s", at.toChars());
+			  Larg:
+			a = new Argument(storageClass, at, ai, null);
+			arguments.push(cast(void*)a);
+			if (token.value == TOK.TOKcomma)
+			{   nextToken();
+				continue;
+			}
+			break;
+			}
+			check(TOK.TOKsemicolon);
+
+			aggr = parseExpression();
+			if (token.value == TOK.TOKslice && arguments.dim == 1)
+			{
+			Argument a = cast(Argument)arguments.data[0];
+			delete arguments;
+			nextToken();
+			Expression upr = parseExpression();
+			check(TOK.TOKrparen);
+			body_ = parseStatement(cast(ParseStatementFlags)0);
+			s = new ForeachRangeStatement(loc, op, a, aggr, upr, body_);
+			}
+			else
+			{
+			check(TOK.TOKrparen);
+			body_ = parseStatement(cast(ParseStatementFlags)0);
+			s = new ForeachStatement(loc, op, arguments, aggr, body_);
+			}
+			break;
+		}
+
+		case TOK.TOKif:
+		{   Argument arg = null;
+			Expression condition2;
+			Statement ifbody2;
+			Statement elsebody2;
+
+			nextToken();
+			check(TOK.TOKlparen);
+
+			if (token.value == TOK.TOKauto)
+			{
+			nextToken();
+			if (token.value == TOK.TOKidentifier)
+			{
+				Token *tt = peek(&token);
+				if (tt.value == TOK.TOKassign)
+				{
+					arg = new Argument(STC.STCundefined, null, token.ident, null);
+					nextToken();
+					nextToken();
+				}
+				else
+				{   error("= expected following auto identifier");
+				goto Lerror;
+				}
+			}
+			else
+			{   error("identifier expected following auto");
+				goto Lerror;
+			}
+			}
+			else if (isDeclaration(&token, 2, TOK.TOKassign, null))
+			{
+			Type at;
+			Identifier ai;
+
+			at = parseType(&ai);
+			check(TOK.TOKassign);
+			arg = new Argument(STC.STCundefined, at, ai, null);
+			}
+
+			// Check for " ident;"
+			else if (token.value == TOK.TOKidentifier)
+			{
+			Token *tt = peek(&token);
+			if (tt.value == TOK.TOKcomma || tt.value == TOK.TOKsemicolon)
+			{
+				arg = new Argument(STC.STCundefined, null, token.ident, null);
+				nextToken();
+				nextToken();
+				if (1 || !global.params.useDeprecated)
+				error("if (v; e) is deprecated, use if (auto v = e)");
+			}
+			}
+
+			condition2 = parseExpression();
+			check(TOK.TOKrparen);
+			ifbody2 = parseStatement(ParseStatementFlags.PSscope);
+			if (token.value == TOK.TOKelse)
+			{
+			nextToken();
+			elsebody2 = parseStatement(ParseStatementFlags.PSscope);
+			}
+			else
+			elsebody2 = null;
+			s = new IfStatement(loc, arg, condition2, ifbody2, elsebody2);
+			break;
+		}
+
+		case TOK.TOKscope:
+			if (peek(&token).value != TOK.TOKlparen)
+			goto Ldeclaration;		// scope used as storage class
+			nextToken();
+			check(TOK.TOKlparen);
+			if (token.value != TOK.TOKidentifier)
+			{	error("scope identifier expected");
+			goto Lerror;
+			}
+			else
+			{	TOK tt = TOK.TOKon_scope_exit;
+			Identifier id = token.ident;
+
+			if (id == Id.exit)
+				tt = TOK.TOKon_scope_exit;
+			else if (id == Id.failure)
+				tt = TOK.TOKon_scope_failure;
+			else if (id == Id.success)
+				tt = TOK.TOKon_scope_success;
+			else
+				error("valid scope identifiers are exit, failure, or success, not %s", id.toChars());
+			nextToken();
+			check(TOK.TOKrparen);
+			Statement st = parseStatement(ParseStatementFlags.PScurlyscope);
+			s = new OnScopeStatement(loc, tt, st);
+			break;
+			}
+
+		case TOK.TOKdebug:
+			nextToken();
+			condition = parseDebugCondition();
+			goto Lcondition;
+
+		case TOK.TOKversion:
+			nextToken();
+			condition = parseVersionCondition();
+			goto Lcondition;
+
+		Lcondition:
+			ifbody = parseStatement(cast(ParseStatementFlags)0 /*ParseStatementFlags.PSsemi*/);
+			elsebody = null;
+			if (token.value == TOK.TOKelse)
+			{
+			nextToken();
+			elsebody = parseStatement(cast(ParseStatementFlags)0 /*ParseStatementFlags.PSsemi*/);
+			}
+			s = new ConditionalStatement(loc, condition, ifbody, elsebody);
+			break;
+
+		case TOK.TOKpragma:
+		{   Identifier ident;
+			Expressions args = null;
+			Statement body_;
+
+			nextToken();
+			check(TOK.TOKlparen);
+			if (token.value != TOK.TOKidentifier)
+			{   error("pragma(identifier expected");
+			goto Lerror;
+			}
+			ident = token.ident;
+			nextToken();
+			if (token.value == TOK.TOKcomma && peekNext() != TOK.TOKrparen)
+			args = parseArguments();	// pragma(identifier, args...);
+			else
+			check(TOK.TOKrparen);		// pragma(identifier);
+			if (token.value == TOK.TOKsemicolon)
+			{	nextToken();
+			body_ = null;
+			}
+			else
+			body_ = parseStatement(ParseStatementFlags.PSsemi);
+			s = new PragmaStatement(loc, ident, args, body_);
+			break;
+		}
+
+		case TOK.TOKswitch:
+			isfinal = false;
+			goto Lswitch;
+
+		Lswitch:
+		{
+			nextToken();
+			check(TOK.TOKlparen);
+			Expression condition2 = parseExpression();
+			check(TOK.TOKrparen);
+			Statement body_ = parseStatement(ParseStatementFlags.PSscope);
+			s = new SwitchStatement(loc, condition2, body_, isfinal);
+			break;
+		}
+
+		case TOK.TOKcase:
+		{   Expression exp;
+			Statements statements;
+			scope Array cases = new Array();	// array of Expression's
+			Expression last = null;
+
+			while (1)
+			{
+			nextToken();
+			exp = parseAssignExp();
+			cases.push(cast(void*)exp);
+			if (token.value != TOK.TOKcomma)
+				break;
+			}
+			check(TOK.TOKcolon);
+
+version (DMDV2) {
+			/* case exp: .. case last:
+			 */
+			if (token.value == TOK.TOKslice)
+			{
+			if (cases.dim > 1)
+				error("only one case allowed for start of case range");
+			nextToken();
+			check(TOK.TOKcase);
+			last = parseAssignExp();
+			check(TOK.TOKcolon);
+			}
+}
+
+			statements = new Statements();
+			while (token.value != TOK.TOKcase &&
+			   token.value != TOK.TOKdefault &&
+			   token.value != TOK.TOKrcurly)
+			{
+			statements.push(cast(void*)parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope));
+			}
+			s = new CompoundStatement(loc, statements);
+			s = new ScopeStatement(loc, s);
+
+///version (DMDV2) {
+			if (last)
+			{
+				s = new CaseRangeStatement(loc, exp, last, s);
+			}
+			else
+///}
+			{
+				// Keep cases in order by building the case statements backwards
+				for (int i = cases.dim; i; i--)
+				{
+					exp = cast(Expression)cases.data[i - 1];
+					s = new CaseStatement(loc, exp, s);
+				}
+			}
+			break;
+		}
+
+		case TOK.TOKdefault:
+		{
+			Statements statements;
+
+			nextToken();
+			check(TOK.TOKcolon);
+
+			statements = new Statements();
+			while (token.value != TOK.TOKcase &&
+			   token.value != TOK.TOKdefault &&
+			   token.value != TOK.TOKrcurly)
+			{
+			statements.push(cast(void*)parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope));
+			}
+			s = new CompoundStatement(loc, statements);
+			s = new ScopeStatement(loc, s);
+			s = new DefaultStatement(loc, s);
+			break;
+		}
+
+		case TOK.TOKreturn:
+		{   Expression exp;
+
+			nextToken();
+			if (token.value == TOK.TOKsemicolon)
+			exp = null;
+			else
+			exp = parseExpression();
+			check(TOK.TOKsemicolon, "return statement");
+			s = new ReturnStatement(loc, exp);
+			break;
+		}
+
+		case TOK.TOKbreak:
+		{   Identifier ident;
+
+			nextToken();
+			if (token.value == TOK.TOKidentifier)
+			{	ident = token.ident;
+			nextToken();
+			}
+			else
+			ident = null;
+			check(TOK.TOKsemicolon, "break statement");
+			s = new BreakStatement(loc, ident);
+			break;
+		}
+
+		case TOK.TOKcontinue:
+		{   Identifier ident;
+
+			nextToken();
+			if (token.value == TOK.TOKidentifier)
+			{	ident = token.ident;
+			nextToken();
+			}
+			else
+			ident = null;
+			check(TOK.TOKsemicolon, "continue statement");
+			s = new ContinueStatement(loc, ident);
+			break;
+		}
+
+		case TOK.TOKgoto:
+		{   Identifier ident;
+
+			nextToken();
+			if (token.value == TOK.TOKdefault)
+			{
+			nextToken();
+			s = new GotoDefaultStatement(loc);
+			}
+			else if (token.value == TOK.TOKcase)
+			{
+			Expression exp = null;
+
+			nextToken();
+			if (token.value != TOK.TOKsemicolon)
+				exp = parseExpression();
+			s = new GotoCaseStatement(loc, exp);
+			}
+			else
+			{
+			if (token.value != TOK.TOKidentifier)
+			{   error("Identifier expected following goto");
+				ident = null;
+			}
+			else
+			{   ident = token.ident;
+				nextToken();
+			}
+			s = new GotoStatement(loc, ident);
+			}
+			check(TOK.TOKsemicolon, "goto statement");
+			break;
+		}
+
+		case TOK.TOKsynchronized:
+		{   Expression exp;
+			Statement body_;
+
+			nextToken();
+			if (token.value == TOK.TOKlparen)
+			{
+			nextToken();
+			exp = parseExpression();
+			check(TOK.TOKrparen);
+			}
+			else
+			exp = null;
+			body_ = parseStatement(ParseStatementFlags.PSscope);
+			s = new SynchronizedStatement(loc, exp, body_);
+			break;
+		}
+
+		case TOK.TOKwith:
+		{   Expression exp;
+			Statement body_;
+
+			nextToken();
+			check(TOK.TOKlparen);
+			exp = parseExpression();
+			check(TOK.TOKrparen);
+			body_ = parseStatement(ParseStatementFlags.PSscope);
+			s = new WithStatement(loc, exp, body_);
+			break;
+		}
+
+		case TOK.TOKtry:
+		{   Statement body_;
+			Array catches = null;
+			Statement finalbody = null;
+
+			nextToken();
+			body_ = parseStatement(ParseStatementFlags.PSscope);
+			while (token.value == TOK.TOKcatch)
+			{
+				Statement handler;
+				Catch c;
+				Type tt;
+				Identifier id;
+				Loc loc2 = this.loc;
+
+				nextToken();
+				if (token.value == TOK.TOKlcurly)
+				{
+					tt = null;
+					id = null;
+				}
+				else
+				{
+					check(TOK.TOKlparen);
+					id = null;
+					tt = parseType(&id);
+					check(TOK.TOKrparen);
+				}
+				handler = parseStatement(cast(ParseStatementFlags)0);
+				c = new Catch(loc2, tt, id, handler);
+				if (!catches)
+					catches = new Array();
+				catches.push(cast(void*)c);
+			}
+
+			if (token.value == TOK.TOKfinally)
+			{	nextToken();
+			finalbody = parseStatement(cast(ParseStatementFlags)0);
+			}
+
+			s = body_;
+			if (!catches && !finalbody)
+			error("catch or finally expected following try");
+			else
+			{	if (catches)
+				s = new TryCatchStatement(loc, body_, catches);
+			if (finalbody)
+				s = new TryFinallyStatement(loc, s, finalbody);
+			}
+			break;
+		}
+
+		case TOK.TOKthrow:
+		{   Expression exp;
+
+			nextToken();
+			exp = parseExpression();
+			check(TOK.TOKsemicolon, "throw statement");
+			s = new ThrowStatement(loc, exp);
+			break;
+		}
+
+		case TOK.TOKvolatile:
+			nextToken();
+			s = parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope);
+version (DMDV2) {
+			if (!global.params.useDeprecated)
+				error("volatile statements deprecated; used synchronized statements instead");
+}
+			s = new VolatileStatement(loc, s);
+			break;
+
+		case TOK.TOKasm:
+		{   Statements statements;
+			Identifier label;
+			Loc labelloc;
+			Token* toklist;
+			Token** ptoklist;
+
+			// Parse the asm block into a sequence of AsmStatements,
+			// each AsmStatement is one instruction.
+			// Separate out labels.
+			// Defer parsing of AsmStatements until semantic processing.
+
+			nextToken();
+			check(TOK.TOKlcurly);
+			toklist = null;
+			ptoklist = &toklist;
+			label = null;
+			statements = new Statements();
+			while (1)
+			{
+			switch (token.value)
+			{
+				case TOK.TOKidentifier:
+				if (!toklist)
+				{
+					// Look ahead to see if it is a label
+					t = peek(&token);
+					if (t.value == TOK.TOKcolon)
+					{   // It's a label
+					label = token.ident;
+					labelloc = this.loc;
+					nextToken();
+					nextToken();
+					continue;
+					}
+				}
+				goto Ldefault;
+
+				case TOK.TOKrcurly:
+				if (toklist || label)
+				{
+					error("asm statements must end in ';'");
+				}
+				break;
+
+				case TOK.TOKsemicolon:
+				s = null;
+				if (toklist || label)
+				{   // Create AsmStatement from list of tokens we've saved
+					s = new AsmStatement(this.loc, toklist);
+					toklist = null;
+					ptoklist = &toklist;
+					if (label)
+					{   
+						s = new LabelStatement(labelloc, label, s);
+						label = null;
+					}
+					statements.push(cast(void*)s);
+				}
+				nextToken();
+				continue;
+
+				case TOK.TOKeof:
+				/* { */
+				error("matching '}' expected, not end of file");
+				break;
+
+				default:
+				Ldefault:
+				*ptoklist = new Token();
+				memcpy(*ptoklist, &token, Token.sizeof);
+				ptoklist = &(*ptoklist).next;
+				*ptoklist = null;
+
+				nextToken();
+				continue;
+			}
+			break;
+			}
+			s = new CompoundStatement(loc, statements);
+			nextToken();
+			break;
+		}
+
+		default:
+			error("found '%s' instead of statement", token.toChars());
+			goto Lerror;
+
+		Lerror:
+			while (token.value != TOK.TOKrcurly &&
+			   token.value != TOK.TOKsemicolon &&
+			   token.value != TOK.TOKeof)
+			nextToken();
+			if (token.value == TOK.TOKsemicolon)
+			nextToken();
+			s = null;
+			break;
+		}
+
+		return s;
+	}
+	
+	/*****************************************
+	 * Parse initializer for variable declaration.
+	 */
+    Initializer parseInitializer()
+	{
+		StructInitializer is_;
+		ArrayInitializer ia;
+		ExpInitializer ie;
+		Expression e;
+		Identifier id;
+		Initializer value;
+		int comma;
+		Loc loc = this.loc;
+		Token* t;
+		int braces;
+		int brackets;
+
+		switch (token.value)
+		{
+			case TOK.TOKlcurly:
+				/* Scan ahead to see if it is a struct initializer or
+				 * a function literal.
+				 * If it contains a ';', it is a function literal.
+				 * Treat { } as a struct initializer.
+				 */
+				braces = 1;
+				for (t = peek(&token); 1; t = peek(t))
+				{
+					switch (t.value)
+					{
+						case TOK.TOKsemicolon:
+						case TOK.TOKreturn:
+							goto Lexpression;
+
+						case TOK.TOKlcurly:
+							braces++;
+							continue;
+
+						case TOK.TOKrcurly:
+							if (--braces == 0)
+								break;
+							continue;
+
+						case TOK.TOKeof:
+							break;
+
+						default:
+							continue;
+					}
+					break;
+				}
+
+				is_ = new StructInitializer(loc);
+				nextToken();
+				comma = 0;
+				while (1)
+				{
+					switch (token.value)
+					{
+						case TOK.TOKidentifier:
+							if (comma == 1)
+								error("comma expected separating field initializers");
+							t = peek(&token);
+							if (t.value == TOK.TOKcolon)
+							{
+								id = token.ident;
+								nextToken();
+								nextToken();	// skip over ':'
+							}
+							else
+							{   
+								id = null;
+							}
+							value = parseInitializer();
+							is_.addInit(id, value);
+							comma = 1;
+							continue;
+
+						case TOK.TOKcomma:
+							nextToken();
+							comma = 2;
+							continue;
+
+						case TOK.TOKrcurly:		// allow trailing comma's
+							nextToken();
+							break;
+
+						case TOK.TOKeof:
+							error("found EOF instead of initializer");
+							break;
+
+						default:
+							value = parseInitializer();
+							is_.addInit(null, value);
+							comma = 1;
+							continue;
+							//error("found '%s' instead of field initializer", token.toChars());
+							//break;
+					}
+					break;
+				}
+				return is_;
+
+			case TOK.TOKlbracket:
+				/* Scan ahead to see if it is an array initializer or
+				 * an expression.
+				 * If it ends with a ';' ',' or '}', it is an array initializer.
+				 */
+				brackets = 1;
+				for (t = peek(&token); 1; t = peek(t))
+				{
+					switch (t.value)
+					{
+						case TOK.TOKlbracket:
+							brackets++;
+							continue;
+
+						case TOK.TOKrbracket:
+							if (--brackets == 0)
+							{   
+								t = peek(t);
+								if (t.value != TOK.TOKsemicolon &&
+									t.value != TOK.TOKcomma &&
+								t.value != TOK.TOKrcurly)
+								goto Lexpression;
+								break;
+							}
+							continue;
+
+						case TOK.TOKeof:
+							break;
+
+						default:
+							continue;
+					}
+					break;
+				}
+
+				ia = new ArrayInitializer(loc);
+				nextToken();
+				comma = 0;
+				while (true)
+				{
+					switch (token.value)
+					{
+						default:
+							if (comma == 1)
+							{   
+								error("comma expected separating array initializers, not %s", token.toChars());
+								nextToken();
+								break;
+							}
+							e = parseAssignExp();
+							if (!e)
+								break;
+							if (token.value == TOK.TOKcolon)
+							{
+								nextToken();
+								value = parseInitializer();
+							}
+							else
+							{   value = new ExpInitializer(e.loc, e);
+								e = null;
+							}
+							ia.addInit(e, value);
+							comma = 1;
+							continue;
+
+						case TOK.TOKlcurly:
+						case TOK.TOKlbracket:
+							if (comma == 1)
+								error("comma expected separating array initializers, not %s", token.toChars());
+							value = parseInitializer();
+							ia.addInit(null, value);
+							comma = 1;
+							continue;
+
+						case TOK.TOKcomma:
+							nextToken();
+							comma = 2;
+							continue;
+
+						case TOK.TOKrbracket:		// allow trailing comma's
+							nextToken();
+							break;
+
+						case TOK.TOKeof:
+							error("found '%s' instead of array initializer", token.toChars());
+							break;
+					}
+					break;
+				}
+				return ia;
+
+			case TOK.TOKvoid:
+				t = peek(&token);
+				if (t.value == TOK.TOKsemicolon || t.value == TOK.TOKcomma)
+				{
+					nextToken();
+					return new VoidInitializer(loc);
+				}
+				goto Lexpression;
+
+			default:
+			Lexpression:
+				e = parseAssignExp();
+				ie = new ExpInitializer(loc, e);
+				return ie;
+		}
+	}
+	
+	/*****************************************
+	 * Parses default argument initializer expression that is an assign expression,
+	 * with special handling for __FILE__ and __LINE__.
+	 */
+version (DMDV2) {
+    Expression parseDefaultInitExp()
+	{
+		if (token.value == TOK.TOKfile ||
+			token.value == TOK.TOKline)
+		{
+			Token* t = peek(&token);
+			if (t.value == TOK.TOKcomma || t.value == TOK.TOKrparen)
+			{   
+				Expression e;
+
+				if (token.value == TOK.TOKfile)
+					e = new FileInitExp(loc);
+				else
+					e = new LineInitExp(loc);
+				nextToken();
+				return e;
+			}
+		}
+
+		Expression e = parseAssignExp();
+		return e;
+	}
+}
+    void check(Loc loc, TOK value)
+	{
+		if (token.value != value)
+			error(loc, "found '%s' when expecting '%s'", token.toChars(), Token.toChars(value));
+		nextToken();
+	}
+	
+    void check(TOK value)
+	{
+		check(loc, value);
+	}
+	
+    void check(TOK value, string string_)
+	{
+		if (token.value != value) {
+			error("found '%s' when expecting '%s' following '%s'", token.toChars(), Token.toChars(value), string_);
+		}
+		nextToken();
+	}
+	
+	/************************************
+	 * Determine if the scanner is sitting on the start of a declaration.
+	 * Input:
+	 *	needId	0	no identifier
+	 *		1	identifier optional
+	 *		2	must have identifier
+	 * Output:
+	 *	if *pt is not null, it is set to the ending token, which would be endtok
+	 */
+
+    bool isDeclaration(Token* t, int needId, TOK endtok, Token** pt)
+	{
+		//printf("isDeclaration(needId = %d)\n", needId);
+		int haveId = 0;
+
+version (DMDV2) {
+		if ((t.value == TOK.TOKconst ||
+			t.value == TOK.TOKinvariant ||
+			t.value == TOK.TOKimmutable ||
+			t.value == TOK.TOKshared) &&
+			peek(t).value != TOK.TOKlparen)
+		{
+			/* const type
+			* immutable type
+			* shared type
+			*/
+			t = peek(t);
+		}
+}
+
+		if (!isBasicType(&t))
+		{
+			goto Lisnot;
+		}
+		if (!isDeclarator(&t, &haveId, endtok))
+			goto Lisnot;
+		if ( needId == 1 ||
+			(needId == 0 && !haveId) ||
+			(needId == 2 &&  haveId))
+		{	
+			if (pt)
+				*pt = t;
+			goto Lis;
+		}
+		else
+			goto Lisnot;
+
+	Lis:
+		//printf("\tis declaration, t = %s\n", t.toChars());
+		return true;
+
+	Lisnot:
+		//printf("\tis not declaration\n");
+		return false;
+	}
+	
+    bool isBasicType(Token** pt)
+	{
+		// This code parallels parseBasicType()
+		Token* t = *pt;
+		Token* t2;
+		int parens;
+		int haveId = 0;
+
+		switch (t.value)
+		{
+		case TOKwchar:
+		case TOKdchar:
+		case TOKbit:
+		case TOKbool:
+		case TOKchar:
+		case TOKint8:
+		case TOKuns8:
+		case TOKint16:
+		case TOKuns16:
+		case TOKint32:
+		case TOKuns32:
+		case TOKint64:
+		case TOKuns64:
+		case TOKfloat32:
+		case TOKfloat64:
+		case TOKfloat80:
+		case TOKimaginary32:
+		case TOKimaginary64:
+		case TOKimaginary80:
+		case TOKcomplex32:
+		case TOKcomplex64:
+		case TOKcomplex80:
+		case TOKvoid:
+			t = peek(t);
+			break;
+
+		case TOK.TOKidentifier:
+		L5:
+			t = peek(t);
+			if (t.value == TOK.TOKnot)
+			{
+			goto L4;
+			}
+			goto L3;
+			while (1)
+			{
+		L2:
+			t = peek(t);
+		L3:
+			if (t.value == TOK.TOKdot)
+			{
+		Ldot:
+				t = peek(t);
+				if (t.value != TOK.TOKidentifier)
+				goto Lfalse;
+				t = peek(t);
+				if (t.value != TOK.TOKnot)
+				goto L3;
+		L4:
+				/* Seen a !
+				 * Look for:
+				 * !( args ), !identifier, etc.
+				 */
+				t = peek(t);
+				switch (t.value)
+				{	case TOK.TOKidentifier:
+					goto L5;
+				case TOK.TOKlparen:
+					if (!skipParens(t, &t))
+					goto Lfalse;
+					break;
+				case TOK.TOKwchar: case TOK.TOKdchar:
+				case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar:
+				case TOK.TOKint8: case TOK.TOKuns8:
+				case TOK.TOKint16: case TOK.TOKuns16:
+				case TOK.TOKint32: case TOK.TOKuns32:
+				case TOK.TOKint64: case TOK.TOKuns64:
+				case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80:
+				case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80:
+				case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80:
+				case TOK.TOKvoid:
+				case TOK.TOKint32v:
+				case TOK.TOKuns32v:
+				case TOK.TOKint64v:
+				case TOK.TOKuns64v:
+				case TOK.TOKfloat32v:
+				case TOK.TOKfloat64v:
+				case TOK.TOKfloat80v:
+				case TOK.TOKimaginary32v:
+				case TOK.TOKimaginary64v:
+				case TOK.TOKimaginary80v:
+				case TOK.TOKnull:
+				case TOK.TOKtrue:
+				case TOK.TOKfalse:
+				case TOK.TOKcharv:
+				case TOK.TOKwcharv:
+				case TOK.TOKdcharv:
+				case TOK.TOKstring:
+				case TOK.TOKfile:
+				case TOK.TOKline:
+					goto L2;
+				default:
+					goto Lfalse;
+				}
+			}
+			else
+				break;
+			}
+			break;
+
+		case TOK.TOKdot:
+			goto Ldot;
+
+		case TOK.TOKtypeof:
+			/* typeof(exp).identifier...
+			 */
+			t = peek(t);
+			if (t.value != TOK.TOKlparen)
+			goto Lfalse;
+			if (!skipParens(t, &t))
+			goto Lfalse;
+			goto L2;
+
+		case TOK.TOKconst:
+		case TOK.TOKinvariant:
+		case TOK.TOKimmutable:
+		case TOK.TOKshared:
+			// const(type)  or  immutable(type)  or  shared(type)
+			t = peek(t);
+			if (t.value != TOK.TOKlparen)
+			goto Lfalse;
+			t = peek(t);
+			if (!isDeclaration(t, 0, TOK.TOKrparen, &t))
+			{
+			goto Lfalse;
+			}
+			t = peek(t);
+			break;
+
+		default:
+			goto Lfalse;
+		}
+		*pt = t;
+		//printf("is\n");
+		return true;
+
+	Lfalse:
+		//printf("is not\n");
+		return false;
+	}
+	
+    bool isDeclarator(Token** pt, int* haveId, TOK endtok)
+	{
+		// This code parallels parseDeclarator()
+		Token* t = *pt;
+		bool parens;
+
+		//printf("Parser.isDeclarator()\n");
+		//t.print();
+		if (t.value == TOK.TOKassign)
+			return false;
+
+		while (true)
+		{
+			parens = false;
+			switch (t.value)
+			{
+				case TOK.TOKmul:
+				//case TOKand:
+					t = peek(t);
+					continue;
+
+				case TOK.TOKlbracket:
+					t = peek(t);
+					if (t.value == TOK.TOKrbracket)
+					{
+						t = peek(t);
+					}
+					else if (isDeclaration(t, 0, TOK.TOKrbracket, &t))
+					{   
+						// It's an associative array declaration
+						t = peek(t);
+					}
+					else
+					{
+						// [ expression ]
+						// [ expression .. expression ]
+						if (!isExpression(&t))
+							return false;
+						if (t.value == TOK.TOKslice)
+						{	
+							t = peek(t);
+							if (!isExpression(&t))
+								return false;
+						}
+						if (t.value != TOK.TOKrbracket)
+							return false;
+						t = peek(t);
+					}
+					continue;
+
+				case TOK.TOKidentifier:
+					if (*haveId)
+						return false;
+					*haveId = true;
+					t = peek(t);
+					break;
+
+				case TOK.TOKlparen:
+					t = peek(t);
+
+					if (t.value == TOK.TOKrparen)
+						return false;		// () is not a declarator
+
+					/* Regard ( identifier ) as not a declarator
+					 * BUG: what about ( *identifier ) in
+					 *	f(*p)(x);
+					 * where f is a class instance with overloaded () ?
+					 * Should we just disallow C-style function pointer declarations?
+					 */
+					if (t.value == TOK.TOKidentifier)
+					{   
+						Token *t2 = peek(t);
+						if (t2.value == TOK.TOKrparen)
+							return false;
+					}
+
+					if (!isDeclarator(&t, haveId, TOK.TOKrparen))
+						return false;
+					t = peek(t);
+					parens = true;
+					break;
+
+				case TOK.TOKdelegate:
+				case TOK.TOKfunction:
+					t = peek(t);
+					if (!isParameters(&t))
+						return false;
+					continue;
+				default:
+					break;	///
+			}
+			break;
+		}
+
+		while (1)
+		{
+			switch (t.value)
+			{
+version (CARRAYDECL) {
+				case TOK.TOKlbracket:
+					parens = false;
+					t = peek(t);
+					if (t.value == TOK.TOKrbracket)
+					{
+						t = peek(t);
+					}
+					else if (isDeclaration(t, 0, TOKrbracket, &t))
+					{   
+						// It's an associative array declaration
+						t = peek(t);
+					}
+					else
+					{
+						// [ expression ]
+						if (!isExpression(&t))
+							return false;
+						if (t.value != TOK.TOKrbracket)
+							return false;
+						t = peek(t);
+					}
+					continue;
+}
+
+				case TOK.TOKlparen:
+					parens = false;
+					if (!isParameters(&t))
+						return false;
+version (DMDV2) {
+					while (true)
+					{
+						switch (t.value)
+						{
+							case TOK.TOKconst:
+							case TOK.TOKinvariant:
+							case TOK.TOKimmutable:
+							case TOK.TOKshared:
+							case TOK.TOKpure:
+							case TOK.TOKnothrow:
+								t = peek(t);
+								continue;
+							case TOK.TOKat:
+								t = peek(t);	// skip '@'
+								t = peek(t);	// skip identifier
+								continue;
+							default:
+								break;
+						}
+						break;
+					}
+}
+					continue;
+
+				// Valid tokens that follow a declaration
+				case TOK.TOKrparen:
+				case TOK.TOKrbracket:
+				case TOK.TOKassign:
+				case TOK.TOKcomma:
+				case TOK.TOKsemicolon:
+				case TOK.TOKlcurly:
+				case TOK.TOKin:
+					// The !parens is to disallow unnecessary parentheses
+					if (!parens && (endtok == TOK.TOKreserved || endtok == t.value))
+					{   
+						*pt = t;
+						return true;
+					}
+					return false;
+
+				default:
+					return false;
+			}
+		}
+	}
+	
+    bool isParameters(Token** pt)
+	{
+		// This code parallels parseParameters()
+		Token* t = *pt;
+
+		//printf("isParameters()\n");
+		if (t.value != TOKlparen)
+			return false;
+
+		t = peek(t);
+		for (;1; t = peek(t))
+		{
+			 L1:
+			switch (t.value)
+			{
+				case TOKrparen:
+					break;
+
+				case TOKdotdotdot:
+					t = peek(t);
+					break;
+
+				case TOKin:
+				case TOKout:
+				case TOKinout:
+				case TOKref:
+				case TOKlazy:
+				case TOKfinal:
+					continue;
+
+				case TOKconst:
+				case TOKinvariant:
+				case TOKimmutable:
+				case TOKshared:
+					t = peek(t);
+					if (t.value == TOKlparen)
+					{
+						t = peek(t);
+						if (!isDeclaration(t, 0, TOKrparen, &t))
+						return false;
+						t = peek(t);	// skip past closing ')'
+						goto L2;
+					}
+					goto L1;
+
+		static if (false) {
+				case TOKstatic:
+					continue;
+				case TOKauto:
+				case TOKalias:
+					t = peek(t);
+					if (t.value == TOKidentifier)
+						t = peek(t);
+					if (t.value == TOKassign)
+					{   t = peek(t);
+						if (!isExpression(&t))
+						return false;
+					}
+					goto L3;
+		}
+
+				default:
+				{	
+					if (!isBasicType(&t))
+						return false;
+					L2:
+					int tmp = false;
+					if (t.value != TOKdotdotdot &&
+						!isDeclarator(&t, &tmp, TOKreserved))
+						return false;
+					if (t.value == TOKassign)
+					{
+						t = peek(t);
+						if (!isExpression(&t))
+							return false;
+					}
+					if (t.value == TOKdotdotdot)
+					{
+						t = peek(t);
+						break;
+					}
+				}
+				L3:
+				if (t.value == TOKcomma)
+				{
+					continue;
+				}
+				break;
+			}
+			break;
+		}
+
+		if (t.value != TOKrparen)
+			return false;
+
+		t = peek(t);
+		*pt = t;
+		return true;
+	}
+	
+    bool isExpression(Token** pt)
+	{
+		// This is supposed to determine if something is an expression.
+		// What it actually does is scan until a closing right bracket
+		// is found.
+
+		Token* t = *pt;
+		int brnest = 0;
+		int panest = 0;
+		int curlynest = 0;
+
+		for (;; t = peek(t))
+		{
+			switch (t.value)
+			{
+				case TOKlbracket:
+					brnest++;
+					continue;
+
+				case TOKrbracket:
+					if (--brnest >= 0)
+						continue;
+					break;
+
+				case TOKlparen:
+					panest++;
+					continue;
+
+				case TOKcomma:
+					if (brnest || panest)
+						continue;
+					break;
+
+				case TOKrparen:
+					if (--panest >= 0)
+						continue;
+					break;
+
+				case TOKlcurly:
+					curlynest++;
+					continue;
+
+				case TOKrcurly:
+					if (--curlynest >= 0)
+						continue;
+					return false;
+
+				case TOKslice:
+					if (brnest)
+						continue;
+					break;
+
+				case TOKsemicolon:
+					if (curlynest)
+						continue;
+					return false;
+
+				case TOKeof:
+					return false;
+
+				default:
+					continue;
+			}
+			break;
+		}
+
+		*pt = t;
+		return true;
+	}
+	
+    int isTemplateInstance(Token t, Token* pt)
+	{
+		assert(false);
+	}
+	
+	/*******************************************
+	 * Skip parens, brackets.
+	 * Input:
+	 *	t is on opening (
+	 * Output:
+	 *	*pt is set to closing token, which is ')' on success
+	 * Returns:
+	 *	!=0	successful
+	 *	0	some parsing error
+	 */
+    bool skipParens(Token* t, Token** pt)
+	{
+		int parens = 0;
+
+		while (1)
+		{
+			switch (t.value)
+			{
+				case TOKlparen:
+					parens++;
+					break;
+
+				case TOKrparen:
+					parens--;
+					if (parens < 0)
+						goto Lfalse;
+					if (parens == 0)
+						goto Ldone;
+					break;
+
+				case TOKeof:
+				case TOKsemicolon:
+					goto Lfalse;
+
+				default:
+					break;
+			}
+			t = peek(t);
+		}
+
+	  Ldone:
+		if (*pt)
+			*pt = t;
+		return true;
+
+	  Lfalse:
+		return false;
+	}
+
+    Expression parseExpression()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		//printf("Parser.parseExpression() loc = %d\n", loc.linnum);
+		e = parseAssignExp();
+		while (token.value == TOK.TOKcomma)
+		{
+			nextToken();
+			e2 = parseAssignExp();
+			e = new CommaExp(loc, e, e2);
+			loc = this.loc;
+		}
+		return e;
+	}
+	
+    Expression parsePrimaryExp()
+	{
+		Expression e;
+		Type t;
+		Identifier id;
+		TOK save;
+		Loc loc = this.loc;
+
+		//printf("parsePrimaryExp(): loc = %d\n", loc.linnum);
+		switch (token.value)
+		{
+		case TOK.TOKidentifier:
+			id = token.ident;
+			nextToken();
+			if (token.value == TOK.TOKnot && peekNext() != TOK.TOKis)
+			{	// identifier!(template-argument-list)
+			TemplateInstance tempinst;
+
+			tempinst = new TemplateInstance(loc, id);
+			nextToken();
+			if (token.value == TOK.TOKlparen)
+				// ident!(template_arguments)
+				tempinst.tiargs = parseTemplateArgumentList();
+			else
+				// ident!template_argument
+				tempinst.tiargs = parseTemplateArgument();
+			e = new ScopeExp(loc, tempinst);
+			}
+			else
+			e = new IdentifierExp(loc, id);
+			break;
+
+		case TOK.TOKdollar:
+			if (!inBrackets)
+			error("'$' is valid only inside [] of index or slice");
+			e = new DollarExp(loc);
+			nextToken();
+			break;
+
+		case TOK.TOKdot:
+			// Signal global scope '.' operator with "" identifier
+			e = new IdentifierExp(loc, Id.empty);
+			break;
+
+		case TOK.TOKthis:
+			e = new ThisExp(loc);
+			nextToken();
+			break;
+
+		case TOK.TOKsuper:
+			e = new SuperExp(loc);
+			nextToken();
+			break;
+
+		case TOK.TOKint32v:
+			e = new IntegerExp(loc, token.int32value, Type.tint32);
+			nextToken();
+			break;
+
+		case TOK.TOKuns32v:
+			e = new IntegerExp(loc, token.uns32value, Type.tuns32);
+			nextToken();
+			break;
+
+		case TOK.TOKint64v:
+			e = new IntegerExp(loc, token.int64value, Type.tint64);
+			nextToken();
+			break;
+
+		case TOK.TOKuns64v:
+			e = new IntegerExp(loc, token.uns64value, Type.tuns64);
+			nextToken();
+			break;
+
+		case TOK.TOKfloat32v:
+			e = new RealExp(loc, token.float80value, Type.tfloat32);
+			nextToken();
+			break;
+
+		case TOK.TOKfloat64v:
+			e = new RealExp(loc, token.float80value, Type.tfloat64);
+			nextToken();
+			break;
+
+		case TOK.TOKfloat80v:
+			e = new RealExp(loc, token.float80value, Type.tfloat80);
+			nextToken();
+			break;
+
+		case TOK.TOKimaginary32v:
+			e = new RealExp(loc, token.float80value, Type.timaginary32);
+			nextToken();
+			break;
+
+		case TOK.TOKimaginary64v:
+			e = new RealExp(loc, token.float80value, Type.timaginary64);
+			nextToken();
+			break;
+
+		case TOK.TOKimaginary80v:
+			e = new RealExp(loc, token.float80value, Type.timaginary80);
+			nextToken();
+			break;
+
+		case TOK.TOKnull:
+			e = new NullExp(loc);
+			nextToken();
+			break;
+
+version (DMDV2) {
+		case TOK.TOKfile:
+		{
+			string s = loc.filename ? loc.filename : mod.ident.toChars();
+			e = new StringExp(loc, s, 0);
+			nextToken();
+			break;
+		}
+
+		case TOK.TOKline:
+			e = new IntegerExp(loc, loc.linnum, Type.tint32);
+			nextToken();
+			break;
+}
+
+		case TOK.TOKtrue:
+			e = new IntegerExp(loc, 1, Type.tbool);
+			nextToken();
+			break;
+
+		case TOK.TOKfalse:
+			e = new IntegerExp(loc, 0, Type.tbool);
+			nextToken();
+			break;
+
+		case TOK.TOKcharv:
+			e = new IntegerExp(loc, token.uns32value, Type.tchar);
+			nextToken();
+			break;
+
+		case TOK.TOKwcharv:
+			e = new IntegerExp(loc, token.uns32value, Type.twchar);
+			nextToken();
+			break;
+
+		case TOK.TOKdcharv:
+			e = new IntegerExp(loc, token.uns32value, Type.tdchar);
+			nextToken();
+			break;
+
+		case TOK.TOKstring:
+		{  
+			const(char)* s;
+			uint len;
+			ubyte postfix;
+
+			// cat adjacent strings
+			s = token.ustring;
+			len = token.len;
+			postfix = token.postfix;
+			while (1)
+			{
+				nextToken();
+				if (token.value == TOK.TOKstring)
+				{   uint len1;
+					uint len2;
+					char* s2;
+
+					if (token.postfix)
+					{	if (token.postfix != postfix)
+						error("mismatched string literal postfixes '%c' and '%c'", postfix, token.postfix);
+					postfix = token.postfix;
+					}
+
+					len1 = len;
+					len2 = token.len;
+					len = len1 + len2;
+					s2 = cast(char*)malloc((len + 1) * ubyte.sizeof);
+					memcpy(s2, s, len1 * ubyte.sizeof);
+					memcpy(s2 + len1, token.ustring, (len2 + 1) * ubyte.sizeof);
+					s = s2;
+				}
+				else
+					break;
+			}
+			e = new StringExp(loc, assumeUnique(s[0..len]), postfix);
+			break;
+		}
+
+		case TOK.TOKvoid:	 t = Type.tvoid;  goto LabelX;
+		case TOK.TOKint8:	 t = Type.tint8;  goto LabelX;
+		case TOK.TOKuns8:	 t = Type.tuns8;  goto LabelX;
+		case TOK.TOKint16:	 t = Type.tint16; goto LabelX;
+		case TOK.TOKuns16:	 t = Type.tuns16; goto LabelX;
+		case TOK.TOKint32:	 t = Type.tint32; goto LabelX;
+		case TOK.TOKuns32:	 t = Type.tuns32; goto LabelX;
+		case TOK.TOKint64:	 t = Type.tint64; goto LabelX;
+		case TOK.TOKuns64:	 t = Type.tuns64; goto LabelX;
+		case TOK.TOKfloat32: t = Type.tfloat32; goto LabelX;
+		case TOK.TOKfloat64: t = Type.tfloat64; goto LabelX;
+		case TOK.TOKfloat80: t = Type.tfloat80; goto LabelX;
+		case TOK.TOKimaginary32: t = Type.timaginary32; goto LabelX;
+		case TOK.TOKimaginary64: t = Type.timaginary64; goto LabelX;
+		case TOK.TOKimaginary80: t = Type.timaginary80; goto LabelX;
+		case TOK.TOKcomplex32: t = Type.tcomplex32; goto LabelX;
+		case TOK.TOKcomplex64: t = Type.tcomplex64; goto LabelX;
+		case TOK.TOKcomplex80: t = Type.tcomplex80; goto LabelX;
+		case TOK.TOKbit:	 t = Type.tbit;     goto LabelX;
+		case TOK.TOKbool:	 t = Type.tbool;    goto LabelX;
+		case TOK.TOKchar:	 t = Type.tchar;    goto LabelX;
+		case TOK.TOKwchar:	 t = Type.twchar; goto LabelX;
+		case TOK.TOKdchar:	 t = Type.tdchar; goto LabelX;
+		LabelX:
+			nextToken();
+		L1:
+			check(TOK.TOKdot, t.toChars());
+			if (token.value != TOK.TOKidentifier)
+			{   error("found '%s' when expecting identifier following '%s.'", token.toChars(), t.toChars());
+			goto Lerr;
+			}
+			e = typeDotIdExp(loc, t, token.ident);
+			nextToken();
+			break;
+
+		case TOK.TOKtypeof:
+		{
+			t = parseTypeof();
+			e = new TypeExp(loc, t);
+			break;
+		}
+
+		case TOK.TOKtypeid:
+		{   Type tt;
+
+			nextToken();
+			check(TOK.TOKlparen, "typeid");
+			tt = parseType();		// ( type )
+			check(TOK.TOKrparen);
+			e = new TypeidExp(loc, tt);
+			break;
+		}
+
+version (DMDV2) {
+		case TOK.TOKtraits:
+		{   /* __traits(identifier, args...)
+			 */
+			Identifier ident;
+			Objects args = null;
+
+			nextToken();
+			check(TOK.TOKlparen);
+			if (token.value != TOK.TOKidentifier)
+			{   error("__traits(identifier, args...) expected");
+			goto Lerr;
+			}
+			ident = token.ident;
+			nextToken();
+			if (token.value == TOK.TOKcomma)
+			args = parseTemplateArgumentList2();	// __traits(identifier, args...)
+			else
+			check(TOK.TOKrparen);		// __traits(identifier)
+
+			e = new TraitsExp(loc, ident, args);
+			break;
+		}
+}
+
+		case TOK.TOKis:
+		{   Type targ;
+			Identifier ident = null;
+			Type tspec = null;
+			TOK tok = TOK.TOKreserved;
+			TOK tok2 = TOK.TOKreserved;
+			TemplateParameters tpl = null;
+			Loc loc2 = this.loc;
+
+			nextToken();
+			if (token.value == TOK.TOKlparen)
+			{
+				nextToken();
+				targ = parseType(&ident);
+				if (token.value == TOK.TOKcolon || token.value == TOK.TOKequal)
+				{
+					tok = token.value;
+					nextToken();
+					if (tok == TOK.TOKequal &&
+					(token.value == TOK.TOKtypedef ||
+					 token.value == TOK.TOKstruct ||
+					 token.value == TOK.TOKunion ||
+					 token.value == TOK.TOKclass ||
+					 token.value == TOK.TOKsuper ||
+					 token.value == TOK.TOKenum ||
+					 token.value == TOK.TOKinterface ||
+	///version (DMDV2) {
+					 token.value == TOK.TOKconst && peek(&token).value == TOK.TOKrparen ||
+					 token.value == TOK.TOKinvariant && peek(&token).value == TOK.TOKrparen ||
+					 token.value == TOK.TOKimmutable && peek(&token).value == TOK.TOKrparen ||
+					 token.value == TOK.TOKshared && peek(&token).value == TOK.TOKrparen ||
+	///}
+					 token.value == TOK.TOKfunction ||
+					 token.value == TOK.TOKdelegate ||
+					 token.value == TOK.TOKreturn))
+					{
+					tok2 = token.value;
+					nextToken();
+					}
+					else
+					{
+					tspec = parseType();
+					}
+				}
+				if (ident && tspec)
+				{
+					if (token.value == TOK.TOKcomma)
+					tpl = parseTemplateParameterList(1);
+					else
+					{	tpl = new TemplateParameters();
+					check(TOK.TOKrparen);
+					}
+					TemplateParameter tp = new TemplateTypeParameter(loc2, ident, null, null);
+					tpl.insert(0, cast(void*)tp);
+				}
+				else
+					check(TOK.TOKrparen);
+			}
+			else
+			{   error("(type identifier : specialization) expected following is");
+			goto Lerr;
+			}
+			e = new IsExp(loc2, targ, ident, tok, tspec, tok2, tpl);
+			break;
+		}
+
+		case TOK.TOKassert:
+		{   
+			Expression msg = null;
+
+			nextToken();
+			check(TOK.TOKlparen, "assert");
+			e = parseAssignExp();
+			if (token.value == TOK.TOKcomma)
+			{	nextToken();
+			msg = parseAssignExp();
+			}
+			check(TOK.TOKrparen);
+			e = new AssertExp(loc, e, msg);
+			break;
+		}
+
+		case TOK.TOKmixin:
+		{
+			nextToken();
+			check(TOK.TOKlparen, "mixin");
+			e = parseAssignExp();
+			check(TOK.TOKrparen);
+			e = new CompileExp(loc, e);
+			break;
+		}
+
+		case TOK.TOKimport:
+		{
+			nextToken();
+			check(TOK.TOKlparen, "import");
+			e = parseAssignExp();
+			check(TOK.TOKrparen);
+			e = new FileExp(loc, e);
+			break;
+		}
+
+		case TOK.TOKlparen:
+			if (peekPastParen(&token).value == TOK.TOKlcurly)
+			{	// (arguments) { statements... }
+			save = TOK.TOKdelegate;
+			goto case_delegate;
+			}
+			// ( expression )
+			nextToken();
+			e = parseExpression();
+			check(loc, TOK.TOKrparen);
+			break;
+
+		case TOK.TOKlbracket:
+		{   /* Parse array literals and associative array literals:
+			 *	[ value, value, value ... ]
+			 *	[ key:value, key:value, key:value ... ]
+			 */
+			Expressions values = new Expressions();
+			Expressions keys = null;
+
+			nextToken();
+			if (token.value != TOK.TOKrbracket)
+			{
+			while (token.value != TOK.TOKeof)
+			{
+				Expression e2 = parseAssignExp();
+				if (token.value == TOK.TOKcolon && (keys || values.dim == 0))
+				{	
+					nextToken();
+					if (!keys)
+						keys = new Expressions();
+					keys.push(cast(void*)e2);
+					e2 = parseAssignExp();
+				}
+				else if (keys)
+				{	
+					error("'key:value' expected for associative array literal");
+					delete keys;
+					keys = null;
+				}
+				values.push(cast(void*)e2);
+				if (token.value == TOK.TOKrbracket)
+					break;
+				check(TOK.TOKcomma);
+			}
+			}
+			check(TOK.TOKrbracket);
+
+			if (keys)
+				e = new AssocArrayLiteralExp(loc, keys, values);
+			else
+				e = new ArrayLiteralExp(loc, values);
+			break;
+		}
+
+		case TOK.TOKlcurly:
+			// { statements... }
+			save = TOK.TOKdelegate;
+			goto case_delegate;
+
+		case TOK.TOKfunction:
+		case TOK.TOKdelegate:
+			save = token.value;
+			nextToken();
+		case_delegate:
+		{
+			/* function type(parameters) { body } pure nothrow
+			 * delegate type(parameters) { body } pure nothrow
+			 * (parameters) { body }
+			 * { body }
+			 */
+			Arguments arguments;
+			int varargs;
+			FuncLiteralDeclaration fd;
+			Type tt;
+			bool isnothrow = false;
+			bool ispure = false;
+
+			if (token.value == TOK.TOKlcurly)
+			{
+			tt = null;
+			varargs = 0;
+			arguments = new Arguments();
+			}
+			else
+			{
+			if (token.value == TOK.TOKlparen)
+				tt = null;
+			else
+			{
+				tt = parseBasicType();
+				tt = parseBasicType2(tt);	// function return type
+			}
+			arguments = parseParameters(&varargs);
+			while (1)
+			{
+				if (token.value == TOK.TOKpure)
+				ispure = true;
+				else if (token.value == TOK.TOKnothrow)
+				isnothrow = true;
+				else
+				break;
+				nextToken();
+			}
+			}
+
+			TypeFunction tf = new TypeFunction(arguments, tt, varargs, linkage);
+			tf.ispure = ispure;
+			tf.isnothrow = isnothrow;
+			fd = new FuncLiteralDeclaration(loc, Loc(0), tf, save, null);
+			parseContracts(fd);
+			e = new FuncExp(loc, fd);
+			break;
+		}
+
+		default:
+			error("expression expected, not '%s'", token.toChars());
+		Lerr:
+			// Anything for e, as long as it's not null
+			e = new IntegerExp(loc, 0, Type.tint32);
+			nextToken();
+			break;
+		}
+		return e;
+	}
+	
+    Expression parseUnaryExp()
+	{
+		Expression e;
+		Loc loc = this.loc;
+
+		switch (token.value)
+		{
+		case TOK.TOKand:
+			nextToken();
+			e = parseUnaryExp();
+			e = new AddrExp(loc, e);
+			break;
+
+		case TOK.TOKplusplus:
+			nextToken();
+			e = parseUnaryExp();
+			e = new AddAssignExp(loc, e, new IntegerExp(loc, 1, Type.tint32));
+			break;
+
+		case TOK.TOKminusminus:
+			nextToken();
+			e = parseUnaryExp();
+			e = new MinAssignExp(loc, e, new IntegerExp(loc, 1, Type.tint32));
+			break;
+
+		case TOK.TOKmul:
+			nextToken();
+			e = parseUnaryExp();
+			e = new PtrExp(loc, e);
+			break;
+
+		case TOK.TOKmin:
+			nextToken();
+			e = parseUnaryExp();
+			e = new NegExp(loc, e);
+			break;
+
+		case TOK.TOKadd:
+			nextToken();
+			e = parseUnaryExp();
+			e = new UAddExp(loc, e);
+			break;
+
+		case TOK.TOKnot:
+			nextToken();
+			e = parseUnaryExp();
+			e = new NotExp(loc, e);
+			break;
+
+		case TOK.TOKtilde:
+			nextToken();
+			e = parseUnaryExp();
+			e = new ComExp(loc, e);
+			break;
+
+		case TOK.TOKdelete:
+			nextToken();
+			e = parseUnaryExp();
+			e = new DeleteExp(loc, e);
+			break;
+
+		case TOK.TOKnew:
+			e = parseNewExp(null);
+			break;
+
+		case TOK.TOKcast:				// cast(type) expression
+		{
+			nextToken();
+			check(TOK.TOKlparen);
+			/* Look for cast(), cast(const), cast(immutable),
+			 * cast(shared), cast(shared const)
+			 */
+			MOD m;
+			if (token.value == TOK.TOKrparen)
+			{
+			m = MOD.MODundefined;
+			goto Lmod1;
+			}
+			else if (token.value == TOK.TOKconst && peekNext() == TOK.TOKrparen)
+			{
+			m = MOD.MODconst;
+			goto Lmod2;
+			}
+			else if ((token.value == TOK.TOKimmutable || token.value == TOK.TOKinvariant) && peekNext() == TOK.TOKrparen)
+			{
+			m = MOD.MODinvariant;
+			goto Lmod2;
+			}
+			else if (token.value == TOK.TOKshared && peekNext() == TOK.TOKrparen)
+			{
+			m = MOD.MODshared;
+			goto Lmod2;
+			}
+			else if (token.value == TOK.TOKconst && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen ||
+				 token.value == TOK.TOKshared && peekNext() == TOK.TOKconst && peekNext2() == TOK.TOKrparen)
+			{
+			m = MOD.MODshared | MOD.MODconst;
+			nextToken();
+			  Lmod2:
+			nextToken();
+			  Lmod1:
+			nextToken();
+			e = parseUnaryExp();
+			e = new CastExp(loc, e, m);
+			}
+			else
+			{
+			Type t = parseType();		// ( type )
+			check(TOK.TOKrparen);
+			e = parseUnaryExp();
+			e = new CastExp(loc, e, t);
+			}
+			break;
+		}
+
+		case TOK.TOKlparen:
+		{   Token *tk;
+
+			tk = peek(&token);
+version (CCASTSYNTAX) {
+			// If cast
+			if (isDeclaration(tk, 0, TOK.TOKrparen, &tk))
+			{
+				tk = peek(tk);		// skip over right parenthesis
+				switch (tk.value)
+				{
+					case TOK.TOKnot:
+						tk = peek(tk);
+						if (tk.value == TOK.TOKis)	// !is
+							break;
+					case TOK.TOKdot:
+					case TOK.TOKplusplus:
+					case TOK.TOKminusminus:
+					case TOK.TOKdelete:
+					case TOK.TOKnew:
+					case TOK.TOKlparen:
+					case TOK.TOKidentifier:
+					case TOK.TOKthis:
+					case TOK.TOKsuper:
+					case TOK.TOKint32v:
+					case TOK.TOKuns32v:
+					case TOK.TOKint64v:
+					case TOK.TOKuns64v:
+					case TOK.TOKfloat32v:
+					case TOK.TOKfloat64v:
+					case TOK.TOKfloat80v:
+					case TOK.TOKimaginary32v:
+					case TOK.TOKimaginary64v:
+					case TOK.TOKimaginary80v:
+					case TOK.TOKnull:
+					case TOK.TOKtrue:
+					case TOK.TOKfalse:
+					case TOK.TOKcharv:
+					case TOK.TOKwcharv:
+					case TOK.TOKdcharv:
+					case TOK.TOKstring:
+static if (false) {
+					case TOK.TOKtilde:
+					case TOK.TOKand:
+					case TOK.TOKmul:
+					case TOK.TOKmin:
+					case TOK.TOKadd:
+}
+					case TOK.TOKfunction:
+					case TOK.TOKdelegate:
+					case TOK.TOKtypeof:
+version (DMDV2) {
+					case TOK.TOKfile:
+					case TOK.TOKline:
+}
+					case TOK.TOKwchar: case TOK.TOKdchar:
+					case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar:
+					case TOK.TOKint8: case TOK.TOKuns8:
+					case TOK.TOKint16: case TOK.TOKuns16:
+					case TOK.TOKint32: case TOK.TOKuns32:
+					case TOK.TOKint64: case TOK.TOKuns64:
+					case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80:
+					case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80:
+					case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80:
+					case TOK.TOKvoid:		// (type)int.size
+					{	
+						// (type) una_exp
+						nextToken();
+						Type t = parseType();
+						check(TOK.TOKrparen);
+
+						// if .identifier
+						if (token.value == TOK.TOKdot)
+						{
+							nextToken();
+							if (token.value != TOK.TOKidentifier)
+							{   
+								error("Identifier expected following (type).");
+								return null;
+							}
+							e = typeDotIdExp(loc, t, token.ident);
+							nextToken();
+							e = parsePostExp(e);
+						}
+						else
+						{
+							e = parseUnaryExp();
+							e = new CastExp(loc, e, t);
+							error("C style cast illegal, use %s", e.toChars());
+						}
+						return e;
+					}
+					
+					default:
+						break;	///
+				}
+			}
+}
+			e = parsePrimaryExp();
+			e = parsePostExp(e);
+			break;
+		}
+		default:
+			e = parsePrimaryExp();
+			e = parsePostExp(e);
+			break;
+		}
+		assert(e);
+		return e;
+	}
+	
+    Expression parsePostExp(Expression e)
+	{
+		Loc loc;
+
+		while (1)
+		{
+		loc = this.loc;
+		switch (token.value)
+		{
+			case TOK.TOKdot:
+			nextToken();
+			if (token.value == TOK.TOKidentifier)
+			{   Identifier id = token.ident;
+
+				nextToken();
+				if (token.value == TOK.TOKnot && peekNext() != TOK.TOKis)
+				{   // identifier!(template-argument-list)
+				TemplateInstance tempinst = new TemplateInstance(loc, id);
+				nextToken();
+				if (token.value == TOK.TOKlparen)
+					// ident!(template_arguments)
+					tempinst.tiargs = parseTemplateArgumentList();
+				else
+					// ident!template_argument
+					tempinst.tiargs = parseTemplateArgument();
+				e = new DotTemplateInstanceExp(loc, e, tempinst);
+				}
+				else
+				e = new DotIdExp(loc, e, id);
+				continue;
+			}
+			else if (token.value == TOK.TOKnew)
+			{
+				e = parseNewExp(e);
+				continue;
+			}
+			else
+				error("identifier expected following '.', not '%s'", token.toChars());
+			break;
+
+			case TOK.TOKplusplus:
+			e = new PostExp(TOK.TOKplusplus, loc, e);
+			break;
+
+			case TOK.TOKminusminus:
+			e = new PostExp(TOK.TOKminusminus, loc, e);
+			break;
+
+			case TOK.TOKlparen:
+			e = new CallExp(loc, e, parseArguments());
+			continue;
+
+			case TOK.TOKlbracket:
+			{	// array dereferences:
+			//	array[index]
+			//	array[]
+			//	array[lwr .. upr]
+			Expression index;
+			Expression upr;
+
+			inBrackets++;
+			nextToken();
+			if (token.value == TOK.TOKrbracket)
+			{   // array[]
+				e = new SliceExp(loc, e, null, null);
+				nextToken();
+			}
+			else
+			{
+				index = parseAssignExp();
+				if (token.value == TOK.TOKslice)
+				{	// array[lwr .. upr]
+				nextToken();
+				upr = parseAssignExp();
+				e = new SliceExp(loc, e, index, upr);
+				}
+				else
+				{	// array[index, i2, i3, i4, ...]
+				Expressions arguments = new Expressions();
+				arguments.push(cast(void*)index);
+				if (token.value == TOK.TOKcomma)
+				{
+					nextToken();
+					while (1)
+					{   Expression arg;
+
+					arg = parseAssignExp();
+					arguments.push(cast(void*)arg);
+					if (token.value == TOK.TOKrbracket)
+						break;
+					check(TOK.TOKcomma);
+					}
+				}
+				e = new ArrayExp(loc, e, arguments);
+				}
+				check(TOK.TOKrbracket);
+				inBrackets--;
+			}
+			continue;
+			}
+
+			default:
+			return e;
+		}
+		nextToken();
+		}
+		
+		assert(false);
+	}
+	
+    Expression parseMulExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseUnaryExp();
+		while (1)
+		{
+			switch (token.value)
+			{
+				case TOK.TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue;
+				case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue;
+				case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue;
+
+				default:
+				break;
+			}
+			break;
+		}
+		return e;
+	}
+	
+    Expression parseShiftExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseAddExp();
+		while (1)
+		{
+			switch (token.value)
+			{
+				case TOK.TOKshl:  nextToken(); e2 = parseAddExp(); e = new ShlExp(loc,e,e2);  continue;
+				case TOK.TOKshr:  nextToken(); e2 = parseAddExp(); e = new ShrExp(loc,e,e2);  continue;
+				case TOK.TOKushr: nextToken(); e2 = parseAddExp(); e = new UshrExp(loc,e,e2); continue;
+
+				default:
+				break;
+			}
+			break;
+		}
+		return e;
+	}
+	
+    Expression parseAddExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseMulExp();
+		while (1)
+		{
+			switch (token.value)
+			{
+				case TOK.TOKadd:    nextToken(); e2 = parseMulExp(); e = new AddExp(loc,e,e2); continue;
+				case TOK.TOKmin:    nextToken(); e2 = parseMulExp(); e = new MinExp(loc,e,e2); continue;
+				case TOK.TOKtilde:  nextToken(); e2 = parseMulExp(); e = new CatExp(loc,e,e2); continue;
+
+				default:
+				break;
+			}
+			break;
+		}
+		return e;
+	}
+	
+    Expression parseRelExp()
+	{
+		assert(false);
+	}
+	
+    Expression parseEqualExp()
+	{
+		assert(false);
+	}
+	
+    Expression parseCmpExp()
+	{
+		Expression e;
+		Expression e2;
+		Token* t;
+		Loc loc = this.loc;
+
+		e = parseShiftExp();
+		TOK op = token.value;
+
+		switch (op)
+		{
+		case TOK.TOKequal:
+		case TOK.TOKnotequal:
+			nextToken();
+			e2 = parseShiftExp();
+			e = new EqualExp(op, loc, e, e2);
+			break;
+
+		case TOK.TOKis:
+			op = TOK.TOKidentity;
+			goto L1;
+
+		case TOK.TOKnot:
+			// Attempt to identify '!is'
+			t = peek(&token);
+			if (t.value != TOK.TOKis)
+			break;
+			nextToken();
+			op = TOK.TOKnotidentity;
+			goto L1;
+
+		L1:
+			nextToken();
+			e2 = parseShiftExp();
+			e = new IdentityExp(op, loc, e, e2);
+			break;
+
+		case TOK.TOKlt:
+		case TOK.TOKle:
+		case TOK.TOKgt:
+		case TOK.TOKge:
+		case TOK.TOKunord:
+		case TOK.TOKlg:
+		case TOK.TOKleg:
+		case TOK.TOKule:
+		case TOK.TOKul:
+		case TOK.TOKuge:
+		case TOK.TOKug:
+		case TOK.TOKue:
+			nextToken();
+			e2 = parseShiftExp();
+			e = new CmpExp(op, loc, e, e2);
+			break;
+
+		case TOK.TOKin:
+			nextToken();
+			e2 = parseShiftExp();
+			e = new InExp(loc, e, e2);
+			break;
+
+		default:
+			break;
+		}
+		return e;
+	}
+	
+    Expression parseAndExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		if (global.params.Dversion == 1)
+		{
+			e = parseEqualExp();
+			while (token.value == TOK.TOKand)
+			{
+				nextToken();
+				e2 = parseEqualExp();
+				e = new AndExp(loc,e,e2);
+				loc = this.loc;
+			}
+		}
+		else
+		{
+			e = parseCmpExp();
+			while (token.value == TOK.TOKand)
+			{
+				nextToken();
+				e2 = parseCmpExp();
+				e = new AndExp(loc,e,e2);
+				loc = this.loc;
+			}
+		}
+		return e;
+	}
+	
+    Expression parseXorExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseAndExp();
+		while (token.value == TOK.TOKxor)
+		{
+			nextToken();
+			e2 = parseAndExp();
+			e = new XorExp(loc, e, e2);
+		}
+
+		return e;
+	}
+
+    Expression parseOrExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseXorExp();
+		while (token.value == TOK.TOKor)
+		{
+			nextToken();
+			e2 = parseXorExp();
+			e = new OrExp(loc, e, e2);
+		}
+		return e;
+	}
+	
+    Expression parseAndAndExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseOrExp();
+		while (token.value == TOK.TOKandand)
+		{
+			nextToken();
+			e2 = parseOrExp();
+			e = new AndAndExp(loc, e, e2);
+		}
+		return e;
+	}
+	
+    Expression parseOrOrExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseAndAndExp();
+		while (token.value == TOK.TOKoror)
+		{
+			nextToken();
+			e2 = parseAndAndExp();
+			e = new OrOrExp(loc, e, e2);
+		}
+
+		return e;
+	}
+	
+    Expression parseCondExp()
+	{
+		Expression e;
+		Expression e1;
+		Expression e2;
+		Loc loc = this.loc;
+
+		e = parseOrOrExp();
+		if (token.value == TOK.TOKquestion)
+		{
+			nextToken();
+			e1 = parseExpression();
+			check(TOK.TOKcolon);
+			e2 = parseCondExp();
+			e = new CondExp(loc, e, e1, e2);
+		}
+		return e;
+	}
+	
+    Expression parseAssignExp()
+	{
+		Expression e;
+		Expression e2;
+		Loc loc;
+
+		e = parseCondExp();
+		while (1)
+		{
+			loc = this.loc;
+			switch (token.value)
+			{
+				case TOK.TOKassign:  nextToken(); e2 = parseAssignExp(); e = new AssignExp(loc,e,e2); continue;
+				case TOK.TOKaddass:  nextToken(); e2 = parseAssignExp(); e = new AddAssignExp(loc,e,e2); continue;
+				case TOK.TOKminass:  nextToken(); e2 = parseAssignExp(); e = new MinAssignExp(loc,e,e2); continue;
+				case TOK.TOKmulass:  nextToken(); e2 = parseAssignExp(); e = new MulAssignExp(loc,e,e2); continue;
+				case TOK.TOKdivass:  nextToken(); e2 = parseAssignExp(); e = new DivAssignExp(loc,e,e2); continue;
+				case TOK.TOKmodass:  nextToken(); e2 = parseAssignExp(); e = new ModAssignExp(loc,e,e2); continue;
+				case TOK.TOKandass:  nextToken(); e2 = parseAssignExp(); e = new AndAssignExp(loc,e,e2); continue;
+				case TOK.TOKorass:   nextToken(); e2 = parseAssignExp(); e = new OrAssignExp(loc,e,e2); continue;
+				case TOK.TOKxorass:  nextToken(); e2 = parseAssignExp(); e = new XorAssignExp(loc,e,e2); continue;
+				case TOK.TOKshlass:  nextToken(); e2 = parseAssignExp(); e = new ShlAssignExp(loc,e,e2); continue;
+				case TOK.TOKshrass:  nextToken(); e2 = parseAssignExp(); e = new ShrAssignExp(loc,e,e2); continue;
+				case TOK.TOKushrass: nextToken(); e2 = parseAssignExp(); e = new UshrAssignExp(loc,e,e2); continue;
+				case TOK.TOKcatass:  nextToken(); e2 = parseAssignExp(); e = new CatAssignExp(loc,e,e2); continue;
+				
+				default:
+					break;
+			}
+			break;
+		}
+
+		return e;
+	}
+	
+	/*************************
+	 * Collect argument list.
+	 * Assume current token is ',', '(' or '['.
+	 */
+    Expressions parseArguments()
+	{
+		// function call
+		Expressions arguments = new Expressions();
+		Expression arg;
+		TOK endtok;
+		
+		if (token.value == TOK.TOKlbracket)
+			endtok = TOK.TOKrbracket;
+		else
+			endtok = TOK.TOKrparen;
+
+		{
+			nextToken();
+			if (token.value != endtok)
+			{
+				while (1)
+				{
+					arg = parseAssignExp();
+					arguments.push(cast(void*)arg);
+					if (token.value == endtok)
+						break;
+					check(TOK.TOKcomma);
+				}
+			}
+			check(endtok);
+		}
+		return arguments;
+	}
+
+    Expression parseNewExp(Expression thisexp)
+	{
+		Type t;
+		Expressions newargs;
+		Expressions arguments = null;
+		Expression e;
+		Loc loc = this.loc;
+
+		nextToken();
+		newargs = null;
+		if (token.value == TOKlparen)
+		{
+			newargs = parseArguments();
+		}
+
+		// An anonymous nested class starts with "class"
+		if (token.value == TOKclass)
+		{
+			nextToken();
+			if (token.value == TOKlparen)
+				arguments = parseArguments();
+
+			BaseClasses baseclasses = null;
+			if (token.value != TOKlcurly)
+				baseclasses = parseBaseClasses();
+
+			Identifier id = null;
+			ClassDeclaration cd = new ClassDeclaration(loc, id, baseclasses);
+
+			if (token.value != TOKlcurly)
+			{   
+				error("{ members } expected for anonymous class");
+				cd.members = null;
+			}
+			else
+			{
+				nextToken();
+				Array decl = parseDeclDefs(0);
+				if (token.value != TOKrcurly)
+					error("class member expected");
+				nextToken();
+				cd.members = decl;
+			}
+
+			e = new NewAnonClassExp(loc, thisexp, newargs, cd, arguments);
+
+			return e;
+		}
+
+		t = parseBasicType();
+		t = parseBasicType2(t);
+		if (t.ty == Taarray)
+		{	
+			TypeAArray taa = cast(TypeAArray)t;
+			Type index = taa.index;
+
+			Expression e2 = index.toExpression();
+			if (e2)
+			{   
+				arguments = new Expressions();
+				arguments.push(cast(void*)e2);
+				t = new TypeDArray(taa.next);
+			}
+			else
+			{
+				error("need size of rightmost array, not type %s", index.toChars());
+				return new NullExp(loc);
+			}
+		}
+		else if (t.ty == Tsarray)
+		{
+			TypeSArray tsa = cast(TypeSArray)t;
+			Expression ee = tsa.dim;
+
+			arguments = new Expressions();
+			arguments.push(cast(void*)ee);
+			t = new TypeDArray(tsa.next);
+		}
+		else if (token.value == TOKlparen)
+		{
+			arguments = parseArguments();
+		}
+
+		e = new NewExp(loc, thisexp, newargs, t, arguments);
+		return e;
+	}
+	
+    void addComment(Dsymbol s, ubyte* blockComment)
+	{
+		s.addComment(combineComments(blockComment, token.lineComment));
+		token.lineComment = null;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PeelStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.PeelStatement;
+
+import dmd.Statement;
+import dmd.Scope;
+import dmd.Loc;
+
+class PeelStatement : Statement
+{
+	Statement s;
+
+	this(Statement s)
+	{
+		assert(false);
+		super(Loc(0));
+	}
+
+	Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Port.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.Port;
+
+import core.stdc.math;
+
+struct Port
+{
+    static int isSignallingNan(double r)
+	{
+		/* A signalling NaN is a NaN with 0 as the most significant bit of
+		 * its significand, which is bit 51 of 0..63 for 64 bit doubles.
+		 */
+		return isnan(r) && !(((cast(ubyte*)&r)[6]) & 8);
+	}
+	
+    static int isSignallingNan(ref real r)
+	{
+		/* A signalling NaN is a NaN with 0 as the most significant bit of
+		 * its significand, which is bit 62 of 0..79 for 80 bit reals.
+		 */
+		return isnan(r) && !(((cast(ubyte*)&r)[7]) & 0x40);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PostBlitDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,67 @@
+module dmd.PostBlitDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+
+class PostBlitDeclaration : FuncDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+		assert(false);
+		super(loc, loc, null, STC.init, null);
+	}
+	
+    this(Loc loc, Loc endloc, Identifier id)
+	{
+		assert(false);
+		super(loc, loc, null, STC.init, null);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    bool isVirtual()
+	{
+		assert(false);
+	}
+	
+    bool addPreInvariant()
+	{
+		assert(false);
+	}
+	
+    bool addPostInvariant()
+	{
+		assert(false);
+	}
+	
+    bool overloadInsert(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+
+    PostBlitDeclaration isPostBlitDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PostExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,83 @@
+module dmd.PostExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.HdrGenState;
+import dmd.IntegerExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TY;
+import dmd.Id;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class PostExp : BinExp
+{
+	this(TOK op, Loc loc, Expression e)
+	{
+		super(loc, op, PostExp.sizeof, e, new IntegerExp(loc, 1, Type.tint32));
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e = this;
+
+		if (!type)
+		{
+			BinExp.semantic(sc);
+			e2 = resolveProperties(sc, e2);
+
+			e = op_overload(sc);
+			if (e)
+				return e;
+
+			e = this;
+			e1 = e1.modifiableLvalue(sc, e1);
+			e1.checkScalar();
+			e1.checkNoBool();
+			if (e1.type.ty == Tpointer)
+				e = scaleFactor(sc);
+			else
+				e2 = e2.castTo(sc, e1.type);
+			e.type = e1.type;
+		}
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return (op == TOKplusplus) ? Id.postinc : Id.postdec;
+	}
+
+	elem* 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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PragmaDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,287 @@
+module dmd.PragmaDeclaration;
+
+import dmd.ArrayTypes;
+import dmd.AttribDeclaration;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.StringExp;
+import dmd.TOK;
+import dmd.WANT;
+import dmd.Global;
+import dmd.Id;
+import dmd.Array;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.FuncDeclaration;
+
+import dmd.backend.Util;
+import dmd.backend.Symbol;
+
+class PragmaDeclaration : AttribDeclaration
+{
+    Expressions args;		// array of Expression's
+
+    this(Loc loc, Identifier ident, Expressions args, Array decl)
+	{
+		super(decl);
+		this.loc = loc;
+		this.ident = ident;
+		this.args = args;
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		//printf("PragmaDeclaration.syntaxCopy(%s)\n", toChars());
+		PragmaDeclaration pd;
+
+		assert(!s);
+		pd = new PragmaDeclaration(loc, ident, Expression.arraySyntaxCopy(args), Dsymbol.arraySyntaxCopy(decl));
+		return pd;
+	}
+	
+    void semantic(Scope sc)
+	{
+		// Should be merged with PragmaStatement
+
+		//printf("\tPragmaDeclaration.semantic '%s'\n",toChars());
+		if (ident == Id.msg)
+		{
+			if (args)
+			{
+				for (size_t i = 0; i < args.dim; i++)
+				{
+					Expression e = cast(Expression)args.data[i];
+
+					e = e.semantic(sc);
+					e = e.optimize(WANTvalue | WANTinterpret);
+					if (e.op == TOKstring)
+					{
+						StringExp se = cast(StringExp)e;
+						writef("%.*s", cast(int)se.len, cast(char*)se.string_);
+					}
+					else
+						error("string expected for message, not '%s'", e.toChars());
+				}
+				writef("\n");
+			}
+			goto Lnodecl;
+		}
+		else if (ident == Id.lib)
+		{
+			if (!args || args.dim != 1)
+				error("string expected for library name");
+			else
+			{
+				Expression e = cast(Expression)args.data[0];
+
+				e = e.semantic(sc);
+				e = e.optimize(WANTvalue | WANTinterpret);
+				args.data[0] = cast(void*)e;
+				if (e.op != TOKstring)
+					error("string expected for library name, not '%s'", e.toChars());
+				else if (global.params.verbose)
+				{
+					StringExp se = cast(StringExp)e;
+					writef("library   %.*s\n", cast(int)se.len, cast(char*)se.string_);
+				}
+			}
+			goto Lnodecl;
+		}
+///	version (IN_GCC) {
+///		else if (ident == Id.GNU_asm)
+///		{
+///		if (! args || args.dim != 2)
+///			error("identifier and string expected for asm name");
+///		else
+///		{
+///			Expression *e;
+///			Declaration *d = null;
+///			StringExp *s = null;
+///
+///			e = (Expression *)args.data[0];
+///			e = e.semantic(sc);
+///			if (e.op == TOKvar)
+///			{
+///			d = ((VarExp *)e).var;
+///			if (! d.isFuncDeclaration() && ! d.isVarDeclaration())
+///				d = null;
+///			}
+///			if (!d)
+///			error("first argument of GNU_asm must be a function or variable declaration");
+///
+///			e = (Expression *)args.data[1];
+///			e = e.semantic(sc);
+///			e = e.optimize(WANTvalue);
+///			if (e.op == TOKstring && ((StringExp *)e).sz == 1)
+///			s = ((StringExp *)e);
+///			else
+///			error("second argument of GNU_asm must be a char string");
+///
+///			if (d && s)
+///			d.c_ident = Lexer.idPool((char*) s.string);
+///		}
+///		goto Lnodecl;
+///		}
+///	}
+		else if (ident == Id.startaddress)
+		{
+			if (!args || args.dim != 1)
+				error("function name expected for start address");
+			else
+			{
+				Expression e = cast(Expression)args.data[0];
+				e = e.semantic(sc);
+				e = e.optimize(WANTvalue | WANTinterpret);
+				args.data[0] = cast(void*)e;
+				Dsymbol sa = getDsymbol(e);
+				if (!sa || !sa.isFuncDeclaration())
+					error("function name expected for start address, not '%s'", e.toChars());
+			}
+			goto Lnodecl;
+		}
+///	version (TARGET_NET) {
+///		else if (ident == Lexer.idPool("assembly"))
+///		{
+///		}
+///	} // TARGET_NET
+		else if (global.params.ignoreUnsupportedPragmas)
+		{
+			if (global.params.verbose)
+			{
+				/* Print unrecognized pragmas
+				 */
+				writef("pragma    %s", ident.toChars());
+				if (args)
+				{
+					for (size_t i = 0; i < args.dim; i++)
+					{
+						Expression e = cast(Expression)args.data[i];
+						e = e.semantic(sc);
+						e = e.optimize(WANTvalue | WANTinterpret);
+						if (i == 0)
+							writef(" (");
+						else
+							writef(",");
+						writef("%s", e.toChars());
+					}
+					if (args.dim)
+						writef(")");
+				}
+				writef("\n");
+			}
+			goto Lnodecl;
+		}
+		else
+			error("unrecognized pragma(%s)", ident.toChars());
+
+		if (decl)
+		{
+			for (uint i = 0; i < decl.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)decl.data[i];
+				s.semantic(sc);
+			}
+		}
+		return;
+
+	Lnodecl:
+		if (decl)
+			error("pragma is missing closing ';'");
+	}
+	
+    void setScope(Scope sc)
+	{
+version (TARGET_NET) {
+    if (ident == Lexer.idPool("assembly"))
+    {
+        if (!args || args.dim != 1)
+        {
+            error("pragma has invalid number of arguments");
+        }
+        else
+        {
+            Expression e = cast(Expression)args.data[0];
+            e = e.semantic(sc);
+            e = e.optimize(WANTvalue | WANTinterpret);
+            args.data[0] = cast(void*)e;
+            if (e.op != TOKstring)
+            {
+                error("string expected, not '%s'", e.toChars());
+            }
+            PragmaScope pragma_ = new PragmaScope(this, sc.parent, cast(StringExp)e);
+
+            assert(sc);
+            pragma_.setScope(sc);
+
+            //add to module members
+            assert(sc.module_);
+            assert(sc.module_.members);
+            sc.module_.members.push(cast(void*)pragma_);
+        }
+    }
+}
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		if (ident == Id.lib)
+		{
+			assert(args && args.dim == 1);
+
+			Expression e = cast(Expression)args.data[0];
+
+			assert(e.op == TOKstring);
+
+			StringExp se = cast(StringExp)e;
+			char* name = cast(char*)malloc(se.len + 1);
+			memcpy(name, se.string_, se.len);
+			name[se.len] = 0;
+		version (OMFOBJ) {
+			/* The OMF format allows library names to be inserted
+			 * into the object file. The linker will then automatically
+			 * search that library, too.
+			 */
+			obj_includelib(name);
+		} else version (ELFOBJ_OR_MACHOBJ) {
+			/* The format does not allow embedded library names,
+			 * so instead append the library name to the list to be passed
+			 * to the linker.
+			 */
+			global.params.libfiles.push(cast(void*) name);
+		} else {
+			error("pragma lib not supported");
+		}
+		}
+///	version (DMDV2) {
+		else if (ident == Id.startaddress)
+		{
+			assert(args && args.dim == 1);
+			Expression e = cast(Expression)args.data[0];
+			Dsymbol sa = getDsymbol(e);
+			FuncDeclaration f = sa.isFuncDeclaration();
+			assert(f);
+			Symbol* s = f.toSymbol();
+			obj_startaddress(s);
+		}
+///	}
+		AttribDeclaration.toObjFile(multiobj);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PragmaStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,55 @@
+module dmd.PragmaStatement;
+
+import dmd.Statement;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.IRState;
+import dmd.BE;
+
+class PragmaStatement : Statement
+{
+    Identifier ident;
+    Expressions args;		// array of Expression's
+    Statement body_;
+
+    this(Loc loc, Identifier ident, Expressions args, Statement body_)
+	{
+		assert(false);
+		super(loc);
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ProtDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,53 @@
+module dmd.ProtDeclaration;
+
+import dmd.AttribDeclaration;
+import dmd.PROT;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.Array;
+
+class ProtDeclaration : AttribDeclaration
+{
+    PROT protection;
+
+    this(PROT p, Array decl)
+	{
+		super(decl);
+
+		protection = p;
+		//printf("decl = %p\n", decl);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void setScope(Scope sc)
+	{
+		if (decl)
+		{
+			setScopeNewSc(sc, sc.stc, sc.linkage, protection, 1, sc.structalign);
+		}
+	}
+	
+    void semantic(Scope sc)
+	{
+		if (decl)
+		{
+			semanticNewSc(sc, sc.stc, sc.linkage, protection, 1, sc.structalign);
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    static void protectionToCBuffer(OutBuffer buf, PROT protection)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PtrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,193 @@
+module dmd.PtrExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.GlobalExpressions;
+import dmd.SymOffExp;
+import dmd.AddrExp;
+import dmd.VarDeclaration;
+import dmd.StructLiteralExp;
+import dmd.TypePointer;
+import dmd.TypeArray;
+import dmd.ErrorExp;
+import dmd.TY;
+import dmd.expression.Ptr;
+import dmd.expression.Util;
+
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+import dmd.backend.OPER;
+
+class PtrExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKstar, PtrExp.sizeof, e);
+		//    if (e.type)
+		//		type = ((TypePointer *)e.type).next;
+	}
+
+	this(Loc loc, Expression e, Type t)
+	{
+		super(loc, TOKstar, PtrExp.sizeof, e);
+		type = t;
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version (LOGSEMANTIC) {
+		printf("PtrExp::semantic('%s')\n", toChars());
+	}
+		if (!type)
+		{
+			UnaExp.semantic(sc);
+			e1 = resolveProperties(sc, e1);
+			if (!e1.type)
+				writef("PtrExp.semantic('%s')\n", toChars());
+			Expression e = op_overload(sc);
+			if (e)
+				return e;
+			Type tb = e1.type.toBasetype();
+			switch (tb.ty)
+			{
+				case Tpointer:
+					type = (cast(TypePointer)tb).next;
+					break;
+
+				case Tsarray:
+				case Tarray:
+					type = (cast(TypeArray)tb).next;
+					e1 = e1.castTo(sc, type.pointerTo());
+					break;
+
+				default:
+					error("can only * a pointer, not a '%s'", e1.type.toChars());
+					return new ErrorExp();
+			}
+			rvalue();
+		}
+		return this;
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+static if (false) {
+		tym = tybasic(e1.ET.Tty);
+		if (!(tyscalar(tym) ||
+		  tym == TYstruct ||
+		  tym == TYarray && e.Eoper == TOKaddr)
+		)
+			synerr(EM_lvalue);	// lvalue expected
+}
+		return this;
+	}
+
+version (DMDV2) {
+	Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		//printf("PtrExp.modifiableLvalue() %s, type %s\n", toChars(), type.toChars());
+
+		if (e1.op == TOKsymoff)
+		{	
+			SymOffExp se = cast(SymOffExp)e1;
+			se.var.checkModify(loc, sc, type);
+			//return toLvalue(sc, e);
+		}
+
+		return Expression.modifiableLvalue(sc, e);
+	}
+}
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+
+		//printf("PtrExp::toElem() %s\n", toChars());
+		e = e1.toElem(irs);
+		e = el_una(OPER.OPind, type.totym(), e);
+
+		if (tybasic(e.Ety) == TYM.TYstruct)
+		{
+			e.Enumbytes = cast(uint)type.size();
+		}
+
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("PtrExp.optimize(result = x%x) %s\n", result, toChars());
+		e1 = e1.optimize(result);
+		// Convert *&ex to ex
+		if (e1.op == TOK.TOKaddress)
+		{	
+			Expression e;
+			Expression ex;
+
+			ex = (cast(AddrExp)e1).e1;
+			if (type.equals(ex.type))
+				e = ex;
+			else
+			{
+				e = ex.copy();
+				e.type = type;
+			}
+			return e;
+		}
+		// Constant fold *(&structliteral + offset)
+		if (e1.op == TOK.TOKadd)
+		{
+			Expression e;
+			e = Ptr(type, e1);
+			if (e !is EXP_CANT_INTERPRET)
+				return e;
+		}
+
+		if (e1.op == TOK.TOKsymoff)
+		{	
+			SymOffExp se = cast(SymOffExp)e1;
+			VarDeclaration v = se.var.isVarDeclaration();
+			Expression e = expandVar(result, v);
+			if (e && e.op == TOK.TOKstructliteral)
+			{   
+				StructLiteralExp sle = cast(StructLiteralExp)e;
+				e = sle.getField(type, se.offset);
+				if (e && e !is EXP_CANT_INTERPRET)
+					return e;
+			}
+		}
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/RET.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,7 @@
+module dmd.RET;
+
+enum RET
+{
+    RETregs	= 1,	// returned in registers
+    RETstack	= 2,	// returned on stack
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/RealExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,207 @@
+module dmd.RealExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.Type;
+import dmd.HdrGenState;
+import dmd.Port;
+import dmd.TY;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+import dmd.Complex;
+
+class RealExp : Expression
+{
+	real value;
+
+	this(Loc loc, real value, Type type)
+	{
+		super(loc, TOK.TOKfloat64, RealExp.sizeof);
+		//printf("RealExp.RealExp(%Lg)\n", value);
+		this.value = value;
+		this.type = type;
+	}
+
+	int equals(Object o)
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		if (!type)
+			type = Type.tfloat64;
+		else
+			type = type.semantic(loc, sc);
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+		assert(false);
+	}
+
+	ulong toInteger()
+	{
+		assert(false);
+	}
+
+	ulong toUInteger()
+	{
+		assert(false);
+	}
+
+	real toReal()
+	{
+		return type.isreal() ? value : 0;
+	}
+
+	real toImaginary()
+	{
+		return type.isreal() ? 0 : value;
+	}
+
+	Complex!(real) toComplex()
+	{
+		return Complex!(real)(toReal(), toImaginary());
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		Expression e = this;
+		if (type != t)
+		{
+			if ((type.isreal() && t.isreal()) ||
+				(type.isimaginary() && t.isimaginary())
+			   )
+			{   
+				e = copy();
+				e.type = t;
+			}
+			else
+				e = Expression.castTo(sc, t);
+		}
+		return e;
+	}
+
+	int isConst()
+	{
+		return 1;
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		eve c;
+		tym_t ty;
+
+		//printf("RealExp.toElem(%p) %s\n", this, toChars());
+		///memset(&c, 0, sizeof(c));
+		ty = type.toBasetype().totym();
+		switch (tybasic(ty))
+		{
+			case TYfloat:
+			case TYifloat:
+				c.Vfloat = value;
+				if (Port.isSignallingNan(value)) {
+					std.stdio.writeln("signalling float");
+					(cast(uint*)&c.Vfloat)[0] &= 0xFFBFFFFFL;
+				}
+				break;
+
+			case TYdouble:
+			case TYidouble:
+				c.Vdouble = value;	// unfortunately, this converts SNAN to QNAN
+				if (Port.isSignallingNan(value)) {
+					std.stdio.writeln("signalling double");
+					// Put SNAN back
+					(cast(uint*)&c.Vdouble)[1] &= 0xFFF7FFFFL;
+				}
+				break;
+
+			case TYldouble:
+			case TYildouble:
+				c.Vldouble = value;
+				break;
+
+			default:
+				print();
+				///type.print();
+				///type.toBasetype().print();
+				writef("ty = %d, tym = %x\n", type.ty, ty);
+				assert(0);
+		}
+		return el_const(ty, &c);
+	}
+	
+	static private char[6] zeropad;
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		float fvalue;
+		double dvalue;
+		real evalue;
+
+		//printf("RealExp.toDt(%Lg)\n", value);
+		switch (type.toBasetype().ty)
+		{
+			case Tfloat32:
+			case Timaginary32:
+				fvalue = value;
+				pdt = dtnbytes(pdt,4,cast(char*)&fvalue);
+				break;
+
+			case Tfloat64:
+			case Timaginary64:
+				dvalue = value;
+				pdt = dtnbytes(pdt,8,cast(char*)&dvalue);
+				break;
+
+			case Tfloat80:
+			case Timaginary80:
+				evalue = value;
+				pdt = dtnbytes(pdt,REALSIZE - REALPAD,cast(char*)&evalue);
+				pdt = dtnbytes(pdt,REALPAD,zeropad.ptr);
+				assert(REALPAD <= zeropad.sizeof);
+				break;
+
+			default:
+				writef("%s\n", toChars());
+				///type.print();
+				assert(0);
+				break;
+		}
+		return pdt;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/RemoveExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,57 @@
+module dmd.RemoveExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.TypeAArray;
+import dmd.TY;
+
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.Symbol;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+/* This deletes the key e1 from the associative array e2
+ */
+
+class RemoveExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOKremove, RemoveExp.sizeof, e1, e2);
+		type = Type.tvoid;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		Type tb = e1.type.toBasetype();
+		assert(tb.ty == Taarray);
+		TypeAArray taa = cast(TypeAArray)tb;
+		elem* ea = e1.toElem(irs);
+		elem* ekey = e2.toElem(irs);
+		elem* ep;
+		elem* keyti;
+
+		if (tybasic(ekey.Ety) == TYstruct)
+		{
+			ekey = el_una(OPstrpar, TYstruct, ekey);
+			ekey.Enumbytes = ekey.E1.Enumbytes;
+			assert(ekey.Enumbytes);
+		}
+
+		Symbol* s = taa.aaGetSymbol("Del", 0);
+		keyti = taa.index.getInternalTypeInfo(null).toElem(irs);
+		ep = el_params(ekey, keyti, ea, null);
+		e = el_bin(OPcall, TYnptr, el_var(s), ep);
+
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ReturnStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,501 @@
+module dmd.ReturnStatement;
+
+import dmd.Loc;
+import dmd.Statement;
+import dmd.GotoStatement;
+import dmd.STC;
+import dmd.CompoundStatement;
+import dmd.Id;
+import dmd.AssignExp;
+import dmd.ExpStatement;
+import dmd.FuncDeclaration;
+import dmd.IntegerExp;
+import dmd.ThisExp;
+import dmd.StructDeclaration;
+import dmd.TypeFunction;
+import dmd.CSX;
+import dmd.RET;
+import dmd.TOK;
+import dmd.Type;
+import dmd.Expression;
+import dmd.StructLiteralExp;
+import dmd.TypeStruct;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InterState;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.TY;
+import dmd.WANT;
+import dmd.VarExp;
+import dmd.VarDeclaration;
+import dmd.BE;
+import dmd.codegen.Util;
+
+import dmd.backend.Blockx;
+import dmd.backend.elem;
+import dmd.backend.TYM;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.mTY;
+import dmd.backend.BC;
+
+class ReturnStatement : Statement
+{
+    Expression exp;
+
+    this(Loc loc, Expression exp)
+	{
+		super(loc);
+		this.exp = exp;
+	}
+	
+    Statement syntaxCopy()
+	{
+		Expression e = exp ? exp.syntaxCopy() : null;
+		return new ReturnStatement(loc, e);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("ReturnStatement.semantic() %s\n", toChars());
+
+		FuncDeclaration fd = sc.parent.isFuncDeclaration();
+		Scope scx = sc;
+		int implicit0 = 0;
+
+		if (sc.fes)
+		{
+			// Find scope of function foreach is in
+			for (; 1; scx = scx.enclosing)
+			{
+				assert(scx);
+				if (scx.func !is fd)
+				{	
+					fd = scx.func;		// fd is now function enclosing foreach
+					break;
+				}
+			}
+		}
+
+		Type tret = fd.type.nextOf();
+		if (fd.tintro) {
+			/* We'll be implicitly casting the return expression to tintro
+			*/
+			tret = fd.tintro.nextOf();
+		}
+
+		Type tbret = null;
+
+		if (tret) {
+			tbret = tret.toBasetype();
+		}
+
+		// main() returns 0, even if it returns void
+		if (!exp && (!tbret || tbret.ty == TY.Tvoid) && fd.isMain())
+		{	
+			implicit0 = 1;
+			exp = new IntegerExp(0);
+		}
+
+		if (sc.incontract || scx.incontract)
+			error("return statements cannot be in contracts");
+
+		if (sc.tf || scx.tf)
+			error("return statements cannot be in finally, scope(exit) or scope(success) bodies");
+
+		if (fd.isCtorDeclaration())
+		{
+			// Constructors implicitly do:
+			//	return this;
+			if (exp && exp.op != TOK.TOKthis) {
+				error("cannot return expression from constructor");
+			}
+
+			exp = new ThisExp(Loc(0));
+		}
+
+		if (!exp) {
+			fd.nrvo_can = 0;
+		}
+
+		if (exp)
+		{
+			fd.hasReturnExp |= 1;
+
+			exp = exp.semantic(sc);
+			exp = resolveProperties(sc, exp);
+			exp = exp.optimize(WANT.WANTvalue);
+
+			if (fd.nrvo_can && exp.op == TOK.TOKvar) {   
+				VarExp ve = cast(VarExp)exp;
+				VarDeclaration v = ve.var.isVarDeclaration();
+
+				if ((cast(TypeFunction)fd.type).isref) {
+					// Function returns a reference
+					fd.nrvo_can = 0;
+				} else if (!v || v.isOut() || v.isRef()) {
+					fd.nrvo_can = 0;
+				} else if (tbret.ty == TY.Tstruct && (cast(TypeStruct)tbret).sym.dtor) {
+					// Struct being returned has destructors
+					fd.nrvo_can = 0;
+				} else if (fd.nrvo_var is null) {
+					if (!v.isDataseg() && !v.isParameter() && v.toParent2() == fd) {
+						//printf("Setting nrvo to %s\n", v.toChars());
+						fd.nrvo_var = v;
+					} else {
+						fd.nrvo_can = 0;
+					}
+				} else if (fd.nrvo_var != v) {
+					fd.nrvo_can = 0;
+				}
+			} else {
+				fd.nrvo_can = 0;
+			}
+
+			if (fd.returnLabel && tbret.ty != TY.Tvoid) {
+				;
+			} else if (fd.inferRetType) {
+				if (fd.type.nextOf()) {
+					if (!exp.type.equals(fd.type.nextOf()))
+						error("mismatched function return type inference of %s and %s", exp.type.toChars(), fd.type.nextOf().toChars());
+				}
+				else
+				{
+					(cast(TypeFunction)fd.type).next = exp.type;
+					fd.type = fd.type.semantic(loc, sc);
+					if (!fd.tintro)
+					{   
+						tret = fd.type.nextOf();
+						tbret = tret.toBasetype();
+					}
+				}
+			} else if (tbret.ty != TY.Tvoid)
+			{
+				exp = exp.implicitCastTo(sc, tret);
+				exp = exp.optimize(WANT.WANTvalue);
+			}
+		} else if (fd.inferRetType) {
+			if (fd.type.nextOf())
+			{
+				if (fd.type.nextOf().ty != TY.Tvoid) {
+					error("mismatched function return type inference of void and %s", fd.type.nextOf().toChars());
+				}
+			}
+			else
+			{
+				(cast(TypeFunction*)fd.type).next = Type.tvoid;
+				fd.type = fd.type.semantic(loc, sc);
+				if (!fd.tintro)
+				{   
+					tret = Type.tvoid;
+					tbret = tret;
+				}
+			}
+		}
+		else if (tbret.ty != TY.Tvoid)	 {// if non-void return
+			error("return expression expected");
+		}
+
+		if (sc.fes)
+		{
+			Statement s;
+
+			if (exp && !implicit0)
+			{
+				exp = exp.implicitCastTo(sc, tret);
+			}
+			if (!exp || exp.op == TOK.TOKint64 || exp.op == TOK.TOKfloat64 ||
+				exp.op == TOK.TOKimaginary80 || exp.op == TOK.TOKcomplex80 ||
+				exp.op == TOK.TOKthis || exp.op == TOK.TOKsuper || exp.op == TOK.TOKnull ||
+				exp.op == TOK.TOKstring)
+			{
+				sc.fes.cases.push(cast(void*)this);
+				// Construct: return cases.dim+1;
+				s = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1));
+			}
+			else if (fd.type.nextOf().toBasetype() == Type.tvoid)
+			{
+				s = new ReturnStatement(Loc(0), null);
+				sc.fes.cases.push(cast(void*)s);
+
+				// Construct: { exp; return cases.dim + 1; }
+				Statement s1 = new ExpStatement(loc, exp);
+				Statement s2 = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1));
+				s = new CompoundStatement(loc, s1, s2);
+			}
+			else
+			{
+				// Construct: return vresult;
+				if (!fd.vresult)
+				{	
+					// Declare vresult
+					VarDeclaration v = new VarDeclaration(loc, tret, Id.result, null);
+					v.noauto = true;
+					v.semantic(scx);
+					if (!scx.insert(v)) {
+						assert(0);
+					}
+					v.parent = fd;
+					fd.vresult = v;
+				}
+
+				s = new ReturnStatement(Loc(0), new VarExp(Loc(0), fd.vresult));
+				sc.fes.cases.push(cast(void*)s);
+
+				// Construct: { vresult = exp; return cases.dim + 1; }
+				exp = new AssignExp(loc, new VarExp(Loc(0), fd.vresult), exp);
+				exp.op = TOK.TOKconstruct;
+				exp = exp.semantic(sc);
+				Statement s1 = new ExpStatement(loc, exp);
+				Statement s2 = new ReturnStatement(Loc(0), new IntegerExp(sc.fes.cases.dim + 1));
+				s = new CompoundStatement(loc, s1, s2);
+			}
+			return s;
+		}
+
+		if (exp)
+		{
+			if (fd.returnLabel && tbret.ty != TY.Tvoid)
+			{
+				assert(fd.vresult);
+				VarExp v = new VarExp(Loc(0), fd.vresult);
+
+				exp = new AssignExp(loc, v, exp);
+				exp.op = TOK.TOKconstruct;
+				exp = exp.semantic(sc);
+			}
+
+			if ((cast(TypeFunction)fd.type).isref && !fd.isCtorDeclaration())
+			{   // Function returns a reference
+				if (tbret.isMutable())
+					exp = exp.modifiableLvalue(sc, exp);
+				else
+					exp = exp.toLvalue(sc, exp);
+
+				if (exp.op == TOK.TOKvar)
+				{	
+					VarExp ve = cast(VarExp)exp;
+					VarDeclaration v = ve.var.isVarDeclaration();
+					if (v && !v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout))) {
+						error("escaping reference to local variable %s", v.toChars());
+					}
+				}
+			}
+
+			//exp.dump(0);
+			//exp.print();
+			exp.checkEscape();
+		}
+
+		/* BUG: need to issue an error on:
+		 *	this
+		 *	{   if (x) return;
+		 *	    super();
+		 *	}
+		 */
+
+		if (sc.callSuper & CSX.CSXany_ctor && !(sc.callSuper & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor))) {
+			error("return without calling constructor");
+		}
+
+		sc.callSuper |= CSX.CSXreturn;
+
+		// See if all returns are instead to be replaced with a goto returnLabel;
+		if (fd.returnLabel)
+		{
+			GotoStatement gs = new GotoStatement(loc, Id.returnLabel);
+
+			gs.label = fd.returnLabel;
+			if (exp)
+			{   
+				/* Replace: return exp;
+				 * with:    exp; goto returnLabel;
+				 */
+				Statement s = new ExpStatement(Loc(0), exp);
+				return new CompoundStatement(loc, s, gs);
+			}
+			return gs;
+		}
+
+		if (exp && tbret.ty == TY.Tvoid && !fd.isMain())
+		{
+			/* Replace:
+			 *	return exp;
+			 * with:
+			 *	exp; return;
+			 */
+			Statement s = new ExpStatement(loc, exp);
+			loc = Loc(0);
+			exp = null;
+			return new CompoundStatement(loc, s, this);
+		}
+
+		return this;
+	}
+	
+    BE blockExit()
+	{
+		BE result = BE.BEreturn;
+		if (exp && exp.canThrow())
+			result |= BE.BEthrow;
+
+		return result;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    int inlineCost(InlineCostState* ics)
+	{
+		// Can't handle return statements nested in if's
+		if (ics.nested)
+			return COST_MAX;
+		return exp ? exp.inlineCost(ics) : 0;
+	}
+	
+    Expression doInline(InlineDoState ids)
+	{
+		//printf("ReturnStatement.doInline() '%s'\n", exp ? exp.toChars() : "");
+		return exp ? exp.doInline(ids) : null;
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		//printf("ReturnStatement.inlineScan()\n");
+		if (exp)
+		{
+			exp = exp.inlineScan(iss);
+		}
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		Blockx* blx = irs.blx;
+
+		incUsage(irs, loc);
+		if (exp)
+		{	
+			elem *e;
+
+			FuncDeclaration func = irs.getFunc();
+			assert(func);
+			assert(func.type.ty == TY.Tfunction);
+			TypeFunction tf = cast(TypeFunction)(func.type);
+
+			RET retmethod = tf.retStyle();
+			if (retmethod == RET.RETstack)
+			{
+				elem* es;
+
+				/* If returning struct literal, write result
+				 * directly into return value
+				 */
+				if (exp.op == TOK.TOKstructliteral)
+				{	
+					assert(false);
+					/*
+					StructLiteralExp se = cast(StructLiteralExp)exp;
+					char save[(StructLiteralExp).sizeof];
+					memcpy(save, se, sizeof(StructLiteralExp));
+					se.sym = irs.shidden;
+					se.soffset = 0;
+					se.fillHoles = 1;
+					e = exp.toElem(irs);
+					memcpy(se, save, sizeof(StructLiteralExp));
+					*/
+				}
+				else
+					e = exp.toElem(irs);
+				
+				assert(e);
+
+				if (exp.op == TOK.TOKstructliteral || (func.nrvo_can && func.nrvo_var))
+				{
+					// Return value via hidden pointer passed as parameter
+					// Write exp; return shidden;
+					es = e;
+				}
+				else
+				{
+					// Return value via hidden pointer passed as parameter
+					// Write *shidden=exp; return shidden;
+					int op;
+					tym_t ety;
+
+					ety = e.Ety;
+					es = el_una(OPER.OPind,ety,el_var(irs.shidden));
+					op = (tybasic(ety) == TYM.TYstruct) ? OPER.OPstreq : OPER.OPeq;
+					es = el_bin(op, ety, es, e);
+					if (op == OPER.OPstreq)
+						es.Enumbytes = cast(uint)exp.type.size();
+version (DMDV2) {
+					/* Call postBlit() on *shidden
+					 */
+					Type tb = exp.type.toBasetype();
+					//if (tb.ty == TY.Tstruct) exp.dump(0);
+					if ((exp.op == TOK.TOKvar || exp.op == TOK.TOKdotvar || exp.op == TOK.TOKstar) &&
+						tb.ty == TY.Tstruct)
+					{   StructDeclaration sd = (cast(TypeStruct)tb).sym;
+						if (sd.postblit)
+						{	
+							FuncDeclaration fd = sd.postblit;
+							elem* ec = el_var(irs.shidden);
+							ec = callfunc(loc, irs, 1, Type.tvoid, ec, tb.pointerTo(), fd, fd.type, null, null);
+							es = el_bin(OPER.OPcomma, ec.Ety, es, ec);
+						}
+
+static if (false) {
+						/* It has been moved, so disable destructor
+						 */
+						if (exp.op == TOK.TOKvar)
+						{	
+							VarExp ve = cast(VarExp)exp;
+							VarDeclaration v = ve.var.isVarDeclaration();
+							if (v && v.rundtor)
+							{
+								elem* er = el_var(v.rundtor.toSymbol());
+								er = el_bin(OPER.OPeq, TYM.TYint, er, el_long(TYM.TYint, 0));
+								es = el_bin(OPER.OPcomma, TYM.TYint, es, er);
+							}
+						}
+}
+					}
+}
+				}
+				e = el_var(irs.shidden);
+				e = el_bin(OPER.OPcomma, e.Ety, es, e);
+			}
+///version (DMDV2) {
+			else if (tf.isref)
+			{   // Reference return, so convert to a pointer
+				Expression ae = exp.addressOf(null);
+				e = ae.toElem(irs);
+			}
+///}
+			else
+			{
+				e = exp.toElem(irs);
+				assert(e);
+			}
+
+			block_appendexp(blx.curblock, e);
+			block_next(blx, BC.BCretexp, null);
+		}
+		else
+			block_next(blx, BC.BCret, null);
+	}
+
+    ReturnStatement isReturnStatement() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/STC.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,43 @@
+module dmd.STC;
+
+enum STC
+{
+    STCundefined    = 0,
+    STCstatic	    = 1,
+    STCextern	    = 2,
+    STCconst	    = 4,
+    STCfinal	    = 8,
+    STCabstract     = 0x10,
+    STCparameter    = 0x20,
+    STCfield	    = 0x40,
+    STCoverride	    = 0x80,
+    STCauto         = 0x100,
+    STCsynchronized = 0x200,
+    STCdeprecated   = 0x400,
+    STCin           = 0x800,		// in parameter
+    STCout          = 0x1000,		// out parameter
+    STClazy	    = 0x2000,		// lazy parameter
+    STCforeach      = 0x4000,		// variable for foreach loop
+    STCcomdat       = 0x8000,		// should go into COMDAT record
+    STCvariadic     = 0x10000,		// variadic function argument
+    STCctorinit     = 0x20000,		// can only be set inside constructor
+    STCtemplateparameter = 0x40000,	// template parameter
+    STCscope	    = 0x80000,		// template parameter
+    STCinvariant    = 0x100000,
+    STCimmutable    = 0x100000,
+    STCref	    = 0x200000,
+    STCinit	    = 0x400000,		// has explicit initializer
+    STCmanifest	    = 0x800000,		// manifest constant
+    STCnodtor	    = 0x1000000,	// don't run destructor
+    STCnothrow	    = 0x2000000,	// never throws exceptions
+    STCpure	    = 0x4000000,	// pure function
+    STCtls	    = 0x8000000,	// thread local
+    STCalias	    = 0x10000000,	// alias parameter
+    STCshared       = 0x20000000,	// accessible from multiple threads
+    STCgshared      = 0x40000000,	// accessible from multiple threads
+					// but not typed as "shared"
+    STC_TYPECTOR    = (STCconst | STCimmutable | STCshared),
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(STC));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Scope.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,355 @@
+module dmd.Scope;
+
+import dmd.Module;
+import dmd.ScopeDsymbol;
+import dmd.FuncDeclaration;
+import dmd.Id;
+import dmd.Dsymbol;
+import dmd.LabelStatement;
+import dmd.SwitchStatement;
+import dmd.TryFinallyStatement;
+import dmd.TemplateInstance;
+import dmd.Statement;
+import dmd.ForeachStatement;
+import dmd.LINK;
+import dmd.PROT;
+import dmd.STC;
+import dmd.AnonymousAggregateDeclaration;
+import dmd.AggregateDeclaration;
+import dmd.ClassDeclaration;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.DocComment;
+import dmd.DsymbolTable;
+import dmd.Global;
+import dmd.CSX;
+import dmd.Util;
+
+enum SCOPE
+{
+	SCOPEctor = 1,	// constructor type
+	SCOPEstaticif = 2,	// inside static if
+	SCOPEfree = 4,	// is on free list
+}
+
+class Scope
+{
+    Scope enclosing;		// enclosing Scope
+
+    Module module_;		// Root module
+    ScopeDsymbol scopesym;	// current symbol
+    ScopeDsymbol sd;		// if in static if, and declaring new symbols,
+				// sd gets the addMember()
+    FuncDeclaration func;	// function we are in
+    Dsymbol parent;		// parent to use
+    LabelStatement slabel;	// enclosing labelled statement
+    SwitchStatement sw;	// enclosing switch statement
+    TryFinallyStatement tf;	// enclosing try finally statement
+    TemplateInstance tinst;    // enclosing template instance
+    Statement sbreak;		// enclosing statement that supports "break"
+    Statement scontinue;	// enclosing statement that supports "continue"
+    ForeachStatement fes;	// if nested function for ForeachStatement, this is it
+    uint offset;		// next offset to use in aggregate
+    int inunion;		// we're processing members of a union
+    int incontract;		// we're inside contract code
+    int nofree;			// set if shouldn't free it
+    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
+    int mustsemantic;		// cannot defer semantic()
+
+    uint callSuper;		// primitive flow analysis for constructors
+///#define	CSXthis_ctor	1	// called this()
+///#define CSXsuper_ctor	2	// called super()
+///#define CSXthis		4	// referenced this
+///#define CSXsuper	8	// referenced super
+///#define CSXlabel	0x10	// seen a label
+///#define CSXreturn	0x20	// seen a return statement
+///#define CSXany_ctor	0x40	// either this() or super() was called
+
+    uint structalign;	// alignment for struct members
+    LINK linkage = LINK.LINKd;		// linkage for external functions
+
+    PROT protection = PROT.PROTpublic;	// protection for class members
+    int explicitProtection;	// set if in an explicit protection attribute
+
+    STC stc;		// storage class
+
+    SCOPE flags;
+
+    AnonymousAggregateDeclaration anonAgg;	// for temporary analysis
+
+    DocComment lastdc;		// documentation comment for last symbol at this scope
+    uint lastoffset;	// offset in docbuf of where to insert next dec
+    OutBuffer docbuf;		// buffer for documentation output
+
+    static Scope freelist;
+///    static void *operator new(size_t sz);
+    static Scope createGlobal(Module module_)
+	{
+		Scope sc = new Scope();
+		sc.module_ = module_;
+		sc.scopesym = new ScopeDsymbol();
+		sc.scopesym.symtab = new DsymbolTable();
+
+		// Add top level package as member of this global scope
+		Dsymbol m = module_;
+		while (m.parent !is null)
+			m = m.parent;
+
+		m.addMember(null, sc.scopesym, 1);
+		m.parent = null;			// got changed by addMember()
+
+		// Create the module scope underneath the global scope
+		sc = sc.push(module_);
+		sc.parent = module_;
+		return sc;
+	}
+
+    this()
+	{
+		// Create root scope
+
+		//printf("Scope.Scope() %p\n", this);
+		this.structalign = global.structalign;
+	}
+	
+    this(Module module_)
+	{
+		assert(false);
+	}
+	
+    this(Scope enclosing)
+	{
+		//printf("Scope.Scope(enclosing = %p) %p\n", enclosing, this);
+		assert(!(enclosing.flags & SCOPE.SCOPEfree));
+		this.module_ = enclosing.module_;
+		this.func   = enclosing.func;
+		this.parent = enclosing.parent;
+		this.sw = enclosing.sw;
+		this.tf = enclosing.tf;
+		this.tinst = enclosing.tinst;
+		this.sbreak = enclosing.sbreak;
+		this.scontinue = enclosing.scontinue;
+		this.fes = enclosing.fes;
+		this.structalign = enclosing.structalign;
+		this.enclosing = enclosing;
+debug {
+		if (enclosing.enclosing)
+			assert(!(enclosing.enclosing.flags & SCOPE.SCOPEfree));
+
+		if (this is enclosing.enclosing)	/// huh?
+		{
+			writef("this = %p, enclosing = %p, enclosing.enclosing = %p\n", this, enclosing, enclosing.enclosing);
+		}
+		assert(this !is enclosing.enclosing);
+}
+		this.linkage = enclosing.linkage;
+		this.protection = enclosing.protection;
+		this.explicitProtection = enclosing.explicitProtection;
+		this.stc = enclosing.stc;
+		this.inunion = enclosing.inunion;
+		this.incontract = enclosing.incontract;
+		this.noctor = enclosing.noctor;
+		this.noaccesscheck = enclosing.noaccesscheck;
+		this.mustsemantic = enclosing.mustsemantic;
+		this.intypeof = enclosing.intypeof;
+		this.parameterSpecialization = enclosing.parameterSpecialization;
+		this.callSuper = enclosing.callSuper;
+		this.docbuf = enclosing.docbuf;
+		assert(this !is enclosing);	/// huh?
+	}
+
+    Scope push()
+	{
+		//printf("Scope.push()\n");
+		Scope s = new Scope(this);
+		assert(this !is s);	/// huh?
+		return s;
+	}
+	
+    Scope push(ScopeDsymbol ss)
+	{
+		//printf("Scope.push(%s)\n", ss.toChars());
+		Scope s = push();
+		s.scopesym = ss;
+		return s;
+	}
+	
+    Scope pop()
+	{
+		//printf("Scope.pop() %p nofree = %d\n", this, nofree);
+		Scope enc = enclosing;
+
+		if (enclosing)
+			enclosing.callSuper |= callSuper;
+
+		if (!nofree)
+		{
+			enclosing = freelist;
+			freelist = this;
+			flags |= SCOPE.SCOPEfree;
+		}
+
+		return enc;
+	}
+
+    void mergeCallSuper(Loc loc, uint cs)
+	{
+		// This does a primitive flow analysis to support the restrictions
+		// regarding when and how constructors can appear.
+		// It merges the results of two paths.
+		// The two paths are callSuper and cs; the result is merged into callSuper.
+
+		if (cs != callSuper)
+		{	
+			int a;
+			int b;
+
+			callSuper |= cs & (CSX.CSXany_ctor | CSX.CSXlabel);
+			if (cs & CSX.CSXreturn)
+			{
+				;
+			}
+			else if (callSuper & CSX.CSXreturn)
+			{
+				callSuper = cs | (callSuper & (CSX.CSXany_ctor | CSX.CSXlabel));
+			}
+			else
+			{
+				a = (cs        & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0;
+				b = (callSuper & (CSX.CSXthis_ctor | CSX.CSXsuper_ctor)) != 0;
+
+				if (a != b)
+					error(loc, "one path skips constructor");
+				callSuper |= cs;
+			}
+		}
+	}
+
+    Dsymbol search(Loc loc, Identifier ident, Dsymbol* pscopesym)
+	{
+		Dsymbol s;
+		Scope sc;
+
+		//printf("Scope.search(%p, '%s')\n", this, ident.toChars());
+		if (ident is Id.empty)
+		{
+			// Look for module scope
+			for (sc = this; sc; sc = sc.enclosing)
+			{
+				assert(sc != sc.enclosing);
+				if (sc.scopesym)
+				{
+				s = sc.scopesym.isModule();
+				if (s)
+				{
+					//printf("\tfound %s.%s\n", s.parent ? s.parent.toChars() : "", s.toChars());
+					if (pscopesym)
+					*pscopesym = sc.scopesym;
+					return s;
+				}
+				}
+			}
+			return null;
+			}
+
+			for (sc = this; sc; sc = sc.enclosing)
+			{
+			assert(sc != sc.enclosing);
+			if (sc.scopesym)
+			{
+				//printf("\tlooking in scopesym '%s', kind = '%s'\n", sc.scopesym.toChars(), sc.scopesym.kind());
+				s = sc.scopesym.search(loc, ident, 0);
+				if (s)
+				{
+				if ((global.params.warnings ||
+					global.params.Dversion > 1) &&
+					ident == Id.length &&
+					sc.scopesym.isArrayScopeSymbol() &&
+					sc.enclosing &&
+					sc.enclosing.search(loc, ident, null))
+				{
+					warning(s.loc, "array 'length' hides other 'length' name in outer scope");
+				}
+
+				//printf("\tfound %s.%s, kind = '%s'\n", s.parent ? s.parent.toChars() : "", s.toChars(), s.kind());
+				if (pscopesym)
+					*pscopesym = sc.scopesym;
+				return s;
+				}
+			}
+		}
+
+		return null;
+	}
+	
+    Dsymbol insert(Dsymbol s)
+	{
+		for (Scope sc = this; sc; sc = sc.enclosing)
+		{
+			//printf("\tsc = %p\n", sc);
+			if (sc.scopesym)
+			{
+				//printf("\t\tsc.scopesym = %p\n", sc.scopesym);
+				if (!sc.scopesym.symtab)
+					sc.scopesym.symtab = new DsymbolTable();
+
+				return sc.scopesym.symtab.insert(s);
+			}
+		}
+
+		assert(false);
+	}
+
+    ClassDeclaration getClassScope()
+	{
+		assert(false);
+	}
+	
+	/********************************************
+	 * Search enclosing scopes for ClassDeclaration.
+	 */
+    AggregateDeclaration getStructClassScope()
+	{
+		for (Scope sc = this; sc; sc = sc.enclosing)
+		{
+			AggregateDeclaration ad;
+			
+			if (sc.scopesym)
+			{
+				ad = sc.scopesym.isClassDeclaration();
+				if (ad)
+					return ad;
+				else
+				{	
+					ad = sc.scopesym.isStructDeclaration();
+					if (ad)
+						return ad;
+				}
+			}
+		}
+
+		return null;
+	}
+	
+    void setNoFree()
+	{
+		//int i = 0;
+
+		//printf("Scope.setNoFree(this = %p)\n", this);
+		for (Scope sc = this; sc; sc = sc.enclosing)
+		{
+			//printf("\tsc = %p\n", sc);
+			sc.nofree = 1;
+
+			assert(!(flags & SCOPE.SCOPEfree));
+			//assert(sc != sc.enclosing);
+			//assert(!sc.enclosing || sc != sc.enclosing.enclosing);
+			//if (++i == 10)
+				//assert(0);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ScopeDsymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,271 @@
+module dmd.ScopeDsymbol;
+
+import dmd.Dsymbol;
+import dmd.Declaration;
+import dmd.Array;
+import dmd.OverloadSet;
+import dmd.Import;
+import dmd.DsymbolTable;
+import dmd.Identifier;
+import dmd.Loc;
+import dmd.PROT;
+import dmd.FuncDeclaration;
+import dmd.Scope;
+import dmd.Util;
+import dmd.Id;
+import dmd.expression.Util;
+
+import core.stdc.stdlib;
+
+class ScopeDsymbol : Dsymbol
+{
+    Array members;		// all Dsymbol's in this scope
+    DsymbolTable symtab;	// members[] sorted into table
+
+    Array imports;		// imported ScopeDsymbol's
+    PROT* prots;	// array of PROT, one for each import
+
+    this()
+	{
+		// do nothing
+	}
+	
+    this(Identifier id)
+	{
+		super(id);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		//printf("%s.ScopeDsymbol.search(ident='%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
+		//if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
+
+		// Look in symbols declared in this module
+		Dsymbol s = symtab ? symtab.lookup(ident) : null;
+		
+		if (s)
+		{
+			//printf("\ts = '%s.%s'\n",toChars(),s.toChars());
+		}
+		else if (imports)
+		{
+			OverloadSet a = null;
+
+			// Look in imported modules
+			for (int i = 0; i < imports.dim; i++)
+			{   
+				ScopeDsymbol ss = cast(ScopeDsymbol)imports.data[i];
+				Dsymbol s2;
+
+				// If private import, don't search it
+				if (flags & 1 && prots[i] == PROT.PROTprivate)
+					continue;
+
+				//printf("\tscanning import '%s', prots = %d, isModule = %p, isImport = %p\n", ss.toChars(), prots[i], ss.isModule(), ss.isImport());
+				/* Don't find private members if ss is a module
+				 */
+				s2 = ss.search(loc, ident, ss.isModule() ? 1 : 0);
+				if (!s)
+					s = s2;
+				else if (s2 && s != s2)
+				{
+				if (s.toAlias() == s2.toAlias())
+				{
+					/* After following aliases, we found the same symbol,
+					 * so it's not an ambiguity.
+					 * But if one alias is deprecated, prefer the other.
+					 */
+					if (s.isDeprecated())
+					s = s2;
+				}
+				else
+				{
+					/* Two imports of the same module should be regarded as
+					 * the same.
+					 */
+					Import i1 = s.isImport();
+					Import i2 = s2.isImport();
+					if (!(i1 && i2 &&
+					  (i1.mod == i2.mod ||
+					   (!i1.parent.isImport() && !i2.parent.isImport() &&
+						i1.ident.equals(i2.ident))
+					  )
+					 )
+					   )
+					{
+					/* If both s2 and s are overloadable (though we only
+					 * need to check s once)
+					 */
+					if (s2.isOverloadable() && (a || s.isOverloadable()))
+					{   if (!a)
+						a = new OverloadSet();
+						/* Don't add to a[] if s2 is alias of previous sym
+						 */
+						for (int j = 0; j < a.a.dim; j++)
+						{	
+							Dsymbol s3 = cast(Dsymbol)a.a.data[j];
+							if (s2.toAlias() == s3.toAlias())
+							{
+								if (s3.isDeprecated())
+									a.a.data[j] = cast(void*)s2;
+								goto Lcontinue;
+							}
+						}
+						a.push(s2);
+					Lcontinue:
+						continue;
+					}
+					if (flags & 4)		// if return null on ambiguity
+						return null;
+					if (!(flags & 2))
+						ss.multiplyDefined(loc, s, s2);
+					break;
+					}
+				}
+				}
+			}
+
+			/* Build special symbol if we had multiple finds
+			 */
+			if (a)
+			{
+				assert(s);
+				a.push(s);
+				s = a;
+			}
+
+			if (s)
+			{
+				Declaration d = s.isDeclaration();
+				if (d && d.protection == PROT.PROTprivate && !d.parent.isTemplateMixin() && !(flags & 2))
+					error("%s is private", d.toPrettyChars());
+			}
+		}
+		return s;
+	}
+	
+    void importScope(ScopeDsymbol s, PROT protection)
+	{
+		//printf("%s.ScopeDsymbol.importScope(%s, %d)\n", toChars(), s.toChars(), protection);
+
+		// No circular or redundant import's
+		if (s != this)
+		{
+			if (!imports)
+				imports = new Array();
+			else
+			{
+				for (int i = 0; i < imports.dim; i++)
+				{   
+					ScopeDsymbol ss = cast(ScopeDsymbol)imports.data[i];
+					if (ss is s)			// if already imported
+					{
+						if (protection > prots[i])
+							prots[i] = protection;	// upgrade access
+						return;
+					}
+				}
+			}
+			imports.push(cast(void*)s);
+			prots = cast(PROT*)realloc(prots, imports.dim * prots[0].sizeof);
+			prots[imports.dim - 1] = protection;
+		}
+	}
+
+    int isforwardRef()
+	{
+		assert(false);
+	}
+	
+    void defineRef(Dsymbol s)
+	{
+		assert(false);
+	}
+
+    static void multiplyDefined(Loc loc, Dsymbol s1, Dsymbol s2)
+	{
+static if (false) {
+		printf("ScopeDsymbol::multiplyDefined()\n");
+		printf("s1 = %p, '%s' kind = '%s', parent = %s\n", s1, s1.toChars(), s1.kind(), s1.parent ? s1.parent.toChars() : "");
+		printf("s2 = %p, '%s' kind = '%s', parent = %s\n", s2, s2.toChars(), s2.kind(), s2.parent ? s2.parent.toChars() : "");
+}
+		if (loc.filename)
+		{
+			.error(loc, "%s at %s conflicts with %s at %s",
+			s1.toPrettyChars(),
+			s1.locToChars(),
+			s2.toPrettyChars(),
+			s2.locToChars());
+		}
+		else
+		{
+			s1.error(loc, "conflicts with %s %s at %s", s2.kind(), s2.toPrettyChars(), s2.locToChars());
+		}
+	}
+
+    Dsymbol nameCollision(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+
+	/*******************************************
+	 * Look for member of the form:
+	 *	const(MemberInfo)[] getMembers(string);
+	 * Returns NULL if not found
+	 */
+    FuncDeclaration findGetMembers()
+	{
+		Dsymbol s = search_function(this, Id.getmembers);
+		FuncDeclaration fdx = s ? s.isFuncDeclaration() : null;
+
+static if (false) {  // Finish
+		static __gshared TypeFunction tfgetmembers;
+
+		if (!tfgetmembers)
+		{
+			Scope sc;
+			Arguments arguments = new Arguments();
+			Arguments arg = new Argument(STCin, Type.tchar.constOf().arrayOf(), null, null);
+			arguments.push(arg);
+
+			Type tret = null;
+			tfgetmembers = new TypeFunction(arguments, tret, 0, LINK.LINKd);
+			tfgetmembers = cast(TypeFunction)tfgetmembers.semantic(0, &sc);
+		}
+		if (fdx)
+			fdx = fdx.overloadExactMatch(tfgetmembers);
+}
+		if (fdx && fdx.isVirtual()) {
+			fdx = null;
+		}
+
+		return fdx;
+	}
+
+    void emitMemberComments(Scope sc)
+	{
+		assert(false);
+	}
+
+    static size_t dim(Array members)
+	{
+		assert(false);
+	}
+	
+    static Dsymbol getNth(Array members, size_t nth, size_t* pn = null)
+	{
+		assert(false);
+	}
+
+    ScopeDsymbol isScopeDsymbol() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ScopeExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,110 @@
+module dmd.ScopeExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.TemplateInstance;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.Global;
+import dmd.Dsymbol;
+import dmd.VarExp;
+import dmd.DotVarExp;
+import dmd.DsymbolExp;
+import dmd.Type;
+
+class ScopeExp : Expression
+{
+	ScopeDsymbol sds;
+
+	this(Loc loc, ScopeDsymbol pkg)
+	{
+		super(loc, TOK.TOKimport, ScopeExp.sizeof);
+		//printf("ScopeExp.ScopeExp(pkg = '%s')\n", pkg.toChars());
+		//static int count; if (++count == 38) *(char*)0=0;
+		this.sds = pkg;
+	}
+
+	Expression syntaxCopy()
+	{
+		ScopeExp se = new ScopeExp(loc, cast(ScopeDsymbol)sds.syntaxCopy(null));
+		return se;
+	}
+
+	Expression semantic(Scope sc)
+	{
+		TemplateInstance ti;
+		ScopeDsymbol sds2;
+
+	version (LOGSEMANTIC) {
+		printf("+ScopeExp.semantic('%s')\n", toChars());
+	}
+	Lagain:
+		ti = sds.isTemplateInstance();
+		if (ti && !global.errors)
+		{
+			Dsymbol s;
+			if (!ti.semanticRun)
+				ti.semantic(sc);
+			s = ti.inst.toAlias();
+			sds2 = s.isScopeDsymbol();
+			if (!sds2)
+			{   
+				Expression e;
+
+				//printf("s = %s, '%s'\n", s.kind(), s.toChars());
+				if (ti.withsym)
+				{
+					// Same as wthis.s
+					e = new VarExp(loc, ti.withsym.withstate.wthis);
+					e = new DotVarExp(loc, e, s.isDeclaration());
+				}
+				else
+					e = new DsymbolExp(loc, s);
+
+				e = e.semantic(sc);
+				//printf("-1ScopeExp.semantic()\n");
+				return e;
+			}
+			if (sds2 != sds)
+			{
+				sds = sds2;
+				goto Lagain;
+			}
+			//printf("sds = %s, '%s'\n", sds.kind(), sds.toChars());
+		}
+		else
+		{
+			//printf("sds = %s, '%s'\n", sds.kind(), sds.toChars());
+			//printf("\tparent = '%s'\n", sds.parent.toChars());
+			sds.semantic(sc);
+		}
+		type = Type.tvoid;
+		//printf("-2ScopeExp.semantic() %s\n", toChars());
+		return this;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		if (sds.isTemplateInstance())
+		{
+			sds.toCBuffer(buf, hgs);
+		}
+		else
+		{
+			buf.writestring(sds.kind());
+			buf.writestring(" ");
+			buf.writestring(sds.toChars());
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ScopeStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,153 @@
+module dmd.ScopeStatement;
+
+import dmd.Statement;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.InlineScanState;
+import dmd.ScopeDsymbol;
+import dmd.ArrayTypes;
+import dmd.CompoundStatement;
+import dmd.IRState;
+import dmd.BE;
+
+import dmd.backend.Blockx;
+import dmd.backend.BC;
+import dmd.backend.Util;
+
+class ScopeStatement : Statement
+{
+    Statement statement;
+
+    this(Loc loc, Statement s)
+	{
+		super(loc);
+		this.statement = s;
+	}
+	
+    Statement syntaxCopy()
+	{
+		Statement s = statement ? statement.syntaxCopy() : null;
+		s = new ScopeStatement(loc, s);
+		return s;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writeByte('{');
+		buf.writenl();
+
+		if (statement)
+			statement.toCBuffer(buf, hgs);
+
+		buf.writeByte('}');
+		buf.writenl();
+	}
+	
+    ScopeStatement isScopeStatement() { return this; }
+	
+    Statement semantic(Scope sc)
+	{
+		ScopeDsymbol sym;
+
+		//printf("ScopeStatement.semantic(sc = %p)\n", sc);
+		if (statement)
+		{	
+			Statements a;
+
+			sym = new ScopeDsymbol();
+			sym.parent = sc.scopesym;
+			sc = sc.push(sym);
+
+			a = statement.flatten(sc);
+			if (a)
+			{
+				statement = new CompoundStatement(loc, a);
+			}
+
+			statement = statement.semantic(sc);
+			if (statement)
+			{
+				Statement sentry;
+				Statement sexception;
+				Statement sfinally;
+
+				statement.scopeCode(sc, &sentry, &sexception, &sfinally);
+				if (sfinally)
+				{
+					//printf("adding sfinally\n");
+					statement = new CompoundStatement(loc, statement, sfinally);
+				}
+			}
+
+			sc.pop();
+		}
+		return this;
+	}
+	
+    bool hasBreak()
+	{
+		//printf("ScopeStatement.hasBreak() %s\n", toChars());
+		return statement ? statement.hasBreak() : false;
+	}
+	
+    bool hasContinue()
+	{
+		return statement ? statement.hasContinue() : false;
+	}
+	
+    bool usesEH()
+	{
+		return statement ? statement.usesEH() : false;
+	}
+	
+    BE blockExit()
+	{
+		//printf("ScopeStatement::blockExit(%p)\n", statement);
+		return statement ? statement.blockExit() : BE.BEfallthru;
+	}
+	
+    bool comeFrom()
+	{
+		//printf("ScopeStatement.comeFrom()\n");
+    return statement ? statement.comeFrom() : false;
+	}
+	
+    bool isEmpty()
+	{
+		//printf("ScopeStatement::isEmpty() %d\n", statement ? statement->isEmpty() : TRUE);
+		return statement ? statement.isEmpty() : true;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (statement)
+			statement = statement.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		if (statement)
+		{
+			Blockx* blx = irs.blx;
+			IRState mystate = IRState(irs,this);
+
+			if (mystate.prev.ident)
+				mystate.ident = mystate.prev.ident;
+
+			statement.toIR(&mystate);
+
+			if (mystate.breakBlock)
+				block_goto(blx, BC.BCgoto, mystate.breakBlock);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Section.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.Section;
+
+import dmd.DocComment;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+
+class Section
+{
+    ubyte* name;
+    uint namelen;
+
+    ubyte* body_;
+    uint bodylen;
+
+    int nooutput;
+
+    void write(DocComment dc, Scope sc, Dsymbol s, OutBuffer buf)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ShlAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,61 @@
+module dmd.ShlAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.Id;
+import dmd.Type;
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.expression.Util;
+
+class ShlAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKshlass, ShlAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		//printf("ShlAssignExp.semantic()\n");
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		e1 = e1.modifiableLvalue(sc, e1);
+		e1.checkScalar();
+		e1.checkNoBool();
+		type = e1.type;
+		typeCombine(sc);
+		e1.checkIntegral();
+		e2 = e2.checkIntegral();
+		e2 = e2.castTo(sc, Type.tshiftcnt);
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.shlass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs,OPshlass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ShlExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,82 @@
+module dmd.ShlExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Id;
+import dmd.Type;
+
+import dmd.expression.shift_optimize;
+import dmd.expression.Shl;
+
+import dmd.backend.OPER;
+
+class ShlExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKshl, ShlExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		//printf("ShlExp.semantic(), type = %p\n", type);
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+
+			if (e)
+				return e;
+
+			e1 = e1.checkIntegral();
+			e2 = e2.checkIntegral();
+			e1 = e1.integralPromotions(sc);
+			e2 = e2.castTo(sc, Type.tshiftcnt);
+			type = e1.type;
+		}
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("ShlExp::optimize(result = %d) %s\n", result, toChars());
+		return shift_optimize(result, this, &Shl);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.shl;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.shl_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPER.OPshl);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ShrAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,63 @@
+module dmd.ShrAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.Id;
+import dmd.TOK;
+import dmd.Type;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+
+import dmd.expression.Util;
+
+class ShrAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKshrass, ShrAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		e1 = e1.modifiableLvalue(sc, e1);
+		e1.checkScalar();
+		e1.checkNoBool();
+		type = e1.type;
+		typeCombine(sc);
+		e1.checkIntegral();
+		e2 = e2.checkIntegral();
+		e2 = e2.castTo(sc, Type.tshiftcnt);
+
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.shrass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPshrass);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ShrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,80 @@
+module dmd.ShrExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.Id;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+
+import dmd.expression.shift_optimize;
+import dmd.expression.Shr;
+
+class ShrExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKshr, ShrExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+			
+			if (e)
+				return e;
+
+			e1 = e1.checkIntegral();
+			e2 = e2.checkIntegral();
+			e1 = e1.integralPromotions(sc);
+			e2 = e2.castTo(sc, Type.tshiftcnt);
+			type = e1.type;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("ShrExp::optimize(result = %d) %s\n", result, toChars());
+		return shift_optimize(result, this, &Shr);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.shr;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.shr_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return toElemBin(irs, OPER.OPshr);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SliceExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,518 @@
+module dmd.SliceExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.InterState;
+import dmd.ScopeDsymbol;
+import dmd.WANT;
+import dmd.ArrayScopeSymbol;
+import dmd.CallExp;
+import dmd.DotIdExp;
+import dmd.Id;
+import dmd.expression.Util;
+import dmd.TypeTuple;
+import dmd.TupleExp;
+import dmd.TypeStruct;
+import dmd.TypeClass;
+import dmd.TY;
+import dmd.Type;
+import dmd.AggregateDeclaration;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.VarDeclaration;
+import dmd.ErrorExp;
+import dmd.TypeExp;
+import dmd.Argument;
+import dmd.ExpInitializer;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.ArrayTypes;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.TOK;
+import dmd.TypeSArray;
+import dmd.GlobalExpressions;
+import dmd.Global;
+import dmd.PREC;
+
+import dmd.expression.Slice;
+import dmd.expression.Util;
+
+import dmd.backend.Util;
+import dmd.backend.Symbol;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.codegen.Util;
+
+import core.stdc.string;
+
+class SliceExp : UnaExp
+{
+	Expression upr;		// null if implicit 0
+    Expression lwr;		// null if implicit [length - 1]
+
+	VarDeclaration lengthVar = null;
+
+	this(Loc loc, Expression e1, Expression lwr, Expression upr)
+	{
+		super(loc, TOK.TOKslice, SliceExp.sizeof, e1);
+		this.upr = upr;
+		this.lwr = lwr;
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		AggregateDeclaration ad;
+		//FuncDeclaration fd;
+		ScopeDsymbol sym;
+
+	version (LOGSEMANTIC) {
+		printf("SliceExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			return this;
+
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+
+		e = this;
+
+		Type t = e1.type.toBasetype();
+		if (t.ty == Tpointer)
+		{
+			if (!lwr || !upr)
+				error("need upper and lower bound to slice pointer");
+		}
+		else if (t.ty == Tarray)
+		{
+		}
+		else if (t.ty == Tsarray)
+		{
+		}
+		else if (t.ty == Tclass)
+		{
+			ad = (cast(TypeClass)t).sym;
+			goto L1;
+		}
+		else if (t.ty == Tstruct)
+		{
+			ad = (cast(TypeStruct)t).sym;
+
+		L1:
+			if (search_function(ad, Id.slice))
+			{
+				// Rewrite as e1.slice(lwr, upr)
+				e = new DotIdExp(loc, e1, Id.slice);
+
+				if (lwr)
+				{
+					assert(upr);
+					e = new CallExp(loc, e, lwr, upr);
+				}
+				else
+				{	
+					assert(!upr);
+					e = new CallExp(loc, e);
+				}
+				e = e.semantic(sc);
+				return e;
+			}
+			goto Lerror;
+		}
+		else if (t.ty == Ttuple)
+		{
+			if (!lwr && !upr)
+				return e1;
+			if (!lwr || !upr)
+			{   error("need upper and lower bound to slice tuple");
+				goto Lerror;
+			}
+		}
+		else
+			goto Lerror;
+
+		{
+			Scope sc2 = sc;
+			if (t.ty == Tsarray || t.ty == Tarray || t.ty == Ttuple)
+			{
+				sym = new ArrayScopeSymbol(sc, this);
+				sym.loc = loc;
+				sym.parent = sc.scopesym;
+				sc2 = sc.push(sym);
+			}
+
+			if (lwr)
+			{	
+				lwr = lwr.semantic(sc2);
+				lwr = resolveProperties(sc2, lwr);
+				lwr = lwr.implicitCastTo(sc2, Type.tsize_t);
+			}
+			if (upr)
+			{	
+				upr = upr.semantic(sc2);
+				upr = resolveProperties(sc2, upr);
+				upr = upr.implicitCastTo(sc2, Type.tsize_t);
+			}
+
+			if (sc2 != sc)
+				sc2.pop();
+		}
+
+		if (t.ty == Ttuple)
+		{
+			lwr = lwr.optimize(WANTvalue);
+			upr = upr.optimize(WANTvalue);
+			ulong i1 = lwr.toUInteger();
+			ulong i2 = upr.toUInteger();
+
+			size_t length;
+			TupleExp te;
+			TypeTuple tup;
+
+			if (e1.op == TOKtuple)		// slicing an expression tuple
+			{   
+				te = cast(TupleExp)e1;
+				length = te.exps.dim;
+			}
+			else if (e1.op == TOKtype)	// slicing a type tuple
+			{   
+				tup = cast(TypeTuple)t;
+				length = Argument.dim(tup.arguments);
+			}
+			else
+				assert(0);
+
+			if (i1 <= i2 && i2 <= length)
+			{   
+				size_t j1 = cast(size_t) i1;
+				size_t j2 = cast(size_t) i2;
+
+				if (e1.op == TOKtuple)
+				{	
+					Expressions exps = new Expressions;
+					exps.setDim(j2 - j1);
+					for (size_t i = 0; i < j2 - j1; i++)
+					{   
+						Expression e2 = cast(Expression)te.exps.data[j1 + i];
+						exps.data[i] = cast(void*)e2;
+					}
+					e = new TupleExp(loc, exps);
+				}
+				else
+				{	
+					Arguments args = new Arguments;
+					args.reserve(j2 - j1);
+					for (size_t i = j1; i < j2; i++)
+					{   
+						Argument arg = Argument.getNth(tup.arguments, i);
+						args.push(cast(void*)arg);
+					}
+					e = new TypeExp(e1.loc, new TypeTuple(args));
+				}
+				e = e.semantic(sc);
+			}
+			else
+			{
+				error("string slice [%ju .. %ju] is out of bounds", i1, i2);
+				e = new ErrorExp();
+			}
+			return e;
+		}
+
+		if (t.ty == Tarray)
+		{
+			type = e1.type;
+		}
+		else
+			type = t.nextOf().arrayOf();
+		return e;
+
+	Lerror:
+		string s;
+		if (t.ty == Tvoid)
+			s = e1.toChars();
+		else
+			s = t.toChars();
+		error("%s cannot be sliced with []", s);
+		e = new ErrorExp();
+		return e;
+	}
+
+	void checkEscape()
+	{
+		e1.checkEscape();
+	}
+
+version (DMDV2) {
+	int isLvalue()
+	{
+		return 1;
+	}
+}
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		return this;
+	}
+
+	Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		error("slice expression %s is not a modifiable lvalue", toChars());
+		return this;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		expToCBuffer(buf, hgs, e1, precedence[op]);
+		buf.writeByte('[');
+		if (upr || lwr)
+		{
+			if (lwr)
+				expToCBuffer(buf, hgs, lwr, PREC.PREC_assign);
+			else
+				buf.writeByte('0');
+			buf.writestring("..");
+			if (upr)
+				expToCBuffer(buf, hgs, upr, PREC.PREC_assign);
+			else
+				buf.writestring("length");		// BUG: should be array.length
+		}
+		buf.writeByte(']');
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("SliceExp::optimize(result = %d) %s\n", result, toChars());
+		e = this;
+		e1 = e1.optimize(WANTvalue | (result & WANTinterpret));
+		if (!lwr)
+		{	
+			if (e1.op == TOKstring)
+			{   
+				// Convert slice of string literal into dynamic array
+				Type t = e1.type.toBasetype();
+				if (t.nextOf())
+					e = e1.castTo(null, t.nextOf().arrayOf());
+			}
+			return e;
+		}
+		e1 = fromConstInitializer(result, e1);
+		lwr = lwr.optimize(WANTvalue | (result & WANTinterpret));
+		upr = upr.optimize(WANTvalue | (result & WANTinterpret));
+		e = Slice(type, e1, lwr, upr);
+		if (e is EXP_CANT_INTERPRET)
+			e = this;
+		//printf("-SliceExp::optimize() %s\n", e->toChars());
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	elem* 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 = cast(uint)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 = cast(TypeSArray)t1;
+					ulong length = tsa.dim.toInteger();
+
+					elength = el_long(TYuint, length);
+					goto L1;
+				}
+				else if (t1.ty == Tarray)
+				{
+					if (lengthVar)
+						elength = el_var(lengthVar.toSymbol());
+					else
+					{
+						elength = e;
+						e = el_same(&elength);
+						elength = el_una(OP64_32, TYuint, elength);
+					}
+					L1:
+					eupr2 = el_same(&eupr);
+					c1 = el_bin(OPle, TYint, eupr, elength);
+					eupr2.Ety = TYuint;			// make sure unsigned comparison
+					c2 = el_bin(OPle, TYint, elwr2, eupr2);
+					c1 = el_bin(OPandand, TYint, c1, c2);	// (c1 && c2)
+
+					L2:
+					// Construct: (c1 || ModuleArray(line))
+					Symbol* sassert;
+
+					sassert = irs.blx.module_.toModuleArray();
+					ea = el_bin(OPcall,TYvoid,el_var(sassert), el_long(TYint, loc.linnum));
+					eb = el_bin(OPoror,TYvoid,c1,ea);
+					elwr = el_combine(elwr, eb);
+
+					elwr2 = el_copytree(elwr2);
+					eupr = el_copytree(eupr2);
+				}
+			}
+
+			eptr = array_toPtr(e1.type, e);
+
+			elem *elength = el_bin(OPmin, TYint, eupr, elwr2);
+			eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz)));
+
+			e = el_pair(TYullong, elength, eptr);
+			e = el_combine(elwr, e);
+			e = el_combine(einit, e);
+		}
+		else if (t1.ty == Tsarray)
+		{
+			e = sarray_toDarray(loc, t1, null, e);
+		}
+
+		el_setLoc(e,loc);
+		return e;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		int cost = 1 + e1.inlineCost(ics);
+		if (lwr)
+			cost += lwr.inlineCost(ics);
+		if (upr)
+			cost += upr.inlineCost(ics);
+		return cost;
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		SliceExp are = cast(SliceExp)copy();
+
+		are.e1 = e1.doInline(ids);
+
+		if (lengthVar)
+		{	
+			//printf("lengthVar\n");
+			VarDeclaration vd = lengthVar;
+			ExpInitializer ie;
+			ExpInitializer ieto;
+			VarDeclaration vto;
+
+			vto = new VarDeclaration(vd.loc, vd.type, vd.ident, vd.init);
+			///*vto = *vd;
+			memcpy(cast(void*)vto, cast(void*)vd, VarDeclaration.classinfo.init.length);
+			
+			vto.parent = ids.parent;
+			vto.csym = null;
+			vto.isym = null;
+
+			ids.from.push(cast(void*)vd);
+			ids.to.push(cast(void*)vto);
+
+			if (vd.init)
+			{
+				ie = vd.init.isExpInitializer();
+				assert(ie);
+				ieto = new ExpInitializer(ie.loc, ie.exp.doInline(ids));
+				vto.init = ieto;
+			}
+
+			are.lengthVar = vto;
+		}
+
+		if (lwr)
+			are.lwr = lwr.doInline(ids);
+		if (upr)
+			are.upr = upr.doInline(ids);
+		return are;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		e1 = e1.inlineScan(iss);
+		if (lwr)
+			lwr = lwr.inlineScan(iss);
+		if (upr)
+			upr = upr.inlineScan(iss);
+		return this;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Statement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,193 @@
+module dmd.Statement;
+
+import dmd.TryCatchStatement;
+import dmd.GotoStatement;
+import dmd.AsmStatement;
+import dmd.ScopeStatement;
+import dmd.DeclarationStatement;
+import dmd.CompoundStatement;
+import dmd.ReturnStatement;
+import dmd.IfStatement;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ArrayTypes;
+import dmd.Expression;
+import dmd.InterState;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.BE;
+import dmd.Global;
+import dmd.Util;
+
+class Statement
+{
+    Loc loc;
+
+    this(Loc loc)
+	{
+		this.loc = loc;
+	}
+
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+
+    void print()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		assert(false);
+	}
+
+    void error(T...)(string format, T t)
+	{
+		assert(false);
+	}
+	
+    void warning(T...)(string format, T t)
+	{
+		if (global.params.warnings && !global.gag)
+		{
+			writef("warning - ");
+			.error(loc, format, t);
+		}
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    TryCatchStatement isTryCatchStatement() { return null; }
+
+    GotoStatement isGotoStatement() { return null; }
+
+    AsmStatement isAsmStatement() { return null; }
+
+version (_DH) {
+    int incontract;
+}
+    ScopeStatement isScopeStatement() { return null; }
+
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    Statement semanticScope(Scope sc, Statement sbreak, Statement scontinue)
+	{
+		Scope scd;
+		Statement s;
+
+		scd = sc.push();
+		if (sbreak)
+			scd.sbreak = sbreak;
+		if (scontinue)
+			scd.scontinue = scontinue;
+		s = semantic(scd);
+		scd.pop();
+		return s;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool hasContinue()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+	// true if statement 'comes from' somewhere else, like a goto
+    bool comeFrom()
+	{
+		//printf("Statement::comeFrom()\n");
+		return false;
+	}
+	
+	// Return TRUE if statement has no code in it
+    bool isEmpty()
+	{
+		//printf("Statement::isEmpty()\n");
+		return false;
+	}
+	
+	/****************************************
+	 * If this statement has code that needs to run in a finally clause
+	 * at the end of the current scope, return that code in the form of
+	 * a Statement.
+	 * Output:
+	 *	*sentry		code executed upon entry to the scope
+	 *	*sexception	code executed upon exit from the scope via exception
+	 *	*sfinally	code executed in finally block
+	 */
+    void scopeCode(Scope sc, Statement* sentry, Statement* sexception, Statement* sfinally)
+	{
+		//printf("Statement::scopeCode()\n");
+		//print();
+		*sentry = null;
+		*sexception = null;
+		*sfinally = null;
+	}
+	
+	/*********************************
+	 * Flatten out the scope by presenting the statement
+	 * as an array of statements.
+	 * Returns NULL if no flattening necessary.
+	 */
+    Statements flatten(Scope sc)
+	{
+		return null;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    int inlineCost(InlineCostState* ics)
+	{
+		return COST_MAX;		// default is we can't inline it
+	}
+	
+    Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+	
+    Statement inlineScan(InlineScanState* iss)
+	{
+		return this;
+	}
+	
+    // Back end
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+	
+    // Avoid dynamic_cast
+    DeclarationStatement isDeclarationStatement() { return null; }
+    CompoundStatement isCompoundStatement() { return null; }
+    ReturnStatement isReturnStatement() { return null; }
+    IfStatement isIfStatement() { return null; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StaticAssert.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,103 @@
+module dmd.StaticAssert;
+
+import dmd.Dsymbol;
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ScopeDsymbol;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Id;
+import dmd.WANT;
+import dmd.Global;
+import dmd.Util;
+
+class StaticAssert : Dsymbol
+{
+    Expression exp;
+    Expression msg;
+
+    this(Loc loc, Expression exp, Expression msg)
+	{
+		super(Id.empty);
+		
+		this.loc = loc;
+		this.exp = exp;
+		this.msg = msg;
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
+	{
+		return false;		// we didn't add anything
+	}
+	
+    void semantic(Scope sc)
+	{
+	}
+	
+    void semantic2(Scope sc)
+	{
+		Expression e;
+
+		//printf("StaticAssert::semantic2() %s\n", toChars());
+		e = exp.semantic(sc);
+		e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		if (e.isBool(false))
+		{
+			if (msg)
+			{   
+				HdrGenState hgs;
+				scope OutBuffer buf = new OutBuffer();
+
+				msg = msg.semantic(sc);
+				msg = msg.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+				hgs.console = 1;
+				msg.toCBuffer(buf, &hgs);
+				error("%s", buf.toChars());
+			}
+			else
+				error("(%s) is false", exp.toChars());
+
+			if(sc.tinst)
+				sc.tinst.printInstantiationTrace();
+
+			if (!global.gag) {
+				fatal();
+			}
+		}
+		else if (!e.isBool(true))
+		{
+			error("(%s) is not evaluatable at compile time", exp.toChars());
+		}
+	}
+	
+    void inlineScan()
+	{
+		assert(false);
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    void toObjFile(int multiobj)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		return "static assert";
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StaticAssertStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,35 @@
+module dmd.StaticAssertStatement;
+
+import dmd.Statement;
+import dmd.StaticAssert;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.Loc;
+
+class StaticAssertStatement : Statement
+{
+    StaticAssert sa;
+
+    this(StaticAssert sa)
+	{
+		super(sa.loc);
+		this.sa = sa;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		sa.semantic2(sc);
+		return null;
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StaticCtorDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,129 @@
+module dmd.StaticCtorDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.AggregateDeclaration;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+import dmd.Identifier;
+import dmd.TypeFunction;
+import dmd.Type;
+import dmd.LINK;
+import dmd.Lexer;
+import dmd.VarDeclaration;
+import dmd.ArrayTypes;
+import dmd.Expression;
+import dmd.Statement;
+import dmd.DeclarationStatement;
+import dmd.AddAssignExp;
+import dmd.EqualExp;
+import dmd.TOK;
+import dmd.IfStatement;
+import dmd.CompoundStatement;
+import dmd.Module;
+import dmd.IntegerExp;
+import dmd.ReturnStatement;
+import dmd.IdentifierExp;
+
+class StaticCtorDeclaration : FuncDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+		super(loc, endloc, Identifier.generateId("_staticCtor"), STCstatic, null);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("StaticCtorDeclaration.semantic()\n");
+
+		type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
+
+		/* If the static ctor appears within a template instantiation,
+		 * it could get called multiple times by the module constructors
+		 * for different modules. Thus, protect it with a gate.
+		 */
+		if (inTemplateInstance())
+		{
+			/* Add this prefix to the function:
+			 *	static int gate;
+			 *	if (++gate != 1) return;
+			 * Note that this is not thread safe; should not have threads
+			 * during static construction.
+			 */
+			Identifier id = Lexer.idPool("__gate");
+			VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null);
+			v.storage_class = STCstatic;
+			Statements sa = new Statements();
+			Statement s = new DeclarationStatement(Loc(0), v);
+			sa.push(cast(void*)s);
+			Expression e = new IdentifierExp(Loc(0), id);
+			e = new AddAssignExp(Loc(0), e, new IntegerExp(1));
+			e = new EqualExp(TOKnotequal, Loc(0), e, new IntegerExp(1));
+			s = new IfStatement(Loc(0), null, e, new ReturnStatement(Loc(0), null), null);
+			sa.push(cast(void*)s);
+			if (fbody)
+				sa.push(cast(void*)fbody);
+			fbody = new CompoundStatement(Loc(0), sa);
+		}
+
+		FuncDeclaration.semantic(sc);
+
+		// We're going to need ModuleInfo
+		Module m = getModule();
+		if (!m)
+			m = sc.module_;
+
+		if (m)
+		{	
+			m.needmoduleinfo = 1;
+	version (IN_GCC) {
+			m.strictlyneedmoduleinfo = 1;
+	}
+		}
+	}
+	
+    AggregateDeclaration isThis()
+	{
+		return null;
+	}
+	
+    bool isStaticConstructor()
+	{
+		return true;
+	}
+	
+    bool isVirtual()
+	{
+		return false;
+	}
+	
+    bool addPreInvariant()
+	{
+		return false;
+	}
+	
+    bool addPostInvariant()
+	{
+		return false;
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    StaticCtorDeclaration isStaticCtorDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StaticDtorDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,138 @@
+module dmd.StaticDtorDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.VarDeclaration;
+import dmd.Dsymbol;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.AggregateDeclaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+import dmd.Identifier;
+import dmd.ClassDeclaration;
+import dmd.Type;
+import dmd.TypeFunction;
+import dmd.LINK;
+import dmd.Lexer;
+import dmd.Statement;
+import dmd.Expression;
+import dmd.EqualExp;
+import dmd.ArrayTypes;
+import dmd.DeclarationStatement;
+import dmd.IdentifierExp;
+import dmd.AddAssignExp;
+import dmd.IntegerExp;
+import dmd.TOK;
+import dmd.IfStatement;
+import dmd.ReturnStatement;
+import dmd.CompoundStatement;
+import dmd.Module;
+
+class StaticDtorDeclaration : FuncDeclaration
+{
+	VarDeclaration vgate;	// 'gate' variable
+
+    this(Loc loc, Loc endloc)
+	{
+		super(loc, endloc, Identifier.generateId("_staticDtor"), STCstatic, null);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		ClassDeclaration cd;
+		Type tret;
+
+		cd = sc.scopesym.isClassDeclaration();
+		if (!cd)
+		{
+		}
+		type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd);
+
+		/* If the static ctor appears within a template instantiation,
+		 * it could get called multiple times by the module constructors
+		 * for different modules. Thus, protect it with a gate.
+		 */
+		if (inTemplateInstance())
+		{
+			/* Add this prefix to the function:
+			 *	static int gate;
+			 *	if (--gate != 0) return;
+			 * Increment gate during constructor execution.
+			 * Note that this is not thread safe; should not have threads
+			 * during static destruction.
+			 */
+			Identifier id = Lexer.idPool("__gate");
+			VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null);
+			v.storage_class = STCstatic;
+			Statements sa = new Statements();
+			Statement s = new DeclarationStatement(Loc(0), v);
+			sa.push(cast(void*)s);
+			Expression e = new IdentifierExp(Loc(0), id);
+			e = new AddAssignExp(Loc(0), e, new IntegerExp(-1));
+			e = new EqualExp(TOKnotequal, Loc(0), e, new IntegerExp(0));
+			s = new IfStatement(Loc(0), null, e, new ReturnStatement(Loc(0), null), null);
+			sa.push(cast(void*)s);
+			if (fbody)
+				sa.push(cast(void*)fbody);
+			fbody = new CompoundStatement(Loc(0), sa);
+			vgate = v;
+		}
+
+		FuncDeclaration.semantic(sc);
+
+		// We're going to need ModuleInfo
+		Module m = getModule();
+		if (!m)
+			m = sc.module_;
+		if (m)
+		{	
+			m.needmoduleinfo = 1;
+	version (IN_GCC) {
+			m.strictlyneedmoduleinfo = 1;
+	}
+		}
+	}
+	
+    AggregateDeclaration isThis()
+	{
+		return null;
+	}
+	
+    bool isStaticDestructor()
+	{
+		return true;
+	}
+	
+    bool isVirtual()
+	{
+		return false;
+	}
+	
+    bool addPreInvariant()
+	{
+		return false;
+	}
+	
+    bool addPostInvariant()
+	{
+		return false;
+	}
+	
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    StaticDtorDeclaration isStaticDtorDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StaticIfCondition.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,70 @@
+module dmd.StaticIfCondition;
+
+import dmd.Expression;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Condition;
+import dmd.HdrGenState;
+import dmd.WANT;
+import dmd.Util;
+
+class StaticIfCondition : Condition
+{
+	Expression exp;
+
+	this(Loc loc, Expression exp)
+	{
+		super(loc);
+		this.exp = exp;
+	}
+
+	Condition syntaxCopy()
+	{
+		assert(false);
+	}
+
+	bool include(Scope sc, ScopeDsymbol s)
+	{
+	static if (false) {
+		printf("StaticIfCondition.include(sc = %p, s = %p)\n", sc, s);
+		if (s)
+		{
+			printf("\ts = '%s', kind = %s\n", s.toChars(), s.kind());
+		}
+	}
+		if (inc == 0)
+		{
+			if (!sc)
+			{
+				error(loc, "static if conditional cannot be at global scope");
+				inc = 2;
+				return 0;
+			}
+
+			sc = sc.push(sc.scopesym);
+			sc.sd = s;			// s gets any addMember()
+			sc.flags |= SCOPE.SCOPEstaticif;
+			Expression e = exp.semantic(sc);
+			sc.pop();
+			e = e.optimize(WANTvalue | WANTinterpret);
+			if (e.isBool(true))
+				inc = 1;
+			else if (e.isBool(false))
+				inc = 2;
+			else
+			{
+				e.error("expression %s is not constant or does not evaluate to a bool", e.toChars());
+				inc = 2;
+			}
+		}
+		return (inc == 1);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StaticIfDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,78 @@
+module dmd.StaticIfDeclaration;
+
+import dmd.ConditionalDeclaration;
+import dmd.ScopeDsymbol;
+import dmd.AttribDeclaration;
+import dmd.Scope;
+import dmd.Condition;
+import dmd.Array;
+import dmd.Dsymbol;
+
+class StaticIfDeclaration : ConditionalDeclaration
+{
+    ScopeDsymbol sd;
+    int addisdone;
+
+    this(Condition condition, Array decl, Array elsedecl)
+	{
+		super(condition, decl, elsedecl);
+		//printf("StaticIfDeclaration::StaticIfDeclaration()\n");
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+
+    bool addMember(Scope sc, ScopeDsymbol sd, int memnum)
+	{
+		//printf("StaticIfDeclaration.addMember() '%s'\n",toChars());
+		/* This is deferred until semantic(), so that
+		 * expressions in the condition can refer to declarations
+		 * in the same scope, such as:
+		 *
+		 * template Foo(int i)
+		 * {
+		 *     const int j = i + 1;
+		 *     static if (j == 3)
+		 *         const int k;
+		 * }
+		 */
+		this.sd = sd;
+		bool m = false;
+
+		if (memnum == 0)
+		{	
+			m = AttribDeclaration.addMember(sc, sd, memnum);
+			addisdone = 1;
+		}
+		return m;
+	}
+	
+    void semantic(Scope sc)
+	{
+		Array d = include(sc, sd);
+
+		//printf("\tStaticIfDeclaration.semantic '%s', d = %p\n",toChars(), d);
+		if (d)
+		{
+			if (!addisdone)
+			{   
+				AttribDeclaration.addMember(sc, sd, 1);
+				addisdone = 1;
+			}
+
+			for (uint i = 0; i < d.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)d.data[i];
+
+				s.semantic(sc);
+			}
+		}
+	}
+
+    string kind()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StorageClassDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,124 @@
+module dmd.StorageClassDeclaration;
+
+import dmd.AttribDeclaration;
+import dmd.Array;
+import dmd.TOK;
+import dmd.Token;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.STC;
+
+class StorageClassDeclaration: AttribDeclaration
+{
+    STC stc;
+
+    this(STC stc, Array decl)
+	{
+		super(decl);
+		
+		this.stc = stc;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void setScope(Scope sc)
+	{
+		if (decl)
+		{
+			STC scstc = sc.stc;
+
+			/* These sets of storage classes are mutually exclusive,
+			 * so choose the innermost or most recent one.
+			 */
+			if (stc & (STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCextern | STC.STCmanifest))
+				scstc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCextern | STC.STCmanifest);
+			if (stc & (STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCtls | STC.STCmanifest | STC.STCgshared))
+				scstc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCtls | STC.STCmanifest | STC.STCgshared);
+			if (stc & (STC.STCconst | STC.STCimmutable | STC.STCmanifest))
+				scstc &= ~(STC.STCconst | STC.STCimmutable | STC.STCmanifest);
+			if (stc & (STC.STCgshared | STC.STCshared | STC.STCtls))
+				scstc &= ~(STC.STCgshared | STC.STCshared | STC.STCtls);
+			scstc |= stc;
+
+			setScopeNewSc(sc, scstc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign);
+		}
+	}
+	
+    void semantic(Scope sc)
+	{
+		if (decl)
+		{
+			STC scstc = sc.stc;
+
+			/* These sets of storage classes are mutually exclusive,
+			 * so choose the innermost or most recent one.
+			 */
+			if (stc & (STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCextern | STC.STCmanifest))
+				scstc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCextern | STC.STCmanifest);
+			if (stc & (STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCtls | STC.STCmanifest | STC.STCgshared))
+				scstc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCtls | STC.STCmanifest | STC.STCgshared);
+			if (stc & (STC.STCconst | STC.STCimmutable | STC.STCmanifest))
+				scstc &= ~(STC.STCconst | STC.STCimmutable | STC.STCmanifest);
+			if (stc & (STC.STCgshared | STC.STCshared | STC.STCtls))
+				scstc &= ~(STC.STCgshared | STC.STCshared | STC.STCtls);
+			scstc |= stc;
+
+			semanticNewSc(sc, scstc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign);
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    static void stcToCBuffer(OutBuffer buf, int stc)
+	{
+		struct SCstring
+		{
+			int stc;
+			TOK tok;
+		};
+
+		static SCstring[] table =
+		[
+			{ STCauto,         TOKauto },
+			{ STCscope,        TOKscope },
+			{ STCstatic,       TOKstatic },
+			{ STCextern,       TOKextern },
+			{ STCconst,        TOKconst },
+			{ STCfinal,        TOKfinal },
+			{ STCabstract,     TOKabstract },
+			{ STCsynchronized, TOKsynchronized },
+			{ STCdeprecated,   TOKdeprecated },
+			{ STCoverride,     TOKoverride },
+			{ STClazy,         TOKlazy },
+			{ STCalias,        TOKalias },
+			{ STCout,          TOKout },
+			{ STCin,           TOKin },
+///		version (DMDV2) {
+///			{ STCimmutable,    TOKimmutable },
+///			{ STCshared,       TOKshared },
+///			{ STCnothrow,      TOKnothrow },
+///			{ STCpure,         TOKpure },
+///			{ STCref,          TOKref },
+///			{ STCtls,          TOKtls },
+///			{ STCgshared,      TOKgshared },
+///		}
+		];
+
+		for (int i = 0; i < table.length; i++)
+		{
+			if (stc & table[i].stc)
+			{
+				buf.writestring(Token.toChars(table[i].tok));
+				buf.writeByte(' ');
+			}
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/String.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,90 @@
+module dmd.String;
+
+import dmd.Array;
+
+import core.stdc.string : strlen;
+import std.string : cmp;
+
+import std.stdio : writefln;
+
+class String
+{
+    string str;
+
+    this(string str)
+	{
+		this.str = str;
+	}
+
+    static hash_t calcHash(const(char)* str, size_t len)
+	{
+		hash_t hash = 0;
+
+		for (;;)
+		{
+			switch (len)
+			{
+				case 0:
+					return hash;
+
+				case 1:
+					hash *= 37;
+					hash += *cast(ubyte*)str;
+					return hash;
+
+				case 2:
+					hash *= 37;
+					hash += *cast(ushort*)str;
+					return hash;
+
+				case 3:
+					hash *= 37;
+					hash += (*(cast(ushort*)str) << 8) +
+						(cast(ubyte*)str)[2];
+					return hash;
+
+				default:
+					hash *= 37;
+					hash += *cast(uint*)str;
+					str += 4;
+					len -= 4;
+					break;
+			}
+		}
+	}
+	
+    static hash_t calcHash(string str)
+	{
+		return calcHash(str.ptr, str.length);
+	}
+	
+    hash_t hashCode()
+	{
+		return calcHash(str.ptr, str.length);
+	}
+    
+	uint len()
+	{
+		return str.length;
+	}
+
+    int equals(Object obj)
+	{
+		return str == (cast(String)obj).str;
+	}
+
+    int compare(Object obj)
+	{
+		return cmp(str, (cast(String)obj).str);
+	}
+	
+    string toChars()
+	{
+		return str;
+	}
+
+    void print()
+	{
+		writefln("String '%s'", str);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StringEntry.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.StringEntry;
+
+import dmd.StringValue;
+import dmd.Dchar;
+import dmd.Lstring;
+
+import core.stdc.stdlib;
+
+struct StringEntry
+{
+    StringEntry* left;
+    StringEntry* right;
+    hash_t hash;
+
+    StringValue value;
+
+	this(immutable(dchar_t)[] s)
+	{
+		hash = Dchar.calcHash(s.ptr, s.length);
+		value.lstring.string_ = s;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StringExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,669 @@
+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.stdc.string;
+
+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
+    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;
+		this.postfix = postfix;
+	}
+
+	int equals(Object o)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+		assert(false);
+	}
+
+	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());
+		}
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	size_t length()
+	{
+		assert(false);
+	}
+
+	StringExp toUTF8(Scope sc)
+	{
+		assert(false);
+	}
+
+	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;
+		}
+		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;
+}
+	}
+	
+	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*)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;
+	}
+
+	int compare(Object obj)
+	{
+		assert(false);
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	uint charAt(size_t i)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	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*)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);
+		}
+
+		return pdt;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StringTable.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,108 @@
+module dmd.StringTable;
+
+import dmd.StringValue;
+import dmd.StringEntry;
+import dmd.Dchar;
+
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class StringTable
+{
+    void** table;
+    uint count;
+    uint tabledim;
+
+    this(uint size = 37)
+	{
+		table = cast(void**)calloc(size, (void*).sizeof);
+		memset(table, 0, size * (void*).sizeof);
+		tabledim = size;
+		count = 0;
+	}
+	
+    ~this()
+	{
+		/// TODO: is it *really* needed?
+		// Zero out dangling pointers to help garbage collector.
+		// Should zero out StringEntry's too.
+		///for (uint i = 0; i < count; i++) {
+		///	table[i] = null;
+		///}
+
+		free(table);
+		//table = null;
+	}
+
+    StringValue* lookup(immutable(dchar_t)[] s)
+	{
+		StringEntry* se = *cast(StringEntry**)search(s);
+		if (se !is null)
+			return &se.value;
+		else
+			return null;
+	}
+	
+    StringValue* insert(immutable(dchar_t)[] s)
+	{
+		StringEntry** pse = cast(StringEntry**)search(s);
+		StringEntry* se = *pse;
+		if (se !is null)
+			return null;		// error: already in table
+		else
+		{
+			se = new StringEntry(s);
+			*pse = se;
+		}
+
+		return &se.value;
+	}
+	
+    StringValue* update(immutable(dchar_t)[] s)
+	{
+		StringEntry **pse;
+		StringEntry *se;
+
+		pse = cast(StringEntry**)search(s);
+		se = *pse;
+		if (se is null)			// not in table: so create new entry
+		{
+			se = new StringEntry(s);
+			*pse = se;
+		}
+		return &se.value;
+	}
+
+private:
+    void** search(immutable(dchar_t)[] s)
+	{
+		int cmp;
+
+		//printf("StringTable::search(%p,%d)\n",s,len);
+		hash_t hash = Dchar.calcHash(s.ptr, s.length);
+		uint u = hash % tabledim;
+		StringEntry** se = cast(StringEntry**)&table[u];
+		//printf("\thash = %d, u = %d\n",hash,u);
+		while (*se)
+		{
+			cmp = (*se).hash - hash;
+			if (cmp == 0)
+			{
+				cmp = (*se).value.lstring.len() - s.length;
+				if (cmp == 0)
+				{
+					cmp = Dchar.memcmp(s.ptr, (*se).value.lstring.toDchars().ptr, s.length);
+					if (cmp == 0)
+						break;
+				}
+			}
+			if (cmp < 0)
+				se = &(*se).left;
+			else
+				se = &(*se).right;
+		}
+
+		//printf("\treturn %p, %p\n",se, (*se));
+		return cast(void**)se;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StringValue.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,16 @@
+module dmd.StringValue;
+
+import dmd.Lstring;
+import dmd.Dchar;
+
+struct StringValue
+{
+    union
+    {
+		int intvalue = 0;
+		void* ptrvalue;
+		dchar_t* string_;
+    }
+
+    Lstring lstring;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StructDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,851 @@
+module dmd.StructDeclaration;
+
+import dmd.AggregateDeclaration;
+import dmd.FuncDeclaration;
+import dmd.DeclarationExp;
+import dmd.VoidInitializer;
+import dmd.Initializer;
+import dmd.ExpInitializer;
+import dmd.TOK;
+import dmd.Statement;
+import dmd.VarExp;
+import dmd.CompoundStatement;
+import dmd.AssignExp;
+import dmd.DotVarExp;
+import dmd.AddrExp;
+import dmd.CastExp;
+import dmd.PostBlitDeclaration;
+import dmd.Lexer;
+import dmd.ExpStatement;
+import dmd.DotIdExp;
+import dmd.TypeSArray;
+import dmd.ThisExp;
+import dmd.ThisDeclaration;
+import dmd.TypeFunction;
+import dmd.Argument;
+import dmd.Id;
+import dmd.TY;
+import dmd.LINK;
+import dmd.Type;
+import dmd.DsymbolTable;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.STC;
+import dmd.Identifier;
+import dmd.TemplateInstance;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.PROT;
+import dmd.TypeStruct;
+import dmd.expression.Util;
+import dmd.Expression;
+import dmd.IdentifierExp;
+import dmd.PtrExp;
+import dmd.CallExp;
+import dmd.ReturnStatement;
+import dmd.ScopeDsymbol;
+import dmd.Module;
+import dmd.VarDeclaration;
+import dmd.InvariantDeclaration;
+import dmd.NewDeclaration;
+import dmd.DeleteDeclaration;
+import dmd.Global;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.SC;
+import dmd.backend.DT;
+import dmd.backend.FL;
+import dmd.backend.glue;
+
+class StructDeclaration : AggregateDeclaration
+{
+    bool zeroInit;		// true if initialize with 0 fill
+	
+version (DMDV2) {
+    int hasIdentityAssign;	// !=0 if has identity opAssign
+    FuncDeclaration cpctor;	// generated copy-constructor, if any
+
+    FuncDeclarations postblits;	// Array of postblit functions
+    FuncDeclaration postblit;	// aggregate postblit
+}
+
+    this(Loc loc, Identifier id)
+	{
+		super(loc, id);
+
+		// For forward references
+		type = new TypeStruct(this);
+		
+		postblits = new FuncDeclarations(); ///
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		int i;
+		Scope sc2;
+
+		//printf("+StructDeclaration.semantic(this=%p, '%s')\n", this, toChars());
+
+		//static int count; if (++count == 20) *(char*)0=0;
+
+		assert(type);
+		if (!members)			// if forward reference
+		return;
+
+		if (symtab)
+		{   if (!scope_)
+				return;             // semantic() already completed
+		}
+		else
+			symtab = new DsymbolTable();
+
+		Scope scx = null;
+		if (scope_)
+		{   sc = scope_;
+			scx = scope_;            // save so we don't make redundant copies
+			scope_ = null;
+		}
+
+		parent = sc.parent;
+		type = type.semantic(loc, sc);
+version (STRUCTTHISREF) {
+		handle = type;
+} else {
+		handle = type.pointerTo();
+}
+		structalign = sc.structalign;
+		protection = sc.protection;
+		storage_class |= sc.stc;
+		if (sc.stc & STC.STCdeprecated)
+		isdeprecated = 1;
+		assert(!isAnonymous());
+		if (sc.stc & STC.STCabstract)
+		error("structs, unions cannot be abstract");
+version (DMDV2) {
+		if (storage_class & STC.STCimmutable)
+			type = type.invariantOf();
+		else if (storage_class & STC.STCconst)
+			type = type.constOf();
+		else if (storage_class & STC.STCshared)
+			type = type.sharedOf();
+}
+
+		if (sizeok == 0)		// if not already done the addMember step
+		{
+		int hasfunctions = 0;
+		for (i = 0; i < members.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+			//printf("adding member '%s' to '%s'\n", s.toChars(), this.toChars());
+			s.addMember(sc, this, 1);
+			if (s.isFuncDeclaration())
+			hasfunctions = 1;
+		}
+
+		// If nested struct, add in hidden 'this' pointer to outer scope
+		if (hasfunctions && !(storage_class & STC.STCstatic))
+			{   Dsymbol s = toParent2();
+				if (s)
+				{
+					AggregateDeclaration ad = s.isAggregateDeclaration();
+					FuncDeclaration fd = s.isFuncDeclaration();
+
+			TemplateInstance ti;
+					if (ad && (ti = ad.parent.isTemplateInstance()) !is null && ti.isnested || fd)
+					{   isnested = true;
+						Type t;
+						if (ad)
+							t = ad.handle;
+						else if (fd)
+						{   
+							AggregateDeclaration add = fd.isMember2();
+							if (add)
+								t = add.handle;
+							else
+								t = Type.tvoidptr;
+						}
+						else
+							assert(0);
+				if (t.ty == TY.Tstruct)
+				t = Type.tvoidptr;	// t should not be a ref type
+						assert(!vthis);
+						vthis = new ThisDeclaration(loc, t);
+				//vthis.storage_class |= STC.STCref;
+						members.push(cast(void*)vthis);
+					}
+				}
+			}
+		}
+
+		sizeok = 0;
+		sc2 = sc.push(this);
+		sc2.stc &= storage_class & STC.STC_TYPECTOR;
+		sc2.parent = this;
+		if (isUnionDeclaration())
+		sc2.inunion = 1;
+		sc2.protection = PROT.PROTpublic;
+		sc2.explicitProtection = 0;
+
+		int members_dim = members.dim;
+		for (i = 0; i < members_dim; i++)
+		{
+		Dsymbol s = cast(Dsymbol)members.data[i];
+		s.semantic(sc2);
+		if (isUnionDeclaration())
+			sc2.offset = 0;
+static if (false) {
+		if (sizeok == 2)
+		{   //printf("forward reference\n");
+			break;
+		}
+}
+		Type t;
+		if (s.isDeclaration() &&
+			(t = s.isDeclaration().type) !is null &&
+			t.toBasetype().ty == TY.Tstruct)
+		{   StructDeclaration sd = cast(StructDeclaration)t.toDsymbol(sc);
+			if (sd.isnested)
+			error("inner struct %s cannot be a field", sd.toChars());
+		}
+		}
+
+		/* The TypeInfo_Struct is expecting an opEquals and opCmp with
+		 * a parameter that is a pointer to the struct. But if there
+		 * isn't one, but is an opEquals or opCmp with a value, write
+		 * another that is a shell around the value:
+		 *	int opCmp(struct *p) { return opCmp(*p); }
+		 */
+
+		TypeFunction tfeqptr;
+		{
+		Arguments arguments = new Arguments;
+		Argument arg = new Argument(STC.STCin, handle, Id.p, null);
+
+		arguments.push(cast(void*)arg);
+		tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd);
+		tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc);
+		}
+
+		TypeFunction tfeq;
+		{
+		Arguments arguments = new Arguments;
+		Argument arg = new Argument(STC.STCin, type, null, null);
+
+		arguments.push(cast(void*)arg);
+		tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd);
+		tfeq = cast(TypeFunction)tfeq.semantic(Loc(0), sc);
+		}
+
+		Identifier id = Id.eq;
+		for (int j = 0; j < 2; j++)
+		{
+			Dsymbol s = search_function(this, id);
+			FuncDeclaration fdx = s ? s.isFuncDeclaration() : null;
+			if (fdx)
+			{   FuncDeclaration fd = fdx.overloadExactMatch(tfeqptr);
+				if (!fd)
+				{	fd = fdx.overloadExactMatch(tfeq);
+				if (fd)
+				{   // Create the thunk, fdptr
+					FuncDeclaration fdptr = new FuncDeclaration(loc, loc, fdx.ident, STC.STCundefined, tfeqptr);
+					Expression e = new IdentifierExp(loc, Id.p);
+					e = new PtrExp(loc, e);
+					Expressions args = new Expressions();
+					args.push(cast(void*)e);
+					e = new IdentifierExp(loc, id);
+					e = new CallExp(loc, e, args);
+					fdptr.fbody = new ReturnStatement(loc, e);
+					ScopeDsymbol ss = fdx.parent.isScopeDsymbol();
+					assert(ss);
+					ss.members.push(cast(void*)fdptr);
+					fdptr.addMember(sc, ss, 1);
+					fdptr.semantic(sc2);
+				}
+				}
+			}
+
+			id = Id.cmp;
+		}
+version (DMDV2) {
+		dtor = buildDtor(sc2);
+		postblit = buildPostBlit(sc2);
+		cpctor = buildCpCtor(sc2);
+		buildOpAssign(sc2);
+}
+
+		sc2.pop();
+
+		if (sizeok == 2)
+		{	// semantic() failed because of forward references.
+		// Unwind what we did, and defer it for later
+		fields.setDim(0);
+		structsize = 0;
+		alignsize = 0;
+		structalign = 0;
+
+		scope_ = scx ? scx : new Scope(sc);
+		scope_.setNoFree();
+		scope_.module_.addDeferredSemantic(this);
+		//printf("\tdeferring %s\n", toChars());
+		return;
+		}
+
+		// 0 sized struct's are set to 1 byte
+		if (structsize == 0)
+		{
+		structsize = 1;
+		alignsize = 1;
+		}
+
+		// Round struct size up to next alignsize boundary.
+		// This will ensure that arrays of structs will get their internals
+		// aligned properly.
+		structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
+
+		sizeok = 1;
+		Module.dprogress++;
+
+		//printf("-StructDeclaration.semantic(this=%p, '%s')\n", this, toChars());
+
+		// Determine if struct is all zeros or not
+		zeroInit = true;
+		for (i = 0; i < fields.dim; i++)
+		{
+		Dsymbol s = cast(Dsymbol)fields.data[i];
+		VarDeclaration vd = s.isVarDeclaration();
+		if (vd && !vd.isDataseg())
+		{
+			if (vd.init)
+			{
+			// Should examine init to see if it is really all 0's
+			zeroInit = false;
+			break;
+			}
+			else
+			{
+			if (!vd.type.isZeroInit(loc))
+			{
+				zeroInit = false;
+				break;
+			}
+			}
+		}
+		}
+
+		/* Look for special member functions.
+		 */
+version (DMDV2) {
+		ctor = search(Loc(0), Id.ctor, 0);
+}
+		inv =    cast(InvariantDeclaration)search(Loc(0), Id.classInvariant, 0);
+		aggNew =       cast(NewDeclaration)search(Loc(0), Id.classNew,       0);
+		aggDelete = cast(DeleteDeclaration)search(Loc(0), Id.classDelete,    0);
+
+		if (sc.func)
+		{
+		semantic2(sc);
+		semantic3(sc);
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string mangle()
+	{
+		//printf("StructDeclaration.mangle() '%s'\n", toChars());
+		return Dsymbol.mangle();
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+	/*******************************************
+	 * We need an opAssign for the struct if
+	 * it has a destructor or a postblit.
+	 * We need to generate one if a user-specified one does not exist.
+	 */
+    bool needOpAssign()
+	{
+static if (false) {
+		printf("StructDeclaration.needOpAssign() %s\n", toChars());
+}
+		if (hasIdentityAssign)
+			goto Ldontneed;
+
+		if (dtor || postblit)
+			goto Lneed;
+
+		/* If any of the fields need an opAssign, then we
+		 * need it too.
+		 */
+		for (size_t i = 0; i < fields.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)fields.data[i];
+			VarDeclaration v = s.isVarDeclaration();
+			assert(v && v.storage_class & STC.STCfield);
+			if (v.storage_class & STC.STCref)
+				continue;
+			Type tv = v.type.toBasetype();
+			while (tv.ty == TY.Tsarray)
+			{   TypeSArray ta = cast(TypeSArray)tv;
+				tv = tv.nextOf().toBasetype();
+			}
+			if (tv.ty == TY.Tstruct)
+			{   TypeStruct ts = cast(TypeStruct)tv;
+				StructDeclaration sd = ts.sym;
+				if (sd.needOpAssign())
+					goto Lneed;
+			}
+		}
+	Ldontneed:
+static if (false) {
+		printf("\tdontneed\n");
+}
+		return false;
+
+	Lneed:
+static if (false) {
+		printf("\tneed\n");
+}
+		return true;
+	}
+	
+	/******************************************
+	 * Build opAssign for struct.
+	 *	S* opAssign(S s) { ... }
+	 */
+    FuncDeclaration buildOpAssign(Scope sc)
+	{
+		if (!needOpAssign())
+			return null;
+
+		//printf("StructDeclaration.buildOpAssign() %s\n", toChars());
+
+		FuncDeclaration fop = null;
+
+		Argument param = new Argument(STC.STCnodtor, type, Id.p, null);
+		Arguments fparams = new Arguments;
+		fparams.push(cast(void*)param);
+		Type ftype = new TypeFunction(fparams, handle, false, LINK.LINKd);
+version (STRUCTTHISREF) {
+		(cast(TypeFunction)ftype).isref = 1;
+}
+
+		fop = new FuncDeclaration(Loc(0), Loc(0), Id.assign, STC.STCundefined, ftype);
+
+		Expression e = null;
+		if (postblit)
+		{	/* Swap:
+			 *    tmp = *this; *this = s; tmp.dtor();
+			 */
+		//printf("\tswap copy\n");
+		Identifier idtmp = Lexer.uniqueId("__tmp");
+		VarDeclaration tmp;
+		AssignExp ec = null;
+		if (dtor)
+		{
+			tmp = new VarDeclaration(Loc(0), type, idtmp, new VoidInitializer(Loc(0)));
+			tmp.noauto = true;
+			e = new DeclarationExp(Loc(0), tmp);
+
+			Expression e2;
+version (STRUCTTHISREF) {
+			e2 = new ThisExp(Loc(0));
+} else {
+			e2 = new PtrExp(Loc(0), new ThisExp(Loc(0)));
+}
+			ec = new AssignExp(Loc(0), new VarExp(Loc(0), tmp), e2);
+			ec.op = TOK.TOKblit;
+			e = Expression.combine(e, ec);
+		}
+		Expression e2;
+version (STRUCTTHISREF) {
+			e2 = new ThisExp(Loc(0));
+} else {
+			e2 = new PtrExp(Loc(0), new ThisExp(Loc(0)));
+}
+	
+		ec = new AssignExp(Loc(0), e2, new IdentifierExp(Loc(0), Id.p));
+		ec.op = TOK.TOKblit;
+		e = Expression.combine(e, ec);
+		if (dtor)
+		{
+			/* Instead of running the destructor on s, run it
+			 * on tmp. This avoids needing to copy tmp back in to s.
+			 */
+			Expression ecc = new DotVarExp(Loc(0), new VarExp(Loc(0), tmp), dtor, 0);
+			ecc = new CallExp(Loc(0), ecc);
+			e = Expression.combine(e, ecc);
+		}
+		}
+		else
+		{	/* Do memberwise copy
+			 */
+		//printf("\tmemberwise copy\n");
+		for (size_t i = 0; i < fields.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)fields.data[i];
+			VarDeclaration v = s.isVarDeclaration();
+			assert(v && v.storage_class & STC.STCfield);
+			// this.v = s.v;
+			AssignExp ec = new AssignExp(Loc(0), new DotVarExp(Loc(0), new ThisExp(Loc(0)), v, 0), new DotVarExp(Loc(0), new IdentifierExp(Loc(0), Id.p), v, 0));
+			ec.op = TOK.TOKblit;
+			e = Expression.combine(e, ec);
+		}
+		}
+		Statement s1 = new ExpStatement(Loc(0), e);
+
+		/* Add:
+		 *   return this;
+		 */
+		e = new ThisExp(Loc(0));
+		Statement s2 = new ReturnStatement(Loc(0), e);
+
+		fop.fbody = new CompoundStatement(Loc(0), s1, s2);
+
+		members.push(cast(void*)fop);
+		fop.addMember(sc, this, 1);
+
+		sc = sc.push();
+		sc.stc = STC.STCundefined;
+		sc.linkage = LINK.LINKd;
+
+		fop.semantic(sc);
+
+		sc.pop();
+
+		//printf("-StructDeclaration.buildOpAssign() %s\n", toChars());
+
+		return fop;
+	}
+	
+	/*****************************************
+	 * Create inclusive postblit for struct by aggregating
+	 * all the postblits in postblits[] with the postblits for
+	 * all the members.
+	 * Note the close similarity with AggregateDeclaration.buildDtor(),
+	 * and the ordering changes (runs forward instead of backwards).
+	 */
+
+version (DMDV2) {
+    FuncDeclaration buildPostBlit(Scope sc)
+	{
+		//printf("StructDeclaration.buildPostBlit() %s\n", toChars());
+		Expression e = null;
+
+		for (size_t i = 0; i < fields.dim; i++)
+		{
+		Dsymbol s = cast(Dsymbol)fields.data[i];
+		VarDeclaration v = s.isVarDeclaration();
+		assert(v && v.storage_class & STC.STCfield);
+		if (v.storage_class & STC.STCref)
+			continue;
+		Type tv = v.type.toBasetype();
+		size_t dim = 1;
+		while (tv.ty == TY.Tsarray)
+		{   TypeSArray ta = cast(TypeSArray)tv;
+			dim *= (cast(TypeSArray)tv).dim.toInteger();
+			tv = tv.nextOf().toBasetype();
+		}
+		if (tv.ty == TY.Tstruct)
+		{   TypeStruct ts = cast(TypeStruct)tv;
+			StructDeclaration sd = ts.sym;
+			if (sd.postblit)
+			{	Expression ex;
+
+			// this.v
+			ex = new ThisExp(Loc(0));
+			ex = new DotVarExp(Loc(0), ex, v, 0);
+
+			if (dim == 1)
+			{   // this.v.postblit()
+				ex = new DotVarExp(Loc(0), ex, sd.postblit, 0);
+				ex = new CallExp(Loc(0), ex);
+			}
+			else
+			{
+				// Typeinfo.postblit(cast(void*)&this.v);
+				Expression ea = new AddrExp(Loc(0), ex);
+				ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo());
+
+				Expression et = v.type.getTypeInfo(sc);
+				et = new DotIdExp(Loc(0), et, Id.postblit);
+
+				ex = new CallExp(Loc(0), et, ea);
+			}
+			e = Expression.combine(e, ex);	// combine in forward order
+			}
+		}
+		}
+
+		/* Build our own "postblit" which executes e
+		 */
+		if (e)
+		{	//printf("Building __fieldPostBlit()\n");
+		PostBlitDeclaration dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__fieldPostBlit"));
+		dd.fbody = new ExpStatement(Loc(0), e);
+		postblits.shift(cast(void*)dd);
+		members.push(cast(void*)dd);
+		dd.semantic(sc);
+		}
+
+		switch (postblits.dim)
+		{
+		case 0:
+			return null;
+
+		case 1:
+			return cast(FuncDeclaration)postblits.data[0];
+
+		default:
+			e = null;
+			for (size_t i = 0; i < postblits.dim; i++)
+			{	FuncDeclaration fd = cast(FuncDeclaration)postblits.data[i];
+			Expression ex = new ThisExp(Loc(0));
+			ex = new DotVarExp(Loc(0), ex, fd, 0);
+			ex = new CallExp(Loc(0), ex);
+			e = Expression.combine(e, ex);
+			}
+			PostBlitDeclaration dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__aggrPostBlit"));
+			dd.fbody = new ExpStatement(Loc(0), e);
+			members.push(cast(void*)dd);
+			dd.semantic(sc);
+			return dd;
+		}
+	}
+}
+
+	/*******************************************
+	 * Build copy constructor for struct.
+	 * Copy constructors are compiler generated only, and are only
+	 * callable from the compiler. They are not user accessible.
+	 * A copy constructor is:
+	 *    void cpctpr(ref S s)
+	 *    {
+	 *	*this = s;
+	 *	this.postBlit();
+	 *    }
+	 * This is done so:
+	 *	- postBlit() never sees uninitialized data
+	 *	- memcpy can be much more efficient than memberwise copy
+	 *	- no fields are overlooked
+	 */
+    FuncDeclaration buildCpCtor(Scope sc)
+	{
+		//printf("StructDeclaration.buildCpCtor() %s\n", toChars());
+		FuncDeclaration fcp = null;
+
+		/* Copy constructor is only necessary if there is a postblit function,
+		 * otherwise the code generator will just do a bit copy.
+		 */
+		if (postblit)
+		{
+		//printf("generating cpctor\n");
+
+		Argument param = new Argument(STC.STCref, type, Id.p, null);
+		Arguments fparams = new Arguments;
+		fparams.push(cast(void*)param);
+		Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd);
+
+		fcp = new FuncDeclaration(Loc(0), Loc(0), Id.cpctor, STC.STCundefined, ftype);
+
+		// Build *this = p;
+		Expression e = new ThisExp(Loc(0));
+version (STRUCTTHISREF) {
+} else {
+		e = new PtrExp(Loc(0), e);
+}
+		AssignExp ea = new AssignExp(Loc(0), e, new IdentifierExp(Loc(0), Id.p));
+		ea.op = TOK.TOKblit;
+		Statement s = new ExpStatement(Loc(0), ea);
+
+		// Build postBlit();
+		e = new VarExp(Loc(0), postblit, 0);
+		e = new CallExp(Loc(0), e);
+
+		s = new CompoundStatement(Loc(0), s, new ExpStatement(Loc(0), e));
+		fcp.fbody = s;
+
+		members.push(cast(void*)fcp);
+
+		sc = sc.push();
+		sc.stc = STC.STCundefined;
+		sc.linkage = LINK.LINKd;
+
+		fcp.semantic(sc);
+
+		sc.pop();
+		}
+
+		return fcp;
+	}
+	
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+	
+    PROT getAccess(Dsymbol smember)	// determine access to smember
+	{
+		assert(false);
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		//printf("StructDeclaration.toObjFile('%s')\n", toChars());
+
+		if (multiobj)
+		{	
+			obj_append(this);
+			return;
+		}
+
+		// Anonymous structs/unions only exist as part of others,
+		// do not output forward referenced structs's
+		if (!isAnonymous() && members)
+		{
+			if (global.params.symdebug) {
+				toDebug();
+			}
+
+			type.getTypeInfo(null);	// generate TypeInfo
+
+			if (true)
+			{
+				// Generate static initializer
+				toInitializer();
+
+static if (false) {
+				sinit.Sclass = SC.SCcomdat;
+} else {
+				if (inTemplateInstance())
+				{
+					sinit.Sclass = SC.SCcomdat;
+				}
+				else
+				{
+					sinit.Sclass = SC.SCglobal;
+				}
+}
+				sinit.Sfl = FL.FLdata;
+
+				toDt(&sinit.Sdt);
+
+version (OMFOBJ) {
+				/* For OMF, common blocks aren't pulled in from the library.
+				 */
+				/* ELF comdef's generate multiple
+				 * definition errors for them from the gnu linker.
+				 * Need to figure out how to generate proper comdef's for ELF.
+				 */
+				// See if we can convert a comdat to a comdef,
+				// which saves on exe file space.
+				if (sinit.Sclass == SCcomdat &&
+					sinit.Sdt &&
+					sinit.Sdt.dt == DT.DT_azeros &&
+					sinit.Sdt.DTnext == null &&
+					!global.params.multiobj)
+				{
+					sinit.Sclass = SC.SCglobal;
+					sinit.Sdt.dt = DT.DT_common;
+				}
+}
+
+version (ELFOBJ) {
+				sinit.Sseg = Segment.CDATA;
+}
+version (MACHOBJ) {
+				sinit.Sseg = Segment.DATA;
+}
+				outdata(sinit);
+			}
+
+			// Put out the members
+			for (uint i = 0; i < members.dim; i++)
+			{
+				Dsymbol member = cast(Dsymbol)members.data[i];
+				member.toObjFile(0);
+			}
+		}
+	}
+	
+    void toDt(dt_t** pdt)
+	{
+		uint offset;
+		uint i;
+		dt_t* dt;
+
+		//printf("StructDeclaration.toDt(), this='%s'\n", toChars());
+		offset = 0;
+
+		// Note equivalence of this loop to class's
+		for (i = 0; i < fields.dim; i++)
+		{
+			VarDeclaration v = cast(VarDeclaration)fields.data[i];
+			//printf("\tfield '%s' voffset %d, offset = %d\n", v.toChars(), v.offset, offset);
+			dt = null;
+			int sz;
+
+			if (v.storage_class & STC.STCref)
+			{
+				sz = PTRSIZE;
+				if (v.offset >= offset)
+					dtnzeros(&dt, sz);
+			}
+			else
+			{
+				sz = cast(uint)v.type.size();
+				Initializer init = v.init;
+				if (init)
+				{   
+					//printf("\t\thas initializer %s\n", init.toChars());
+					ExpInitializer ei = init.isExpInitializer();
+					Type tb = v.type.toBasetype();
+					if (ei && tb.ty == TY.Tsarray)
+						(cast(TypeSArray)tb).toDtElem(&dt, ei.exp);
+					else
+						dt = init.toDt();
+				}
+				else if (v.offset >= offset)
+					v.type.toDt(&dt);
+			}
+			if (dt)
+			{
+				if (v.offset < offset)
+					error("overlapping initialization for struct %s.%s", toChars(), v.toChars());
+				else
+				{
+					if (offset < v.offset)
+						dtnzeros(pdt, v.offset - offset);
+					dtcat(pdt, dt);
+					offset = v.offset + sz;
+				}
+			}
+		}
+
+		if (offset < structsize)
+			dtnzeros(pdt, structsize - offset);
+
+		dt_optimize(*pdt);
+	}
+	
+    void toDebug()			// to symbolic debug info
+	{
+		assert(false);
+	}
+
+    StructDeclaration isStructDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StructInitializer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,62 @@
+module dmd.StructInitializer;
+
+import dmd.Initializer;
+import dmd.ArrayTypes;
+import dmd.Array;
+import dmd.Loc;
+import dmd.Type;
+import dmd.Scope;
+import dmd.Identifier;
+import dmd.AggregateDeclaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+
+import dmd.backend.dt_t;
+
+class StructInitializer : Initializer
+{
+    Identifiers field;	// of Identifier *'s
+    Initializers value;	// parallel array of Initializer *'s
+
+    Array vars;		// parallel array of VarDeclaration *'s
+    AggregateDeclaration ad;	// which aggregate this is for
+
+    this(Loc loc)
+	{
+		assert(false);
+		super(loc);
+	}
+	
+    Initializer syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    void addInit(Identifier field, Initializer value)
+	{
+		assert(false);
+	}
+	
+    Initializer semantic(Scope sc, Type t)
+	{
+		assert(false);
+	}
+	
+    Expression toExpression()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    dt_t* toDt()
+	{
+		assert(false);
+	}
+
+    StructInitializer isStructInitializer() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/StructLiteralExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,134 @@
+module dmd.StructLiteralExp;
+
+import dmd.Expression;
+import dmd.StructDeclaration;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.backend.Symbol;
+import dmd.HdrGenState;
+import dmd.backend.dt_t;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+
+
+class StructLiteralExp : Expression
+{
+	StructDeclaration sd;		// which aggregate this is for
+    Expressions elements;	// parallels sd->fields[] with
+				// NULL entries for fields to skip
+
+    Symbol* sym;		// back end symbol to initialize with literal
+    size_t soffset;		// offset from start of s
+    int fillHoles;		// fill alignment 'holes' with zero
+
+	this(Loc loc, StructDeclaration sd, Expressions elements)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression getField(Type type, uint offset)
+	{
+		assert(false);
+	}
+
+	int getFieldIndex(Type type, uint offset)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+
+	int isLvalue()
+	{
+		assert(false);
+	}
+
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		assert(false);
+	}
+
+	bool canThrow()
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SuperExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,125 @@
+module dmd.SuperExp;
+
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.FuncDeclaration;
+import dmd.ClassDeclaration;
+import dmd.Dsymbol;
+import dmd.HdrGenState;
+import dmd.ThisExp;
+import dmd.TOK;
+import dmd.CSX;
+import dmd.Type;
+
+class SuperExp : ThisExp
+{
+	this(Loc loc)
+	{
+		super(loc);
+		op = TOK.TOKsuper;
+	}
+
+	Expression semantic(Scope sc)
+	{
+		FuncDeclaration fd;
+		FuncDeclaration fdthis;
+
+	version (LOGSEMANTIC) {
+		printf("SuperExp.semantic('%s')\n", toChars());
+	}
+		if (type)
+			return this;
+
+		/* Special case for typeof(this) and typeof(super) since both
+		 * should work even if they are not inside a non-static member function
+		 */
+		if (sc.intypeof)
+		{
+			// Find enclosing class
+			for (Dsymbol s = sc.parent; 1; s = s.parent)
+			{
+				ClassDeclaration cd;
+
+				if (!s)
+				{
+					error("%s is not in a class scope", toChars());
+					goto Lerr;
+				}
+				cd = s.isClassDeclaration();
+				if (cd)
+				{
+					cd = cd.baseClass;
+					if (!cd)
+					{   
+						error("class %s has no 'super'", s.toChars());
+						goto Lerr;
+					}
+					type = cd.type;
+					return this;
+				}
+			}
+		}
+
+		fdthis = sc.parent.isFuncDeclaration();
+		fd = hasThis(sc);
+		if (!fd)
+			goto Lerr;
+		assert(fd.vthis);
+		var = fd.vthis;
+		assert(var.parent);
+
+		Dsymbol s = fd.toParent();
+		while (s && s.isTemplateInstance())
+			s = s.toParent();
+		assert(s);
+		ClassDeclaration cd = s.isClassDeclaration();
+	//printf("parent is %s %s\n", fd.toParent().kind(), fd.toParent().toChars());
+		if (!cd)
+			goto Lerr;
+		if (!cd.baseClass)
+		{
+			error("no base class for %s", cd.toChars());
+			type = fd.vthis.type;
+		}
+		else
+		{
+			type = cd.baseClass.type;
+		}
+
+		var.isVarDeclaration().checkNestedReference(sc, loc);
+
+		if (!sc.intypeof)
+			sc.callSuper |= CSXsuper;
+		return this;
+
+	Lerr:
+		error("'super' is only allowed in non-static class member functions");
+		type = Type.tint32;
+		return this;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SwitchErrorStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,33 @@
+module dmd.SwitchErrorStatement;
+
+import dmd.Statement;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.BE;
+
+class SwitchErrorStatement : Statement
+{
+	this(Loc loc)
+	{
+		assert(false);
+		super(loc);
+	}
+
+	BE blockExit()
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SwitchStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,440 @@
+module dmd.SwitchStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.DefaultStatement;
+import dmd.TryFinallyStatement;
+import dmd.Array;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.InterState;
+import dmd.BE;
+import dmd.TY;
+import dmd.WANT;
+import dmd.GotoCaseStatement;
+import dmd.CaseStatement;
+import dmd.ArrayTypes;
+import dmd.CompoundStatement;
+import dmd.Global;
+import dmd.SwitchErrorStatement;
+import dmd.Type;
+import dmd.HaltExp;
+import dmd.ExpStatement;
+import dmd.BreakStatement;
+import dmd.EnumDeclaration;
+import dmd.TypeEnum;
+import dmd.Dsymbol;
+import dmd.EnumMember;
+import dmd.TypeTypedef;
+import dmd.TOK;
+import dmd.StringExp;
+
+import dmd.backend.Util;
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.BC;
+import dmd.backend.dt_t;
+import dmd.backend.Symbol;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.RTLSYM;
+import dmd.backend.targ_types;
+
+class SwitchStatement : Statement
+{
+    Expression condition;
+    Statement body_;
+    bool isFinal;
+
+    DefaultStatement sdefault = null;
+    TryFinallyStatement tf = null;
+    Array gotoCases;		// array of unresolved GotoCaseStatement's
+    Array cases;		// array of CaseStatement's
+    int hasNoDefault = 0;	// !=0 if no default statement
+    int hasVars = 0;		// !=0 if has variable case values
+
+    this(Loc loc, Expression c, Statement b, bool isFinal)
+	{
+		super(loc);
+		
+		this.condition = c;
+		this.body_ = b;
+		this.isFinal = isFinal;
+		
+		gotoCases = new Array();
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("SwitchStatement.semantic(%p)\n", this);
+		tf = sc.tf;
+		assert(!cases);		// ensure semantic() is only run once
+		condition = condition.semantic(sc);
+		condition = resolveProperties(sc, condition);
+		if (condition.type.isString())
+		{
+			// If it's not an array, cast it to one
+			if (condition.type.ty != Tarray)
+			{
+				condition = condition.implicitCastTo(sc, condition.type.nextOf().arrayOf());
+			}
+			condition.type = condition.type.constOf();
+		}
+		else
+		{	
+			condition = condition.integralPromotions(sc);
+			condition.checkIntegral();
+		}
+		condition = condition.optimize(WANTvalue);
+
+		sc = sc.push();
+		sc.sbreak = this;
+		sc.sw = this;
+
+		cases = new Array();
+		sc.noctor++;	// BUG: should use Scope.mergeCallSuper() for each case instead
+		body_ = body_.semantic(sc);
+		sc.noctor--;
+
+		// Resolve any goto case's with exp
+		for (int i = 0; i < gotoCases.dim; i++)
+		{
+			GotoCaseStatement gcs = cast(GotoCaseStatement)gotoCases.data[i];
+
+			if (!gcs.exp)
+			{
+				gcs.error("no case statement following goto case;");
+				break;
+			}
+
+			for (Scope scx = sc; scx; scx = scx.enclosing)
+			{
+				if (!scx.sw)
+					continue;
+				for (int j = 0; j < scx.sw.cases.dim; j++)
+				{
+					CaseStatement cs = cast(CaseStatement)scx.sw.cases.data[j];
+
+					if (cs.exp.equals(gcs.exp))
+					{
+						gcs.cs = cs;
+						goto Lfoundcase;
+					}
+				}
+			}
+			gcs.error("case %s not found", gcs.exp.toChars());
+
+		Lfoundcase:
+			;
+		}
+
+		if (!sc.sw.sdefault && !isFinal)
+		{	
+			hasNoDefault = 1;
+
+			warning("switch statement has no default");
+
+			// Generate runtime error if the default is hit
+			Statements a = new Statements();
+			CompoundStatement cs;
+			Statement s;
+
+			if (global.params.useSwitchError)
+				s = new SwitchErrorStatement(loc);
+			else
+			{   
+				Expression e = new HaltExp(loc);
+				s = new ExpStatement(loc, e);
+			}
+
+			a.reserve(4);
+			a.push(cast(void*)body_);
+			a.push(cast(void*)new BreakStatement(loc, null));
+			sc.sw.sdefault = new DefaultStatement(loc, s);
+			a.push(cast(void*)sc.sw.sdefault);
+			cs = new CompoundStatement(loc, a);
+			body_ = cs;
+		}
+
+	version (DMDV2) {
+		if (isFinal)
+		{	
+			Type t = condition.type;
+			while (t.ty == Ttypedef)
+			{   
+				// Don't use toBasetype() because that will skip past enums
+				t = (cast(TypeTypedef)t).sym.basetype;
+			}
+			if (condition.type.ty == Tenum)
+			{   
+				TypeEnum te = cast(TypeEnum)condition.type;
+				EnumDeclaration ed = te.toDsymbol(sc).isEnumDeclaration();
+				assert(ed);
+				size_t dim = ed.members.dim;
+				for (size_t i = 0; i < dim; i++)
+				{
+					EnumMember em = (cast(Dsymbol)ed.members.data[i]).isEnumMember();
+					if (em)
+					{
+						for (size_t j = 0; j < cases.dim; j++)
+						{   
+							CaseStatement cs = cast(CaseStatement)cases.data[j];
+							if (cs.exp.equals(em.value))
+								goto L1;
+						}
+						error("enum member %s not represented in final switch", em.toChars());
+					}
+				L1:
+					;
+				}
+			}
+		}
+	}
+
+		sc.pop();
+		return this;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		BE result = BE.BEnone;
+		if (condition.canThrow())
+			result |= BE.BEthrow;
+
+		if (body_)
+		{	result |= body_.blockExit();
+			if (result & BE.BEbreak)
+			{   
+				result |= BE.BEfallthru;
+				result &= ~BE.BEbreak;
+			}
+		}
+		else
+			result |= BE.BEfallthru;
+
+		return result;
+	}
+
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		//printf("SwitchStatement.inlineScan()\n");
+		condition = condition.inlineScan(iss);
+		body_ = body_ ? body_.inlineScan(iss) : null;
+		if (sdefault)
+			sdefault = cast(DefaultStatement)sdefault.inlineScan(iss);
+		if (cases)
+		{
+			for (int i = 0; i < cases.dim; i++)
+			{   
+				Statement s = cast(Statement)cases.data[i];
+				cases.data[i] = cast(void*)s.inlineScan(iss);
+			}
+		}
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		int string;
+		Blockx* blx = irs.blx;
+
+		//printf("SwitchStatement.toIR()\n");
+		IRState mystate = IRState(irs,this);
+
+		mystate.switchBlock = blx.curblock;
+
+		/* Block for where "break" goes to
+		 */
+		mystate.breakBlock = block_calloc(blx);
+
+		/* Block for where "default" goes to.
+		 * If there is a default statement, then that is where default goes.
+		 * If not, then do:
+		 *   default: break;
+		 * by making the default block the same as the break block.
+		 */
+		mystate.defaultBlock = sdefault ? block_calloc(blx) : mystate.breakBlock;
+
+		int numcases = 0;
+		if (cases)
+			numcases = cases.dim;
+
+		incUsage(irs, loc);
+		elem* econd = condition.toElem(&mystate);
+
+	version (DMDV2) {
+		if (hasVars)
+		{	
+			/* Generate a sequence of if-then-else blocks for the cases.
+			 */
+			if (econd.Eoper != OPvar)
+			{
+				elem* e = exp2_copytotemp(econd);
+				block_appendexp(mystate.switchBlock, e);
+				econd = e.E2;
+			}
+
+			for (int i = 0; i < numcases; i++)
+			{   
+				CaseStatement cs = cast(CaseStatement)cases.data[i];
+
+				elem* ecase = cs.exp.toElem(&mystate);
+				elem* e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase);
+				block* b = blx.curblock;
+				block_appendexp(b, e);
+				block* bcase = block_calloc(blx);
+				cs.cblock = bcase;
+				block_next(blx, BCiftrue, null);
+				list_append(&b.Bsucc, bcase);
+				list_append(&b.Bsucc, blx.curblock);
+			}
+
+			/* The final 'else' clause goes to the default
+			 */
+			block* b = blx.curblock;
+			block_next(blx, BCgoto, null);
+			list_append(&b.Bsucc, mystate.defaultBlock);
+
+			body_.toIR(&mystate);
+
+			/* Have the end of the switch body fall through to the block
+			 * following the switch statement.
+			 */
+			block_goto(blx, BCgoto, mystate.breakBlock);
+			return;
+		}
+	}
+
+		if (condition.type.isString())
+		{
+			// Number the cases so we can unscramble things after the sort()
+			for (int i = 0; i < numcases; i++)
+			{   
+				CaseStatement cs = cast(CaseStatement)cases.data[i];
+				cs.index = i;
+			}
+
+			cases.sort();
+
+			/* Create a sorted array of the case strings, and si
+			 * will be the symbol for it.
+			 */
+			dt_t* dt = null;
+			Symbol* si = symbol_generate(SCstatic,type_fake(TYullong));
+		version (MACHOBJ) {
+			si.Sseg = Segment.DATA;
+		}
+			dtdword(&dt, numcases);
+			dtxoff(&dt, si, 8, TYnptr);
+
+			for (int i = 0; i < numcases; i++)
+			{   
+				CaseStatement cs = cast(CaseStatement)cases.data[i];
+
+				if (cs.exp.op != TOKstring)
+				{	
+					error("case '%s' is not a string", cs.exp.toChars());	// BUG: this should be an assert
+				}
+				else
+				{
+					StringExp se = cast(StringExp)(cs.exp);
+					uint len = se.len;
+					dtdword(&dt, len);
+					dtabytes(&dt, TYnptr, 0, se.len * se.sz, cast(char*)se.string_);
+				}
+			}
+
+			si.Sdt = dt;
+			si.Sfl = FLdata;
+			outdata(si);
+
+			/* Call:
+			 *	_d_switch_string(string[] si, string econd)
+			 */
+			elem* eparam = el_param(econd, el_var(si));
+			switch (condition.type.nextOf().ty)
+			{
+				case Tchar:
+					econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_STRING]), eparam);
+					break;
+				case Twchar:
+					econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_USTRING]), eparam);
+					break;
+				case Tdchar:	// BUG: implement
+					econd = el_bin(OPcall, TYint, el_var(rtlsym[RTLSYM_SWITCH_DSTRING]), eparam);
+					break;
+				default:
+					assert(0);
+			}
+			elem_setLoc(econd, loc);
+			string = 1;
+		}
+		else
+			string = 0;
+		block_appendexp(mystate.switchBlock, econd);
+		block_next(blx,BCswitch,null);
+
+		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
+		 */
+		*pu++ = numcases;
+		list_append(&mystate.switchBlock.Bsucc, mystate.defaultBlock);
+
+		/* Fill in the first entry in each pair, which is the case value.
+		 * CaseStatement.toIR() will fill in
+		 * the second entry for each pair with the block.
+		 */
+		for (int i = 0; i < numcases; i++)
+		{
+			CaseStatement cs = cast(CaseStatement)cases.data[i];
+			if (string)
+			{
+				pu[cs.index] = i;
+			}
+			else
+			{
+				pu[i] = cs.exp.toInteger();
+			}
+		}
+
+		body_.toIR(&mystate);
+
+		/* Have the end of the switch body fall through to the block
+		 * following the switch statement.
+		 */
+		block_goto(blx, BCgoto, mystate.breakBlock);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SymOffExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,230 @@
+module dmd.SymOffExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.backend.dt_t;
+import dmd.SymbolExp;
+import dmd.VarDeclaration;
+import dmd.DelegateExp;
+import dmd.ThisExp;
+import dmd.FuncDeclaration;
+import dmd.IntegerExp;
+import dmd.ErrorExp;
+import dmd.TY;
+import dmd.TOK;
+
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class SymOffExp : SymbolExp
+{
+	uint offset;
+
+	this(Loc loc, Declaration var, uint offset, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKsymoff, SymOffExp.sizeof, var, hasOverloads);
+		
+		this.offset = offset;
+		VarDeclaration v = var.isVarDeclaration();
+		if (v && v.needThis())
+			error("need 'this' for address of %s", v.toChars());
+	}
+
+	Expression semantic(Scope sc)
+	{
+	version(LOGSEMANTIC) {
+		printf("SymOffExp::semantic('%s')\n", toChars());
+	}
+		//var.semantic(sc);
+		if (!type)
+			type = var.type.pointerTo();
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+			v.checkNestedReference(sc, loc);
+		return this;
+	}
+
+	void checkEscape()
+	{
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+		{
+			if (!v.isDataseg())
+				error("escaping reference to local variable %s", v.toChars());
+		}
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	int isConst()
+	{
+		return 2;
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		int i;
+
+		//printf("SymOffExp.doInline(%s)\n", toChars());
+		for (i = 0; i < ids.from.dim; i++)
+		{
+			if (var is cast(Declaration)ids.from.data[i])
+			{
+				SymOffExp se = cast(SymOffExp)copy();
+
+				se.var = cast(Declaration)ids.to.data[i];
+				return se;
+			}
+		}
+		return this;
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+	static if (false) {
+		printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		MATCH result = type.implicitConvTo(t);
+		//printf("\tresult = %d\n", result);
+
+		if (result == MATCHnomatch)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+			FuncDeclaration f;
+
+			t = t.toBasetype();
+			if (type.ty == Tpointer && type.nextOf().ty == Tfunction &&
+				(t.ty == Tpointer || t.ty == Tdelegate) && t.nextOf().ty == Tfunction)
+			{
+				f = var.isFuncDeclaration();
+				if (f)
+				{	
+					f = f.overloadExactMatch(t.nextOf());
+					if (f)
+					{   
+						if ((t.ty == Tdelegate && (f.needThis() || f.isNested())) ||
+							(t.ty == Tpointer && !(f.needThis() || f.isNested())))
+						{
+							result = MATCHexact;
+						}
+					}
+				}
+			}
+		}
+		//printf("\tresult = %d\n", result);
+		return result;
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+	static if (false) {
+		printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", toChars(), type.toChars(), t.toChars());
+	}
+		if (type == t && hasOverloads == 0)
+			return this;
+
+		Expression e;
+		Type tb = t.toBasetype();
+		Type typeb = type.toBasetype();
+
+		if (tb != typeb)
+		{
+			// Look for pointers to functions where the functions are overloaded.
+			FuncDeclaration f;
+
+			if (hasOverloads &&
+				typeb.ty == Tpointer && typeb.nextOf().ty == Tfunction &&
+				(tb.ty == Tpointer || tb.ty == Tdelegate) && tb.nextOf().ty == Tfunction)
+			{
+				f = var.isFuncDeclaration();
+				if (f)
+				{
+					f = f.overloadExactMatch(tb.nextOf());
+					if (f)
+					{
+						if (tb.ty == Tdelegate)
+						{
+							if (f.needThis() && hasThis(sc))
+							{
+								e = new DelegateExp(loc, new ThisExp(loc), f);
+								e = e.semantic(sc);
+							}
+							else if (f.isNested())
+							{
+								e = new DelegateExp(loc, new IntegerExp(0), f);
+								e = e.semantic(sc);
+							}
+							else if (f.needThis())
+							{   
+								error("no 'this' to create delegate for %s", f.toChars());
+								e = new ErrorExp();
+							}
+							else
+							{   
+								error("cannot cast from function pointer to delegate");
+								e = new ErrorExp();
+							}
+						}
+						else
+						{
+							e = new SymOffExp(loc, f, 0);
+							e.type = t;
+						}
+			version (DMDV2) {
+						f.tookAddressOf++;
+			}
+						return e;
+					}
+				}
+			}
+			e = Expression.castTo(sc, t);
+		}
+		else
+		{	
+			e = copy();
+			e.type = t;
+			(cast(SymOffExp)e).hasOverloads = 0;
+		}
+		return e;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		//printf("SymOffExp.toDt('%s')\n", var.toChars());
+		assert(var);
+		if (!(var.isDataseg() || var.isCodeseg()) ||
+			var.needThis() ||
+			var.isThreadlocal()
+		)
+		{
+			debug writef("SymOffExp.toDt()\n");
+			error("non-constant expression %s", toChars());
+			return pdt;
+		}
+
+		Symbol* s = var.toSymbol();
+		return dtxoff(pdt, s, offset, TYnptr);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SymbolDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,42 @@
+module dmd.SymbolDeclaration;
+
+import dmd.Declaration;
+import dmd.StructDeclaration;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.STC;
+import dmd.Identifier;
+
+import dmd.backend.Symbol;
+
+import core.stdc.string;
+import std.stdio;
+
+// This is a shell around a back end symbol
+
+class SymbolDeclaration : Declaration
+{
+    Symbol* sym;
+    StructDeclaration dsym;
+
+    this(Loc loc, Symbol* s, StructDeclaration dsym)
+	{
+		int len = strlen(s.Sident.ptr);
+		string name = s.Sident.ptr[0..len].idup;
+
+		super(new Identifier(name, TOK.TOKidentifier));
+		
+		this.loc = loc;
+		sym = s;
+		this.dsym = dsym;
+		storage_class |= STCconst;
+	}
+
+    Symbol* toSymbol()
+	{
+		return sym;
+	}
+
+    // Eliminate need for dynamic_cast
+    SymbolDeclaration isSymbolDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SymbolExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,202 @@
+module dmd.SymbolExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.TOK;
+import dmd.TY;
+import dmd.Type;
+import dmd.SymOffExp;
+import dmd.FuncDeclaration;
+import dmd.VarDeclaration;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+import dmd.backend.SC;
+import dmd.backend.elem;
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.codegen.Util;
+
+class SymbolExp : Expression
+{
+	Declaration var;
+
+	int hasOverloads;
+
+	this(Loc loc, TOK op, int size, Declaration var, int hasOverloads)
+	{
+		super(loc, op, size);
+		assert(var);
+		this.var = var;
+		this.hasOverloads = hasOverloads;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		Symbol* s;
+		elem* e;
+		tym_t tym;
+		Type tb = (op == TOK.TOKsymoff) ? var.type.toBasetype() : type.toBasetype();
+		int offset = (op == TOK.TOKsymoff) ? (cast(SymOffExp)this).offset : 0;
+		FuncDeclaration fd;
+		VarDeclaration v = var.isVarDeclaration();
+
+		//printf("SymbolExp::toElem('%s') %p\n", toChars(), this);
+		//printf("\tparent = '%s'\n", var.parent ? var.parent.toChars() : "null");
+		if (op == TOK.TOKvar && var.needThis())
+		{
+			error("need 'this' to access member %s", toChars());
+			return el_long(TYM.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 == SC.SCauto || s.Sclass == SC.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(OPER.OPaddr, TYM.TYnptr, ethis);
+
+				if (v && v.offset)
+					soffset = v.offset;
+				else
+				{
+					soffset = s.Soffset;
+					/* If fd is a non-static member function of a class or struct,
+					 * then ethis isn't the frame pointer.
+					 * ethis is the 'this' pointer to the class/struct instance.
+					 * We must offset it.
+					 */
+					if (fd.vthis)
+					{
+						soffset -= fd.vthis.toSymbol().Soffset;
+					}
+					//printf("\tSoffset = x%x, sthis.Soffset = x%x\n", s.Soffset, irs.sthis.Soffset);
+				}
+
+				if (!nrvo)
+					soffset += offset;
+
+				e = el_bin(OPER.OPadd, TYM.TYnptr, ethis, el_long(TYM.TYnptr, soffset));
+
+				if (op == TOK.TOKvar)
+					e = el_una(OPER.OPind, TYM.TYnptr, e);
+				if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef())
+					e = el_una(OPER.OPind, s.ty(), e);
+				else if (op == TOK.TOKsymoff && nrvo)
+				{   
+					e = el_una(OPER.OPind, TYM.TYnptr, e);
+					e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
+				}
+				goto L1;
+			}
+		}
+
+		/* If var is a member of a closure
+		 */
+		if (v && v.offset)
+		{	
+			assert(irs.sclosure);
+			e = el_var(irs.sclosure);
+			e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, v.offset));
+			if (op == TOK.TOKvar)
+			{   
+				e = el_una(OPER.OPind, type.totym(), e);
+				if (tybasic(e.Ety) == TYM.TYstruct)
+				e.Enumbytes = cast(uint)type.size();
+				el_setLoc(e, loc);
+			}
+			if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef())
+			{   
+				e.Ety = TYM.TYnptr;
+				e = el_una(OPER.OPind, s.ty(), e);
+			}
+			else if (op == TOK.TOKsymoff && nrvo)
+			{   e = el_una(OPER.OPind, TYM.TYnptr, e);
+				e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
+			}
+			else if (op == TOK.TOKsymoff)
+			{
+				e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
+			}
+			goto L1;
+		}
+
+		if (s.Sclass == SC.SCauto && s.Ssymnum == -1)
+		{
+			//printf("\tadding symbol\n");
+			symbol_add(s);
+		}
+
+		if (var.isImportedSymbol())
+		{
+			assert(op == TOK.TOKvar);
+			e = el_var(var.toImport());
+			e = el_una(OPER.OPind,s.ty(),e);
+		}
+		else if ((var.isParameter() && tb.ty == 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 = TYM.TYnptr;
+			if (op == TOK.TOKvar)
+				e = el_una(OPER.OPind, s.ty(), e);
+			else if (offset)
+					e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, offset));
+		}
+		else if (op == TOK.TOKvar)
+			e = el_var(s);
+		else
+		{   
+			e = nrvo ? el_var(s) : el_ptr(s);
+			e = el_bin(OPER.OPadd, e.Ety, e, el_long(TYM.TYint, offset));
+		}
+	L1:
+		if (op == TOK.TOKvar)
+		{
+			if (nrvo)
+			{
+				e.Ety = TYM.TYnptr;
+				e = el_una(OPER.OPind, 0, e);
+			}
+			if (tb.ty == TY.Tfunction)
+			{
+				tym = s.Stype.Tty;
+			}
+			else
+				tym = type.totym();
+			e.Ejty = cast(ubyte)tym;
+			e.Ety = e.Ejty;
+			if (tybasic(tym) == TYM.TYstruct)
+			{
+				e.Enumbytes = cast(uint)type.size();
+			}
+			else if (tybasic(tym) == TYM.TYarray)
+			{
+				e.Ejty = TYM.TYstruct;
+				e.Ety = e.Ejty;
+				e.Enumbytes = cast(uint)type.size();
+			}
+		}
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/SynchronizedStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,193 @@
+module dmd.SynchronizedStatement;
+
+import dmd.Statement;
+import dmd.IntegerExp;
+import dmd.TypeSArray;
+import dmd.CompoundStatement;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.ClassDeclaration;
+import dmd.Id;
+import dmd.TypeIdentifier;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.CastExp;
+import dmd.TryFinallyStatement;
+import dmd.ExpStatement;
+import dmd.CallExp;
+import dmd.DeclarationExp;
+import dmd.VarExp;
+import dmd.DeclarationStatement;
+import dmd.ArrayTypes;
+import dmd.Statement;
+import dmd.VarDeclaration;
+import dmd.ExpInitializer;
+import dmd.Lexer;
+import dmd.Identifier;
+import dmd.FuncDeclaration;
+import dmd.BE;
+import dmd.STC;
+import dmd.DotIdExp;
+
+import dmd.backend.elem;
+import dmd.backend.Util;
+
+class SynchronizedStatement : Statement
+{
+    Expression exp;
+    Statement body_;
+
+    this(Loc loc, Expression exp, Statement body_)
+	{
+		super(loc);
+		
+		this.exp = exp;
+		this.body_ = body_;
+		this.esync = null;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		if (exp)
+		{
+			exp = exp.semantic(sc);
+			exp = resolveProperties(sc, exp);
+			ClassDeclaration cd = exp.type.isClassHandle();
+			if (!cd)
+				error("can only synchronize on class objects, not '%s'", exp.type.toChars());
+			else if (cd.isInterfaceDeclaration())
+			{   
+				/* Cast the interface to an object, as the object has the monitor,
+				 * not the interface.
+				 */
+				Type t = new TypeIdentifier(Loc(0), Id.Object_);
+
+				t = t.semantic(Loc(0), sc);
+				exp = new CastExp(loc, exp, t);
+				exp = exp.semantic(sc);
+			}
+
+static if (true) {
+			/* Rewrite as:
+			 *  auto tmp = exp;
+			 *  _d_monitorenter(tmp);
+			 *  try { body } finally { _d_monitorexit(tmp); }
+			 */
+			Identifier id = Lexer.uniqueId("__sync");
+			ExpInitializer ie = new ExpInitializer(loc, exp);
+			VarDeclaration tmp = new VarDeclaration(loc, exp.type, id, ie);
+
+			Statements cs = new Statements();
+			cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+
+			FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorenter);
+			Expression e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
+			e.type = Type.tvoid;			// do not run semantic on e
+			cs.push(cast(void*)new ExpStatement(loc, e));
+
+			FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorexit);
+			e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
+			e.type = Type.tvoid;			// do not run semantic on e
+			Statement s = new ExpStatement(loc, e);
+			s = new TryFinallyStatement(loc, body_, s);
+			cs.push(cast(void*)s);
+
+			s = new CompoundStatement(loc, cs);
+			return s.semantic(sc);
+}
+		}
+///	static if (true) {
+		else
+		{	
+			/* Generate our own critical section, then rewrite as:
+			 *  __gshared byte[CriticalSection.sizeof] critsec;
+			 *  _d_criticalenter(critsec.ptr);
+			 *  try { body } finally { _d_criticalexit(critsec.ptr); }
+			 */
+			Identifier id = Lexer.uniqueId("__critsec");
+			Type t = new TypeSArray(Type.tint8, new IntegerExp(PTRSIZE +  os_critsecsize()));
+			VarDeclaration tmp = new VarDeclaration(loc, t, id, null);
+			tmp.storage_class |= STCgshared | STCstatic;
+
+			Statements cs = new Statements();
+			cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+
+			FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalenter);
+			Expression e = new DotIdExp(loc, new VarExp(loc, tmp), Id.ptr);
+			e = e.semantic(sc);
+			e = new CallExp(loc, new VarExp(loc, fdenter), e);
+			e.type = Type.tvoid;			// do not run semantic on e
+			cs.push(cast(void*)new ExpStatement(loc, e));
+
+			FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalexit);
+			e = new DotIdExp(loc, new VarExp(loc, tmp), Id.ptr);
+			e = e.semantic(sc);
+			e = new CallExp(loc, new VarExp(loc, fdexit), e);
+			e.type = Type.tvoid;			// do not run semantic on e
+			Statement s = new ExpStatement(loc, e);
+			s = new TryFinallyStatement(loc, body_, s);
+			cs.push(cast(void*)s);
+
+			s = new CompoundStatement(loc, cs);
+			return s.semantic(sc);
+		}
+///	}
+		if (body_)
+			body_ = body_.semantic(sc);
+
+		return this;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool hasContinue()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+
+// Back end
+    elem* esync;
+
+	this(Loc loc, elem *esync, Statement body_)
+	{
+		assert(false);
+		super(loc);
+	}
+	
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TFLAGS.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,11 @@
+module dmd.TFLAGS;
+
+enum TFLAGS
+{
+	TFLAGSintegral	= 1,
+	TFLAGSfloating	= 2,
+	TFLAGSunsigned	= 4,
+	TFLAGSreal		= 8,
+	TFLAGSimaginary = 0x10,
+	TFLAGScomplex	= 0x20,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TOK.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,251 @@
+module dmd.TOK;
+
+version (DMDV2) {	
+	enum TOK
+	{
+		TOKreserved,
+
+		// Other
+		TOKlparen,	TOKrparen,
+		TOKlbracket,	TOKrbracket,
+		TOKlcurly,	TOKrcurly,
+		TOKcolon,	TOKneg,
+		TOKsemicolon,	TOKdotdotdot,
+		TOKeof,		TOKcast,
+		TOKnull,	TOKassert,
+		TOKtrue,	TOKfalse,
+		TOKarray,	TOKcall,
+		TOKaddress,
+		TOKtype,	TOKthrow,
+		TOKnew,		TOKdelete,
+		TOKstar,	TOKsymoff,
+		TOKvar,		TOKdotvar,
+		TOKdotti,	TOKdotexp,
+		TOKdottype,	TOKslice,
+		TOKarraylength,	TOKversion,
+		TOKmodule,	TOKdollar,
+		TOKtemplate,	TOKdottd,
+		TOKdeclaration,	TOKtypeof,
+		TOKpragma,	TOKdsymbol,
+		TOKtypeid,	TOKuadd,
+		TOKremove,
+		TOKnewanonclass, TOKcomment,
+		TOKarrayliteral, TOKassocarrayliteral,
+		TOKstructliteral,
+
+		// Operators
+		TOKlt,		TOKgt,
+		TOKle,		TOKge,
+		TOKequal,	TOKnotequal,
+		TOKidentity,	TOKnotidentity,
+		TOKindex,	TOKis,
+		TOKtobool,
+
+	// 60
+		// NCEG floating point compares
+		// !<>=     <>    <>=    !>     !>=   !<     !<=   !<>
+		TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
+
+		TOKshl,		TOKshr,
+		TOKshlass,	TOKshrass,
+		TOKushr,	TOKushrass,
+		TOKcat,		TOKcatass,	// ~ ~=
+		TOKadd,		TOKmin,		TOKaddass,	TOKminass,
+		TOKmul,		TOKdiv,		TOKmod,
+		TOKmulass,	TOKdivass,	TOKmodass,
+		TOKand,		TOKor,		TOKxor,
+		TOKandass,	TOKorass,	TOKxorass,
+		TOKassign,	TOKnot,		TOKtilde,
+		TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
+		TOKdot,		TOKarrow,	TOKcomma,
+		TOKquestion,	TOKandand,	TOKoror,
+
+	// 104
+		// Numeric literals
+		TOKint32v, TOKuns32v,
+		TOKint64v, TOKuns64v,
+		TOKfloat32v, TOKfloat64v, TOKfloat80v,
+		TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
+
+		// Char constants
+		TOKcharv, TOKwcharv, TOKdcharv,
+
+		// Leaf operators
+		TOKidentifier,	TOKstring,
+		TOKthis,	TOKsuper,
+		TOKhalt,	TOKtuple,
+
+		// Basic types
+		TOKvoid,
+		TOKint8, TOKuns8,
+		TOKint16, TOKuns16,
+		TOKint32, TOKuns32,
+		TOKint64, TOKuns64,
+		TOKfloat32, TOKfloat64, TOKfloat80,
+		TOKimaginary32, TOKimaginary64, TOKimaginary80,
+		TOKcomplex32, TOKcomplex64, TOKcomplex80,
+		TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
+		TOKcent, TOKucent,
+
+		// Aggregates
+		TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
+		TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
+		TOKmixin,
+
+		TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
+		TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
+		TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
+		TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
+
+		// Statements
+		TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
+		TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
+		TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
+		TOKasm, TOKforeach, TOKforeach_reverse,
+		TOKscope,
+		TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
+
+		// Contracts
+		TOKbody, TOKinvariant,
+
+		// Testing
+		TOKunittest,
+
+		// Added after 1.0
+		TOKref,
+		TOKmacro,
+
+		TOKtraits,
+		TOKoverloadset,
+		TOKpure,
+		TOKnothrow,
+		TOKtls,
+		TOKgshared,
+		TOKline,
+		TOKfile,
+		TOKshared,
+		TOKat,
+
+		TOKMAX
+	}
+} else {
+	enum TOK
+	{
+		TOKreserved,
+
+		// Other
+		TOKlparen,	TOKrparen,
+		TOKlbracket,	TOKrbracket,
+		TOKlcurly,	TOKrcurly,
+		TOKcolon,	TOKneg,
+		TOKsemicolon,	TOKdotdotdot,
+		TOKeof,		TOKcast,
+		TOKnull,	TOKassert,
+		TOKtrue,	TOKfalse,
+		TOKarray,	TOKcall,
+		TOKaddress,
+		TOKtype,	TOKthrow,
+		TOKnew,		TOKdelete,
+		TOKstar,	TOKsymoff,
+		TOKvar,		TOKdotvar,
+		TOKdotti,	TOKdotexp,
+		TOKdottype,	TOKslice,
+		TOKarraylength,	TOKversion,
+		TOKmodule,	TOKdollar,
+		TOKtemplate,	TOKdottd,
+		TOKdeclaration,	TOKtypeof,
+		TOKpragma,	TOKdsymbol,
+		TOKtypeid,	TOKuadd,
+		TOKremove,
+		TOKnewanonclass, TOKcomment,
+		TOKarrayliteral, TOKassocarrayliteral,
+		TOKstructliteral,
+
+		// Operators
+		TOKlt,		TOKgt,
+		TOKle,		TOKge,
+		TOKequal,	TOKnotequal,
+		TOKidentity,	TOKnotidentity,
+		TOKindex,	TOKis,
+		TOKtobool,
+
+	// 60
+		// NCEG floating point compares
+		// !<>=     <>    <>=    !>     !>=   !<     !<=   !<>
+		TOKunord,TOKlg,TOKleg,TOKule,TOKul,TOKuge,TOKug,TOKue,
+
+		TOKshl,		TOKshr,
+		TOKshlass,	TOKshrass,
+		TOKushr,	TOKushrass,
+		TOKcat,		TOKcatass,	// ~ ~=
+		TOKadd,		TOKmin,		TOKaddass,	TOKminass,
+		TOKmul,		TOKdiv,		TOKmod,
+		TOKmulass,	TOKdivass,	TOKmodass,
+		TOKand,		TOKor,		TOKxor,
+		TOKandass,	TOKorass,	TOKxorass,
+		TOKassign,	TOKnot,		TOKtilde,
+		TOKplusplus,	TOKminusminus,	TOKconstruct,	TOKblit,
+		TOKdot,		TOKarrow,	TOKcomma,
+		TOKquestion,	TOKandand,	TOKoror,
+
+	// 104
+		// Numeric literals
+		TOKint32v, TOKuns32v,
+		TOKint64v, TOKuns64v,
+		TOKfloat32v, TOKfloat64v, TOKfloat80v,
+		TOKimaginary32v, TOKimaginary64v, TOKimaginary80v,
+
+		// Char constants
+		TOKcharv, TOKwcharv, TOKdcharv,
+
+		// Leaf operators
+		TOKidentifier,	TOKstring,
+		TOKthis,	TOKsuper,
+		TOKhalt,	TOKtuple,
+
+		// Basic types
+		TOKvoid,
+		TOKint8, TOKuns8,
+		TOKint16, TOKuns16,
+		TOKint32, TOKuns32,
+		TOKint64, TOKuns64,
+		TOKfloat32, TOKfloat64, TOKfloat80,
+		TOKimaginary32, TOKimaginary64, TOKimaginary80,
+		TOKcomplex32, TOKcomplex64, TOKcomplex80,
+		TOKchar, TOKwchar, TOKdchar, TOKbit, TOKbool,
+		TOKcent, TOKucent,
+
+		// Aggregates
+		TOKstruct, TOKclass, TOKinterface, TOKunion, TOKenum, TOKimport,
+		TOKtypedef, TOKalias, TOKoverride, TOKdelegate, TOKfunction,
+		TOKmixin,
+
+		TOKalign, TOKextern, TOKprivate, TOKprotected, TOKpublic, TOKexport,
+		TOKstatic, /*TOKvirtual,*/ TOKfinal, TOKconst, TOKabstract, TOKvolatile,
+		TOKdebug, TOKdeprecated, TOKin, TOKout, TOKinout, TOKlazy,
+		TOKauto, TOKpackage, TOKmanifest, TOKimmutable,
+
+		// Statements
+		TOKif, TOKelse, TOKwhile, TOKfor, TOKdo, TOKswitch,
+		TOKcase, TOKdefault, TOKbreak, TOKcontinue, TOKwith,
+		TOKsynchronized, TOKreturn, TOKgoto, TOKtry, TOKcatch, TOKfinally,
+		TOKasm, TOKforeach, TOKforeach_reverse,
+		TOKscope,
+		TOKon_scope_exit, TOKon_scope_failure, TOKon_scope_success,
+
+		// Contracts
+		TOKbody, TOKinvariant,
+
+		// Testing
+		TOKunittest,
+
+		// Added after 1.0
+		TOKref,
+		TOKmacro,
+
+		TOKMAX
+	}
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(TOK));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TY.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,58 @@
+module dmd.TY;
+
+enum TY
+{
+    Tarray,		// slice array, aka T[]
+    Tsarray,		// static array, aka T[dimension]
+    Tnarray,		// resizable array, aka T[new]
+    Taarray,		// associative array, aka T[type]
+    Tpointer,
+    Treference,
+    Tfunction,
+    Tident,
+    Tclass,
+    Tstruct,
+    Tenum,
+    Ttypedef,
+    Tdelegate,
+
+    Tnone,
+    Tvoid,
+    Tint8,
+    Tuns8,
+    Tint16,
+    Tuns16,
+    Tint32,
+    Tuns32,
+    Tint64,
+    Tuns64,
+    Tfloat32,
+    Tfloat64,
+    Tfloat80,
+
+    Timaginary32,
+    Timaginary64,
+    Timaginary80,
+
+    Tcomplex32,
+    Tcomplex64,
+    Tcomplex80,
+
+    Tbit,
+    Tbool,
+    Tchar,
+	Tascii = Tchar,
+    Twchar,
+    Tdchar,
+
+    Terror,
+    Tinstance,
+    Ttypeof,
+    Ttuple,
+    Tslice,
+    Treturn,
+    TMAX
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(TY));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateAliasParameter.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,87 @@
+module dmd.TemplateAliasParameter;
+
+import dmd.TemplateParameter;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Type;
+import dmd.ArrayTypes;
+import dmd.Scope;
+import dmd.Declaration;
+import dmd.MATCH;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Dsymbol;
+
+class TemplateAliasParameter : TemplateParameter
+{
+    /* Syntax:
+     *	specType ident : specAlias = defaultAlias
+     */
+
+    Type specType;
+    Object specAlias;
+    Object defaultAlias;
+
+    static Dsymbol sdummy;
+
+    this(Loc loc, Identifier ident, Type specType, Object specAlias, Object defaultAlias)
+	{
+		assert(false);
+		super(loc, ident);
+	}
+
+    TemplateAliasParameter isTemplateAliasParameter()
+	{
+		assert(false);
+	}
+	
+    TemplateParameter syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    void declareParameter(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope)
+	{
+		assert(false);
+	}
+	
+    void print(Object oarg, Object oded)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    Object specialization()
+	{
+		assert(false);
+	}
+	
+    Object defaultArg(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+	
+    bool overloadMatch(TemplateParameter)
+	{
+		assert(false);
+	}
+	
+    MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags)
+	{
+		assert(false);
+	}
+	
+    void* dummyArg()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1143 @@
+module dmd.TemplateDeclaration;
+
+import dmd.Loc;
+import dmd.ScopeDsymbol;
+import dmd.ArrayTypes;
+import dmd.Dsymbol;
+import dmd.STC;
+import dmd.TemplateThisParameter;
+import dmd.Global;
+import dmd.Array;
+import dmd.Identifier;
+import dmd.TypeArray;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.TypeIdentifier;
+import dmd.TypeDelegate;
+import dmd.IntegerExp;
+import dmd.TypeSArray;
+import dmd.StringExp;
+import dmd.TOK;
+import dmd.Argument;
+import dmd.CtorDeclaration;
+import dmd.TypeFunction;
+import dmd.TY;
+import dmd.OutBuffer;
+import dmd.Declaration;
+import dmd.HdrGenState;
+import dmd.TemplateInstance;
+import dmd.WANT;
+import dmd.FuncDeclaration;
+import dmd.TemplateTupleParameter;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.Tuple;
+import dmd.TupleDeclaration;
+import dmd.Initializer;
+import dmd.ExpInitializer;
+import dmd.TemplateValueParameter;
+import dmd.AliasDeclaration;
+import dmd.VarDeclaration;
+import dmd.TemplateParameter;
+import dmd.TemplateTypeParameter;
+
+import dmd.expression.Util;
+
+import std.stdio;
+
+/**************************************
+ * Determine if TemplateDeclaration is variadic.
+ */
+
+TemplateTupleParameter isVariadic(TemplateParameters parameters)
+{   
+	size_t dim = parameters.dim;
+    TemplateTupleParameter tp = null;
+
+    if (dim)
+		tp = (cast(TemplateParameter)parameters.data[dim - 1]).isTemplateTupleParameter();
+
+    return tp;
+}
+
+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)
+    {
+		string p = s.ident ? s.ident.toChars() : s.toChars();
+		buf.writestring(p);
+    }
+    else if (v)
+    {
+		Objects args = v.objects;
+		for (size_t i = 0; i < args.dim; i++)
+		{
+			if (i)
+				buf.writeByte(',');
+			Object o = cast(Object)args.data[i];
+			ObjectToCBuffer(buf, hgs, o);
+		}
+    }
+    else if (!oarg)
+    {
+		buf.writestring("null");
+    }
+    else
+    {
+		debug writef("bad Object = %p\n", oarg);
+		assert(0);
+    }
+}
+
+class TemplateDeclaration : ScopeDsymbol
+{
+    TemplateParameters parameters;	// array of TemplateParameter's
+
+    TemplateParameters origParameters;	// originals for Ddoc
+    Expression constraint;
+    Array instances;			// array of TemplateInstance's
+
+    TemplateDeclaration overnext;	// next overloaded TemplateDeclaration
+    TemplateDeclaration overroot;	// first in overnext list
+
+    int semanticRun;			// 1 semantic() run
+
+    Dsymbol onemember;		// if !=NULL then one member of this template
+
+    int literal;		// this template declaration is a literal
+
+    this(Loc loc, Identifier id, TemplateParameters parameters, Expression constraint, Array decldefs)
+	{	
+		super(id);
+		
+	version (LOG) {
+		printf("TemplateDeclaration(this = %p, id = '%s')\n", this, id.toChars());
+	}
+	static if (false) {
+		if (parameters)
+			for (int i = 0; i < parameters.dim; i++)
+			{   
+				TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+				//printf("\tparameter[%d] = %p\n", i, tp);
+				TemplateTypeParameter ttp = tp.isTemplateTypeParameter();
+
+				if (ttp)
+				{
+					printf("\tparameter[%d] = %s : %s\n", i, tp.ident.toChars(), ttp.specType ? ttp.specType.toChars() : "");
+				}
+			}
+	}
+		
+		this.loc = loc;
+		this.parameters = parameters;
+		this.origParameters = parameters;
+		this.constraint = constraint;
+		this.members = decldefs;
+		
+		instances = new Array();
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+
+    void semantic(Scope sc)
+	{
+	version (LOG) {
+		printf("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars());
+	}
+		if (semanticRun)
+			return;		// semantic() already run
+		semanticRun = 1;
+
+		if (sc.func)
+		{
+	version (DMDV1) {
+			error("cannot declare template at function scope %s", sc.func.toChars());
+	}
+		}
+
+		if (/*global.params.useArrayBounds &&*/ sc.module_)
+		{
+			// Generate this function as it may be used
+			// when template is instantiated in other modules
+			sc.module_.toModuleArray();
+		}
+
+		if (/*global.params.useAssert &&*/ sc.module_)
+		{
+			// Generate this function as it may be used
+			// when template is instantiated in other modules
+			sc.module_.toModuleAssert();
+		}
+
+		/* Remember Scope for later instantiations, but make
+		 * a copy since attributes can change.
+		 */
+		this.scope_ = new Scope(sc);	/// A light copy
+		this.scope_.setNoFree();
+
+		// Set up scope for parameters
+		ScopeDsymbol paramsym = new ScopeDsymbol();
+		paramsym.parent = sc.parent;
+		Scope paramscope = sc.push(paramsym);
+		paramscope.parameterSpecialization = 1;
+		paramscope.stc = STCundefined;
+
+		if (!parent)
+			parent = sc.parent;
+
+		if (global.params.doDocComments)
+		{
+			origParameters = new TemplateParameters();
+			origParameters.setDim(parameters.dim);
+			for (int i = 0; i < parameters.dim; i++)
+			{
+				TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+				origParameters.data[i] = cast(void*)tp.syntaxCopy();
+			}
+		}
+
+		for (int i = 0; i < parameters.dim; i++)
+		{
+			TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+			tp.declareParameter(paramscope);
+		}
+
+		for (int i = 0; i < parameters.dim; i++)
+		{
+			TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+
+			tp.semantic(paramscope);
+			if (i + 1 != parameters.dim && tp.isTemplateTupleParameter())
+				error("template tuple parameter must be last one");
+		}
+
+		paramscope.pop();
+
+		if (members)
+		{
+			Dsymbol s;
+			if (Dsymbol.oneMembers(members, &s))
+			{
+				if (s && s.ident && s.ident.equals(ident))
+				{
+					onemember = s;
+					s.parent = this;
+				}
+			}
+		}
+
+		/* BUG: should check:
+		 *	o no virtual functions or non-static data members of classes
+		 */
+	}
+
+    bool overloadInsert(Dsymbol s)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    string kind()
+	{
+		assert(false);
+	}
+
+    string toChars()
+	{
+		assert(false);
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+
+//    void toDocBuffer(OutBuffer *buf);
+
+	/***************************************
+	 * Given that ti is an instance of this TemplateDeclaration,
+	 * deduce the types of the parameters to this, and store
+	 * 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.
+	 */
+    MATCH matchWithInstance(TemplateInstance ti, Objects dedtypes, int flag)
+	{
+		MATCH m;
+		int dedtypes_dim = dedtypes.dim;
+
+	version (LOGM) {
+		printf("\n+TemplateDeclaration.matchWithInstance(this = %s, ti = %s, flag = %d)\n", toChars(), ti.toChars(), flag);
+	}
+
+	static if (false) {
+		printf("dedtypes.dim = %d, parameters.dim = %d\n", dedtypes_dim, parameters.dim);
+		if (ti.tiargs.dim)
+			printf("ti.tiargs.dim = %d, [0] = %p\n", ti.tiargs.dim, ti.tiargs.data[0]);
+	}
+		dedtypes.zero();
+
+		int parameters_dim = parameters.dim;
+		int variadic = isVariadic() !is null;
+
+		// If more arguments than parameters, no match
+		if (ti.tiargs.dim > parameters_dim && !variadic)
+		{
+	version (LOGM) {
+		printf(" no match: more arguments than parameters\n");
+	}
+		return MATCHnomatch;
+		}
+
+		assert(dedtypes_dim == parameters_dim);
+		assert(dedtypes_dim >= ti.tiargs.dim || variadic);
+
+		// Set up scope for parameters
+		assert(cast(size_t)cast(void*)scope_ > 0x10000);
+		ScopeDsymbol paramsym = new ScopeDsymbol();
+		paramsym.parent = scope_.parent;
+		Scope paramscope = scope_.push(paramsym);
+		paramscope.stc = STCundefined;
+
+		// Attempt type deduction
+		m = MATCHexact;
+		for (int i = 0; i < dedtypes_dim; i++)
+		{	
+			MATCH m2;
+			TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+			Declaration sparam;
+
+			//printf("\targument [%d]\n", i);
+		version (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() : "");
+		}
+
+		version (DMDV1) {
+			m2 = tp.matchArg(paramscope, ti.tiargs, i, parameters, dedtypes, &sparam);
+		} else {
+			m2 = tp.matchArg(paramscope, ti.tiargs, i, parameters, dedtypes, &sparam, (flag & 2) ? 1 : 0);
+		}
+			//printf("\tm2 = %d\n", m2);
+
+			if (m2 == MATCHnomatch)
+			{
+		static if (false) {
+				printf("\tmatchArg() for parameter %i failed\n", i);
+		}
+				goto Lnomatch;
+			}
+
+			if (m2 < m)
+				m = m2;
+
+			if (!flag)
+				sparam.semantic(paramscope);
+			if (!paramscope.insert(sparam))
+				goto Lnomatch;
+		}
+
+		if (!flag)
+		{
+			/* Any parameter left without a type gets the type of
+			 * its corresponding arg
+			 */
+			for (int i = 0; i < dedtypes_dim; i++)
+			{
+				if (!dedtypes.data[i])
+				{
+					assert(i < ti.tiargs.dim);
+					dedtypes.data[i] = ti.tiargs.data[i];
+				}
+			}
+		}
+
+	version (DMDV2) {
+		if (m && constraint && !(flag & 1))
+		{	/* Check to see if constraint is satisfied.
+			 */
+			Expression e = constraint.syntaxCopy();
+			paramscope.flags |= SCOPE.SCOPEstaticif;
+			e = e.semantic(paramscope);
+			e = e.optimize(WANTvalue | WANTinterpret);
+			if (e.isBool(true)) {
+				;
+			} else if (e.isBool(false))
+				goto Lnomatch;
+			else
+			{
+				e.error("constraint %s is not constant or does not evaluate to a bool", e.toChars());
+			}
+		}
+	}
+
+	version (LOGM) {
+		// Print out the results
+		printf("--------------------------\n");
+		printf("template %s\n", toChars());
+		printf("instance %s\n", ti.toChars());
+		if (m)
+		{
+			for (int i = 0; i < dedtypes_dim; i++)
+			{
+				TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+				Object oarg;
+
+				printf(" [%d]", i);
+
+				if (i < ti.tiargs.dim)
+					oarg = cast(Object)ti.tiargs.data[i];
+				else
+					oarg = null;
+				tp.print(oarg, cast(Object)dedtypes.data[i]);
+			}
+		}
+		else
+			goto Lnomatch;
+	}
+
+	version (LOGM) {
+		printf(" match = %d\n", m);
+	}
+		goto Lret;
+
+	Lnomatch:
+	version (LOGM) {
+		printf(" no match\n");
+	}
+		m = MATCHnomatch;
+
+	Lret:
+		paramscope.pop();
+	version (LOGM) {
+		printf("-TemplateDeclaration.matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
+	}
+		return m;
+	}
+	
+    MATCH leastAsSpecialized(TemplateDeclaration td2)
+	{
+		assert(false);
+	}
+
+	/*************************************************
+	 * Match function arguments against a specific template function.
+	 * Input:
+	 *	loc		instantiation location
+	 *	targsi		Expression/Type initial list of template arguments
+	 *	ethis		'this' argument if !null
+	 *	fargs		arguments to function
+	 * Output:
+	 *	dedargs		Expression/Type deduced template arguments
+	 * Returns:
+	 *	match level
+	 */
+    MATCH deduceFunctionTemplateMatch(Loc loc, Objects targsi, Expression ethis, Expressions fargs, Objects dedargs)
+	{
+		size_t nfparams;
+		size_t nfargs;
+		size_t nargsi;		// array size of targsi
+		int fptupindex = -1;
+		int tuple_dim = 0;
+		MATCH match = MATCHexact;
+		FuncDeclaration fd = onemember.toAlias().isFuncDeclaration();
+		Arguments fparameters;		// function parameter list
+		int fvarargs;			// function varargs
+		scope Objects dedtypes = new Objects();	// for T:T*, the dedargs is the T*, dedtypes is the T
+
+	static if (false) {
+		printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars());
+		for (i = 0; i < fargs.dim; i++)
+		{	
+			Expression e = cast(Expression)fargs.data[i];
+			printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars());
+		}
+		printf("fd = %s\n", fd.toChars());
+		printf("fd.type = %p\n", fd.type);
+	}
+
+		assert(cast(size_t)cast(void*)scope_ > 0x10000);
+
+		dedargs.setDim(parameters.dim);
+		dedargs.zero();
+
+		dedtypes.setDim(parameters.dim);
+		dedtypes.zero();
+
+		// Set up scope for parameters
+		ScopeDsymbol paramsym = new ScopeDsymbol();
+		paramsym.parent = scope_.parent;
+		Scope paramscope = scope_.push(paramsym);
+
+		TemplateTupleParameter tp = isVariadic();
+
+	static if (false) {
+		for (i = 0; i < dedargs.dim; i++)
+		{
+			printf("\tdedarg[%d] = ", i);
+			Object oarg = cast(Object)dedargs.data[i];
+			if (oarg) printf("%s", oarg.toChars());
+				printf("\n");
+		}
+	}
+
+
+		nargsi = 0;
+		if (targsi)
+		{	// Set initial template arguments
+			size_t n;
+
+			nargsi = targsi.dim;
+			n = parameters.dim;
+			if (tp)
+				n--;
+			if (nargsi > n)
+			{   
+				if (!tp)
+					goto Lnomatch;
+
+				/* The extra initial template arguments
+				 * now form the tuple argument.
+				 */
+				Tuple t = new Tuple();
+				assert(parameters.dim);
+				dedargs.data[parameters.dim - 1] = cast(void*)t;
+
+				tuple_dim = nargsi - n;
+				t.objects.setDim(tuple_dim);
+				for (size_t i = 0; i < tuple_dim; i++)
+				{
+					t.objects.data[i] = cast(void*)targsi.data[n + i];
+				}
+				declareParameter(paramscope, tp, t);
+			}
+			else
+				n = nargsi;
+
+			memcpy(dedargs.data, targsi.data, n * (*dedargs.data).sizeof);
+
+			for (size_t i = 0; i < n; i++)
+			{   
+				assert(i < parameters.dim);
+				TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i];
+				MATCH m;
+				Declaration sparam = null;
+
+				m = tp2.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam);
+				//printf("\tdeduceType m = %d\n", m);
+				if (m == MATCHnomatch)
+					goto Lnomatch;
+				if (m < match)
+					match = m;
+
+				sparam.semantic(paramscope);
+				if (!paramscope.insert(sparam))
+					goto Lnomatch;
+			}
+		}
+	static if (false) {
+		for (i = 0; i < dedargs.dim; i++)
+		{
+			printf("\tdedarg[%d] = ", i);
+			Object oarg = cast(Object)dedargs.data[i];
+			if (oarg) printf("%s", oarg.toChars());
+				printf("\n");
+		}
+	}
+
+		if (fd.type)
+		{
+			assert(fd.type.ty == Tfunction);
+			TypeFunction fdtype = cast(TypeFunction)fd.type;
+			fparameters = fdtype.parameters;
+			fvarargs = fdtype.varargs;
+		}
+		else
+		{	
+			CtorDeclaration fctor = fd.isCtorDeclaration();
+			assert(fctor);
+			fparameters = fctor.arguments;
+			fvarargs = fctor.varargs;
+		}
+
+		nfparams = Argument.dim(fparameters);	// number of function parameters
+		nfargs = fargs ? fargs.dim : 0;		// number of function arguments
+
+		/* Check for match of function arguments with variadic template
+		 * parameter, such as:
+		 *
+		 * template Foo(T, A...) { void Foo(T t, A a); }
+		 * void main() { Foo(1,2,3); }
+		 */
+		if (tp)				// if variadic
+		{
+			if (nfparams == 0)		// if no function parameters
+			{
+				Tuple t = new Tuple();
+				//printf("t = %p\n", t);
+				dedargs.data[parameters.dim - 1] = cast(void*)t;
+				declareParameter(paramscope, tp, t);
+				goto L2;
+			}
+			else if (nfargs < nfparams - 1)
+				goto L1;
+			else
+			{
+				/* 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.
+				 */
+				for (fptupindex = 0; fptupindex < nfparams; fptupindex++)
+				{
+					Argument fparam = cast(Argument)fparameters.data[fptupindex];
+					if (fparam.type.ty != Tident)
+						continue;
+					TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
+					if (!tp.ident.equals(tid.ident) || tid.idents.dim)
+						continue;
+
+					if (fvarargs)		// variadic function doesn't
+						goto Lnomatch;	// go with variadic template
+
+					/* The types of the function arguments
+					 * now form the tuple argument.
+					 */
+					Tuple t = new Tuple();
+					dedargs.data[parameters.dim - 1] = cast(void*)t;
+
+					tuple_dim = nfargs - (nfparams - 1);
+					t.objects.setDim(tuple_dim);
+					for (size_t i = 0; i < tuple_dim; i++)
+					{   
+						Expression farg = cast(Expression)fargs.data[fptupindex + i];
+						t.objects.data[i] = cast(void*)farg.type;
+					}
+					declareParameter(paramscope, tp, t);
+					goto L2;
+				}
+				fptupindex = -1;
+			}
+		}
+
+	L1:
+		if (nfparams == nfargs) {
+			;
+		} else if (nfargs > nfparams) {
+			if (fvarargs == 0)
+				goto Lnomatch;		// too many args, no match
+			match = MATCHconvert;		// match ... with a conversion
+		}
+
+	L2:
+	version (DMDV2) {
+		// Match 'ethis' to any TemplateThisParameter's
+		if (ethis)
+		{
+			for (size_t i = 0; i < parameters.dim; i++)
+			{   
+				TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i];
+				TemplateThisParameter ttp = tp2.isTemplateThisParameter();
+				if (ttp)
+				{	
+					MATCH m;
+
+					Type t = new TypeIdentifier(Loc(0), ttp.ident);
+					m = ethis.type.deduceType(paramscope, t, parameters, dedtypes);
+					if (!m)
+						goto Lnomatch;
+					if (m < match)
+						match = m;		// pick worst match
+				}
+			}
+		}
+	}
+
+		// Loop through the function parameters
+		for (size_t 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(fparameters, i);
+
+			if (i >= nfargs)		// if not enough arguments
+			{
+				if (fparam.defaultArg)
+				{	
+					/* Default arguments do not participate in template argument
+					 * deduction.
+					 */
+					goto Lmatch;
+				}
+			}
+			else
+			{   
+				Expression farg = cast(Expression)fargs.data[i];
+		static if (false) {
+				printf("\tfarg.type   = %s\n", farg.type.toChars());
+				printf("\tfparam.type = %s\n", fparam.type.toChars());
+		}
+				Type argtype = farg.type;
+
+		version (DMDV2) {
+				/* Allow string literals which are type [] to match with [dim]
+				 */
+				if (farg.op == TOKstring)
+				{	
+					StringExp se = cast(StringExp)farg;
+					if (!se.committed && argtype.ty == Tarray &&
+						fparam.type.toBasetype().ty == Tsarray)
+					{
+						argtype = new TypeSArray(argtype.nextOf(), new IntegerExp(se.loc, se.len, Type.tindex));
+						argtype = argtype.semantic(se.loc, null);
+						argtype = argtype.invariantOf();
+					}
+				}
+		}
+
+				MATCH m;
+				m = argtype.deduceType(paramscope, fparam.type, parameters, dedtypes);
+				//printf("\tdeduceType m = %d\n", m);
+
+				/* If no match, see if there's a conversion to a delegate
+				 */
+				if (!m && fparam.type.toBasetype().ty == Tdelegate)
+				{
+					TypeDelegate td = cast(TypeDelegate)fparam.type.toBasetype();
+					TypeFunction tf = cast(TypeFunction)td.next;
+
+					if (!tf.varargs && Argument.dim(tf.parameters) == 0)
+					{
+						m = farg.type.deduceType(paramscope, tf.next, parameters, dedtypes);
+						if (!m && tf.next.toBasetype().ty == Tvoid)
+							m = MATCHconvert;
+					}
+					//printf("\tm2 = %d\n", m);
+				}
+
+				if (m)
+				{	
+					if (m < match)
+						match = m;		// pick worst match
+					continue;
+				}
+			}
+
+			/* The following code for variadic arguments closely
+			 * matches TypeFunction.callMatch()
+			 */
+			if (!(fvarargs == 2 && i + 1 == nfparams))
+				goto Lnomatch;
+
+			/* Check for match with function parameter T...
+			 */
+			Type tb = fparam.type.toBasetype();
+			switch (tb.ty)
+			{
+				// Perhaps we can do better with this, see TypeFunction.callMatch()
+				case Tsarray:
+				{
+					TypeSArray tsa = cast(TypeSArray)tb;
+					ulong sz = tsa.dim.toInteger();
+					if (sz != nfargs - i)
+						goto Lnomatch;
+				}
+				case Tarray:
+				{   
+					TypeArray ta = cast(TypeArray)tb;
+					for (; i < nfargs; i++)
+					{
+						Expression arg = cast(Expression)fargs.data[i];
+						assert(arg);
+						MATCH m;
+						/* If lazy array of delegates,
+						 * convert arg(s) to delegate(s)
+						 */
+						Type tret = fparam.isLazyArray();
+						if (tret)
+						{
+							if (ta.next.equals(arg.type))
+							{   
+								m = MATCHexact;
+							}
+							else
+							{
+								m = arg.implicitConvTo(tret);
+								if (m == MATCHnomatch)
+								{
+									if (tret.toBasetype().ty == Tvoid)
+										m = MATCHconvert;
+								}
+							}
+						}
+						else
+						{
+							m = arg.type.deduceType(paramscope, ta.next, parameters, dedtypes);
+							//m = arg.implicitConvTo(ta.next);
+						}
+						if (m == MATCHnomatch)
+							goto Lnomatch;
+						if (m < match)
+							match = m;
+					}
+					goto Lmatch;
+				}
+				case Tclass:
+				case Tident:
+					goto Lmatch;
+
+				default:
+					goto Lnomatch;
+			}
+		}
+
+	Lmatch:
+
+		/* Fill in any missing arguments with their defaults.
+		 */
+		for (size_t i = nargsi; i < dedargs.dim; i++)
+		{
+			TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i];
+			//printf("tp2[%d] = %s\n", i, tp2.ident.toChars());
+			/* For T:T*, the dedargs is the T*, dedtypes is the T
+			 * But for function templates, we really need them to match
+			 */
+			Object oarg = cast(Object)dedargs.data[i];
+			Object oded = cast(Object)dedtypes.data[i];
+			//printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded);
+			//if (oarg) printf("oarg: %s\n", oarg.toChars());
+			//if (oded) printf("oded: %s\n", oded.toChars());
+			if (!oarg)
+			{
+				if (oded)
+				{
+					if (tp2.specialization())
+					{   
+						/* The specialization can work as long as afterwards
+						 * the oded == oarg
+						 */
+						Declaration sparam;
+						dedargs.data[i] = cast(void*)oded;
+						MATCH m2 = tp2.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam, 0);
+						//printf("m2 = %d\n", m2);
+						if (!m2)
+							goto Lnomatch;
+						if (m2 < match)
+							match = m2;		// pick worst match
+						if (dedtypes.data[i] !is cast(void*)oded)
+							error("specialization not allowed for deduced parameter %s", tp2.ident.toChars());
+					}
+				}
+				else
+				{	
+					oded = tp2.defaultArg(loc, paramscope);
+					if (!oded)
+						goto Lnomatch;
+				}
+				declareParameter(paramscope, tp2, oded);
+				dedargs.data[i] = cast(void*)oded;
+			}
+		}
+
+	version (DMDV2) {
+		if (constraint)
+		{	/* Check to see if constraint is satisfied.
+			 */
+			Expression e = constraint.syntaxCopy();
+			paramscope.flags |= SCOPE.SCOPEstaticif;
+			e = e.semantic(paramscope);
+			e = e.optimize(WANTvalue | WANTinterpret);
+			if (e.isBool(true)) {
+				;
+			} else if (e.isBool(false))
+				goto Lnomatch;
+			else
+			{
+				e.error("constraint %s is not constant or does not evaluate to a bool", e.toChars());
+			}
+		}
+	}
+
+	static if (false) {
+		for (i = 0; i < dedargs.dim; i++)
+		{	
+			Type t = cast(Type)dedargs.data[i];
+			printf("\tdedargs[%d] = %d, %s\n", i, t.dyncast(), t.toChars());
+		}
+	}
+
+		paramscope.pop();
+		//printf("\tmatch %d\n", match);
+		return match;
+
+	Lnomatch:
+		paramscope.pop();
+		//printf("\tnomatch\n");
+		return MATCHnomatch;
+	}
+    
+	/*************************************************
+	 * Given function arguments, figure out which template function
+	 * to expand, and return that function.
+	 * If no match, give error message and return null.
+	 * Input:
+	 *	sc		instantiation scope
+	 *	loc		instantiation location
+	 *	targsi		initial list of template arguments
+	 *	ethis		if !null, the 'this' pointer argument
+	 *	fargs		arguments to function
+	 *	flags		1: do not issue error message on no match, just return null
+	 */
+	FuncDeclaration deduceFunctionTemplate(Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions fargs, int flags = 0)
+	{
+		MATCH m_best = MATCHnomatch;
+		TemplateDeclaration td_ambig = null;
+		TemplateDeclaration td_best = null;
+		Objects tdargs = new Objects();
+		TemplateInstance ti;
+		FuncDeclaration fd;
+
+	static if (false) {
+		printf("TemplateDeclaration.deduceFunctionTemplate() %s\n", toChars());
+		printf("    targsi:\n");
+		if (targsi)
+		{	
+			for (int i = 0; i < targsi.dim; i++)
+			{   
+				Object arg = cast(Object)targsi.data[i];
+				printf("\t%s\n", arg.toChars());
+			}
+		}
+		printf("    fargs:\n");
+		for (int i = 0; i < fargs.dim; i++)
+		{	
+			Expression arg = cast(Expression)fargs.data[i];
+			printf("\t%s %s\n", arg.type.toChars(), arg.toChars());
+			//printf("\tty = %d\n", arg.type.ty);
+		}
+	}
+
+		for (TemplateDeclaration td = this; td; td = td.overnext)
+		{
+			if (!td.semanticRun)
+			{
+				error("forward reference to template %s", td.toChars());
+				goto Lerror;
+			}
+			if (!td.onemember || !td.onemember.toAlias().isFuncDeclaration())
+			{
+				error("is not a function template");
+				goto Lerror;
+			}
+
+			MATCH m;
+			scope Objects dedargs = new Objects();
+
+			m = td.deduceFunctionTemplateMatch(loc, targsi, ethis, fargs, dedargs);
+			//printf("deduceFunctionTemplateMatch = %d\n", m);
+			if (!m)			// if no match
+				continue;
+
+			if (m < m_best)
+				goto Ltd_best;
+			if (m > m_best)
+				goto Ltd;
+
+			{
+				// Disambiguate by picking the most specialized TemplateDeclaration
+				MATCH c1 = td.leastAsSpecialized(td_best);
+				MATCH c2 = td_best.leastAsSpecialized(td);
+				//printf("c1 = %d, c2 = %d\n", c1, c2);
+
+				if (c1 > c2)
+					goto Ltd;
+				else if (c1 < c2)
+					goto Ltd_best;
+				else
+					goto Lambig;
+			}
+
+			  Lambig:		// td_best and td are ambiguous
+			td_ambig = td;
+			continue;
+
+			  Ltd_best:		// td_best is the best match so far
+			td_ambig = null;
+			continue;
+
+			  Ltd:		// td is the new best match
+			td_ambig = null;
+			assert(cast(size_t)cast(void*)td.scope_ > 0x10000);
+			td_best = td;
+			m_best = m;
+			tdargs.setDim(dedargs.dim);
+			memcpy(tdargs.data, dedargs.data, tdargs.dim * (void*).sizeof);
+			continue;
+		}
+		if (!td_best)
+		{
+			if (!(flags & 1))
+				error(loc, "does not match any function template declaration");
+			goto Lerror;
+		}
+		if (td_ambig)
+		{
+			error(loc, "matches more than one function template declaration:\n  %s\nand:\n  %s",
+				td_best.toChars(), td_ambig.toChars());
+		}
+
+		/* The best match is td_best with arguments tdargs.
+		 * Now instantiate the template.
+		 */
+		assert(cast(size_t)cast(void*)td_best.scope_ > 0x10000);
+		ti = new TemplateInstance(loc, td_best, tdargs);
+		ti.semantic(sc);
+		fd = ti.toAlias().isFuncDeclaration();
+		if (!fd)
+		goto Lerror;
+		return fd;
+
+	  Lerror:
+///	version (DMDV2) {
+		if (!(flags & 1))
+///	}
+		{
+			HdrGenState hgs;
+
+			scope OutBuffer bufa = new OutBuffer();
+			Objects args = targsi;
+			if (args)
+			{   
+				for (int i = 0; i < args.dim; i++)
+				{
+					if (i)
+						bufa.writeByte(',');
+					Object oarg = cast(Object)args.data[i];
+					ObjectToCBuffer(bufa, &hgs, oarg);
+				}
+			}
+
+			scope OutBuffer buf = new OutBuffer();
+			argExpTypesToCBuffer(buf, fargs, &hgs);
+			error(loc, "cannot deduce template function from argument types !(%s)(%s)", bufa.toChars(), buf.toChars());
+		}
+		return null;
+	}
+	
+	/**************************************************
+	 * Declare template parameter tp with value o, and install it in the scope sc.
+	 */
+    void declareParameter(Scope sc, TemplateParameter tp, Object o)
+	{
+		//printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o);
+
+		Type targ = isType(o);
+		Expression ea = isExpression(o);
+		Dsymbol sa = isDsymbol(o);
+		Tuple va = isTuple(o);
+
+		Dsymbol s;
+
+		// See if tp.ident already exists with a matching definition
+		Dsymbol scopesym;
+		s = sc.search(loc, tp.ident, &scopesym);
+		if (s && scopesym == sc.scopesym)
+		{
+			TupleDeclaration td = s.isTupleDeclaration();
+			if (va && td)
+			{   
+				Tuple tup = new Tuple();
+				assert(false);	// < not implemented
+				///tup.objects = *td.objects;
+				if (match(va, tup, this, sc))
+				{
+					return;
+				}
+			}
+		}
+
+		if (targ)
+		{
+			//printf("type %s\n", targ.toChars());
+			s = new AliasDeclaration(Loc(0), tp.ident, targ);
+		}
+		else if (sa)
+		{
+			//printf("Alias %s %s;\n", sa.ident.toChars(), tp.ident.toChars());
+			s = new AliasDeclaration(Loc(0), tp.ident, sa);
+		}
+		else if (ea)
+		{
+			// tdtypes.data[i] always matches ea here
+			Initializer init = new ExpInitializer(loc, ea);
+			TemplateValueParameter tvp = tp.isTemplateValueParameter();
+
+			Type t = tvp ? tvp.valType : null;
+
+			VarDeclaration v = new VarDeclaration(loc, t, tp.ident, init);
+			v.storage_class = STCmanifest;
+			s = v;
+		}
+		else if (va)
+		{
+			//printf("\ttuple\n");
+			s = new TupleDeclaration(loc, tp.ident, va.objects);
+		}
+		else
+		{
+			debug writefln(o.toString());
+			assert(0);
+		}
+
+		if (!sc.insert(s))
+			error("declaration %s is already defined", tp.ident.toChars());
+
+		s.semantic(sc);
+	}
+	
+    TemplateDeclaration isTemplateDeclaration() { return this; }
+
+    TemplateTupleParameter isVariadic()
+	{
+		return .isVariadic(parameters);
+	}
+	
+    bool isOverloadable()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,31 @@
+module dmd.TemplateExp;
+
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.HdrGenState;
+import dmd.TemplateDeclaration;
+import dmd.TOK;
+
+class TemplateExp : Expression
+{
+	TemplateDeclaration td;
+
+	this(Loc loc, TemplateDeclaration td)
+	{
+		super(loc, TOK.TOKtemplate, TemplateExp.sizeof);
+		//printf("TemplateExp(): %s\n", td.toChars());
+		this.td = td;
+	}
+
+	void rvalue()
+	{
+		error("template %s has no value", toChars());
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(td.toChars());
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateInstance.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1386 @@
+module dmd.TemplateInstance;
+
+import dmd.ScopeDsymbol;
+import dmd.IntegerExp;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.TupleDeclaration;
+import dmd.TemplateParameter;
+import dmd.AliasDeclaration;
+import dmd.TemplateDeclaration;
+import dmd.TupleExp;
+import dmd.WithScopeSymbol;
+import dmd.Dsymbol;
+import dmd.Module;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.Global;
+import dmd.Util;
+import dmd.Type;
+import dmd.Expression;
+import dmd.Tuple;
+import dmd.STC;
+import dmd.TOK;
+import dmd.TY;
+import dmd.TypeTuple;
+import dmd.Argument;
+import dmd.WANT;
+import dmd.ExpInitializer;
+import dmd.Array;
+import dmd.DsymbolTable;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.VarDeclaration;
+import dmd.VarExp;
+import dmd.FuncExp;
+import dmd.Declaration;
+import dmd.MATCH;
+
+import dmd.backend.glue;
+
+Tuple isTuple(Object o)
+{
+    //return dynamic_cast<Tuple *>(o);
+    ///if (!o || o.dyncast() != DYNCAST_TUPLE)
+	///	return null;
+    return cast(Tuple)o;
+}
+
+/******************************
+ * If o1 matches o2, return 1.
+ * Else, return 0.
+ */
+
+bool match(Object o1, Object o2, TemplateDeclaration tempdecl, Scope sc)
+{
+    Type t1 = isType(o1);
+    Type t2 = isType(o2);
+    Expression e1 = isExpression(o1);
+    Expression e2 = isExpression(o2);
+    Dsymbol s1 = isDsymbol(o1);
+    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
+     * we'll do that another day.
+     */
+
+    if (t1)
+    {
+		/* if t1 is an instance of ti, then give error
+		 * about recursive expansions.
+		 */
+		Dsymbol s = t1.toDsymbol(sc);
+		if (s && s.parent)
+		{   
+			TemplateInstance ti1 = s.parent.isTemplateInstance();
+			if (ti1 && ti1.tempdecl == tempdecl)
+			{
+				for (Scope sc1 = sc; sc1; sc1 = sc1.enclosing)
+				{
+					if (sc1.scopesym == ti1)
+					{
+						error("recursive template expansion for template argument %s", t1.toChars());
+						return true;	// fake a match
+					}
+				}
+			}
+		}
+
+		//printf("t1 = %s\n", t1.toChars());
+		//printf("t2 = %s\n", t2.toChars());
+		if (!t2 || !t1.equals(t2))
+			goto Lnomatch;
+    }
+    else if (e1)
+    {
+static if (false) {
+		if (e1 && e2)
+		{
+			printf("match %d\n", e1.equals(e2));
+			e1.print();
+			e2.print();
+			e1.type.print();
+			e2.type.print();
+		}
+}
+		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 Lnomatch;
+		}
+	version (DMDV2) {
+		VarDeclaration vv1 = s1.isVarDeclaration();
+		VarDeclaration vv2 = s2.isVarDeclaration();
+		if (vv1 && vv2 && vv1.storage_class & vv2.storage_class & STCmanifest)
+		{   
+			ExpInitializer ei1 = vv1.init.isExpInitializer();
+			ExpInitializer ei2 = vv2.init.isExpInitializer();
+			if (ei1 && ei2 && !ei1.exp.equals(ei2.exp))
+				goto Lnomatch;
+		}
+	}
+    }
+    else if (v1)
+    {
+		if (!v2)
+			goto Lnomatch;
+
+		if (v1.objects.dim != v2.objects.dim)
+			goto Lnomatch;
+
+		for (size_t i = 0; i < v1.objects.dim; i++)
+		{
+			if (!match(cast(Object)v1.objects.data[i], cast(Object)v2.objects.data[i], tempdecl, sc))
+				goto Lnomatch;
+		}
+    }
+    //printf("match\n");
+    return true;	// match
+
+Lnomatch:
+    //printf("nomatch\n");
+    return false;	// nomatch;
+}
+
+class TemplateInstance : ScopeDsymbol
+{
+    /* Given:
+     *	foo!(args) =>
+     *	    name = foo
+     *	    tiargs = args
+     */
+    Identifier name;
+    //Array idents;
+    Objects tiargs;		// Array of Types/Expressions of template
+				// instance arguments [int*, char, 10*10]
+
+    Objects tdtypes;		// Array of Types/Expressions corresponding
+				// to TemplateDeclaration.parameters
+				// [int, char, 100]
+
+    TemplateDeclaration tempdecl;	// referenced by foo.bar.abc
+    TemplateInstance inst;		// refer to existing instance
+    TemplateInstance tinst;		// enclosing template instance
+    ScopeDsymbol argsym;		// argument symbol table
+    AliasDeclaration aliasdecl;	// !=null if instance is an alias for its
+					// sole member
+    WithScopeSymbol withsym;		// if a member of a with statement
+    int semanticRun;	// has semantic() been done?
+    int semantictiargsdone;	// has semanticTiargs() been done?
+    int nest;		// for recursion detection
+    int havetempdecl;	// 1 if used second constructor
+    Dsymbol isnested;	// if referencing local symbols, this is the context
+    int errors;		// 1 if compiled with errors
+version (IN_GCC) {
+    /* On some targets, it is necessary to know whether a symbol
+       will be emitted in the output or not before the symbol
+       is used.  This can be different from getModule(). */
+    Module objFileModule;
+}
+
+    this(Loc loc, Identifier ident)
+	{
+		super(null);
+		
+	version (LOG) {
+		printf("TemplateInstance(this = %p, ident = '%s')\n", this, ident ? ident.toChars() : "null");
+	}
+		this.loc = loc;
+		this.name = ident;
+		
+		tdtypes = new Objects();
+	}
+
+	/*****************
+	 * This constructor is only called when we figured out which function
+	 * template to instantiate.
+	 */
+    this(Loc loc, TemplateDeclaration td, Objects tiargs)
+	{
+		super(null);
+		
+	version (LOG) {
+		printf("TemplateInstance(this = %p, tempdecl = '%s')\n", this, td.toChars());
+	}
+		this.loc = loc;
+		this.name = td.ident;
+		this.tiargs = tiargs;
+		this.tempdecl = td;
+		this.semantictiargsdone = 1;
+		this.havetempdecl = 1;
+
+		assert(cast(size_t)cast(void*)tempdecl.scope_ > 0x10000);
+		
+		tdtypes = new Objects();
+	}
+
+    static Objects arraySyntaxCopy(Objects objs)
+	{
+		assert(false);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+
+    void semantic(Scope sc)
+	{
+	    if (global.errors)
+		{
+			if (!global.gag)
+			{
+				/* Trying to soldier on rarely generates useful messages
+				 * at this point.
+				 */
+				fatal();
+			}
+			return;
+		}
+
+	version (LOG) {
+		printf("\n+TemplateInstance.semantic('%s', this=%p)\n", toChars(), this);
+	}
+
+		if (inst)		// if semantic() was already run
+		{
+version (LOG) {
+			printf("-TemplateInstance.semantic('%s', this=%p) already run\n", inst.toChars(), inst);
+}
+			return;
+		}
+
+		// get the enclosing template instance from the scope tinst
+		tinst = sc.tinst;
+
+		if (semanticRun != 0)
+		{
+			error(loc, "recursive template expansion");
+		//	inst = this;
+			return;
+		}
+
+		semanticRun = 1;
+
+	version (LOG) {
+		printf("\tdo semantic\n");
+	}
+		if (havetempdecl)
+		{
+			assert(cast(size_t)cast(void*)tempdecl.scope_ > 0x10000);
+
+			// Deduce tdtypes
+			tdtypes.setDim(tempdecl.parameters.dim);
+			if (!tempdecl.matchWithInstance(this, tdtypes, 2))
+			{
+				error("incompatible arguments for template instantiation");
+				inst = this;
+				return;
+			}
+		}
+		else
+		{
+			/* Run semantic on each argument, place results in tiargs[]
+			 * (if we havetempdecl, then tiargs is already evaluated)
+			 */
+			semanticTiargs(sc);
+
+			tempdecl = findTemplateDeclaration(sc);
+			if (tempdecl)
+				tempdecl = findBestMatch(sc);
+
+			if (!tempdecl || global.errors)
+			{   
+				inst = this;
+				//printf("error return %p, %d\n", tempdecl, global.errors);
+				return;		// error recovery
+			}
+		}
+
+		hasNestedArgs(tiargs);
+
+		/* See if there is an existing TemplateInstantiation that already
+		 * implements the typeargs. If so, just refer to that one instead.
+		 */
+
+		for (size_t i = 0; i < tempdecl.instances.dim; i++)
+		{
+			TemplateInstance ti = cast(TemplateInstance)tempdecl.instances.data[i];
+		version (LOG) {
+			printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti.toChars());
+		}
+			assert(tdtypes.dim == ti.tdtypes.dim);
+
+			// Nesting must match
+			if (isnested !is ti.isnested)
+			{
+				//printf("test2 isnested %s ti.isnested %s\n", isnested ? isnested.toChars() : "", ti.isnested ? ti.isnested.toChars() : "");
+				continue;
+			}
+		static if (false) {
+			if (isnested && sc.parent != ti.parent)
+				continue;
+		}
+			for (size_t j = 0; j < tdtypes.dim; j++)
+			{   
+				Object o1 = cast(Object)tdtypes.data[j];
+				Object o2 = cast(Object)ti.tdtypes.data[j];
+				if (!match(o1, o2, tempdecl, sc))
+				{
+					goto L1;
+				}
+			}
+
+			// It's a match
+			inst = ti;
+			parent = ti.parent;
+		version (LOG) {
+			printf("\tit's a match with instance %p\n", inst);
+		}
+			return;
+
+		L1:
+			;
+		}
+
+		/* So, we need to implement 'this' instance.
+		 */
+	version (LOG) {
+		printf("\timplement template instance '%s'\n", toChars());
+	}
+		uint errorsave = global.errors;
+		inst = this;
+		int tempdecl_instance_idx = tempdecl.instances.dim;
+		tempdecl.instances.push(cast(void*)this);
+		parent = tempdecl.parent;
+		//printf("parent = '%s'\n", parent.kind());
+
+		ident = genIdent();		// need an identifier for name mangling purposes.
+
+	static if (true) {
+		if (isnested)
+			parent = isnested;
+	}
+		//printf("parent = '%s'\n", parent.kind());
+
+		// Add 'this' to the enclosing scope's members[] so the semantic routines
+		// will get called on the instance members
+	static if (true) {
+		int dosemantic3 = 0;
+		{	
+			Array a;
+
+			Scope scx = sc;
+	static if (false) {
+			for (scx = sc; scx; scx = scx.enclosing)
+				if (scx.scopesym)
+					break;
+	}
+
+			//if (scx && scx.scopesym) printf("3: scx is %s %s\n", scx.scopesym.kind(), scx.scopesym.toChars());
+			if (scx && scx.scopesym &&
+				scx.scopesym.members && !scx.scopesym.isTemplateMixin()
+
+///	static if (false) {	// removed because it bloated compile times
+///				/* The problem is if A imports B, and B imports A, and both A
+///				 * and B instantiate the same template, does the compilation of A
+///				 * or the compilation of B do the actual instantiation?
+///				 *
+///				 * see bugzilla 2500.
+///				 */
+///				&& !scx.module.selfImports()
+///	}
+			   )
+			{
+				//printf("\t1: adding to %s %s\n", scx.scopesym.kind(), scx.scopesym.toChars());
+				a = scx.scopesym.members;
+			}
+			else
+			{   Module m = sc.module_.importedFrom;
+				//printf("\t2: adding to module %s instead of module %s\n", m.toChars(), sc.module.toChars());
+				a = m.members;
+				if (m.semanticRun >= 3)
+					dosemantic3 = 1;
+			}
+
+			for (int i = 0; 1; i++)
+			{
+				if (i == a.dim)
+				{
+					a.push(cast(void*)this);
+					break;
+				}
+
+				if (this is cast(Dsymbol)a.data[i])	// if already in Array
+					break;
+			}
+		}
+	}
+
+		// Copy the syntax trees from the TemplateDeclaration
+		members = Dsymbol.arraySyntaxCopy(tempdecl.members);
+
+		// Create our own scope for the template parameters
+		Scope scope_ = tempdecl.scope_;
+		if (!tempdecl.semanticRun)
+		{
+			error("template instantiation %s forward references template declaration %s\n", toChars(), tempdecl.toChars());
+			return;
+		}
+
+	version (LOG) {
+		printf("\tcreate scope for template parameters '%s'\n", toChars());
+	}
+		argsym = new ScopeDsymbol();
+		argsym.parent = scope_.parent;
+		scope_ = scope_.push(argsym);
+	//    scope.stc = 0;
+
+		// Declare each template parameter as an alias for the argument type
+		Scope paramscope = scope_.push();
+		paramscope.stc = STCundefined;
+		declareParameters(paramscope);
+		paramscope.pop();
+
+		// Add members of template instance to template instance symbol table
+	//    parent = scope.scopesym;
+		symtab = new DsymbolTable();
+		int memnum = 0;
+		for (int i = 0; i < members.dim; i++)
+		{
+			Dsymbol s = cast(Dsymbol)members.data[i];
+	version (LOG) {
+			printf("\t[%d] adding member '%s' %p kind %s to '%s', memnum = %d\n", i, s.toChars(), s, s.kind(), this.toChars(), memnum);
+	}
+			memnum |= s.addMember(scope_, this, memnum);
+		}
+
+	version (LOG) {
+		printf("adding members done\n");
+	}
+
+		/* See if there is only one member of template instance, and that
+		 * member has the same name as the template instance.
+		 * If so, this template instance becomes an alias for that member.
+		 */
+		//printf("members.dim = %d\n", members.dim);
+		if (members.dim)
+		{
+			Dsymbol s;
+			if (Dsymbol.oneMembers(members, &s) && s)
+			{
+				//printf("s.kind = '%s'\n", s.kind());
+				//s.print();
+				//printf("'%s', '%s'\n", s.ident.toChars(), tempdecl.ident.toChars());
+				if (s.ident && s.ident.equals(tempdecl.ident))
+				{
+					//printf("setting aliasdecl\n");
+					aliasdecl = new AliasDeclaration(loc, s.ident, s);
+				}
+			}
+		}
+
+		// Do semantic() analysis on template instance members
+	version (LOG) {
+		printf("\tdo semantic() on template instance members '%s'\n", toChars());
+	}
+		Scope sc2;
+		sc2 = scope_.push(this);
+		//printf("isnested = %d, sc.parent = %s\n", isnested, sc.parent.toChars());
+		sc2.parent = /*isnested ? sc.parent :*/ this;
+		sc2.tinst = this;
+
+		try
+		{
+			static int nest;
+			//printf("%d\n", nest);
+			if (++nest > 500)
+			{
+				global.gag = 0;			// ensure error message gets printed
+				error("recursive expansion");
+				fatal();
+			}
+			for (int i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+				//printf("\t[%d] semantic on '%s' %p kind %s in '%s'\n", i, s.toChars(), s, s.kind(), this.toChars());
+				//printf("test: isnested = %d, sc2.parent = %s\n", isnested, sc2.parent.toChars());
+				//	if (isnested)
+				//	    s.parent = sc.parent;
+				//printf("test3: isnested = %d, s.parent = %s\n", isnested, s.parent.toChars());
+				s.semantic(sc2);
+				//printf("test4: isnested = %d, s.parent = %s\n", isnested, s.parent.toChars());
+				sc2.module_.runDeferredSemantic();
+			}
+			--nest;
+		}
+		catch
+		{
+			global.gag = 0;			// ensure error message gets printed
+			error("recursive expansion");
+			fatal();
+		}
+
+		/* If any of the instantiation members didn't get semantic() run
+		 * on them due to forward references, we cannot run semantic2()
+		 * or semantic3() yet.
+		 */
+		for (size_t i = 0; i < Module.deferred.dim; i++)
+		{	
+			Dsymbol sd = cast(Dsymbol)Module.deferred.data[i];
+
+			if (sd.parent is this)
+				goto Laftersemantic;
+		}
+
+		/* The problem is when to parse the initializer for a variable.
+		 * Perhaps VarDeclaration.semantic() should do it like it does
+		 * for initializers inside a function.
+		 */
+		//    if (sc.parent.isFuncDeclaration())
+
+		/* BUG 782: this has problems if the classes this depends on
+		 * are forward referenced. Find a way to defer semantic()
+		 * on this template.
+		 */
+		semantic2(sc2);
+
+		if (sc.func || dosemantic3)
+		{
+			semantic3(sc2);
+		}
+
+	Laftersemantic:
+		sc2.pop();
+
+		scope_.pop();
+
+		// Give additional context info if error occurred during instantiation
+		if (global.errors != errorsave)
+		{
+			error("error instantiating");
+			if (tinst && !global.gag)
+			{   
+				tinst.printInstantiationTrace();
+				fatal();
+			}
+			errors = 1;
+			if (global.gag)
+				tempdecl.instances.remove(tempdecl_instance_idx);
+		}
+
+	version (LOG) {
+		printf("-TemplateInstance.semantic('%s', this=%p)\n", toChars(), this);
+	}
+	}
+
+    void semantic2(Scope sc)
+	{
+		int i;
+
+		if (semanticRun >= 2)
+			return;
+
+		semanticRun = 2;
+	version (LOG) {
+		printf("+TemplateInstance::semantic2('%s')\n", toChars());
+	}
+
+		if (!errors && members)
+		{
+			sc = tempdecl.scope_;
+			assert(sc);
+			sc = sc.push(argsym);
+			sc = sc.push(this);
+			sc.tinst = this;
+
+			for (i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+	version (LOG) {
+				printf("\tmember '%s', kind = '%s'\n", s.toChars(), s.kind());
+	}
+				s.semantic2(sc);
+			}
+
+			sc = sc.pop();
+			sc.pop();
+		}
+
+	version (LOG) {
+		printf("-TemplateInstance::semantic2('%s')\n", toChars());
+	}
+	}
+
+    void semantic3(Scope sc)
+	{
+	version (LOG) {
+		printf("TemplateInstance.semantic3('%s'), semanticRun = %d\n", toChars(), semanticRun);
+	}
+	//if (toChars()[0] == 'D') *(char*)0=0;
+		if (semanticRun >= 3)
+			return;
+		semanticRun = 3;
+		if (!errors && members)
+		{
+			sc = tempdecl.scope_;
+			sc = sc.push(argsym);
+			sc = sc.push(this);
+			sc.tinst = this;
+			for (int i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+				s.semantic3(sc);
+			}
+			sc = sc.pop();
+			sc.pop();
+		}
+	}
+
+    void inlineScan()
+	{
+	version (LOG) {
+		printf("TemplateInstance.inlineScan('%s')\n", toChars());
+	}
+		if (!errors && members)
+		{
+			for (int i = 0; i < members.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)members.data[i];
+				s.inlineScan();
+			}
+		}
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		int i;
+
+		Identifier id = name;
+		buf.writestring(id.toChars());
+		buf.writestring("!(");
+		if (nest)
+			buf.writestring("...");
+		else
+		{
+			nest++;
+			Objects args = tiargs;
+			for (i = 0; i < args.dim; i++)
+			{
+				if (i)
+					buf.writeByte(',');
+				Object oarg = cast(Object)args.data[i];
+				ObjectToCBuffer(buf, hgs, oarg);
+			}
+			nest--;
+		}
+		buf.writeByte(')');
+	}
+	
+    Dsymbol toAlias()			// resolve real symbol
+	{
+	version (LOG) {
+		printf("TemplateInstance::toAlias()\n");
+	}
+		if (!inst)
+		{	
+			error("cannot resolve forward reference");
+			return this;
+		}
+
+		if (inst !is this)
+			return inst.toAlias();
+
+		if (aliasdecl)
+		{
+			return aliasdecl.toAlias();
+		}
+
+		return inst;
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		scope OutBuffer buf = new OutBuffer();
+		HdrGenState hgs;
+
+		toCBuffer(buf, &hgs);
+		return buf.extractString();
+	}
+	
+    string mangle()
+	{
+		assert(false);
+	}
+	
+    void printInstantiationTrace()
+	{
+		assert(false);
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+	version (LOG) {
+		printf("TemplateInstance.toObjFile('%s', this = %p)\n", toChars(), this);
+	}
+		if (!errors && members)
+		{
+			if (multiobj)
+				// Append to list of object files to be written later
+				obj_append(this);
+			else
+			{
+				for (int i = 0; i < members.dim; i++)
+				{
+					Dsymbol s = cast(Dsymbol)members.data[i];
+					s.toObjFile(multiobj);
+				}
+			}
+		}
+	}
+
+    // Internal
+	/**********************************
+	 * Input:
+	 *	flags	1: replace const variables with their initializers
+	 */
+    static void semanticTiargs(Loc loc, Scope sc, Objects tiargs, int flags)
+	{
+		// Run semantic on each argument, place results in tiargs[]
+		//printf("+TemplateInstance.semanticTiargs() %s\n", toChars());
+		if (!tiargs)
+			return;
+		for (size_t j = 0; j < tiargs.dim; j++)
+		{
+			Object o = cast(Object)tiargs.data[j];
+			Type ta = isType(o);
+			Expression ea = isExpression(o);
+			Dsymbol sa = isDsymbol(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());
+				// It might really be an Expression or an Alias
+				ta.resolve(loc, sc, &ea, &ta, &sa);
+				if (ea)
+				{
+					ea = ea.semantic(sc);
+					/* This test is to skip substituting a const var with
+					 * its initializer. The problem is the initializer won't
+					 * match with an 'alias' parameter. Instead, do the
+					 * const substitution in TemplateValueParameter.matchArg().
+					 */
+					if (ea.op != TOKvar || flags & 1)
+						ea = ea.optimize(WANTvalue | WANTinterpret);
+
+					tiargs.data[j] = cast(void*)ea;
+				}
+				else if (sa)
+				{	
+					tiargs.data[j] = cast(void*)sa;
+					TupleDeclaration d = sa.toAlias().isTupleDeclaration();
+					if (d)
+					{
+						size_t dim = d.objects.dim;
+						tiargs.remove(j);
+						tiargs.insert(j, d.objects);
+						j--;
+					}
+				}
+				else if (ta)
+				{
+				Ltype:
+					if (ta.ty == Ttuple)
+					{   
+						// Expand tuple
+						TypeTuple tt = cast(TypeTuple)ta;
+						size_t dim = tt.arguments.dim;
+						tiargs.remove(j);
+						if (dim)
+						{	
+							tiargs.reserve(dim);
+							for (size_t i = 0; i < dim; i++)
+							{   
+								Argument arg = cast(Argument)tt.arguments.data[i];
+								tiargs.insert(j + i, cast(void*)arg.type);
+							}
+						}
+						j--;
+					}
+					else
+						tiargs.data[j] = cast(void*)ta;
+				}
+				else
+				{
+					assert(global.errors);
+					tiargs.data[j] = cast(void*)Type.terror;
+				}
+			}
+			else if (ea)
+			{
+				if (!ea)
+				{	
+					assert(global.errors);
+					ea = new IntegerExp(0);
+				}
+				assert(ea);
+				ea = ea.semantic(sc);
+				if (ea.op != TOKvar || flags & 1)
+					ea = ea.optimize(WANTvalue | WANTinterpret);
+				tiargs.data[j] = cast(void*)ea;
+				if (ea.op == TOKtype)
+				{	
+					ta = ea.type;
+					goto Ltype;
+				}
+				if (ea.op == TOKtuple)
+				{   
+					// Expand tuple
+					TupleExp te = cast(TupleExp)ea;
+					size_t dim = te.exps.dim;
+					tiargs.remove(j);
+					if (dim)
+					{   
+						tiargs.reserve(dim);
+						for (size_t i = 0; i < dim; i++)
+						tiargs.insert(j + i, te.exps.data[i]);
+					}
+					j--;
+				}
+			}
+			else if (sa)
+			{
+				TemplateDeclaration td = sa.isTemplateDeclaration();
+				if (td && !td.semanticRun && td.literal)
+					td.semantic(sc);
+			}
+			else
+			{
+				assert(0);
+			}
+			//printf("1: tiargs.data[%d] = %p\n", j, tiargs.data[j]);
+		}
+
+static if (false) {
+		printf("-TemplateInstance.semanticTiargs('%s', this=%p)\n", toChars(), this);
+		for (size_t j = 0; j < tiargs.dim; j++)
+		{
+			Object o = cast(Object)tiargs.data[j];
+			Type ta = isType(o);
+			Expression ea = isExpression(o);
+			Dsymbol sa = isDsymbol(o);
+			Tuple va = isTuple(o);
+
+			printf("\ttiargs[%d] = ta %p, ea %p, sa %p, va %p\n", j, ta, ea, sa, va);
+		}
+}
+	}
+
+    void semanticTiargs(Scope sc)
+	{
+		//printf("+TemplateInstance.semanticTiargs() %s\n", toChars());
+		if (semantictiargsdone)
+			return;
+
+		semantictiargsdone = 1;
+		semanticTiargs(loc, sc, tiargs, 0);
+	}
+
+	/**********************************************
+	 * Find template declaration corresponding to template instance.
+	*/
+	TemplateDeclaration findTemplateDeclaration(Scope sc)
+	{
+		//printf("TemplateInstance.findTemplateDeclaration() %s\n", toChars());
+		if (!tempdecl)
+		{
+			/* Given:
+			 *    foo!( ... )
+			 * figure out which TemplateDeclaration foo refers to.
+			 */
+			Dsymbol s;
+			Dsymbol scopesym;
+			int i;
+
+			Identifier id = name;
+			s = sc.search(loc, id, &scopesym);
+			if (!s)
+			{   
+				error("identifier '%s' is not defined", id.toChars());
+				return null;
+			}
+		version (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());
+		}
+			withsym = scopesym.isWithScopeSymbol();
+
+			/* We might have found an alias within a template when
+			 * we really want the template.
+			 */
+			TemplateInstance ti;
+			if (s.parent &&
+				(ti = s.parent.isTemplateInstance()) !is null)
+			{
+				if (
+					(ti.name == id ||
+					ti.toAlias().ident == id)
+					&&
+					ti.tempdecl
+				  )
+				{
+					/* This is so that one can refer to the enclosing
+					 * template, even if it has the same name as a member
+					 * of the template, if it has a !(arguments)
+					 */
+					tempdecl = ti.tempdecl;
+					if (tempdecl.overroot)		// if not start of overloaded list of TemplateDeclaration's
+						tempdecl = tempdecl.overroot; // then get the start
+
+					s = tempdecl;
+				}
+			}
+
+			s = s.toAlias();
+
+			/* It should be a TemplateDeclaration, not some other symbol
+			 */
+			tempdecl = s.isTemplateDeclaration();
+			if (!tempdecl)
+			{
+				if (!s.parent && global.errors)
+				return null;
+				if (!s.parent && s.getType())
+				{	
+					Dsymbol s2 = s.getType().toDsymbol(sc);
+					if (!s2)
+					{
+						error("%s is not a template declaration, it is a %s", id.toChars(), s.kind());
+						return null;
+					}
+					s = s2;
+				}
+		debug {
+				//if (!s.parent) printf("s = %s %s\n", s.kind(), s.toChars());
+		}
+				//assert(s.parent);
+				TemplateInstance ti2 = s.parent ? s.parent.isTemplateInstance() : null;
+				if (ti2 &&
+					(ti2.name == id ||
+					ti2.toAlias().ident == id)
+					&&
+					ti2.tempdecl
+				  )
+				{
+					/* This is so that one can refer to the enclosing
+					 * template, even if it has the same name as a member
+					 * of the template, if it has a !(arguments)
+					 */
+					tempdecl = ti2.tempdecl;
+					if (tempdecl.overroot)		// if not start of overloaded list of TemplateDeclaration's
+						tempdecl = tempdecl.overroot; // then get the start
+				}
+				else
+				{
+					error("%s is not a template declaration, it is a %s", id.toChars(), s.kind());
+					return null;
+				}
+			}
+		}
+		else
+			assert(tempdecl.isTemplateDeclaration());
+
+		return tempdecl;
+	}
+
+    TemplateDeclaration findBestMatch(Scope sc)
+	{
+		/* Since there can be multiple TemplateDeclaration's with the same
+		 * name, look for the best match.
+		 */
+		TemplateDeclaration td_ambig = null;
+		TemplateDeclaration td_best = null;
+		MATCH m_best = MATCHnomatch;
+		scope Objects dedtypes = new Objects();
+
+	version (LOG) {
+		printf("TemplateInstance.findBestMatch()\n");
+	}
+		// First look for forward references
+		for (TemplateDeclaration td = tempdecl; td; td = td.overnext)
+		{
+			if (!td.semanticRun)
+			{
+				if (td.scope_)
+				{	
+					// Try to fix forward reference
+					td.semantic(td.scope_);
+				}
+				if (!td.semanticRun)
+				{
+					error("%s forward references template declaration %s\n", toChars(), td.toChars());
+					return null;
+				}
+			}
+		}
+
+		for (TemplateDeclaration td = tempdecl; td; td = td.overnext)
+		{
+			MATCH m;
+
+		//if (tiargs.dim) printf("2: tiargs.dim = %d, data[0] = %p\n", tiargs.dim, tiargs.data[0]);
+
+			// If more arguments than parameters,
+			// then this is no match.
+			if (td.parameters.dim < tiargs.dim)
+			{
+				if (!td.isVariadic())
+					continue;
+			}
+
+			dedtypes.setDim(td.parameters.dim);
+			dedtypes.zero();
+			assert(td.semanticRun);
+			m = td.matchWithInstance(this, dedtypes, 0);
+			//printf("matchWithInstance = %d\n", m);
+			if (!m)			// no match at all
+				continue;
+
+			if (m < m_best)
+				goto Ltd_best;
+			if (m > m_best)
+				goto Ltd;
+
+			{
+				// Disambiguate by picking the most specialized TemplateDeclaration
+				MATCH c1 = td.leastAsSpecialized(td_best);
+				MATCH c2 = td_best.leastAsSpecialized(td);
+				//printf("c1 = %d, c2 = %d\n", c1, c2);
+
+				if (c1 > c2)
+					goto Ltd;
+				else if (c1 < c2)
+					goto Ltd_best;
+				else
+					goto Lambig;
+			}
+
+		Lambig:		// td_best and td are ambiguous
+			td_ambig = td;
+			continue;
+
+		Ltd_best:		// td_best is the best match so far
+			td_ambig = null;
+			continue;
+
+		Ltd:		// td is the new best match
+			td_ambig = null;
+			td_best = td;
+			m_best = m;
+			tdtypes.setDim(dedtypes.dim);
+			memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * (void*).sizeof);
+			continue;
+		}
+
+		if (!td_best)
+		{
+			if (tempdecl && !tempdecl.overnext)
+				// Only one template, so we can give better error message
+				error("%s does not match template declaration %s", toChars(), tempdecl.toChars());
+			else
+				error("%s does not match any template declaration", toChars());
+			return null;
+		}
+
+		if (td_ambig)
+		{
+			error("%s matches more than one template declaration, %s and %s",
+				toChars(), td_best.toChars(), td_ambig.toChars());
+		}
+
+		/* The best match is td_best
+		 */
+		tempdecl = td_best;
+
+	static if (false) {
+		/* Cast any value arguments to be same type as value parameter
+		 */
+		for (size_t i = 0; i < tiargs.dim; i++)
+		{	
+			Object o = cast(Object)tiargs.data[i];
+			Expression ea = isExpression(o);	// value argument
+			TemplateParameter tp = cast(TemplateParameter)tempdecl.parameters.data[i];
+			assert(tp);
+			TemplateValueParameter tvp = tp.isTemplateValueParameter();
+			if (tvp)
+			{
+				assert(ea);
+				ea = ea.castTo(tvp.valType);
+				ea = ea.optimize(WANTvalue | WANTinterpret);
+				tiargs.data[i] = cast(Object)ea;
+			}
+		}
+	}
+
+	version (LOG) {
+		printf("\tIt's a match with template declaration '%s'\n", tempdecl.toChars());
+	}
+		return tempdecl;
+	}
+
+	/****************************************************
+	 * Declare parameters of template instance, initialize them with the
+	 * template instance arguments.
+	 */
+    void declareParameters(Scope sc)
+	{
+		//printf("TemplateInstance::declareParameters()\n");
+		for (int i = 0; i < tdtypes.dim; i++)
+		{
+			TemplateParameter tp = cast(TemplateParameter)tempdecl.parameters.data[i];
+			//Object o = cast(Object)tiargs.data[i];
+			Object o = cast(Object)tdtypes.data[i];		// initializer for tp
+
+			//printf("\ttdtypes[%d] = %p\n", i, o);
+			tempdecl.declareParameter(sc, tp, o);
+		}
+	}
+
+	/*****************************************
+	 * Determines if a TemplateInstance will need a nested
+	 * generation of the TemplateDeclaration.
+	 */
+    bool hasNestedArgs(Objects args)
+	{
+		bool nested = false;
+		//printf("TemplateInstance::hasNestedArgs('%s')\n", tempdecl.ident.toChars());
+
+		/* A nested instance happens when an argument references a local
+		 * symbol that is on the stack.
+		 */
+		for (size_t i = 0; i < args.dim; i++)
+		{   
+			Object o = cast(Object)args.data[i];
+			Expression ea = isExpression(o);
+			Dsymbol sa = isDsymbol(o);
+			Tuple va = isTuple(o);
+			if (ea)
+			{
+				if (ea.op == TOKvar)
+				{
+					sa = (cast(VarExp)ea).var;
+					goto Lsa;
+				}
+				if (ea.op == TOKfunction)
+				{
+					sa = (cast(FuncExp)ea).fd;
+					goto Lsa;
+				}
+			}
+			else if (sa)
+			{
+			  Lsa:
+				Declaration d = null;
+				TemplateDeclaration td = sa.isTemplateDeclaration();
+				if (td && td.literal)
+				{
+					goto L2;
+				}
+				d = sa.isDeclaration();
+				if (d && !d.isDataseg() &&
+///		version (DMDV2) {
+					!(d.storage_class & STCmanifest) &&
+///		}
+					(!d.isFuncDeclaration() || d.isFuncDeclaration().isNested()) &&
+					!isTemplateMixin())
+				{
+					 L2:
+					// if module level template
+					if (tempdecl.toParent().isModule())
+					{   
+						Dsymbol dparent = sa.toParent();
+						if (!isnested)
+							isnested = dparent;
+						else if (isnested != dparent)
+						{
+							/* 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; p; p = p.parent)
+							{
+								if (p == isnested)
+								{	
+									isnested = dparent;
+									goto L1;	// dparent is most nested
+								}
+							}
+							error("%s is nested in both %s and %s",
+								toChars(), isnested.toChars(), dparent.toChars());
+						}
+					  L1:
+						//printf("\tnested inside %s\n", isnested.toChars());
+						nested |= 1;
+					}
+					else
+						error("cannot use local '%s' as parameter to non-global template %s", d.toChars(), tempdecl.toChars());
+				}
+			}
+			else if (va)
+			{
+				nested |= hasNestedArgs(va.objects);
+			}
+		}
+		return nested;
+	}
+
+	/****************************************
+	 * This instance needs an identifier for name mangling purposes.
+	 * Create one by taking the template declaration name and adding
+	 * the type signature for it.
+	 */
+    Identifier genIdent()
+	{
+		scope OutBuffer buf = new OutBuffer();
+		string id;
+		Objects args;
+
+		//printf("TemplateInstance::genIdent('%s')\n", tempdecl.ident.toChars());
+		id = tempdecl.ident.toChars();
+		buf.printf("__T%d%s", id.length, id);	///!
+		args = tiargs;
+		for (int i = 0; i < args.dim; i++)
+		{   
+			Object o = cast(Object)args.data[i];
+			Type ta = isType(o);
+			Expression ea = isExpression(o);
+			Dsymbol sa = isDsymbol(o);
+			Tuple va = isTuple(o);
+			//printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
+			if (ta)
+			{
+				buf.writeByte('T');
+				if (ta.deco)
+					buf.writestring(ta.deco);
+				else
+				{
+					debug writef("ta = %d, %s\n", ta.ty, ta.toChars());
+					assert(global.errors);
+				}
+			}
+			else if (ea)
+			{
+			  Lea:
+				long v;
+				real r;
+
+				ea = ea.optimize(WANTvalue | WANTinterpret);
+				if (ea.op == TOKvar)
+				{
+					sa = (cast(VarExp)ea).var;
+					ea = null;
+					goto Lsa;
+				}
+				if (ea.op == TOKfunction)
+				{
+					sa = (cast(FuncExp)ea).fd;
+					ea = null;
+					goto Lsa;
+				}
+				buf.writeByte('V');
+				if (ea.op == TOKtuple)
+				{	
+					ea.error("tuple is not a valid template value argument");
+					continue;
+				}
+		static if (true) {
+				/* Use deco that matches what it would be for a function parameter
+				 */
+				buf.writestring(ea.type.deco);
+		} else {
+				// Use type of parameter, not type of argument
+				TemplateParameter tp = cast(TemplateParameter)tempdecl.parameters.data[i];
+				assert(tp);
+				TemplateValueParameter tvp = tp.isTemplateValueParameter();
+				assert(tvp);
+				buf.writestring(tvp.valType.deco);
+		}
+				ea.toMangleBuffer(buf);
+			}
+			else if (sa)
+			{
+			  Lsa:
+				buf.writeByte('S');
+				Declaration d = sa.isDeclaration();
+				if (d && (!d.type || !d.type.deco))
+				{	
+					error("forward reference of %s", d.toChars());
+					continue;
+				}
+		static if (false) {
+				VarDeclaration v = sa.isVarDeclaration();
+				if (v && v.storage_class & STCmanifest)
+				{	
+					ExpInitializer ei = v.init.isExpInitializer();
+					if (ei)
+					{
+						ea = ei.exp;
+						goto Lea;
+					}
+				}
+		}
+				string p = sa.mangle();
+				buf.printf("%zu%s", p.length, p);
+			}
+			else if (va)
+			{
+				assert(i + 1 == args.dim);		// must be last one
+				args = va.objects;
+				i = -1;
+			}
+			else
+				assert(0);
+		}
+		buf.writeByte('Z');
+		id = buf.toChars();
+		buf.data = null;
+		//printf("\tgenIdent = %s\n", id);
+		return new Identifier(id, TOKidentifier);
+	}
+
+    TemplateInstance isTemplateInstance() { return this; }
+
+    AliasDeclaration isAliasDeclaration()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateMixin.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,81 @@
+module dmd.TemplateMixin;
+
+import dmd.TemplateInstance;
+import dmd.Array;
+import dmd.Type;
+import dmd.ArrayTypes;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class TemplateMixin : TemplateInstance
+{
+    Array idents;
+    Type tqual;
+
+    this(Loc loc, Identifier ident, Type tqual, Array idents, Objects tiargs)
+	{
+		assert(false);
+		super(loc, ident);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void semantic2(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void semantic3(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void inlineScan()
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    bool oneMember(Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    bool hasPointers()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		assert(false);
+	}
+
+    TemplateMixin isTemplateMixin() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateParameter.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,87 @@
+module dmd.TemplateParameter;
+
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Declaration;
+import dmd.TemplateTypeParameter;
+import dmd.TemplateValueParameter;
+import dmd.TemplateAliasParameter;
+import dmd.TemplateThisParameter;
+import dmd.TemplateTupleParameter;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.MATCH;
+import dmd.ArrayTypes;
+
+class TemplateParameter
+{
+    /* For type-parameter:
+     *	template Foo(ident)		// specType is set to NULL
+     *	template Foo(ident : specType)
+     * For value-parameter:
+     *	template Foo(valType ident)	// specValue is set to NULL
+     *	template Foo(valType ident : specValue)
+     * For alias-parameter:
+     *	template Foo(alias ident)
+     * For this-parameter:
+     *	template Foo(this ident)
+     */
+
+    Loc loc;
+    Identifier ident;
+
+    Declaration sparam;
+
+    this(Loc loc, Identifier ident)
+	{
+		this.loc = loc;
+		this.ident = ident;
+	}
+
+    TemplateTypeParameter isTemplateTypeParameter()
+	{
+		assert(false);
+	}
+	
+    TemplateValueParameter isTemplateValueParameter()
+	{
+		assert(false);
+	}
+	
+    TemplateAliasParameter isTemplateAliasParameter()
+	{
+		assert(false);
+	}
+	
+version (DMDV2) {
+    TemplateThisParameter isTemplateThisParameter()
+	{
+		assert(false);
+	}
+}
+    TemplateTupleParameter isTemplateTupleParameter()
+	{
+		return null;
+	}
+
+    abstract TemplateParameter syntaxCopy();
+    abstract void declareParameter(Scope sc);
+    abstract void semantic(Scope);
+    abstract void print(Object oarg, Object oded);
+    abstract void toCBuffer(OutBuffer buf, HdrGenState* hgs);
+    abstract Object specialization();
+    abstract Object defaultArg(Loc loc, Scope sc);
+
+    /* If TemplateParameter's match as far as overloading goes.
+     */
+    abstract bool overloadMatch(TemplateParameter);
+
+    /* Match actual argument against parameter.
+     */
+    abstract MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags = 0);
+
+    /* Create dummy argument based on parameter.
+     */
+    abstract void* dummyArg();
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateThisParameter.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,39 @@
+module dmd.TemplateThisParameter;
+
+import dmd.TemplateTypeParameter;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.TemplateParameter;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+class TemplateThisParameter : TemplateTypeParameter
+{
+    /* Syntax:
+     *	this ident : specType = defaultType
+     */
+    Type specType;	// type parameter: if !=NULL, this is the type specialization
+    Type defaultType;
+
+    this(Loc loc, Identifier ident, Type specType, Type defaultType)
+	{
+		assert(false);
+		super(loc, ident, specType, defaultType);
+	}
+
+    TemplateThisParameter isTemplateThisParameter()
+	{	
+		assert(false);
+	}
+	
+    TemplateParameter syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateTupleParameter.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,149 @@
+module dmd.TemplateTupleParameter;
+
+import dmd.TemplateParameter;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.TypeIdentifier;
+import dmd.AliasDeclaration;
+import dmd.Scope;
+import dmd.ArrayTypes;
+import dmd.MATCH;
+import dmd.Declaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Util;
+import dmd.Tuple;
+import dmd.Dsymbol;
+import dmd.TemplateInstance;
+import dmd.Type;
+import dmd.Expression;
+import dmd.TupleDeclaration;
+
+class TemplateTupleParameter : TemplateParameter
+{
+    /* Syntax:
+     *	ident ...
+     */
+
+    this(Loc loc, Identifier ident)
+	{
+		super(loc, ident);
+		this.ident = ident;
+	}
+
+    TemplateTupleParameter isTemplateTupleParameter()
+	{
+		return this;
+	}
+	
+    TemplateParameter syntaxCopy()
+	{
+		TemplateTupleParameter tp = new TemplateTupleParameter(loc, ident);
+		return tp;
+	}
+	
+    void declareParameter(Scope sc)
+	{
+		TypeIdentifier ti = new TypeIdentifier(loc, ident);
+		sparam = new AliasDeclaration(loc, ident, ti);
+		if (!sc.insert(sparam))
+			error(loc, "parameter '%s' multiply defined", ident.toChars());
+	}
+	
+    void semantic(Scope)
+	{
+	}
+	
+    void print(Object oarg, Object oded)
+	{
+		writef(" %s... [", ident.toChars());
+		Tuple v = isTuple(oded);
+		assert(v);
+
+		//printf("|%d| ", v.objects.dim);
+		for (int i = 0; i < v.objects.dim; i++)
+		{
+			if (i)
+				writef(", ");
+
+			Object o = cast(Object)v.objects.data[i];
+
+			Dsymbol sa = isDsymbol(o);
+			if (sa)
+				writef("alias: %s", sa.toChars());
+
+			Type ta = isType(o);
+			if (ta)
+				writef("type: %s", ta.toChars());
+
+			Expression ea = isExpression(o);
+			if (ea)
+				writef("exp: %s", ea.toChars());
+
+			assert(!isTuple(o));		// no nested Tuple arguments
+		}
+
+		writef("]\n");
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(ident.toChars());
+		buf.writestring("...");
+	}
+	
+    Object specialization()
+	{
+		return null;
+	}
+	
+    Object defaultArg(Loc loc, Scope sc)
+	{
+		return null;
+	}
+	
+    bool overloadMatch(TemplateParameter tp)
+	{
+		TemplateTupleParameter tvp = tp.isTemplateTupleParameter();
+		if (tvp) {
+			return true;			// match
+		}
+
+	Lnomatch:
+		return false;
+	}
+	
+    MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags)
+	{
+		//printf("TemplateTupleParameter.matchArg()\n");
+
+		/* The rest of the actual arguments (tiargs[]) form the match
+		 * for the variadic parameter.
+		 */
+		assert(i + 1 == dedtypes.dim);	// must be the last one
+		Tuple ovar;
+		if (i + 1 == tiargs.dim && isTuple(cast(Object)tiargs.data[i]))
+			ovar = isTuple(cast(Object)tiargs.data[i]);
+		else
+		{
+			ovar = new Tuple();
+			//printf("ovar = %p\n", ovar);
+			if (i < tiargs.dim)
+			{
+				//printf("i = %d, tiargs.dim = %d\n", i, tiargs.dim);
+				ovar.objects.setDim(tiargs.dim - i);
+				for (size_t j = 0; j < ovar.objects.dim; j++)
+					ovar.objects.data[j] = tiargs.data[i + j];
+			}
+		}
+		*psparam = new TupleDeclaration(loc, ident, ovar.objects);
+		dedtypes.data[i] = cast(void*)ovar;
+
+		return MATCH.MATCHexact;
+	}
+	
+    void* dummyArg()
+	{
+		return null;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateTypeParameter.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,215 @@
+module dmd.TemplateTypeParameter;
+
+import dmd.TemplateParameter;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Declaration;
+import dmd.ArrayTypes;
+import dmd.TypeIdentifier;
+import dmd.AliasDeclaration;
+import dmd.Util;
+import dmd.MATCH;
+import dmd.Dsymbol;
+
+class TemplateTypeParameter : TemplateParameter
+{
+    /* Syntax:
+     *	ident : specType = defaultType
+     */
+    Type specType;	// type parameter: if !=null, this is the type specialization
+    Type defaultType;
+
+    this(Loc loc, Identifier ident, Type specType, Type defaultType)
+	{
+		super(loc, ident);
+		this.ident = ident;
+		this.specType = specType;
+		this.defaultType = defaultType;
+	}
+
+    TemplateTypeParameter isTemplateTypeParameter()
+	{
+		return this;
+	}
+	
+    TemplateParameter syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    void declareParameter(Scope sc)
+	{
+		//printf("TemplateTypeParameter.declareParameter('%s')\n", ident.toChars());
+		TypeIdentifier ti = new TypeIdentifier(loc, ident);
+		sparam = new AliasDeclaration(loc, ident, ti);
+		if (!sc.insert(sparam))
+			error(loc, "parameter '%s' multiply defined", ident.toChars());
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("TemplateTypeParameter.semantic('%s')\n", ident.toChars());
+		if (specType)
+		{
+			specType = specType.semantic(loc, sc);
+		}
+	static if (false) {	// Don't do semantic() until instantiation
+		if (defaultType)
+		{
+			defaultType = defaultType.semantic(loc, sc);
+		}
+	}
+	}
+
+    void print(Object oarg, Object oded)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(ident.toChars());
+		if (specType)
+		{
+			buf.writestring(" : ");
+			specType.toCBuffer(buf, null, hgs);
+		}
+		if (defaultType)
+		{
+			buf.writestring(" = ");
+			defaultType.toCBuffer(buf, null, hgs);
+		}
+	}
+
+    Object specialization()
+	{
+		return specType;
+	}
+
+    Object defaultArg(Loc loc, Scope sc)
+	{
+		Type t;
+
+		t = defaultType;
+		if (t)
+		{
+			t = t.syntaxCopy();
+			t = t.semantic(loc, sc);
+		}
+		return t;
+	}
+
+    bool overloadMatch(TemplateParameter)
+	{
+		assert(false);
+	}
+
+	/*******************************************
+	 * Match to a particular TemplateParameter.
+	 * Input:
+	 *	i		i'th argument
+	 *	tiargs[]	actual arguments to template instance
+	 *	parameters[]	template parameters
+	 *	dedtypes[]	deduced arguments to template instance
+	 *	*psparam	set to symbol declared and initialized to dedtypes[i]
+	 *	flags		1: don't do 'toHeadMutable()'
+	 */
+    MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags)
+	{
+		//printf("TemplateTypeParameter.matchArg()\n");
+		Type t;
+		Object oarg;
+		MATCH m = MATCHexact;
+		Type ta;
+
+		if (i < tiargs.dim)
+			oarg = cast(Object)tiargs.data[i];
+		else
+		{	
+			// Get default argument instead
+			oarg = defaultArg(loc, sc);
+			if (!oarg)
+			{   
+				assert(i < dedtypes.dim);
+				// It might have already been deduced
+				oarg = cast(Object)dedtypes.data[i];
+				if (!oarg)
+				{
+					goto Lnomatch;
+				}
+				flags |= 1;		// already deduced, so don't to toHeadMutable()
+			}
+		}
+
+		ta = isType(oarg);
+		if (!ta)
+		{
+			//printf("%s %p %p %p\n", oarg.toChars(), isExpression(oarg), isDsymbol(oarg), isTuple(oarg));
+			goto Lnomatch;
+		}
+		//printf("ta is %s\n", ta.toChars());
+
+		t = cast(Type)dedtypes.data[i];
+
+		if (specType)
+		{
+			//printf("\tcalling deduceType(): ta is %s, specType is %s\n", ta.toChars(), specType.toChars());
+			MATCH m2 = ta.deduceType(sc, specType, parameters, dedtypes);
+			if (m2 == MATCHnomatch)
+			{   
+				//printf("\tfailed deduceType\n");
+				goto Lnomatch;
+			}
+
+			if (m2 < m)
+				m = m2;
+			t = cast(Type)dedtypes.data[i];
+		}
+		else
+		{
+			// So that matches with specializations are better
+			m = MATCHconvert;
+
+			/* This is so that:
+			 *   template Foo(T), Foo!(const int), => ta == int
+			 */
+		//	if (!(flags & 1))
+		//	    ta = ta.toHeadMutable();
+
+			if (t)
+			{   // Must match already deduced type
+
+				m = MATCHexact;
+				if (!t.equals(ta))
+				{	
+					//printf("t = %s ta = %s\n", t.toChars(), ta.toChars());
+					goto Lnomatch;
+				}
+			}
+		}
+
+		if (!t)
+		{
+			dedtypes.data[i] = cast(void*)ta;
+			t = ta;
+		}
+
+		*psparam = new AliasDeclaration(loc, ident, t);
+		//printf("\tm = %d\n", m);
+		return m;
+
+	Lnomatch:
+		*psparam = null;
+		//printf("\tm = %d\n", MATCHnomatch);
+		return MATCHnomatch;
+	}
+	
+    void* dummyArg()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TemplateValueParameter.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,87 @@
+module dmd.TemplateValueParameter;
+
+import dmd.TemplateParameter;
+import dmd.Scope;
+import dmd.Declaration;
+import dmd.ArrayTypes;
+import dmd.Type;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.MATCH;
+
+class TemplateValueParameter : TemplateParameter
+{
+    /* Syntax:
+     *	valType ident : specValue = defaultValue
+     */
+
+    Type valType;
+    Expression specValue;
+    Expression defaultValue;
+
+    static Expression edummy;
+
+    this(Loc loc, Identifier ident, Type valType, Expression specValue, Expression defaultValue)
+	{
+		assert(false);
+		super(loc, ident);
+	}
+
+    TemplateValueParameter isTemplateValueParameter()
+	{
+		assert(false);
+	}
+	
+    TemplateParameter syntaxCopy()
+	{
+		assert(false);
+	}
+
+    void declareParameter(Scope sc)
+	{
+		assert(false);
+	}
+
+    void semantic(Scope)
+	{
+		assert(false);
+	}
+
+    void print(Object oarg, Object oded)
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Object specialization()
+	{
+		assert(false);
+	}
+
+    Object defaultArg(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+
+    bool overloadMatch(TemplateParameter)
+	{
+		assert(false);
+	}
+
+    MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags)
+	{
+		assert(false);
+	}
+
+    void* dummyArg()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ThisDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,25 @@
+module dmd.ThisDeclaration;
+
+import dmd.VarDeclaration;
+import dmd.Dsymbol;
+import dmd.Loc;
+import dmd.Type;
+import dmd.Id;
+
+// For the "this" parameter to member functions
+
+class ThisDeclaration : VarDeclaration
+{
+    this(Loc loc, Type t)
+	{
+		super(loc, t, Id.This, null);
+		noauto = true;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    ThisDeclaration isThisDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ThisExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,189 @@
+module dmd.ThisExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.StructDeclaration;
+import dmd.ClassDeclaration;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.backend.elem;
+import dmd.CSX;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Type;
+import dmd.TOK;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.VarExp;
+import dmd.TY;
+
+import dmd.codegen.Util;
+import dmd.backend.TYM;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+
+class ThisExp : Expression
+{
+	Declaration var;
+
+	this(Loc loc)
+	{
+		super(loc, TOK.TOKthis, ThisExp.sizeof);
+		//printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		FuncDeclaration fd;
+		FuncDeclaration fdthis;
+
+	version (LOGSEMANTIC) {
+		printf("ThisExp::semantic()\n");
+	}
+		if (type)
+		{	
+			//assert(global.errors || var);
+			return this;
+		}
+
+		/* Special case for typeof(this) and typeof(super) since both
+		 * should work even if they are not inside a non-static member function
+		 */
+		if (sc.intypeof)
+		{
+			// Find enclosing struct or class
+			for (Dsymbol s = sc.parent; 1; s = s.parent)
+			{
+				if (!s)
+				{
+					error("%s is not in a class or struct scope", toChars());
+					goto Lerr;
+				}
+				ClassDeclaration cd = s.isClassDeclaration();
+				if (cd)
+				{
+					type = cd.type;
+					return this;
+				}
+				StructDeclaration sd = s.isStructDeclaration();
+				if (sd)
+				{
+		version (STRUCTTHISREF) {
+				type = sd.type;
+		} else {
+				type = sd.type.pointerTo();
+		}
+				return this;
+				}
+			}
+		}
+
+		fdthis = sc.parent.isFuncDeclaration();
+		fd = hasThis(sc);	// fd is the uplevel function with the 'this' variable
+		if (!fd)
+			goto Lerr;
+
+		assert(fd.vthis);
+		var = fd.vthis;
+		assert(var.parent);
+		type = var.type;
+		var.isVarDeclaration().checkNestedReference(sc, loc);
+		if (!sc.intypeof)
+			sc.callSuper |= CSXthis;
+		return this;
+
+	Lerr:
+		error("'this' is only defined in non-static member functions, not %s", sc.parent.toChars());
+		type = Type.terror;
+		return this;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	bool isBool(bool result)
+	{
+		return result ? true : false;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("this");
+	}
+
+version (DMDV2) {
+	int isLvalue()
+	{
+		return 1;
+	}
+}
+	Expression toLvalue(Scope sc, Expression e)
+	{
+		return this;
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		FuncDeclaration fd = ics.fd;
+		if (!ics.hdrscan)
+			if (fd.isNested() || !ics.hasthis)
+				return COST_MAX;
+
+		return 1;
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		//if (!ids.vthis)
+		//error("no 'this' when inlining %s", ids.parent.toChars());
+		if (!ids.vthis)
+		{
+			return this;
+		}
+
+		VarExp ve = new VarExp(loc, ids.vthis);
+		ve.type = type;
+		return ve;
+	}
+
+	elem* 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);
+
+	version (STRUCTTHISREF) {
+		if (type.ty == Tstruct)
+		{	
+			ethis = el_una(OPind, TYstruct, ethis);
+			ethis.Enumbytes = cast(uint)type.size();
+		}
+	}
+		el_setLoc(ethis,loc);
+		return ethis;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/ThrowStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,85 @@
+module dmd.ThrowStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.IRState;
+import dmd.InlineScanState;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.FuncDeclaration;
+import dmd.BE;
+
+import dmd.backend.Util;
+import dmd.backend.Blockx;
+import dmd.backend.elem;
+import dmd.backend.RTLSYM;
+import dmd.backend.OPER;
+import dmd.backend.TYM;
+
+class ThrowStatement : Statement
+{
+    Expression exp;
+
+    this(Loc loc, Expression exp)
+	{
+		super(loc);
+		this.exp = exp;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("ThrowStatement::semantic()\n");
+
+		FuncDeclaration fd = sc.parent.isFuncDeclaration();
+		fd.hasReturnExp |= 2;
+
+		if (sc.incontract)
+			error("Throw statements cannot be in contracts");
+		exp = exp.semantic(sc);
+		exp = resolveProperties(sc, exp);
+		if (!exp.type.toBasetype().isClassHandle())
+			error("can only throw class objects, not type %s", exp.type.toChars());
+		return this;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		return BE.BEthrow;  // obviously
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (exp)
+			exp = exp.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		// throw(exp)
+
+		Blockx *blx = irs.blx;
+
+		incUsage(irs, loc);
+		elem *e = exp.toElem(irs);
+	static if (false) {
+		e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_LTHROW]),e);
+	} else {
+		e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_THROW]),e);
+	}
+		block_appendexp(blx.curblock, e);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Token.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,215 @@
+module dmd.Token;
+
+import dmd.TOK;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.Utf;
+
+import core.stdc.stdio;
+import core.stdc.ctype;
+
+struct Token
+{
+    Token* next;
+    ubyte* ptr;		// pointer to first character of this token within buffer
+    TOK value;
+    ubyte* blockComment; // doc comment string prior to this token
+    ubyte* lineComment;	 // doc comment for previous token
+    
+	union
+    {
+		// Integers
+		int 	int32value;
+		uint	uns32value;
+		long	int64value;
+		ulong	uns64value;
+
+	// Floats
+version (IN_GCC) {
+	// real_t float80value; // can't use this in a union!
+} else {
+		real float80value;
+}
+
+		struct
+		{
+			const(char)* ustring;	// UTF8 string
+			uint len;
+			ubyte postfix;	// 'c', 'w', 'd'
+		};
+
+		Identifier ident;
+    }
+
+version (IN_GCC) {
+    real float80value; // can't use this in a union!
+}
+
+    static string tochars[TOK.TOKMAX];
+///    static void *operator new(size_t sz);
+
+    int isKeyword()
+	{
+		assert(false);
+	}
+	
+    void print()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		static char buffer[3 + 3 * value.sizeof + 1];
+
+		string p;
+
+		switch (value)
+		{
+		case TOK.TOKint32v:
+version (IN_GCC) {
+			sprintf(buffer.ptr,"%d",cast(int)int64value);
+} else {
+			sprintf(buffer.ptr,"%d",int32value);
+}
+			break;
+
+		case TOK.TOKuns32v:
+		case TOK.TOKcharv:
+		case TOK.TOKwcharv:
+		case TOK.TOKdcharv:
+version (IN_GCC) {
+			sprintf(buffer.ptr,"%uU",cast(uint)uns64value);
+} else {
+			sprintf(buffer.ptr,"%uU",uns32value);
+}
+			break;
+
+		case TOK.TOKint64v:
+			sprintf(buffer.ptr,"%jdL",int64value);
+			break;
+
+		case TOK.TOKuns64v:
+			sprintf(buffer.ptr,"%juUL",uns64value);
+			break;
+
+version (IN_GCC) {
+		case TOK.TOKfloat32v:
+		case TOK.TOKfloat64v:
+		case TOK.TOKfloat80v:
+			float80value.format(buffer, sizeof(buffer));
+			break;
+		case TOK.TOKimaginary32v:
+		case TOK.TOKimaginary64v:
+		case TOK.TOKimaginary80v:
+			float80value.format(buffer, sizeof(buffer));
+			// %% buffer
+			strcat(buffer, "i");
+			break;
+} else {
+		case TOK.TOKfloat32v:
+			sprintf(buffer.ptr,"%Lgf", float80value);
+			break;
+
+		case TOK.TOKfloat64v:
+			sprintf(buffer.ptr,"%Lg", float80value);
+			break;
+
+		case TOK.TOKfloat80v:
+			sprintf(buffer.ptr,"%LgL", float80value);
+			break;
+
+		case TOK.TOKimaginary32v:
+			sprintf(buffer.ptr,"%Lgfi", float80value);
+			break;
+
+		case TOK.TOKimaginary64v:
+			sprintf(buffer.ptr,"%Lgi", float80value);
+			break;
+
+		case TOK.TOKimaginary80v:
+			sprintf(buffer.ptr,"%LgLi", float80value);
+			break;
+}
+
+		case TOK.TOKstring:
+version (CSTRINGS) {
+			p = string;
+} else {
+		{   OutBuffer buf;
+
+			buf.writeByte('"');
+			for (size_t i = 0; i < len; )
+			{	
+				dchar c;			///! 
+
+				utf_decodeChar(ustring[0..len], &i, &c);
+				switch (c)
+				{
+					case 0:
+					break;
+
+					case '"':
+					case '\\':
+					buf.writeByte('\\');
+					default:
+					if (isprint(c))
+						buf.writeByte(c);
+					else if (c <= 0x7F)
+						buf.printf("\\x%02x", c);
+					else if (c <= 0xFFFF)
+						buf.printf("\\u%04x", c);
+					else
+						buf.printf("\\U%08x", c);
+					continue;
+				}
+				break;
+			}
+			buf.writeByte('"');
+			if (postfix)
+			buf.writeByte('"');
+			buf.writeByte(0);
+			p = buf.extractString();
+		}
+}
+			break;
+
+		case TOK.TOKidentifier:
+		case TOK.TOKenum:
+		case TOK.TOKstruct:
+		case TOK.TOKimport:
+		case TOK.TOKwchar: case TOK.TOKdchar:
+		case TOK.TOKbit: case TOK.TOKbool: case TOK.TOKchar:
+		case TOK.TOKint8: case TOK.TOKuns8:
+		case TOK.TOKint16: case TOK.TOKuns16:
+		case TOK.TOKint32: case TOK.TOKuns32:
+		case TOK.TOKint64: case TOK.TOKuns64:
+		case TOK.TOKfloat32: case TOK.TOKfloat64: case TOK.TOKfloat80:
+		case TOK.TOKimaginary32: case TOK.TOKimaginary64: case TOK.TOKimaginary80:
+		case TOK.TOKcomplex32: case TOK.TOKcomplex64: case TOK.TOKcomplex80:
+		case TOK.TOKvoid:
+			p = ident.toChars();
+			break;
+
+		default:
+			p = toChars(value);
+			break;
+		}
+		return p;
+	}
+	
+    static string toChars(TOK value)
+	{
+		string p;
+		static char buffer[3 + 3 * value.sizeof + 1];
+
+		p = tochars[value];
+		if (!p)
+		{
+			int len = sprintf(buffer.ptr, "TOK%d".ptr, value);
+			p = buffer[0..len].idup;
+		}
+
+		return p;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TraitsExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,39 @@
+module dmd.TraitsExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class TraitsExp : Expression
+{
+	Identifier ident;
+
+	Objects args;
+
+	this(Loc loc, Identifier ident, Objects args)
+	{
+		assert(false);
+		super(loc, TOK.init, 0);
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TryCatchStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,201 @@
+module dmd.TryCatchStatement;
+
+import dmd.Statement;
+import dmd.Array;
+import dmd.Loc;
+import dmd.Id;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.OutBuffer;
+import dmd.Catch;
+import dmd.HdrGenState;
+import dmd.BE;
+
+import dmd.backend.BC;
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.Blockx;
+import dmd.backend.block;
+import dmd.backend.mTY;
+import dmd.backend.TYM;
+
+class TryCatchStatement : Statement
+{
+    Statement body_;
+    Array catches;
+
+    this(Loc loc, Statement body_, Array catches)
+	{
+		super(loc);
+		this.body_ = body_;
+		this.catches = catches;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		body_ = body_.semanticScope(sc, null /*this*/, null);
+
+		/* Even if body is null, still do semantic analysis on catches
+		 */
+		for (size_t i = 0; i < catches.dim; i++)
+		{   
+			Catch c = cast(Catch)catches.data[i];
+			c.semantic(sc);
+
+			// Determine if current catch 'hides' any previous catches
+			for (size_t j = 0; j < i; j++)
+			{   
+				Catch cj = cast(Catch)catches.data[j];
+				string si = c.loc.toChars();
+				string sj = cj.loc.toChars();
+
+				if (c.type.toBasetype().implicitConvTo(cj.type.toBasetype()))
+					error("catch at %s hides catch at %s", sj, si);
+			}
+		}
+
+		if (!body_ || body_.isEmpty())
+		{
+			return null;
+		}
+		return this;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(body_);
+		BE result = body_.blockExit();
+
+		BE catchresult = BE.BEnone;
+		for (size_t i = 0; i < catches.dim; i++)
+		{
+			Catch c = cast(Catch)catches.data[i];
+			catchresult |= c.blockExit();
+
+		/* If we're catching Object, then there is no throwing
+		 */
+		Identifier id = c.type.toBasetype().isClassHandle().ident;
+		if (i == 0 &&
+			(id is Id.Object_ || id is Id.Throwable || id is Id.Exception))
+		{
+			result &= ~BE.BEthrow;
+		}
+		}
+		return result | catchresult;
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (body_)
+			body_ = body_.inlineScan(iss);
+		if (catches)
+		{
+			for (int i = 0; i < catches.dim; i++)
+			{   
+				Catch c = cast(Catch)catches.data[i];
+
+				if (c.handler)
+					c.handler = c.handler.inlineScan(iss);
+			}
+		}
+		return this;
+	}
+
+	/***************************************
+	 * Builds the following:
+	 *	_try
+	 *	block
+	 *	jcatch
+	 *	handler
+	 * A try-catch statement.
+	 */
+    void toIR(IRState *irs)
+	{
+		Blockx *blx = irs.blx;
+
+	version (SEH) {
+		nteh_declarvars(blx);
+	}
+
+		IRState mystate = IRState(irs, this);
+
+		block* tryblock = block_goto(blx,BCgoto,null);
+
+		int previndex = blx.scope_index;
+		tryblock.Blast_index = previndex;
+		blx.scope_index = tryblock.Bscope_index = blx.next_index++;
+
+		// Set the current scope index
+		setScopeIndex(blx,tryblock,tryblock.Bscope_index);
+
+		// This is the catch variable
+		tryblock.jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr));
+
+		blx.tryblock = tryblock;
+		block *breakblock = block_calloc(blx);
+		block_goto(blx,BC_try,null);
+		if (body_)
+		{
+			body_.toIR(&mystate);
+		}
+		blx.tryblock = tryblock.Btry;
+
+		// break block goes here
+		block_goto(blx, BCgoto, breakblock);
+
+		setScopeIndex(blx,blx.curblock, previndex);
+		blx.scope_index = previndex;
+
+		// create new break block that follows all the catches
+		breakblock = block_calloc(blx);
+
+		list_append(&blx.curblock.Bsucc, breakblock);
+		block_next(blx,BCgoto,null);
+	 
+		assert(catches);
+		for (int i = 0 ; i < catches.dim; i++)
+		{
+			Catch cs = cast(Catch)(catches.data[i]);
+			if (cs.var)
+				cs.var.csym = tryblock.jcatchvar;
+			block* bcatch = blx.curblock;
+			if (cs.type)
+				bcatch.Bcatchtype = cs.type.toBasetype().toSymbol();
+			list_append(&tryblock.Bsucc,bcatch);
+			block_goto(blx,BCjcatch,null);
+			if (cs.handler !is null)
+			{
+				IRState catchState = IRState(irs, this);
+				cs.handler.toIR(&catchState);
+			}
+			list_append(&blx.curblock.Bsucc, breakblock);
+			block_next(blx, BCgoto, null);
+		}
+
+		block_next(blx,cast(BC)blx.curblock.BC, breakblock);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    TryCatchStatement isTryCatchStatement() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TryFinallyStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,160 @@
+module dmd.TryFinallyStatement;
+
+import dmd.Statement;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.InlineScanState;
+import dmd.CompoundStatement;
+import dmd.IRState;
+import dmd.BE;
+
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.BC;
+import dmd.backend.Util;
+
+import dmd.codegen.Util;
+
+class TryFinallyStatement : Statement
+{
+    Statement body_;
+    Statement finalbody;
+
+    this(Loc loc, Statement body_, Statement finalbody)
+	{
+		super(loc);
+		this.body_ = body_;
+		this.finalbody = finalbody;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		//printf("TryFinallyStatement::semantic()\n");
+		body_ = body_.semantic(sc);
+		sc = sc.push();
+		sc.tf = this;
+		sc.sbreak = null;
+		sc.scontinue = null;	// no break or continue out of finally block
+		finalbody = finalbody.semantic(sc);
+		sc.pop();
+		if (!body_)
+			return finalbody;
+		if (!finalbody)
+			return body_;
+		if (body_.blockExit() == BE.BEfallthru)
+		{	
+			Statement s = new CompoundStatement(loc, body_, finalbody);
+			return s;
+		}
+		return this;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool hasContinue()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		if (body_)
+			return body_.blockExit();
+		return BE.BEfallthru;
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (body_)
+			body_ = body_.inlineScan(iss);
+		if (finalbody)
+			finalbody = finalbody.inlineScan(iss);
+		return this;
+	}
+
+	/****************************************
+	 * A try-finally statement.
+	 * Builds the following:
+	 *	_try
+	 *	block
+	 *	_finally
+	 *	finalbody
+	 *	_ret
+	 */
+    void toIR(IRState* irs)
+	{
+		//printf("TryFinallyStatement.toIR()\n");
+		Blockx* blx = irs.blx;
+
+	version (SEH) {
+		nteh_declarvars(blx);
+	}
+
+		block* tryblock = block_goto(blx, BCgoto, null);
+
+		int previndex = blx.scope_index;
+		tryblock.Blast_index = previndex;
+		tryblock.Bscope_index = blx.next_index++;
+		blx.scope_index = tryblock.Bscope_index;
+
+		// Current scope index
+		setScopeIndex(blx,tryblock,tryblock.Bscope_index);
+
+		blx.tryblock = tryblock;
+		block_goto(blx,BC_try,null);
+
+		IRState bodyirs = IRState(irs, this);
+		block* breakblock = block_calloc(blx);
+		block* contblock = block_calloc(blx);
+
+		if (body_)
+			body_.toIR(&bodyirs);
+		blx.tryblock = tryblock.Btry;	// back to previous tryblock
+
+		setScopeIndex(blx,blx.curblock,previndex);
+		blx.scope_index = previndex;
+
+		block_goto(blx,BCgoto, breakblock);
+		block* finallyblock = block_goto(blx,BCgoto,contblock);
+
+		list_append(&tryblock.Bsucc,finallyblock);
+
+		block_goto(blx,BC_finally,null);
+
+		IRState finallyState = IRState(irs, this);
+		breakblock = block_calloc(blx);
+		contblock = block_calloc(blx);
+
+		setScopeIndex(blx, blx.curblock, previndex);
+		if (finalbody)
+			finalbody.toIR(&finallyState);
+		block_goto(blx, BCgoto, contblock);
+		block_goto(blx, BCgoto, breakblock);
+
+		block* retblock = blx.curblock;
+		block_next(blx,BC_ret,null);
+
+		list_append(&finallyblock.Bsucc, blx.curblock);
+		list_append(&retblock.Bsucc, blx.curblock);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Tuple.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.Tuple;
+
+import dmd.ArrayTypes;
+
+class Tuple
+{
+	Objects objects;
+
+	int dyncast()
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TupleDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,45 @@
+module dmd.TupleDeclaration;
+
+import dmd.Declaration;
+import dmd.ArrayTypes;
+import dmd.TypeTuple;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Type;
+
+class TupleDeclaration : Declaration
+{
+    Objects objects;
+    int isexp;			// 1: expression tuple
+
+    TypeTuple tupletype;	// !=NULL if this is a type tuple
+
+    this(Loc loc, Identifier ident, Objects objects)
+	{
+		assert(false);
+		super(ident);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+
+    Type getType()
+	{
+		assert(false);
+	}
+	
+    bool needThis()
+	{
+		assert(false);
+	}
+	
+    TupleDeclaration isTupleDeclaration() { return this; }
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TupleExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,110 @@
+module dmd.TupleExp;
+
+import dmd.Expression;
+import dmd.TupleDeclaration;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.IRState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.ArrayTypes;
+import dmd.TOK;
+
+class TupleExp : Expression
+{
+	Expressions exps;
+
+	this(Loc loc, Expressions exps)
+	{
+		assert(false);
+		super(Loc(0), TOK.init, 0);
+	}
+
+	this(Loc loc, TupleDeclaration tup)
+	{
+		assert(false);
+		super(Loc(0), TOK.init, 0);
+	}
+
+	Expression syntaxCopy()
+	{
+		assert(false);
+	}
+
+	int equals(Object o)
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	void checkEscape()
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+
+	bool canThrow()
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Type.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,2445 @@
+module dmd.Type;
+
+import dmd.TY;
+import dmd.Argument;
+import dmd.TOK;
+import dmd.STC;
+import dmd.TypeArray;
+import dmd.DotVarExp;
+import dmd.ErrorExp;
+import dmd.StringExp;
+import dmd.IntegerExp;
+import dmd.VarExp;
+import dmd.TemplateParameter;
+import dmd.TypeInfoSharedDeclaration;
+import dmd.TypeInfoConstDeclaration;
+import dmd.TypeInfoInvariantDeclaration;
+import dmd.Module;
+import dmd.Id;
+import dmd.Util;
+import dmd.VarDeclaration;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.Identifier;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Dsymbol;
+import dmd.MATCH;
+import dmd.TypeInfoDeclaration;
+import dmd.ClassDeclaration;
+import dmd.StringTable;
+import dmd.ArrayTypes;
+import dmd.TypeBasic;
+import dmd.DYNCAST;
+import dmd.MOD;
+import dmd.Lexer;
+import dmd.TypeSArray;
+import dmd.TypeDArray;
+import dmd.TypeAArray;
+import dmd.TypePointer;
+import dmd.TypeReference;
+import dmd.TypeFunction;
+import dmd.TypeDelegate;
+import dmd.TypeIdentifier;
+import dmd.TypeInstance;
+import dmd.TypeTypeof;
+import dmd.TypeReturn;
+import dmd.TypeStruct;
+import dmd.TypeEnum;
+import dmd.TypeTypedef;
+import dmd.TypeClass;
+import dmd.TypeTuple;
+import dmd.TypeSlice;
+import dmd.Global;
+import dmd.StringValue;
+
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+
+import core.stdc.stdio;
+
+/* These have default values for 32 bit code, they get
+ * adjusted for 64 bit code.
+ */
+
+int PTRSIZE = 4;
+
+int Tsize_t;
+int Tptrdiff_t;
+
+/* REALSIZE = size a real consumes in memory
+ * REALPAD = 'padding' added to the CPU real size to bring it up to REALSIZE
+ * REALALIGNSIZE = alignment for reals
+ */
+version (TARGET_OSX) {
+	int REALSIZE = 16;
+	int REALPAD = 6;
+	int REALALIGNSIZE = 16;
+} else version (XXX) { /// TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
+	int REALSIZE = 12;
+	int REALPAD = 2;
+	int REALALIGNSIZE = 4;
+} else {
+	int REALSIZE = 10;
+	int REALPAD = 0;
+	int REALALIGNSIZE = 2;
+}
+
+/****
+ * Given an identifier, figure out which TemplateParameter it is.
+ * Return -1 if not found.
+ */
+
+int templateIdentifierLookup(Identifier id, TemplateParameters parameters)
+{
+    for (size_t i = 0; i < parameters.dim; i++)
+    {   
+		TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+
+		if (tp.ident.equals(id))
+			return i;
+    }
+    return -1;
+}
+
+int templateParameterLookup(Type tparam, TemplateParameters parameters)
+{
+    assert(tparam.ty == Tident);
+    TypeIdentifier tident = cast(TypeIdentifier)tparam;
+    //printf("\ttident = '%s'\n", tident.toChars());
+    if (tident.idents.dim == 0)
+    {
+		return templateIdentifierLookup(tident.ident, parameters);
+    }
+    return -1;
+}
+
+class Type
+{
+    TY ty;
+    MOD mod;	// modifiers MODxxxx
+	/* pick this order of numbers so switch statements work better
+	 */
+///	#define MODconst     1	// type is const
+///	#define MODinvariant 4	// type is invariant
+///	#define MODshared    2	// type is shared
+    string deco;
+
+    /* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc.
+     * They should not be referenced by anybody but mtype.c.
+     * They can be null if not lazily evaluated yet.
+     * Note that there is no "shared immutable", because that is just immutable
+     */
+
+    Type cto;		// MODconst ? mutable version of this type : const version
+    Type ito;		// MODinvariant ? mutable version of this type : invariant version
+    Type sto;		// MODshared ? mutable version of this type : shared mutable version
+    Type scto;		// MODshared|MODconst ? mutable version of this type : shared const version
+
+    Type pto;		// merged pointer to this type
+    Type rto;		// reference to this type
+    Type arrayof;	// array of this type
+    TypeInfoDeclaration vtinfo;	// TypeInfo object for this Type
+
+    type* ctype;	// for back end
+
+    static ClassDeclaration typeinfo;
+    static ClassDeclaration typeinfoclass;
+    static ClassDeclaration typeinfointerface;
+    static ClassDeclaration typeinfostruct;
+    static ClassDeclaration typeinfotypedef;
+    static ClassDeclaration typeinfopointer;
+    static ClassDeclaration typeinfoarray;
+    static ClassDeclaration typeinfostaticarray;
+    static ClassDeclaration typeinfoassociativearray;
+    static ClassDeclaration typeinfoenum;
+    static ClassDeclaration typeinfofunction;
+    static ClassDeclaration typeinfodelegate;
+    static ClassDeclaration typeinfotypelist;
+    static ClassDeclaration typeinfoconst;
+    static ClassDeclaration typeinfoinvariant;
+    static ClassDeclaration typeinfoshared;
+
+    static Type basic[TY.TMAX];
+    static ubyte mangleChar[TY.TMAX];
+    static ubyte sizeTy[TY.TMAX];
+    static StringTable stringtable;
+
+    // These tables are for implicit conversion of binary ops;
+    // the indices are the type of operand one, followed by operand two.
+    static ubyte impcnvResult[TY.TMAX][TY.TMAX] = [
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,29,30,31,37,20,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,29,30,31,37,21,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,29,30,31,37,22,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,29,30,31,37,23,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,30,30,31,37,24,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,31,31,31,37,25,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,33,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+	];
+
+    static ubyte impcnvType1[TY.TMAX][TY.TMAX] = [
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,23,24,25,37,20,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,23,24,25,37,21,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,23,24,25,37,22,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,23,24,25,37,23,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,24,24,25,37,24,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,37,25,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,26,26,26,26,26,26,26,26,26,27,28,26,27,28,26,27,28,37,26,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,27,27,27,27,27,27,27,27,27,27,28,27,27,28,27,27,28,37,27,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,37,28,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,33,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+	];
+	
+    static ubyte impcnvType2[TY.TMAX][TY.TMAX] = [
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,31,37,20,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,31,37,21,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,31,37,22,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,33,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+		[37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37],
+	];
+
+    // If !=0, give warning on implicit conversion
+    static const(bool) impcnvWarn[TY.TMAX][TY.TMAX] = [
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+		[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+	];
+	
+	static this()
+	{
+		stringtable = new StringTable();
+	}
+	
+	static ~this()
+	{
+		delete stringtable;
+	}
+
+    this(TY ty)
+	{
+		this.ty = ty;
+	}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+
+    int equals(Object o)
+	{
+		Type t = cast(Type)o;
+		//printf("Type.equals(%s, %s)\n", toChars(), t.toChars());
+		if (this is o || (t && deco == t.deco) &&		// deco strings are unique
+		 deco !is null)				// and semantic() has been run
+		{
+			//printf("deco = '%s', t.deco = '%s'\n", deco, t.deco);
+			return 1;
+		}
+		//if (deco && t && t.deco) printf("deco = '%s', t.deco = '%s'\n", deco, t.deco);
+		return 0;
+	}
+	
+    DYNCAST dyncast() { return DYNCAST.DYNCAST_TYPE; } // kludge for template.isType()
+
+	/*******************************
+	 * Returns:
+	 *	0	types are distinct
+	 *	1	this is covariant with t
+	 *	2	arguments match as far as overloading goes,
+	 *		but types are not covariant
+	 *	3	cannot determine covariance because of forward references
+	 */
+    int covariant(Type t)
+	{
+static if (false) {
+		printf("Type.covariant(t = %s) %s\n", t.toChars(), toChars());
+		printf("deco = %p, %p\n", deco, t.deco);
+	//    printf("ty = %d\n", next.ty);
+		printf("mod = %x, %x\n", mod, t.mod);
+}
+
+		int inoutmismatch = 0;
+
+		TypeFunction t1;
+		TypeFunction t2;
+
+		if (equals(t))
+			return 1;			// covariant
+
+		if (ty != TY.Tfunction || t.ty != TY.Tfunction)
+			goto Ldistinct;
+
+		t1 = cast(TypeFunction)this;
+		t2 = cast(TypeFunction)t;
+
+		if (t1.varargs != t2.varargs)
+			goto Ldistinct;
+
+		if (t1.parameters && t2.parameters)
+		{
+			size_t dim = Argument.dim(t1.parameters);
+			if (dim != Argument.dim(t2.parameters))
+				goto Ldistinct;
+
+			for (size_t i = 0; i < dim; i++)
+			{   
+				Argument arg1 = Argument.getNth(t1.parameters, i);
+				Argument arg2 = Argument.getNth(t2.parameters, i);
+
+				if (!arg1.type.equals(arg2.type))
+				{
+///static if (false) {
+///				// turn on this for contravariant argument types, see bugzilla 3075
+///				// We can add const, but not subtract it
+///				if (arg2.type.implicitConvTo(arg1.type) < MATCH.MATCHconst)
+///}
+					goto Ldistinct;
+				}
+				if ((arg1.storageClass & ~STC.STCscope) != (arg2.storageClass & ~STC.STCscope))
+					inoutmismatch = 1;
+				// We can add scope, but not subtract it
+				if (!(arg1.storageClass & STC.STCscope) && (arg2.storageClass & STC.STCscope))
+					inoutmismatch = 1;
+			}
+		}
+		else if (t1.parameters != t2.parameters)
+			goto Ldistinct;
+
+		// The argument lists match
+		if (inoutmismatch)
+			goto Lnotcovariant;
+		if (t1.linkage != t2.linkage)
+			goto Lnotcovariant;
+
+	  {
+		// Return types
+		Type t1n = t1.next;
+		Type t2n = t2.next;
+
+		if (t1n.equals(t2n))
+		goto Lcovariant;
+		if (t1n.ty == TY.Tclass && t2n.ty == TY.Tclass)
+		{
+			/* If same class type, but t2n is const, then it's
+			 * covariant. Do this test first because it can work on
+			 * forward references.
+			 */
+			if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym &&
+				t2n.mod == MOD.MODconst)
+				goto Lcovariant;
+
+			// If t1n is forward referenced:
+			ClassDeclaration cd = (cast(TypeClass)t1n).sym;
+			if (!cd.baseClass && cd.baseclasses.dim && !cd.isInterfaceDeclaration())
+			{
+				return 3;
+			}
+		}
+		if (t1n.implicitConvTo(t2n))
+			goto Lcovariant;
+	  }
+
+	goto Lnotcovariant;
+
+	Lcovariant:
+		/* Can convert mutable to const
+		 */
+		if (t1.mod != t2.mod)
+		{
+			if (!(t1.mod & MOD.MODconst) && (t2.mod & MOD.MODconst))
+				goto Lnotcovariant;
+			if (!(t1.mod & MOD.MODshared) && (t2.mod & MOD.MODshared))
+				goto Lnotcovariant;
+		}
+
+		/* Can convert pure to impure, and nothrow to throw
+		 */
+		if (!t1.ispure && t2.ispure)
+			goto Lnotcovariant;
+
+		if (!t1.isnothrow && t2.isnothrow)
+			goto Lnotcovariant;
+
+		if (t1.isref != t2.isref)
+			goto Lnotcovariant;
+
+		//printf("\tcovaraint: 1\n");
+		return 1;
+
+	Ldistinct:
+		//printf("\tcovaraint: 0\n");
+		return 0;
+
+	Lnotcovariant:
+		//printf("\tcovaraint: 2\n");
+		return 2;
+	}
+
+    string toChars()
+	{
+		scope OutBuffer buf = new OutBuffer();
+
+		HdrGenState hgs;
+		toCBuffer(buf, null, &hgs);
+		return buf.toChars();
+	}
+	
+    static char needThisPrefix()
+	{
+		return 'M';		// name mangling prefix for functions needing 'this'
+	}
+	
+    static void init()
+	{
+		Lexer.initKeywords();
+
+		for (int i = 0; i < TY.TMAX; i++)
+			sizeTy[i] = TypeBasic.sizeof;
+
+		sizeTy[TY.Tsarray] = TypeSArray.sizeof;
+		sizeTy[TY.Tarray] = TypeDArray.sizeof;
+		//sizeTy[TY.Tnarray] = TypeNArray.sizeof;
+		sizeTy[TY.Taarray] = TypeAArray.sizeof;
+		sizeTy[TY.Tpointer] = TypePointer.sizeof;
+		sizeTy[TY.Treference] = TypeReference.sizeof;
+		sizeTy[TY.Tfunction] = TypeFunction.sizeof;
+		sizeTy[TY.Tdelegate] = TypeDelegate.sizeof;
+		sizeTy[TY.Tident] = TypeIdentifier.sizeof;
+		sizeTy[TY.Tinstance] = TypeInstance.sizeof;
+		sizeTy[TY.Ttypeof] = TypeTypeof.sizeof;
+		sizeTy[TY.Tenum] = TypeEnum.sizeof;
+		sizeTy[TY.Ttypedef] = TypeTypedef.sizeof;
+		sizeTy[TY.Tstruct] = TypeStruct.sizeof;
+		sizeTy[TY.Tclass] = TypeClass.sizeof;
+		sizeTy[TY.Ttuple] = TypeTuple.sizeof;
+		sizeTy[TY.Tslice] = TypeSlice.sizeof;
+		sizeTy[TY.Treturn] = TypeReturn.sizeof;
+
+		mangleChar[TY.Tarray] = 'A';
+		mangleChar[TY.Tsarray] = 'G';
+		mangleChar[TY.Tnarray] = '@';
+		mangleChar[TY.Taarray] = 'H';
+		mangleChar[TY.Tpointer] = 'P';
+		mangleChar[TY.Treference] = 'R';
+		mangleChar[TY.Tfunction] = 'F';
+		mangleChar[TY.Tident] = 'I';
+		mangleChar[TY.Tclass] = 'C';
+		mangleChar[TY.Tstruct] = 'S';
+		mangleChar[TY.Tenum] = 'E';
+		mangleChar[TY.Ttypedef] = 'T';
+		mangleChar[TY.Tdelegate] = 'D';
+
+		mangleChar[TY.Tnone] = 'n';
+		mangleChar[TY.Tvoid] = 'v';
+		mangleChar[TY.Tint8] = 'g';
+		mangleChar[TY.Tuns8] = 'h';
+		mangleChar[TY.Tint16] = 's';
+		mangleChar[TY.Tuns16] = 't';
+		mangleChar[TY.Tint32] = 'i';
+		mangleChar[TY.Tuns32] = 'k';
+		mangleChar[TY.Tint64] = 'l';
+		mangleChar[TY.Tuns64] = 'm';
+		mangleChar[TY.Tfloat32] = 'f';
+		mangleChar[TY.Tfloat64] = 'd';
+		mangleChar[TY.Tfloat80] = 'e';
+
+		mangleChar[TY.Timaginary32] = 'o';
+		mangleChar[TY.Timaginary64] = 'p';
+		mangleChar[TY.Timaginary80] = 'j';
+		mangleChar[TY.Tcomplex32] = 'q';
+		mangleChar[TY.Tcomplex64] = 'r';
+		mangleChar[TY.Tcomplex80] = 'c';
+
+		mangleChar[TY.Tbool] = 'b';
+		mangleChar[TY.Tascii] = 'a';
+		mangleChar[TY.Twchar] = 'u';
+		mangleChar[TY.Tdchar] = 'w';
+
+		mangleChar[TY.Tbit] = '@';
+		mangleChar[TY.Tinstance] = '@';
+		mangleChar[TY.Terror] = '@';
+		mangleChar[TY.Ttypeof] = '@';
+		mangleChar[TY.Ttuple] = 'B';
+		mangleChar[TY.Tslice] = '@';
+		mangleChar[TY.Treturn] = '@';
+
+debug {
+		for (int i = 0; i < TY.TMAX; i++) {
+			if (!mangleChar[i]) {
+				writef("ty = %d\n", i);
+			}
+			assert(mangleChar[i]);
+		}
+}
+		// Set basic types
+		static TY[] basetab = [
+			TY.Tvoid, TY.Tint8, TY.Tuns8, TY.Tint16, TY.Tuns16, TY.Tint32, TY.Tuns32, TY.Tint64, TY.Tuns64,
+			TY.Tfloat32, TY.Tfloat64, TY.Tfloat80,
+			TY.Timaginary32, TY.Timaginary64, TY.Timaginary80,
+			TY.Tcomplex32, TY.Tcomplex64, TY.Tcomplex80,
+			TY.Tbool,
+			TY.Tascii, TY.Twchar, TY.Tdchar
+		];
+
+		foreach (bt; basetab) {
+			Type t = new TypeBasic(bt);
+			t = t.merge();
+			basic[bt] = t;
+		}
+
+		basic[TY.Terror] = basic[TY.Tint32];
+
+		tvoidptr = tvoid.pointerTo();
+
+		if (global.params.isX86_64) {
+			PTRSIZE = 8;
+			if (global.params.isLinux || global.params.isFreeBSD || global.params.isSolaris)
+				REALSIZE = 10;
+			else
+				REALSIZE = 8;
+			Tsize_t = TY.Tuns64;
+			Tptrdiff_t = TY.Tint64;
+		}
+		else
+		{
+			PTRSIZE = 4;
+version (TARGET_OSX) {
+			REALSIZE = 16;
+			REALPAD = 6;
+} else version (XXX) { //#elif TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS
+			REALSIZE = 12;
+			REALPAD = 2;
+} else {
+			REALSIZE = 10;
+			REALPAD = 0;
+}
+			Tsize_t = TY.Tuns32;
+			Tptrdiff_t = TY.Tint32;
+		}
+	}
+	
+    ulong size()
+	{
+		return size(Loc(0));
+	}
+	
+    ulong size(Loc loc)
+	{
+		error(loc, "no size for type %s", toChars());
+		return 1;
+	}
+	
+    uint alignsize()
+	{
+		return cast(uint)size(Loc(0));	///
+	}
+
+    Type semantic(Loc loc, Scope sc)
+	{
+		return merge();
+	}
+	
+    Type trySemantic(Loc loc, Scope sc)
+	{
+		uint errors = global.errors;
+		global.gag++;			// suppress printing of error messages
+		Type t = semantic(loc, sc);
+		global.gag--;
+		if (errors != global.errors)	// if any errors happened
+		{
+			global.errors = errors;
+			t = null;
+		}
+		return t;
+	}
+
+	/********************************
+	 * Name mangling.
+	 * Input:
+	 *	flag	0x100	do not do const/invariant
+	 */
+    void toDecoBuffer(OutBuffer buf, int flag = 0)
+	{
+		if (flag != mod && flag != 0x100)
+		{
+			if (mod & MOD.MODshared)
+				buf.writeByte('O');
+
+			if (mod & MOD.MODconst)
+				buf.writeByte('x');
+			else if (mod & MOD.MODinvariant)
+				buf.writeByte('y');
+
+			// Cannot be both const and invariant
+			assert((mod & (MOD.MODconst | MOD.MODinvariant)) != (MOD.MODconst | MOD.MODinvariant));
+		}
+		buf.writeByte(mangleChar[ty]);
+	}
+	
+    Type merge()
+	{
+		Type t = this;
+		assert(t);
+
+		//printf("merge(%s)\n", toChars());
+		if (deco is null)
+		{
+			OutBuffer buf = new OutBuffer();
+
+			//if (next)
+				//next = next.merge();
+			toDecoBuffer(buf);
+			StringValue* sv = stringtable.update(buf.extractString());
+			if (sv.ptrvalue)
+			{
+				t = cast(Type) sv.ptrvalue;
+debug {
+				if (!t.deco)
+					writef("t = %s\n", t.toChars());
+}
+				assert(t.deco);
+				//printf("old value, deco = '%s' %p\n", t.deco, t.deco);
+			}
+			else
+			{
+				sv.ptrvalue = cast(void*)this;
+				deco = sv.lstring.string_;
+				//printf("new value, deco = '%s' %p\n", t.deco, t.deco);
+			}
+		}
+		return t;
+	}
+
+	/*************************************
+	 * This version does a merge even if the deco is already computed.
+	 * Necessary for types that have a deco, but are not merged.
+	 */
+    Type merge2()
+	{
+		//printf("merge2(%s)\n", toChars());
+		Type t = this;
+		assert(t);
+		if (!t.deco)
+			return t.merge();
+
+		StringValue* sv = stringtable.lookup(t.deco);
+		if (sv && sv.ptrvalue)
+		{   
+			t = cast(Type)sv.ptrvalue;
+			assert(t.deco);
+		}
+		else
+			assert(0);
+
+		return t;
+	}
+
+    void toCBuffer(OutBuffer buf, Identifier ident, HdrGenState* hgs)
+	{
+		toCBuffer2(buf, hgs, MOD.MODundefined);
+		if (ident)
+		{
+			buf.writeByte(' ');
+			buf.writestring(ident.toChars());
+		}
+	}
+
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		buf.writestring(toChars());
+	}
+
+    void toCBuffer3(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		if (mod != this.mod)
+		{
+			string p;
+
+			if (this.mod & MOD.MODshared)
+				buf.writestring("shared(");
+
+			switch (this.mod & (MOD.MODconst | MOD.MODinvariant))
+			{
+				case MOD.MODundefined:
+					toCBuffer2(buf, hgs, this.mod);
+					break;
+				case MOD.MODconst:
+					p = "const(";
+					goto L1;
+				case MOD.MODinvariant:
+					p = "immutable(";
+					L1:	buf.writestring(p);
+					toCBuffer2(buf, hgs, this.mod);
+					buf.writeByte(')');
+					break;
+			}
+
+			if (this.mod & MOD.MODshared)
+				buf.writeByte(')');
+		}
+	}
+
+    void modToBuffer(OutBuffer buf)
+	{
+		if (mod & MOD.MODshared)
+			buf.writestring(" shared");
+		if (mod & MOD.MODconst)
+			buf.writestring(" const");
+		if (mod & MOD.MODinvariant)
+			buf.writestring(" immutable");
+	}
+
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+    bool isintegral()
+	{
+		return false;
+	}
+	
+    bool isfloating()	// real, imaginary, or complex
+	{
+		return false;
+	}
+	
+    bool isreal()
+	{
+		return false;
+	}
+	
+    bool isimaginary()
+	{
+		return false;
+	}
+	
+    bool iscomplex()
+	{
+		return false;
+	}
+	
+    bool isscalar()
+	{
+		return false;
+	}
+	
+    bool isunsigned()
+	{
+		return false;
+	}
+	
+    bool isauto()
+	{
+		return false;
+	}
+	
+    int isString()
+	{
+		return false;
+	}
+	
+	/**************************
+	 * Given:
+	 *	T a, b;
+	 * Can we assign:
+	 *	a = b;
+	 * ?
+	 */
+    int isAssignable()
+	{
+		return true;
+	}
+	
+    bool checkBoolean()	// if can be converted to boolean value
+	{
+		return isscalar();
+	}
+
+	/*********************************
+	 * Check type to see if it is based on a deprecated symbol.
+	 */
+    void checkDeprecated(Loc loc, Scope sc)
+	{
+		Dsymbol s = toDsymbol(sc);
+		if (s)
+			s.checkDeprecated(loc, sc);
+	}
+
+    bool isConst()	{ return (mod & MOD.MODconst) != 0; }
+
+	int isInvariant()	{ return mod & MOD.MODinvariant; }
+
+	int isMutable()	{ return !(mod & (MOD.MODconst | MOD.MODinvariant)); }
+
+	int isShared()	{ return mod & MOD.MODshared; }
+
+	int isSharedConst()	{ return mod == (MOD.MODshared | MOD.MODconst); }
+
+	/********************************
+	 * Convert to 'const'.
+	 */
+	Type constOf()
+	{
+static if (false) {
+		//printf("Type.constOf() %p %s\n", this, toChars());
+		if (isConst())
+			return this;
+		if (cto)
+			return cto;
+		Type t = makeConst();
+		t = t.merge();
+		cto = t;
+		if (ito)
+			ito.cto = t;
+		//if (t.nextOf()) assert(t.nextOf().isConst());
+		//printf("-Type.constOf() %p %s\n", t, toChars());
+		return t;
+} else {
+		//printf("Type.constOf() %p %s\n", this, toChars());
+		if (mod == MOD.MODconst)
+			return this;
+		if (cto)
+		{
+			assert(cto.mod == MOD.MODconst);
+			return cto;
+		}
+		Type t = makeConst();
+		t = t.merge();
+		t.fixTo(this);
+		//printf("-Type.constOf() %p %s\n", t, toChars());
+		return t;
+}
+	}
+
+	/********************************
+	 * Convert to 'immutable'.
+	 */
+    Type invariantOf()
+	{	
+static if (false) {
+		//printf("Type.invariantOf() %p %s\n", this, toChars());
+		if (isInvariant())
+		{
+			return this;
+		}
+		if (ito)
+		{
+			//if (!ito.isInvariant()) printf("\tito is %p %s\n", ito, ito.toChars());
+			assert(ito.isInvariant());
+			return ito;
+		}
+		Type t = makeInvariant();
+		t = t.merge();
+		ito = t;
+		if (cto)
+			cto.ito = t;
+static if (false) {// fails for function types
+		if (t.nextOf() && !t.nextOf().isInvariant())
+		{
+			assert(0);
+		}
+}
+		//printf("\t%p\n", t);
+		return t;
+} else {
+		//printf("Type.invariantOf() %p %s\n", this, toChars());
+		if (isInvariant())
+		{
+			return this;
+		}
+		if (ito)
+		{
+			assert(ito.isInvariant());
+			return ito;
+		}
+		Type t = makeInvariant();
+		t = t.merge();
+		t.fixTo(this);
+		//printf("\t%p\n", t);
+		return t;
+}
+	}
+
+    Type mutableOf()
+	{
+	static if (false) {
+		//printf("Type.mutableOf() %p, %s\n", this, toChars());
+		Type t = this;
+		if (isConst())
+		{	
+			t = cto;
+			assert(!t || t.isMutable());
+		}
+		else if (isInvariant())
+		{	
+			t = ito;
+			assert(!t || t.isMutable());
+		}
+		if (!t)
+		{
+			uint sz = this.classinfo.init.length;
+			t = cast(Type)malloc(sz);
+			memcpy(cast(void*)t, cast(void*)this, sz);
+			t.mod = 0;
+			t.deco = null;
+			t.arrayof = null;
+			t.pto = null;
+			t.rto = null;
+			t.cto = null;
+			t.ito = null;
+			t.sto = null;
+			t.scto = null;
+			t.vtinfo = null;
+			if (ty == Tsarray)
+			{   
+				TypeSArray ta = cast(TypeSArray)t;
+				//ta.next = ta.next.mutableOf();
+			}
+			t = t.merge();
+			if (isConst())
+			{   cto = t;
+				t.cto = this;
+				if (ito)
+					ito.cto = this;
+			}
+			else if (isInvariant())
+			{   ito = t;
+				t.ito = this;
+				if (cto)
+					cto.ito = this;
+			}
+		}
+		return t;
+	} else {
+		//printf("Type.mutableOf() %p, %s\n", this, toChars());
+		Type t = this;
+		if (isConst())
+		{	
+			if (isShared())
+				t = sto;		// shared const => shared
+			else
+				t = cto;
+			assert(!t || t.isMutable());
+		}
+		else if (isInvariant())
+		{	
+			t = ito;
+			assert(!t || (t.isMutable() && !t.isShared()));
+		}
+		if (!t)
+		{
+			uint sz = this.classinfo.init.length;
+			t = cast(Type)malloc(sz);
+			memcpy(cast(void*)t, cast(void*)this, sz);
+			t.mod = MODundefined;
+			t.deco = null;
+			t.arrayof = null;
+			t.pto = null;
+			t.rto = null;
+			t.cto = null;
+			t.ito = null;
+			t.sto = null;
+			t.scto = null;
+			t.vtinfo = null;
+			t = t.merge();
+
+			t.fixTo(this);
+
+			switch (mod)
+			{
+				case MODconst:
+					t.cto = this;
+					break;
+
+				case MODinvariant:
+					t.ito = this;
+					break;
+
+				case MODshared:
+					t.sto = this;
+					break;
+
+				case MODshared | MODconst:
+					t.scto = this;
+					break;
+
+				default:
+					assert(0);
+			}
+		}
+		return t;
+	}
+	}
+
+    Type sharedOf()
+	{
+		//printf("Type.sharedOf() %p, %s\n", this, toChars());
+		if (mod == MOD.MODshared)
+		{
+			return this;
+		}
+		if (sto)
+		{
+			assert(sto.isShared());
+			return sto;
+		}
+
+		Type t = makeShared();
+		t = t.merge();
+		t.fixTo(this);
+
+		//printf("\t%p\n", t);
+		return t;
+	}
+
+    Type sharedConstOf()
+	{
+		//printf("Type.sharedConstOf() %p, %s\n", this, toChars());
+		if (mod == (MODshared | MODconst))
+		{
+			return this;
+		}
+		if (scto)
+		{
+			assert(scto.mod == (MODshared | MODconst));
+			return scto;
+		}
+
+		Type t = makeSharedConst();
+		t = t.merge();
+		t.fixTo(this);
+		//printf("\t%p\n", t);
+
+		return t;
+	}
+	
+	static uint X(MOD m, MOD n)
+	{
+		return (((m) << 3) | (n));
+	}
+
+	/**********************************
+	 * For our new type 'this', which is type-constructed from t,
+	 * fill in the cto, ito, sto, scto shortcuts.
+	 */
+    void fixTo(Type t)
+	{
+		ito = t.ito;
+static if (false) {
+		/* Cannot do these because these are not fully transitive:
+		 * there can be a shared ptr to immutable, for example.
+		 * Immutable subtypes are always immutable, though.
+		 */
+		cto = t.cto;
+		sto = t.sto;
+		scto = t.scto;
+}
+
+		assert(mod != t.mod);
+
+		switch (X(mod, t.mod))
+		{
+		case X(MOD.MODundefined, MOD.MODconst):
+			cto = t;
+			break;
+
+		case X(MOD.MODundefined, MOD.MODinvariant):
+			ito = t;
+			break;
+
+		case X(MOD.MODundefined, MOD.MODshared):
+			sto = t;
+			break;
+
+		case X(MOD.MODundefined, MOD.MODshared | MOD.MODconst):
+			scto = t;
+			break;
+
+
+		case X(MOD.MODconst, MOD.MODundefined):
+			cto = null;
+			goto L2;
+
+		case X(MOD.MODconst, MOD.MODinvariant):
+			ito = t;
+			goto L2;
+
+		case X(MOD.MODconst, MOD.MODshared):
+			sto = t;
+			goto L2;
+
+		case X(MOD.MODconst, MOD.MODshared | MOD.MODconst):
+			scto = t;
+		L2:
+			t.cto = this;
+			break;
+
+
+		case X(MOD.MODinvariant, MOD.MODundefined):
+			ito = null;
+			goto L3;
+
+		case X(MOD.MODinvariant, MOD.MODconst):
+			cto = t;
+			goto L3;
+
+		case X(MOD.MODinvariant, MOD.MODshared):
+			sto = t;
+			goto L3;
+
+		case X(MOD.MODinvariant, MOD.MODshared | MOD.MODconst):
+			scto = t;
+		L3:
+			t.ito = this;
+			if (t.cto) t.cto.ito = this;
+			if (t.sto) t.sto.ito = this;
+			if (t.scto) t.scto.ito = this;
+			break;
+
+
+		case X(MOD.MODshared, MOD.MODundefined):
+			sto = null;
+			goto L4;
+
+		case X(MOD.MODshared, MOD.MODconst):
+			cto = t;
+			goto L4;
+
+		case X(MOD.MODshared, MOD.MODinvariant):
+			ito = t;
+			goto L4;
+
+		case X(MOD.MODshared, MOD.MODshared | MOD.MODconst):
+			scto = t;
+		L4:
+			t.sto = this;
+			break;
+
+
+		case X(MOD.MODshared | MOD.MODconst, MOD.MODundefined):
+			scto = null;
+			break;
+
+		case X(MOD.MODshared | MOD.MODconst, MOD.MODconst):
+			cto = t;
+			break;
+
+		case X(MOD.MODshared | MOD.MODconst, MOD.MODinvariant):
+			ito = t;
+			break;
+
+		case X(MOD.MODshared | MOD.MODconst, MOD.MODshared):
+			sto = t;
+		L5:
+			t.scto = this;
+			break;
+		}
+
+		check();
+		t.check();
+		//printf("fixTo: %s, %s\n", toChars(), t.toChars());
+	}
+	
+	/***************************
+	 * Look for bugs in constructing types.
+	 */
+    void check()
+	{
+		switch (mod)
+		{
+		case MOD.MODundefined:
+			if (cto) assert(cto.mod == MOD.MODconst);
+			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (sto) assert(sto.mod == MOD.MODshared);
+			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+			break;
+
+		case MOD.MODconst:
+			if (cto) assert(cto.mod == MOD.MODundefined);
+			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (sto) assert(sto.mod == MOD.MODshared);
+			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+			break;
+
+		case MOD.MODinvariant:
+			if (cto) assert(cto.mod == MOD.MODconst);
+			if (ito) assert(ito.mod == MOD.MODundefined);
+			if (sto) assert(sto.mod == MOD.MODshared);
+			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+			break;
+
+		case MOD.MODshared:
+			if (cto) assert(cto.mod == MOD.MODconst);
+			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (sto) assert(sto.mod == MOD.MODundefined);
+			if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst));
+			break;
+
+		case MOD.MODshared | MOD.MODconst:
+			if (cto) assert(cto.mod == MOD.MODconst);
+			if (ito) assert(ito.mod == MOD.MODinvariant);
+			if (sto) assert(sto.mod == MOD.MODshared);
+			if (scto) assert(scto.mod == MOD.MODundefined);
+			break;
+		}
+
+		Type tn = nextOf();
+		if (tn && ty != TY.Tfunction && ty != TY.Tdelegate)
+		{
+			// Verify transitivity
+			switch (mod)
+			{
+				case MOD.MODundefined:
+					break;
+
+				case MOD.MODconst:
+					assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODconst);
+					break;
+
+				case MOD.MODinvariant:
+					assert(tn.mod == MOD.MODinvariant);
+					break;
+
+				case MOD.MODshared:
+					assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODshared);
+					break;
+
+				case MOD.MODshared | MOD.MODconst:
+					assert(tn.mod & MOD.MODinvariant || tn.mod & (MOD.MODshared | MOD.MODconst));
+					break;
+			}
+			tn.check();
+		}
+	}
+
+    Type castMod(uint mod)
+	{
+		assert(false);
+	}
+	
+	/************************************
+	 * Add MODxxxx bits to existing type.
+	 * We're adding, not replacing, so adding const to
+	 * a shared type => "shared const"
+	 */
+    Type addMod(MOD mod)
+	{
+		Type t = this;
+
+		/* Add anything to immutable, and it remains immutable
+		 */
+		if (!t.isInvariant())
+		{
+			switch (mod)
+			{
+				case MOD.MODundefined:
+					break;
+
+				case MOD.MODconst:
+					if (isShared())
+						t = sharedConstOf();
+					else
+						t = constOf();
+					break;
+
+				case MOD.MODinvariant:
+					t = invariantOf();
+					break;
+
+				case MOD.MODshared:
+					if (isConst())
+						t = sharedConstOf();
+					else
+						t = sharedOf();
+					break;
+
+				case MOD.MODshared | MOD.MODconst:
+					t = sharedConstOf();
+					break;
+			}
+		}
+		return t;
+	}
+	
+    Type addStorageClass(STC stc)
+	{
+		/* Just translate to MOD bits and let addMod() do the work
+		 */
+		MOD mod = MOD.MODundefined;
+
+		if (stc & STC.STCimmutable)
+			mod = MOD.MODinvariant;
+		else
+		{	
+			if (stc & (STC.STCconst | STC.STCin))
+				mod = MOD.MODconst;
+			if (stc & STC.STCshared)
+				mod |= MOD.MODshared;
+		}
+
+		return addMod(mod);
+	}
+	
+    Type pointerTo()
+	{
+		if (pto is null)
+		{
+			Type t = new TypePointer(this);
+			pto = t.merge();
+		}
+
+		return pto;
+	}
+	
+    Type referenceTo()
+	{
+		assert(false);
+	}
+
+version (DumbClone) {
+	final Type clone()
+	{
+		auto size = this.classinfo.init.length;
+		auto ptr = malloc(size);
+		memcpy(ptr, cast(void*)this, size);
+
+		return cast(Type)ptr;
+	}
+} else {
+	final Type cloneTo(Type t)
+	{
+		t.ctype = ctype;
+		return t;
+	}
+
+	Type clone()
+	{
+		assert(this.classinfo is Type.classinfo);
+		return cloneTo(new Type(ty));
+	}
+}
+	
+    Type arrayOf()
+	{
+		if (!arrayof)
+		{	
+			Type t = new TypeDArray(this);
+			arrayof = t.merge();
+		}
+		return arrayof;
+	}
+	
+    Type makeConst()
+	{
+		//printf("Type.makeConst() %p, %s\n", this, toChars());
+		if (cto)
+			return cto;
+
+		Type t = clone();
+		t.mod = MOD.MODconst;
+		
+		t.deco = null;
+		t.arrayof = null;
+		t.pto = null;
+		t.rto = null;
+		t.cto = null;
+		t.ito = null;
+		t.sto = null;
+		t.scto = null;
+		t.vtinfo = null;
+		
+		//printf("-Type.makeConst() %p, %s\n", t, toChars());
+		return t;
+	}
+	
+    Type makeInvariant()
+	{
+		if (ito) {
+			return ito;
+		}
+
+		Type t = clone();
+		t.mod = MOD.MODinvariant;
+
+		t.deco = null;
+		t.arrayof = null;
+		t.pto = null;
+		t.rto = null;
+		t.cto = null;
+		t.ito = null;
+		t.sto = null;
+		t.scto = null;
+		t.vtinfo = null;
+
+		return t;
+	}
+	
+    Type makeShared()
+	{
+		if (sto)
+			return sto;
+
+		Type t = clone();
+		t.mod = MOD.MODshared;
+
+		t.deco = null;
+		t.arrayof = null;
+		t.pto = null;
+		t.rto = null;
+		t.cto = null;
+		t.ito = null;
+		t.sto = null;
+		t.scto = null;
+		t.vtinfo = null;
+
+		return t;
+	}
+	
+    Type makeSharedConst()
+	{
+		if (scto)
+			return scto;
+
+		Type t = clone();
+		t.mod = MODshared | MODconst;
+
+		t.deco = null;
+		t.arrayof = null;
+		t.pto = null;
+		t.rto = null;
+		t.cto = null;
+		t.ito = null;
+		t.sto = null;
+		t.scto = null;
+		t.vtinfo = null;
+
+		return t;
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		return null;
+	}
+
+	/*******************************
+	 * If this is a shell around another type,
+	 * get that other type.
+	 */
+		
+    Type toBasetype()
+	{
+		return this;
+	}
+	
+	/**************************
+	 * Return type with the top level of it being mutable.
+	 */
+    Type toHeadMutable()
+	{
+		if (!mod)
+			return this;
+
+		return mutableOf();
+	}
+	
+    bool isBaseOf(Type t, int* poffset)
+	{
+		return false;		// assume not
+	}
+	
+	/*******************************
+	 * Determine if converting 'this' to 'to' is an identity operation,
+	 * a conversion to const operation, or the types aren't the same.
+	 * Returns:
+	 *	MATCHequal	'this' == 'to'
+	 *	MATCHconst	'to' is const
+	 *	MATCHnomatch	conversion to mutable or invariant
+	 */
+    MATCH constConv(Type to)
+	{
+		if (equals(to))
+			return MATCH.MATCHexact;
+		if (ty == to.ty && to.mod == MOD.MODconst)
+			return MATCH.MATCHconst;
+		return MATCH.MATCHnomatch;
+	}
+	
+	/********************************
+	 * Determine if 'this' can be implicitly converted
+	 * to type 'to'.
+	 * Returns:
+	 *	MATCHnomatch, MATCHconvert, MATCHconst, MATCHexact
+	 */
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("Type.implicitConvTo(this=%p, to=%p)\n", this, to);
+		//printf("from: %s\n", toChars());
+		//printf("to  : %s\n", to.toChars());
+		if (this is to)
+			return MATCHexact;
+
+		return MATCHnomatch;
+	}
+	
+    ClassDeclaration isClassHandle()
+	{
+		return null;
+	}
+
+    Expression getProperty(Loc loc, Identifier ident)
+	{
+		Expression e;
+
+version (LOGDOTEXP) {
+		printf("Type.getProperty(type = '%s', ident = '%s')\n", toChars(), ident.toChars());
+}
+		if (ident == Id.__sizeof)
+		{
+			e = new IntegerExp(loc, size(loc), Type.tsize_t);
+		}
+		else if (ident == Id.size)
+		{
+			error(loc, ".size property should be replaced with .sizeof");
+			e = new ErrorExp();
+		}
+		else if (ident is Id.alignof_)
+		{
+			e = new IntegerExp(loc, alignsize(), Type.tsize_t);
+		}
+		else if (ident == Id.typeinfo_)
+		{
+			if (!global.params.useDeprecated)
+				error(loc, ".typeinfo deprecated, use typeid(type)");
+			e = getTypeInfo(null);
+		}
+		else if (ident == Id.init_)
+		{
+			if (ty == TY.Tvoid)
+				error(loc, "void does not have an initializer");
+			e = defaultInit(loc);
+		}
+		else if (ident is Id.mangleof_)
+		{
+			string s;
+			if (!deco) {  
+				s = toChars();
+				error(loc, "forward reference of type %s.mangleof", s);
+			} else {
+				s = deco;
+			}
+
+			e = new StringExp(loc, s, 'c');
+			Scope sc = new Scope();
+			e = e.semantic(sc);
+		}
+		else if (ident is Id.stringof_)
+		{	
+			string s = toChars();
+			e = new StringExp(loc, s, 'c');
+			Scope sc = new Scope();
+			e = e.semantic(sc);
+		}
+		else
+		{
+			error(loc, "no property '%s' for type '%s'", ident.toChars(), toChars());
+			e = new ErrorExp();
+		}
+		return e;
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+		VarDeclaration v = null;
+
+version (LOGDOTEXP) {
+		printf("Type.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+}
+		if (e.op == TOK.TOKdotvar)
+		{
+			DotVarExp dv = cast(DotVarExp)e;
+			v = dv.var.isVarDeclaration();
+		}
+		else if (e.op == TOK.TOKvar)
+		{
+			VarExp ve = cast(VarExp)e;
+			v = ve.var.isVarDeclaration();
+		}
+		if (v)
+		{
+			if (ident is Id.offset)
+			{
+				if (!global.params.useDeprecated)
+					error(e.loc, ".offset deprecated, use .offsetof");
+				goto Loffset;
+			}
+			else if (ident is Id.offsetof)
+			{
+			  Loffset:
+				if (v.storage_class & STC.STCfield)
+				{
+					e = new IntegerExp(e.loc, v.offset, Type.tsize_t);
+					return e;
+				}
+			}
+			else if (ident is Id.init_)
+			{
+static if (false) {
+				if (v.init)
+				{
+					if (v.init.isVoidInitializer())
+						error(e.loc, "%s.init is void", v.toChars());
+					else
+					{   Loc loc = e.loc;
+						e = v.init.toExpression();
+						if (e.op == TOK.TOKassign || e.op == TOK.TOKconstruct || e.op == TOK.TOKblit)
+						{
+							e = (cast(AssignExp)e).e2;
+
+							/* Take care of case where we used a 0
+							 * to initialize the struct.
+							 */
+							if (e.type == Type.tint32 &&
+								e.isBool(0) &&
+								v.type.toBasetype().ty == TY.Tstruct)
+							{
+								e = v.type.defaultInit(e.loc);
+							}
+						}
+						e = e.optimize(WANTvalue | WANTinterpret);
+			//		    if (!e.isConst())
+			//			error(loc, ".init cannot be evaluated at compile time");
+					}
+					return e;
+				}
+}
+				Expression ex = defaultInit(e.loc);
+				return ex;
+			}
+		}
+		if (ident is Id.typeinfo_)
+		{
+			if (!global.params.useDeprecated)
+				error(e.loc, ".typeinfo deprecated, use typeid(type)");
+			e = getTypeInfo(sc);
+			return e;
+		}
+		if (ident is Id.stringof_)
+		{		
+			string s = e.toChars();
+			e = new StringExp(e.loc, s, 'c');
+			Scope sc2 = new Scope(); ///
+			e = e.semantic(sc2);
+			return e;
+		}
+		return getProperty(e.loc, ident);
+	}
+	
+    uint memalign(uint salign)
+	{
+		return salign;
+	}
+	
+    ///Expression defaultInit(Loc loc = Loc(0))
+    Expression defaultInit(Loc loc)
+	{
+		assert(false);
+	}
+	
+    ///bool isZeroInit(Loc loc = Loc(0))		// if initializer is 0
+	bool isZeroInit(Loc loc)		// if initializer is 0
+	{
+		assert(false);
+	}
+	
+    dt_t** toDt(dt_t** pdt)
+	{
+		//printf("Type.toDt()\n");
+		Expression e = defaultInit(Loc(0));
+		return e.toDt(pdt);
+	}
+	
+    Identifier getTypeInfoIdent(int internal)
+	{
+		// _init_10TypeInfo_%s
+		scope OutBuffer buf = new OutBuffer();
+		Identifier id;
+		char* name;
+		int len;
+
+		if (internal)
+		{	
+			buf.writeByte(mangleChar[ty]);
+			if (ty == TY.Tarray)
+				buf.writeByte(mangleChar[(cast(TypeArray)this).next.ty]);
+		}
+		else
+			toDecoBuffer(buf);
+
+		len = buf.offset;
+		name = cast(char*)alloca(19 + len.sizeof * 3 + len + 1);
+		buf.writeByte(0);
+	version (TARGET_OSX) {
+		// The LINKc will prepend the _
+		len = sprintf(name, "D%dTypeInfo_%s6__initZ".ptr, 9 + len, buf.data);
+	} else {
+		len = sprintf(name, "_D%dTypeInfo_%s6__initZ".ptr, 9 + len, buf.data);
+	}
+		if (global.params.isWindows)
+			name++;			// C mangling will add it back in
+		//printf("name = %s\n", name);
+		id = Lexer.idPool(name[0..len-1].idup);
+		return id;
+	}
+	
+	/* These form the heart of template argument deduction.
+	 * Given 'this' being the type argument to the template instance,
+	 * it is matched against the template declaration parameter specialization
+	 * 'tparam' to determine the type to be used for the parameter.
+	 * Example:
+	 *	template Foo(T:T*)	// template declaration
+	 *	Foo!(int*)		// template instantiation
+	 * Input:
+	 *	this = int*
+	 *	tparam = T
+	 *	parameters = [ T:T* ]	// Array of TemplateParameter's
+	 * Output:
+	 *	dedtypes = [ int ]	// Array of Expression/Type's
+	 */
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+	static if (false) {
+		printf("Type.deduceType()\n");
+		printf("\tthis   = %d, ", ty); print();
+		printf("\ttparam = %d, ", tparam.ty); tparam.print();
+	}
+		if (!tparam)
+			goto Lnomatch;
+
+		if (this == tparam)
+			goto Lexact;
+
+		if (tparam.ty == Tident)
+		{
+			// Determine which parameter tparam is
+			int i = templateParameterLookup(tparam, parameters);
+			if (i == -1)
+			{
+				if (!sc)
+					goto Lnomatch;
+
+				/* Need a loc to go with the semantic routine.
+				 */
+				Loc loc;
+				if (parameters.dim)
+				{
+					TemplateParameter tp = cast(TemplateParameter)parameters.data[0];
+					loc = tp.loc;
+				}
+
+				/* BUG: what if tparam is a template instance, that
+				 * has as an argument another Tident?
+				 */
+				tparam = tparam.semantic(loc, sc);
+				assert(tparam.ty != Tident);
+				return deduceType(sc, tparam, parameters, dedtypes);
+			}
+
+			TemplateParameter tp = cast(TemplateParameter)parameters.data[i];
+
+			// Found the corresponding parameter tp
+			if (!tp.isTemplateTypeParameter())
+				goto Lnomatch;
+			Type tt = this;
+			Type at = cast(Type)dedtypes.data[i];
+
+			// 3*3 == 9 cases
+			if (tparam.isMutable())
+			{   // foo(U:U) T            => T
+				// foo(U:U) const(T)     => const(T)
+				// foo(U:U) invariant(T) => invariant(T)
+				if (!at)
+				{   
+					dedtypes.data[i] = cast(void*)this;
+					goto Lexact;
+				}
+			}
+			else if (mod == tparam.mod)
+			{   // foo(U:const(U))     const(T)     => T
+				// foo(U:invariant(U)) invariant(T) => T
+				tt = mutableOf();
+				if (!at)
+				{   
+					dedtypes.data[i] = cast(void*)tt;
+					goto Lexact;
+				}
+			}
+			else if (tparam.isConst())
+			{   // foo(U:const(U)) T            => T
+				// foo(U:const(U)) invariant(T) => T
+				tt = mutableOf();
+				if (!at)
+				{   
+					dedtypes.data[i] = cast(void*)tt;
+					goto Lconst;
+				}
+			}
+			else
+			{   // foo(U:invariant(U)) T        => nomatch
+				// foo(U:invariant(U)) const(T) => nomatch
+				if (!at)
+					goto Lnomatch;
+			}
+
+			if (tt.equals(at))
+				goto Lexact;
+			else if (tt.ty == Tclass && at.ty == Tclass)
+			{
+				return tt.implicitConvTo(at);
+			}
+			else if (tt.ty == Tsarray && at.ty == Tarray &&
+				tt.nextOf().implicitConvTo(at.nextOf()) >= MATCHconst)
+			{
+				goto Lexact;
+			}
+			else
+				goto Lnomatch;
+		}
+
+		if (ty != tparam.ty)
+		return implicitConvTo(tparam);
+	//	goto Lnomatch;
+
+		if (nextOf())
+			return nextOf().deduceType(sc, tparam.nextOf(), parameters, dedtypes);
+
+	Lexact:
+		return MATCHexact;
+
+	Lnomatch:
+		return MATCHnomatch;
+
+	version (DMDV2) {
+	Lconst:
+		return MATCHconst;
+	}
+	}
+
+    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		//printf("Type.resolve() %s, %d\n", toChars(), ty);
+		Type t = semantic(loc, sc);
+		*pt = t;
+		*pe = null;
+		*ps = null;
+	}
+	
+	/*******************************************
+	 * Get a canonicalized form of the TypeInfo for use with the internal
+	 * runtime library routines. Canonicalized in that static arrays are
+	 * represented as dynamic arrays, enums are represented by their
+	 * underlying type, etc. This reduces the number of TypeInfo's needed,
+	 * so we can use the custom internal ones more.
+	 */
+    Expression getInternalTypeInfo(Scope sc)
+	{
+		TypeInfoDeclaration tid;
+		Expression e;
+		Type t;
+		static TypeInfoDeclaration internalTI[TMAX];
+
+		//printf("Type.getInternalTypeInfo() %s\n", toChars());
+		t = toBasetype();
+		switch (t.ty)
+		{
+			case Tsarray:
+		static if (false) {
+				// convert to corresponding dynamic array type
+				t = t.nextOf().mutableOf().arrayOf();
+		}
+				break;
+
+			case Tclass:
+				if ((cast(TypeClass)t).sym.isInterfaceDeclaration())
+					break;
+				goto Linternal;
+
+			case Tarray:
+				// convert to corresponding dynamic array type
+				t = t.nextOf().mutableOf().arrayOf();
+				if (t.nextOf().ty != Tclass)
+					break;
+				goto Linternal;
+
+			case Tfunction:
+			case Tdelegate:
+			case Tpointer:
+			Linternal:
+				tid = internalTI[t.ty];
+				if (!tid)
+				{	
+					tid = new TypeInfoDeclaration(t, 1);
+					internalTI[t.ty] = tid;
+				}
+				e = new VarExp(Loc(0), tid);
+				e = e.addressOf(sc);
+				e.type = tid.type;	// do this so we don't get redundant dereference
+				return e;
+
+			default:
+				break;
+		}
+		//printf("\tcalling getTypeInfo() %s\n", t.toChars());
+		return t.getTypeInfo(sc);
+	}
+	
+	/****************************************************
+	 * Get the exact TypeInfo.
+	 */
+    Expression getTypeInfo(Scope sc)
+	{
+		Expression e;
+		Type t;
+
+		//printf("Type.getTypeInfo() %p, %s\n", this, toChars());
+		t = merge2();	// do this since not all Type's are merge'd
+		if (!t.vtinfo)
+		{
+version (DMDV2) {
+			if (t.isShared())	// does both 'shared' and 'shared const'
+				t.vtinfo = new TypeInfoSharedDeclaration(t);
+			else if (t.isConst())
+				t.vtinfo = new TypeInfoConstDeclaration(t);
+			else if (t.isInvariant())
+				t.vtinfo = new TypeInfoInvariantDeclaration(t);
+			else
+				t.vtinfo = t.getTypeInfoDeclaration();
+} else {
+			t.vtinfo = t.getTypeInfoDeclaration();
+}
+			assert(t.vtinfo);
+			vtinfo = t.vtinfo;
+
+			/* If this has a custom implementation in std/typeinfo, then
+			 * do not generate a COMDAT for it.
+			 */
+			if (!t.builtinTypeInfo())
+			{   
+				// Generate COMDAT
+				if (sc)			// if in semantic() pass
+				{	
+					// Find module that will go all the way to an object file
+					Module m = sc.module_.importedFrom;
+					m.members.push(cast(void*)t.vtinfo);
+				}
+				else			// if in obj generation pass
+				{
+					t.vtinfo.toObjFile(global.params.multiobj);
+				}
+			}
+		}
+		e = new VarExp(Loc(0), t.vtinfo);
+		e = e.addressOf(sc);
+		e.type = t.vtinfo.type;		// do this so we don't get redundant dereference
+		return e;
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		//printf("Type.getTypeInfoDeclaration() %s\n", toChars());
+		return new TypeInfoDeclaration(this, 0);
+	}
+	
+	/* These decide if there's an instance for them already in std.typeinfo,
+	 * because then the compiler doesn't need to build one.
+	 */
+    bool builtinTypeInfo()
+	{
+		return false;
+	}
+	
+	/*******************************
+	 * If one of the subtypes of this type is a TypeIdentifier,
+	 * i.e. it's an unresolved type, return that type.
+	 */
+    Type reliesOnTident()
+	{
+		return null;
+	}
+	
+    Expression toExpression()
+	{
+		assert(false);
+	}
+	
+	/***************************************
+	 * Return true if type has pointers that need to
+	 * be scanned by the GC during a collection cycle.
+	 */
+    bool hasPointers()
+	{
+		return false;
+	}
+	
+	/*************************************
+	 * If this is a type of something, return that something.
+	 */
+    Type nextOf()
+	{
+		return null;
+	}
+	
+    ulong sizemask()
+	{
+		assert(false);
+	}
+	
+    static void error(T...)(Loc loc, string format, T t)
+	{
+		.error(loc, format, t);
+	}
+	
+    static void warning(T...)(Loc loc, string format, T t)
+	{
+		assert(false);
+	}
+
+    // For backend
+	/*****************************
+	 * Return back end type corresponding to D front end type.
+	 */
+    TYM totym()
+	{
+		TYM t;
+
+		switch (ty)
+		{
+		case TY.Tvoid:	t = TYM.TYvoid;	break;
+		case TY.Tint8:	t = TYM.TYschar;	break;
+		case TY.Tuns8:	t = TYM.TYuchar;	break;
+		case TY.Tint16:	t = TYM.TYshort;	break;
+		case TY.Tuns16:	t = TYM.TYushort;	break;
+		case TY.Tint32:	t = TYM.TYint;	break;
+		case TY.Tuns32:	t = TYM.TYuint;	break;
+		case TY.Tint64:	t = TYM.TYllong;	break;
+		case TY.Tuns64:	t = TYM.TYullong;	break;
+		case TY.Tfloat32:	t = TYM.TYfloat;	break;
+		case TY.Tfloat64:	t = TYM.TYdouble;	break;
+		case TY.Tfloat80:	t = TYM.TYldouble;	break;
+		case TY.Timaginary32: t = TYM.TYifloat; break;
+		case TY.Timaginary64: t = TYM.TYidouble; break;
+		case TY.Timaginary80: t = TYM.TYildouble; break;
+		case TY.Tcomplex32: t = TYM.TYcfloat;	break;
+		case TY.Tcomplex64: t = TYM.TYcdouble;	break;
+		case TY.Tcomplex80: t = TYM.TYcldouble; break;
+		//case Tbit:	t = TYM.TYuchar;	break;
+		case TY.Tbool:	t = TYM.TYbool;	break;
+		case TY.Tchar:	t = TYM.TYchar;	break;
+	version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+		case TY.Twchar:	t = TYM.TYwchar_t;	break;
+		case TY.Tdchar:	t = TYM.TYdchar;	break;
+	} else {
+		case TY.Twchar:	t = TYM.TYwchar_t;	break;
+		case TY.Tdchar:
+			t = (global.params.symdebug == 1) ? TYM.TYdchar : TYM.TYulong;
+			break;
+	}
+
+		case TY.Taarray:	t = TYM.TYaarray;	break;
+		case TY.Tclass:
+		case TY.Treference:
+		case TY.Tpointer:	t = TYM.TYnptr;	break;
+		case TY.Tdelegate:	t = TYM.TYdelegate;	break;
+		case TY.Tarray:	t = TYM.TYdarray;	break;
+		case TY.Tsarray:	t = TYM.TYarray;	break;
+		case TY.Tstruct:	t = TYM.TYstruct;	break;
+
+		case TY.Tenum:
+		case TY.Ttypedef:
+			 t = toBasetype().totym();
+			 break;
+
+		case TY.Tident:
+		case TY.Ttypeof:
+	debug {
+			writef("ty = %d, '%s'\n", ty, toChars());
+	}
+			error (Loc(0), "forward reference of %s", toChars());
+			t = TYM.TYint;
+			break;
+
+		default:
+	debug {
+			writef("ty = %d, '%s'\n", ty, toChars());
+	}
+			assert(0);
+		}
+
+	version (DMDV2) {
+		// Add modifiers
+		switch (mod)
+		{
+		case MOD.MODundefined:
+			break;
+		case MOD.MODconst:
+			t |= mTY.mTYconst;
+			break;
+		case MOD.MODinvariant:
+			t |= mTY.mTYimmutable;
+			break;
+		case MOD.MODshared:
+			t |= mTY.mTYshared;
+			break;
+		case MOD.MODshared | MOD.MODconst:
+			t |= mTY.mTYshared | mTY.mTYconst;
+			break;
+		default:
+			assert(0);
+		}
+	}
+
+		return t;
+	}
+	
+	/***************************************
+	 * Convert from D type to C type.
+	 * This is done so C debug info can be generated.
+	 */
+    type* toCtype()
+	{
+		if (!ctype)
+		{
+			ctype = type_fake(totym());
+			ctype.Tcount++;
+		}
+		return ctype;
+	}
+	
+    type* toCParamtype()
+	{
+		return toCtype();
+	}
+	
+    Symbol* toSymbol()
+	{
+		assert(false);
+	}
+	
+    // For eliminating dynamic_cast
+    TypeBasic isTypeBasic()
+	{
+		return null;
+	}
+
+	static Type tvoid()
+	{
+		return basic[TY.Tvoid];
+	}
+
+	static Type tint8()
+	{
+		return basic[TY.Tint8];
+	}
+
+	static Type tuns8()
+	{
+		return basic[TY.Tuns8];
+	}
+
+	static Type tint16()
+	{
+		return basic[TY.Tint16];
+	}
+
+	static Type tuns16()
+	{
+		return basic[TY.Tuns16];
+	}
+
+	static Type tint32()
+	{
+		return basic[TY.Tint32];
+	}
+
+	static Type tuns32()
+	{
+		return basic[TY.Tuns32];
+	}
+
+	static Type tint64()
+	{
+		return basic[TY.Tint64];
+	}
+
+	static Type tuns64()
+	{
+		return basic[TY.Tuns64];
+	}
+
+	static Type tfloat32()
+	{
+		return basic[TY.Tfloat32];
+	}
+
+	static Type tfloat64()
+	{
+		return basic[TY.Tfloat64];
+	}
+
+	static Type tfloat80()
+	{
+		return basic[TY.Tfloat80];
+	}
+
+	static Type timaginary32()
+	{
+		return basic[TY.Timaginary32];
+	}
+
+	static Type timaginary64()
+	{
+		return basic[TY.Timaginary64];
+	}
+
+	static Type timaginary80()
+	{
+		return basic[TY.Timaginary80];
+	}
+
+	static Type tcomplex32()
+	{
+		return basic[TY.Tcomplex32];
+	}
+
+	static Type tcomplex64()
+	{
+		return basic[TY.Tcomplex64];
+	}
+
+	static Type tcomplex80()
+	{
+		return basic[TY.Tcomplex80];
+	}
+
+	static Type tbit()
+	{
+		return basic[TY.Tbit];
+	}
+
+	static Type tbool()
+	{
+		return basic[TY.Tbool];
+	}
+
+	static Type tchar()
+	{
+		return basic[TY.Tchar];
+	}
+
+	static Type twchar()
+	{
+		return basic[TY.Twchar];
+	}
+
+	static Type tdchar()
+	{
+		return basic[TY.Tdchar];
+	}
+	
+	// Some special types
+    static Type tshiftcnt()
+	{
+		return tint32;		// right side of shift expression
+	}
+
+//    #define tboolean	tint32		// result of boolean expression
+    static Type tboolean()
+	{
+		return tbool;		// result of boolean expression
+	}
+	
+    static Type tindex()
+	{
+		return tint32;		// array/ptr index
+	}
+	
+    static Type tvoidptr;		// void*
+    
+	static Type terror()
+	{
+		return basic[TY.Terror];	// for error recovery
+	}
+
+    static Type tsize_t()
+	{
+		return basic[Tsize_t];		// matches size_t alias
+	}
+	
+    static Type tptrdiff_t()
+	{
+		return basic[Tptrdiff_t];	// matches ptrdiff_t alias
+	}
+	
+    static Type thash_t()
+	{
+		return tsize_t;			// matches hash_t alias
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeAArray.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,360 @@
+module dmd.TypeAArray;
+
+import dmd.TypeArray;
+import dmd.MOD;
+import dmd.ArrayTypes;
+import dmd.TypeInfoDeclaration;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.Type;
+import dmd.TypeSArray;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.TY;
+import dmd.Id;
+import dmd.CallExp;
+import dmd.IntegerExp;
+import dmd.FuncDeclaration;
+import dmd.VarExp;
+import dmd.TypeFunction;
+import dmd.NullExp;
+import dmd.Array;
+
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.SC;
+import dmd.backend.LIST;
+import dmd.backend.TYM;
+import dmd.backend.TF;
+import dmd.backend.mTYman;
+
+import core.stdc.stdio;
+import core.stdc.stdlib;
+
+class TypeAArray : TypeArray
+{
+    Type index;		// key type
+
+    this(Type t, Type index)
+	{
+		super(Taarray, t);
+		this.index = index;
+	}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    ulong size(Loc loc)
+	{
+		return PTRSIZE /* * 2*/;
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeAArray::semantic() %s index.ty = %d\n", toChars(), index.ty);
+
+		// Deal with the case where we thought the index was a type, but
+		// in reality it was an expression.
+		if (index.ty == Tident || index.ty == Tinstance || index.ty == Tsarray)
+		{
+			Expression e;
+			Type t;
+			Dsymbol s;
+
+			index.resolve(loc, sc, &e, &t, &s);
+			if (e)
+			{   // It was an expression -
+				// Rewrite as a static array
+				TypeSArray tsa = new TypeSArray(next, e);
+				return tsa.semantic(loc,sc);
+			}
+			else if (t)
+				index = t;
+			else
+				index.error(loc, "index is not a type or an expression");
+		}
+		else
+			index = index.semantic(loc,sc);
+
+		if (index.nextOf() && !index.nextOf().isInvariant())
+		{
+			index = index.constOf().mutableOf();
+static if (false) {
+			printf("index is %p %s\n", index, index.toChars());
+			index.check();
+			printf("index.mod = x%x\n", index.mod);
+			printf("index.ito = x%x\n", index.ito);
+			if (index.ito) {
+				printf("index.ito.mod = x%x\n", index.ito.mod);
+				printf("index.ito.ito = x%x\n", index.ito.ito);
+			}
+}
+		}
+
+		switch (index.toBasetype().ty)
+		{
+			case Tbool:
+			case Tfunction:
+			case Tvoid:
+			case Tnone:
+				error(loc, "can't have associative array key of %s", index.toBasetype().toChars());
+				break;
+			default:
+				break;	///
+		}
+		next = next.semantic(loc,sc);
+		transitive();
+
+		switch (next.toBasetype().ty)
+		{
+			case Tfunction:
+			case Tnone:
+				error(loc, "can't have associative array of %s", next.toChars());
+				break;
+			default:
+				break;	///
+		}
+		if (next.isauto())
+			error(loc, "cannot have array of auto %s", next.toChars());
+
+		return merge();
+	}
+	
+    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		Type.toDecoBuffer(buf, flag);
+		index.toDecoBuffer(buf);
+		next.toDecoBuffer(buf, (flag & 0x100) ? MOD.MODundefined : mod);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+	version (LOGDOTEXP) {
+		printf("TypeAArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+	}
+		if (ident == Id.length)
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+
+			fd = FuncDeclaration.genCfunc(Type.tsize_t, Id.aaLen);
+			ec = new VarExp(Loc(0), fd);
+			arguments = new Expressions();
+			arguments.push(cast(void*)e);
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = (cast(TypeFunction)fd.type).next;
+		}
+		else if (ident == Id.keys)
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+			int size = cast(int)index.size(e.loc);
+
+			assert(size);
+			fd = FuncDeclaration.genCfunc(Type.tindex, Id.aaKeys);
+			ec = new VarExp(Loc(0), fd);
+			arguments = new Expressions();
+			arguments.push(cast(void*)e);
+			arguments.push(cast(void*)new IntegerExp(Loc(0), size, Type.tsize_t));
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = index.arrayOf();
+		}
+		else if (ident == Id.values)
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+
+			fd = FuncDeclaration.genCfunc(Type.tindex, Id.aaValues);
+			ec = new VarExp(Loc(0), fd);
+			arguments = new Expressions();
+			arguments.push(cast(void*)e);
+			size_t keysize = cast(size_t)index.size(e.loc);
+			keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1);
+			arguments.push(cast(void*)new IntegerExp(Loc(0), keysize, Type.tsize_t));
+			arguments.push(cast(void*)new IntegerExp(Loc(0), next.size(e.loc), Type.tsize_t));
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = next.arrayOf();
+		}
+		else if (ident == Id.rehash)
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+
+			fd = FuncDeclaration.genCfunc(Type.tint64, Id.aaRehash);
+			ec = new VarExp(Loc(0), fd);
+			arguments = new Expressions();
+			arguments.push(cast(void*)e.addressOf(sc));
+			arguments.push(cast(void*)index.getInternalTypeInfo(sc));
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = this;
+		}
+		else
+		{
+			e = Type.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypeAArray.defaultInit() '%s'\n", toChars());
+	}
+		Expression e = new NullExp(loc);
+		e.type = this;
+		return e;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		assert(false);
+	}
+	
+    bool checkBoolean()
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		assert(false);
+	}
+	
+    bool hasPointers()
+	{
+		return true;
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		assert(false);
+	}
+	
+    MATCH constConv(Type to)
+	{
+		assert(false);
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    // Back end
+	/********************************************
+	 * Determine the right symbol to look up
+	 * an associative array element.
+	 * Input:
+	 *	flags	0	don't add value signature
+	 *		1	add value signature
+	 */
+    Symbol* aaGetSymbol(const(char)* func, int flags)
+    in
+    {
+		assert(func);
+		assert((flags & ~1) == 0);
+    }
+    out (result)
+    {
+		assert(result);
+    }
+    body
+    {
+		int sz;
+		char* id;
+		type* t;
+		Symbol* s;
+		int i;
+
+		// Dumb linear symbol table - should use associative array!
+		static Array sarray = null;
+
+		//printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key);
+	static if (false) {
+		scope OutBuffer buf = new OutBuffer();
+		key.toKeyBuffer(buf);
+
+		sz = next.size();		// it's just data, so we only care about the size
+		sz = (sz + 3) & ~3;		// reduce proliferation of library routines
+		id = cast(char*)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1);
+		buf.writeByte(0);
+		if (flags & 1)
+			sprintf(id, "_aa%s%s%d", func, buf.data, sz);
+		else
+			sprintf(id, "_aa%s%s", func, buf.data);
+	} else {
+		id = cast(char*)alloca(3 + strlen(func) + 1);
+		sprintf(id, "_aa%s", func);
+	}
+		if (!sarray)
+			sarray = new Array();
+
+		// See if symbol is already in sarray
+		for (i = 0; i < sarray.dim; i++)
+		{   
+			s = cast(Symbol*)sarray.data[i];
+			if (strcmp(id, s.Sident.ptr) == 0)
+				return s;			// use existing Symbol
+		}
+
+		// Create new Symbol
+
+		s = symbol_calloc(id);
+		slist_add(s);
+		s.Sclass = SCextern;
+		s.Ssymnum = -1;
+		symbol_func(s);
+
+		t = type_alloc(TYnfunc);
+		t.Tflags = TFprototype | TFfixed;
+		t.Tmangle = mTYman_c;
+		t.Tparamtypes = null;
+		t.Tnext = next.toCtype();
+		t.Tnext.Tcount++;
+		t.Tcount++;
+		s.Stype = t;
+
+		sarray.push(s);			// remember it
+		return s;
+    }
+
+    type* toCtype()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeArray.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,134 @@
+module dmd.TypeArray;
+
+import dmd.Type;
+import dmd.TypeNext;
+import dmd.Id;
+import dmd.Loc;
+import dmd.ArrayTypes;
+import dmd.CallExp;
+import dmd.FuncDeclaration;
+import dmd.VarExp;
+import dmd.Expression;
+import dmd.MATCH;
+import dmd.Scope;
+import dmd.Identifier;
+import dmd.TY;
+import dmd.IntegerExp;
+import dmd.Global;
+
+// Allow implicit conversion of T[] to T*
+bool IMPLICIT_ARRAY_TO_PTR()
+{
+	return global.params.useDeprecated;
+}
+
+class TypeArray : TypeNext
+{
+    this(TY ty, Type next)
+	{
+		super(ty, next);
+	}
+
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+		Type n = this.next.toBasetype();		// uncover any typedef's
+
+	version (LOGDOTEXP) {
+		printf("TypeArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+	}
+		if (ident == Id.reverse && (n.ty == Tchar || n.ty == Twchar))
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+			string nm;
+			static string name[2] = [ "_adReverseChar", "_adReverseWchar" ];
+
+			nm = name[n.ty == Twchar];
+			fd = FuncDeclaration.genCfunc(Type.tindex, nm);
+			ec = new VarExp(Loc(0), fd);
+			e = e.castTo(sc, n.arrayOf());	// convert to dynamic array
+			arguments = new Expressions();
+			arguments.push(cast(void*)e);
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = next.arrayOf();
+		}
+		else if (ident == Id.sort && (n.ty == Tchar || n.ty == Twchar))
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+			string nm;
+			static string name2[2] = [ "_adSortChar", "_adSortWchar" ];
+
+			nm = name2[n.ty == Twchar];
+			fd = FuncDeclaration.genCfunc(Type.tindex, nm);
+			ec = new VarExp(Loc(0), fd);
+			e = e.castTo(sc, n.arrayOf());	// convert to dynamic array
+			arguments = new Expressions();
+			arguments.push(cast(void*)e);
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = next.arrayOf();
+		}
+		else if (ident == Id.reverse || ident == Id.dup || ident == Id.idup)
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+			int size = cast(int)next.size(e.loc);
+			int dup;
+
+			assert(size);
+			dup = (ident == Id.dup || ident == Id.idup);
+			fd = FuncDeclaration.genCfunc(Type.tindex, dup ? Id.adDup : Id.adReverse);
+			ec = new VarExp(Loc(0), fd);
+			e = e.castTo(sc, n.arrayOf());	// convert to dynamic array
+			arguments = new Expressions();
+			if (dup)
+				arguments.push(cast(void*)getTypeInfo(sc));
+			arguments.push(cast(void*)e);
+			if (!dup)
+				arguments.push(cast(void*)new IntegerExp(Loc(0), size, Type.tsize_t));
+			e = new CallExp(e.loc, ec, arguments);
+			if (ident == Id.idup)
+			{   
+				Type einv = next.invariantOf();
+				if (next.implicitConvTo(einv) < MATCHconst)
+					error(e.loc, "cannot implicitly convert element type %s to immutable", next.toChars());
+				e.type = einv.arrayOf();
+			}
+			else
+				e.type = next.mutableOf().arrayOf();
+		}
+		else if (ident == Id.sort)
+		{
+			Expression ec;
+			FuncDeclaration fd;
+			Expressions arguments;
+
+			fd = FuncDeclaration.genCfunc(tint32.arrayOf(), "_adSort");
+			ec = new VarExp(Loc(0), fd);
+			e = e.castTo(sc, n.arrayOf());	// convert to dynamic array
+			arguments = new Expressions();
+			arguments.push(cast(void*)e);
+			arguments.push(n.ty == Tsarray
+					? cast(void*)n.getTypeInfo(sc)	// don't convert to dynamic array
+					: cast(void*)n.getInternalTypeInfo(sc));
+			e = new CallExp(e.loc, ec, arguments);
+			e.type = next.arrayOf();
+		}
+		else
+		{
+			e = Type.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeBasic.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,779 @@
+module dmd.TypeBasic;
+
+import dmd.Type;
+import dmd.Id;
+import dmd.MOD;
+import dmd.TOK;
+import dmd.Token;
+import dmd.TFLAGS;
+import dmd.TY;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.IntegerExp;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.CppMangleState;
+import dmd.MATCH;
+import dmd.RealExp;
+import dmd.ComplexExp;
+import dmd.Util;
+import dmd.Port;
+import dmd.Complex;
+
+class TypeBasic : Type
+{
+    string dstring;
+    uint flags;
+
+    this(TY ty)
+	{
+		super(ty);
+
+		enum TFLAGSintegral	= 1;
+		enum TFLAGSfloating = 2;
+		enum TFLAGSunsigned = 4;
+		enum TFLAGSreal = 8;
+		enum TFLAGSimaginary = 0x10;
+		enum TFLAGScomplex = 0x20;
+
+		string d;
+
+		uint flags = 0;
+		switch (ty)
+		{
+		case TY.Tvoid:	d = Token.toChars(TOK.TOKvoid);
+				break;
+
+		case TY.Tint8:	d = Token.toChars(TOK.TOKint8);
+				flags |= TFLAGSintegral;
+				break;
+
+		case TY.Tuns8:	d = Token.toChars(TOK.TOKuns8);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Tint16:	d = Token.toChars(TOK.TOKint16);
+				flags |= TFLAGSintegral;
+				break;
+
+		case TY.Tuns16:	d = Token.toChars(TOK.TOKuns16);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Tint32:	d = Token.toChars(TOK.TOKint32);
+				flags |= TFLAGSintegral;
+				break;
+
+		case TY.Tuns32:	d = Token.toChars(TOK.TOKuns32);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Tfloat32:	d = Token.toChars(TOK.TOKfloat32);
+				flags |= TFLAGSfloating | TFLAGSreal;
+				break;
+
+		case TY.Tint64:	d = Token.toChars(TOK.TOKint64);
+				flags |= TFLAGSintegral;
+				break;
+
+		case TY.Tuns64:	d = Token.toChars(TOK.TOKuns64);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Tfloat64:	d = Token.toChars(TOK.TOKfloat64);
+				flags |= TFLAGSfloating | TFLAGSreal;
+				break;
+
+		case TY.Tfloat80:	d = Token.toChars(TOK.TOKfloat80);
+				flags |= TFLAGSfloating | TFLAGSreal;
+				break;
+
+		case TY.Timaginary32: d = Token.toChars(TOK.TOKimaginary32);
+				flags |= TFLAGSfloating | TFLAGSimaginary;
+				break;
+
+		case TY.Timaginary64: d = Token.toChars(TOK.TOKimaginary64);
+				flags |= TFLAGSfloating | TFLAGSimaginary;
+				break;
+
+		case TY.Timaginary80: d = Token.toChars(TOK.TOKimaginary80);
+				flags |= TFLAGSfloating | TFLAGSimaginary;
+				break;
+
+		case TY.Tcomplex32: d = Token.toChars(TOK.TOKcomplex32);
+				flags |= TFLAGSfloating | TFLAGScomplex;
+				break;
+
+		case TY.Tcomplex64: d = Token.toChars(TOK.TOKcomplex64);
+				flags |= TFLAGSfloating | TFLAGScomplex;
+				break;
+
+		case TY.Tcomplex80: d = Token.toChars(TOK.TOKcomplex80);
+				flags |= TFLAGSfloating | TFLAGScomplex;
+				break;
+
+		case TY.Tbool:	d = "bool";
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Tascii:	d = Token.toChars(TOK.TOKchar);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Twchar:	d = Token.toChars(TOK.TOKwchar);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+
+		case TY.Tdchar:	d = Token.toChars(TOK.TOKdchar);
+				flags |= TFLAGSintegral | TFLAGSunsigned;
+				break;
+		}
+
+		this.dstring = d;
+		this.flags = flags;
+		merge();
+	}
+
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Type syntaxCopy()
+	{
+		// No semantic analysis done on basic types, no need to copy
+		return this;
+	}
+	
+    ulong size(Loc loc)
+	{
+		uint size;
+
+		//printf("TypeBasic.size()\n");
+		switch (ty)
+		{
+			case TY.Tint8:
+			case TY.Tuns8:	size = 1;	break;
+			case TY.Tint16:
+			case TY.Tuns16:	size = 2;	break;
+			case TY.Tint32:
+			case TY.Tuns32:
+			case TY.Tfloat32:
+			case TY.Timaginary32:
+					size = 4;	break;
+			case TY.Tint64:
+			case TY.Tuns64:
+			case TY.Tfloat64:
+			case TY.Timaginary64:
+					size = 8;	break;
+			case TY.Tfloat80:
+			case TY.Timaginary80:
+					size = REALSIZE;	break;
+			case TY.Tcomplex32:
+					size = 8;		break;
+			case TY.Tcomplex64:
+					size = 16;		break;
+			case TY.Tcomplex80:
+					size = REALSIZE * 2;	break;
+
+			case TY.Tvoid:
+				//size = Type.size();	// error message
+				size = 1;
+				break;
+
+			case TY.Tbool:	size = 1;		break;
+			case TY.Tascii:	size = 1;		break;
+			case TY.Twchar:	size = 2;		break;
+			case TY.Tdchar:	size = 4;		break;
+
+			default:
+				assert(0);
+				break;
+		}
+
+		//printf("TypeBasic.size() = %d\n", size);
+		return size;
+	}
+	
+    uint alignsize()
+	{
+		uint sz;
+
+		switch (ty)
+		{
+		case TY.Tfloat80:
+		case TY.Timaginary80:
+		case TY.Tcomplex80:
+			sz = REALALIGNSIZE;
+			break;
+
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+		case TY.Tint64:
+		case TY.Tuns64:
+		case TY.Tfloat64:
+		case TY.Timaginary64:
+		case TY.Tcomplex32:
+		case TY.Tcomplex64:
+			sz = 4;
+			break;
+}
+
+		default:
+			sz = cast(uint)size(Loc(0));	///
+			break;
+		}
+
+		return sz;
+	}
+	
+    Expression getProperty(Loc loc, Identifier ident)
+	{
+		Expression e;
+		long ivalue;
+		real fvalue;
+
+		//printf("TypeBasic.getProperty('%s')\n", ident.toChars());
+		if (ident is Id.max)
+		{
+			switch (ty)
+			{
+				case TY.Tint8:	ivalue = byte.max;		goto Livalue;
+				case TY.Tuns8:	ivalue = ubyte.max;		goto Livalue;
+				case TY.Tint16:	ivalue = short.max;		goto Livalue;
+				case TY.Tuns16:	ivalue = ushort.max;	goto Livalue;
+				case TY.Tint32:	ivalue = int.max;		goto Livalue;
+				case TY.Tuns32:	ivalue = uint.max;		goto Livalue;
+				case TY.Tint64:	ivalue = long.max;		goto Livalue;
+				case TY.Tuns64:	ivalue = ulong.max;		goto Livalue;
+				case TY.Tbool:	ivalue = bool.max;		goto Livalue;
+				case TY.Tchar:	ivalue = char.max;		goto Livalue;
+				case TY.Twchar:	ivalue = wchar.max;		goto Livalue;
+				case TY.Tdchar:	ivalue = 0x10FFFF;		goto Livalue;
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	fvalue = float.max;	goto Lfvalue;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	fvalue = double.max;goto Lfvalue;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	fvalue = real.max;	goto Lfvalue;
+			}
+		}
+		else if (ident is Id.min)
+		{
+			switch (ty)
+			{
+				case TY.Tint8:		ivalue = byte.min;		goto Livalue;
+				case TY.Tuns8:		ivalue = ubyte.min;		goto Livalue;
+				case TY.Tint16:		ivalue = short.min;		goto Livalue;
+				case TY.Tuns16:		ivalue = ushort.min;	goto Livalue;
+				case TY.Tint32:		ivalue = int.min;		goto Livalue;
+				case TY.Tuns32:		ivalue = uint.min;		goto Livalue;
+				case TY.Tint64:		ivalue = long.min;		goto Livalue;
+				case TY.Tuns64:		ivalue = ulong.min;		goto Livalue;
+				case TY.Tbool:		ivalue = bool.min;		goto Livalue;
+				case TY.Tchar:		ivalue = char.min;		goto Livalue;
+				case TY.Twchar:		ivalue = wchar.min;		goto Livalue;
+				case TY.Tdchar:		ivalue = dchar.min;		goto Livalue;
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	fvalue = float.min;		goto Lfvalue;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	fvalue = double.min;		goto Lfvalue;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	fvalue = real.min;		goto Lfvalue;
+			}
+		}
+		else if (ident is Id.nan)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Tcomplex64:
+				case TY.Tcomplex80:
+				case TY.Timaginary32:
+				case TY.Timaginary64:
+				case TY.Timaginary80:
+				case TY.Tfloat32:
+				case TY.Tfloat64:
+				case TY.Tfloat80:
+				{
+					fvalue = real.nan;
+					goto Lfvalue;
+				}
+			}
+		}
+		else if (ident is Id.infinity)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Tcomplex64:
+				case TY.Tcomplex80:
+				case TY.Timaginary32:
+				case TY.Timaginary64:
+				case TY.Timaginary80:
+				case TY.Tfloat32:
+				case TY.Tfloat64:
+				case TY.Tfloat80:
+					fvalue = real.infinity;
+					goto Lfvalue;
+			}
+		}
+		else if (ident is Id.dig)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	ivalue = float.dig;	goto Lint;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	ivalue = double.dig;	goto Lint;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	ivalue = real.dig;	goto Lint;
+			}
+		}
+		else if (ident is Id.epsilon)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	fvalue = float.epsilon;	goto Lfvalue;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	fvalue = double.epsilon;	goto Lfvalue;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	fvalue = real.epsilon;	goto Lfvalue;
+			}
+		}
+		else if (ident is Id.mant_dig)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	ivalue = float.mant_dig;	goto Lint;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	ivalue = double.mant_dig;	goto Lint;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	ivalue = real.mant_dig; goto Lint;
+			}
+		}
+		else if (ident is Id.max_10_exp)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	ivalue = float.max_10_exp;	goto Lint;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	ivalue = double.max_10_exp;	goto Lint;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	ivalue = real.max_10_exp;	goto Lint;
+			}
+		}
+		else if (ident is Id.max_exp)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	ivalue = float.max_exp;	goto Lint;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	ivalue = double.max_exp;	goto Lint;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	ivalue = real.max_exp;	goto Lint;
+			}
+		}
+		else if (ident is Id.min_10_exp)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	ivalue = float.min_10_exp;	goto Lint;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	ivalue = double.min_10_exp;	goto Lint;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	ivalue = real.min_10_exp;	goto Lint;
+			}
+		}
+		else if (ident is Id.min_exp)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:
+				case TY.Timaginary32:
+				case TY.Tfloat32:	ivalue = float.min_exp;	goto Lint;
+				case TY.Tcomplex64:
+				case TY.Timaginary64:
+				case TY.Tfloat64:	ivalue = double.min_exp;	goto Lint;
+				case TY.Tcomplex80:
+				case TY.Timaginary80:
+				case TY.Tfloat80:	ivalue = real.min_exp;	goto Lint;
+			}
+		}
+
+	Ldefault:
+		return Type.getProperty(loc, ident);
+
+	Livalue:
+		e = new IntegerExp(loc, ivalue, this);
+		return e;
+
+	Lfvalue:
+		if (isreal() || isimaginary())
+			e = new RealExp(loc, fvalue, this);
+		else
+		{
+			Complex!(real) cvalue;
+			cvalue.re = fvalue;
+			cvalue.im = fvalue;
+
+			//for (int i = 0; i < 20; i++)
+			//    printf("%02x ", ((unsigned char *)&cvalue)[i]);
+			//printf("\n");
+			e = new ComplexExp(loc, cvalue, this);
+		}
+		return e;
+
+	Lint:
+		e = new IntegerExp(loc, ivalue, Type.tint32);
+		return e;
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+version (LOGDOTEXP) {
+		printf("TypeBasic.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+}
+		Type t;
+
+		if (ident is Id.re)
+		{
+			switch (ty)
+			{
+				case TY.Tcomplex32:	t = tfloat32;		goto L1;
+				case TY.Tcomplex64:	t = tfloat64;		goto L1;
+				case TY.Tcomplex80:	t = tfloat80;		goto L1;
+				L1:
+					e = e.castTo(sc, t);
+					break;
+
+				case TY.Tfloat32:
+				case TY.Tfloat64:
+				case TY.Tfloat80:
+					break;
+
+				case TY.Timaginary32:	t = tfloat32;		goto L2;
+				case TY.Timaginary64:	t = tfloat64;		goto L2;
+				case TY.Timaginary80:	t = tfloat80;		goto L2;
+				L2:
+					e = new RealExp(Loc(0), 0.0, t);
+					break;
+
+				default:
+					return Type.getProperty(e.loc, ident);
+			}
+		}
+		else if (ident is Id.im)
+		{	
+			Type t2;
+
+			switch (ty)
+			{
+				case TY.Tcomplex32:	t = timaginary32;	t2 = tfloat32;	goto L3;
+				case TY.Tcomplex64:	t = timaginary64;	t2 = tfloat64;	goto L3;
+				case TY.Tcomplex80:	t = timaginary80;	t2 = tfloat80;	goto L3;
+				L3:
+					e = e.castTo(sc, t);
+					e.type = t2;
+					break;
+
+				case TY.Timaginary32:	t = tfloat32;	goto L4;
+				case TY.Timaginary64:	t = tfloat64;	goto L4;
+				case TY.Timaginary80:	t = tfloat80;	goto L4;
+				L4:
+					e = e.copy();
+					e.type = t;
+					break;
+
+				case TY.Tfloat32:
+				case TY.Tfloat64:
+				case TY.Tfloat80:
+					e = new RealExp(Loc(0), 0.0, this);
+					break;
+
+				default:
+					return Type.getProperty(e.loc, ident);
+			}
+		}
+		else
+		{
+			return Type.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+    string toChars()
+	{
+		return Type.toChars();
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		//printf("TypeBasic.toCBuffer2(mod = %d, this.mod = %d)\n", mod, this.mod);
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		buf.writestring(dstring);
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+    bool isintegral()
+	{
+		//printf("TypeBasic.isintegral('%s') x%x\n", toChars(), flags);
+		return (flags & TFLAGS.TFLAGSintegral) != 0;
+	}
+	
+    bool isbit()
+	{
+		assert(false);
+	}
+	
+    bool isfloating()
+	{
+		return (flags & TFLAGS.TFLAGSfloating) != 0;
+	}
+	
+    bool isreal()
+	{
+		return (flags & TFLAGS.TFLAGSreal) != 0;
+	}
+	
+    bool isimaginary()
+	{
+		return (flags & TFLAGS.TFLAGSimaginary) != 0;
+	}
+	
+    bool iscomplex()
+	{
+		return (flags & TFLAGS.TFLAGScomplex) != 0;
+	}
+
+    bool isscalar()
+	{
+		return (flags & (TFLAGS.TFLAGSintegral | TFLAGS.TFLAGSfloating)) != 0;
+	}
+	
+    bool isunsigned()
+	{
+		return (flags & TFLAGS.TFLAGSunsigned) != 0;
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("TypeBasic.implicitConvTo(%s) from %s\n", to.toChars(), toChars());
+		if (this is to)
+			return MATCH.MATCHexact;
+
+version (DMDV2) {
+		if (ty is to.ty)
+		{
+			return (mod == to.mod) ? MATCH.MATCHexact : MATCH.MATCHconst;
+		}
+}
+
+		if (ty == TY.Tvoid || to.ty == TY.Tvoid)
+			return MATCH.MATCHnomatch;
+		if (to.ty == TY.Tbool)
+			return MATCH.MATCHnomatch;
+		if (!to.isTypeBasic())
+			return MATCH.MATCHnomatch;
+
+		TypeBasic tob = cast(TypeBasic)to;
+		if (flags & TFLAGS.TFLAGSintegral)
+		{
+		// Disallow implicit conversion of integers to imaginary or complex
+		if (tob.flags & (TFLAGS.TFLAGSimaginary | TFLAGS.TFLAGScomplex))
+			return MATCH.MATCHnomatch;
+
+version (DMDV2) {
+		// If converting from integral to integral
+		if (1 && tob.flags & TFLAGS.TFLAGSintegral)
+		{   ulong sz = size(Loc(0));
+			ulong tosz = tob.size(Loc(0));
+
+			/* Can't convert to smaller size
+			 */
+			if (sz > tosz)
+			return MATCH.MATCHnomatch;
+
+			/* Can't change sign if same size
+			 */
+			/*if (sz == tosz && (flags ^ tob.flags) & TFLAGSunsigned)
+			return MATCH.MATCHnomatch;*/
+		}
+}
+		}
+		else if (flags & TFLAGS.TFLAGSfloating)
+		{
+		// Disallow implicit conversion of floating point to integer
+		if (tob.flags & TFLAGS.TFLAGSintegral)
+			return MATCH.MATCHnomatch;
+
+		assert(tob.flags & TFLAGS.TFLAGSfloating);
+
+		// Disallow implicit conversion from complex to non-complex
+		if (flags & TFLAGS.TFLAGScomplex && !(tob.flags & TFLAGS.TFLAGScomplex))
+			return MATCH.MATCHnomatch;
+
+		// Disallow implicit conversion of real or imaginary to complex
+		if (flags & (TFLAGS.TFLAGSreal | TFLAGS.TFLAGSimaginary) &&
+			tob.flags & TFLAGS.TFLAGScomplex)
+			return MATCH.MATCHnomatch;
+
+		// Disallow implicit conversion to-from real and imaginary
+		if ((flags & (TFLAGS.TFLAGSreal | TFLAGS.TFLAGSimaginary)) !=
+			(tob.flags & (TFLAGS.TFLAGSreal | TFLAGS.TFLAGSimaginary)))
+			return MATCH.MATCHnomatch;
+		}
+		return MATCH.MATCHconvert;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+		long value = 0;
+
+version (SNAN_DEFAULT_INIT) {
+		/*
+		 * Use a payload which is different from the machine NaN,
+		 * so that uninitialised variables can be
+		 * detected even if exceptions are disabled.
+		 */
+		ushort[8] snan = [ 0, 0, 0, 0xA000, 0x7FFF, 0, 0, 0 ];
+		/*
+		 * Although long doubles are 10 bytes long, some
+		 * C ABIs pad them out to 12 or even 16 bytes, so
+		 * leave enough space in the snan array.
+		 */
+		assert(REALSIZE <= snan.sizeof);
+		real fvalue = *cast(real*)snan.ptr;
+}
+
+	version (LOGDEFAULTINIT) {
+		printf("TypeBasic.defaultInit() '%s'\n", toChars());
+	}
+		switch (ty)
+		{
+			case TY.Tchar:
+				value = 0xFF;
+				break;
+
+			case TY.Twchar:
+			case TY.Tdchar:
+				value = 0xFFFF;
+				break;
+
+			case TY.Timaginary32:
+			case TY.Timaginary64:
+			case TY.Timaginary80:
+			case TY.Tfloat32:
+			case TY.Tfloat64:
+			case TY.Tfloat80:
+	version (SNAN_DEFAULT_INIT) {
+				return new RealExp(loc, fvalue, this);
+	} else {
+				return getProperty(loc, Id.nan);
+	}
+
+			case TY.Tcomplex32:
+			case TY.Tcomplex64:
+			case TY.Tcomplex80:
+	version (SNAN_DEFAULT_INIT) {
+			{   
+				// Can't use fvalue + I*fvalue (the im part becomes a quiet NaN).
+				Complex!(real) cvalue;
+				cvalue.re = fvalue;
+				cvalue.im = fvalue;
+
+				return new ComplexExp(loc, cvalue, this);
+			}
+	} else {
+				return getProperty(loc, Id.nan);
+	}
+
+			case TY.Tvoid:
+				error(loc, "void does not have a default initializer");
+
+			default:
+				break;		///
+		}
+		return new IntegerExp(loc, value, this);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		switch (ty)
+		{
+			case TY.Tchar:
+			case TY.Twchar:
+			case TY.Tdchar:
+			case TY.Timaginary32:
+			case TY.Timaginary64:
+			case TY.Timaginary80:
+			case TY.Tfloat32:
+			case TY.Tfloat64:
+			case TY.Tfloat80:
+			case TY.Tcomplex32:
+			case TY.Tcomplex64:
+			case TY.Tcomplex80:
+				return false;		// no
+			default:
+				break;
+		}
+
+		return true;			// yes
+	}
+	
+    bool builtinTypeInfo()
+	{
+	version (DMDV2) {
+		return mod ? false : true;
+	} else {
+		return true;
+	}
+	}
+	
+    // For eliminating dynamic_cast
+    TypeBasic isTypeBasic()
+	{
+		return this;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeClass.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,637 @@
+module dmd.TypeClass;
+
+import dmd.Type;
+import dmd.ClassDeclaration;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.CppMangleState;
+import dmd.ArrayTypes;
+import dmd.TypeInfoDeclaration;
+import dmd.TY;
+import dmd.MOD;
+import dmd.Global;
+import dmd.TypePointer;
+import dmd.Declaration;
+import dmd.VarDeclaration;
+import dmd.TOK;
+import dmd.DotExp;
+import dmd.Id;
+import dmd.ScopeExp;
+import dmd.DotVarExp;
+import dmd.VarExp;
+import dmd.PtrExp;
+import dmd.AddExp;
+import dmd.IntegerExp;
+import dmd.DotIdExp;
+import dmd.EnumMember;
+import dmd.TemplateMixin;
+import dmd.TemplateDeclaration;
+import dmd.TemplateInstance;
+import dmd.OverloadSet;
+import dmd.DotTypeExp;
+import dmd.TupleExp;
+import dmd.ClassInfoDeclaration;
+import dmd.TypeInfoInterfaceDeclaration;
+import dmd.TypeInfoClassDeclaration;
+import dmd.Util;
+import dmd.NullExp;
+import dmd.TypeExp;
+import dmd.DotTemplateExp;
+import dmd.ErrorExp;
+import dmd.ThisExp;
+import dmd.CommaExp;
+
+import dmd.expression.Util;
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.SC;
+import dmd.backend.STR;
+import dmd.backend.TYM;
+import dmd.backend.LIST;
+import dmd.backend.Classsym;
+
+import std.string : toStringz;
+
+class TypeClass : Type
+{
+    ClassDeclaration sym;
+
+    this(ClassDeclaration sym)
+	{
+		super(TY.Tclass);
+		this.sym = sym;
+	}
+
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    ulong size(Loc loc)
+	{
+		return PTRSIZE;
+	}
+	
+    string toChars()
+	{
+		if (mod)
+			return Type.toChars();
+		return sym.toPrettyChars();
+	}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeClass.semantic(%s)\n", sym.toChars());
+		if (deco)
+			return this;
+		//printf("\t%s\n", merge().deco);
+		return merge();
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		return sym;
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		string name = sym.mangle();
+		//printf("TypeClass.toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name);
+		Type.toDecoBuffer(buf, flag);
+		buf.printf("%s", name);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		buf.writestring(sym.toChars());
+	}
+
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+		uint offset;
+
+		Expression b;
+		VarDeclaration v;
+		Dsymbol s;
+
+version (LOGDOTEXP) {
+		printf("TypeClass.dotExp(e='%s', ident='%s')\n", e.toChars(), ident.toChars());
+}
+
+		if (e.op == TOK.TOKdotexp)
+		{
+			DotExp de = cast(DotExp)e;
+
+			if (de.e1.op == TOK.TOKimport)
+			{
+				ScopeExp se = cast(ScopeExp)de.e1;
+
+				s = se.sds.search(e.loc, ident, 0);
+				e = de.e1;
+				goto L1;
+			}
+		}
+
+		if (ident is Id.tupleof_)
+		{
+			/* Create a TupleExp
+			 */
+			e = e.semantic(sc);	// do this before turning on noaccesscheck
+			Expressions exps = new Expressions;
+			exps.reserve(sym.fields.dim);
+			for (size_t i = 0; i < sym.fields.dim; i++)
+			{   
+				VarDeclaration v2 = cast(VarDeclaration)sym.fields.data[i];
+				Expression fe = new DotVarExp(e.loc, e, v2);
+				exps.push(cast(void*)fe);
+			}
+			e = new TupleExp(e.loc, exps);
+			sc = sc.push();
+			sc.noaccesscheck = 1;
+			e = e.semantic(sc);
+			sc.pop();
+			return e;
+		}
+
+		s = sym.search(e.loc, ident, 0);
+	L1:
+		if (!s)
+		{
+			// See if it's a base class
+			ClassDeclaration cbase;
+			for (cbase = sym.baseClass; cbase; cbase = cbase.baseClass)
+			{
+				if (cbase.ident.equals(ident))
+				{
+					e = new DotTypeExp(Loc(0), e, cbase);
+					return e;
+				}
+			}
+
+			if (ident is Id.classinfo_)
+			{
+				assert(ClassDeclaration.classinfo);
+				Type t = ClassDeclaration.classinfo.type;
+				if (e.op == TOK.TOKtype || e.op == TOK.TOKdottype)
+				{
+					/* For type.classinfo, we know the classinfo
+					 * at compile time.
+					 */
+					if (!sym.vclassinfo)
+						sym.vclassinfo = new ClassInfoDeclaration(sym);
+
+					e = new VarExp(e.loc, sym.vclassinfo);
+					e = e.addressOf(sc);
+					e.type = t;	// do this so we don't get redundant dereference
+				}
+				else
+				{	
+					/* For class objects, the classinfo reference is the first
+					 * entry in the vtbl[]
+					 */
+					e = new PtrExp(e.loc, e);
+					e.type = t.pointerTo();
+					if (sym.isInterfaceDeclaration())
+					{
+						if (sym.isCPPinterface())
+						{	
+							/* C++ interface vtbl[]s are different in that the
+							 * first entry is always pointer to the first virtual
+							 * function, not classinfo.
+							 * We can't get a .classinfo for it.
+							 */
+							error(e.loc, "no .classinfo for C++ interface objects");
+						}
+						/* For an interface, the first entry in the vtbl[]
+						 * is actually a pointer to an instance of struct Interface.
+						 * The first member of Interface is the .classinfo,
+						 * so add an extra pointer indirection.
+						 */
+						e.type = e.type.pointerTo();
+						e = new PtrExp(e.loc, e);
+						e.type = t.pointerTo();
+					}
+					e = new PtrExp(e.loc, e, t);
+				}
+				return e;
+			}
+
+			if (ident is Id.__vptr)
+			{   
+				/* The pointer to the vtbl[]
+				 * *cast(invariant(void*)**)e
+				 */
+				e = e.castTo(sc, tvoidptr.invariantOf().pointerTo().pointerTo());
+				e = new PtrExp(e.loc, e);
+				e = e.semantic(sc);
+				return e;
+			}
+
+			if (ident is Id.__monitor)
+			{   /* The handle to the monitor (call it a void*)
+				 * *(cast(void**)e + 1)
+				 */
+				e = e.castTo(sc, tvoidptr.pointerTo());
+				e = new AddExp(e.loc, e, new IntegerExp(1));
+				e = new PtrExp(e.loc, e);
+				e = e.semantic(sc);
+				return e;
+			}
+
+			if (ident is Id.typeinfo_)
+			{
+				if (!global.params.useDeprecated)
+					error(e.loc, ".typeinfo deprecated, use typeid(type)");
+
+				return getTypeInfo(sc);
+			}
+			if (ident is Id.outer && sym.vthis)
+			{
+				s = sym.vthis;
+			}
+			else
+			{
+				if (ident !is Id.__sizeof	 &&
+					ident !is Id.alignof_ &&
+					ident !is Id.init_ &&
+					ident !is Id.mangleof_ &&
+					ident !is Id.stringof_ &&
+					ident !is Id.offsetof)
+				{
+					/* See if we should forward to the alias this.
+					 */
+					if (sym.aliasthis)
+					{   
+						/* Rewrite e.ident as:
+						 *	e.aliasthis.ident
+						 */
+						e = new DotIdExp(e.loc, e, sym.aliasthis.ident);
+						e = new DotIdExp(e.loc, e, ident);
+						return e.semantic(sc);
+					}
+
+					/* Look for overloaded opDot() to see if we should forward request
+					 * to it.
+					 */
+					Dsymbol fd = search_function(sym, Id.opDot);
+					if (fd)
+					{   
+						/* Rewrite e.ident as:
+						 *	e.opId().ident
+						 */
+						e = build_overload(e.loc, sc, e, null, fd.ident);
+						e = new DotIdExp(e.loc, e, ident);
+						return e.semantic(sc);
+					}
+				}
+
+				return Type.dotExp(sc, e, ident);
+			}
+		}
+
+		if (!s.isFuncDeclaration())	// because of overloading
+			s.checkDeprecated(e.loc, sc);
+		
+		s = s.toAlias();
+		v = s.isVarDeclaration();
+		
+		if (v && !v.isDataseg())
+		{	
+			Expression ei = v.getConstInitializer();
+
+			if (ei)
+			{   
+				e = ei.copy();	// need to copy it if it's a StringExp
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+
+		if (s.getType())
+		{
+		//	if (e.op == TOKtype)
+				return new TypeExp(e.loc, s.getType());
+		//	return new DotTypeExp(e.loc, e, s);
+		}
+
+		EnumMember em = s.isEnumMember();
+		if (em)
+		{
+			assert(em.value);
+			return em.value.copy();
+		}
+
+		TemplateMixin tm = s.isTemplateMixin();
+		if (tm)
+		{
+			Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm));
+			de.type = e.type;
+			return de;
+		}
+
+		TemplateDeclaration td = s.isTemplateDeclaration();
+		if (td)
+		{
+			e = new DotTemplateExp(e.loc, e, td);
+			e.semantic(sc);
+			return e;
+		}
+
+		TemplateInstance ti = s.isTemplateInstance();
+		if (ti)
+		{	
+			if (!ti.semanticRun)
+				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;
+		}
+
+		OverloadSet o = s.isOverloadSet();
+		if (o)
+		{	
+			/* We really should allow this
+			 */
+			error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars());
+			return new ErrorExp();
+		}
+
+		Declaration d = s.isDeclaration();
+		if (!d)
+		{
+			e.error("%s.%s is not a declaration", e.toChars(), ident.toChars());
+			return new ErrorExp();
+		}
+
+		if (e.op == TOK.TOKtype)
+		{
+			/* It's:
+			 *    Class.d
+			 */
+			if (d.isTupleDeclaration())
+			{
+				e = new TupleExp(e.loc, d.isTupleDeclaration());
+				e = e.semantic(sc);
+				return e;
+			}
+			else if (d.needThis() && (hasThis(sc) || !d.isFuncDeclaration()))
+			{
+				if (sc.func)
+				{
+					ClassDeclaration thiscd;
+					thiscd = sc.func.toParent().isClassDeclaration();
+
+					if (thiscd)
+					{
+						ClassDeclaration cd = e.type.isClassHandle();
+
+						if (cd is thiscd)
+						{
+							e = new ThisExp(e.loc);
+							e = new DotTypeExp(e.loc, e, cd);
+							DotVarExp de = new DotVarExp(e.loc, e, d);
+							e = de.semantic(sc);
+							return e;
+						}
+						else if ((!cd || !cd.isBaseOf(thiscd, null)) && !d.isFuncDeclaration())
+							e.error("'this' is required, but %s is not a base class of %s", e.type.toChars(), thiscd.toChars());
+					}
+				}
+
+				/* Rewrite as:
+				 *	this.d
+				 */
+				DotVarExp de = new DotVarExp(e.loc, new ThisExp(e.loc), d);
+				e = de.semantic(sc);
+				return e;
+			}
+			else
+			{
+				VarExp ve = new VarExp(e.loc, d, 1);
+				return ve;
+			}
+		}
+
+		if (d.isDataseg())
+		{
+			// (e, d)
+			accessCheck(e.loc, sc, e, d);
+			VarExp ve = new VarExp(e.loc, d);
+			e = new CommaExp(e.loc, e, ve);
+			e.type = d.type;
+			return e;
+		}
+
+		if (d.parent && d.toParent().isModule())
+		{
+			// (e, d)
+			VarExp ve = new VarExp(e.loc, d, 1);
+			e = new CommaExp(e.loc, e, ve);
+			e.type = d.type;
+			return e;
+		}
+
+		DotVarExp de = new DotVarExp(e.loc, e, d);
+		return de.semantic(sc);
+	}
+	
+    ClassDeclaration isClassHandle()
+	{
+		return sym;
+	}
+	
+    bool isBaseOf(Type t, int* poffset)
+	{
+		assert(false);
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("TypeClass.implicitConvTo(to = '%s') %s\n", to.toChars(), toChars());
+		MATCH m = constConv(to);
+		if (m != MATCH.MATCHnomatch)
+			return m;
+
+		ClassDeclaration cdto = to.isClassHandle();
+		if (cdto && cdto.isBaseOf(sym, null))
+		{	
+			//printf("'to' is base\n");
+			return MATCH.MATCHconvert;
+		}
+
+		if (global.params.Dversion == 1)
+		{
+			// Allow conversion to (void *)
+			if (to.ty == TY.Tpointer && (cast(TypePointer)to).next.ty == TY.Tvoid)
+				return MATCH.MATCHconvert;
+		}
+
+		m = MATCH.MATCHnomatch;
+		if (sym.aliasthis)
+		{
+			Declaration d = sym.aliasthis.isDeclaration();
+			if (d)
+			{   
+				assert(d.type);
+				Type t = d.type.addMod(mod);
+				m = t.implicitConvTo(to);
+			}
+		}
+
+		return m;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+version (LOGDEFAULTINIT) {
+		printf("TypeClass::defaultInit() '%s'\n", toChars());
+}
+		Expression e = new NullExp(loc);
+		e.type = this;
+		return e;
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return true;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    bool isauto()
+	{
+		return sym.isauto;
+	}
+	
+    bool checkBoolean()
+	{
+		return true;
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		if (sym.isInterfaceDeclaration())
+			return new TypeInfoInterfaceDeclaration(this);
+		else
+			return new TypeInfoClassDeclaration(this);
+	}
+	
+    bool hasPointers()
+	{
+		return true;
+	}
+	
+    bool builtinTypeInfo()
+	{
+		/* This is statically put out with the ClassInfo, so
+		 * claim it is built in so it isn't regenerated by each module.
+		 */
+	version (DMDV2) {
+		return mod ? false : true;
+	} else {
+		return true;
+	}
+	}
+	
+version (DMDV2) {
+    Type toHeadMutable()
+	{
+		assert(false);
+	}
+	
+    MATCH constConv(Type to)
+	{
+		if (equals(to))
+			return MATCH.MATCHexact;
+
+		if (ty == to.ty && sym == (cast(TypeClass)to).sym && to.mod == MOD.MODconst)
+			return MATCH.MATCHconst;
+
+		return MATCH.MATCHnomatch;
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+}
+
+    type* toCtype()
+	{
+		type* t;
+		Symbol* s;
+
+		//printf("TypeClass.toCtype() %s\n", toChars());
+		if (ctype)
+			return ctype;
+
+		/* Need this symbol to do C++ name mangling
+		 */
+		string name = sym.isCPPinterface() ? sym.ident.toChars() : sym.toPrettyChars();
+		s = symbol_calloc(toStringz(name));
+		s.Sclass = SC.SCstruct;
+		s.Sstruct = struct_calloc();
+		s.Sstruct.Sflags |= STR.STRclass;
+		s.Sstruct.Salignsize = sym.alignsize;
+		s.Sstruct.Sstructalign = cast(ubyte)sym.structalign;
+		s.Sstruct.Sstructsize = sym.structsize;
+
+		t = type_alloc(TYM.TYstruct);
+		t.Ttag = cast(Classsym*)s;		// structure tag name
+		t.Tcount++;
+		s.Stype = t;
+		slist_add(s);
+
+		t = type_allocn(TYM.TYnptr, t);
+
+		t.Tcount++;
+		ctype = t;
+
+		/* Add in fields of the class
+		 * (after setting ctype to avoid infinite recursion)
+		 */
+		if (global.params.symdebug)
+			for (int i = 0; i < sym.fields.dim; i++)
+			{   
+				VarDeclaration v = cast(VarDeclaration)sym.fields.data[i];
+
+				Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype());
+				s2.Smemoff = v.offset;
+				list_append(&s.Sstruct.Sfldlst, s2);
+			}
+
+		return t;
+	}
+	
+    Symbol* toSymbol()
+	{
+		return sym.toSymbol();
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeDArray.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,339 @@
+module dmd.TypeDArray;
+
+import dmd.TypeArray;
+import dmd.MOD;
+import dmd.Id;
+import dmd.TOK;
+import dmd.StringExp;
+import dmd.IntegerExp;
+import dmd.ArrayLengthExp;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.ArrayTypes;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeInfoArrayDeclaration;
+import dmd.NullExp;
+import dmd.TY;
+import dmd.TypeStruct;
+import dmd.Util;
+import dmd.TypePointer;
+import dmd.Global;
+
+import dmd.backend.TYPE;
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.Util;
+import dmd.backend.SC;
+import dmd.backend.TYM;
+import dmd.backend.LIST;
+
+import core.stdc.stdlib;
+import core.stdc.stdio;
+
+// Dynamic array, no dimension
+class TypeDArray : TypeArray
+{
+    this(Type t)
+	{
+		super(TY.Tarray, t);
+		//printf("TypeDArray(t = %p)\n", t);
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Type syntaxCopy()
+	{
+		Type t = next.syntaxCopy();
+		if (t == next)
+			t = this;
+		else
+		{	
+			t = new TypeDArray(t);
+			t.mod = mod;
+		}
+		return t;
+	}
+	
+    ulong size(Loc loc)
+	{
+		//printf("TypeDArray.size()\n");
+		return PTRSIZE * 2;
+	}
+	
+    uint alignsize()
+	{
+		// A DArray consists of two ptr-sized values, so align it on pointer size
+		// boundary
+		return PTRSIZE;
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		Type tn = next;
+
+		tn = next.semantic(loc,sc);
+		Type tbn = tn.toBasetype();
+		switch (tbn.ty)
+		{
+			case TY.Tfunction:
+			case TY.Tnone:
+			case TY.Ttuple:
+				error(loc, "can't have array of %s", tbn.toChars());
+				tn = next = tint32;
+				break;
+			case TY.Tstruct:
+			{   
+				TypeStruct ts = cast(TypeStruct)tbn;
+				if (ts.sym.isnested)
+					error(loc, "cannot have array of inner structs %s", ts.toChars());
+				break;
+			}
+			
+			default:
+				break;	///
+		}
+		if (tn.isauto())
+			error(loc, "cannot have array of auto %s", tn.toChars());
+
+		next = tn;
+		transitive();
+		return merge();
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		Type.toDecoBuffer(buf, flag);
+		if (next)
+			next.toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		if (mod != this.mod)
+		{
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		next.toCBuffer2(buf, hgs, this.mod);
+		buf.writestring("[]");
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+version (LOGDOTEXP) {
+		printf("TypeDArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+}
+		if (ident is Id.length)
+		{
+			if (e.op == TOK.TOKstring)
+			{   
+				StringExp se = cast(StringExp)e;
+
+				return new IntegerExp(se.loc, se.len, Type.tindex);
+			}
+			e = new ArrayLengthExp(e.loc, e);
+			e.type = Type.tsize_t;
+			return e;
+		}
+		else if (ident is Id.ptr)
+		{
+			e = e.castTo(sc, next.pointerTo());
+			return e;
+		}
+		else
+		{
+			e = TypeArray.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+    int isString()
+	{
+		assert(false);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return true;
+	}
+	
+    bool checkBoolean()
+	{
+		return true;
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("TypeDArray.implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
+		if (equals(to))
+			return MATCHexact;
+
+		// Allow implicit conversion of array to pointer
+		if (IMPLICIT_ARRAY_TO_PTR && to.ty == Tpointer)
+		{
+			TypePointer tp = cast(TypePointer)to;
+
+			/* Allow conversion to void*
+			 */
+			if (tp.next.ty == Tvoid &&
+				(next.mod == tp.next.mod || tp.next.mod == MODconst))
+			{
+				return MATCHconvert;
+			}
+
+			return next.constConv(to);
+		}
+
+		if (to.ty == Tarray)
+		{	
+			int offset = 0;
+			TypeDArray ta = cast(TypeDArray)to;
+
+			if (!(next.mod == ta.next.mod || ta.next.mod == MODconst))
+				return MATCHnomatch;	// not const-compatible
+
+			/* Allow conversion to void[]
+			 */
+			if (next.ty != Tvoid && ta.next.ty == Tvoid)
+			{
+				return MATCHconvert;
+			}
+
+			MATCH m = next.constConv(ta.next);
+			if (m != MATCHnomatch)
+			{
+				if (m == MATCHexact && mod != to.mod)
+				m = MATCHconst;
+				return m;
+			}
+
+			/* Allow conversions of T[][] to const(T)[][]
+			 */
+			if (mod == ta.mod && next.ty == Tarray && ta.next.ty == Tarray)
+			{
+				m = next.implicitConvTo(ta.next);
+				if (m == MATCHconst)
+				return m;
+			}
+
+			/* Conversion of array of derived to array of base
+			 */
+			if (ta.next.isBaseOf(next, &offset) && offset == 0)
+				return MATCHconvert;
+		}
+		return Type.implicitConvTo(to);
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypeDArray.defaultInit() '%s'\n", toChars());
+	}
+		Expression e = new NullExp(loc);
+		e.type = this;
+		return e;
+	}
+	
+    bool builtinTypeInfo()
+	{
+	version (DMDV2) {
+		return !mod && (next.isTypeBasic() !is null && !next.mod ||
+			// strings are so common, make them builtin
+			next.ty == Tchar && next.mod == MODinvariant);
+	} else {
+		return next.isTypeBasic() !is null;
+	}
+	}
+version (DMDV2) {
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+	static if (false) {
+		printf("TypeDArray.deduceType()\n");
+		printf("\tthis   = %d, ", ty); print();
+		printf("\ttparam = %d, ", tparam.ty); tparam.print();
+	}
+		return Type.deduceType(sc, tparam, parameters, dedtypes);
+
+	  Lnomatch:
+		return MATCHnomatch;
+	}
+}
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		return new TypeInfoArrayDeclaration(this);
+	}
+
+    bool hasPointers()
+	{
+		return true;
+	}
+
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms);
+}
+
+    type* toCtype()
+	{
+		type *t;
+
+		if (ctype)
+			return ctype;
+
+		if (0 && global.params.symdebug)
+		{
+			/* Create a C type out of:
+			 *	struct _Array_T { size_t length; T* data; }
+			 */
+			Symbol* s;
+			char *id;
+
+			assert(next.deco);
+			id = cast(char*) alloca(7 + next.deco.length + 1);
+			sprintf(id, "_Array_%.*s", next.deco);
+			s = symbol_calloc(id);
+			s.Sclass = SC.SCstruct;
+			s.Sstruct = struct_calloc();
+			s.Sstruct.Sflags |= 0;
+			s.Sstruct.Salignsize = alignsize();
+			s.Sstruct.Sstructalign = cast(ubyte)global.structalign;
+			s.Sstruct.Sstructsize = cast(uint)size(Loc(0));
+			slist_add(s);
+
+			Symbol* s1 = symbol_name("length", SC.SCmember, Type.tsize_t.toCtype());
+			list_append(&s.Sstruct.Sfldlst, s1);
+
+			Symbol* s2 = symbol_name("data", SC.SCmember, next.pointerTo().toCtype());
+			s2.Smemoff = cast(uint)Type.tsize_t.size();
+			list_append(&s.Sstruct.Sfldlst, s2);
+
+			t = type_alloc(TYM.TYstruct);
+			t.Ttag = cast(Classsym*)s;		// structure tag name
+			t.Tcount++;
+			s.Stype = t;
+		}
+		else
+		{
+			if (global.params.symdebug == 1)
+			{
+				// Generate D symbolic debug info, rather than C
+				t = type_allocn(TYM.TYdarray, next.toCtype());
+			}
+			else
+				t = type_fake(TYM.TYdarray);
+		}
+		t.Tcount++;
+		ctype = t;
+		return t;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeDelegate.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,213 @@
+module dmd.TypeDelegate;
+
+import dmd.Type;
+import dmd.TypeNext;
+import dmd.MOD;
+import dmd.OutBuffer;
+import dmd.Id;
+import dmd.AddExp;
+import dmd.PtrExp;
+import dmd.IntegerExp;
+import dmd.NullExp;
+import dmd.TypeFunction;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.CppMangleState;
+import dmd.Argument;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeInfoDelegateDeclaration;
+import dmd.TY;
+import dmd.Global;
+
+import dmd.backend.TYPE;
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.TYM;
+import dmd.backend.SC;
+import dmd.backend.Util;
+import dmd.backend.LIST;
+
+class TypeDelegate : TypeNext
+{
+    // .next is a TypeFunction
+
+    this(Type t)
+	{
+		super(TY.Tfunction, t);
+		ty = TY.Tdelegate;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Type syntaxCopy()
+	{
+		Type t = next.syntaxCopy();
+		if (t == next)
+			t = this;
+		else
+		{	
+			t = new TypeDelegate(t);
+			t.mod = mod;
+		}
+		return t;
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		if (deco)			// if semantic() already run
+		{
+			//printf("already done\n");
+			return this;
+		}
+
+		next = next.semantic(loc, sc);
+		return merge();
+	}
+	
+    ulong size(Loc loc)
+	{
+		return PTRSIZE * 2;
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		TypeFunction tf = cast(TypeFunction)next;
+
+		tf.next.toCBuffer2(buf, hgs, MODundefined);
+		buf.writestring(" delegate");
+		Argument.argsToCBuffer(buf, hgs, tf.parameters, tf.varargs);
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypeDelegate.defaultInit() '%s'\n", toChars());
+	}
+		Expression e;
+		e = new NullExp(loc);
+		e.type = this;
+		return e;
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return true;
+	}
+	
+    bool checkBoolean()
+	{
+		return true;
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		return new TypeInfoDelegateDeclaration(this);
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+	version (LOGDOTEXP) {
+		printf("TypeDelegate.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+	}
+		if (ident == Id.ptr)
+		{
+			e.type = tvoidptr;
+			return e;
+		}
+		else if (ident == Id.funcptr)
+		{
+			e = e.addressOf(sc);
+			e.type = tvoidptr;
+			e = new AddExp(e.loc, e, new IntegerExp(PTRSIZE));
+			e.type = tvoidptr;
+			e = new PtrExp(e.loc, e);
+			e.type = next.pointerTo();
+			return e;
+		}
+		else
+		{
+			e = Type.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+    bool hasPointers()
+	{
+		return true;
+	}
+
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		type* t;
+
+		if (ctype)
+			return ctype;
+
+		if (0 && global.params.symdebug)
+		{
+			/* A delegate consists of:
+			 *    _Delegate { void* frameptr; Function *funcptr; }
+			 */
+
+			static Symbol* s;
+
+			if (!s)
+			{
+				s = symbol_calloc("_Delegate");
+				s.Sclass = SC.SCstruct;
+				s.Sstruct = struct_calloc();
+				s.Sstruct.Sflags |= 0;	/// huh?
+				s.Sstruct.Salignsize = alignsize();
+				s.Sstruct.Sstructalign = cast(ubyte)global.structalign;
+				s.Sstruct.Sstructsize = cast(uint)size(Loc(0));
+				slist_add(s);
+
+				Symbol* s1 = symbol_name("frameptr", SC.SCmember, Type.tvoidptr.toCtype());
+				list_append(&s.Sstruct.Sfldlst, s1);
+
+				Symbol* s2 = symbol_name("funcptr", SC.SCmember, Type.tvoidptr.toCtype());
+				s2.Smemoff = cast(uint)Type.tvoidptr.size();
+				list_append(&s.Sstruct.Sfldlst, s2);
+			}
+
+			t = type_alloc(TYM.TYstruct);
+			t.Ttag = cast(Classsym*)s;		// structure tag name
+			t.Tcount++;
+			s.Stype = t;
+		}
+		else
+		{
+			if (global.params.symdebug == 1)
+			{
+				// Generate D symbolic debug info, rather than C
+				t = type_allocn(TYM.TYdelegate, next.toCtype());
+			}
+			else
+				t = type_fake(TYM.TYdelegate);
+		}
+
+		t.Tcount++;
+		ctype = t;
+		return t;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeEnum.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,228 @@
+module dmd.TypeEnum;
+
+import dmd.Type;
+import dmd.EnumDeclaration;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.Id;
+import dmd.ErrorExp;
+import dmd.Dsymbol;
+import dmd.EnumMember;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.OutBuffer;
+import dmd.CppMangleState;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeInfoEnumDeclaration;
+import dmd.ArrayTypes;
+import dmd.TY;
+import dmd.Util;
+
+import dmd.backend.TYPE;
+
+class TypeEnum : Type
+{
+    EnumDeclaration sym;
+
+    this(EnumDeclaration sym)
+	{
+		super(TY.Tenum);
+		this.sym = sym;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    ulong size(Loc loc)
+	{
+		if (!sym.memtype)
+		{
+			error(loc, "enum %s is forward referenced", sym.toChars());
+			return 4;
+		}
+		return sym.memtype.size(loc);
+	}
+	
+    uint alignsize()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeEnum::semantic() %s\n", toChars());
+		//sym.semantic(sc);
+		return merge();
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		return sym;
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		string name = sym.mangle();
+		Type.toDecoBuffer(buf, flag);
+		buf.printf("%s", name);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, int mod)
+	{
+		assert(false);
+	}
+
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+	version (LOGDOTEXP) {
+		printf("TypeEnum::dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), toChars());
+	}
+		Dsymbol s = sym.search(e.loc, ident, 0);
+		if (!s)
+		{
+			if (ident is Id.max ||
+				ident is Id.min ||
+				ident is Id.init_ ||
+				ident is Id.stringof_ ||
+				!sym.memtype
+			   )
+			{
+				return getProperty(e.loc, ident);
+			}
+
+			return sym.memtype.dotExp(sc, e, ident);
+		}
+
+		EnumMember m = s.isEnumMember();
+		Expression em = m.value.copy();
+		em.loc = e.loc;
+		return em;
+	}
+	
+    Expression getProperty(Loc loc, Identifier ident)
+	{
+		assert(false);
+	}
+	
+    bool isintegral()
+	{
+		return true;
+	}
+	
+    bool isfloating()
+	{
+		return false;
+	}
+	
+    bool isscalar()
+	{
+		return true;
+		//return sym.memtype.isscalar();
+	}
+	
+    bool isunsigned()
+	{
+		return sym.memtype.isunsigned();
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		MATCH m;
+
+		//printf("TypeEnum::implicitConvTo()\n");
+		if (ty == to.ty && sym == (cast(TypeEnum)to).sym)
+			m = (mod == to.mod) ? MATCHexact : MATCHconst;
+		else if (sym.memtype.implicitConvTo(to))
+			m = MATCHconvert;	// match with conversions
+		else
+			m = MATCHnomatch;	// no match
+		return m;
+	}
+	
+    MATCH constConv(Type to)
+	{
+		assert(false);
+	}
+	
+    Type toBasetype()
+	{
+		if (!sym.memtype)
+		{
+			debug writef("2: ");
+			error(sym.loc, "enum %s is forward referenced", sym.toChars());
+			return tint32;
+		}
+
+		return sym.memtype.toBasetype();
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypeEnum::defaultInit() '%s'\n", toChars());
+	}
+		// Initialize to first member of enum
+		//printf("%s\n", sym.defaultval.type.toChars());
+		if (!sym.defaultval)
+		{
+			error(loc, "forward reference of %s.init", toChars());
+			return new ErrorExp();
+		}
+		return sym.defaultval;
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		if (!sym.defaultval)
+		{
+			debug writef("3: ");
+			error(loc, "enum %s is forward referenced", sym.toChars());
+			return 0;
+		}
+		return sym.defaultval.isBool(false);
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		return new TypeInfoEnumDeclaration(this);
+	}
+	
+    bool hasPointers()
+	{
+		return toBasetype().hasPointers();
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		return sym.memtype.toCtype();
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,62 @@
+module dmd.TypeExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class TypeExp : Expression
+{
+	this(Loc loc, Type type)
+	{
+		super(loc, TOK.TOKtype, TypeExp.sizeof);
+		//printf("TypeExp::TypeExp(%s)\n", type->toChars());
+		this.type = type;
+	}
+
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	Expression syntaxCopy()
+	{
+		//printf("TypeExp.syntaxCopy()\n");
+		return new TypeExp(loc, type.syntaxCopy());
+	}
+
+	Expression semantic(Scope sc)
+	{
+		//printf("TypeExp::semantic(%s)\n", type->toChars());
+		type = type.semantic(loc, sc);
+		return this;
+	}
+
+	void rvalue()
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	Expression optimize(int result)
+	{
+		return this;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeFunction.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,734 @@
+module dmd.TypeFunction;
+
+import dmd.TypeNext;
+import dmd.TypeSArray;
+import dmd.TypeArray;
+import dmd.ArrayTypes;
+import dmd.LINK;
+import dmd.StructDeclaration;
+import dmd.TypeStruct;
+import dmd.Global;
+import dmd.STC;
+import dmd.MOD;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.CppMangleState;
+import dmd.TypeInfoDeclaration;
+import dmd.MATCH;
+import dmd.Argument;
+import dmd.Expression;
+import dmd.RET;
+import dmd.TY;
+import dmd.Util;
+
+import dmd.backend.TYPE;
+import dmd.backend.PARAM;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.TF;
+import dmd.backend.mTY;
+
+import core.stdc.stdlib;
+import core.stdc.string;
+
+class TypeFunction : TypeNext
+{
+    // .next is the return type
+
+    Arguments parameters;	// function parameters
+    int varargs;	// 1: T t, ...) style for variable number of arguments
+			// 2: T t ...) style for variable number of arguments
+    bool isnothrow;	// true: nothrow
+    bool ispure;	// true: pure
+    bool isproperty;	// can be called without parentheses
+    bool isref;		// true: returns a reference
+    LINK linkage;	// calling convention
+
+    int inuse;
+
+    this(Arguments parameters, Type treturn, int varargs, LINK linkage)
+	{
+		super(TY.Tfunction, treturn);
+
+		//if (!treturn) *(char*)0=0;
+	//    assert(treturn);
+		assert(0 <= varargs && varargs <= 2);
+		this.parameters = parameters;
+		this.varargs = varargs;
+		this.linkage = linkage;
+	}
+	
+    Type syntaxCopy()
+	{
+		Type treturn = next ? next.syntaxCopy() : null;
+		Arguments params = Argument.arraySyntaxCopy(parameters);
+		TypeFunction t = new TypeFunction(params, treturn, varargs, linkage);
+		t.mod = mod;
+		t.isnothrow = isnothrow;
+		t.ispure = ispure;
+		t.isproperty = isproperty;
+		t.isref = isref;
+
+		return t;
+	}
+
+version (DumbClone) {
+} else {
+	final TypeFunction cloneTo(TypeFunction t)
+	{
+		super.cloneTo(t);
+		
+		// these 3 should be set by ctor
+		assert(t.parameters is null);
+		assert(t.varargs == varargs);
+		assert(t.linkage == linkage);
+
+		t.isnothrow = isnothrow;
+		t.ispure = ispure;
+		t.isproperty = isproperty;
+		t.isref = isref;
+		t.inuse = inuse;
+
+		if (parameters)
+		{
+			t.parameters = parameters.copy();
+			for (size_t i = 0; i < parameters.dim; i++)
+			{   
+				Argument arg = cast(Argument)parameters.data[i];
+				Argument cpy = arg.clone();
+				t.parameters.data[i] = cast(void*)cpy;
+			}
+		}
+
+		return t;
+	}
+
+	TypeFunction clone()
+	{
+		assert(this.classinfo == TypeFunction.classinfo);
+		return cloneTo(new TypeFunction(null, next, varargs, linkage));
+	}
+}
+    Type semantic(Loc loc, Scope sc)
+	{
+		if (deco)			// if semantic() already run
+		{
+			//printf("already done\n");
+			return this;
+		}
+		//printf("TypeFunction.semantic() this = %p\n", this);
+		//printf("TypeFunction.semantic() %s, sc.stc = %x\n", toChars(), sc.stc);
+
+		/* Copy in order to not mess up original.
+		 * This can produce redundant copies if inferring return type,
+		 * as semantic() will get called again on this.
+		 */
+
+		TypeFunction tf = cast(TypeFunction)clone();
+
+		if (sc.stc & STC.STCpure)
+			tf.ispure = true;
+		if (sc.stc & STC.STCnothrow)
+			tf.isnothrow = true;
+		if (sc.stc & STC.STCref)
+			tf.isref = true;
+
+		tf.linkage = sc.linkage;
+		if (tf.next)
+		{
+			tf.next = tf.next.semantic(loc,sc);
+			if (tf.next.toBasetype().ty == TY.Tsarray)
+			{   error(loc, "functions cannot return static array %s", tf.next.toChars());
+				tf.next = Type.terror;
+			}
+			if (tf.next.toBasetype().ty == TY.Tfunction)
+			{   error(loc, "functions cannot return a function");
+				tf.next = Type.terror;
+			}
+			if (tf.next.toBasetype().ty == TY.Ttuple)
+			{   error(loc, "functions cannot return a tuple");
+				tf.next = Type.terror;
+			}
+			if (tf.next.isauto() && !(sc.flags & SCOPE.SCOPEctor))
+			error(loc, "functions cannot return scope %s", tf.next.toChars());
+		}
+
+		if (tf.parameters)
+		{	size_t dim = Argument.dim(tf.parameters);
+
+			for (size_t i = 0; i < dim; i++)
+			{   Argument arg = Argument.getNth(tf.parameters, i);
+
+				tf.inuse++;
+				arg.type = arg.type.semantic(loc,sc);
+				if (tf.inuse == 1) tf.inuse--;
+
+				arg.type = arg.type.addStorageClass(arg.storageClass);
+
+				if (arg.storageClass & (STC.STCauto | STC.STCalias | STC.STCstatic))
+				{
+					if (!arg.type)
+					continue;
+				}
+
+				Type t = arg.type.toBasetype();
+
+				if (arg.storageClass & (STC.STCout | STC.STCref | STC.STClazy))
+				{
+					if (t.ty == TY.Tsarray)
+						error(loc, "cannot have out or ref parameter of type %s", t.toChars());
+					if (arg.storageClass & STC.STCout && arg.type.mod)
+						error(loc, "cannot have const/invariant out parameter of type %s", t.toChars());
+				}
+				if (!(arg.storageClass & STC.STClazy) && t.ty == TY.Tvoid)
+					error(loc, "cannot have parameter of type %s", arg.type.toChars());
+
+				if (arg.defaultArg)
+				{
+					arg.defaultArg = arg.defaultArg.semantic(sc);
+					arg.defaultArg = resolveProperties(sc, arg.defaultArg);
+					arg.defaultArg = arg.defaultArg.implicitCastTo(sc, arg.type);
+				}
+
+				/* If arg turns out to be a tuple, the number of parameters may
+				 * change.
+				 */
+				if (t.ty == TY.Ttuple)
+				{	dim = Argument.dim(tf.parameters);
+					i--;
+				}
+			}
+		}
+		if (tf.next)
+		tf.deco = tf.merge().deco;
+
+		if (tf.inuse)
+		{	error(loc, "recursive type");
+			tf.inuse = 0;
+			return terror;
+		}
+
+		if (tf.varargs == 1 && tf.linkage != LINK.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 tf;
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		ubyte mc;
+
+		//printf("TypeFunction.toDecoBuffer() this = %p %s\n", this, toChars());
+		//static int nest; if (++nest == 50) *(char*)0=0;
+		if (inuse)
+		{	
+			inuse = 2;		// flag error to caller
+			return;
+		}
+		inuse++;
+static if (true) {
+		if (mod & MOD.MODshared)
+			buf.writeByte('O');
+		if (mod & MOD.MODconst)
+			buf.writeByte('x');
+		else if (mod & MOD.MODinvariant)
+			buf.writeByte('y');
+}
+		switch (linkage)
+		{
+			case LINK.LINKd:		mc = 'F';	break;
+			case LINK.LINKc:		mc = 'U';	break;
+			case LINK.LINKwindows:	mc = 'W';	break;
+			case LINK.LINKpascal:	mc = 'V';	break;
+			case LINK.LINKcpp:		mc = 'R';	break;
+		}
+		buf.writeByte(mc);
+		if (ispure || isnothrow || isproperty || isref)
+		{
+			if (ispure)
+				buf.writestring("Na");
+			if (isnothrow)
+				buf.writestring("Nb");
+			if (isref)
+				buf.writestring("Nc");
+			if (isproperty)
+				buf.writestring("Nd");
+		}
+		// Write argument types
+		Argument.argsToDecoBuffer(buf, parameters);
+		//if (buf.data[buf.offset - 1] == '@') halt();
+		buf.writeByte('Z' - varargs);	// mark end of arg list
+		next.toDecoBuffer(buf);
+		inuse--;
+	}
+	
+    void toCBuffer(OutBuffer buf, Identifier ident, HdrGenState* hgs)
+	{
+		//printf("TypeFunction.toCBuffer() this = %p\n", this);
+		string p = null;
+
+		if (inuse)
+		{	
+			inuse = 2;		// flag error to caller
+			return;
+		}
+		inuse++;
+
+		/* Use 'storage class' style for attributes
+		 */
+		if (mod & MODconst)
+			buf.writestring("const ");
+		if (mod & MODinvariant)
+			buf.writestring("immutable ");
+		if (mod & MODshared)
+			buf.writestring("shared ");
+
+		if (ispure)
+			buf.writestring("pure ");
+		if (isnothrow)
+			buf.writestring("nothrow ");
+		if (isproperty)
+			buf.writestring("@property ");
+		if (isref)
+			buf.writestring("ref ");
+
+		if (next && (!ident || ident.toHChars2() == ident.toChars()))
+			next.toCBuffer2(buf, hgs, MODundefined);
+		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);
+		if (ident)
+		{   
+			buf.writeByte(' ');
+			buf.writestring(ident.toHChars2());
+		}
+		Argument.argsToCBuffer(buf, hgs, parameters, varargs);
+		inuse--;
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		//printf("TypeFunction::toCBuffer2() this = %p, ref = %d\n", this, isref);
+		string p;
+
+		if (inuse)
+		{
+			inuse = 2;		// flag error to caller
+			return;
+		}
+
+		inuse++;
+		if (next)
+			next.toCBuffer2(buf, hgs, MODundefined);
+
+		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);
+
+		/* Use postfix style for attributes
+		 */
+		if (mod != this.mod)
+		{
+			modToBuffer(buf);
+		}
+
+		if (ispure)
+			buf.writestring(" pure");
+		if (isnothrow)
+			buf.writestring(" nothrow");
+		if (isproperty)
+			buf.writestring(" @property");
+		if (isref)
+			buf.writestring(" ref");
+
+		inuse--;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		assert(false);
+	}
+	
+    Type reliesOnTident()
+	{
+		if (parameters)
+		{
+			for (size_t i = 0; i < parameters.dim; i++)
+			{   
+				Argument arg = cast(Argument)parameters.data[i];
+				Type t = arg.type.reliesOnTident();
+				if (t)
+					return t;
+			}
+		}
+		return next.reliesOnTident();
+	}
+
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+	/***************************
+	 * Examine function signature for parameter p and see if
+	 * p can 'escape' the scope of the function.
+	 */
+    bool parameterEscapes(Argument p)
+	{
+		/* Scope parameters do not escape.
+		 * Allow 'lazy' to imply 'scope' -
+		 * lazy parameters can be passed along
+		 * as lazy parameters to the next function, but that isn't
+		 * escaping.
+		 */
+		if (p.storageClass & (STC.STCscope | STC.STClazy))
+			return false;
+
+		if (ispure)
+		{	/* With pure functions, we need only be concerned if p escapes
+			 * via any return statement.
+			 */
+			Type tret = nextOf().toBasetype();
+			if (!isref && !tret.hasPointers())
+			{   /* The result has no references, so p could not be escaping
+				 * that way.
+				 */
+				return false;
+			}
+		}
+
+		/* Assume it escapes in the absence of better information.
+		 */
+		return true;
+	}
+
+	/********************************
+	 * 'args' are being matched to function 'this'
+	 * Determine match level.
+	 * Returns:
+	 *	MATCHxxxx
+	 */
+    MATCH callMatch(Expression ethis, Expressions args)
+	{
+		//printf("TypeFunction.callMatch() %s\n", toChars());
+		MATCH match = MATCH.MATCHexact;		// assume exact match
+
+		if (ethis)
+		{
+			Type t = ethis.type;
+			if (t.toBasetype().ty == TY.Tpointer)
+				t = t.toBasetype().nextOf();	// change struct* to struct
+
+			if (t.mod != mod)
+			{
+				if (mod == MOD.MODconst)
+					match = MATCH.MATCHconst;
+				else
+					return MATCH.MATCHnomatch;
+			}
+		}
+
+		size_t nparams = Argument.dim(parameters);
+		size_t nargs = args ? args.dim : 0;
+		if (nparams == nargs) {
+			;
+		} else if (nargs > nparams)
+		{
+			if (varargs == 0)
+				goto Nomatch;		// too many args; no match
+			match = MATCH.MATCHconvert;		// match ... with a "conversion" match level
+		}
+
+		for (size_t u = 0; u < nparams; u++)
+		{	
+			MATCH m;
+			Expression arg;
+
+			// BUG: what about out and ref?
+
+			Argument p = Argument.getNth(parameters, u);
+			assert(p);
+			if (u >= nargs)
+			{
+				if (p.defaultArg)
+					continue;
+				if (varargs == 2 && u + 1 == nparams)
+					goto L1;
+				goto Nomatch;		// not enough arguments
+			}
+
+			arg = cast(Expression)args.data[u];
+			assert(arg);
+
+			// Non-lvalues do not match ref or out parameters
+			if (p.storageClass & (STC.STCref | STC.STCout) && !arg.isLvalue())
+				goto Nomatch;
+
+			if (p.storageClass & STC.STClazy && p.type.ty == TY.Tvoid && arg.type.ty != TY.Tvoid)
+				m = MATCH.MATCHconvert;
+			else
+				m = arg.implicitConvTo(p.type);
+			//printf("\tm = %d\n", m);
+			if (m == MATCH.MATCHnomatch)			// if no match
+			{
+			  L1:
+				if (varargs == 2 && u + 1 == nparams)	// if last varargs param
+				{	
+					Type tb = p.type.toBasetype();
+					TypeSArray tsa;
+					long sz;
+
+					switch (tb.ty)
+					{
+						case TY.Tsarray:
+							tsa = cast(TypeSArray)tb;
+							sz = tsa.dim.toInteger();
+							if (sz != nargs - u)
+								goto Nomatch;
+						case TY.Tarray:
+						{	
+							TypeArray ta = cast(TypeArray)tb;
+							for (; u < nargs; u++)
+							{
+								arg = cast(Expression)args.data[u];
+								assert(arg);
+static if (true) {
+								/* If lazy array of delegates,
+								 * convert arg(s) to delegate(s)
+								 */
+								Type tret = p.isLazyArray();
+								if (tret)
+								{
+									if (ta.next.equals(arg.type))
+									{   
+										m = MATCH.MATCHexact;
+									}
+									else
+									{
+										m = arg.implicitConvTo(tret);
+										if (m == MATCH.MATCHnomatch)
+										{
+											if (tret.toBasetype().ty == TY.Tvoid)
+												m = MATCH.MATCHconvert;
+										}
+									}
+								}
+								else
+									m = arg.implicitConvTo(ta.next);
+} else {
+								m = arg.implicitConvTo(ta.next);
+}
+								if (m == MATCH.MATCHnomatch)
+									goto Nomatch;
+
+								if (m < match)
+									match = m;
+							}
+							goto Ldone;
+						}
+
+						case TY.Tclass:
+							// Should see if there's a constructor match?
+							// Or just leave it ambiguous?
+							goto Ldone;
+
+						default:
+							goto Nomatch;
+					}
+				}
+
+				goto Nomatch;
+			}
+
+			if (m < match)
+				match = m;			// pick worst match
+		}
+
+	Ldone:
+		//printf("match = %d\n", match);
+		return match;
+
+	Nomatch:
+		//printf("no match\n");
+		return MATCH.MATCHnomatch;
+	}
+	
+    type* toCtype()
+	{
+		if (ctype) {
+			return ctype;
+		}
+
+		type* t;
+		if (true)
+		{
+			param_t* paramtypes;
+			tym_t tyf;
+			type* tp;
+
+			paramtypes = null;
+			size_t nparams = Argument.dim(parameters);
+			for (size_t i = 0; i < nparams; i++)
+			{   
+				Argument arg = Argument.getNth(parameters, i);
+				tp = arg.type.toCtype();
+				if (arg.storageClass & (STC.STCout | STC.STCref))
+				{   
+					// C doesn't have reference types, so it's really a pointer
+					// to the parameter type
+					tp = type_allocn(TYM.TYref, tp);
+				}
+				param_append_type(&paramtypes,tp);
+			}
+			tyf = totym();
+			t = type_alloc(tyf);
+			t.Tflags |= TF.TFprototype;
+			if (varargs != 1)
+				t.Tflags |= TF.TFfixed;
+			ctype = t;
+			t.Tnext = next.toCtype();
+			t.Tnext.Tcount++;
+			t.Tparamtypes = paramtypes;
+		}
+		ctype = t;
+		return t;
+	}
+	
+	/***************************
+	 * Determine return style of function - whether in registers or
+	 * through a hidden pointer to the caller's stack.
+	 */
+    RET retStyle()
+	{
+		//printf("TypeFunction.retStyle() %s\n", toChars());
+version (DMDV2) {
+		if (isref)
+			return RET.RETregs;			// returns a pointer
+}
+
+		Type tn = next.toBasetype();
+
+		if (tn.ty == TY.Tstruct)
+		{	
+			StructDeclaration sd = (cast(TypeStruct)tn).sym;
+			if (global.params.isLinux && linkage != LINK.LINKd) {
+				;
+			}
+///version (DMDV2) {
+			else if (sd.dtor || sd.cpctor) {
+				;
+			}
+///}
+			else
+			{
+				switch (cast(int)tn.size())
+				{   
+					case 1:
+					case 2:
+					case 4:
+					case 8:
+						return RET.RETregs;	// return small structs in regs
+								// (not 3 byte structs!)
+					default:
+						break;
+				}
+			}
+			return RET.RETstack;
+		}
+		else if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
+			 linkage == LINK.LINKc &&
+			 tn.iscomplex())
+		{
+			if (tn.ty == TY.Tcomplex32)
+				return RET.RETregs;	// in EDX:EAX, not ST1:ST0
+			else
+				return RET.RETstack;
+		}
+		else
+			return RET.RETregs;
+	}
+
+    TYM totym()
+	{
+		TYM tyf;
+
+		//printf("TypeFunction.totym(), linkage = %d\n", linkage);
+		switch (linkage)
+		{
+		case LINK.LINKwindows:
+			tyf = (varargs == 1) ? TYM.TYnfunc : TYM.TYnsfunc;
+			break;
+
+		case LINK.LINKpascal:
+			tyf = (varargs == 1) ? TYM.TYnfunc : TYM.TYnpfunc;
+			break;
+
+		case LINK.LINKc:
+			tyf = TYM.TYnfunc;
+	version (XXX) {///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+			if (retStyle() == RET.RETstack)
+				tyf = TYM.TYhfunc;
+	}
+			break;
+
+		case LINK.LINKd:
+			tyf = (varargs == 1) ? TYM.TYnfunc : TYM.TYjfunc;
+			break;
+
+		case LINK.LINKcpp:
+			tyf = TYM.TYnfunc;
+			break;
+
+		default:
+			writef("linkage = %d\n", linkage);
+			assert(0);
+		}
+	version (DMDV2) {
+		if (isnothrow)
+			tyf |= mTY.mTYnothrow;
+	}
+		return tyf;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeIdentifier.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,180 @@
+module dmd.TypeIdentifier;
+
+import dmd.TypeQualified;
+import dmd.MOD;
+import dmd.Identifier;
+import dmd.IdentifierExp;
+import dmd.DotIdExp;
+import dmd.TypeTypedef;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.Type;
+import dmd.Dsymbol;
+import dmd.MATCH;
+import dmd.ArrayTypes;
+import dmd.TY;
+import dmd.Util;
+
+debug import dmd.Global;
+
+class TypeIdentifier : TypeQualified
+{
+    Identifier ident;
+
+    this(Loc loc, Identifier ident)
+	{
+		super(TY.Tident, loc);
+		this.ident = ident;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Type syntaxCopy()
+	{
+		TypeIdentifier t = new TypeIdentifier(loc, ident);
+		t.syntaxCopyHelper(this);
+		t.mod = mod;
+
+		return t;
+	}
+	
+    //char *toChars();
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		Type.toDecoBuffer(buf, flag);
+		string name = ident.toChars();
+		buf.printf("%d%s", name.length, name);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		buf.writestring(this.ident.toChars());
+		toCBuffer2Helper(buf, hgs);
+	}
+
+	/*************************************
+	 * Takes an array of Identifiers and figures out if
+	 * it represents a Type or an Expression.
+	 * Output:
+	 *	if expression, *pe is set
+	 *	if type, *pt is set
+	 */
+    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		Dsymbol scopesym;
+
+		//printf("TypeIdentifier::resolve(sc = %p, idents = '%s')\n", sc, toChars());
+		Dsymbol s = sc.search(loc, ident, &scopesym);
+		resolveHelper(loc, sc, s, scopesym, pe, pt, ps);
+		if (*pt)
+			(*pt) = (*pt).addMod(mod);
+	}
+	
+	/*****************************************
+	 * See if type resolves to a symbol, if so,
+	 * return that symbol.
+	 */
+    Dsymbol toDsymbol(Scope sc)
+	{
+		//printf("TypeIdentifier::toDsymbol('%s')\n", toChars());
+		if (!sc)
+			return null;
+		//printf("ident = '%s'\n", ident.toChars());
+
+		Dsymbol scopesym;
+		Dsymbol s = sc.search(loc, ident, &scopesym);
+		if (s)
+		{
+			for (int i = 0; i < idents.dim; i++)
+			{
+				Identifier id = cast(Identifier)idents.data[i];
+				s = s.searchX(loc, sc, id);
+				if (!s)                 // failed to find a symbol
+				{	
+					//printf("\tdidn't find a symbol\n");
+					break;
+				}
+			}
+		}
+
+		return s;
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		Type t;
+		Expression e;
+		Dsymbol s;
+
+		//printf("TypeIdentifier::semantic(%s)\n", toChars());
+		resolve(loc, sc, &e, &t, &s);
+		if (t)
+		{
+			//printf("\tit's a type %d, %s, %s\n", t.ty, t.toChars(), t.deco);
+
+			if (t.ty == TY.Ttypedef)
+			{   
+				TypeTypedef tt = cast(TypeTypedef)t;
+
+				if (tt.sym.sem == 1)
+				error(loc, "circular reference of typedef %s", tt.toChars());
+			}
+			t = t.addMod(mod);
+		}
+		else
+		{
+debug {
+		if (!global.gag) {
+			writef("1: ");
+		}
+}
+			if (s)
+			{
+				s.error(loc, "is used as a type");
+				//halt();
+			}
+			else {
+				error(loc, "%s is used as a type", toChars());
+			}
+			t = tvoid;
+		}
+		//t.print();
+		return t;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    Type reliesOnTident()
+	{
+		return this;
+	}
+	
+    Expression toExpression()
+	{
+		Expression e = new IdentifierExp(loc, ident);
+		for (int i = 0; i < idents.dim; i++)
+		{
+			Identifier id = cast(Identifier)idents.data[i];
+			e = new DotIdExp(loc, e, id);
+		}
+
+		return e;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoArrayDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,34 @@
+module dmd.TypeInfoArrayDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.Type;
+import dmd.TY;
+import dmd.TypeDArray;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoArrayDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoArrayDeclaration::toDt()\n");
+		dtxoff(pdt, Type.typeinfoarray.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Array
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Tarray);
+
+		TypeDArray tc = cast(TypeDArray)tinfo;
+
+		tc.next.getTypeInfo(null);
+		dtxoff(pdt, tc.next.vtinfo.toSymbol(), 0, TYnptr); // TypeInfo for array of type
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoClassDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,40 @@
+module dmd.TypeInfoClassDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.ClassInfoDeclaration;
+import dmd.TypeClass;
+import dmd.TY;
+import dmd.Util;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.Symbol;
+
+class TypeInfoClassDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
+		dtxoff(pdt, Type.typeinfoclass.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Tclass);
+
+		TypeClass tc = cast(TypeClass)tinfo;
+
+		if (!tc.sym.vclassinfo)
+			tc.sym.vclassinfo = new ClassInfoDeclaration(tc.sym);
+
+		Symbol* s = tc.sym.vclassinfo.toSymbol();
+		assert(s.Sxtrnnum == 0);
+
+		dtxoff(pdt, s, 0, TYnptr);		// ClassInfo for tinfo
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoConstDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,28 @@
+module dmd.TypeInfoConstDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.Type;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoConstDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoConstDeclaration.toDt() %s\n", toChars());
+		dtxoff(pdt, Type.typeinfoconst.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Const
+		dtdword(pdt, 0);			    // monitor
+		Type tm = tinfo.mutableOf();
+		tm = tm.merge();
+		tm.getTypeInfo(null);
+		dtxoff(pdt, tm.vtinfo.toSymbol(), 0, TYnptr);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,114 @@
+module dmd.TypeInfoDeclaration;
+
+import dmd.VarDeclaration;
+import dmd.Type;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.STC;
+import dmd.PROT;
+import dmd.LINK;
+
+import dmd.backend.Symbol;
+import dmd.backend.dt_t;
+import dmd.backend.DT;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.glue;
+import dmd.backend.Util;
+import dmd.backend.TYPE;
+
+import core.stdc.stdio;
+
+class TypeInfoDeclaration : VarDeclaration
+{
+    Type tinfo;
+
+    this(Type tinfo, int internal)
+	{
+		super(Loc(0), Type.typeinfo.type, tinfo.getTypeInfoIdent(internal), null);
+		this.tinfo = tinfo;
+		storage_class = STC.STCstatic | STC.STCgshared;
+		protection = PROT.PROTpublic;
+		linkage = LINK.LINKc;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+
+    void semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+    void emitComment(Scope sc)
+	{
+		assert(false);
+	}
+
+    Symbol* toSymbol()
+	{
+		//printf("TypeInfoDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage);
+		return VarDeclaration.toSymbol();
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		Symbol* s;
+		uint sz;
+		Dsymbol parent;
+
+		//printf("TypeInfoDeclaration.toObjFile(%p '%s') protection %d\n", this, toChars(), protection);
+
+		if (multiobj)
+		{
+			obj_append(this);
+			return;
+		}
+
+		s = toSymbol();
+		sz = cast(uint)type.size();
+
+		parent = this.toParent();
+		s.Sclass = SC.SCcomdat;
+		s.Sfl = FL.FLdata;
+
+		toDt(&s.Sdt);
+
+		dt_optimize(s.Sdt);
+
+		// See if we can convert a comdat to a comdef,
+		// which saves on exe file space.
+		if (s.Sclass == SC.SCcomdat &&
+			s.Sdt.dt == DT.DT_azeros &&
+			s.Sdt.DTnext == null)
+		{
+			s.Sclass = SC.SCglobal;
+			s.Sdt.dt = DT.DT_common;
+		}
+
+version (XXX) { ///ELFOBJ || MACHOBJ // Burton
+		if (s.Sdt && s.Sdt.dt == DT_azeros && s.Sdt.DTnext == null)
+			s.Sseg = Segment.UDATA;
+		else
+			s.Sseg = Segment.DATA;
+}
+		outdata(s);
+		if (isExport())
+			obj_export(s,0);
+	}
+
+    void toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoDelegateDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,33 @@
+module dmd.TypeInfoDelegateDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeDelegate;
+import dmd.TY;
+
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoDelegateDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoDelegateDeclaration.toDt()\n");
+		dtxoff(pdt, Type.typeinfodelegate.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Delegate
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Tdelegate);
+
+		TypeDelegate tc = cast(TypeDelegate)tinfo;
+
+		tc.next.nextOf().getTypeInfo(null);
+		dtxoff(pdt, tc.next.nextOf().vtinfo.toSymbol(), 0, TYnptr); // TypeInfo for delegate return value
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoEnumDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,66 @@
+module dmd.TypeInfoEnumDeclaration;
+
+import dmd.TY;
+import dmd.Type;
+import dmd.Loc;
+import dmd.TypeEnum;
+import dmd.EnumDeclaration;
+import dmd.TypeInfoDeclaration;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+import std.string : toStringz;
+
+class TypeInfoEnumDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoEnumDeclaration::toDt()\n");
+		dtxoff(pdt, Type.typeinfoenum.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Enum
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Tenum);
+
+		TypeEnum tc = cast(TypeEnum)tinfo;
+		EnumDeclaration sd = tc.sym;
+
+		/* Put out:
+		 *	TypeInfo base;
+		 *	char[] name;
+		 *	void[] m_init;
+		 */
+
+		if (sd.memtype)
+		{	
+			sd.memtype.getTypeInfo(null);
+			dtxoff(pdt, sd.memtype.vtinfo.toSymbol(), 0, TYnptr);	// TypeInfo for enum members
+		}
+		else
+			dtdword(pdt, 0);
+
+		string name = sd.toPrettyChars();
+		size_t namelen = name.length;
+		dtdword(pdt, namelen);
+		dtabytes(pdt, TYnptr, 0, namelen + 1, toStringz(name));
+
+		// void[] init;
+		if (!sd.defaultval || tinfo.isZeroInit(Loc(0)))
+		{	
+			// 0 initializer, or the same as the base type
+			dtdword(pdt, 0);	// init.length
+			dtdword(pdt, 0);	// init.ptr
+		}
+		else
+		{
+			dtdword(pdt, cast(int)sd.type.size());	// init.length
+			dtxoff(pdt, sd.toInitializer(), 0, TYnptr);	// init.ptr
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoInterfaceDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,38 @@
+module dmd.TypeInfoInterfaceDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.ClassInfoDeclaration;
+import dmd.TypeClass;
+import dmd.TY;
+
+import dmd.backend.dt_t;
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoInterfaceDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoInterfaceDeclaration.toDt() %s\n", tinfo.toChars());
+		dtxoff(pdt, Type.typeinfointerface.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Tclass);
+
+		TypeClass tc = cast(TypeClass)tinfo;
+		Symbol *s;
+
+		if (!tc.sym.vclassinfo)
+			tc.sym.vclassinfo = new ClassInfoDeclaration(tc.sym);
+		s = tc.sym.vclassinfo.toSymbol();
+		dtxoff(pdt, s, 0, TYnptr);		// ClassInfo for tinfo
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoInvariantDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,27 @@
+module dmd.TypeInfoInvariantDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoInvariantDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoInvariantDeclaration.toDt() %s\n", toChars());
+		dtxoff(pdt, Type.typeinfoinvariant.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Invariant
+		dtdword(pdt, 0);			    // monitor
+		Type tm = tinfo.mutableOf();
+		tm = tm.merge();
+		tm.getTypeInfo(null);
+		dtxoff(pdt, tm.vtinfo.toSymbol(), 0, TYnptr);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoPointerDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,32 @@
+module dmd.TypeInfoPointerDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.TypePointer;
+import dmd.TY;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypeInfoPointerDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoPointerDeclaration::toDt()\n");
+		dtxoff(pdt, Type.typeinfopointer.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Pointer
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Tpointer);
+
+		TypePointer tc = cast(TypePointer)tinfo;
+
+		tc.next.getTypeInfo(null);
+		dtxoff(pdt, tc.next.vtinfo.toSymbol(), 0, TYnptr); // TypeInfo for type being pointed to
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoSharedDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,20 @@
+module dmd.TypeInfoSharedDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.backend.dt_t;
+
+class TypeInfoSharedDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		assert(false);
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoStructDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,229 @@
+module dmd.TypeInfoStructDeclaration;
+
+import dmd.Type;
+import dmd.TY;
+import dmd.MOD;
+import dmd.Loc;
+import dmd.Argument;
+import dmd.STC;
+import dmd.TypeStruct;
+import dmd.TypeFunction;
+import dmd.StructDeclaration;
+import dmd.FuncDeclaration;
+import dmd.Dsymbol;
+import dmd.ArrayTypes;
+import dmd.Scope;
+import dmd.LINK;
+import dmd.Id;
+import dmd.TypeInfoDeclaration;
+import dmd.backend.dt_t;
+import dmd.backend.TYM;
+import dmd.backend.Util;
+import dmd.expression.Util;
+
+import std.string : toStringz;
+
+class TypeInfoStructDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoStructDeclaration.toDt() '%s'\n", toChars());
+
+		uint offset = Type.typeinfostruct.structsize;
+
+		dtxoff(pdt, Type.typeinfostruct.toVtblSymbol(), 0, TYM.TYnptr); // vtbl for TypeInfo_Struct
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == TY.Tstruct);
+
+		TypeStruct tc = cast(TypeStruct)tinfo;
+		StructDeclaration sd = tc.sym;
+
+		/* Put out:
+		 *	char[] name;
+		 *	void[] init;
+		 *	hash_t function(in void*) xtoHash;
+		 *	bool function(in void*, in void*) xopEquals;
+		 *	int function(in void*, in void*) xopCmp;
+		 *	string function(const(void)*) xtoString;
+		 *	uint m_flags;
+		 *  xgetMembers;
+		 *	xdtor;
+		 *	xpostblit;
+		 *
+		 *	name[]
+		 */
+
+		string name = sd.toPrettyChars();
+		size_t namelen = name.length;
+		dtdword(pdt, namelen);
+
+		//dtabytes(pdt, TYnptr, 0, namelen + 1, name);
+		dtxoff(pdt, toSymbol(), offset, TYM.TYnptr);
+		offset += namelen + 1;
+
+		// void[] init;
+		dtdword(pdt, sd.structsize);	// init.length
+		if (sd.zeroInit)
+			dtdword(pdt, 0);		// null for 0 initialization
+		else
+			dtxoff(pdt, sd.toInitializer(), 0, TYM.TYnptr);	// init.ptr
+		FuncDeclaration fd;
+		FuncDeclaration fdx;
+		TypeFunction tf;
+		Type ta;
+		Dsymbol s;
+
+		static TypeFunction tftohash;
+		static TypeFunction tftostring;
+
+		if (!tftohash)
+		{
+			scope Scope sc = new Scope();
+
+			tftohash = new TypeFunction(null, Type.thash_t, 0, LINK.LINKd);
+			tftohash.mod = MOD.MODconst;
+			tftohash = cast(TypeFunction)tftohash.semantic(Loc(0), sc);
+
+			tftostring = new TypeFunction(null, Type.tchar.invariantOf().arrayOf(), 0, LINK.LINKd);
+			tftostring = cast(TypeFunction)tftostring.semantic(Loc(0), sc);
+		}
+
+		TypeFunction tfeqptr;
+		{	
+			// bool opEqual(const T*) const;
+			scope Scope sc = new Scope();
+			Arguments arguments = new Arguments;
+		version (STRUCTTHISREF) {
+			// arg type is ref const T
+			Argument arg = new Argument(STC.STCref, tc.constOf(), null, null);
+		} else {
+			// arg type is const T*
+			Argument arg = new Argument(STC.STCin, tc.pointerTo(), null, null);
+		}
+
+			arguments.push(cast(void*)arg);
+			tfeqptr = new TypeFunction(arguments, Type.tbool, 0, LINK.LINKd);
+			tfeqptr.mod = MOD.MODconst;
+			tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc);
+		}
+
+		TypeFunction tfcmpptr;
+		{
+			scope Scope sc = new Scope();
+			Arguments arguments = new Arguments;
+		version (STRUCTTHISREF) {
+			// arg type is ref const T
+			Argument arg = new Argument(STC.STCref, tc.constOf(), null, null);
+		} else {
+			// arg type is const T*
+			Argument arg = new Argument(STC.STCin, tc.pointerTo(), null, null);
+		}
+
+			arguments.push(cast(void*)arg);
+			tfcmpptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd);
+			tfcmpptr.mod = MOD.MODconst;
+			tfcmpptr = cast(TypeFunction)tfcmpptr.semantic(Loc(0), sc);
+		}
+
+		s = search_function(sd, Id.tohash);
+		fdx = s ? s.isFuncDeclaration() : null;
+		if (fdx)
+		{	
+			fd = fdx.overloadExactMatch(tftohash);
+			if (fd)
+				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
+			else
+				//fdx.error("must be declared as extern (D) uint toHash()");
+				dtdword(pdt, 0);
+		}
+		else
+			dtdword(pdt, 0);
+
+		s = search_function(sd, Id.eq);
+		fdx = s ? s.isFuncDeclaration() : null;
+		if (fdx)
+		{
+			//printf("test1 %s, %s, %s\n", fdx.toChars(), fdx.type.toChars(), tfeqptr.toChars());
+			fd = fdx.overloadExactMatch(tfeqptr);
+			if (fd)
+				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
+			else
+			{   
+				fd = fdx.overloadExactMatch(tfcmpptr);
+				if (fd)
+					fdx.error("must return bool, not int");
+				//fdx.error("must be declared as extern (D) int %s(%s*)", fdx.toChars(), sd.toChars());
+				dtdword(pdt, 0);
+			}
+		}
+		else
+			dtdword(pdt, 0);
+
+		s = search_function(sd, Id.cmp);
+		fdx = s ? s.isFuncDeclaration() : null;
+		if (fdx)
+		{
+			//printf("test1 %s, %s, %s\n", fdx.toChars(), fdx.type.toChars(), tfeqptr.toChars());
+			fd = fdx.overloadExactMatch(tfcmpptr);
+			if (fd)
+			{
+				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
+				//printf("test2\n");
+			}
+			else
+				//fdx.error("must be declared as extern (D) int %s(%s*)", fdx.toChars(), sd.toChars());
+				dtdword(pdt, 0);
+		}
+		else
+			dtdword(pdt, 0);
+	
+		s = search_function(sd, Id.tostring);
+		fdx = s ? s.isFuncDeclaration() : null;
+		if (fdx)
+		{	
+			fd = fdx.overloadExactMatch(tftostring);
+			if (fd)
+				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
+			else
+				//fdx.error("must be declared as extern (D) char[] toString()");
+				dtdword(pdt, 0);
+		}
+		else
+			dtdword(pdt, 0);
+
+		// uint m_flags;
+		dtdword(pdt, tc.hasPointers());
+
+version (DMDV2) {
+		// xgetMembers
+		FuncDeclaration sgetmembers = sd.findGetMembers();
+		if (sgetmembers)
+			dtxoff(pdt, sgetmembers.toSymbol(), 0, TYM.TYnptr);
+		else
+			dtdword(pdt, 0);			// xgetMembers
+
+		// xdtor
+		FuncDeclaration sdtor = sd.dtor;
+		if (sdtor)
+			dtxoff(pdt, sdtor.toSymbol(), 0, TYM.TYnptr);
+		else
+			dtdword(pdt, 0);			// xdtor
+
+		// xpostblit
+		FuncDeclaration spostblit = sd.postblit;
+		if (spostblit)
+			dtxoff(pdt, spostblit.toSymbol(), 0, TYM.TYnptr);
+		else
+			dtdword(pdt, 0);			// xpostblit
+}
+		// name[]
+		dtnbytes(pdt, namelen + 1, toStringz(name));
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoTypedefDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,65 @@
+module dmd.TypeInfoTypedefDeclaration;
+
+import dmd.Type;
+import dmd.TypeInfoDeclaration;
+import dmd.TypedefDeclaration;
+import dmd.TypeTypedef;
+import dmd.TY;
+import dmd.Loc;
+import dmd.backend.dt_t;
+import dmd.backend.TYM;
+import dmd.backend.Util;
+
+import std.string;
+
+class TypeInfoTypedefDeclaration : TypeInfoDeclaration
+{
+	this(Type tinfo)
+	{
+		super(tinfo, 0);
+	}
+
+	void toDt(dt_t** pdt)
+	{
+		//printf("TypeInfoTypedefDeclaration.toDt() %s\n", toChars());
+
+		dtxoff(pdt, Type.typeinfotypedef.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Typedef
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Ttypedef);
+
+		TypeTypedef tc = cast(TypeTypedef)tinfo;
+		TypedefDeclaration sd = tc.sym;
+		//printf("basetype = %s\n", sd.basetype.toChars());
+
+		/* Put out:
+		 *	TypeInfo base;
+		 *	char[] name;
+		 *	void[] m_init;
+		 */
+
+		sd.basetype = sd.basetype.merge();
+		sd.basetype.getTypeInfo(null);		// generate vtinfo
+		assert(sd.basetype.vtinfo);
+		dtxoff(pdt, sd.basetype.vtinfo.toSymbol(), 0, TYnptr);	// TypeInfo for basetype
+
+		string name = sd.toPrettyChars();
+		size_t namelen = name.length;
+		dtdword(pdt, namelen);
+		dtabytes(pdt, TYnptr, 0, namelen + 1, toStringz(name));
+
+		// void[] init;
+		if (tinfo.isZeroInit(Loc(0)) || !sd.init)
+		{	
+			// 0 initializer, or the same as the base type
+			dtdword(pdt, 0);	// init.length
+			dtdword(pdt, 0);	// init.ptr
+		}
+		else
+		{
+			dtdword(pdt, cast(int)sd.type.size());	// init.length
+			dtxoff(pdt, sd.toInitializer(), 0, TYnptr);	// init.ptr
+		}
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInstance.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,118 @@
+module dmd.TypeInstance;
+
+import dmd.TypeQualified;
+import dmd.TemplateInstance;
+import dmd.MOD;
+import dmd.MATCH;
+import dmd.Loc;
+import dmd.Global;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Dsymbol;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.ArrayTypes;
+import dmd.TY;
+
+/* Similar to TypeIdentifier, but with a TemplateInstance as the root
+ */
+class TypeInstance : TypeQualified
+{
+    TemplateInstance tempinst;
+
+    this(Loc loc, TemplateInstance tempinst)
+	{
+		super(Tinstance, loc);
+		this.tempinst = tempinst;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    //char *toChars();
+	
+    //void toDecoBuffer(OutBuffer *buf, int flag);
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		// Note close similarity to TypeIdentifier::resolve()
+		Dsymbol s;
+
+		*pe = null;
+		*pt = null;
+		*ps = null;
+
+	static if (false) {
+		if (!idents.dim)
+		{
+			error(loc, "template instance '%s' has no identifier", toChars());
+			return;
+		}
+	}
+		//id = (Identifier *)idents.data[0];
+		//printf("TypeInstance::resolve(sc = %p, idents = '%s')\n", sc, id->toChars());
+		s = tempinst;
+		if (s)
+			s.semantic(sc);
+		resolveHelper(loc, sc, s, null, pe, pt, ps);
+		if (*pt)
+			*pt = (*pt).addMod(mod);
+		//printf("pt = '%s'\n", (*pt)->toChars());
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		Type t;
+		Expression e;
+		Dsymbol s;
+
+		//printf("TypeInstance::semantic(%s)\n", toChars());
+
+		if (sc.parameterSpecialization)
+		{
+			uint errors = global.errors;
+			global.gag++;
+
+			resolve(loc, sc, &e, &t, &s);
+
+			global.gag--;
+			if (errors != global.errors)
+			{   
+				if (global.gag == 0)
+					global.errors = errors;
+
+				return null;
+			}
+		}
+		else
+			resolve(loc, sc, &e, &t, &s);
+
+		return s;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeNext.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,137 @@
+module dmd.TypeNext;
+
+import dmd.Type;
+import dmd.TY;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.MATCH;
+import dmd.MOD;
+
+class TypeNext : Type
+{
+    Type next;
+
+    this(TY ty, Type next)
+	{
+		super(ty);
+		this.next = next;
+	}
+version (DumbClone) {
+} else {
+	final TypeNext cloneTo(TypeNext t)
+	{
+		super.cloneTo(t);
+		return t;
+	}
+
+	TypeNext clone()
+	{
+		assert(this.classinfo == TypeNext.classinfo);
+		return cloneTo(new TypeNext(ty, next));
+	}
+}
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		super.toDecoBuffer(buf, flag);
+		assert(next !is this);
+		//printf("this = %p, ty = %d, next = %p, ty = %d\n", this, this.ty, next, next.ty);
+		next.toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
+	}
+
+    void checkDeprecated(Loc loc, Scope sc)
+	{
+		Type.checkDeprecated(loc, sc);
+		if (next)	// next can be null if TypeFunction and auto return type
+			next.checkDeprecated(loc, sc);
+	}
+	
+    Type reliesOnTident()
+	{
+		return next.reliesOnTident();
+	}
+	
+    Type nextOf()
+	{
+		return next;
+	}
+	
+    Type makeConst()
+	{
+		//printf("TypeNext::makeConst() %p, %s\n", this, toChars());
+		if (cto)
+		{
+			assert(cto.mod == MOD.MODconst);
+			return cto;
+		}
+		
+		TypeNext t = cast(TypeNext)super.makeConst();
+		if (ty != TY.Tfunction && ty != TY.Tdelegate &&
+			(next.deco || next.ty == TY.Tfunction) &&
+			!next.isInvariant() && !next.isConst())
+		{
+			if (next.isShared())
+				t.next = next.sharedConstOf();
+			else
+				t.next = next.constOf();
+		}
+		//printf("TypeNext::makeConst() returns %p, %s\n", t, t.toChars());
+		return t;
+	}
+	
+    Type makeInvariant()
+	{
+		//printf("TypeNext::makeInvariant() %s\n", toChars());
+		if (ito)
+		{	
+			assert(ito.isInvariant());
+			return ito;
+		}
+		TypeNext t = cast(TypeNext)Type.makeInvariant();
+		if (ty != TY.Tfunction && ty != TY.Tdelegate && (next.deco || next.ty == TY.Tfunction) && !next.isInvariant())
+		{	
+			t.next = next.invariantOf();
+		}
+		return t;
+	}
+	
+    Type makeShared()
+	{
+		//printf("TypeNext::makeShared() %s\n", toChars());
+		if (sto)
+		{	
+			assert(sto.mod == MODshared);
+			return sto;
+		}    
+		TypeNext t = cast(TypeNext)Type.makeShared();
+		if (ty != Tfunction && ty != Tdelegate &&
+			(next.deco || next.ty == Tfunction) &&
+			!next.isInvariant() && !next.isShared())
+		{
+			if (next.isConst())
+				t.next = next.sharedConstOf();
+			else
+				t.next = next.sharedOf();
+		}
+
+		//printf("TypeNext::makeShared() returns %p, %s\n", t, t.toChars());
+		return t;
+	}
+	
+    Type makeSharedConst()
+	{
+		assert(false);
+	}
+	
+    MATCH constConv(Type to)
+	{
+		assert(false);
+	}
+	
+    void transitive()
+	{
+		/* Invoke transitivity of type attributes
+		 */
+		next = next.addMod(mod);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypePointer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,200 @@
+module dmd.TypePointer;
+
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.TypeNext;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.MATCH;
+import dmd.Expression;
+import dmd.NullExp;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeInfoPointerDeclaration;
+import dmd.CppMangleState;
+import dmd.TY;
+import dmd.Util;
+import dmd.MOD;
+import dmd.Global;
+
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+
+class TypePointer : TypeNext
+{
+    this(Type t)
+	{
+		super(TY.Tpointer, t);
+	}
+version (DumbClone) {
+} else {		
+	final TypePointer cloneTo(TypePointer t)
+	{
+		super.cloneTo(t);
+		return t;
+	}
+
+	TypePointer clone()
+	{
+		assert(this.classinfo == TypePointer.classinfo);
+		return cloneTo(new TypePointer(next));
+	}
+}
+    Type syntaxCopy()
+	{
+		Type t = next.syntaxCopy();
+		if (t == next)
+			t = this;
+		else
+		{	
+			t = new TypePointer(t);
+			t.mod = mod;
+		}
+		return t;
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypePointer.semantic()\n");
+		if (deco)
+			return this;
+		Type n = next.semantic(loc, sc);
+		switch (n.toBasetype().ty)
+		{
+			case TY.Ttuple:
+				error(loc, "can't have pointer to %s", n.toChars());
+				n = tint32;
+				break;
+			default:
+				break;
+		}
+		if (n !is next)
+		{
+			deco = null;
+		}
+		next = n;
+		transitive();
+		return merge();
+	}
+	
+    ulong size(Loc loc)
+	{
+		return PTRSIZE;
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		//printf("TypePointer::toCBuffer2() next = %d\n", next->ty);
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		next.toCBuffer2(buf, hgs, this.mod);
+		if (next.ty != Tfunction)
+			buf.writeByte('*');
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("TypePointer.implicitConvTo(to = %s) %s\n", to.toChars(), toChars());
+
+		if (equals(to))
+			return MATCH.MATCHexact;
+		if (to.ty == TY.Tpointer)
+		{	
+			TypePointer tp = cast(TypePointer)to;
+			assert(tp.next);
+
+			if (!(next.mod == tp.next.mod || tp.next.mod == MOD.MODconst))
+				return MATCH.MATCHnomatch;        // not const-compatible
+
+			/* Alloc conversion to void[]
+			 */
+			if (next.ty != TY.Tvoid && tp.next.ty == TY.Tvoid)
+			{
+				return MATCH.MATCHconvert;
+			}
+
+			MATCH m = next.constConv(tp.next);
+			if (m != MATCH.MATCHnomatch)
+			{
+				if (m == MATCH.MATCHexact && mod != to.mod)
+					m = MATCH.MATCHconst;
+				return m;
+			}
+
+			/* Conversion of ptr to derived to ptr to base
+			 */
+			int offset = 0;
+			if (tp.next.isBaseOf(next, &offset) && offset == 0)
+				return MATCH.MATCHconvert;
+		}
+		return MATCH.MATCHnomatch;
+	}
+	
+    bool isscalar()
+	{
+		return true;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypePointer::defaultInit() '%s'\n", toChars());
+	}
+		Expression e = new NullExp(loc);
+		e.type = this;
+		return e;
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return true;
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		return new TypeInfoPointerDeclaration(this);
+	}
+	
+    bool hasPointers()
+	{
+		return true;
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		type* tn;
+		type* t;
+
+		//printf("TypePointer.toCtype() %s\n", toChars());
+		if (ctype)
+			return ctype;
+
+		if (1 || global.params.symdebug)
+		{	/* Need to always do this, otherwise C++ name mangling
+			 * goes awry.
+			 */
+			t = type_alloc(TYM.TYnptr);
+			ctype = t;
+			tn = next.toCtype();
+			t.Tnext = tn;
+			tn.Tcount++;
+		}
+		else
+			t = type_fake(totym());
+
+		t.Tcount++;
+		ctype = t;
+		return t;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeQualified.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,271 @@
+module dmd.TypeQualified;
+
+import dmd.Type;
+import dmd.Import;
+import dmd.TypeExp;
+import dmd.DotIdExp;
+import dmd.VarDeclaration;
+import dmd.EnumMember;
+import dmd.TupleDeclaration;
+import dmd.Id;
+import dmd.VarExp;
+import dmd.TemplateInstance;
+import dmd.Loc;
+import dmd.Array;
+import dmd.TY;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.DYNCAST;
+import dmd.Expression;
+import dmd.Util;
+
+class TypeQualified : Type
+{
+    Loc loc;
+    Array idents;	// array of Identifier's representing ident.ident.ident etc.
+
+    this(TY ty, Loc loc)
+	{
+		super(ty);
+		this.loc = loc;
+		
+		idents = new Array();
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}	
+    void syntaxCopyHelper(TypeQualified t)
+	{
+		//printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t->toChars(), toChars());
+		idents.setDim(t.idents.dim);
+		for (int i = 0; i < idents.dim; i++)
+		{
+			Identifier id = cast(Identifier)t.idents.data[i];
+			if (id.dyncast() == DYNCAST.DYNCAST_DSYMBOL)
+			{
+				TemplateInstance ti = cast(TemplateInstance)id;
+
+				ti = cast(TemplateInstance)ti.syntaxCopy(null);
+				id = cast(Identifier)ti;
+			}
+
+			idents.data[i] = cast(void*)id;
+		}
+	}
+	
+    void addIdent(Identifier ident)
+	{
+		idents.push(cast(void*)ident);
+	}
+	
+    void toCBuffer2Helper(OutBuffer buf, HdrGenState* hgs)
+	{
+		int i;
+
+		for (i = 0; i < idents.dim; i++)
+		{
+			Identifier id = cast(Identifier)idents.data[i];
+			buf.writeByte('.');
+
+			if (id.dyncast() == DYNCAST.DYNCAST_DSYMBOL)
+			{
+				TemplateInstance ti = cast(TemplateInstance)id;
+				ti.toCBuffer(buf, hgs);
+			} else {
+				buf.writestring(id.toChars());
+			}
+		}
+	}
+	
+    ulong size(Loc loc)
+	{
+		assert(false);
+	}
+	
+	/*************************************
+	* Takes an array of Identifiers and figures out if
+	 * it represents a Type or an Expression.
+	 * Output:
+	 *	if expression, *pe is set
+	 *	if type, *pt is set
+	 */
+    void resolveHelper(Loc loc, Scope sc, Dsymbol s, Dsymbol scopesym, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		VarDeclaration v;
+		EnumMember em;
+		TupleDeclaration td;
+		Expression e;
+
+static if (false) {
+		printf("TypeQualified.resolveHelper(sc = %p, idents = '%s')\n", sc, toChars());
+		if (scopesym)
+			printf("\tscopesym = '%s'\n", scopesym.toChars());
+}
+		*pe = null;
+		*pt = null;
+		*ps = null;
+		if (s)
+		{
+			//printf("\t1: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
+			s.checkDeprecated(loc, sc);		// check for deprecated aliases
+			s = s.toAlias();
+			//printf("\t2: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
+			for (int i = 0; i < idents.dim; i++)
+			{
+				Identifier id = cast(Identifier)idents.data[i];
+				Dsymbol sm = s.searchX(loc, sc, id);
+				//printf("\t3: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
+				//printf("\tgetType = '%s'\n", s.getType().toChars());
+				if (!sm)
+				{	
+					Type t;
+
+					v = s.isVarDeclaration();
+					if (v && id == Id.length)
+					{
+						e = v.getConstInitializer();
+						if (!e)
+							e = new VarExp(loc, v);
+						t = e.type;
+						if (!t)
+						goto Lerror;
+						goto L3;
+					}
+					t = s.getType();
+					if (!t && s.isDeclaration())
+						t = s.isDeclaration().type;
+					if (t)
+					{
+						sm = t.toDsymbol(sc);
+						if (sm)
+						{	sm = sm.search(loc, id, 0);
+						if (sm)
+							goto L2;
+						}
+						//e = t.getProperty(loc, id);
+						e = new TypeExp(loc, t);
+						e = t.dotExp(sc, e, id);
+						i++;
+					L3:
+						for (; i < idents.dim; i++)
+						{
+							id = cast(Identifier)idents.data[i];
+							//printf("e: '%s', id: '%s', type = %p\n", e.toChars(), id.toChars(), e.type);
+							if (id == Id.offsetof)
+							{   e = new DotIdExp(e.loc, e, id);
+								e = e.semantic(sc);
+							}
+							else
+								e = e.type.dotExp(sc, e, id);
+						}
+						*pe = e;
+					}
+					else
+					  Lerror:
+						error(loc, "identifier '%s' of '%s' is not defined", id.toChars(), toChars());
+					return;
+				}
+			L2:
+				s = sm.toAlias();
+			}
+
+			v = s.isVarDeclaration();
+			if (v)
+			{
+///static if (false) {
+///				// It's not a type, it's an expression
+///				Expression *e = v.getConstInitializer();
+///				if (e)
+///				{
+///					*pe = e.copy();	// make copy so we can change loc
+///					(*pe).loc = loc;
+///				}
+///				else
+///}
+				{
+///static if (false) {
+///					WithScopeSymbol withsym;
+///					if (scopesym && (withsym = scopesym.isWithScopeSymbol()) !is null)
+///					{
+///						// Same as wthis.ident
+///						e = new VarExp(loc, withsym.withstate.wthis);
+///						e = new DotIdExp(loc, e, ident);
+///						//assert(0);	// BUG: should handle this
+///					}
+///					else
+///}
+						*pe = new VarExp(loc, v);
+				}
+				return;
+			}
+			em = s.isEnumMember();
+			if (em)
+			{
+				// It's not a type, it's an expression
+				*pe = em.value.copy();
+				return;
+			}
+
+		L1:
+			Type t = s.getType();
+			if (!t)
+			{
+				// If the symbol is an import, try looking inside the import
+				Import si;
+
+				si = s.isImport();
+				if (si)
+				{
+					s = si.search(loc, s.ident, 0);
+					if (s && s != si)
+						goto L1;
+					s = si;
+				}
+				*ps = s;
+				return;
+			}
+			if (t.ty == TY.Tinstance && t != this && !t.deco)
+			{   
+				error(loc, "forward reference to '%s'", t.toChars());
+				return;
+			}
+
+			if (t != this)
+			{
+				if (t.reliesOnTident())
+				{
+					Scope scx;
+
+					for (scx = sc; 1; scx = scx.enclosing)
+					{
+						if (!scx)
+						{   
+							error(loc, "forward reference to '%s'", t.toChars());
+							return;
+						}
+						if (scx.scopesym == scopesym)
+							break;
+					}
+					t = t.semantic(loc, scx);
+					//((TypeIdentifier *)t).resolve(loc, scx, pe, &t, ps);
+				}
+			}
+			if (t.ty == TY.Ttuple)
+				*pt = t;
+			else
+				*pt = t.merge();
+		}
+		if (!s)
+		{
+			error(loc, "identifier '%s' is not defined", toChars());
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeReference.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,72 @@
+module dmd.TypeReference;
+
+import dmd.Type;
+import dmd.MOD;
+import dmd.TypeNext;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.CppMangleState;
+import dmd.TY;
+
+class TypeReference : TypeNext
+{
+    this(Type t)
+	{
+		super(TY.init, null);
+		assert(false);
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+	
+    ulong size(Loc loc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+		assert(false);
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+		assert(false);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		assert(false);
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeReturn.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,91 @@
+module dmd.TypeReturn;
+
+import dmd.Loc;
+import dmd.MOD;
+import dmd.Type;
+import dmd.TypeQualified;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.TY;
+
+class TypeReturn : TypeQualified
+{
+    this(Loc loc)
+	{
+		super(TY.Treturn, loc);
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	
+    Type syntaxCopy()
+	{
+		TypeReturn t = new TypeReturn(loc);
+		t.syntaxCopyHelper(this);
+		t.mod = mod;
+		return t;
+	}
+
+    Dsymbol toDsymbol(Scope sc)
+	{
+		Type *t = semantic(0, sc);
+		if (t == this)
+			return null;
+		return t.toDsymbol(sc);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		Type t;
+		if (!sc.func)
+		{	
+			error(loc, "typeof(return) must be inside function");
+			goto Lerr;
+		}
+		t = sc.func.type.nextOf();
+		t = t.addMod(mod);
+
+		if (idents.dim)
+		{
+			Dsymbol s = t.toDsymbol(sc);
+			for (size_t i = 0; i < idents.dim; i++)
+			{
+				if (!s)
+					break;
+				Identifier id = cast(Identifier)idents.data[i];
+				s = s.searchX(loc, sc, id);
+			}
+			if (s)
+			{
+				t = s.getType();
+				if (!t)
+				{	
+					error(loc, "%s is not a type", s.toChars());
+					goto Lerr;
+				}
+			}
+			else
+			{   
+				error(loc, "cannot resolve .property for %s", toChars());
+				goto Lerr;
+			}
+		}
+
+		return t;
+
+	Lerr:
+		return terror;
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeSArray.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,455 @@
+module dmd.TypeSArray;
+
+import dmd.TypeArray;
+import dmd.MOD;
+import dmd.Argument;
+import dmd.TypeStruct;
+import dmd.TypeTuple;
+import dmd.VarExp;
+import dmd.IntegerExp;
+import dmd.Expression;
+import dmd.Type;
+import dmd.TupleDeclaration;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.STC;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.TypeDArray;
+import dmd.TypePointer;
+import dmd.ArrayTypes;
+import dmd.WANT;
+import dmd.TypeInfoDeclaration;
+import dmd.TY;
+import dmd.Util;
+import dmd.Id;
+
+import dmd.type.Util;
+
+import dmd.backend.dt_t;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.DT;
+
+// Static array, one with a fixed dimension
+class TypeSArray : TypeArray
+{
+    Expression dim;
+
+    this(Type t, Expression dim)
+	{
+		super(TY.Tsarray, t);
+		//printf("TypeSArray(%s)\n", dim.toChars());
+		this.dim = dim;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+
+    ulong size(Loc loc)
+	{
+		if (!dim)
+			return Type.size(loc);
+
+		long sz = dim.toInteger();
+
+		{	
+			long n, n2;
+			n = next.size();
+			n2 = n * sz;
+			if (n && (n2 / n) != sz)
+				goto Loverflow;
+
+			sz = n2;
+		}
+		return sz;
+
+	Loverflow:
+		error(loc, "index %jd overflow for static array", sz);
+		return 1;
+	}
+	
+    uint alignsize()
+	{
+		return next.alignsize();
+	}
+
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeSArray.semantic() %s\n", toChars());
+
+		Type t;
+		Expression e;
+		Dsymbol s;
+		next.resolve(loc, sc, &e, &t, &s);
+		if (dim && s && s.isTupleDeclaration())
+		{	
+			TupleDeclaration sd = s.isTupleDeclaration();
+
+			dim = semanticLength(sc, sd, dim);
+			dim = dim.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			ulong d = dim.toUInteger();
+
+			if (d >= sd.objects.dim)
+			{   error(loc, "tuple index %ju exceeds %u", d, sd.objects.dim);
+				return Type.terror;
+			}
+			///Object o = cast(Object)sd.objects.data[(size_t)d];
+			///if (o.dyncast() != DYNCAST_TYPE)
+			///{   
+			///	error(loc, "%s is not a type", toChars());
+			///	return Type.terror;
+			///}
+			///t = cast(Type)o;
+			
+			t = cast(Type)sd.objects.data[cast(size_t)d];
+			if (t is null) {
+				error(loc, "%s is not a type", toChars());
+				return Type.terror;
+			}
+			return t;
+		}
+
+		next = next.semantic(loc,sc);
+		transitive();
+
+		Type tbn = next.toBasetype();
+
+		if (dim)
+		{	
+			long n, n2;
+
+		dim = semanticLength(sc, tbn, dim);
+
+		dim = dim.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		if (sc && sc.parameterSpecialization && dim.op == TOK.TOKvar &&
+			(cast(VarExp)dim).var.storage_class & STC.STCtemplateparameter)
+		{
+			/* It could be a template parameter N which has no value yet:
+			 *   template Foo(T : T[N], size_t N);
+			 */
+			return this;
+		}
+		long d1 = dim.toInteger();
+		dim = dim.castTo(sc, tsize_t);
+		dim = dim.optimize(WANT.WANTvalue);
+		long d2 = dim.toInteger();
+
+		if (d1 != d2)
+			goto Loverflow;
+
+		if (tbn.isintegral() ||
+			 tbn.isfloating() ||
+			 tbn.ty == TY.Tpointer ||
+			 tbn.ty == TY.Tarray ||
+			 tbn.ty == TY.Tsarray ||
+			 tbn.ty == TY.Taarray ||
+			 tbn.ty == TY.Tclass)
+		{
+			/* Only do this for types that don't need to have semantic()
+			 * run on them for the size, since they may be forward referenced.
+			 */
+			n = tbn.size(loc);
+			n2 = n * d2;
+			if (cast(int)n2 < 0)
+			goto Loverflow;
+			if (n2 >= 0x1000000)	// put a 'reasonable' limit on it
+			goto Loverflow;
+			if (n && n2 / n != d2)
+			{
+			  Loverflow:
+			error(loc, "index %jd overflow for static array", d1);
+			dim = new IntegerExp(Loc(0), 1, tsize_t);
+			}
+		}
+		}
+		switch (tbn.ty)
+		{
+			case TY.Ttuple:
+			{   // Index the tuple to get the type
+				assert(dim);
+				TypeTuple tt = cast(TypeTuple)tbn;
+				ulong d = dim.toUInteger();
+
+				if (d >= tt.arguments.dim)
+				{	
+					error(loc, "tuple index %ju exceeds %u", d, tt.arguments.dim);
+					return Type.terror;
+				}
+				Argument arg = cast(Argument)tt.arguments.data[cast(size_t)d];
+				return arg.type;
+			}
+			case TY.Tstruct:
+			{   TypeStruct ts = cast(TypeStruct)tbn;
+				if (ts.sym.isnested)
+				error(loc, "cannot have array of inner structs %s", ts.toChars());
+				break;
+			}
+			case TY.Tfunction:
+			case TY.Tnone:
+				error(loc, "can't have array of %s", tbn.toChars());
+				tbn = next = tint32;
+				break;
+			default:		///
+				break;
+		}
+		if (tbn.isauto())
+			error(loc, "cannot have array of auto %s", tbn.toChars());
+		return merge();
+	}
+
+    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		assert(false);
+	}
+
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		Type.toDecoBuffer(buf, flag);
+		if (dim)
+			//buf.printf("%ju", dim.toInteger());	///
+			buf.printf("%s", dim.toInteger());
+		if (next)
+			/* Note that static arrays are value types, so
+			 * for a parameter, propagate the 0x100 to the next
+			 * level, since for T[4][3], any const should apply to the T,
+			 * not the [4].
+			 */
+			next.toDecoBuffer(buf,  (flag & 0x100) ? flag : mod);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+	version (LOGDOTEXP) {
+		printf("TypeSArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+	}
+		if (ident == Id.length)
+		{
+			e = dim;
+		}
+		else if (ident == Id.ptr)
+		{
+			e = e.castTo(sc, next.pointerTo());
+		}
+		else
+		{
+			e = TypeArray.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+    int isString()
+	{
+		assert(false);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return next.isZeroInit(loc);
+	}
+	
+    uint memalign(uint salign)
+	{
+		return next.memalign(salign);
+	}
+	
+    MATCH constConv(Type to)
+	{
+		assert(false);
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("TypeSArray.implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
+
+		// Allow implicit conversion of static array to pointer or dynamic array
+		if (IMPLICIT_ARRAY_TO_PTR && to.ty == Tpointer)
+		{
+			TypePointer tp = cast(TypePointer)to;
+
+			if (next.mod != tp.next.mod && tp.next.mod != MODconst)
+				return MATCHnomatch;
+
+			if (tp.next.ty == Tvoid || next.constConv(tp.next) != MATCHnomatch)
+			{
+				return MATCHconvert;
+			}
+			return MATCHnomatch;
+		}
+		if (to.ty == Tarray)
+		{
+			int offset = 0;
+			TypeDArray ta = cast(TypeDArray)to;
+
+			if (next.mod != ta.next.mod && ta.next.mod != MODconst)
+				return MATCHnomatch;
+
+			if (next.equals(ta.next) ||
+				next.implicitConvTo(ta.next) >= MATCHconst ||
+				(ta.next.isBaseOf(next, &offset) && offset == 0) ||
+				ta.next.ty == Tvoid
+			)
+				return MATCHconvert;
+
+			return MATCHnomatch;
+		}
+		if (to.ty == Tsarray)
+		{
+			if (this == to)
+				return MATCHexact;
+
+			TypeSArray tsa = cast(TypeSArray)to;
+
+			if (dim.equals(tsa.dim))
+			{
+				/* Since static arrays are value types, allow
+				 * conversions from const elements to non-const
+				 * ones, just like we allow conversion from const int
+				 * to int.
+				 */
+				MATCH m = next.implicitConvTo(tsa.next);
+				if (m >= MATCHconst)
+				{
+					if (mod != to.mod)
+						m = MATCHconst;
+					return m;
+				}
+			}
+		}
+		return MATCHnomatch;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypeSArray.defaultInit() '%s'\n", toChars());
+	}
+		return next.defaultInit(loc);
+	}
+	
+    dt_t** toDt(dt_t** pdt)
+	{
+		return toDtElem(pdt, null);
+	}
+	
+    dt_t** toDtElem(dt_t** pdt, Expression e)
+	{
+		int i;
+
+		//printf("TypeSArray::toDtElem()\n");
+		uint len = cast(uint)dim.toInteger();
+		if (len)
+		{
+			while (*pdt)
+				pdt = &((*pdt).DTnext);
+			Type tnext = next;
+			Type tbn = tnext.toBasetype();
+			while (tbn.ty == Tsarray)
+			{   
+				TypeSArray tsa = cast(TypeSArray)tbn;
+
+				len *= tsa.dim.toInteger();
+				tnext = tbn.nextOf();
+				tbn = tnext.toBasetype();
+			}
+			if (!e)				// if not already supplied
+				e = tnext.defaultInit(Loc(0));	// use default initializer
+			if (tbn.ty == Tstruct)
+				tnext.toDt(pdt);
+			else
+				e.toDt(pdt);
+			dt_optimize(*pdt);
+			if ((*pdt).dt == DT_azeros && !(*pdt).DTnext)
+			{
+				(*pdt).DTazeros *= len;
+				pdt = &((*pdt).DTnext);
+			}
+			else if ((*pdt).dt == DT_1byte && (*pdt).DTonebyte == 0 && !(*pdt).DTnext)
+			{
+				(*pdt).dt = DT_azeros;
+				(*pdt).DTazeros = len;
+				pdt = &((*pdt).DTnext);
+			}
+			else if (e.op != TOKstring)
+			{
+				for (i = 1; i < len; i++)
+				{
+					if (tbn.ty == Tstruct)
+					{   
+						pdt = tnext.toDt(pdt);
+						while (*pdt)
+							pdt = &((*pdt).DTnext);
+					}
+					else
+						pdt = e.toDt(pdt);
+				}
+			}
+		}
+		return pdt;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		assert(false);
+	}
+	
+    Expression toExpression()
+	{
+		assert(false);
+	}
+	
+    bool hasPointers()
+	{
+		return next.hasPointers();
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		if (!ctype)
+		{
+			type* tn = next.toCtype();
+			ctype = type_allocn(TYarray, tn);
+			ctype.Tdim = cast(uint)dim.toInteger();
+		}
+
+		return ctype;
+	}
+	
+    type* toCParamtype()
+	{
+		// arrays are passed as pointers
+		return next.pointerTo().toCtype();
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeSlice.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,52 @@
+module dmd.TypeSlice;
+
+import dmd.Type;
+import dmd.TypeNext;
+import dmd.MOD;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.TY;
+
+class TypeSlice : TypeNext
+{
+    Expression lwr;
+    Expression upr;
+
+    this(Type next, Expression lwr, Expression upr)
+	{
+		super(TY.init, null);
+		assert(false);
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+	
+    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeStruct.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,589 @@
+module dmd.TypeStruct;
+
+import dmd.Type;
+import dmd.StructDeclaration;
+import dmd.Declaration;
+import dmd.STC;
+import dmd.MOD;
+import dmd.OutBuffer;
+import dmd.DotVarExp;
+import dmd.TemplateMixin;
+import dmd.DotTemplateExp;
+import dmd.DsymbolExp;
+import dmd.TypeExp;
+import dmd.EnumMember;
+import dmd.Id;
+import dmd.DotIdExp;
+import dmd.ScopeExp;
+import dmd.TupleExp;
+import dmd.TemplateDeclaration;
+import dmd.OverloadSet;
+import dmd.Import;
+import dmd.DotExp;
+import dmd.ErrorExp;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.ArrayTypes;
+import dmd.TemplateInstance;
+import dmd.FuncDeclaration;
+import dmd.VarExp;
+import dmd.CommaExp;
+import dmd.ThisExp;
+import dmd.SymbolDeclaration;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeInfoStructDeclaration;
+import dmd.TY;
+import dmd.TOK;
+import dmd.Global;
+import dmd.VarDeclaration;
+import dmd.Util;
+import dmd.expression.Util;
+
+import dmd.backend.TYPE;
+import dmd.backend.dt_t;
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.backend.STR;
+import dmd.backend.TYM;
+import dmd.backend.Classsym;
+import dmd.backend.SC;
+import dmd.backend.LIST;
+
+import std.string : toStringz;
+
+class TypeStruct : Type
+{
+    StructDeclaration sym;
+
+    this(StructDeclaration sym)
+	{
+		super(TY.Tstruct);
+		this.sym = sym;
+	}
+version (DumbClone) {
+} else {	
+	final TypeStruct cloneTo(TypeStruct t)
+	{
+		super.cloneTo(t);
+		assert(t.sym is sym);
+		return t;
+	}
+	
+	TypeStruct clone()
+	{
+		assert(this.classinfo == TypeStruct.classinfo);
+		return cloneTo(new TypeStruct(sym));
+	}
+}
+    ulong size(Loc loc)
+	{
+		return sym.size(loc);
+	}
+	
+    uint alignsize()
+	{
+		uint sz;
+
+		sym.size(Loc(0));		// give error for forward references
+		sz = sym.alignsize;
+		if (sz > sym.structalign)
+			sz = sym.structalign;
+		return sz;
+	}
+	
+    string toChars()
+	{
+		assert(false);
+	}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeStruct.semantic('%s')\n", sym.toChars());
+
+		/* Cannot do semantic for sym because scope chain may not
+		 * be right.
+		 */
+		//sym.semantic(sc);
+
+		return merge();
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		return sym;
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		string name = sym.mangle();
+		//printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", toChars(), name);
+		Type.toDecoBuffer(buf, flag);
+		buf.printf("%s", name);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		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());
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+		uint offset;
+
+		VarDeclaration v;
+		Dsymbol s;
+		DotVarExp de;
+		Declaration d;
+
+	version (LOGDOTEXP) {
+		printf("TypeStruct.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+	}
+		if (!sym.members)
+		{
+			error(e.loc, "struct %s is forward referenced", sym.toChars());
+			return new ErrorExp();
+		}
+
+		/* If e.tupleof
+		 */
+		if (ident is Id.tupleof_)
+		{
+			/* Create a TupleExp out of the fields of the struct e:
+			 * (e.field0, e.field1, e.field2, ...)
+			 */
+			e = e.semantic(sc);	// do this before turning on noaccesscheck
+			Expressions exps = new Expressions;
+			exps.reserve(sym.fields.dim);
+			for (size_t i = 0; i < sym.fields.dim; i++)
+			{   
+				VarDeclaration v2 = cast(VarDeclaration)sym.fields.data[i];
+				Expression fe = new DotVarExp(e.loc, e, v2);
+				exps.push(cast(void*)fe);
+			}
+			e = new TupleExp(e.loc, exps);
+			sc = sc.push();
+			sc.noaccesscheck = 1;
+			e = e.semantic(sc);
+			sc.pop();
+			return e;
+		}
+
+		if (e.op == TOK.TOKdotexp)
+		{	
+			DotExp de2 = cast(DotExp)e;
+
+			if (de2.e1.op == TOK.TOKimport)
+			{
+				assert(0);	// cannot find a case where this happens; leave
+					// assert in until we do
+				ScopeExp se = cast(ScopeExp)de2.e1;
+
+				s = se.sds.search(e.loc, ident, 0);
+				e = de2.e1;
+				goto L1;
+			}
+		}
+
+		s = sym.search(e.loc, ident, 0);
+	L1:
+		if (!s)
+		{
+			if (ident !is Id.__sizeof &&
+				ident !is Id.alignof_ &&
+				ident !is Id.init_ &&
+				ident !is Id.mangleof_ &&
+				ident !is Id.stringof_ &&
+				ident !is Id.offsetof)
+			{
+				/* See if we should forward to the alias this.
+				 */
+				if (sym.aliasthis)
+				{	
+					/* Rewrite e.ident as:
+					 *	e.aliasthis.ident
+					 */
+					e = new DotIdExp(e.loc, e, sym.aliasthis.ident);
+					e = new DotIdExp(e.loc, e, ident);
+					return e.semantic(sc);
+				}
+
+				/* Look for overloaded opDot() to see if we should forward request
+				 * to it.
+				 */
+				Dsymbol fd = search_function(sym, Id.opDot);
+				if (fd)
+				{   
+					/* Rewrite e.ident as:
+					 *	e.opId().ident
+					 */
+					e = build_overload(e.loc, sc, e, null, fd.ident);
+					e = new DotIdExp(e.loc, e, ident);
+					return e.semantic(sc);
+				}
+			}
+
+			return Type.dotExp(sc, e, ident);
+		}
+
+		if (!s.isFuncDeclaration())	// because of overloading
+			s.checkDeprecated(e.loc, sc);
+
+		s = s.toAlias();
+
+		v = s.isVarDeclaration();
+		if (v && !v.isDataseg())
+		{
+			Expression ei = v.getConstInitializer();
+			if (ei)
+			{   
+				e = ei.copy();	// need to copy it if it's a StringExp
+				e = e.semantic(sc);
+				return e;
+			}
+		}
+
+		if (s.getType())
+		{
+			//return new DotTypeExp(e.loc, e, s);
+			return new TypeExp(e.loc, s.getType());
+		}
+
+		EnumMember em = s.isEnumMember();
+		if (em)
+		{
+			assert(em.value);
+			return em.value.copy();
+		}
+
+		TemplateMixin tm = s.isTemplateMixin();
+		if (tm)
+		{
+			Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, tm));
+			de2.type = e.type;
+			return de2;
+		}
+
+		TemplateDeclaration td = s.isTemplateDeclaration();
+		if (td)
+		{
+			e = new DotTemplateExp(e.loc, e, td);
+			e.semantic(sc);
+			return e;
+		}
+
+		TemplateInstance ti = s.isTemplateInstance();
+		if (ti)
+		{	
+			if (!ti.semanticRun)
+				ti.semantic(sc);
+			s = ti.inst.toAlias();
+			if (!s.isTemplateInstance())
+				goto L1;
+			Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, ti));
+			de2.type = e.type;
+			return de2;
+		}
+
+		Import timp = s.isImport();
+		if (timp)
+		{
+			e = new DsymbolExp(e.loc, s, 0);
+			e = e.semantic(sc);
+			return e;
+		}
+
+		OverloadSet o = s.isOverloadSet();
+		if (o)
+		{	
+			/* We really should allow this, triggered by:
+			 *   template c()
+			 *   {
+			 *		void a();
+			 *		void b () { this.a(); }
+			 *   }
+			 *   struct S
+			 *   {
+			 *		mixin c;
+			 *		mixin c;
+			 *  }
+			 *  alias S e;
+			 */
+			error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars());
+			return new ErrorExp();
+		}
+
+		d = s.isDeclaration();
+
+	debug {
+		if (!d)
+			writef("d = %s '%s'\n", s.kind(), s.toChars());
+	}
+		assert(d);
+
+		if (e.op == TOK.TOKtype)
+		{	
+			FuncDeclaration fd = sc.func;
+
+			if (d.isTupleDeclaration())
+			{
+				e = new TupleExp(e.loc, d.isTupleDeclaration());
+				e = e.semantic(sc);
+				return e;
+			}
+
+			if (d.needThis() && fd && fd.vthis)
+			{
+				e = new DotVarExp(e.loc, new ThisExp(e.loc), d);
+				e = e.semantic(sc);
+				return e;
+			}
+
+			return new VarExp(e.loc, d, 1);
+		}
+
+		if (d.isDataseg())
+		{
+			// (e, d)
+			accessCheck(e.loc, sc, e, d);
+			VarExp ve = new VarExp(e.loc, d);
+			e = new CommaExp(e.loc, e, ve);
+			e.type = d.type;
+			return e;
+		}
+
+		if (v)
+		{
+			if (v.toParent() != sym)
+				sym.error(e.loc, "'%s' is not a member", v.toChars());
+
+			// *(&e + offset)
+			accessCheck(e.loc, sc, e, d);
+static if (false) {
+			Expression b = new AddrExp(e.loc, e);
+			b.type = e.type.pointerTo();
+			b = new AddExp(e.loc, b, new IntegerExp(e.loc, v.offset, Type.tint32));
+			b.type = v.type.pointerTo();
+			b = new PtrExp(e.loc, b);
+			b.type = v.type.addMod(e.type.mod);
+			return b;
+}
+		}
+
+		de = new DotVarExp(e.loc, e, d);
+		return de.semantic(sc);
+	}
+	
+    uint memalign(uint salign)
+	{
+		sym.size(Loc(0));		// give error for forward references
+		return sym.structalign;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+		Symbol* s;
+		Declaration d;
+
+	version (LOGDEFAULTINIT) {
+		printf("TypeStruct::defaultInit() '%s'\n", toChars());
+	}
+		s = sym.toInitializer();
+		d = new SymbolDeclaration(sym.loc, s, sym);
+		assert(d);
+		d.type = this;
+		return new VarExp(sym.loc, d);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return sym.zeroInit;
+	}
+	
+    int isAssignable()
+	{
+		/* If any of the fields are const or invariant,
+		 * then one cannot assign this struct.
+		 */
+		for (size_t i = 0; i < sym.fields.dim; i++)
+		{   
+			VarDeclaration v = cast(VarDeclaration)sym.fields.data[i];
+			if (v.isConst() || v.isInvariant())
+				return false;
+		}
+		return true;
+	}
+	
+    bool checkBoolean()
+	{
+		return false;
+	}
+	
+    dt_t** toDt(dt_t** pdt)
+	{
+		sym.toDt(pdt);
+		return pdt;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		return new TypeInfoStructDeclaration(this);
+	}
+	
+    bool hasPointers()
+	{
+		StructDeclaration s = sym;
+
+		sym.size(Loc(0));		// give error for forward references
+		for (size_t i = 0; i < s.fields.dim; i++)
+		{
+			Dsymbol sm = cast(Dsymbol)s.fields.data[i];
+			Declaration d = sm.isDeclaration();
+			if (d.storage_class & STC.STCref || d.hasPointers())
+				return true;
+		}
+
+		return false;
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		MATCH m;
+
+		//printf("TypeStruct.implicitConvTo(%s => %s)\n", toChars(), to.toChars());
+		if (ty == to.ty && sym == (cast(TypeStruct)to).sym)
+		{	
+			m = MATCHexact;		// exact match
+			if (mod != to.mod)
+			{
+				if (to.mod == MODconst)
+					m = MATCHconst;
+				else
+				{	/* Check all the fields. If they can all be converted,
+					 * allow the conversion.
+					 */
+					for (int i = 0; i < sym.fields.dim; i++)
+					{   
+						Dsymbol s = cast(Dsymbol)sym.fields.data[i];
+						VarDeclaration v = s.isVarDeclaration();
+						assert(v && v.storage_class & STCfield);
+
+						// 'from' type
+						Type tvf = v.type.addMod(mod);
+
+						// 'to' type
+						Type tv = v.type.castMod(to.mod);
+
+						//printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), tvf.implicitConvTo(tv));
+						if (tvf.implicitConvTo(tv) < MATCHconst)
+							return MATCHnomatch;
+					}
+					m = MATCHconst;
+				}
+			}
+		}
+		else if (sym.aliasthis)
+		{
+			m = MATCHnomatch;
+			Declaration d = sym.aliasthis.isDeclaration();
+			if (d)
+			{   
+				assert(d.type);
+				Type t = d.type.addMod(mod);
+				m = t.implicitConvTo(to);
+			}
+		}
+		else
+			m = MATCHnomatch;	// no match
+		return m;
+	}
+	
+    MATCH constConv(Type to)
+	{
+		if (equals(to))
+			return MATCHexact;
+		if (ty == to.ty && sym == (cast(TypeStruct)to).sym && to.mod == MODconst)
+			return MATCHconst;
+		return MATCHnomatch;
+	}
+	
+    Type toHeadMutable()
+	{
+		assert(false);
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		type* t;
+		Symbol* s;
+
+		if (ctype)
+			return ctype;
+
+		//printf("TypeStruct.toCtype() '%s'\n", sym.toChars());
+		s = symbol_calloc(toStringz(sym.toPrettyChars()));
+		s.Sclass = SC.SCstruct;
+		s.Sstruct = struct_calloc();
+		s.Sstruct.Sflags |= 0;	/// huh?
+		s.Sstruct.Salignsize = sym.alignsize;
+		s.Sstruct.Sstructalign = cast(ubyte)sym.structalign;
+		s.Sstruct.Sstructsize = sym.structsize;
+
+		if (sym.isUnionDeclaration())
+			s.Sstruct.Sflags |= STR.STRunion;
+
+		t = type_alloc(TYM.TYstruct);
+		t.Ttag = cast(Classsym*)s;		// structure tag name
+		t.Tcount++;
+		s.Stype = t;
+		slist_add(s);
+		ctype = t;
+
+		/* Add in fields of the struct
+		 * (after setting ctype to avoid infinite recursion)
+		 */
+		if (global.params.symdebug) {
+			for (int i = 0; i < sym.fields.dim; i++)
+			{   
+				VarDeclaration v = cast(VarDeclaration)sym.fields.data[i];
+
+				Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype());
+				s2.Smemoff = v.offset;
+				list_append(&s.Sstruct.Sfldlst, s2);
+			}
+		}
+
+		//printf("t = %p, Tflags = x%x\n", t, t.Tflags);
+		return t;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeTuple.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,78 @@
+module dmd.TypeTuple;
+
+import dmd.Type;
+import dmd.ArrayTypes;
+import dmd.MOD;
+import dmd.TypeInfoDeclaration;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Scope;
+import dmd.TY;
+
+class TypeTuple : Type
+{
+    Arguments arguments;	// types making up the tuple
+
+    this(Arguments arguments)
+	{
+		assert(false);
+		super(TY.init);
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	
+    this(Expressions exps)
+	{
+		assert(false);
+		super(TY.init);
+	}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		assert(false);
+	}
+	
+    int equals(Object *o)
+	{
+		assert(false);
+	}
+	
+    Type reliesOnTident()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		assert(false);
+	}
+	
+    Expression getProperty(Loc loc, Identifier ident)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeTypedef.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,296 @@
+module dmd.TypeTypedef;
+
+import dmd.Type;
+import dmd.TypedefDeclaration;
+import dmd.MOD;
+import dmd.Loc;
+import dmd.Id;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.ArrayTypes;
+import dmd.MATCH;
+import dmd.TypeSArray;
+import dmd.CppMangleState;
+import dmd.TypeInfoDeclaration;
+import dmd.TypeInfoTypedefDeclaration;
+import dmd.TY;
+
+import dmd.backend.TYPE;
+import dmd.backend.dt_t;
+
+class TypeTypedef : Type
+{
+    TypedefDeclaration sym;
+
+    this(TypedefDeclaration sym)
+	{
+		super(Ttypedef);
+		this.sym = sym;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    ulong size(Loc loc)
+	{
+		return sym.basetype.size(loc);
+	}
+	
+    uint alignsize()
+	{
+		assert(false);
+	}
+	
+    string toChars()
+	{
+		assert(false);
+	}
+	
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeTypedef::semantic(%s), sem = %d\n", toChars(), sym->sem);
+		sym.semantic(sc);
+		return merge();
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		return sym;
+	}
+	
+    void toDecoBuffer(OutBuffer buf, int flag)
+	{
+		Type.toDecoBuffer(buf, flag);
+		string name = sym.mangle();
+		buf.printf("%s", name);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+	version (LOGDOTEXP) {
+		printf("TypeTypedef.dotExp(e = '%s', ident = '%s') '%s'\n", e.toChars(), ident.toChars(), toChars());
+	}
+		if (ident is Id.init_)
+		{
+			return Type.dotExp(sc, e, ident);
+		}
+		return sym.basetype.dotExp(sc, e, ident);
+	}
+	
+    Expression getProperty(Loc loc, Identifier ident)
+	{
+		assert(false);
+	}
+	
+    bool isbit()
+	{
+		assert(false);
+	}
+	
+    bool isintegral()
+	{
+		//printf("TypeTypedef::isintegral()\n");
+		//printf("sym = '%s'\n", sym->toChars());
+		//printf("basetype = '%s'\n", sym->basetype->toChars());
+		return sym.basetype.isintegral();
+	}
+	
+    bool isfloating()
+	{
+		return sym.basetype.isfloating();
+	}
+	
+    bool isreal()
+	{
+		return sym.basetype.isreal();
+	}
+	
+    bool isimaginary()
+	{
+		return sym.basetype.isimaginary();
+	}
+	
+    bool iscomplex()
+	{
+		return sym.basetype.iscomplex();
+	}
+	
+    bool isscalar()
+	{
+		return sym.basetype.isscalar();
+	}
+	
+    bool isunsigned()
+	{
+		return sym.basetype.isunsigned();
+	}
+	
+    bool checkBoolean()
+	{
+		assert(false);
+	}
+	
+    int isAssignable()
+	{
+		return sym.basetype.isAssignable();
+	}
+	
+    Type toBasetype()
+	{
+		if (sym.inuse)
+		{
+			sym.error("circular definition");
+			sym.basetype = Type.terror;
+			return Type.terror;
+		}
+		sym.inuse = 1;
+		Type t = sym.basetype.toBasetype();
+		sym.inuse = 0;
+		t = t.addMod(mod);
+		return t;
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		MATCH m;
+
+		//printf("TypeTypedef::implicitConvTo(to = %s) %s\n", to->toChars(), toChars());
+		if (equals(to))
+			m = MATCHexact;		// exact match
+		else if (sym.basetype.implicitConvTo(to))
+			m = MATCHconvert;	// match with conversions
+		else if (ty == to.ty && sym == (cast(TypeTypedef)to).sym)
+		{
+			m = constConv(to);
+		}
+		else
+			m = MATCHnomatch;	// no match
+		return m;
+	}
+	
+    MATCH constConv(Type to)
+	{
+		assert(false);
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+		Expression e;
+		Type bt;
+
+	version (LOGDEFAULTINIT) {
+		printf("TypeTypedef::defaultInit() '%s'\n", toChars());
+	}
+		if (sym.init)
+		{
+			//sym->init->toExpression()->print();
+			return sym.init.toExpression();
+		}
+		bt = sym.basetype;
+		e = bt.defaultInit(loc);
+		e.type = this;
+		while (bt.ty == Tsarray)
+		{	
+			TypeSArray tsa = cast(TypeSArray)bt;
+			e.type = tsa.next;
+			bt = tsa.next.toBasetype();
+		}
+		return e;
+	}
+
+    bool isZeroInit(Loc loc)
+	{
+		if (sym.init)
+		{
+			if (sym.init.isVoidInitializer())
+				return true;		// initialize voids to 0
+			Expression e = sym.init.toExpression();
+			if (e && e.isBool(false))
+				return true;
+
+			return false;		// assume not
+		}
+		if (sym.inuse)
+		{
+			sym.error("circular definition");
+			sym.basetype = Type.terror;
+		}
+		sym.inuse = 1;
+		bool result = sym.basetype.isZeroInit(loc);
+		sym.inuse = 0;
+
+		return result;
+	}
+	
+    dt_t** toDt(dt_t** pdt)
+	{
+		if (sym.init)
+		{
+			dt_t* dt = sym.init.toDt();
+
+			while (*pdt)
+				pdt = &((*pdt).DTnext);
+			*pdt = dt;
+			return pdt;
+		}
+
+		sym.basetype.toDt(pdt);
+		return pdt;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		return new TypeInfoTypedefDeclaration(this);
+	}
+	
+    bool hasPointers()
+	{
+		return toBasetype().hasPointers();
+	}
+	
+    Type toHeadMutable()
+	{
+		assert(false);
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		return sym.basetype.toCtype();
+	}
+	
+    type* toCParamtype()
+	{
+		return sym.basetype.toCParamtype();
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeTypeof.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,167 @@
+module dmd.TypeTypeof;
+
+import dmd.TypeQualified;
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.MOD;
+import dmd.Type;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.TY;
+import dmd.Util;
+import dmd.TOK;
+
+class TypeTypeof : TypeQualified
+{
+    Expression exp;
+
+    this(Loc loc, Expression exp)
+	{
+		super(TY.Ttypeof, loc);
+		this.exp = exp;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Dsymbol toDsymbol(Scope sc)
+	{
+		Type t = semantic(loc, sc);
+		if (t is this)
+			return null;
+
+		return t.toDsymbol(sc);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+
+    Type semantic(Loc loc, Scope sc)
+	{
+		Expression e;
+		Type t;
+
+		//printf("TypeTypeof.semantic() %p\n", this);
+
+		//static int nest; if (++nest == 50) *(char*)0=0;
+
+/+static if (false) {
+		/* Special case for typeof(this) and typeof(super) since both
+		 * should work even if they are not inside a non-static member function
+		 */
+		if (exp.op == TOK.TOKthis || exp.op == TOK.TOKsuper)
+		{
+			/ / Find enclosing struct or class
+			for (Dsymbol *s = sc.parent; 1; s = s.parent)
+			{
+				ClassDeclaration *cd;
+				StructDeclaration *sd;
+
+				if (!s)
+				{
+				error(loc, "%s is not in a struct or class scope", exp.toChars());
+				goto Lerr;
+				}
+				cd = s.isClassDeclaration();
+				if (cd)
+				{
+				if (exp.op == TOK.TOKsuper)
+				{
+					cd = cd.baseClass;
+					if (!cd)
+					{	error(loc, "class %s has no 'super'", s.toChars());
+					goto Lerr;
+					}
+				}
+				t = cd.type;
+				break;
+				}
+				sd = s.isStructDeclaration();
+				if (sd)
+				{
+				if (exp.op == TOK.TOKsuper)
+				{
+					error(loc, "struct %s has no 'super'", sd.toChars());
+					goto Lerr;
+				}
+				t = sd.type.pointerTo();
+				break;
+				}
+			}
+		}
+		else
+}+/
+		{
+			sc.intypeof++;
+			exp = exp.semantic(sc);
+			sc.intypeof--;
+			if (exp.op == TOK.TOKtype)
+			{
+				error(loc, "argument %s to typeof is not an expression", exp.toChars());
+			}
+			t = exp.type;
+			if (!t)
+			{
+				error(loc, "expression (%s) has no type", exp.toChars());
+				goto Lerr;
+			}
+			if (t.ty == TY.Ttypeof)
+				error(loc, "forward reference to %s", toChars());
+
+			/* typeof should reflect the true type,
+			 * not what 'auto' would have gotten us.
+			 */
+			//t = t.toHeadMutable();
+		}
+		if (idents.dim)
+		{
+			Dsymbol s = t.toDsymbol(sc);
+			for (size_t i = 0; i < idents.dim; i++)
+			{
+				if (!s)
+				break;
+				Identifier id = cast(Identifier)idents.data[i];
+				s = s.searchX(loc, sc, id);
+			}
+
+			if (s)
+			{
+				t = s.getType();
+				if (!t)
+				{	
+					error(loc, "%s is not a type", s.toChars());
+					goto Lerr;
+				}
+			}
+			else
+			{   
+				error(loc, "cannot resolve .property for %s", toChars());
+				goto Lerr;
+			}
+		}
+		return t;
+
+	Lerr:
+		return tvoid;
+	}
+	
+    ulong size(Loc loc)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypedefDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,179 @@
+module dmd.TypedefDeclaration;
+
+import dmd.Declaration;
+import dmd.Initializer;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Scope;
+import dmd.OutBuffer;
+import dmd.ExpInitializer;
+import dmd.HdrGenState;
+import dmd.TypeTypedef;
+import dmd.Global;
+import dmd.STC;
+
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+
+class TypedefDeclaration : Declaration
+{
+    Type basetype;
+    Initializer init;
+    int sem = 0;// 0: semantic() has not been run
+				// 1: semantic() is in progress
+				// 2: semantic() has been run
+				// 3: semantic2() has been run
+
+    this(Loc loc, Identifier id, Type basetype, Initializer init)
+	{
+		super(id);
+		
+		this.type = new TypeTypedef(this);
+		this.basetype = basetype.toBasetype();
+		this.init = init;
+
+	version (_DH) {
+		this.htype = null;
+		this.hbasetype = null;
+	}
+		this.loc = loc;
+		this.sinit = null;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+    Dsymbol syntaxCopy(Dsymbol)
+	{
+		assert(false);
+	}
+	
+    void semantic(Scope sc)
+	{
+		//printf("TypedefDeclaration::semantic(%s) sem = %d\n", toChars(), sem);
+		if (sem == 0)
+		{	
+			sem = 1;
+			basetype = basetype.semantic(loc, sc);
+			sem = 2;
+			type = type.semantic(loc, sc);
+			if (sc.parent.isFuncDeclaration() && init)
+				semantic2(sc);
+			storage_class |= sc.stc & STCdeprecated;
+		}
+		else if (sem == 1)
+		{
+			error("circular definition");
+		}
+	}
+	
+    void semantic2(Scope sc)
+	{
+		//printf("TypedefDeclaration::semantic2(%s) sem = %d\n", toChars(), sem);
+		if (sem == 2)
+		{	
+			sem = 3;
+			if (init)
+			{
+				init = init.semantic(sc, basetype);
+
+				ExpInitializer ie = init.isExpInitializer();
+				if (ie)
+				{
+					if (ie.exp.type == basetype)
+						ie.exp.type = type;
+				}
+			}
+		}
+	}
+	
+    string mangle()
+	{
+		//printf("TypedefDeclaration::mangle() '%s'\n", toChars());
+		return Dsymbol.mangle();
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+	
+    Type getType()
+	{
+		return type;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+version (_DH) {
+    Type htype;
+    Type hbasetype;
+}
+
+    void toDocBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		//printf("TypedefDeclaration::toObjFile('%s')\n", toChars());
+		if (global.params.symdebug)
+			toDebug();
+
+		type.getTypeInfo(null);	// generate TypeInfo
+
+		TypeTypedef tc = cast(TypeTypedef)type;
+		if (type.isZeroInit(Loc(0)) || !tc.sym.init) {
+			;
+		} else
+		{
+			SC scclass = SCglobal;
+			if (inTemplateInstance())
+				scclass = SCcomdat;
+
+			// Generate static initializer
+			toInitializer();
+			sinit.Sclass = scclass;
+			sinit.Sfl = FLdata;
+
+		version (ELFOBJ) { // Burton
+			sinit.Sseg = Segment.CDATA;
+		}
+		version (MACHOBJ) {
+			sinit.Sseg = Segment.DATA;
+		}
+			sinit.Sdt = tc.sym.init.toDt();
+			outdata(sinit);
+		}
+	}
+	
+    void toDebug()
+	{
+		assert(false);
+	}
+	
+    int cvMember(ubyte* p)
+	{
+		assert(false);
+	}
+
+    TypedefDeclaration isTypedefDeclaration() { return this; }
+
+    Symbol* sinit;
+    Symbol* toInitializer()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeidExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,52 @@
+module dmd.TypeidExp;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.HdrGenState;
+import dmd.TOK;
+
+class TypeidExp : Expression
+{
+	Type typeidType;
+
+	this(Loc loc, Type typeidType)
+	{
+		super(loc, TOK.TOKtypeid, TypeidExp.sizeof);
+		this.typeidType = typeidType;
+	}
+
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+	Expression syntaxCopy()
+	{
+		return new TypeidExp(loc, typeidType.syntaxCopy());
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+	version (LOGSEMANTIC) {
+		printf("TypeidExp.semantic()\n");
+	}
+		typeidType = typeidType.semantic(loc, sc);
+		e = typeidType.getTypeInfo(sc);
+		if (e.loc.linnum == 0)
+			e.loc = loc;		// so there's at least some line number info
+		return e;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UAddExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,28 @@
+module dmd.UAddExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.UnaExp;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.TOK;
+
+class UAddExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UnaExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,169 @@
+module dmd.UnaExp;
+
+import dmd.Expression;
+import dmd.InterState;
+import dmd.TY;
+import dmd.TypeClass;
+import dmd.TypeStruct;
+import dmd.Dsymbol;
+import dmd.AggregateDeclaration;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.DotIdExp;
+import dmd.ArrayExp;
+import dmd.CallExp;
+import dmd.PREC;
+import dmd.Token;
+import dmd.expression.Util;
+
+class UnaExp : Expression
+{
+	Expression e1;
+
+	this(Loc loc, TOK op, int size, Expression e1)
+	{
+		super(loc, op, size);
+		this.e1 = e1;
+	}
+
+	Expression syntaxCopy()
+	{
+		UnaExp e = cast(UnaExp)copy();
+		e.type = null;
+		e.e1 = e.e1.syntaxCopy();
+
+		return e;
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		writef("UnaExp.semantic('%s')\n", toChars());
+}
+		e1 = e1.semantic(sc);
+	//    if (!e1.type)
+	//	error("%s has no value", e1.toChars());
+		return this;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(Token.toChars(op));
+		expToCBuffer(buf, hgs, e1, precedence[op]);
+	}
+
+	Expression optimize(int result)
+	{
+		e1 = e1.optimize(result);
+		return this;
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	Expression interpretCommon(InterState* istate, Expression *(*fp)(Type* a0, Expression* a1))
+	{
+		assert(false);
+	}
+
+	bool canThrow()
+	{
+		return e1.canThrow();
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		return 1 + e1.inlineCost(ics);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		UnaExp ue = cast(UnaExp)copy();
+
+		ue.e1 = e1.doInline(ids);
+		return ue;
+	}
+
+	Expression inlineScan(InlineScanState* iss)
+	{
+		e1 = e1.inlineScan(iss);
+		return this;
+	}
+	
+	/************************************
+	 * Operator overload.
+	 * Check for operator overload, if so, replace
+	 * with function call.
+	 * Return null if not an operator overload.
+	 */
+	Expression op_overload(Scope sc)
+	{
+		//printf("UnaExp.op_overload() (%s)\n", toChars());
+		AggregateDeclaration ad;
+		Dsymbol fd;
+		Type t1 = e1.type.toBasetype();
+
+		if (t1.ty == TY.Tclass)
+		{
+			ad = (cast(TypeClass)t1).sym;
+			goto L1;
+		}
+		else if (t1.ty == TY.Tstruct)
+		{
+			ad = (cast(TypeStruct)t1).sym;
+
+			L1:
+			fd = search_function(ad, opId());
+			if (fd)
+			{
+				if (op == TOK.TOKarray)
+				{
+					/* Rewrite op e1[arguments] as:
+					 *    e1.fd(arguments)
+					 */
+					Expression e = new DotIdExp(loc, e1, fd.ident);
+					ArrayExp ae = cast(ArrayExp)this;
+					e = new CallExp(loc, e, ae.arguments);
+					e = e.semantic(sc);
+					return e;
+				}
+				else
+				{
+					// Rewrite +e1 as e1.add()
+					return build_overload(loc, sc, e1, null, fd.ident);
+				}
+			}
+
+version (DMDV2) {
+			// Didn't find it. Forward to aliasthis
+			if (ad.aliasthis)
+			{
+				/* Rewrite op(e1) as:
+				 *	op(e1.aliasthis)
+				 */
+				Expression e1 = new DotIdExp(loc, this.e1, ad.aliasthis.ident);
+				Expression e = copy();
+				(cast(UnaExp)e).e1 = e1;
+				e = e.semantic(sc);
+				return e;
+			}
+}
+		}
+		return null;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UnionDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,27 @@
+module dmd.UnionDeclaration;
+
+import dmd.StructDeclaration;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+
+class UnionDeclaration : StructDeclaration
+{
+    this(Loc loc, Identifier id)
+	{
+		assert(false);
+		super(loc, id);
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+
+    UnionDeclaration isUnionDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UnitTestDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,92 @@
+module dmd.UnitTestDeclaration;
+
+import dmd.FuncDeclaration;
+import dmd.Loc;
+import dmd.Dsymbol;
+import dmd.AggregateDeclaration;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Type;
+import dmd.Scope;
+import dmd.Global;
+import dmd.LINK;
+import dmd.TypeFunction;
+import dmd.Module;
+import dmd.STC;
+import dmd.Lexer;
+import dmd.Identifier;
+
+/*******************************
+ * Generate unique unittest function Id so we can have multiple
+ * instances per module.
+ */
+Identifier unitTestId()
+{
+    return Lexer.uniqueId("__unittest");
+}
+
+class UnitTestDeclaration : FuncDeclaration
+{
+    this(Loc loc, Loc endloc)
+	{
+		super(loc, endloc, unitTestId(), STC.STCundefined, null);
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		UnitTestDeclaration utd;
+
+		assert(!s);
+		utd = new UnitTestDeclaration(loc, endloc);
+
+		return FuncDeclaration.syntaxCopy(utd);
+	}
+
+    void semantic(Scope sc)
+	{
+		if (global.params.useUnitTests)
+		{
+			type = new TypeFunction(null, Type.tvoid, false, LINKd);
+			Scope sc2 = sc.push();
+			sc2.linkage = LINK.LINKd;
+			FuncDeclaration.semantic(sc2);
+			sc2.pop();
+		}
+
+		// We're going to need ModuleInfo even if the unit tests are not
+		// compiled in, because other modules may import this module and refer
+		// to this ModuleInfo.
+		Module m = getModule();
+		if (!m)
+			m = sc.module_;
+		if (m)
+			m.needmoduleinfo = 1;
+	}
+
+    AggregateDeclaration isThis()
+	{
+		assert(false);
+	}
+
+    bool isVirtual()
+	{
+		assert(false);
+	}
+
+    bool addPreInvariant()
+	{
+		assert(false);
+	}
+
+    bool addPostInvariant()
+	{
+		assert(false);
+	}
+
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    UnitTestDeclaration isUnitTestDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UnrolledLoopStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,92 @@
+module dmd.UnrolledLoopStatement;
+
+import dmd.Expression;
+import dmd.Statement;
+import dmd.InterState;
+import dmd.ArrayTypes;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.InlineDoState;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.BE;
+
+class UnrolledLoopStatement : Statement
+{
+	Statements statements;
+
+	this(Loc loc, Statements statements)
+	{
+		assert(false);
+		super(loc);
+	}
+
+	Statement syntaxCopy()
+	{
+		assert(false);
+	}
+
+	Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+
+	bool hasBreak()
+	{
+		assert(false);
+	}
+
+	bool hasContinue()
+	{
+		assert(false);
+	}
+
+	bool usesEH()
+	{
+		assert(false);
+	}
+
+	BE blockExit()
+	{
+		assert(false);
+	}
+
+	bool comeFrom()
+	{
+		assert(false);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		assert(false);
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		assert(false);
+	}
+
+	Statement inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+
+	void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UshrAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,59 @@
+module dmd.UshrAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.Id;
+import dmd.TOK;
+import dmd.Type;
+import dmd.backend.elem;
+import dmd.expression.Util;
+
+class UshrAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKushrass, UshrAssignExp.sizeof, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		BinExp.semantic(sc);
+		e2 = resolveProperties(sc, e2);
+
+		e = op_overload(sc);
+		if (e)
+			return e;
+
+		e1 = e1.modifiableLvalue(sc, e1);
+		e1.checkScalar();
+		e1.checkNoBool();
+		type = e1.type;
+		typeCombine(sc);
+		e1.checkIntegral();
+		e2 = e2.checkIntegral();
+		e2 = e2.castTo(sc, Type.tshiftcnt);
+		return this;
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.ushrass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/UshrExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,85 @@
+module dmd.UshrExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Id;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.TYFL;
+import dmd.backend.Util;
+import dmd.expression.Util;
+import dmd.expression.Ushr;
+import dmd.expression.shift_optimize;
+
+class UshrExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKushr, UshrExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+			if (e)
+				return e;
+			e1 = e1.checkIntegral();
+			e2 = e2.checkIntegral();
+			e1 = e1.integralPromotions(sc);
+			e2 = e2.castTo(sc, Type.tshiftcnt);
+			type = e1.type;
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		//printf("UshrExp.optimize(result = %d) %s\n", result, toChars());
+		return shift_optimize(result, this, &Ushr);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	Identifier opId()
+	{
+		return Id.ushr;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.ushr_r;
+	}
+
+	elem* 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;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Utf.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,28 @@
+module dmd.Utf;
+
+import dmd.Dchar;
+
+import std.utf;
+
+string utf_decodeChar(const(char)[] s, size_t* pidx, dchar* presult)
+{
+	try {
+		*presult = decode(s, *pidx);
+	} catch (Exception e) {
+		return e.toString();
+	}
+
+	return null;
+}
+
+string utf_decodeWchar(const(wchar)[] s, size_t* pidx, dchar* presult)
+{
+	assert(false);
+}
+
+bool utf_isValidDchar(uint c)
+{
+	return isValidDchar(c);
+}
+
+extern (C++) extern int HtmlNamedEntity(ubyte* p, int length);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/Util.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1089 @@
+module dmd.Util;
+
+import dmd.Loc;
+import dmd.Library;
+import dmd.File;
+import dmd.String;
+import dmd.OutBuffer;
+import dmd.FileName;
+import dmd.Global;
+import dmd.PREC;
+import dmd.TOK;
+
+import std.process : getenv;
+import std.c.string;
+import std.stdio : writef, writefln, write;
+import std.c.process : spawnl, spawnlp;
+import core.stdc.stdlib;
+import core.stdc.ctype;
+import core.stdc.stdarg;
+import core.stdc.stdio;
+
+extern(C) int putenv(char*);
+
+//version = LOG;
+
+version (Windows) {
+} else {
+	import core.sys.posix.stdlib : putenv;
+}
+
+enum MAX_PATH = 256; ///
+
+version (Windows) {
+	import core.sys.windows.windows : GetModuleFileNameA;
+}
+
+string fromStringz(const(char)* s)
+{
+	return s[0..strlen(s)].idup;
+}
+
+void warning(T...)(string format, T t)
+{
+	assert(false);
+}
+
+void warning(T...)(Loc loc, string format, T t)
+{
+	assert(false);
+}
+
+void error(T...)(Loc loc, string format, T t)
+{
+	if (!global.gag)
+    {
+		string p = loc.toChars();
+
+		if (p.length != 0)
+			writef("%s: ", p);
+
+		write("Error: ");
+		writefln(format, t);
+
+		//halt();
+    }
+    global.errors++;
+}
+
+char* strupr(char* s)
+{
+    char* t = s;
+    
+    while (*s)
+    {
+		*s = cast(char)toupper(*s);
+		s++;
+    }
+
+    return t;
+}
+
+char[] skipspace(char[] p)
+{
+	foreach (i, c; p) {
+		if (!isspace(c)) {
+			return p[i..$];
+		}
+	}
+	
+	return null;
+}
+
+char* skipspace(char* p)
+{
+    while (isspace(*p))
+		p++;
+		
+	return p;
+}
+
+void inifile(string argv0, string inifile)
+{
+    char *path;		// need path for @P macro
+    string filename;
+    int i;
+    int k;
+    int envsection = 0;
+
+version (LOG) {
+    writef("inifile(argv0 = '%s', inifile = '%s')\n", argv0, inifile);
+}
+    if (FileName.absolute(inifile)) {
+		filename = inifile;
+    } else {
+		/* Look for inifile in the following sequence of places:
+		 *	o current directory
+		 *	o home directory
+		 *	o directory off of argv0
+		 *	o /etc/
+		 */
+		if (FileName.exists(inifile)) {
+			filename = inifile;
+		} else {
+			filename = FileName.combine(getenv("HOME"), inifile);
+			if (!FileName.exists(filename)) {
+version (_WIN32) { // This fix by Tim Matthews
+				char resolved_name_b[MAX_PATH + 1];
+				auto resolved_name = resolved_name_b[].idup;
+				if (GetModuleFileNameA(null, resolved_name_b.ptr, MAX_PATH + 1) && FileName.exists(resolved_name))
+				{
+					filename = FileName.replaceName(resolved_name, inifile);
+					if (FileName.exists(filename)) {
+						goto Ldone;
+					}
+				}
+}
+				filename = FileName.replaceName(argv0, inifile);
+				if (!FileName.exists(filename)) {
+version (XXX) { /// linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+	version (XXX) { /// __GLIBC__ || __APPLE__ || __FreeBSD__ || __sun&&__SVR4   // This fix by Thomas Kuehne
+					/* argv0 might be a symbolic link,
+					* so try again looking past it to the real path
+					*/
+		version (XXX) {/// #if __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+					char resolved_name[PATH_MAX + 1];
+					char* real_argv0 = realpath(argv0, resolved_name);
+		} else {
+					char* real_argv0 = realpath(argv0, null);
+		}
+					//printf("argv0 = %s, real_argv0 = %p\n", argv0, real_argv0);
+					if (real_argv0) {
+						filename = FileName.replaceName(real_argv0, inifile);
+		version (linux) {
+						free(real_argv0);
+		}
+						if (FileName.exists(filename)) {
+							goto Ldone;
+						}
+					}
+	} else {
+					static assert (false, "use of glibc non-standard extension realpath(char*, null)");
+	}
+					if (true) {
+						// Search PATH for argv0
+						const(char)* p = getenv("PATH");
+	version (LOG) {
+						writef("\tPATH='%s'\n", p);
+	}
+						Array paths = FileName.splitPath(p);
+						filename = FileName.searchPath(paths, argv0, 0);
+						if (!filename) {
+							goto Letc;		// argv0 not found on path
+						}
+						
+						filename = FileName.replaceName(filename, inifile);
+						if (FileName.exists(filename)) {
+							goto Ldone;
+						}
+					}
+}
+					// Search /etc/ for inifile
+		Letc:
+					filename = FileName.combine("/etc/", inifile);
+
+		Ldone:
+		    ;
+				}
+			}
+		}
+    }
+	
+    path = cast(char*)toStringz(FileName.path(filename));
+
+version (LOG) {
+    writef("\tpath = '%s', filename = '%s'\n", fromStringz(path), filename);
+}
+
+    scope File file = new File(filename);
+
+    if (file.read()) {
+		return;			// error reading file
+	}
+	
+	scope OutBuffer buf = new OutBuffer();
+
+    // Parse into lines
+    int eof = 0;
+    for (i = 0; i < file.len && !eof; i++)
+    {
+		int linestart = i;
+
+		for (; i < file.len; i++)
+		{
+			switch (file.buffer[i])
+			{
+				case '\r':
+					break;
+
+				case '\n':
+					// Skip if it was preceded by '\r'
+					if (i && file.buffer[i - 1] == '\r')
+						goto Lskip;
+					break;
+
+				case 0:
+				case 0x1A:
+					eof = 1;
+					break;
+
+				default:
+					continue;
+				}
+				break;
+		}
+
+		// The line is file.buffer[linestart..i]
+		char *line;
+		int len;
+		char *p;
+		char* pn;
+
+		line = cast(char*)&file.buffer[linestart];
+		len = i - linestart;
+
+		buf.reset();
+
+		// First, expand the macros.
+		// Macros are bracketed by % characters.
+
+		for (k = 0; k < len; k++)
+		{
+			if (line[k] == '%')
+			{
+				int j;
+
+				for (j = k + 1; j < len; j++)
+				{
+					if (line[j] == '%')
+					{
+						if (j - k == 3 && memicmp(&line[k + 1], "@P", 2) == 0)
+						{
+							// %@P% is special meaning the path to the .ini file
+							p = path;
+							if (!*p)
+								p = cast(char*)".";
+						}
+						else
+						{
+							int l = j - k;
+							char tmp[10];	// big enough most of the time
+
+							if (l <= tmp.sizeof)
+								p = tmp.ptr;
+							else
+								p = cast(char*)alloca(l);
+							l--;
+							memcpy(p, &line[k + 1], l);
+							p[l] = 0;
+							strupr(p);
+							p = core.stdc.stdlib.getenv(p);
+							if (!p)
+								p = cast(char*)"";
+						}
+						buf.writestring(p[0..strlen(p)]);	///
+						k = j;
+						goto L1;
+					}
+				}
+			}
+			buf.writeByte(line[k]);
+		 L1:
+			;
+		}
+
+		// Remove trailing spaces
+		while (buf.offset && isspace(buf.data[buf.offset - 1]))
+			buf.offset--;
+
+		char[] pp = buf.getString();
+
+		// The expanded line is in p.
+		// Now parse it for meaning.
+
+		pp = skipspace(pp);
+		if (pp.length != 0) {
+			switch (pp[0])
+			{
+				case ';':		// comment
+					break;
+
+				case '[':		// look for [Environment]
+					pp = skipspace(pp[1..$]);
+					for (pn = pp.ptr; isalnum(*pn); pn++) {
+						;
+					}
+					
+					if (pn - pp.ptr == 11 &&
+						memicmp(pp.ptr, "Environment", 11) == 0 &&
+						*skipspace(pn) == ']'
+					   )
+						envsection = 1;
+					else
+						envsection = 0;
+					break;
+
+				default:
+					if (envsection)
+					{
+						pn = pp.ptr;
+
+						// Convert name to upper case;
+						// remove spaces bracketing =
+						auto p2 = pn;
+						for ( ; *p2; p2++)
+						{   if (islower(*p2))
+								*p2 &= ~0x20;
+							else if (isspace(*p))
+								memmove(p2, p2 + 1, strlen(p2));
+							else if (*p2 == '=')
+							{
+								p2++;
+								while (isspace(*p2))
+									memmove(p2, p2 + 1, strlen(p2));
+								break;
+							}
+						}
+
+						//putenv(pn);
+						putenv(cast(char*)toStringz(pp));
+
+version (LOG) {
+						writef("\tputenv('%s')\n", pn[0..strlen(pn)]);
+						//printf("getenv(\"TEST\") = '%s'\n",getenv("TEST"));
+}
+					}
+					break;
+			}
+		}
+
+	Lskip:
+		;
+    }
+}
+
+///int response_expand(int *pargc, char ***pargv);
+void browse(const(char)* url)
+{
+	assert(false);
+}
+
+string[] getenv_setargv(string envvar, string[] args)
+{
+    char *p;
+
+    string[] argv = args.dup;
+    int argc = args.length;
+
+    int wildcard;		// do wildcard expansion
+    int instring;
+    int slash;
+    char c;
+    int j;
+
+    string ienv = getenv(envvar);
+    if (ienv is null)
+		return args;
+
+    char[] env = ienv.dup;	// create our own writable copy
+
+    j = 1;			// leave argv[0] alone
+	char* e = env.ptr;
+    while (1)
+    {
+		wildcard = 1;
+		switch (*e)
+		{
+			case ' ':
+			case '\t':
+			e++;
+			break;
+
+			case 0:
+			goto Ldone;
+
+			case '"':
+			wildcard = 0;
+			default:
+			argv ~= assumeUnique(e[0..strlen(e)]);		// append
+			//argv.insert(j, env);		// insert at position j
+			j++;
+			argc++;
+			p = e;
+			slash = 0;
+			instring = 0;
+			c = 0;
+			
+			char* ecopy = e;
+
+			while (1)
+			{
+				c = *e++;
+				switch (c)
+				{
+				case '"':
+					p -= (slash >> 1);
+					if (slash & 1)
+					{
+						p--;
+						goto Laddc;
+					}
+					instring ^= 1;
+					slash = 0;
+					continue;
+
+				case '\\':
+					slash++;
+					*p++ = c;
+					continue;
+
+				case ' ':
+				case '\t':
+					if (instring)
+						goto Laddc;
+				case 0:
+					*p = 0;
+					if (argv.length != 0) {
+						argv[$-1].length = p - argv[$-1].ptr;
+					}
+					//if (wildcard)
+					//wildcardexpand();	// not implemented
+					if (c == 0) goto Ldone;
+					break;
+
+				default:
+				Laddc:
+					slash = 0;
+					*p++ = c;
+					continue;
+				}
+				break;
+			}
+		}
+    }
+
+Ldone:
+    return argv;
+}
+
+void error(T...)(string format, T t)
+{
+	writefln(format, t);
+    exit(EXIT_FAILURE);
+}
+
+void usage()
+{
+	writef("Digital Mars D Compiler %s\n%s %s\n", global.version_, global.copyright, global.written);
+    writef(
+"Documentation: http://www.digitalmars.com/d/2.0/index.html\n"
+"Usage:\n"
+"  dmd files.d ... { -switch }\n"
+"\n"
+"  files.d        D source files\n"
+"  @cmdfile       read arguments from cmdfile\n"
+"  -c             do not link\n"
+"  -cov           do code coverage analysis\n"
+"  -D             generate documentation\n"
+"  -Dddocdir      write documentation file to docdir directory\n"
+"  -Dffilename    write documentation file to filename\n"
+"  -d             allow deprecated features\n"
+"  -debug         compile in debug code\n"
+"  -debug=level   compile in debug code <= level\n"
+"  -debug=ident   compile in debug code identified by ident\n"
+"  -debuglib=name    set symbolic debug library to name\n"
+"  -defaultlib=name  set default library to name\n"
+"  -deps=filename write module dependencies to filename\n"
+"  -g             add symbolic debug info\n"
+"  -gc            add symbolic debug info, pretend to be C\n"
+"  -H             generate 'header' file\n"
+"  -Hdhdrdir      write 'header' file to hdrdir directory\n"
+"  -Hffilename    write 'header' file to filename\n"
+"  --help         print help\n"
+"  -Ipath         where to look for imports\n"
+"  -ignore        ignore unsupported pragmas\n"
+"  -inline        do function inlining\n"
+"  -Jpath         where to look for string imports\n"
+"  -Llinkerflag   pass linkerflag to link\n"
+"  -lib           generate library rather than object files\n"
+"  -man           open web browser on manual page\n"
+"  -nofloat       do not emit reference to floating point\n"
+"  -O             optimize\n"
+"  -o-            do not write object file\n"
+"  -odobjdir      write object & library files to directory objdir\n"
+"  -offilename	 name output file to filename\n"
+"  -op            do not strip paths from source file\n"
+"  -profile	 profile runtime performance of generated code\n"
+"  -quiet         suppress unnecessary messages\n"
+"  -release	 compile release version\n"
+"  -run srcfile args...   run resulting program, passing args\n"
+"  -safe          safe memory model\n"
+"  -unittest      compile in unit tests\n"
+"  -v             verbose\n"
+"  -version=level compile in version code >= level\n"
+"  -version=ident compile in version code identified by ident\n"
+"  -vtls          list all variables going into thread local storage\n"
+"  -w             enable warnings\n"
+);
+}
+
+void fatal()
+{
+static if (false) {
+    halt();
+} else {
+    exit(EXIT_FAILURE);
+}
+}
+
+void halt()
+{
+	assert(false);
+}
+
+void initPrecedence()
+{
+	precedence[TOK.TOKdotvar] = PREC.PREC_primary;
+    precedence[TOK.TOKimport] = PREC.PREC_primary;
+    precedence[TOK.TOKidentifier] = PREC.PREC_primary;
+    precedence[TOK.TOKthis] = PREC.PREC_primary;
+    precedence[TOK.TOKsuper] = PREC.PREC_primary;
+    precedence[TOK.TOKint64] = PREC.PREC_primary;
+    precedence[TOK.TOKfloat64] = PREC.PREC_primary;
+    precedence[TOK.TOKnull] = PREC.PREC_primary;
+    precedence[TOK.TOKstring] = PREC.PREC_primary;
+    precedence[TOK.TOKarrayliteral] = PREC.PREC_primary;
+    precedence[TOK.TOKtypeid] = PREC.PREC_primary;
+    precedence[TOK.TOKis] = PREC.PREC_primary;
+    precedence[TOK.TOKassert] = PREC.PREC_primary;
+    precedence[TOK.TOKfunction] = PREC.PREC_primary;
+    precedence[TOK.TOKvar] = PREC.PREC_primary;
+version (DMDV2) {
+    precedence[TOK.TOKdefault] = PREC.PREC_primary;
+}
+
+    // post
+    precedence[TOK.TOKdotti] = PREC.PREC_primary;
+    precedence[TOK.TOKdot] = PREC.PREC_primary;
+//  precedence[TOK.TOKarrow] = PREC.PREC_primary;
+    precedence[TOK.TOKplusplus] = PREC.PREC_primary;
+    precedence[TOK.TOKminusminus] = PREC.PREC_primary;
+    precedence[TOK.TOKcall] = PREC.PREC_primary;
+    precedence[TOK.TOKslice] = PREC.PREC_primary;
+    precedence[TOK.TOKarray] = PREC.PREC_primary;
+
+    precedence[TOK.TOKaddress] = PREC.PREC_unary;
+    precedence[TOK.TOKstar] = PREC.PREC_unary;
+    precedence[TOK.TOKneg] = PREC.PREC_unary;
+    precedence[TOK.TOKuadd] = PREC.PREC_unary;
+    precedence[TOK.TOKnot] = PREC.PREC_unary;
+    precedence[TOK.TOKtobool] = PREC.PREC_add;
+    precedence[TOK.TOKtilde] = PREC.PREC_unary;
+    precedence[TOK.TOKdelete] = PREC.PREC_unary;
+    precedence[TOK.TOKnew] = PREC.PREC_unary;
+    precedence[TOK.TOKcast] = PREC.PREC_unary;
+
+    precedence[TOK.TOKmul] = PREC.PREC_mul;
+    precedence[TOK.TOKdiv] = PREC.PREC_mul;
+    precedence[TOK.TOKmod] = PREC.PREC_mul;
+
+    precedence[TOK.TOKadd] = PREC.PREC_add;
+    precedence[TOK.TOKmin] = PREC.PREC_add;
+    precedence[TOK.TOKcat] = PREC.PREC_add;
+
+    precedence[TOK.TOKshl] = PREC.PREC_shift;
+    precedence[TOK.TOKshr] = PREC.PREC_shift;
+    precedence[TOK.TOKushr] = PREC.PREC_shift;
+
+    precedence[TOK.TOKlt] = PREC.PREC_rel;
+    precedence[TOK.TOKle] = PREC.PREC_rel;
+    precedence[TOK.TOKgt] = PREC.PREC_rel;
+    precedence[TOK.TOKge] = PREC.PREC_rel;
+    precedence[TOK.TOKunord] = PREC.PREC_rel;
+    precedence[TOK.TOKlg] = PREC.PREC_rel;
+    precedence[TOK.TOKleg] = PREC.PREC_rel;
+    precedence[TOK.TOKule] = PREC.PREC_rel;
+    precedence[TOK.TOKul] = PREC.PREC_rel;
+    precedence[TOK.TOKuge] = PREC.PREC_rel;
+    precedence[TOK.TOKug] = PREC.PREC_rel;
+    precedence[TOK.TOKue] = PREC.PREC_rel;
+    precedence[TOK.TOKin] = PREC.PREC_rel;
+
+static if (false) {
+    precedence[TOK.TOKequal] = PREC.PREC_equal;
+    precedence[TOK.TOKnotequal] = PREC.PREC_equal;
+    precedence[TOK.TOKidentity] = PREC.PREC_equal;
+    precedence[TOK.TOKnotidentity] = PREC.PREC_equal;
+} else {
+    /* Note that we changed precedence, so that < and != have the same
+     * precedence. This change is in the parser, too.
+     */
+    precedence[TOK.TOKequal] = PREC.PREC_rel;
+    precedence[TOK.TOKnotequal] = PREC.PREC_rel;
+    precedence[TOK.TOKidentity] = PREC.PREC_rel;
+    precedence[TOK.TOKnotidentity] = PREC.PREC_rel;
+}
+
+    precedence[TOK.TOKand] = PREC.PREC_and;
+
+    precedence[TOK.TOKxor] = PREC.PREC_xor;
+
+    precedence[TOK.TOKor] = PREC.PREC_or;
+
+    precedence[TOK.TOKandand] = PREC.PREC_andand;
+
+    precedence[TOK.TOKoror] = PREC.PREC_oror;
+
+    precedence[TOK.TOKquestion] = PREC.PREC_cond;
+
+    precedence[TOK.TOKassign] = PREC.PREC_assign;
+    precedence[TOK.TOKconstruct] = PREC.PREC_assign;
+    precedence[TOK.TOKblit] = PREC.PREC_assign;
+    precedence[TOK.TOKaddass] = PREC.PREC_assign;
+    precedence[TOK.TOKminass] = PREC.PREC_assign;
+    precedence[TOK.TOKcatass] = PREC.PREC_assign;
+    precedence[TOK.TOKmulass] = PREC.PREC_assign;
+    precedence[TOK.TOKdivass] = PREC.PREC_assign;
+    precedence[TOK.TOKmodass] = PREC.PREC_assign;
+    precedence[TOK.TOKshlass] = PREC.PREC_assign;
+    precedence[TOK.TOKshrass] = PREC.PREC_assign;
+    precedence[TOK.TOKushrass] = PREC.PREC_assign;
+    precedence[TOK.TOKandass] = PREC.PREC_assign;
+    precedence[TOK.TOKorass] = PREC.PREC_assign;
+    precedence[TOK.TOKxorass] = PREC.PREC_assign;
+
+    precedence[TOK.TOKcomma] = PREC.PREC_expr;
+}
+
+int runLINK()
+{
+version (_WIN32) {
+    string p;
+    int i;
+    int status;
+    scope OutBuffer cmdbuf = new OutBuffer();
+
+    global.params.libfiles.push(cast(void*)new String("user32"));
+    global.params.libfiles.push(cast(void*)new String("kernel32"));
+
+    for (i = 0; i < global.params.objfiles.dim; i++)
+    {
+		if (i)
+			cmdbuf.writeByte('+');
+		p = (cast(String)global.params.objfiles.data[i]).str;
+		string ext = FileName.ext(p);
+		if (ext)
+			// Write name sans extension
+			writeFilename(cmdbuf, p[0..p.length - ext.length - 1]);
+		else
+			writeFilename(cmdbuf, p);
+    }
+    cmdbuf.writeByte(',');
+    if (global.params.exefile)
+		writeFilename(cmdbuf, global.params.exefile);
+    else
+    {	
+		/* Generate exe file name from first obj name.
+		 * No need to add it to cmdbuf because the linker will default to it.
+		 */
+		string n = (cast(String)global.params.objfiles.data[0]).str;
+		n = FileName.name(n);
+		FileName fn = FileName.forceExt(n, "exe");
+		global.params.exefile = fn.toChars();
+    }
+
+    // Make sure path to exe file exists
+    {	
+		string pp = FileName.path(global.params.exefile);
+		FileName.ensurePathExists(pp);
+    }
+
+    cmdbuf.writeByte(',');
+    if (global.params.run)
+		cmdbuf.writestring("nul");
+
+//    if (mapfile)
+//	cmdbuf.writestring(output);
+    cmdbuf.writeByte(',');
+
+    for (i = 0; i < global.params.libfiles.dim; i++)
+    {
+		if (i)
+			cmdbuf.writeByte('+');
+		writeFilename(cmdbuf, (cast(String)global.params.libfiles.data[i]).str);
+    }
+
+    if (global.params.deffile)
+    {
+		cmdbuf.writeByte(',');
+		writeFilename(cmdbuf, global.params.deffile);
+    }
+
+    /* Eliminate unnecessary trailing commas	*/
+    while (1)
+    {   
+		i = cmdbuf.offset;
+		if (!i || cmdbuf.data[i - 1] != ',')
+			break;
+		cmdbuf.offset--;
+    }
+
+    if (global.params.resfile)
+    {
+		cmdbuf.writestring("/RC:");
+		writeFilename(cmdbuf, global.params.resfile);
+    }
+
+static if (false) {
+    if (mapfile)
+		cmdbuf.writestring("/m");
+    if (debuginfo)
+		cmdbuf.writestring("/li");
+    if (codeview)
+    {
+		cmdbuf.writestring("/co");
+		if (codeview3)
+			cmdbuf.writestring(":3");
+    }
+} else {
+    if (global.params.symdebug)
+		cmdbuf.writestring("/co");
+}
+
+    cmdbuf.writestring("/noi");
+    for (i = 0; i < global.params.linkswitches.dim; i++)
+    {
+		cmdbuf.writestring((cast(String)global.params.linkswitches.data[i]).str);
+    }
+    cmdbuf.writeByte(';');
+
+    p = cmdbuf.toChars();
+
+    FileName lnkfilename = null;
+    size_t plen = p.length;
+    if (plen > 7000)
+    {
+		lnkfilename = FileName.forceExt(global.params.exefile, "lnk");
+		scope File flnk = new File(lnkfilename);
+		flnk.setbuffer(cast(void*)p.ptr, plen);
+		flnk.ref_ = 1;
+		if (flnk.write())
+			error("error writing file %s", lnkfilename);
+		if (lnkfilename.len() < plen)
+			p = std.string.format("@%s", lnkfilename.toChars());
+    }
+
+    string linkcmd = getenv("LINKCMD");
+    if (!linkcmd)
+		linkcmd = "link";
+
+    status = executecmd(linkcmd, p, 1);
+    if (lnkfilename)
+    {
+		remove(toStringz(lnkfilename.toChars()));
+		///delete lnkfilename;
+    }
+    return status;
+} else if (XXX) {/// linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+	assert(false);
+	/+
+    pid_t childpid;
+    int i;
+    int status;
+
+    // Build argv[]
+    Array argv;
+
+    const char *cc = getenv("CC");
+    if (!cc)
+	cc = "gcc";
+    argv.push((void *)cc);
+    argv.insert(1, global.params.objfiles);
+
+    // None of that a.out stuff. Use explicit exe file name, or
+    // generate one from name of first source file.
+    argv.push((void *)"-o");
+    if (global.params.exefile)
+    {
+	argv.push(global.params.exefile);
+    }
+    else
+    {	// Generate exe file name from first obj name
+	char *n = (char *)global.params.objfiles.data[0];
+	char *e;
+	char *ex;
+
+	n = FileName.name(n);
+	e = FileName.ext(n);
+	if (e)
+	{
+	    e--;			// back up over '.'
+	    ex = (char *)mem.malloc(e - n + 1);
+	    memcpy(ex, n, e - n);
+	    ex[e - n] = 0;
+	}
+	else
+	    ex = (char *)"a.out";	// no extension, so give up
+	argv.push(ex);
+	global.params.exefile = ex;
+    }
+
+    // Make sure path to exe file exists
+    {	char *p = FileName.path(global.params.exefile);
+	FileName.ensurePathExists(p);
+	mem.free(p);
+    }
+
+    if (global.params.symdebug)
+	argv.push((void *)"-g");
+
+    if (global.params.isX86_64)
+	argv.push((void *)"-m64");
+    else
+	argv.push((void *)"-m32");
+
+    if (0 && global.params.exefile)
+    {
+	/* This switch enables what is known as 'smart linking'
+	 * in the Windows world, where unreferenced sections
+	 * are removed from the executable. It eliminates unreferenced
+	 * functions, essentially making a 'library' out of a module.
+	 * Although it is documented to work with ld version 2.13,
+	 * in practice it does not, but just seems to be ignored.
+	 * Thomas Kuehne has verified that it works with ld 2.16.1.
+	 * BUG: disabled because it causes exception handling to fail
+	 */
+	argv.push((void *)"-Xlinker");
+	argv.push((void *)"--gc-sections");
+    }
+
+    for (i = 0; i < global.params.linkswitches.dim; i++)
+    {	char *p = (char *)global.params.linkswitches.data[i];
+	if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l'))
+	    // Don't need -Xlinker if switch starts with -l
+	    argv.push((void *)"-Xlinker");
+	argv.push((void *) p);
+    }
+
+    /* Add each library, prefixing it with "-l".
+     * The order of libraries passed is:
+     *  1. any libraries passed with -L command line switch
+     *  2. libraries specified on the command line
+     *  3. libraries specified by pragma(lib), which were appended
+     *     to global.params.libfiles.
+     *  4. standard libraries.
+     */
+    for (i = 0; i < global.params.libfiles.dim; i++)
+    {	char *p = (char *)global.params.libfiles.data[i];
+	size_t plen = strlen(p);
+	if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a')
+	    argv.push((void *)p);
+	else
+	{
+	    char *s = (char *)mem.malloc(plen + 3);
+	    s[0] = '-';
+	    s[1] = 'l';
+	    memcpy(s + 2, p, plen + 1);
+	    argv.push((void *)s);
+	}
+    }
+
+    /* Standard libraries must go after user specified libraries
+     * passed with -l.
+     */
+    const char *libname = (global.params.symdebug)
+				? global.params.debuglibname
+				: global.params.defaultlibname;
+    char *buf = (char *)malloc(2 + strlen(libname) + 1);
+    strcpy(buf, "-l");
+    strcpy(buf + 2, libname);
+    argv.push((void *)buf);		// turns into /usr/lib/libphobos2.a
+
+//    argv.push((void *)"-ldruntime");
+    argv.push((void *)"-lpthread");
+    argv.push((void *)"-lm");
+
+    if (!global.params.quiet || global.params.verbose)
+    {
+	// Print it
+	for (i = 0; i < argv.dim; i++)
+	    printf("%s ", (char *)argv.data[i]);
+	printf("\n");
+	fflush(stdout);
+    }
+
+    argv.push(null);
+    childpid = fork();
+    if (childpid == 0)
+    {
+	execvp((char *)argv.data[0], (char **)argv.data);
+	perror((char *)argv.data[0]);		// failed to execute
+	return -1;
+    }
+
+    waitpid(childpid, &status, 0);
+
+    status=WEXITSTATUS(status);
+    if (status)
+	printf("--- errorlevel %d\n", status);
+    return status;
+	+/
+} else {
+    writef ("Linking is not yet supported for this version of DMD.\n");
+    return -1;
+}
+}
+
+int runProgram()
+{
+	assert(false);
+}
+
+void deleteExeFile()
+{
+	assert(false);
+}
+
+/****************************************
+ * Write filename to cmdbuf, quoting if necessary.
+ */
+
+void writeFilename(OutBuffer buf, string filename)
+{
+	auto len = filename.length;
+    /* Loop and see if we need to quote
+     */
+    for (size_t i = 0; i < len; i++)
+    {	
+		char c = filename[i];
+
+		if (isalnum(c) || c == '_')
+			continue;
+
+		/* Need to quote
+		 */
+		buf.writeByte('"');
+		buf.writestring(filename);
+		buf.writeByte('"');
+		return;
+    }
+
+    /* No quoting necessary
+     */
+    buf.writestring(filename);
+}
+
+/******************************
+ * Execute a rule.  Return the status.
+ *	cmd	program to run
+ *	args	arguments to cmd, as a string
+ *	useenv	if cmd knows about _CMDLINE environment variable
+ */
+
+version (_WIN32) {
+int executecmd(string cmd, string args, int useenv)
+{
+    int status;
+    size_t len = args.length;
+
+    if (!global.params.quiet || global.params.verbose)
+    {
+		printf("%s %s\n", cmd, args);
+		fflush(stdout);
+    }
+
+    if (len > 255)
+    {   
+		char* q;
+		static char[9] envname = "@_CMDLINE";
+
+		envname[0] = '@';
+		switch (useenv)
+		{   
+			case 0:	goto L1;
+			case 2: envname[0] = '%';	break;
+			default: break;	///
+		}
+		q = cast(char*) alloca(envname.sizeof + len + 1);
+		sprintf(q, "%s=%s", envname.ptr + 1, args);
+		status = putenv(q);
+		if (status == 0)
+			args = envname[].idup;
+		else
+		{
+		L1:
+			error("command line length of %d is too long",len);
+		}
+    }
+
+    status = executearg0(cmd, args);
+version (_WIN32) {
+    if (status == -1) {
+		auto cmdZ = toStringz(cmd);
+		auto argsZ = toStringz(args);
+		status = spawnlp(0, cmdZ, cmdZ, argsZ, null);
+	}
+}
+//    if (global.params.verbose)
+//	printf("\n");
+    if (status)
+    {
+	if (status == -1)
+	    printf("Can't run '%s', check PATH\n", cmd);
+	else
+	    printf("--- errorlevel %d\n", status);
+    }
+    return status;
+}
+}
+
+/**************************************
+ * Attempt to find command to execute by first looking in the directory
+ * where DMD was run from.
+ * Returns:
+ *	-1	did not find command there
+ *	!=-1	exit status from command
+ */
+
+version (_WIN32) {
+int executearg0(string cmd, string args)
+{
+    string file;
+    string argv0 = global.params.argv0;
+
+    //printf("argv0='%s', cmd='%s', args='%s'\n",argv0,cmd,args);
+
+    // If cmd is fully qualified, we don't do this
+    if (FileName.absolute(cmd))
+		return -1;
+
+    file = FileName.replaceName(argv0, cmd);
+
+    //printf("spawning '%s'\n",file);
+version (_WIN32) {
+	auto fileZ = toStringz(file);
+	auto argsZ = toStringz(args);
+    return spawnl(0, fileZ, fileZ, argsZ, null);
+} else version (XXX) { ///#elif linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+	assert(false);
+	/+
+    char *full;
+    int cmdl = strlen(cmd);
+
+    full = (char*) mem.malloc(cmdl + strlen(args) + 2);
+    if (full == null)
+	return 1;
+    strcpy(full, cmd);
+    full [cmdl] = ' ';
+    strcpy(full + cmdl + 1, args);
+
+    int result = system(full);
+
+    mem.free(full);
+    return result;
+	+/
+} else {
+    static assert(false);
+}
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VarDeclaration.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1188 @@
+module dmd.VarDeclaration;
+
+import dmd.Declaration;
+import dmd.SliceExp;
+import dmd.ClassDeclaration;
+import dmd.DeleteExp;
+import dmd.SymOffExp;
+import dmd.DotIdExp;
+import dmd.PtrExp;
+import dmd.CallExp;
+import dmd.DotVarExp;
+import dmd.CommaExp;
+import dmd.CastExp;
+import dmd.WANT;
+import dmd.StructDeclaration;
+import dmd.DsymbolExp;
+import dmd.TypeSArray;
+import dmd.IntegerExp;
+import dmd.VarExp;
+import dmd.AssignExp;
+import dmd.TypeTypedef;
+import dmd.ArrayInitializer;
+import dmd.StructInitializer;
+import dmd.NewExp;
+import dmd.TupleDeclaration;
+import dmd.AggregateDeclaration;
+import dmd.InterfaceDeclaration;
+import dmd.TemplateInstance;
+import dmd.Id;
+import dmd.Initializer;
+import dmd.TypeStruct;
+import dmd.TypeTuple;
+import dmd.Argument;
+import dmd.ExpInitializer;
+import dmd.ArrayTypes;
+import dmd.Dsymbol;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.STC;
+import dmd.TOK;
+import dmd.TupleExp;
+import dmd.Global;
+import dmd.FuncDeclaration;
+import dmd.Type;
+import dmd.TY;
+import dmd.LINK;
+import dmd.Scope;
+import dmd.Identifier;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.PROT;
+
+import dmd.backend.Symbol;
+import dmd.backend.TYM;
+import dmd.backend.FL;
+import dmd.backend.DT;
+import dmd.backend.mTY;
+import dmd.backend.SC;
+import dmd.backend.mTYman;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.LIST;
+
+import std.stdio : writef;
+import std.string : toStringz;
+
+class VarDeclaration : Declaration
+{
+    Initializer init;
+    uint offset;
+    bool noauto;			// no auto semantics
+version (DMDV2) {
+    FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+} else {
+    int nestedref;		// referenced by a lexically nested function
+}
+    int ctorinit;		// it has been initialized in a ctor
+    int onstack;		// 1: it has been allocated on the stack
+				// 2: on stack, run destructor anyway
+    int canassign;		// it can be assigned to
+    Dsymbol aliassym;		// if redone as alias to another symbol
+    Expression value;		// when interpreting, this is the value
+				// (null if value not determinable)
+version (DMDV2) {
+    VarDeclaration rundtor;	// if !null, rundtor is tested at runtime to see
+				// if the destructor should be run. Used to prevent
+				// dtor calls on postblitted vars
+}
+
+    this(Loc loc, Type type, Identifier id, Initializer init)
+	{
+		super(id);
+		
+debug {
+		if (!type && !init)
+		{
+			writef("VarDeclaration('%s')\n", id.toChars());
+			//*(char*)0=0;
+		}
+}
+		assert(type || init);
+		this.type = type;
+		this.init = init;
+		this.loc = loc;
+		
+		nestedrefs = new FuncDeclarations();
+	}
+
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		//printf("VarDeclaration.syntaxCopy(%s)\n", toChars());
+
+		VarDeclaration sv;
+		if (s)
+		{	
+			sv = cast(VarDeclaration)s;
+		}
+		else
+		{
+			Initializer init = null;
+			if (this.init)
+			{   
+				init = this.init.syntaxCopy();
+				//init.isExpInitializer().exp.print();
+				//init.isExpInitializer().exp.dump(0);
+			}
+
+			sv = new VarDeclaration(loc, type ? type.syntaxCopy() : null, ident, init);
+			sv.storage_class = storage_class;
+		}
+
+	version (_DH) {
+		// Syntax copy for header file
+		if (!htype)      // Don't overwrite original
+		{
+			if (type)    // Make copy for both old and new instances
+			{   htype = type.syntaxCopy();
+				sv.htype = type.syntaxCopy();
+			}
+		}
+		else            // Make copy of original for new instance
+			sv.htype = htype.syntaxCopy();
+		if (!hinit)
+		{	
+			if (init)
+			{   
+				hinit = init.syntaxCopy();
+				sv.hinit = init.syntaxCopy();
+			}
+		}
+		else
+			sv.hinit = hinit.syntaxCopy();
+	}
+		return sv;
+	}
+
+    void semantic(Scope sc)
+	{
+static if (false) {
+		printf("VarDeclaration.semantic('%s', parent = '%s')\n", toChars(), sc.parent.toChars());
+		printf(" type = %s\n", type ? type.toChars() : "null");
+		printf(" stc = x%x\n", sc.stc);
+		printf(" storage_class = x%x\n", storage_class);
+		printf("linkage = %d\n", sc.linkage);
+		//if (strcmp(toChars(), "mul") == 0) halt();
+}
+
+		storage_class |= sc.stc;
+		if (storage_class & STC.STCextern && init)
+			error("extern symbols cannot have initializers");
+		
+		/* If auto type inference, do the inference
+		 */
+		int inferred = 0;
+		if (!type)
+		{	
+			inuse++;
+			type = init.inferType(sc);
+			inuse--;
+			inferred = 1;
+
+			/* This is a kludge to support the existing syntax for RAII
+			 * declarations.
+			 */
+			storage_class &= ~STC.STCauto;
+			originalType = type;
+		}
+		else
+		{	
+			if (!originalType)
+				originalType = type;
+				
+			type = type.semantic(loc, sc);
+		}
+		//printf(" semantic type = %s\n", type ? type.toChars() : "null");
+
+		type.checkDeprecated(loc, sc);
+		linkage = sc.linkage;
+		this.parent = sc.parent;
+		//printf("this = %p, parent = %p, '%s'\n", this, parent, parent.toChars());
+		protection = sc.protection;
+		//printf("sc.stc = %x\n", sc.stc);
+		//printf("storage_class = x%x\n", storage_class);
+
+version (DMDV2) {
+		if (storage_class & STC.STCgshared && global.params.safe && !sc.module_.safe)
+		{
+		error("__gshared not allowed in safe mode; use shared");
+		}
+}
+
+		Dsymbol parent = toParent();
+		FuncDeclaration fd = parent.isFuncDeclaration();
+
+		Type tb = type.toBasetype();
+		if (tb.ty == TY.Tvoid && !(storage_class & STC.STClazy))
+		{	error("voids have no value");
+		type = Type.terror;
+		tb = type;
+		}
+		if (tb.ty == TY.Tfunction)
+		{	error("cannot be declared to be a function");
+		type = Type.terror;
+		tb = type;
+		}
+		if (tb.ty == TY.Tstruct)
+		{	TypeStruct ts = cast(TypeStruct)tb;
+
+		if (!ts.sym.members)
+		{
+			error("no definition of struct %s", ts.toChars());
+		}
+		}
+
+		if (tb.ty == TY.Ttuple)
+		{   /* Instead, declare variables for each of the tuple elements
+			* and add those.
+			*/
+		TypeTuple tt = cast(TypeTuple)tb;
+		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);
+
+			OutBuffer buf;
+			buf.printf("_%s_field_%zu", ident.toChars(), i);
+			buf.writeByte(0);
+			string name = buf.extractString();
+			Identifier id = new Identifier(name, TOK.TOKidentifier);
+
+			Expression einit = ie;
+			if (ie && ie.op == TOK.TOKtuple)
+			{	einit = cast(Expression)(cast(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);
+
+			if (sc.scopesym)
+			{	//printf("adding %s to %s\n", v.toChars(), sc.scopesym.toChars());
+			if (sc.scopesym.members)
+				sc.scopesym.members.push(cast(void*)v);
+			}
+
+			Expression e = new DsymbolExp(loc, v);
+			exps.data[i] = cast(void*)e;
+		}
+		TupleDeclaration v2 = new TupleDeclaration(loc, ident, exps);
+		v2.isexp = 1;
+		aliassym = v2;
+		return;
+		}
+
+	Lagain:
+		/* Storage class can modify the type
+		 */
+		type = type.addStorageClass(storage_class);
+
+		/* Adjust storage class to reflect type
+		 */
+		if (type.isConst())
+		{	storage_class |= STC.STCconst;
+		if (type.isShared())
+			storage_class |= STC.STCshared;
+		}
+		else if (type.isInvariant())
+		storage_class |= STC.STCimmutable;
+		else if (type.isShared())
+		storage_class |= STC.STCshared;
+
+		if (isSynchronized())
+		{
+		error("variable %s cannot be synchronized", toChars());
+		}
+		else if (isOverride())
+		{
+		error("override cannot be applied to variable");
+		}
+		else if (isAbstract())
+		{
+		error("abstract cannot be applied to variable");
+		}
+		else if (storage_class & STC.STCfinal)
+		{
+		error("final cannot be applied to variable");
+		}
+
+		if (storage_class & (STC.STCstatic | STC.STCextern | STC.STCmanifest | STC.STCtemplateparameter | STC.STCtls | STC.STCgshared))
+		{
+		}
+		else
+		{
+		AggregateDeclaration aad = sc.anonAgg;
+		if (!aad)
+			aad = parent.isAggregateDeclaration();
+		if (aad)
+		{
+///version (DMDV2) {
+			assert(!(storage_class & (STC.STCextern | STC.STCstatic | STC.STCtls | STC.STCgshared)));
+
+			if (storage_class & (STC.STCconst | STC.STCimmutable) && init)
+			{
+			if (!type.toBasetype().isTypeBasic())
+				storage_class |= STC.STCstatic;
+			}
+			else
+///}
+			aad.addField(sc, this);
+		}
+
+		InterfaceDeclaration id = parent.isInterfaceDeclaration();
+		if (id)
+		{
+			error("field not allowed in interface");
+		}
+
+		/* Templates cannot add fields to aggregates
+		 */
+		TemplateInstance ti = parent.isTemplateInstance();
+		if (ti)
+		{
+			// Take care of nested templates
+			while (1)
+			{
+			TemplateInstance ti2 = ti.tempdecl.parent.isTemplateInstance();
+			if (!ti2)
+				break;
+			ti = ti2;
+			}
+
+			// If it's a member template
+			AggregateDeclaration ad = ti.tempdecl.isMember();
+			if (ad && storage_class != STC.STCundefined)
+			{
+			error("cannot use template to add field to aggregate '%s'", ad.toChars());
+			}
+		}
+		}
+
+version (DMDV2) {
+		if ((storage_class & (STC.STCref | STC.STCparameter | STC.STCforeach)) == STC.STCref && ident != Id.This)
+		{
+			error("only parameters or foreach declarations can be ref");
+		}
+}
+
+		if (type.isauto() && !noauto)
+		{
+			if (storage_class & (STC.STCfield | STC.STCout | STC.STCref | STC.STCstatic | STC.STCmanifest | STC.STCtls | STC.STCgshared) || !fd)
+			{
+				error("globals, statics, fields, manifest constants, ref and out parameters cannot be scope");
+			}
+
+			if (!(storage_class & (STC.STCauto | STC.STCscope)))
+			{
+				if (!(storage_class & STC.STCparameter) && ident != Id.withSym)
+				error("reference to scope class must be scope");
+			}
+		}
+
+		if ((isConst() || isInvariant()) && !init && !fd)
+		{
+			// Initialize by constructor only
+			storage_class |= STC.STCctorinit;
+		}
+
+		if (init)
+			storage_class |= STC.STCinit;     // remember we had an explicit initializer
+		else if (storage_class & STC.STCmanifest)
+			error("manifest constants must have initializers");
+
+		TOK op = TOK.TOKconstruct;
+		if (!init && !sc.inunion && !isStatic() && fd &&
+		(!(storage_class & (STC.STCfield | STC.STCin | STC.STCforeach | STC.STCparameter)) || (storage_class & STC.STCout)) &&
+		type.size() != 0)
+		{
+		// Provide a default initializer
+		//printf("Providing default initializer for '%s'\n", toChars());
+		if (type.ty == TY.Tstruct &&
+			(cast(TypeStruct)type).sym.zeroInit)
+		{   /* If a struct is all zeros, as a special case
+			 * set it's initializer to the integer 0.
+			 * In AssignExp.toElem(), we check for this and issue
+			 * a memset() to initialize the struct.
+			 * Must do same check in interpreter.
+			 */
+			Expression e = new IntegerExp(loc, 0, Type.tint32);
+			Expression e1;
+			e1 = new VarExp(loc, this);
+			e = new AssignExp(loc, e1, e);
+			e.op = TOK.TOKconstruct;
+			e.type = e1.type;		// don't type check this, it would fail
+			init = new ExpInitializer(loc, e);
+			return;
+		}
+		else if (type.ty == TY.Ttypedef)
+		{   TypeTypedef td = cast(TypeTypedef)type;
+			if (td.sym.init)
+			{	init = td.sym.init;
+			ExpInitializer ie = init.isExpInitializer();
+			if (ie)
+				// Make copy so we can modify it
+				init = new ExpInitializer(ie.loc, ie.exp);
+			}
+			else
+			init = getExpInitializer();
+		}
+		else
+		{
+			init = getExpInitializer();
+		}
+		// Default initializer is always a blit
+		op = TOK.TOKblit;
+		}
+
+		if (init)
+		{
+		sc = sc.push();
+		sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref);
+
+		ArrayInitializer ai = init.isArrayInitializer();
+		if (ai && tb.ty == TY.Taarray)
+		{
+			init = ai.toAssocArrayInitializer();
+		}
+
+		StructInitializer si = init.isStructInitializer();
+		ExpInitializer ei = init.isExpInitializer();
+
+		// See if initializer is a NewExp that can be allocated on the stack
+		if (ei && isScope() && ei.exp.op == TOK.TOKnew)
+		{   NewExp ne = cast(NewExp)ei.exp;
+			if (!(ne.newargs && ne.newargs.dim))
+			{	ne.onstack = 1;
+			onstack = 1;
+			if (type.isBaseOf(ne.newtype.semantic(loc, sc), null))
+				onstack = 2;
+			}
+		}
+
+		// If inside function, there is no semantic3() call
+		if (sc.func)
+		{
+			// If local variable, use AssignExp to handle all the various
+			// possibilities.
+			if (fd &&
+			!(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) &&
+			!init.isVoidInitializer())
+			{
+			//printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars());
+			if (!ei)
+			{
+				Expression e = init.toExpression();
+				if (!e)
+				{
+				init = init.semantic(sc, type);
+				e = init.toExpression();
+				if (!e)
+				{   error("is not a static and cannot have static initializer");
+					return;
+				}
+				}
+				ei = new ExpInitializer(init.loc, e);
+				init = ei;
+			}
+
+			Expression e1 = new VarExp(loc, this);
+
+			Type t = type.toBasetype();
+			if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout)))
+			{
+				ei.exp = ei.exp.semantic(sc);
+				if (!ei.exp.implicitConvTo(type))
+				{
+				int dim = cast(int)(cast(TypeSArray)t).dim.toInteger();	///
+				// If multidimensional static array, treat as one large array
+				while (1)
+				{
+					t = t.nextOf().toBasetype();
+					if (t.ty != TY.Tsarray)
+						break;
+					dim *= (cast(TypeSArray)t).dim.toInteger();
+					e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex));
+				}
+				}
+				e1 = new SliceExp(loc, e1, null, null);
+			}
+			else if (t.ty == TY.Tstruct)
+			{
+				ei.exp = ei.exp.semantic(sc);
+version (DMDV2) {
+				/* Look to see if initializer is a call to the constructor
+				 */
+				StructDeclaration sd = (cast(TypeStruct)t).sym;
+				if (sd.ctor &&		// there are constructors
+				ei.exp.type.ty == TY.Tstruct &&	// rvalue is the same struct
+				(cast(TypeStruct)ei.exp.type).sym == sd &&
+				ei.exp.op == TOK.TOKstar)
+				{
+				/* Look for form of constructor call which is:
+				 *    *__ctmp.ctor(arguments...)
+				 */
+				PtrExp pe = cast(PtrExp)ei.exp;
+				if (pe.e1.op == TOK.TOKcall)
+				{   CallExp ce = cast(CallExp)pe.e1;
+					if (ce.e1.op == TOK.TOKdotvar)
+					{	DotVarExp dve = cast(DotVarExp)ce.e1;
+					if (dve.var.isCtorDeclaration())
+					{   /* It's a constructor call, currently constructing
+						 * a temporary __ctmp.
+						 */
+						/* Before calling the constructor, initialize
+						 * variable with a bit copy of the default
+						 * initializer
+						 */
+						Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc));
+						e.op = TOK.TOKblit;
+						e.type = t;
+						ei.exp = new CommaExp(loc, e, ei.exp);
+
+						/* Replace __ctmp being constructed with e1
+						 */
+						dve.e1 = e1;
+						return;
+					}
+					}
+				}
+				}
+}
+				if (!ei.exp.implicitConvTo(type))
+				{	Type ti = ei.exp.type.toBasetype();
+				// Don't cast away invariant or mutability in initializer
+				if (!(ti.ty == TY.Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc)))
+					ei.exp = new CastExp(loc, ei.exp, type);
+				}
+			}
+			ei.exp = new AssignExp(loc, e1, ei.exp);
+			ei.exp.op = op;
+			canassign++;
+			ei.exp = ei.exp.semantic(sc);
+			canassign--;
+			ei.exp.optimize(WANT.WANTvalue);
+			}
+			else
+			{
+			init = init.semantic(sc, type);
+			}
+		}
+		else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) ||
+			 type.isConst() || type.isInvariant())
+		{
+			/* Because we may need the results of a const declaration in a
+			 * subsequent type, such as an array dimension, before semantic2()
+			 * gets ordinarily run, try to run semantic2() now.
+			 * Ignore failure.
+			 */
+
+			if (!global.errors && !inferred)
+			{
+			uint errors = global.errors;
+			global.gag++;
+			//printf("+gag\n");
+			Expression e;
+			Initializer i2 = init;
+			inuse++;
+			if (ei)
+			{
+				e = ei.exp.syntaxCopy();
+				e = e.semantic(sc);
+				e = e.implicitCastTo(sc, type);
+			}
+			else if (si || ai)
+			{   i2 = init.syntaxCopy();
+				i2 = i2.semantic(sc, type);
+			}
+			inuse--;
+			global.gag--;
+			//printf("-gag\n");
+			if (errors != global.errors)	// if errors happened
+			{
+				if (global.gag == 0)
+				global.errors = errors;	// act as if nothing happened
+version (DMDV2) {
+				/* Save scope for later use, to try again
+				 */
+				scope_ = new Scope(sc);
+				scope_.setNoFree();
+}
+			}
+			else if (ei)
+			{
+				if (isDataseg())
+					/* static const/invariant does CTFE
+					 */
+					e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+				else
+					e = e.optimize(WANT.WANTvalue);
+				if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64)
+				{
+					ei.exp = e;		// no errors, keep result
+				}
+///version (DMDV2) {
+				else
+				{
+				/* Save scope for later use, to try again
+				 */
+				scope_ = new Scope(sc);
+				scope_.setNoFree();
+				}
+///}
+			}
+			else
+				init = i2;		// no errors, keep result
+			}
+		}
+		sc = sc.pop();
+		}
+	}
+
+    void semantic2(Scope sc)
+	{
+		//printf("VarDeclaration.semantic2('%s')\n", toChars());
+		if (init && !toParent().isFuncDeclaration())
+		{	
+			inuse++;
+static if (false) {
+			ExpInitializer ei = init.isExpInitializer();
+			if (ei)
+			{
+				ei.exp.dump(0);
+				printf("type = %p\n", ei.exp.type);
+			}
+}
+			init = init.semantic(sc, type);
+			inuse--;
+		}
+	}
+
+    string kind()
+	{
+		return "variable";
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+version (_DH) {
+    Type htype;
+    Initializer hinit;
+}
+    bool needThis()
+	{
+		//printf("VarDeclaration.needThis(%s, x%x)\n", toChars(), storage_class);
+		return (storage_class & STC.STCfield) != 0;
+	}
+	
+    bool isImportedSymbol()
+	{
+		if (protection == PROT.PROTexport && !init && (storage_class & STC.STCstatic || parent.isModule()))
+			return true;
+
+		return false;
+	}
+
+    bool isDataseg()
+	{
+static if (false) {
+		printf("VarDeclaration.isDataseg(%p, '%s')\n", this, toChars());
+		printf("%x, %p, %p\n", storage_class & (STC.STCstatic | STC.STCconst), parent.isModule(), parent.isTemplateInstance());
+		printf("parent = '%s'\n", parent.toChars());
+}
+		if (storage_class & STC.STCmanifest)
+			return false;
+
+		Dsymbol parent = this.toParent();
+		if (!parent && !(storage_class & STC.STCstatic))
+		{	
+			error("forward referenced");
+			type = Type.terror;
+			return false;
+		}
+
+		return canTakeAddressOf() && (storage_class & (STC.STCstatic | STC.STCextern | STC.STCtls | STC.STCgshared) || toParent().isModule() || toParent().isTemplateInstance());
+	}
+	
+    bool isThreadlocal()
+	{
+		//printf("VarDeclaration.isThreadlocal(%p, '%s')\n", this, toChars());
+static if (false) { /// || TARGET_OSX
+		/* To be thread-local, must use the __thread storage class.
+		 * BUG: OSX doesn't support thread local yet.
+		 */
+		return isDataseg() && (storage_class & (STC.STCtls | STC.STCconst | STC.STCimmutable | STC.STCshared | STC.STCgshared)) == STC.STCtls;
+} else {
+		/* Data defaults to being thread-local. It is not thread-local
+		 * if it is immutable, const or shared.
+		 */
+		bool i = isDataseg() && !(storage_class & (STC.STCimmutable | STC.STCconst | STC.STCshared | STC.STCgshared));
+		//printf("\treturn %d\n", i);
+		return i;
+}
+	}
+	
+    bool hasPointers()
+	{
+		//printf("VarDeclaration.hasPointers() %s, ty = %d\n", toChars(), type.ty);
+		return (!isDataseg() && type.hasPointers());
+	}
+	
+version (DMDV2) {
+    bool canTakeAddressOf()
+	{
+static if (false) {
+		/* Global variables and struct/class fields of the form:
+		 *	const int x = 3;
+		 * are not stored and hence cannot have their address taken.
+		 */
+		if ((isConst() || isInvariant()) && (storage_class & STC.STCinit) && (!(storage_class & (STC.STCstatic | STC.STCextern)) || (storage_class & STC.STCfield)) &&
+			(!parent || toParent().isModule() || toParent().isTemplateInstance()) && type.toBasetype().isTypeBasic())
+		{
+			return false;
+		}
+} else {
+		if (storage_class & STC.STCmanifest)
+			return false;
+}
+		return true;
+	}
+	
+    int needsAutoDtor()
+	{
+		assert(false);
+	}
+}
+
+	/******************************************
+	 * If a variable has an auto destructor call, return call for it.
+	 * Otherwise, return null.
+	 */
+    Expression callAutoDtor(Scope sc)
+	{
+		Expression e = null;
+
+		//printf("VarDeclaration.callAutoDtor() %s\n", toChars());
+
+		if (noauto || storage_class & STC.STCnodtor)
+			return null;
+
+		// Destructors for structs and arrays of structs
+		bool array = false;
+		Type tv = type.toBasetype();
+		while (tv.ty == TY.Tsarray)
+		{   
+			TypeSArray ta = cast(TypeSArray)tv;
+			array = true;
+			tv = tv.nextOf().toBasetype();
+		}
+		if (tv.ty == TY.Tstruct)
+		{   
+			TypeStruct ts = cast(TypeStruct)tv;
+			StructDeclaration sd = ts.sym;
+			if (sd.dtor)
+			{
+				if (array)
+				{
+					// Typeinfo.destroy(cast(void*)&v);
+					Expression ea = new SymOffExp(loc, this, 0, 0);
+					ea = new CastExp(loc, ea, Type.tvoid.pointerTo());
+					Expressions args = new Expressions();
+					args.push(cast(void*)ea);
+
+					Expression et = type.getTypeInfo(sc);
+					et = new DotIdExp(loc, et, Id.destroy);
+
+					e = new CallExp(loc, et, args);
+				}
+				else
+				{
+					e = new VarExp(loc, this);
+					e = new DotVarExp(loc, e, sd.dtor, 0);
+					e = new CallExp(loc, e);
+				}
+				return e;
+			}
+		}
+
+		// Destructors for classes
+		if (storage_class & (STC.STCauto | STC.STCscope))
+		{
+			for (ClassDeclaration cd = type.isClassHandle(); cd; cd = cd.baseClass)
+			{
+				/* We can do better if there's a way with onstack
+				 * 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;
+					Expression ec = new VarExp(loc, this);
+					e = new DeleteExp(loc, ec);
+					e.type = Type.tvoid;
+					break;
+				}
+			}
+		}
+		return e;
+	}
+
+	/****************************
+	 * Get ExpInitializer for a variable, if there is one.
+	 */
+    ExpInitializer getExpInitializer()
+	{
+		ExpInitializer ei;
+
+		if (init)
+			ei = init.isExpInitializer();
+		else
+		{
+			Expression e = type.defaultInit(loc);
+			if (e)
+				ei = new ExpInitializer(loc, e);
+			else
+				ei = null;
+		}
+		return ei;
+	}
+
+	/*******************************************
+	 * If variable has a constant expression initializer, get it.
+	 * Otherwise, return null.
+	 */
+    Expression getConstInitializer()
+	{
+		if ((isConst() || isInvariant() || storage_class & STC.STCmanifest) && storage_class & STC.STCinit)
+		{
+			ExpInitializer ei = getExpInitializer();
+			if (ei)
+				return ei.exp;
+		}
+
+		return null;
+	}
+
+    void checkCtorConstInit()
+	{
+	static if (false) { /* doesn't work if more than one static ctor */
+		if (ctorinit == 0 && isCtorinit() && !(storage_class & STCfield))
+			error("missing initializer in static constructor for const variable");
+	}
+	}
+
+	/************************************
+	 * Check to see if this variable is actually in an enclosing function
+	 * rather than the current one.
+	 */
+    void checkNestedReference(Scope sc, Loc loc)
+	{
+		if (parent && !isDataseg() && parent != sc.parent && !(storage_class & STC.STCmanifest))
+		{
+			// The function that this variable is in
+			FuncDeclaration fdv = toParent().isFuncDeclaration();
+			// The current function
+			FuncDeclaration fdthis = sc.parent.isFuncDeclaration();
+
+			if (fdv && fdthis && fdv !is fdthis)
+			{
+				if (loc.filename)
+					fdthis.getLevel(loc, fdv);
+
+				for (int i = 0; i < nestedrefs.dim; i++)
+				{	
+					FuncDeclaration f = cast(FuncDeclaration)nestedrefs.data[i];
+					if (f == fdthis)
+						goto L1;
+				}
+				nestedrefs.push(cast(void*)fdthis);
+			  L1: ;
+
+				for (int i = 0; i < fdv.closureVars.dim; i++)
+				{	
+					Dsymbol s = cast(Dsymbol)fdv.closureVars.data[i];
+					if (s == this)
+						goto L2;
+				}
+
+				fdv.closureVars.push(cast(void*)this);
+			  L2: ;
+
+				//printf("fdthis is %s\n", fdthis.toChars());
+				//printf("var %s in function %s is nested ref\n", toChars(), fdv.toChars());
+			}
+		}
+	}
+
+    Dsymbol toAlias()
+	{
+		//printf("VarDeclaration::toAlias('%s', this = %p, aliassym = %p)\n", toChars(), this, aliassym);
+		assert(this !is aliassym);
+		return aliassym ? aliassym.toAlias() : this;
+	}
+
+    Symbol* toSymbol()
+	{
+		//printf("VarDeclaration.toSymbol(%s)\n", toChars());
+		//if (needThis()) *(char*)0=0;
+		assert(!needThis());
+		if (!csym)
+		{	
+			Symbol* s;
+			TYPE* t;
+			string id;
+
+			if (isDataseg())
+				id = mangle();
+			else
+				id = ident.toChars();
+
+			s = symbol_calloc(toStringz(id));
+
+			if (storage_class & (STC.STCout | STC.STCref))
+			{
+				if (global.params.symdebug && storage_class & STC.STCparameter)
+				{
+					t = type_alloc(TYM.TYnptr);		// should be TYref, but problems in back end
+					t.Tnext = type.toCtype();
+					t.Tnext.Tcount++;
+				}
+				else
+					t = type_fake(TYM.TYnptr);
+			}
+			else if (storage_class & STC.STClazy)
+				t = type_fake(TYM.TYdelegate);		// Tdelegate as C type
+			else if (isParameter())
+				t = type.toCParamtype();
+			else
+				t = type.toCtype();
+
+			t.Tcount++;
+
+			if (isDataseg())
+			{
+				if (isThreadlocal())
+				{	
+					/* Thread local storage
+					 */
+					TYPE* ts = t;
+					ts.Tcount++;	// make sure a different t is allocated
+					type_setty(&t, t.Tty | mTY.mTYthread);
+					ts.Tcount--;
+
+					if (global.params.vtls)
+					{
+						string p = loc.toChars();
+						writef("%s: %s is thread local\n", p ? p : "", toChars());
+					}
+				}
+
+				s.Sclass = SC.SCextern;
+				s.Sfl = FL.FLextern;
+				slist_add(s);
+			}
+			else
+			{
+				s.Sclass = SC.SCauto;
+				s.Sfl = FL.FLauto;
+
+				if (nestedrefs.dim)
+				{
+					/* Symbol is accessed by a nested function. Make sure
+					 * it is not put in a register, and that the optimizer
+					 * assumes it is modified across function calls and pointer
+					 * dereferences.
+					 */
+					//printf("\tnested ref, not register\n");
+					type_setcv(&t, t.Tty | mTY.mTYvolatile);
+				}
+			}
+
+			mangle_t m = 0;
+			switch (linkage)
+			{
+				case LINK.LINKwindows:
+					m = mTYman.mTYman_std;
+					break;
+
+				case LINK.LINKpascal:
+					m = mTYman.mTYman_pas;
+					break;
+
+				case LINK.LINKc:
+					m = mTYman.mTYman_c;
+					break;
+
+				case LINK.LINKd:
+					m = mTYman.mTYman_d;
+					break;
+
+				case LINK.LINKcpp:
+					m = mTYman.mTYman_cpp;
+					break;
+
+				default:
+					writef("linkage = %d\n", linkage);
+					assert(0);
+			}
+			type_setmangle(&t, m);
+			s.Stype = t;
+
+			csym = s;
+		}
+		return csym;
+	}
+
+    void toObjFile(int multiobj)			// compile to .obj file
+	{
+		Symbol* s;
+		uint sz;
+		Dsymbol parent;
+
+		//printf("VarDeclaration.toObjFile(%p '%s' type=%s) protection %d\n", this, toChars(), type.toChars(), protection);
+		//printf("\talign = %d\n", type.alignsize());
+
+		if (aliassym)
+		{	
+			toAlias().toObjFile(0);
+			return;
+		}
+
+	version (DMDV2) {
+		// Do not store variables we cannot take the address of
+		if (!canTakeAddressOf())
+		{
+			return;
+		}
+	}
+
+		if (isDataseg() && !(storage_class & STC.STCextern))
+		{
+			s = toSymbol();
+			sz = cast(uint)type.size();
+
+			parent = this.toParent();
+///		version (DMDV1) {	/* private statics should still get a global symbol, in case
+///			 * another module inlines a function that references it.
+///			 */
+///			if (/*protection == PROT.PROTprivate ||*/
+///				!parent || parent.ident == null || parent.isFuncDeclaration())
+///			{
+///				s.Sclass = SC.SCstatic;
+///			}
+///			else
+///		}
+			{
+				if (storage_class & STC.STCcomdat)
+					s.Sclass = SC.SCcomdat;
+				else
+					s.Sclass = SC.SCglobal;
+
+				do
+				{
+					/* Global template data members need to be in comdat's
+					 * in case multiple .obj files instantiate the same
+					 * template with the same types.
+					 */
+					if (parent.isTemplateInstance() && !parent.isTemplateMixin())
+					{
+		version (DMDV1) {
+						/* These symbol constants have already been copied,
+						 * so no reason to output them.
+						 * Note that currently there is no way to take
+						 * the address of such a const.
+						 */
+						if (isConst() && type.toBasetype().ty != TY.Tsarray && init && init.isExpInitializer())
+							return;
+		}
+						s.Sclass = SC.SCcomdat;
+						break;
+					}
+					parent = parent.parent;
+				} while (parent);
+			}
+
+			s.Sfl = FL.FLdata;
+
+			if (init)
+			{   
+				s.Sdt = init.toDt();
+
+				// Look for static array that is block initialized
+				Type tb;
+				ExpInitializer ie = init.isExpInitializer();
+
+				tb = type.toBasetype();
+				if (tb.ty == TY.Tsarray && ie
+					&& !tb.nextOf().equals(ie.exp.type.toBasetype().nextOf())
+					&& ie.exp.implicitConvTo(tb.nextOf()))
+				{
+					int dim = cast(int)(cast(TypeSArray)tb).dim.toInteger();
+
+					// Duplicate Sdt 'dim-1' times, as we already have the first one
+					while (--dim > 0)
+					{
+						ie.exp.toDt(&s.Sdt);
+					}
+				}
+			}
+			else if (storage_class & STC.STCextern)
+			{
+				s.Sclass = SC.SCextern;
+				s.Sfl = FL.FLextern;
+				s.Sdt = null;
+				// BUG: if isExport(), shouldn't we make it dllimport?
+				return;
+			}
+			else
+			{
+				type.toDt(&s.Sdt);
+			}
+			dt_optimize(s.Sdt);
+
+			// See if we can convert a comdat to a comdef,
+			// which saves on exe file space.
+			if (s.Sclass == SC.SCcomdat &&
+				s.Sdt &&
+				s.Sdt.dt == DT.DT_azeros &&
+				s.Sdt.DTnext is null &&
+				!isThreadlocal())
+			{
+				s.Sclass = SC.SCglobal;
+				s.Sdt.dt = DT.DT_common;
+			}
+
+		version (ELFOBJ_OR_MACHOBJ) { // Burton
+			if (s.Sdt && s.Sdt.dt == DT.DT_azeros && s.Sdt.DTnext is null)
+				s.Sseg = Segment.UDATA;
+			else
+				s.Sseg = Segment.DATA;
+		}
+			if (sz)
+			{   
+				outdata(s);
+				if (isExport())
+					obj_export(s, 0);
+			}
+		}
+	}
+
+    int cvMember(ubyte* p)
+	{
+		assert(false);
+	}
+
+    // Eliminate need for dynamic_cast
+    VarDeclaration isVarDeclaration() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VarExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,258 @@
+module dmd.VarExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.FuncLiteralDeclaration;
+import dmd.VarDeclaration;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.TY;
+import dmd.STC;
+import dmd.SymbolExp;
+import dmd.Type;
+import dmd.backend.dt_t;
+import dmd.expression.Util;
+
+// Variable
+
+class VarExp : SymbolExp
+{
+	this(Loc loc, Declaration var, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads);
+		
+		//printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars());
+		//if (strcmp(var.ident.toChars(), "func") == 0) halt();
+		this.type = var.type;
+	}
+
+	int equals(Object o)
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		FuncLiteralDeclaration fd;
+
+	version (LOGSEMANTIC) {
+		printf("VarExp.semantic(%s)\n", toChars());
+	}
+		if (!type)
+		{
+			type = var.type;
+static if (false) {
+			if (var.storage_class & STC.STClazy)
+			{
+				TypeFunction tf = new TypeFunction(null, type, 0, LINK.LINKd);
+				type = new TypeDelegate(tf);
+				type = type.semantic(loc, sc);
+			}
+}
+		}
+
+		/* Fix for 1161 doesn't work because it causes protection
+		 * problems when instantiating imported templates passing private
+		 * variables as alias template parameters.
+		 */
+		//accessCheck(loc, sc, null, var);
+
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+		{
+static if (false) {
+			if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init)
+			{
+				ExpInitializer ei = v.init.isExpInitializer();
+				if (ei)
+				{
+					//ei.exp.implicitCastTo(sc, type).print();
+					return ei.exp.implicitCastTo(sc, type);
+				}
+			}
+}
+			v.checkNestedReference(sc, loc);
+version (DMDV2) {
+	static if (true) {
+			if (sc.func)
+			{
+				/* Determine if sc.func is pure or if any function that
+				 * encloses it is also pure.
+				 */
+				bool hasPureParent = false;
+				for (FuncDeclaration outerfunc = sc.func; outerfunc;)
+				{
+					if (outerfunc.isPure())
+					{
+						hasPureParent = true;
+						break;
+					}
+					Dsymbol parent = outerfunc.toParent2();
+					if (!parent)
+						break;
+					outerfunc = parent.isFuncDeclaration();
+				}
+
+				/* If ANY of its enclosing functions are pure,
+				 * it cannot do anything impure.
+				 * If it is pure, it cannot access any mutable variables other
+				 * than those inside itself
+				 */
+				if (hasPureParent && !sc.intypeof && v.isDataseg() && !v.isInvariant())
+				{
+					error("pure function '%s' cannot access mutable static data '%s'",
+						sc.func.toChars(), v.toChars());
+				}
+				else if (sc.func.isPure() && sc.parent != v.parent && !sc.intypeof && !v.isInvariant() && !(v.storage_class & STC.STCmanifest))
+				{
+					error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars());
+					if (v.isEnumDeclaration())
+						error("enum");
+				}	
+			}
+	} else {
+			if (sc.func && sc.func.isPure() && !sc.intypeof)
+			{
+				if (v.isDataseg() && !v.isInvariant())
+					error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars());
+			}
+	}
+}
+		}
+		else
+		{
+static if (false) {
+			if ((fd = var.isFuncLiteralDeclaration()) !is null)
+			{	
+				Expression e = new FuncExp(loc, fd);
+				e.type = type;
+				return e;
+			}
+}
+		}
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		return fromConstInitializer(result, this);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+		return var.toChars();
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(var.toChars());
+	}
+
+	void checkEscape()
+	{
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+		{	
+			Type tb = v.type.toBasetype();
+			// if reference type
+			if (tb.ty == TY.Tarray || tb.ty == TY.Tsarray || tb.ty == TY.Tclass)
+			{
+				if ((v.isAuto() || v.isScope()) && !v.noauto)
+					error("escaping reference to scope local %s", v.toChars());
+				else if (v.storage_class & STC.STCvariadic)
+					error("escaping reference to variadic parameter %s", v.toChars());
+			}
+		}
+	}
+
+version (DMDV2) {
+	int isLvalue()
+	{
+		if (var.storage_class & STClazy)
+			return 0;
+		return 1;
+	}
+}
+	Expression toLvalue(Scope sc, Expression e)
+	{
+static if (false) {
+		tym = tybasic(e1.ET.Tty);
+		if (!(tyscalar(tym) ||
+		  tym == TYM.TYstruct ||
+		  tym == TYM.TYarray && e.Eoper == TOK.TOKaddr))
+		{
+			synerr(EM_lvalue);	// lvalue expected
+		}
+}
+		if (var.storage_class & STC.STClazy)
+			error("lazy variables cannot be lvalues");
+
+		return this;
+	}
+
+	Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		//printf("VarExp::modifiableLvalue('%s')\n", var.toChars());
+		if (type && type.toBasetype().ty == TY.Tsarray)
+			error("cannot change reference to static array '%s'", var.toChars());
+
+		var.checkModify(loc, sc, type);
+
+		// See if this expression is a modifiable lvalue (i.e. not const)
+		return toLvalue(sc, e);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		//printf("VarExp.inlineCost() %s\n", toChars());
+		return 1;
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		int i;
+
+		//printf("VarExp.doInline(%s)\n", toChars());
+		for (i = 0; i < ids.from.dim; i++)
+		{
+			if (var == cast(Declaration)ids.from.data[i])
+			{
+				VarExp ve = cast(VarExp)copy();
+
+				ve.var = cast(Declaration)ids.to.data[i];
+				return ve;
+			}
+		}
+		return this;
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VersionCondition.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,140 @@
+module dmd.VersionCondition;
+
+import dmd.DVCondition;
+import dmd.Loc;
+import dmd.Module;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Identifier;
+import dmd.Global;
+import dmd.String;
+import dmd.Util : error;
+
+import std.string : startsWith;
+
+// for findCondition
+import dmd.Array;
+import core.stdc.string;
+
+import std.stdio;
+
+bool findCondition(Array ids, Identifier ident)
+{
+    if (ids !is null) {
+		foreach (i; 0..ids.dim)
+		{
+			string id = (cast(String)ids.data[i]).str;
+			if (id == ident.toChars()) {
+				return true;
+			}
+		}
+    }
+
+    return false;
+}
+
+class VersionCondition : DVCondition
+{
+    static void setGlobalLevel(uint level)
+	{
+		global.params.versionlevel = level;
+	}
+	
+    static void checkPredefined(Loc loc, string ident)
+	{
+version (DMDV2) {
+		static string[] reserved = [
+			"DigitalMars", "X86", "X86_64",
+			"Windows", "Win32", "Win64",
+			"linux",
+			/* Although Posix is predefined by D1, disallowing its
+			 * redefinition breaks makefiles and older builds.
+			 */
+			"Posix",
+			"D_NET",
+			"OSX", "FreeBSD",
+			"Solaris",
+			"LittleEndian", "BigEndian",
+			"all",
+			"none",
+		];
+} else {
+		static string[] reserved = [
+			"DigitalMars", "X86", "X86_64",
+			"Windows", "Win32", "Win64",
+			"linux",
+			"OSX", "FreeBSD",
+			"Solaris",
+			"LittleEndian", "BigEndian",
+			"all",
+			"none",
+		];
+}
+		foreach (reservedIdent; reserved)
+		{
+			if (ident == reservedIdent)
+				goto Lerror;
+		}
+
+		if (ident.startsWith("D_")) {
+			goto Lerror;
+		}
+
+		return;
+
+	  Lerror:
+		error(loc, "version identifier '%s' is reserved and cannot be set", ident);
+	}
+	
+    static void addGlobalIdent(string ident)
+	{
+		checkPredefined(Loc(0), ident);
+		addPredefinedGlobalIdent(ident);
+	}
+	
+    static void addPredefinedGlobalIdent(string ident)
+	{
+		global.params.versionids.push(cast(void*)new String(ident));	///
+	}
+
+    this(Module mod, uint level, Identifier ident)
+	{
+		super(mod, level, ident);
+	}
+
+    final bool include(Scope sc, ScopeDsymbol s)
+	{
+		//printf("VersionCondition::include() level = %d, versionlevel = %d\n", level, global.params.versionlevel);
+		//if (ident) printf("\tident = '%s'\n", ident->toChars());
+		if (inc == 0) {
+			inc = 2;
+			if (ident !is null) {
+				if (findCondition(mod.versionids, ident)) {
+					inc = 1;
+				} else if (findCondition(global.params.versionids, ident)) {
+					inc = 1;
+				} else {
+					if (!mod.versionidsNot) {
+						mod.versionidsNot = new Array();
+					}
+					mod.versionidsNot.push(cast(void*)new String(ident.toChars()));	//
+				}
+			} else if (level <= global.params.versionlevel || level <= mod.versionlevel) {
+				inc = 1;
+			}
+		}
+
+		return (inc == 1);
+	}
+	
+    final void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		if (ident !is null) {
+			buf.printf("version (%s)", ident.toChars());
+		} else {
+			buf.printf("version (%u)", level);
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VersionSymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,87 @@
+module dmd.VersionSymbol;
+
+import dmd.Dsymbol;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Module;
+import dmd.Array;
+import dmd.VersionCondition;
+import dmd.Scope;
+import dmd.ScopeDsymbol;
+import dmd.HdrGenState;
+import dmd.String;
+import dmd.OutBuffer;
+
+class VersionSymbol : Dsymbol
+{
+    uint level;
+
+	/* VersionSymbol's happen for statements like:
+	 *	version = identifier;
+	 *	version = integer;
+	 */
+    this(Loc loc, Identifier ident)
+	{
+		super(ident);
+		this.loc = loc;
+	}
+	
+    this(Loc loc, uint level)
+	{
+		super();
+
+		this.level = level;
+		this.loc = loc;
+	}
+	
+    Dsymbol syntaxCopy(Dsymbol s)
+	{
+		assert(false);
+	}
+	
+    bool addMember(Scope sc, ScopeDsymbol s, int memnum)
+	{
+		//printf("VersionSymbol::addMember('%s') %s\n", sd->toChars(), toChars());
+
+		// Do not add the member to the symbol table,
+		// just make sure subsequent debug declarations work.
+		Module m = s.isModule();
+		if (ident)
+		{
+			VersionCondition.checkPredefined(loc, ident.toChars());
+			if (!m)
+				error("declaration must be at module level");
+			else
+			{
+				if (findCondition(m.versionidsNot, ident))
+					error("defined after use");
+				if (!m.versionids)
+					m.versionids = new Array();
+				m.versionids.push(cast(void*)new String(ident.toChars()));
+			}
+		}
+		else
+		{
+			if (!m)
+				error("level declaration must be at module level");
+			else
+				m.versionlevel = level;
+		}
+
+		return false;
+	}
+	
+    void semantic(Scope sc)
+	{
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    string kind()
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VoidInitializer.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,50 @@
+module dmd.VoidInitializer;
+
+import dmd.Initializer;
+import dmd.Type;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.Expression;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+
+import dmd.backend.dt_t;
+
+class VoidInitializer : Initializer
+{
+    Type type = null;		// type that this will initialize to
+
+    this(Loc loc)
+	{
+		super(loc);
+	}
+	
+    Initializer syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Initializer semantic(Scope sc, Type t)
+	{
+		//printf("VoidInitializer.semantic(t = %p)\n", t);
+		type = t;
+		return this;
+	}
+	
+    Expression toExpression()
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    dt_t* toDt()
+	{
+		assert(false);
+	}
+
+    VoidInitializer isVoidInitializer() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VolatileStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,99 @@
+module dmd.VolatileStatement;
+
+import dmd.Statement;
+import dmd.ArrayTypes;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.BE;
+
+import dmd.backend.block;
+import dmd.backend.Blockx;
+import dmd.backend.Util;
+import dmd.backend.BC;
+//import dmd.backend.BFL;
+
+class VolatileStatement : Statement
+{
+    Statement statement;
+
+    this(Loc loc, Statement statement)
+	{
+		super(loc);
+		this.statement = statement;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		if (statement)
+			statement = statement.semantic(sc);
+		return this;
+	}
+	
+    Statements flatten(Scope sc)
+	{
+		Statements a = statement ? statement.flatten(sc) : null;
+		if (a)
+		{	
+			for (int i = 0; i < a.dim; i++)
+			{   
+				Statement s = cast(Statement)a.data[i];
+
+				s = new VolatileStatement(loc, s);
+				a.data[i] = cast(void*)s;
+			}
+		}
+
+		return a;
+	}
+	
+    BE blockExit()
+	{
+		return statement ? statement.blockExit() : BE.BEfallthru;
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		if (statement)
+			statement = statement.inlineScan(iss);
+		return this;
+	}
+
+    void toIR(IRState* irs)
+	{
+		block* b;
+
+		if (statement)
+		{
+			Blockx* blx = irs.blx;
+
+			block_goto(blx, BCgoto, null);
+			b = blx.curblock;
+
+			statement.toIR(irs);
+
+			block_goto(blx, BCgoto, null);
+
+			// Mark the blocks generated as volatile
+			for (; b != blx.curblock; b = b.Bnext)
+			{   
+				b.Bflags |= BFL.BFLvolatile;
+				if (b.Belem)
+					el_setVolatile(b.Belem);
+			}
+		}
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/WANT.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,11 @@
+module dmd.WANT;
+
+enum WANT
+{
+	WANTflags = 1,
+    WANTvalue = 2,
+    WANTinterpret = 4,
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(WANT));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/WhileStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,86 @@
+module dmd.WhileStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.HdrGenState;
+import dmd.OutBuffer;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.Loc;
+import dmd.BE;
+import dmd.ForStatement;
+
+class WhileStatement : Statement
+{
+    Expression condition;
+    Statement body_;
+
+    this(Loc loc, Expression c, Statement b)
+	{
+		super(loc);
+		condition = c;
+		body_ = b;
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		/* Rewrite as a for(;condition;) loop
+		 */
+
+		Statement s = new ForStatement(loc, null, condition, null, body_);
+		s = s.semantic(sc);
+		return s;
+	}
+	
+    bool hasBreak()
+	{
+		assert(false);
+	}
+	
+    bool hasContinue()
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+	
+    bool comeFrom()
+	{
+		assert(false);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+	
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/WithScopeSymbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,24 @@
+module dmd.WithScopeSymbol;
+
+import dmd.ScopeDsymbol;
+import dmd.WithStatement;
+import dmd.Loc;
+import dmd.Identifier;
+import dmd.Dsymbol;
+
+class WithScopeSymbol : ScopeDsymbol
+{
+    WithStatement withstate;
+
+    this(WithStatement withstate)
+	{
+		assert(false);
+	}
+	
+    Dsymbol search(Loc loc, Identifier ident, int flags)
+	{
+		assert(false);
+	}
+
+    WithScopeSymbol isWithScopeSymbol() { return this; }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/WithStatement.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,60 @@
+module dmd.WithStatement;
+
+import dmd.Statement;
+import dmd.Expression;
+import dmd.VarDeclaration;
+import dmd.Loc;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.InlineScanState;
+import dmd.IRState;
+import dmd.Scope;
+import dmd.BE;
+
+class WithStatement : Statement
+{
+    Expression exp;
+    Statement body_;
+    VarDeclaration wthis;
+
+    this(Loc loc, Expression exp, Statement body_)
+	{
+		assert(false);
+		super(loc);
+	}
+	
+    Statement syntaxCopy()
+	{
+		assert(false);
+	}
+	
+    Statement semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+	
+    bool usesEH()
+	{
+		assert(false);
+	}
+	
+    BE blockExit()
+	{
+		assert(false);
+	}
+
+    Statement inlineScan(InlineScanState* iss)
+	{
+		assert(false);
+	}
+
+    void toIR(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/XorAssignExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,53 @@
+module dmd.XorAssignExp;
+
+import dmd.BinExp;
+import dmd.Loc;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.ArrayTypes;
+import dmd.Identifier;
+import dmd.IRState;
+import dmd.Id;
+import dmd.TOK;
+import dmd.backend.elem;
+
+class XorAssignExp : BinExp
+{
+    this(Loc loc, Expression e1, Expression e2)
+	{
+		assert(false);
+		super(loc, TOK.init, 0, e1, e2);
+	}
+	
+    Expression semantic(Scope sc)
+	{
+		assert(false);
+	}
+	
+    Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+	
+    void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+	
+    Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+    Identifier opId()    /* For operator overloading */
+	{
+		return Id.xorass;
+	}
+
+    elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/XorExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,118 @@
+module dmd.XorExp;
+
+import dmd.Expression;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Id;
+import dmd.Type;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IntRange;
+import dmd.IRState;
+import dmd.ArrayTypes;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.TY;
+
+import dmd.backend.elem;
+import dmd.expression.Util;
+import dmd.expression.Xor;
+
+class XorExp : BinExp
+{
+	this(Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, TOK.TOKxor, XorExp.sizeof, e1, e2);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+
+		if (!type)
+		{	
+			BinExp.semanticp(sc);
+			e = op_overload(sc);
+			if (e)
+				return e;
+			if (e1.type.toBasetype().ty == Tbool &&
+				e2.type.toBasetype().ty == Tbool)
+			{
+				type = e1.type;
+				e = this;
+			}
+			else
+			{
+				typeCombine(sc);
+				if (e1.op != TOKslice && e2.op != TOKslice)
+				{
+					e1.checkIntegral();
+					e2.checkIntegral();
+				}
+			}
+		}
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		e1 = e1.optimize(result);
+		e2 = e2.optimize(result);
+		if (e1.isConst() == 1 && e2.isConst() == 1)
+			e = Xor(type, e1, e2);
+		else
+			e = this;
+
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void buildArrayIdent(OutBuffer buf, Expressions arguments)
+	{
+		assert(false);
+	}
+
+	Expression buildArrayLoop(Arguments fparams)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+		assert(false);
+	}
+
+	IntRange getIntRange()
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.ixor;
+	}
+
+	Identifier opId_r()
+	{
+		return Id.ixor_r;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		assert(false);
+	}
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/BC.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,42 @@
+module dmd.backend.BC;
+
+enum BC
+{
+    BCgoto	= 1,	// goto Bsucc block
+    BCiftrue	= 2,	// if (Belem) goto Bsucc[0] else Bsucc[1]
+    BCret	= 3,	// return (no return value)
+    BCretexp	= 4,	// return with return value
+    BCexit	= 5,	// never reaches end of block (like exit() was called)
+    BCasm	= 6,	// inline assembler block (Belem is NULL, Bcode
+			// contains code generated).
+			// These blocks have one or more successors in Bsucc,
+			// never 0
+    BCswitch	= 7,	// switch statement
+			// Bswitch points to switch data
+			// Default is Bsucc
+			// Cases follow in linked list
+    BCifthen	= 8,	// a BCswitch is converted to if-then
+			// statements
+    BCjmptab	= 9,	// a BCswitch is converted to a jump
+			// table (switch value is index into
+			// the table)
+    BCtry	= 10,	// C++ try block
+			// first block in a try-block. The first block in
+			// Bsucc is the next one to go to, subsequent
+			// blocks are the catch blocks
+    BCcatch	= 11,	// C++ catch block
+    BCjump	= 12,	// Belem specifies (near) address to jump to
+    BC_try	= 13,	// SEH: first block of try-except or try-finally
+			// Jupiter, Mars: try-catch or try-finally
+    BC_filter	= 14,	// SEH exception-filter (always exactly one block)
+    BC_finally	= 15,	// first block of SEH termination-handler,
+			// or finally block
+    BC_ret	= 16,	// last block of SEH termination-handler or finally block
+    BC_except	= 17,	// first block of SEH exception-handler
+    BCjcatch	= 18,	// first block of Jupiter or Mars catch-block
+    BCjplace	= 19,	// Jupiter: placeholder
+    BCMAX
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(BC));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Blockx.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,27 @@
+module dmd.backend.Blockx;
+
+import dmd.Module;
+import dmd.Declaration;
+import dmd.ClassDeclaration;
+
+import dmd.backend.Symbol;
+import dmd.backend.block;
+import dmd.backend.elem;
+
+alias Symbol Funcsym;
+
+struct Blockx
+{
+    block* startblock;
+    block* curblock;
+    Funcsym* funcsym;
+    Symbol* context;		// eh frame context variable
+    int scope_index;		// current scope index
+    int next_index;		// value for next scope index
+    uint flags;		// value to OR into Bflags
+    block* tryblock;		// current enclosing try block
+    elem* init;			// static initializer
+    ClassDeclaration classdec;
+    Declaration member;	// member we're compiling for
+    Module module_;		// module we're in
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Classsym.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,5 @@
+module dmd.backend.Classsym;
+
+import dmd.backend.Symbol;
+
+alias Symbol Classsym;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Config.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,259 @@
+module dmd.backend.Config;
+
+import dmd.backend.LINKAGE;
+import dmd.EnumUtils;
+
+extern (C) {
+	void cod3_set64();
+	void cod3_set386();
+}
+
+extern (C++) extern
+{
+	__gshared char debuga;		/* cg - watch assignaddr()		*/
+	__gshared char debugb;		/* watch block optimization		*/
+	__gshared char debugc;		/* watch code generated			*/
+	__gshared char debugd;		/* watch debug information generated	*/
+	__gshared char debuge;		// dump eh info
+	__gshared char debugf;		/* trees after dooptim			*/
+	__gshared char debugg;		/* trees for code generator		*/
+	__gshared char debugo;		// watch optimizer
+	__gshared char debugr;		// watch register allocation
+	__gshared char debugs;		/* watch common subexp eliminator	*/
+	__gshared char debugt;		/* do test points			*/
+	__gshared char debugu;
+	__gshared char debugw;		/* watch progress			*/
+	__gshared char debugx;		/* suppress predefined CPP stuff	*/
+	__gshared char debugy;		/* watch output to il buffer		*/
+}
+
+// This part of the configuration is saved in the precompiled header for use
+// in comparing to make sure it hasn't changed.
+
+enum CFG2
+{
+	CFG2comdat = 1,	// use initialized common blocks
+	CFG2nodeflib = 2,	// no default library imbedded in OBJ file
+	CFG2browse = 4,	// generate browse records
+	CFG2dyntyping = 8,	// generate dynamic typing information
+	CFG2fulltypes = 0x10,	// don't optimize CV4 class info
+	CFG2warniserr = 0x20,	// treat warnings as errors
+	CFG2phauto = 0x40,	// automatic precompiled headers
+	CFG2phuse = 0x80,	// use precompiled headers
+	CFG2phgen = 0x100,	// generate precompiled header
+	CFG2once = 0x200,	// only include header files once
+	CFG2hdrdebug = 0x400,	// generate debug info for header
+	CFG2phautoy = 0x800,	// fast build precompiled headers
+	CFG2noobj = 0x1000,	// we are not generating a .OBJ file
+	CFG2noerrmax = 0x4000,	// no error count maximum
+	CFG2expand = 0x8000,	// expanded output to list file
+	CFG2seh	= 0x10000,	// use Win32 SEH to support any exception handling
+	CFGX2 = (CFG2warniserr | CFG2phuse | CFG2phgen | CFG2phauto | CFG2once | CFG2hdrdebug | CFG2noobj | CFG2noerrmax | CFG2expand | CFG2nodeflib),
+}
+
+enum CFG3ju = 1;	// char == unsigned char
+enum CFG3eh = 4;	// generate exception handling stuff
+enum CFG3strcod = 8;	// strings are placed in code segment
+enum CFG3eseqds = 0x10;	// ES == DS at all times
+enum CFG3ptrchk = 0x20;	// generate pointer validation code
+enum CFG3strictproto = 0x40;	// strict prototyping
+enum CFG3autoproto = 0x80;	// auto prototyping
+enum CFG3rtti = 0x100;	// add RTTI support
+enum CFG3relax = 0x200;	// relaxed type checking (C only)
+enum CFG3cpp = 0x400;	// C++ compile
+enum CFG3igninc = 0x800;	// ignore standard include directory
+version (XXX) {///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS) {
+enum CFG3mars = 0x1000;	// use mars libs and headers
+enum NO_FAR	= true;	// always ignore __far and __huge keywords
+} else {
+enum CFG3nofar = 0x1000;	// ignore __far and __huge keywords
+///enum NO_FAR = (config.flags3 & CFG3nofar);
+}
+enum CFG3noline = 0x2000;	// do not output #line directives
+enum CFG3comment = 0x4000;	// leave comments in preprocessed output
+enum CFG3cppcomment = 0x8000;	// allow C++ style comments
+enum CFG3wkfloat = 0x10000;	// make floating point references weak externs
+enum CFG3digraphs = 0x20000;	// support ANSI C++ digraphs
+///#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+enum CFG3semirelax = 0x40000;	// moderate relaxed type checking
+///#endif
+enum CFG3pic = 0x80000;	// position independent code
+enum CFGX3 = (CFG3strcod | CFG3ptrchk);
+
+enum CFG4speed = 1;	// optimized for speed
+enum CFG4space = 2;	// optimized for space
+enum CFG4optimized = (CFG4speed | CFG4space);
+enum CFG4allcomdat = 4;	// place all functions in COMDATs
+enum CFG4fastfloat = 8;	// fast floating point (-ff)
+enum CFG4fdivcall = 0x10;	// make function call for FDIV opcodes
+enum CFG4tempinst = 0x20;	// instantiate templates for undefined functions
+enum CFG4oldstdmangle = 0x40;	// do stdcall mangling without @
+enum CFG4pascal = 0x80;	// default to pascal linkage
+enum CFG4stdcall = 0x100;	// default to std calling convention
+enum CFG4cacheph = 0x200;	// cache precompiled headers in memory
+enum CFG4alternate = 0x400;	// if alternate digraph tokens
+enum CFG4bool = 0x800;	// support 'bool' as basic type
+enum CFG4wchar_t = 0x1000;	// support 'wchar_t' as basic type
+enum CFG4notempexp = 0x2000;	// no instantiation of template functions
+enum CFG4anew = 0x4000;	// allow operator new[] and delete[] overloading
+enum CFG4oldtmangle = 0x8000;	// use old template name mangling
+enum CFG4dllrtl = 0x10000;	// link with DLL RTL
+enum CFG4noemptybaseopt = 0x40000;	// turn off empty base class optimization
+enum CFG4stackalign = CFG4speed;	// align stack to 8 bytes
+enum CFG4nowchar_t = 0x80000;	// use unsigned short name mangling for wchar_t
+enum CFG4forscope = 0x100000; // new C++ for scoping rules
+enum CFG4warnccast = 0x200000; // warn about C style casts
+enum CFG4adl = 0x400000; // argument dependent lookup
+enum CFG4enumoverload = 0x800000; // enum overloading
+enum CFG4implicitfromvoid = 0x1000000;	// allow implicit cast from void* to T*
+enum CFG4dependent = 0x2000000;	// dependent / non-dependent lookup
+enum CFG4wchar_is_long = 0x4000000;	// wchar_t is 4 bytes
+enum CFG4underscore = 0x8000000;	// prepend _ for C mangling
+enum CFGX4 = (CFG4optimized | CFG4fastfloat | CFG4fdivcall | CFG4tempinst | CFG4cacheph | CFG4notempexp | CFG4stackalign | CFG4dependent);
+enum CFGY4 = (CFG4nowchar_t | CFG4noemptybaseopt | CFG4adl | CFG4enumoverload | CFG4implicitfromvoid | CFG4wchar_is_long | CFG4underscore);
+
+mixin(BringToCurrentScope!(CFG2));
+
+enum TARGET
+{
+	TARGET_8086=		0,
+	TARGET_80286=		2,
+	TARGET_80386=		3,
+	TARGET_80486=		4,
+	TARGET_Pentium=		5,
+	TARGET_PentiumMMX=	6,
+	TARGET_PentiumPro=	7,
+	TARGET_PentiumII=	8,
+	TARGET_AMD64=		9,	//(32 or 64 bit mode)
+}
+
+mixin(BringToCurrentScope!(TARGET));
+
+enum CV4 = 2;		// Codeview 4 symbolic info
+
+struct Config
+{
+    char language;		// 'C' = C, 'D' = C++
+//#define CPP (config.language == 'D')
+    char version_[8];		// = VERSION
+    char exetype[3];		// distinguish exe types so PH
+				// files are distinct (= SUFFIX)
+
+    char target_cpu;		// instruction selection
+    char target_scheduler;	// instruction scheduling (normally same as selection)
+
+    short versionint;		// intermediate file version (= VERSIONINT)
+    int defstructalign;		// struct alignment specified by command line
+    short hxversion;		// HX version number
+    char fulltypes;
+    uint wflags;		// flags for Windows code generation
+
+    char inline8087;		/* 0:	emulator
+				   1:	IEEE 754 inline 8087 code
+				   2:	fast inline 8087 code
+				 */
+    short memmodel;		// 0:S,X,N,F, 1:M, 2:C, 3:L, 4:V
+    uint exe;		// target operating system
+
+///#define EX_flat		(EX_OS2 | EX_NT | EX_LINUX | EX_WIN64 | EX_LINUX64 | \
+///			 EX_OSX | EX_OSX64 | EX_FREEBSD | EX_FREEBSD64 | \
+///			 EX_SOLARIS | EX_SOLARIS64)
+///#define EX_dos		(EX_DOSX | EX_ZPM | EX_RATIONAL | EX_PHARLAP | \
+///			 EX_COM | EX_MZ /*| EX_WIN16*/)
+
+/* CFGX: flags ignored in precompiled headers
+ * CFGY: flags copied from precompiled headers into current config
+ */
+    uint flags;
+    uint flags2;
+    uint flags3;
+    uint flags4;
+    uint flags5;
+///#define CFG5debug	1	// compile in __debug code
+///#define CFG5in		2	// compile in __in code
+///#define CFG5out		4	// compile in __out code
+///#define CFG5invariant	8	// compile in __invariant code
+
+///#if HTOD
+///    unsigned htodFlags;		// configuration for htod
+///#define HTODFinclude	1	// -hi drill down into #include files
+///#define HTODFsysinclude	2	// -hs drill down into system #include files
+///#define HTODFtypedef	4	// -ht drill down into typedefs
+///#define HTODFcdecl	8	// -hc skip C declarations as comments
+///#endif
+    char ansi_c;		// strict ANSI C
+				// 89 for ANSI C89, 99 for ANSI C99
+    char asian_char;		/* 0: normal, 1: Japanese, 2: Chinese	*/
+				/* and Taiwanese, 3: Korean		*/
+    uint threshold;		// data larger than threshold is assumed to
+				// be far (16 bit models only)
+///#define THRESHMAX 0xFFFF	// if threshold == THRESHMAX, all data defaults
+				// to near
+    LINKAGE linkage;	// default function call linkage
+}
+
+extern (C++) extern __gshared Config config;
+
+enum CVNONE = 0;		// No symbolic info
+///enum CVOLD = 1;		// Codeview 1 symbolic info
+///enum CV4 = 2;		// Codeview 4 symbolic info
+///enum CVSYM = 3;		// Symantec format
+///enum CVTDB = 4;		// Symantec format written to file
+///enum CVDWARF_C = 5;		// Dwarf in C format
+///enum CVDWARF_D = 6;		// Dwarf in D format
+///enum CVSTABS = 7;		// Elf Stabs in C format
+
+enum CFGuchar = 1;	// chars are unsigned
+enum CFGsegs = 2;	// new code seg for each far func
+enum CFGtrace = 4;	// output trace functions
+enum CFGglobal = 8;	// make all static functions global
+enum CFGstack = 0x20;	// add stack overflow checking
+enum CFGalwaysframe = 0x40;	// always generate stack frame
+enum CFGnoebp = 0x80;	// do not use EBP as general purpose register
+enum CFGromable = 0x100;	// put switch tables in code segment
+enum CFGeasyomf = 0x200;	// generate Pharlap Easy-OMF format
+enum CFGfarvtbls = 0x800;	// store vtables in far segments
+enum CFGnoinlines = 0x1000;	// do not inline functions
+enum CFGnowarning = 0x8000;	// disable warnings
+enum CFGX = (CFGnowarning);
+
+enum EX_DOSX = 1;	// DOSX 386 program
+enum EX_ZPM = 2;	// ZPM 286 program
+enum EX_RATIONAL = 4;	// RATIONAL 286 program
+enum EX_PHARLAP = 8;	// PHARLAP 386 program
+enum EX_COM = 0x10;	// MSDOS .COM program
+//#define EX_WIN16	0x20	// Windows 3.x 16 bit program
+enum EX_OS2 = 0x40;	// OS/2 2.0 32 bit program
+enum EX_OS1 = 0x80;	// OS/2 1.x 16 bit program
+enum EX_NT = 0x100;	// NT
+enum EX_MZ = 0x200;	// MSDOS real mode program
+enum EX_XENIX = 0x400;
+enum EX_SCOUNIX = 0x800;
+enum EX_UNIXSVR4 = 0x1000;
+enum EX_LINUX = 0x2000;
+enum EX_WIN64 = 0x4000;	// AMD64 and Windows (64 bit mode)
+enum EX_LINUX64 = 0x8000;	// AMD64 and Linux (64 bit mode)
+enum EX_OSX = 0x10000;
+enum EX_OSX64 = 0x20000;
+enum EX_FREEBSD = 0x40000;
+enum EX_FREEBSD64 = 0x80000;
+enum EX_SOLARIS = 0x100000;
+enum EX_SOLARIS64 = 0x200000;
+
+enum WFwindows = 1;	// generating code for Windows app or DLL
+enum WFdll = 2;	// generating code for Windows DLL
+enum WFincbp = 4;	// mark far stack frame with inc BP / dec BP
+enum WFloadds = 8;	// assume __loadds for all functions
+enum WFexpdef = 0x10;	// generate export definition records for
+				// exported functions
+enum WFss = 0x20;	// load DS from SS
+enum WFreduced = 0x40;	// skip DS load for non-exported functions
+enum WFdgroup = 0x80;	// load DS from DGROUP
+enum WFexport = 0x100;	// assume __export for all far functions
+enum WFds = 0x200;	// load DS from DS
+enum WFmacros = 0x400;	// define predefined windows macros
+enum WFssneds = 0x800;	// SS != DS
+enum WFthunk = 0x1000;	// use fixups instead of direct ref to CS
+enum WFsaveds = 0x2000;	// use push/pop DS for far functions
+enum WFdsnedgroup = 0x4000;	// DS != DGROUP
+enum WFexe = 0x8000;	// generating code for Windows EXE
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Configv.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,19 @@
+module dmd.backend.Configv;
+
+import dmd.backend.LANG;
+
+// Configuration that is not saved in precompiled header
+
+struct Configv
+{
+    char addlinenumbers;	// put line number info in .OBJ file
+    char verbose;		// 0: compile quietly (no messages)
+				// 1: show progress to DLL (default)
+				// 2: full verbosity
+    char* csegname;		// code segment name
+    char* deflibname;		// default library name
+    LANG language;		// message language
+    int errmax;			// max error count
+}
+
+Configv configv;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Cstate.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,21 @@
+module dmd.backend.Cstate;
+
+import dmd.backend.Symbol;
+import dmd.backend.LIST;
+import dmd.backend.symtab_t;
+
+struct BLKLST;
+ 
+struct Cstate
+{
+    BLKLST* CSfilblk;	// current source file we are parsing
+    Symbol* CSlinkage;		// table of forward referenced linkage pragmas
+    list_t CSlist_freelist;	// free list for list package
+    symtab_t* CSpsymtab;	// pointer to current Symbol table
+version (MEMORYHX) {
+    void** CSphx;		// pointer to HX data block
+}
+    char* modname;		// module unique identifier
+}
+
+extern (C++) extern __gshared Cstate cstate;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/DT.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,19 @@
+module dmd.backend.DT;
+
+import dmd.backend.dt_t;
+
+enum DT
+{
+    DT_abytes,
+    DT_azeros,  // 1
+    DT_xoff,
+    DT_1byte,
+    DT_nbytes,
+    DT_common,
+    DT_symsize,
+    DT_coff,
+    DT_ibytes, // 8
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(DT));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/F.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,60 @@
+module dmd.backend.F;
+
+enum F
+{
+	Fpending = 1,	// if function has been queued for being written
+	Foutput	= 2,	/* if function has been written out	*/
+	Finline	= 0x10,	/* if SCinline, and function really is inline */
+	Foverload = 0x20,	/* if function can be overloaded	*/
+	Ftypesafe = 0x40,	/* if function name needs type appended	*/
+	Fmustoutput = 0x80,	/* set for forward ref'd functions that	*/
+					/* must be output			*/
+	Finlinenest = 0x1000, /* used as a marker to prevent nested	*/
+					/* inlines from expanding		*/
+	Flinkage = 0x2000,	/* linkage is already specified		*/
+	Fstatic	= 0x4000,	/* static member function (no this)	*/
+	Foperator = 4,	/* if operator overload			*/
+	Fcast = 8,	/* if cast overload			*/
+	Fvirtual = 0x100,	/* if function is a virtual function	*/
+	Fctor = 0x200,	/* if function is a constructor		*/
+	Fdtor = 0x400,	/* if function is a destructor		*/
+	Fnotparent = 0x800,	/* if function is down Foversym chain	*/
+	Fbitcopy = 0x8000,	/* it's a simple bitcopy (op=() or X(X&)) */
+	Fpure = 0x10000,	// pure function
+	Finstance = 0x20000,	// function is an instance of a template
+	Ffixed = 0x40000,	// ctor has had cpp_fixconstructor() run on it,
+						// dtor has had cpp_fixdestructor()
+	Fintro = 0x80000,	// function doesn't hide a previous virtual function
+	///#if !TX86
+	///Fstcstd = 0x100000,	// static constructor or static destructor
+	///#endif
+	Fkeeplink = 0x200000,	// don't change linkage to default
+	Fnodebug = 0x400000,	// do not generate debug info for this function
+	Fgen = 0x800000,	// compiler generated function
+	Finvariant = 0x1000000,	// __invariant function
+	Fexplicit = 0x2000000,	// explicit constructor
+	Fsurrogate = 0x4000000,	// surrogate call function
+}
+
+enum F3
+{
+	Fvtblgen = 0x01,	// generate vtbl[] when this function is defined
+	Femptyexc = 0x02,	// empty exception specification (obsolete, use Tflags & TFemptyexc)
+	Fcppeh = 0x04,	// uses C++ EH
+	Fdeclared = 0x10,	// already declared function Symbol
+	Fmark = 0x20,	// has unbalanced OPctor's
+	Fnteh = 0x08,	// uses NT Structured EH
+	Fdoinline = 0x40,	// do inline walk
+	Foverridden	= 0x80,	// ignore for overriding purposes
+///#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+///    Fnowrite	= 0x100,	// SCinline should never output definition
+///#else
+	Fjmonitor = 0x100,	// Jupiter synchronized function
+///#endif
+	Fnosideeff = 0x200,	// function has no side effects
+	F3badoparrow = 0x400,	// bad operator->()
+	Fmain = 0x800,	// function is main() or wmain()
+	Fnested	= 0x1000,	// D nested function with 'this'
+	Fmember	= 0x2000,	// D member function with 'this'
+	Fnotailrecursion = 0x4000,	// no tail recursion optimizations
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/FL.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,59 @@
+module dmd.backend.FL;
+
+/**************************************
+ * Element types.
+ * These should be combined with storage classes.
+ */
+
+enum FL
+{
+	FLunde,
+	FLconst,	// numerical constant
+	FLoper,		// operator node
+	FLfunc,		// function symbol
+	FLdata,		// ref to data segment variable
+	FLreg,		// ref to register variable
+	FLpseudo,	// pseuodo register variable
+	FLauto,		// ref to automatic variable
+	FLpara,		// ref to function parameter variable
+	FLextern,	// ref to external variable
+	FLtmp,		// ref to a stack temporary, int contains temp number
+	FLcode,		// offset to code
+	FLblock,	// offset to block
+	FLudata,	// ref to udata segment variable
+	FLcs,		// ref to common subexpression number
+	FLswitch,	// ref to offset of switch data block
+	FLfltreg,	// ref to floating reg on stack, int contains offset
+	FLoffset,	// offset (a variation on constant, needed so we
+			// can add offsets (different meaning for FLconst))
+	FLdatseg,	// ref to data segment offset
+	FLctor,		// constructed object
+	FLdtor,		// destructed object
+///#if TX86
+	FLndp,		// saved 8087 register
+	FLfardata,	// ref to far data segment
+	FLlocalsize,	// replaced with # of locals in the stack frame
+	FLcsdata,	// ref to code segment variable
+	FLtlsdata,	// thread local storage
+	FLbprel,	// ref to variable at fixed offset from frame pointer
+	FLframehandler,	// ref to C++ frame handler for NT EH
+	FLasm,		// (code) an ASM code
+	FLblockoff,	// address of block
+	FLallocatmp,	// temp for built-in alloca()
+	FLstack,	// offset from ESP rather than EBP
+	FLdsymbol,	// it's a Dsymbol
+///#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+	// Change this, update debug.c too
+///	FLgot,		// global offset table entry outside this object file
+///	FLgotoff,	// global offset table entry inside this object file
+	//FLoncedata,	// link once data
+	//FLoncecode,	// link once code
+///#endif
+///#else
+///	TARGET_enumFL
+///#endif
+	FLMAX
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(FL));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Funcsym.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3 @@
+module dmd.backend.Funcsym;
+
+struct Funcsym;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/LANG.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,10 @@
+module dmd.backend.LANG;
+
+// Language for error messages
+enum LANG
+{
+	LANGenglish,
+	LANGgerman,
+	LANGfrench,
+	LANGjapanese,
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/LINKAGE.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.backend.LINKAGE;
+
+/* Linkage type		*/
+enum LINKAGE
+{
+    LINK_C,			/* C style				*/
+    LINK_CPP,			/* C++ style				*/
+    LINK_PASCAL,		/* Pascal style				*/
+    LINK_FORTRAN,
+    LINK_SYSCALL,
+    LINK_STDCALL,
+    LINK_D,			// D code
+    LINK_MAXDIM			/* array dimension			*/
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/LIST.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1 @@
+module dmd.backend.LIST;

import dmd.backend.Symbol;

struct LIST
{
	/* Do not access items in this struct directly, use the		*/
	/* functions designed for that purpose.				*/
	LIST* next;	/* next element in list			*/
	int count;		/* when 0, element may be deleted	*/

	union
	{
		void *ptr;	/* data pointer				*/
		int data;
	}
}

alias LIST* list_t;			/* pointer to a list entry		*/
alias list_t symlist_t;		/* pointer to a list entry		*/

extern (C++) extern {
	__gshared list_t slist;
	list_t list_prepend(list_t* plist, void* ptr);
	void slist_add(Symbol* s);
}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/OPER.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,358 @@
+module dmd.backend.OPER;
+
+enum OPER : ubyte ///
+{
+	OPunde,			/* place holder for undefined operator	*/
+
+	OPadd,
+	OPmin,
+	OPmul,
+	OPdiv,
+	OPmod,
+	OPshr,			// unsigned right shift
+	OPshl,
+	OPand,
+	OPxor,
+	OPor,
+	OPashr,			// signed right shift
+	OPnot,
+	OPbool,			/* "booleanize"			*/
+	OPcom,
+	OPcond,
+	OPcomma,
+	OPoror,
+	OPandand,
+	OPbit,			/* ref to bit field		*/
+	OPind,			/* *E				*/
+	OPaddr,			/* &E				*/
+	OPneg,			/* unary -			*/
+	OPuadd,			/* unary +			*/
+///#if TX86
+	OPvoid,			// where casting to void is not a no-op
+	OPabs,			/* absolute value		*/
+	OPsqrt,			/* square root			*/
+	OPrndtol,		// round to short, long, long long (inline 8087 only)
+	OPsin,			// sine
+	OPcos,			// cosine
+	OPrint,			// round to int
+	OPscale,		// ldexp
+	OPyl2x,			// y * log2(x)
+	OPyl2xp1,		// y * log2(x + 1)
+	OPstrlen,		/* strlen()			*/
+	OPstrcpy,		/* strcpy()			*/
+	OPstrcat,		/* strcat()			*/
+	OPstrcmp,		/* strcmp()			*/
+	OPmemcpy,
+	OPmemcmp,
+	OPmemset,
+	OPsetjmp,		// setjmp()
+	OPremquo,		// / and % in one operation
+
+	OPbsf,			// bit scan forward
+	OPbsr,			// bit scan reverse
+	OPbt,			// bit test
+	OPbtc,			// bit test and complement
+	OPbtr,			// bit test and reset
+	OPbts,			// bit test and set
+	OPbswap,		// swap bytes
+///#endif
+
+	OPstreq,		/* structure assignment		*/
+
+	OPnegass,		// x = -x
+	OPpostinc,		/* x++				*/
+	OPpostdec,		/* x--				*/
+
+	OPeq,
+	OPaddass,
+	OPminass,
+	OPmulass,
+	OPdivass,
+	OPmodass,
+	OPshrass,
+	OPshlass,
+	OPandass,
+	OPxorass,
+	OPorass,
+
+/* Convert from token to assignment operator	*/
+///#define asgtoktoop(tok)	((int) (tok) + ((int)OPeq - (int) TKeq))
+
+	OPashrass,
+
+	/* relational operators	(in same order as corresponding tokens) */
+///#define RELOPMIN	((int)OPle)
+	OPle,
+	OPgt,
+	OPlt,
+	OPge,
+	OPeqeq,
+	OPne,
+
+	OPunord,	/* !<>=		*/
+	OPlg,		/* <>		*/
+	OPleg,		/* <>=		*/
+	OPule,		/* !>		*/
+	OPul,		/* !>=		*/
+	OPuge,		/* !<		*/
+	OPug,		/* !<=		*/
+	OPue,		/* !<>		*/
+	OPngt,
+	OPnge,
+	OPnlt,
+	OPnle,
+	OPord,
+	OPnlg,
+	OPnleg,
+	OPnule,
+	OPnul,
+	OPnuge,
+	OPnug,
+	OPnue,
+
+///#define rel_toktoop(tk)	((enum OPER)((int)tk - (int)TKle + (int)OPle))
+
+/***************** End of relational operators ******************/
+///#define CNVOPMIN	(OPnue+1)
+
+// parallel array inconvtab[] in cgelem.c)
+
+///#if TX86
+
+/* Convert from conversion operator to conversion index		*/
+///#define convidx(op)	((int)(op) - CNVOPMIN)
+
+/*	8,16,32,64	integral type of unspecified sign
+	s,u		signed/unsigned
+	f,d,ld		float/double/long double
+	np,fp,vp,f16p	near pointer/far pointer/handle pointer/far16 pointer
+	cvp		const handle pointer
+ */
+
+	OPb_8,		// convert bit to byte
+	OPd_s32,
+	OPs32_d,
+	OPd_s16,
+	OPs16_d,
+	OPd_u16,
+	OPu16_d,
+	OPd_u32,
+	OPu32_d,
+	OPd_s64,
+	OPs64_d,
+	OPd_u64,
+	OPu64_d,
+	OPd_f,
+	OPf_d,
+	OPvp_fp,
+	OPcvp_fp,	// const handle * => far *
+	OPs16_32,	// short to long
+	OPu16_32,	// unsigned short to long
+	OP32_16,	// long to short
+	OPu8_16,	// unsigned char to short
+	OPs8_16,	// signed char to short
+	OP16_8,		// short to 8 bits
+	OPu32_64,	// unsigned long to long long
+	OPs32_64,	// long to long long
+	OP64_32,	// long long to long
+///#define OPsfltdbl	OPunde
+///#define OPdblsflt	OPunde
+	OPoffset,	// get offset of far pointer
+	OPnp_fp,	// convert near pointer to far
+	OPnp_f16p,	// from 0:32 to 16:16
+	OPf16p_np,	// from 16:16 to 0:32
+	OPld_d,
+	OPd_ld,
+	OPld_u64,
+///#else
+///TARGET_CONVERSION_OPS
+///#endif
+
+///#define CNVOPMAX	(OPc_r-1)
+///#define convidx(op)	((int)(op) - CNVOPMIN)
+/* Convert from conversion operator to conversion index		*/
+
+///#if 1
+// The old conversion operators - retain until we get the code fixed
+///#define OPlngdbl	OPs32_d
+///#define OPdblint	OPd_s16
+///#define OPintdbl	OPs16_d
+///#define OPdbluns	OPd_u16
+///#define OPunsdbl	OPu16_d
+///#define OPdblulng	OPd_u32
+///#define OPulngdbl	OPu32_d
+///#define OPdblllng	OPd_s64
+///#define OPllngdbl	OPs64_d
+///#define OPdblullng	OPd_u64
+///#define OPdblflt	OPd_f
+///#define OPvptrfptr	OPvp_fp
+///#define OPcvptrfptr	OPcvp_fp	// const handle * => far *
+///#define OPshtlng	OPs16_32	// short to long
+///#define OPushtlng	OPu16_32	// unsigned short to long
+///#define OPlngsht	OP32_16		// long to short
+///#define OPu8int		OPu8_16		// unsigned char to short
+///#define OPs8int		OPs8_16		// signed char to short
+///#define OPint8		OP16_8		// short to 8 bits
+///#define OPulngllng	OPu32_64	// unsigned long to long long
+///#define OPlngllng	OPs32_64	// long to long long
+///#define OPllnglng	OP64_32		// long long to long
+///#define OPsfltdbl	OPunde
+///#define OPdblsflt	OPunde
+///#define OPoffset	OPoffset	// get offset of far pointer
+///#define OPptrlptr	OPnp_fp		// convert near pointer to far
+///#define OPtofar16	OPnp_f16p	// from 0:32 to 16:16
+///#define OPfromfar16	OPf16p_np	// from 16:16 to 0:32
+
+///#endif
+
+/***************** End of conversion operators ******************/
+
+	OPc_r,		// complex to real
+	OPc_i,		// complex to imaginary
+	OPmsw,		// top 32 bits of 64 bit word (32 bit code gen)
+			// top 16 bits of 32 bit word (16 bit code gen)
+
+	OPparam,		/* function parameter separator	*/
+	OPcall,			/* binary function call		*/
+	OPucall,		/* unary function call		*/
+	OPcallns,		// binary function call, no side effects
+	OPucallns,		// unary function call, no side effects
+
+	OPsizeof,		/* for forward-ref'd structs	*/
+	OPstrctor,		/* call ctor on struct param	*/
+	OPstrthis,		// 'this' pointer for OPstrctor
+	OPstrpar,		/* structure func param		*/
+	OPconst,		/* constant			*/
+	OPrelconst,		/* constant that contains an address */
+	OPvar,			/* variable			*/
+	OPreg,			// register (used in inline asm operand expressions)
+	OPcolon,		/* : as in ?:			*/
+	OPcolon2,		// alternate version with different EH semantics
+	OPstring,		/* address of string		*/
+	OPasm,			/* in-line assembly code	*/
+	OPinfo,			// attach info (used to attach ctor/dtor
+	OPhalt,			// insert HLT instruction
+				// info for exception handling)
+	OPctor,
+	OPdtor,
+	OPmark,
+	OPpair,			// build register pair, E1 is lsb, E2 = msb
+	OPrpair,		// build reversed register pair, E1 is msb, E2 = lsb
+	OPframeptr,		// load pointer to base of frame
+	OPgot,			// load pointer to global offset table
+
+	// Jupiter operators
+	OParray,		// access Jupiter array, left is handle, right is index
+	OParraylength,		// evaluates array handle into array length
+	OPfield,		// access Jupiter object field, left is handle, right is offset
+	OPnewarray,		// allocate Jupiter array, left is dimension, right is type
+	OPmultinewarray,	// allocate multidimensional Jupiter array
+				// left is dimensions, right is (numdims,type signature)
+	OPinstanceof,		// left is class id, right is handle
+	OPfinalinstanceof,      // left is class id, right is handle
+	OPcheckcast,		// left is class id, right is handle
+	OPhstring,		// handle to static string
+	OPnullcheck,		// check if pointer is null
+
+///#if TX86
+	OPinp,			/* input from I/O port		*/
+	OPoutp,			/* output to I/O port		*/
+///#endif
+	/* C++ operators */
+	OPnew,			// operator new
+	OPanew,			// operator new[]
+	OPdelete,		// operator delete
+	OPadelete,		// operator delete[]
+	OPbrack,		/* [] subscript			*/
+	OParrow,		/* for -> overloading		*/
+	OParrowstar,		/* for ->* overloading		*/
+	OPpreinc,		/* ++x overloading		*/
+	OPpredec,		/* --x overloading		*/
+
+///#ifdef TARGET_INLINEFUNC_OPS
+///	TARGET_INLINEFUNC_OPS
+///#endif
+
+///#if (TARGET_POWERPC)
+	OPeieio,
+///#endif
+	
+	OPMAX			/* 1 past last operator		*/
+}
+
+enum RELOPMIN = cast(int)OPER.OPle;
+
+extern(C++) extern __gshared const ubyte[OPER.OPMAX] optab1;
+extern(C++) extern __gshared const ubyte[OPER.OPMAX] optab2;
+extern(C++) extern __gshared const ubyte[OPER.OPMAX] optab3;
+extern(C++) extern __gshared const ubyte[OPER.OPMAX] opcost;
+
+enum _OT
+{
+	_OTbinary = 1,
+	_OTunary = 2,
+	_OTcommut = 4,
+	_OTassoc = 8,
+	_OTsideff = 0x10,
+	_OTeop0e = 0x20,
+	_OTeop00 = 0x40,
+	_OTeop1e = 0x80,
+
+	/* optab2[]	*/
+	_OTlogical = 1,
+	_OTwid = 2,
+	_OTcall = 4,
+	_OTrtol = 8,
+	_OTassign = 0x10,
+	_OTdef = 0x20,
+	_OTae = 0x40,
+	_OTexp = 0x80,
+}
+
+/+
+// optab3[]
+#define _OTboolnop	1
++/
+
+ubyte OTbinary(OPER op) {
+	return (optab1[op] & _OT._OTbinary);
+}
+
+/+
+#define OTunary(op)	(optab1[op]&_OTunary)
+#define OTleaf(op)	(!(optab1[op]&(_OTunary|_OTbinary)))
+#define OTcommut(op)	(optab1[op]&_OTcommut)
+#define OTassoc(op)	(optab1[op]&_OTassoc)
+#define OTassign(op)	(optab2[op]&_OTassign)
+#define OTpost(op)	((op) == OPpostinc || (op) == OPpostdec)
+#define OTeop0e(op)	(optab1[op]&_OTeop0e)
+#define OTeop00(op)	(optab1[op]&_OTeop00)
+#define OTeop1e(op)	(optab1[op]&_OTeop1e)
+#define OTsideff(op)	(optab1[op]&_OTsideff)
+#define OTconv(op)	((op) >= CNVOPMIN && (op) <= CNVOPMAX)
+#define OTlogical(op)	(optab2[op]&_OTlogical)
+#define OTwid(op)	(optab2[op]&_OTwid)
+#define OTopeq(op)	((op) >= OPaddass && (op) <= OPashrass)
+#define OTop(op)	((op) >= OPadd && (op) <= OPor)
+#define OTcall(op)	(optab2[op]&_OTcall)
+#define OTrtol(op)	(optab2[op]&_OTrtol)
+#define OTrel(op)	((op) >= OPle && (op) <= OPnue)
+#define OTrel2(op)	((op) >= OPle && (op) <= OPge)
+#define OTdef(op)	(optab2[op]&_OTdef)
+#define OTae(op)	(optab2[op]&_OTae)
+#define OTexp(op)	(optab2[op]&_OTexp)
+#if 1
+#define OTboolnop(op)	(optab3[op]&_OTboolnop)
+#define OTcalldef(op)	(OTcall(op) || (op) == OPstrcpy || (op) == OPstrcat || (op) == OPmemcpy)
+#else
+#endif 
+
+/* Convert op= to op	*/
+#define opeqtoop(opx)	((opx) - OPaddass + OPadd)
+
+/* Convert op to op=	*/
+#define optoopeq(opx)	((opx) - OPadd + OPaddass)
++/
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(OPER));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/PARAM.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,4 @@
+module dmd.backend.PARAM;
+
+struct PARAM;
+alias PARAM param_t;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/REG.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.backend.REG;
+
+enum REG
+{
+	AX = 0,
+	CX = 1,
+	DX = 2,
+	BX = 3,
+	SP = 4,
+	BP = 5,
+	SI = 6,
+	DI = 7,
+	ES = 9,
+	PSW = 10,
+	STACK = 11,	// top of stack
+	MEM = 12,	// memory
+	OTHER = 13,	// other things
+	ST0 = 14,	// 8087 top of stack register
+	ST01 = 15,	// top two 8087 registers; for complex types
+
+	NOREG = 100,	// no register
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/REGMAX.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3 @@
+module dmd.backend.REGMAX;
+
+enum REGMAX = 10;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/RTLSYM.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,101 @@
+module dmd.backend.RTLSYM;
+
+import dmd.backend.Symbol;
+
+enum RTLSYM
+{
+    RTLSYM_THROW,
+	RTLSYM_MONITOR_HANDLER,
+	RTLSYM_MONITOR_PROLOG,
+	RTLSYM_MONITOR_EPILOG,
+	RTLSYM_DCOVER,
+	RTLSYM_DASSERT,
+	RTLSYM_DASSERT_MSG,
+	RTLSYM_DARRAY,
+	RTLSYM_DINVARIANT,
+	RTLSYM__DINVARIANT,
+	RTLSYM_MEMCPY,
+	RTLSYM_MEMSET8,
+	RTLSYM_MEMSET16,
+	RTLSYM_MEMSET32,
+	RTLSYM_MEMSET64,
+	RTLSYM_MEMSET128,
+	RTLSYM_MEMSET80,
+	RTLSYM_MEMSET160,
+	RTLSYM_MEMSETN,
+	RTLSYM_MODULO,
+	RTLSYM_MONITORENTER,
+	RTLSYM_MONITOREXIT,
+	RTLSYM_CRITICALENTER,
+	RTLSYM_CRITICALEXIT,
+	RTLSYM_SWITCH_STRING,
+	RTLSYM_SWITCH_USTRING,
+	RTLSYM_SWITCH_DSTRING,
+	RTLSYM_DSWITCHERR,
+	RTLSYM_DHIDDENFUNC,
+	RTLSYM_NEWCLASS,
+	RTLSYM_NEWARRAYT,
+	RTLSYM_NEWARRAYIT,
+	RTLSYM_NEWARRAYMT,
+	RTLSYM_NEWARRAYMIT,
+	RTLSYM_ARRAYLITERALT,
+	RTLSYM_ASSOCARRAYLITERALT,
+	RTLSYM_CALLFINALIZER,
+	RTLSYM_CALLINTERFACEFINALIZER,
+	RTLSYM_DELCLASS,
+	RTLSYM_DELINTERFACE,
+	RTLSYM_ALLOCMEMORY,
+	RTLSYM_DELARRAY,
+	RTLSYM_DELARRAYT,
+	RTLSYM_DELMEMORY,
+	RTLSYM_INTERFACE,
+	RTLSYM_DYNAMIC_CAST,
+	RTLSYM_INTERFACE_CAST,
+	RTLSYM_FATEXIT,
+	RTLSYM_ARRAYCATT,
+	RTLSYM_ARRAYCATNT,
+	RTLSYM_ARRAYAPPENDT,
+	RTLSYM_ARRAYAPPENDCT,
+	RTLSYM_ARRAYSETLENGTHT,
+	RTLSYM_ARRAYSETLENGTHIT,
+	RTLSYM_ARRAYCOPY, 
+	RTLSYM_ARRAYASSIGN, 
+	RTLSYM_ARRAYCTOR, 
+	RTLSYM_ARRAYSETASSIGN, 
+	RTLSYM_ARRAYSETCTOR, 
+	RTLSYM_ARRAYCAST, 
+	RTLSYM_ARRAYCAST_FROMBIT, 
+	RTLSYM_ARRAYEQ, 
+	RTLSYM_ARRAYEQ2, 
+	RTLSYM_ARRAYEQBIT, 
+	RTLSYM_ARRAYCMP, 
+	RTLSYM_ARRAYCMP2, 
+	RTLSYM_ARRAYCMPCHAR, 
+	RTLSYM_ARRAYCMPBIT, 
+	RTLSYM_OBJ_EQ, 
+	RTLSYM_OBJ_CMP, 
+	RTLSYM_EXCEPT_HANDLER2, 
+	RTLSYM_EXCEPT_HANDLER3,  
+	RTLSYM_CPP_HANDLER, 
+	RTLSYM_D_LOCAL_UNWIND2,  
+	RTLSYM_TLS_INDEX, 
+	RTLSYM_TLS_ARRAY,    
+	RTLSYM_EXCEPT_LIST, 
+	RTLSYM_SETJMP3, 
+	RTLSYM_LONGJMP, 
+	RTLSYM_INTONLY, 
+	RTLSYM_ALLOCA, 
+	RTLSYM_CPP_LONGJMP, 
+	RTLSYM_PTRCHK, 
+	RTLSYM_CHKSTK, 
+	RTLSYM_TRACE_PRO_N, 
+	RTLSYM_TRACE_PRO_F, 
+	RTLSYM_TRACE_EPI_N, 
+	RTLSYM_TRACE_EPI_F,
+    RTLSYM_MAX
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(RTLSYM));
+
+extern(C++) extern __gshared Symbol* rtlsym[RTLSYM.RTLSYM_MAX];
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/SC.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,51 @@
+module dmd.backend.SC;
+
+enum SC : ubyte
+{
+  	SCunde,
+	SCauto,
+	SCstatic,
+	SCextern,
+	SCregister,
+	SCpseudo,
+	SCglobal,
+	SCcomdat,
+	SCparameter,
+	SCregpar,
+	SCfastpar,
+	SCtypedef,
+	SCexplicit,
+	SCmutable,
+	SCtmp,
+	SClabel, 
+	SCstruct, 
+	SCenum, 
+	SCfield, 
+	SCconst, 
+	SCmember, 
+	SCanon, 
+	SCinline, 
+	SCsinline, 
+	SCeinline, 
+	SCoverload, 
+	SCfriend, 
+	SCvirtual, 
+	SClocstat, 
+	SCtemplate, 
+	SCfunctempl, 
+	SCftexpspec, 
+	SClinkage, 
+	SCpublic, 
+	SCcomdef, 
+	SCbprel, 
+	SCnamespace, 
+	SCalias, 
+	SCfuncalias, 
+	SCmemalias, 
+	SCstack,
+	SCadl,
+	SCMAX
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(SC));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/SEN.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,7 @@
+module dmd.backend.SEN;
+
+enum SEN
+{
+	SENnotagname = 1,	// no tag name for enum
+	SENforward = 2,	// forward referenced enum
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/SFL.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,67 @@
+module dmd.backend.SFL;
+
+enum SFL
+{
+	SFLmark	= 0x08,	// temporary marker
+	SFLvalue = 0x01,	// Svalue contains const expression
+	SFLimplem = 0x02,	// if seen implementation of Symbol
+					// (function body for functions,
+					// initializer for variables)
+	SFLdouble = 0x02,	// SCregpar or SCparameter, where float
+					// is really passed as a double
+	SFLfree = 0x04,	// if we can symbol_free() a Symbol in
+					// a Symbol table[]
+	SFLexit = 0x10,	// tyfunc: function does not return
+					// (ex: exit,abort,_assert,longjmp)
+	SFLtrue = 0x200,	// value of Symbol != 0
+	SFLreplace = SFLmark,	// variable gets replaced in inline expansion
+	SFLskipinit = 0x10000,	// SCfield, SCmember: initializer is skipped
+	SFLnodebug = 0x20000,	// don't generate debug info
+	SFLwasstatic = 0x800000, // was an uninitialized static
+	SFLweak	= 0x1000000, // resolve to NULL if not found
+
+	// CPP
+	SFLnodtor = 0x10,	// set if destructor for Symbol is already called
+	SFLdtorexp = 0x80,	// Svalue has expression to tack onto dtor
+	SFLmutable = 0x100000,	// SCmember or SCfield is mutable
+	SFLdyninit = 0x200000,	// symbol has dynamic initializer
+	SFLtmp = 0x400000,	// symbol is a generated temporary
+
+///version (XXX) {///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+///    SFLthunk = 0x40000, // symbol is temporary for thunk
+///}
+
+	// Possible values for protection bits
+	SFLprivate = 0x60,
+	SFLprotected = 0x40,
+	SFLpublic = 0x20,
+	SFLnone	= 0x00,
+	SFLpmask = 0x60,	// mask for the protection bits
+///version (VEC_VTBL_LIST) {
+///	SFLvtbl	= 0x2000,	// Symbol is a vtable or vbtable
+///}
+
+	// OPTIMIZER and CODGEN
+	SFLdead	= 0x800,	// this variable is dead
+	
+	// OPTIMIZER only
+	SFLunambig = 0x400,	// only accessible by unambiguous reference,
+					// i.e. cannot be addressed via pointer
+					// (GTregcand is a subset of this)
+					// P.S. code generator turns off this
+					// flag if any reads are done from it.
+					// This is to eliminate stores to it
+					// that are never read.
+					
+	SFLlivexit = 0x1000,	// live on exit from function
+	SFLnotbasiciv = 0x4000,	// not a basic induction variable
+	SFLnord	= SFLdouble, // SCauto,SCregister,SCtmp: disallow redundant warnings
+	
+	// CODGEN only
+	SFLread	= 0x40000,	// variable is actually read from
+					// (to eliminate dead stores)
+	SFLspill = 0x80000,	// only in register part of the time
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(SFL));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/STR.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,34 @@
+module dmd.backend.STR;
+
+enum STR
+{
+	STRanonymous = 0x01,	// set for unions with no tag names
+	STRglobal = 0x02,	// defined at file scope
+
+	STRnotagname = 0x04,	// struct/class with no tag name
+	STRoutdef = 0x08,	// we've output the debug definition
+	STRbitfields = 0x10,	// set if struct contains bit fields
+	STRpredef = 0x1000, // a predefined struct
+	STRunion = 0x4000,	// actually, it's a union
+
+	STRabstract = 0x20,	// abstract class
+	STRbitcopy = 0x40,	// set if operator=() is merely a bit copy
+	STRanyctor = 0x80,	// set if any constructors were defined
+					// by the user
+	STRnoctor = 0x100,	// no constructors allowed
+	STRgen = 0x200,	// if struct is an instantiation of a
+					// template class, and was generated by
+					// that template
+	STRvtblext = 0x400,	// generate vtbl[] only when first member function
+					// definition is encountered (see Fvtblgen)
+	STRexport = 0x800,	// all member functions are to be _export
+	STRclass = 0x8000,	// it's a class, not a struct
+///version (TX86) {
+	STRimport = 0x40000,	// imported class
+	STRstaticmems = 0x80000,	// class has static members
+///}
+	STR0size = 0x100000,	// zero sized struct
+	STRinstantiating = 0x200000,	// if currently being instantiated
+	STRexplicit	= 0x400000,	// if explicit template instantiation
+	STRgenctor0	= 0x800000,	// need to gen X::X()
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/SYMIDX.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3 @@
+module dmd.backend.SYMIDX;
+
+alias int SYMIDX;		// symbol table index
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Srcpos.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,23 @@
+module dmd.backend.Srcpos;
+
+struct Srcpos
+{
+    uint Slinnum;		// 0 means no info available
+version (TX86) {
+version (SPP_OR_SCPP) {
+    Sfile** Sfilptr;	// file
+///    #define srcpos_sfile(p)	(**(p).Sfilptr)
+///    #define srcpos_name(p)	(srcpos_sfile(p).SFname)
+}
+version (MARS) {
+    char* Sfilename;
+///    #define srcpos_name(p)	((p).SFname)
+}
+}
+version (M_UNIX) {
+    short Sfilnum;		// file number
+}
+version (SOURCE_OFFSETS) {
+    uint Sfiloff;	// byte offset
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/StringTab.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,17 @@
+module dmd.backend.StringTab;
+
+import dmd.Module;
+import dmd.backend.Symbol;
+
+struct StringTab
+{
+    Module m;		// module we're generating code for
+    Symbol* si;
+    void* string_;
+    size_t sz;
+    size_t len;
+}
+
+enum STSIZE = 16;
+__gshared StringTab[STSIZE] stringTab;
+__gshared size_t stidx;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Symbol.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,388 @@
+module dmd.backend.Symbol;
+
+import dmd.backend.dt_t;
+import dmd.backend.TYPE;
+import dmd.backend.LIST;
+import dmd.backend.block;
+import dmd.backend.func_t;
+import dmd.backend.enum_t;
+import dmd.backend.elem;
+import dmd.backend.struct_t;
+import dmd.backend.template_t;
+import dmd.backend.targ_types;
+import dmd.backend.vec_t;
+import dmd.backend.SYMIDX;
+import dmd.backend.regm_t;
+import dmd.backend.Util;
+
+struct Symbol
+{
+    ushort	id;
+
+    Symbol* Sl;
+	Symbol* Sr;		// left, right child
+
+    Symbol *Snext;		// next in threaded list
+
+    dt_t* Sdt;			// variables: initializer
+    type* Stype;		// type of Symbol
+
+    tym_t ty()
+	{
+		return Stype.Tty;
+	}
+
+    union			// variants for different Symbol types
+    {
+		enum_t* Senum;		// SCenum
+		struct
+		{    
+			func_t* Sfunc;	// tyfunc
+			list_t Spath1;	// SCfuncalias member functions: same as Spath
+					// and in same position
+					// SCadl: list of associated functions for ADL lookup
+		}
+		struct			// SClabel
+		{   
+			int Slabel;		// TRUE if label was defined
+			block* Slabelblk;	// label block
+		}
+///		#define Senumlist Senum->SEenumlist
+
+		struct			// SClinkage
+		{
+			int Slinkage;	// tym linkage bits
+			uint Smangle;
+		}
+
+		struct
+		{
+			char Sbit;		// SCfield: bit position of start of bit field
+			char Swidth;	// SCfield: width in bits of bit field
+			targ_size_t Smemoff; // SCmember,SCfield: offset from start of struct
+		}
+
+		elem* Svalue;		/* SFLvalue: value of const
+				   SFLdtorexp: for objects with destructor,
+				   conditional expression to precede dtor call
+				 */
+
+		struct_t* Sstruct;	// SCstruct
+		template_t* Stemplate;	// SCtemplate
+		Symbol* Simport;	// SCextern: if dllimport Symbol, this is the
+				// Symbol it was imported from
+
+		ubyte Spreg;	// SCfastpar: register parameter is passed in
+    }
+
+    Symbol* Sscope;		// enclosing scope (could be struct tag,
+				// enclosing inline function for statics,
+				// or namespace)
+///#define isclassmember(s)	((s)->Sscope && (s)->Sscope->Sclass == SCstruct)
+
+    const(char)* prettyIdent;	// the symbol identifer as the user sees it
+
+    enum_SC Sclass;		// storage class (SCxxxx)
+    char Sfl;			// flavor (FLxxxx)
+    SYMFLGS Sflags;		// flag bits (SFLxxxx)
+
+    vec_t	Srange;		// live range, if any
+    vec_t	Slvreg;		// when symbol is in register
+    targ_size_t Ssize;		// tyfunc: size of function
+    targ_size_t Soffset;	// variables: offset of Symbol in its storage class
+
+    SYMIDX Ssymnum;		// Symbol number (index into globsym.tab[])
+				// SCauto,SCparameter,SCtmp,SCregpar,SCregister
+
+    short Sseg;			// segment index
+
+    int Sweight;		// usage count, the higher the number,
+				// the more worthwhile it is to put in
+				// a register
+    union
+    {
+		uint Sxtrnnum;	// SCcomdef,SCextern,SCcomdat: external symbol # (starting from 1)
+		uint Stypidx;	// SCstruct,SCunion,SCclass,SCenum,SCtypedef: debug info type index
+
+		struct
+		{ 
+			ubyte Sreglsw;
+			ubyte Sregmsw;
+			regm_t Sregm;	// mask of registers
+		}
+    }
+
+    regm_t	Sregsaved;	// mask of registers not affected by this func
+
+    char Sident[35];	// identifier string (dynamic array)
+				// (the size is for static Symbols)
+
+    bool needThis()	// true if symbol needs a 'this' pointer
+	{
+		assert(false);
+	}
+}
+
+void dumpSymbol(Symbol* foo)
+{
+	foreach (a, b; foo.tupleof)
+	{
+		static if (typeof(foo.tupleof[a]).stringof != "char[35u]") {
+			std.stdio.writeln(foo.tupleof[a].stringof, " ", cast(char*)&foo.tupleof[a] - cast(char*)foo, " = ", cast(int)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, ");");
+		}
+	}
+	
+	std.stdio.writefln("(*foo).Sclass %d = %d", (cast(char*)&foo.Sclass - cast(char*)foo), cast(int)foo.Sclass);
+	//std.stdio.writeln("printf(\"(*foo).Sclass %d %d\\n\", ((char*)&foo->Sclass - (char*)foo), (int)foo->Sclass);");
+}
+
+/+
+struct Symbol
+{
+debug {
+    ushort	id;
+///#define IDsymbol 0x5678
+///#define symbol_debug(s) assert((s)->id == IDsymbol)
+///#define class_debug(s) assert((s)->id == IDsymbol)
+} else {
+///#define symbol_debug(s)
+///#define class_debug(s)
+}
+
+    Symbol* Sl;
+	Symbol* Sr;		// left, right child
+
+version (TX86) {
+    Symbol *Snext;		// next in threaded list
+}
+    dt_t* Sdt;			// variables: initializer
+    type* Stype;		// type of Symbol
+
+	auto ty() {
+		assert(false);
+		//return Stype.Tty;
+	}
+
+	auto Senumlist()
+	{
+		return Senum.SEenumlist;
+	}
+
+    union			// variants for different Symbol types
+    {
+		enum_t* Senum;		// SCenum
+		struct
+		{   
+			func_t* Sfunc;	// tyfunc
+			list_t Spath1;	// SCfuncalias member functions: same as Spath
+					// and in same position
+					// SCadl: list of associated functions for ADL lookup
+		}
+		struct			// SClabel
+		{   
+			int Slabel;		// TRUE if label was defined
+			block* Slabelblk_;	// label block
+		}
+
+version (TX86) {
+		struct			// SClinkage
+		{
+			long Slinkage;	// tym linkage bits
+			uint Smangle;
+		}
+} else {
+		long Slinkage;		// SClinkage, tym linkage bits
+}
+
+		struct
+		{
+			char Sbit;		// SCfield: bit position of start of bit field
+			char Swidth;	// SCfield: width in bits of bit field
+version (TX86) {
+			targ_size_t Smemoff; // SCmember,SCfield: offset from start of struct
+}
+		}
+
+		elem* Svalue;		/* 	SFLvalue: value of const
+								SFLdtorexp: for objects with destructor,
+								conditional expression to precede dtor call
+							*/
+		struct_t* Sstruct;	// SCstruct
+
+		template_t* Stemplate;	// SCtemplate
+
+version (SCPP) {
+		struct			// SCnamespace
+		{   
+			Symbol* Snameroot;	// the Symbol table for the namespace
+			list_t Susing;	// other namespaces from using-directives
+		}
+		struct
+		{
+			Symbol* Smemalias;	// SCalias: pointer to Symbol to use instead
+					// (generated by using-declarations and
+					// namespace-alias-definitions)
+					// SCmemalias: pointer to member of base class
+					// to use instead (using-declarations)
+			symlist_t Spath;	// SCmemalias: path of classes to get to base
+					// class of which Salias is a member
+		}
+}
+	
+version (TX86) {
+		Symbol* Simport;	// SCextern: if dllimport Symbol, this is the
+					// Symbol it was imported from
+}
+		ubyte Spreg;	// SCfastpar: register parameter is passed in
+    }
+
+version (SCPP_OR_MARS) {
+    Symbol* Sscope;		// enclosing scope (could be struct tag,
+				// enclosing inline function for statics,
+				// or namespace)
+	//#define isclassmember(s)	((s)->Sscope && (s)->Sscope->Sclass == SCstruct)
+}
+
+version (SCPP) {
+    Symbol* Scover;		// if there is a tag name and a regular name
+				// of the same identifier, Scover is the tag
+				// Scover can be SCstruct, SCenum, SCtemplate
+				// or an SCalias to them.
+	//#define isscover(s)		((s)->Sclass == SCstruct || (s)->Sclass == SCenum || (s)->Sclass == SCtemplate)
+    uint Ssequence;		// sequence number (used for 2 level lookup)
+				// also used as 'parameter number' for SCTtemparg
+} else version (MARS) {
+    const(char)* prettyIdent;	// the symbol identifer as the user sees it
+} else version (AUTONEST) {
+    ubyte Spush;	// # of pushes followed by # of
+    ubyte Spop;		// pops of scope level
+}
+
+version (ELFOBJ_OR_MACHOBJ) {
+    int         obj_si;       // Symbol index of coff or elf symbol
+    uint 		dwarf_off;    // offset into .debug section
+    targ_size_t code_off;	// rel. offset from start of block where var is initialized
+    targ_size_t last_off;	// last offset using var
+}
+
+version (TARGET_OSX) {
+    targ_size_t Slocalgotoffset;
+}
+
+    SC Sclass;		// storage class (SCxxxx)
+    char Sfl;			// flavor (FLxxxx)
+    SYMFLGS Sflags;		// flag bits (SFLxxxx)
+///	#define SFLmark		0x08	// temporary marker
+///	#define SFLvalue	0x01	// Svalue contains const expression
+///	#define SFLimplem	0x02	// if seen implementation of Symbol
+					// (function body for functions,
+					// initializer for variables)
+///	#define SFLdouble	0x02	// SCregpar or SCparameter, where float
+					// is really passed as a double
+///	#define SFLfree		0x04	// if we can symbol_free() a Symbol in
+					// a Symbol table[]
+///	#define SFLexit		0x10	// tyfunc: function does not return
+					// (ex: exit,abort,_assert,longjmp)
+///	#define SFLtrue		0x200	// value of Symbol != 0
+///	#define SFLreplace	SFLmark	// variable gets replaced in inline expansion
+///	#define SFLskipinit	0x10000	// SCfield, SCmember: initializer is skipped
+///	#define SFLnodebug	0x20000	// don't generate debug info
+///	#define SFLwasstatic	0x800000 // was an uninitialized static
+///	#define SFLweak		0x1000000 // resolve to NULL if not found
+
+	// CPP
+///	#define SFLnodtor	0x10	// set if destructor for Symbol is already called
+///	#define SFLdtorexp	0x80	// Svalue has expression to tack onto dtor
+///	#define SFLmutable	0x100000	// SCmember or SCfield is mutable
+///	#define SFLdyninit	0x200000	// symbol has dynamic initializer
+///	#define SFLtmp		0x400000	// symbol is a generated temporary
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+    	///#define SFLthunk	0x40000 // symbol is temporary for thunk
+}
+
+	// Possible values for protection bits
+///	#define SFLprivate	0x60
+///	#define SFLprotected	0x40
+///	#define SFLpublic	0x20
+///	#define SFLnone		0x00
+///	#define SFLpmask	0x60	// mask for the protection bits
+version (VEC_VTBL_LIST) {
+///	#define SFLvtbl		0x2000	// Symbol is a vtable or vbtable
+}
+
+	// OPTIMIZER and CODGEN
+///	#define	GTregcand	0x100	// if Symbol is a register candidate
+///	#define	SFLdead		0x800	// this variable is dead
+
+	// OPTIMIZER only
+///	#define	SFLunambig	0x400	// only accessible by unambiguous reference,
+					// i.e. cannot be addressed via pointer
+					// (GTregcand is a subset of this)
+					// P.S. code generator turns off this
+					// flag if any reads are done from it.
+					// This is to eliminate stores to it
+					// that are never read.
+///	#define	SFLlivexit	0x1000	// live on exit from function
+///	#define	SFLnotbasiciv	0x4000	// not a basic induction variable
+///	#define SFLnord		SFLdouble // SCauto,SCregister,SCtmp: disallow redundant warnings
+
+	// CODGEN only
+///	#define GTtried	  	SFLmark	// tried to place in register
+///	#define GTbyte	  	0x8000	// variable is sometimes accessed as
+///	#define SFLread		0x40000	// variable is actually read from
+					// (to eliminate dead stores)
+///	#define SFLspill	0x80000	// only in register part of the time
+
+    vec_t	Srange;		// live range, if any
+    vec_t	Slvreg;		// when symbol is in register
+    targ_size_t Ssize;		// tyfunc: size of function
+    targ_size_t Soffset;	// variables: offset of Symbol in its storage class
+version (TARGET_MAC) {
+///#define Smemoff Soffset
+}
+
+    // CPP || OPTIMIZER
+    SYMIDX Ssymnum;		// Symbol number (index into globsym.tab[])
+				// SCauto,SCparameter,SCtmp,SCregpar,SCregister
+    // CODGEN
+version (TX86) {
+    short Sseg;			// segment index
+}
+    int Sweight;		// usage count, the higher the number,
+				// the more worthwhile it is to put in
+				// a register
+    union
+    {
+		uint Sxtrnnum;	// SCcomdef,SCextern,SCcomdat: external symbol # (starting from 1)
+		uint Stypidx;	// SCstruct,SCunion,SCclass,SCenum,SCtypedef: debug info type index
+		struct
+		{
+			ubyte Sreglsw;
+			ubyte Sregmsw;
+			regm_t Sregm;	// mask of registers
+		}			// SCregister,SCregpar,SCpseudo: register number
+    }
+
+version (TX86) {
+    regm_t	Sregsaved;	// mask of registers not affected by this func
+}
+
+version (SOURCE_4SYMS) {
+    Srcpos Ssrcpos;		// file position for definition
+}
+    // Target Additions
+///    TARGET_structSYMBOL
+version (TX86) {
+    char Sident[SYM_PREDEF_SZ];	// identifier string (dynamic array)
+				// (the size is for static Symbols)
+} else {
+    long[0] Sident;	// identifier string (dynamic array) as a str4
+}
+
+    bool needThis()	// true if symbol needs a 'this' pointer
+	{
+		assert(false);
+	}
+}
++/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/TF.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,30 @@
+module dmd.backend.TF;
+
+enum TF
+{
+	TFprototype	 = 1,	/* if this function is prototyped	*/
+	TFfixed	= 2,	/* if prototype has a fixed # of parameters */
+	TFforward = 8,	// TYstruct: if forward reference of tag name
+	TFsizeunknown = 0x10,	// TYstruct,TYarray: if size of type is unknown
+					// TYmptr: the Stag is TYident type
+	TFfuncret = 0x20,	// C++,tyfunc(): overload based on function return value
+	TFfuncparam	= 0x20,	// TYarray: top level function parameter
+	TFstatic = 0x40,	// TYarray: static dimension
+	TFvla = 0x80,	// TYarray: variable length array
+	TFemptyexc = 0x100,	// tyfunc(): empty exception specification
+
+	// C
+	TFgenerated = 4,	// if we generated the prototype ourselves
+
+	// CPP
+	TFdependent = 4,	// template dependent type
+
+///version (TX86) {
+///} else {
+///	TFhydrated = 0x20,	// type data already hydrated
+///	TFbasicrev = 0x80,	// if basic reserved type
+///}
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(TF));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/TYFL.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,175 @@
+module dmd.backend.TYFL;
+
+import dmd.backend.Util;
+
+extern(C++) ubyte* get_tytab();
+ubyte* tytab() { return get_tytab(); }
+
+extern(C++) ubyte* get_tytab2();
+ubyte* tytab2() { return get_tytab2(); }
+
+/* Array to give the size in bytes of a type, -1 means error	*/
+extern(C++) byte* get_tysize();
+byte* tysize() { return get_tysize(); }
+
+enum TYFL
+{
+	/* Flags in tytab[] array	*/
+	TYFLptr	= 1,
+	TYFLreal = 2,
+	TYFLintegral = 4,
+	TYFLcomplex	= 8,
+	TYFLimaginary = 0x10,
+	TYFLuns	= 0x20,
+	TYFLmptr = 0x40,
+	TYFLfv = 0x80,	/* TYfptr || TYvptr	*/
+
+	/* Flags in tytab2[] array	*/
+///version (TX86) {
+	TYFLfarfunc	= 1,
+	TYFLpascal = 2,	/* callee cleans up stack		*/
+	TYFLrevparam = 4,	/* function parameters are reversed	*/
+///} else {
+///	TYFLcallstkc = 1,	/* callee cleans up stack		*/
+///	TYFLrevparam = 2,	/* function parameters are reversed	*/
+///}
+	TYFLshort = 0x10,
+	TYFLaggregate = 0x20,
+	TYFLfunc = 0x40,
+	TYFLref	= 0x80,
+}
+
+/* Groupings of types	*/
+
+ubyte tyintegral(uint ty) {
+	return (tytab[(ty) & 0xFF] & TYFL.TYFLintegral);
+}
+
+ubyte tyarithmetic(uint ty) {
+	return (tytab[(ty) & 0xFF] & (TYFL.TYFLintegral | TYFL.TYFLreal | TYFL.TYFLimaginary | TYFL.TYFLcomplex));
+}
+
+ubyte tyaggregate(uint ty) {
+	return (tytab2[(ty) & 0xFF] & TYFL.TYFLaggregate);
+}
+
+ubyte tyscalar(uint ty) {
+	return (tytab[(ty) & 0xFF] & (TYFL.TYFLintegral | TYFL.TYFLreal | TYFL.TYFLimaginary | TYFL.TYFLcomplex | TYFL.TYFLptr | TYFL.TYFLmptr));
+}
+
+ubyte tyfloating(uint ty) {
+	return (tytab[(ty) & 0xFF] & (TYFL.TYFLreal | TYFL.TYFLimaginary | TYFL.TYFLcomplex));
+}
+
+ubyte tyimaginary(uint ty) {
+	return (tytab[(ty) & 0xFF] & TYFL.TYFLimaginary);
+}
+
+ubyte tycomplex(uint ty) {
+	return (tytab[(ty) & 0xFF] & TYFL.TYFLcomplex);
+}
+
+ubyte tyreal(uint ty) {
+	return (tytab[(ty) & 0xFF] & TYFL.TYFLreal);
+}
+
+/* Types that are chars or shorts	*/
+ubyte tyshort(uint ty) {
+	return (tytab2[(ty) & 0xFF] & TYFL.TYFLshort);
+}
+
+/+
+/* Detect TYlong or TYulong	*/
+#define tylong(ty)	(tybasic(ty) == TYlong || tybasic(ty) == TYulong)
++/
+
+/* Use to detect a pointer type	*/
+ubyte typtr(uint ty) {
+	return (tytab[(ty) & 0xFF] & TYFL.TYFLptr);
+}
+
+/* Use to detect a reference type */
+ubyte tyref(uint ty) {
+	return (tytab2[(ty) & 0xFF] & TYFL.TYFLref);
+}
+
+/* Use to detect a pointer type or a member pointer	*/
+ubyte tymptr(uint ty) {
+	return (tytab[(ty) & 0xFF] & (TYFL.TYFLptr | TYFL.TYFLmptr));
+}
+
+/* Detect TYfptr or TYvptr	*/
+ubyte tyfv(uint ty)	{
+	return (tytab[(ty) & 0xFF] & TYFL.TYFLfv);
+}
+
+/+
+// Give size of type
+char tysize(uint ty) {
+	return tysize[(ty) & 0xFF];
+}
+
+/* All data types that fit in exactly 8 bits	*/
+bool tybyte(uint ty) {
+	return (tysize(ty) == 1);
+}
+
+/* Types that fit into a single machine register	*/
+bool tyreg(TY ty) {
+	return (tysize(ty) <= REGSIZE);
+}
++/
+
+/* Detect function type	*/
+ubyte tyfunc(uint ty) {
+	return (tytab2[(ty) & 0xFF] & TYFL.TYFLfunc);
+}
+
+/* Detect function type where parameters are pushed in reverse order	*/
+ubyte tyrevfunc(uint ty) {
+	return (tytab2[(ty) & 0xFF] & TYFL.TYFLrevparam);
+}
+
+/* Detect unsigned types */
+ubyte tyuns(uint ty) {
+	return (tytab[(ty) & 0xFF] & (TYFL.TYFLuns | TYFL.TYFLptr));
+}
+
+/* Target dependent info	*/
+version (TX86) {
+///	#define TYoffset TYuint		/* offset to an address		*/
+
+	/* Detect cpp function type (callee cleans up stack)	*/
+	ubyte typfunc(uint ty) {
+		return (tytab2[(ty) & 0xFF] & TYFL.TYFLpascal);
+	}
+} else {
+	/* Detect cpp function type (callee cleans up stack)	*/
+	ubyte typfunc(uint ty) {
+		return (tytab2[(ty) & 0xFF] & TYFL.TYFLcallstkc);
+	}
+}
+
+/* Array to convert a type to its unsigned equivalent	*/
+extern(C++) extern tym_t* get_tytouns();
+
+tym_t touns(int ty) {
+	return get_tytouns[ty & 0xFF];
+}
+
+/* Determine if TYffunc or TYfpfunc (a far function) */
+ubyte tyfarfunc(uint ty)	{
+	return (tytab2[(ty) & 0xFF] & TYFL.TYFLfarfunc);
+}
+
+/+
+// Determine if parameter can go in register for TYjfunc
+#ifndef tyjparam
+#define tyjparam(ty)	(tysize(ty) <= intsize && !tyfloating(ty) && tybasic(ty) != TYstruct)
+#endif
+
+/* Determine relaxed type	*/
+#ifndef tyrelax
+#define tyrelax(ty)	(_tyrelax[tybasic(ty)])
+#endif
++/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/TYM.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,84 @@
+module dmd.backend.TYM;
+
+enum TYM
+{
+    TYbool		= 0,
+    TYchar		= 1,
+    TYschar		= 2,	// signed char
+    TYuchar		= 3,	// unsigned char
+    TYshort		= 4,
+    TYwchar_t		= 5,
+    TYushort		= 6,	// unsigned short
+    TYenum		= 7,	// enumeration value
+    TYint		= 8,
+    TYuint		= 9,	// unsigned
+    TYlong		= 0xA,
+    TYulong		= 0xB,	// unsigned long
+    TYdchar		= 0xC,	// 32 bit Unicode char
+    TYllong		= 0xD,	// 64 bit long
+    TYullong		= 0xE,	// 64 bit unsigned long
+    TYfloat		= 0xF,	// 32 bit real
+    TYdouble		= 0x10,	// 64 bit real
+
+    // long double is mapped to either of the following at runtime:
+    TYdouble_alias	= 0x11,	// 64 bit real (but distinct for overload purposes)
+    TYldouble		= 0x12,	// 80 bit real
+
+    // Add imaginary and complex types for D and C99
+    TYifloat		= 0x13,
+    TYidouble		= 0x14,
+    TYildouble		= 0x15,
+    TYcfloat		= 0x16,
+    TYcdouble		= 0x17,
+    TYcldouble		= 0x18,
+
+///#if TX86
+    TYjhandle		= 0x19,	// Jupiter handle type, equals TYnptr except
+				// that the debug type is different so the
+				// debugger can distinguish them
+    TYnptr		= 0x1A,	// data segment relative pointer
+    TYsptr		= 0x1B,	// stack segment relative pointer
+    TYcptr		= 0x1C,	// code segment relative pointer
+    TYf16ptr		= 0x1D,	// special OS/2 far16 pointer
+    TYfptr		= 0x1E,	// far pointer (has segment and offset)
+    TYhptr		= 0x1F,	// huge pointer (has segment and offset)
+    TYvptr		= 0x20,	// __handle pointer (has segment and offset)
+    TYref		= 0x21,	// reference to another type
+    TYvoid		= 0x22,
+    TYstruct		= 0x23,	// watch tyaggregate()
+    TYarray		= 0x24,	// watch tyaggregate()
+    TYnfunc		= 0x25,	// near C func
+    TYffunc		= 0x26,	// far  C func
+    TYnpfunc		= 0x27,	// near Cpp func
+    TYfpfunc		= 0x28,	// far  Cpp func
+    TYnsfunc		= 0x29,	// near stdcall func
+    TYfsfunc		= 0x2A,	// far stdcall func
+    TYifunc		= 0x2B,	// interrupt func
+    TYmemptr		= 0x2C,	// pointer to member
+    TYident		= 0x2D,	// type-argument
+    TYtemplate		= 0x2E,	// unexpanded class template
+    TYvtshape		= 0x2F,	// virtual function table
+    TYptr		= 0x30,	// generic pointer type
+    TYf16func		= 0x31,	// _far16 _pascal function
+    TYnsysfunc		= 0x32,	// near __syscall func
+    TYfsysfunc		= 0x33,	// far __syscall func
+    TYmfunc		= 0x34,	// NT C++ member func
+    TYjfunc		= 0x35,	// LINKd D function
+    TYhfunc		= 0x36, // C function with hidden parameter
+    TYnref		= 0x37,	// near reference
+    TYfref		= 0x38,	// far reference
+    TYMAX		= 0x39,
+
+///#if MARS
+	TYaarray = TYnptr,
+	TYdelegate = TYllong,
+	TYdarray = TYullong,
+///#endif
+}
+
+extern (C++) extern {
+	__gshared int TYptrdiff, TYsize, TYsize_t;
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(TYM));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/TYPE.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,127 @@
+module dmd.backend.TYPE;
+
+import dmd.backend.Util;
+import dmd.backend.Srcpos;
+import dmd.backend.elem;
+import dmd.backend.LIST;
+import dmd.backend.TYM;
+import dmd.backend.PARAM;
+import dmd.backend.targ_types;
+import dmd.backend.Classsym;
+
+struct TYPE
+{
+debug {
+    ushort	id;
+	enum IDtype = 0x1234;
+///#define type_debug(t) assert((t)->id == IDtype)
+} else {
+///#define type_debug(t)
+}
+
+    tym_t	Tty;		/* mask (TYxxx)				*/
+    ushort Tflags;	// TFxxxxx
+
+version (TX86) {
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+///#define mTYnoret	0x010000	// function has no return
+///#define mTYtransu	0x010000	// transparent union
+} else {
+///#define mTYfar16	0x010000
+}
+///#define mTYstdcall	0x020000
+///#define mTYfastcall	0x040000
+///#define mTYinterrupt	0x080000
+///#define mTYcdecl	0x100000
+///#define mTYpascal	0x200000
+///#define mTYsyscall	0x400000
+///#define mTYjava		0x800000
+
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+///#define mTYTFF		0xFE0000
+} else {
+///#define mTYTFF		0xFF0000
+}
+
+
+///#define TARGET_strucTYPE
+    mangle_t Tmangle;		// name mangling
+// Return name mangling of type
+///#define type_mangle(t)	((t)->Tmangle)
+}
+
+    uint Tcount;		// # pointing to this type
+    TYPE* Tnext;		// next in list
+				// TYenum: gives base type
+    union
+    {
+		targ_size_t Tdim;	// TYarray: # of elements in array
+		elem* Tel;	// TFvla: gives dimension (NULL if '*')
+		PARAM* Tparamtypes; // TYfunc, TYtemplate: types of function parameters
+		Classsym* Ttag;	// TYstruct,TYmemptr: tag symbol
+				// TYenum,TYvtshape: tag symbol
+		char* Tident;		// TYident: identifier
+version (SCPP) {
+		TYPE* Talternate;	// typtr: type of parameter before converting
+}
+version (MARS) {
+		TYPE* Tkey;	// typtr: key type for associative arrays
+}
+    }
+
+    list_t Texcspec;		// tyfunc(): list of types of exception specification
+
+static if (false) {
+    ushort Tstabidx;	// Index into stab types
+}
+///    TARGET_strucTYPE
+version (SOURCE_4TYPES) {
+    Srcpos Tsrcpos;		/* position of type definition */
+}
+version (HTOD) {
+    Symbol* Ttypedef;		// if this type came from a typedef, this is
+				// the typedef symbol
+}
+}
+
+void dumpTYPE(TYPE* 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, ");");
+	}
+}
+
+alias TYPE type;
+
+alias type* typep_t;
+
+extern(C++) extern __gshared typep_t tstypes[TYM.TYMAX];
+extern(C++) extern __gshared typep_t tsptr2types[TYM.TYMAX];
+
+ref type* tsbool	  () { return tstypes[TYM.TYbool]; }
+ref type* tschar    () { return tstypes[TYM.TYchar]; }
+ref type* tsschar   () { return tstypes[TYM.TYschar]; }
+ref type* tsuchar   () { return tstypes[TYM.TYuchar]; }
+ref type* tsshort   () { return tstypes[TYM.TYshort]; }
+ref type* tsushort  () { return tstypes[TYM.TYushort]; }
+ref type* tswchar_t () { return tstypes[TYM.TYwchar_t]; }
+ref type* tsint     () { return tstypes[TYM.TYint]; }
+ref type* tsuns     () { return tstypes[TYM.TYuint]; }
+ref type* tslong    () { return tstypes[TYM.TYlong]; }
+ref type* tsulong   () { return tstypes[TYM.TYulong]; }
+ref type* tsdchar   () { return tstypes[TYM.TYdchar]; }
+ref type* tsllong   () { return tstypes[TYM.TYllong]; }
+ref type* tsullong  () { return tstypes[TYM.TYullong]; }
+ref type* tsfloat   () { return tstypes[TYM.TYfloat]; }
+ref type* tsdouble  () { return tstypes[TYM.TYdouble]; }
+ref type* tsreal64  () { return tstypes[TYM.TYdouble_alias]; }
+ref type* tsldouble () { return tstypes[TYM.TYldouble]; }
+ref type* tsvoid	() { return tstypes[TYM.TYvoid]; }
+ref type* tsifloat   () { return tstypes[TYM.TYifloat]; }
+ref type* tsidouble  () { return tstypes[TYM.TYidouble]; }
+ref type* tsildouble () { return tstypes[TYM.TYildouble]; }
+ref type* tscfloat   () { return tstypes[TYM.TYcfloat]; }
+ref type* tscdouble  () { return tstypes[TYM.TYcdouble]; }
+ref type* tscldouble () { return tstypes[TYM.TYcldouble]; }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Thunk.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3 @@
+module dmd.backend.Thunk;
+
+struct Thunk;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/Util.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,133 @@
+module dmd.backend.Util;
+
+import dmd.Array;
+import dmd.Loc;
+
+import dmd.backend.elem;
+import dmd.backend.Symbol;
+import dmd.backend.TYPE;
+import dmd.backend.SC;
+import dmd.backend.dt_t;
+import dmd.backend.LIST;
+import dmd.backend.block;
+import dmd.backend.targ_types;
+import dmd.backend.SYMIDX;
+import dmd.backend.PARAM;
+import dmd.backend.Blockx;
+import dmd.backend.struct_t;
+import dmd.backend.BC;
+import dmd.backend.code;
+
+import std.string;
+
+alias ubyte mangle_t;
+
+alias SC enum_SC;
+alias uint SYMFLGS;
+
+version (MARS) {
+	enum SYM_PREDEF_SZ = 35;
+} else {
+	enum SYM_PREDEF_SZ = 22;
+}
+
+//extern (C++) extern {
+	elem* eictor;
+	Symbol* ictorlocalgot;
+	elem* ector;
+	Array ectorgates;
+	elem* edtor;
+	elem* etest;
+	int dtorcount;
+	Symbol* localgot;
+//}
+
+static this()
+{
+	ectorgates = new Array();
+}
+
+alias uint tym_t;		// data type big enough for type masks
+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);
+	e.Esrcpos.Slinnum = loc.linnum;
+}
+
+void elem_setLoc(elem* e, Loc loc) {
+	return el_setLoc(e, loc);
+}
+
+struct_t* struct_calloc() {
+	return cast(struct_t *) mem_fcalloc(struct_t.sizeof);
+}
+///#define struct_free(st)	((void)(st))
+
+extern (C++) {
+	void* mem_fcalloc(uint numbytes);
+	void obj_initfile(const(char)* filename, const(char)* csegname, const(char)* modname);
+	Symbol* symbol_calloc(const(char)* id);
+	type* type_fake(tym_t);
+	dt_t** dtnzeros(dt_t** pdtend, targ_size_t size);
+	void outdata(Symbol* s);
+	int reftoident(int seg, targ_size_t offset, Symbol* s, targ_size_t val, int flags);
+	dt_t ** dtnbytes(dt_t** pdtend, targ_size_t size, const(char)* ptr);
+	type* type_alloc(tym_t ty);
+	elem_p el_params(elem_p, ...);
+	elem_p el_ptr(Symbol*);
+	elem_p el_long(tym_t, targ_long);
+	elem_p el_bin(uint, tym_t, elem_p, elem_p);
+	elem_p el_var(Symbol*);
+	elem_p el_combine(elem_p, elem_p);
+	block* block_calloc();
+	void writefunc(Symbol* sfunc);
+	void obj_termfile();
+	int objextdef(const(char)* name);
+	void obj_includelib(const(char)* name);
+	SYMIDX symbol_add(Symbol* s);
+	elem* el_param(elem* e1, elem* e2);
+	elem* el_una(uint op, tym_t ty, elem* e1);
+	Symbol* symbol_name(const(char)* name, int sclass, type* t);
+	type* type_setcv(type** pt, tym_t cv);
+	int type_jparam(type* t);
+	void obj_export(Symbol* s, uint argsize);
+	void obj_startaddress(Symbol* s);
+	void symbol_func(Symbol* s);
+	type* type_allocn(tym_t, type* tn);
+	param_t* param_append_type(param_t** pp, type* t);
+	void block_appendexp(block* b, elem* e);
+	void block_next(Blockx* bctx, BC bc, block* bn);
+	dt_t** dtxoff(dt_t** pdtend, Symbol* s,targ_size_t offset, tym_t ty);
+	dt_t** dtdword(dt_t** pdtend, int value);
+	dt_t** dtabytes(dt_t** pdtend, tym_t ty, targ_size_t offset, targ_size_t size, const(char)* ptr);
+	void obj_moduleinfo(Symbol* scc);
+	Symbol* symbol_genauto(TYPE* t);
+	elem* el_same(elem**);
+	void el_free(elem*);
+	Symbol* symbol_generate(int sclass, type* t);
+	elem* el_calloc();
+	void dt_optimize(dt_t* dt);
+	type* type_setty(type**, int);
+	type* type_setmangle(type** pt, mangle_t mangle);
+	list_t list_append(list_t* plist, void* ptr);
+	dt_t** dtcat(dt_t** pdtend, dt_t* dt);
+	elem_p el_copytree(elem_p);
+	elem_p el_pair(tym_t, elem_p, elem_p);
+	int el_allbits(elem *e, int bit);
+	block* block_goto(Blockx* bctx, BC bc, block* bn);
+	block* block_calloc(Blockx* blx);
+	targ_size_t type_paramsize_i(type* t);
+	int os_critsecsize();
+	void el_setVolatile(elem* e);
+	elem* exp2_copytotemp(elem* e);
+	elem* el_const(tym_t, eve*);
+	elem *el_params(void** args, int length);
+	
+	void cod3_thunk(Symbol* sthunk, Symbol* sfunc, uint p, tym_t thisty, targ_size_t d, int i, targ_size_t d2);
+	
+	version (SEH) {
+		void nteh_declarvars(Blockx* bx);
+		elem* nteh_setScopeTableIndex(Blockx* blx, int scope_index);
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/block.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,153 @@
+module dmd.backend.block;
+
+import dmd.backend.elem;
+import dmd.backend.LIST;
+import dmd.backend.regm_t;
+import dmd.backend.Symbol;
+import dmd.backend.Srcpos;
+import dmd.backend.code;
+import dmd.backend.SYMIDX;
+import dmd.backend.vec_t;
+import dmd.backend.targ_types;
+import dmd.backend.con_t;
+
+struct block
+{
+    union
+    {
+		elem* Belem;		// pointer to elem tree
+		list_t	Blist;		// list of expressions
+    };
+
+    block* Bnext;		// pointer to next block in list
+    list_t	  Bsucc;	// linked list of pointers to successors
+				//     of this block
+    list_t	  Bpred;	// and the predecessor list
+
+    int Bindex;			// into created object stack
+    int Bendindex;		// index at end of block
+    block* Btry;		// BCtry,BC_try: enclosing try block, if any
+				// BC???: if in try-block, points to BCtry or BC_try
+				// note that can't have a BCtry and BC_try in
+				// the same function.
+    union
+    {	
+		targ_llong	*Bswitch;	// BCswitch: pointer to switch data
+		struct
+		{
+			regm_t usIasmregs;		// Registers modified
+			ubyte bIasmrefparam;   // References parameters?
+		}
+
+		struct
+		{
+			Symbol* catchvar;		// __throw() fills in this
+		}
+
+		struct
+		{   
+			Symbol* catchtype;		// one type for each catch block
+		}
+
+		struct
+		{
+			Symbol* jcatchvar;		// __j_throw() fills in this
+			int Bscope_index;		// index into scope table
+			int Blast_index;		// enclosing index into scope table
+		}
+    }
+	
+	public alias catchtype Bcatchtype;
+
+    Srcpos	Bsrcpos;	// line number (0 if not known)
+    ubyte BC;		// exit condition (enum BC)
+// NEW
+    ubyte Balign;	// alignment
+
+    ushort Bflags;		// flags (BFLxxxx)
+    code* Bcode;		// code generated for this block
+
+    uint Bweight;		// relative number of times this block
+				// is executed (optimizer and codegen)
+
+    uint	Bdfoidx;	// index of this block in dfo[]
+    union
+    {
+		// CPP
+		struct
+		{
+			SYMIDX	symstart;	// (symstart <= symnum < symend) Symbols
+			SYMIDX	symend;		// are declared in this block
+			block* endscope;	// block that forms the end of the
+						// scope for the declared Symbols
+			uint blknum;		// position of block from startblock
+			Symbol* Binitvar;	// !=NULL points to an auto variable with
+						// an explicit or implicit initializer
+			block* gotolist;	// BCtry, BCcatch: backward list of try scopes
+			block* gotothread;	// BCgoto: threaded list of goto's to
+						// unknown labels
+		}
+
+		// OPTIMIZER
+		struct
+		{
+			vec_t	Bdom;		// mask of dominators for this block
+			vec_t	Binrd;
+			vec_t	Boutrd;		// IN and OUT for reaching definitions
+			vec_t	Binlv;
+			vec_t	Boutlv;		// IN and OUT for live variables
+			vec_t	Bin;
+			vec_t	Bout;		// IN and OUT for other flow analyses
+			vec_t	Bgen;
+			vec_t	Bkill;		// pointers to bit vectors used by data
+						// flow analysis
+
+			// BCiftrue can have different vectors for the 2nd successor:
+			vec_t	Bout2;
+			vec_t	Bgen2;
+			vec_t	Bkill2;
+		}
+
+		// CODGEN
+		struct
+		{
+			targ_size_t	Btablesize;	// BCswitch, BCjmptab
+			targ_size_t	Btableoffset;	// BCswitch, BCjmptab
+			targ_size_t	Boffset;	// code offset of start of this block
+			targ_size_t	Bsize;		// code size of this block
+			con_t	Bregcon;	// register state at block exit
+			targ_size_t Btryoff;	// BCtry: offset of try block data
+		}
+    }
+}
+
+enum BFL
+{
+	BFLvisited = 1,		// set if block is visited
+	BFLmark = 2,		// set if block is visited
+	BFLjmpoptdone = 4,		// set when no more jump optimizations
+				   	//  are possible for this block
+	BFLnostackopt = 8,		// set when stack elimination should not
+					// be done
+///version (NTEXCEPTIONS) {
+	BFLehcode = 0x10,	// set when we need to load exception code
+	BFLunwind = 0x1000,	// do local_unwind following block
+///}
+///version (TARGET_POWERPC) {
+///	BFLstructret = 0x10,	/* Set if a struct return is changed to
+///					   block type BCret.  This is done to avoid
+///					   error messages */
+///}
+	BFLnomerg = 0x20,	// do not merge with other blocks
+///version (TX86) {
+	BFLprolog = 0x80,	// generate function prolog
+	BFLepilog = 0x100,	// generate function epilog
+	BFLrefparam = 0x200,	// referenced parameter
+	BFLreflocal = 0x400,	// referenced local
+	BFLoutsideprolog = 0x800,	// outside function prolog/epilog
+    BFLlabel = 0x2000,	// block preceded by label
+///} else {
+///	BFLlooprt = 0x40,	// set if looprotate() changes it's Bnext
+///}
+	BFLvolatile = 0x4000,	// block is volatile
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/code.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,146 @@
+module dmd.backend.code;
+
+import dmd.backend.targ_types;
+import dmd.backend.Srcpos;
+import dmd.backend.elem;
+import dmd.backend.block;
+import dmd.backend.Symbol;
+import dmd.Declaration;
+import dmd.LabelDsymbol;
+
+/**********************************
+ * Code data type
+ */
+
+union evc
+{
+    targ_int	Vint;		// also used for tmp numbers (FLtmp)
+    targ_uns	Vuns;
+    targ_long	Vlong;
+
+    struct EP
+    {	
+		targ_size_t Vpointer;
+		int Vseg;		// segment the pointer is in
+    } EP _EP;
+
+    Srcpos	Vsrcpos;	// source position for OPlinnum
+    elem* Vtor;		// OPctor/OPdtor elem
+    block* Vswitch;	// when FLswitch and we have a switch table
+    code* Vcode;		// when code is target of a jump (FLcode)
+    block* Vblock;	// when block " (FLblock)
+
+    struct SP
+    {
+		targ_size_t Voffset;	// offset from symbol
+		Symbol* Vsym;		// pointer to symbol table (FLfunc,FLextern)
+    } SP sp;
+
+version (MARS) {
+    struct DSP
+    {
+		targ_size_t Voffset;	// offset from symbol
+		Declaration Vsym;	// pointer to D symbol table
+    } DSP dsp;
+}
+
+version (MARS) {
+    struct LAB
+    {
+		targ_size_t Voffset;	// offset from symbol
+		LabelDsymbol Vsym;	// pointer to Label
+    } LAB lab;
+}
+
+    struct AS
+    {   
+		uint len;
+		char* bytes;
+    } AS as;			// asm node (FLasm)
+}
+
+enum CF
+{
+	CFes	         = 1,	// generate an ES: segment override for this instr
+	CFjmp16	         = 2,	// need 16 bit jump offset (long branch)
+	CFtarg	         = 4,	// this code is the target of a jump
+	CFseg	         = 8,	// get segment of immediate value
+	CFoff	      = 0x10,	// get offset of immediate value
+	CFss	      = 0x20,	// generate an SS: segment override (not with
+							// CFes at the same time, though!)
+	CFpsw	     =  0x40,	// we need the flags result after this instruction
+	CFopsize     =  0x80,	// prefix with operand size
+	CFaddrsize   = 0x100,	// prefix with address size
+	CFds	     = 0x200,	// need DS override (not with es, ss, or cs )	
+	CFcs	     = 0x400,	// need CS override
+	CFfs	     = 0x800,	// need FS override
+	CFgs = (CFcs | CFfs),	// need GS override
+	CFwait      = 0x1000,	// If I32 it indicates when to output a WAIT
+	CFselfrel   = 0x2000, 	// if self-relative
+	CFunambig   = 0x4000,   // indicates cannot be accessed by other addressing
+							// modes
+	CFtarg2	    = 0x8000,	// like CFtarg, but we can't optimize this away
+	CFvolatile = 0x10000,	// volatile reference, do not schedule
+	CFclassinit= 0x20000,	// class init code
+
+	CFSEG	= (CFes | CFss | CFds | CFcs | CFfs | CFgs),
+	CFPREFIX = (CFSEG | CFopsize | CFaddrsize),
+}
+
+struct code
+{
+    code* next;
+    uint Iflags;
+
+    ubyte Ijty = 0;		// type of operand, 0 if unknown
+
+    ubyte Iop;
+    ubyte Irm;		// reg/mode
+
+    ubyte Iop2;		// second opcode byte
+    ubyte Isib = 0;		// SIB byte
+
+    ubyte Iop3;		// third opcode byte
+
+    ubyte IFL1;
+	ubyte IFL2;		// FLavors of 1st, 2nd operands
+    evc IEV1;		// 1st operand, if any
+	
+	ref targ_size_t IEVpointer1 () { return IEV1._EP.Vpointer; }
+	ref int IEVseg1     () { return IEV1._EP.Vseg; }
+	ref Symbol* IEVsym1     () { return IEV1.sp.Vsym; }
+	ref Declaration IEVdsym1    () { return IEV1.dsp.Vsym; }
+	ref targ_size_t IEVoffset1  () { return IEV1.sp.Voffset; }
+	ref LabelDsymbol IEVlsym1    () { return IEV1.lab.Vsym; }
+	ref targ_int IEVint1	   () { return IEV1.Vint; }
+	
+    evc IEV2;		// 2nd operand, if any
+
+	ref targ_size_t IEVpointer2 () { return IEV2._EP.Vpointer; }
+	ref int IEVseg2     () { return IEV2._EP.Vseg; }
+	ref Symbol* IEVsym2     () { return IEV2.sp.Vsym; }
+	ref Declaration IEVdsym2    () { return IEV2.dsp.Vsym; }
+	ref targ_size_t IEVoffset2  () { return IEV2.sp.Voffset; }
+	ref LabelDsymbol IEVlsym2    () { return IEV2.lab.Vsym; }
+	ref targ_int IEVint2	   () { return IEV2.Vint; }
+/+
+    void print();		// pretty-printer
++/
+}
+
+import std.stdio;
+
+void dumpCode(code* foo)
+{
+	writefln("code.sizeof: %d", code.sizeof);
+	writefln("Srcpos.sizeof: %d", Srcpos.sizeof);
+	writefln("evc.sizeof: %d", evc.sizeof);
+	writefln("EP.sizeof: %d", evc.EP.sizeof);
+	writefln("SP.sizeof: %d", evc.SP.sizeof);
+	writefln("targ_long.sizeof: %d", targ_long.sizeof);
+	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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/con_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,17 @@
+module dmd.backend.con_t;
+
+import dmd.backend.cse_t;
+import dmd.backend.immed_t;
+import dmd.backend.regm_t;
+
+struct con_t
+{
+	cse_t cse;			// CSEs in registers
+    immed_t immed;		// immediate values in registers
+    regm_t mvar;		// mask of register variables
+    regm_t mpvar;		// mask of SCfastpar register variables
+    regm_t indexregs;		// !=0 if more than 1 uncommitted index register
+    regm_t used;		// mask of registers used
+    regm_t params;		// mask of registers which still contain register
+				// function parameters
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/cse_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.backend.cse_t;
+
+import dmd.backend.elem;
+import dmd.backend.regm_t;
+
+enum REGMAX = 10;
+
+struct cse_t
+{   
+	elem* value[REGMAX];	// expression values in registers
+    regm_t mval;		// mask of which values in value[] are valid
+    regm_t mops;		// subset of mval that contain common subs that need
+				// to be stored in csextab[] if they are destroyed
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/dt_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,51 @@
+module dmd.backend.dt_t;
+
+import dmd.backend.targ_types;
+import dmd.backend.Symbol;
+
+struct dt_t
+{
+	dt_t* DTnext;			// next in list
+    char dt;				// type (DTxxxx)
+    ubyte Dty;			// pointer type
+
+    union
+    {
+		struct				// DTibytes
+		{
+			char DTn;			// number of bytes
+			char DTdata[7];		// data
+		}
+
+		char DTonebyte;		// DT1byte
+
+		targ_size_t DTazeros;		// DTazeros,DTcommon,DTsymsize
+
+		struct				// DTabytes
+		{
+			char* DTpbytes;		// pointer to the bytes
+			uint DTnbytes;		// # of bytes
+version (TX86) {
+			int DTseg;			// segment it went into
+}
+			targ_size_t DTabytes;		// offset of abytes for DTabytes
+		}
+
+		struct				// DTxoff
+		{
+			Symbol* DTsym;		// symbol pointer
+			targ_size_t DToffset;	// offset from symbol
+		}
+    }
+}
+
+import std.stdio;
+
+void dumpDt(dt_t* 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
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/elem.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,156 @@
+module dmd.backend.elem;
+
+import dmd.Port;
+import dmd.Complex;
+
+import dmd.backend.targ_types;
+import dmd.backend.Symbol;
+import dmd.backend.PARAM;
+import dmd.backend.LIST;
+import dmd.backend.Classsym;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.Srcpos;
+
+/*********************************
+ * Union of all data types. Storage allocated must be the right
+ * size of the data on the TARGET, not the host.
+ */
+
+union eve
+{
+	targ_char	Vchar;
+	targ_schar	Vschar;
+	targ_uchar	Vuchar;
+	targ_short	Vshort;
+	targ_ushort	Vushort;
+	targ_int	Vint;	 // also used for tmp numbers (FLtmp)
+	targ_uns	Vuns;
+	targ_long	Vlong;
+	targ_ulong	Vulong;
+	targ_llong	Vllong;
+	targ_ullong	Vullong;
+	targ_float	Vfloat;
+	targ_double	Vdouble;
+    targ_ldouble	Vldouble;
+	Complex!(float)	Vcfloat;
+	Complex!(double)Vcdouble;
+	Complex!(real)	Vcldouble;
+	targ_size_t	Vpointer;
+	targ_ptrdiff_t	Vptrdiff;
+	targ_uchar Vreg;	// register number for OPreg elems
+
+	struct VFP			// 48 bit 386 far pointer
+	{   targ_long	Voff;
+	    targ_ushort	Vseg;
+	} VFP Vfp;
+
+	struct SP
+	{
+	    targ_size_t Voffset;// offset from symbol
+	    Symbol* Vsym;	// pointer to symbol table
+	    union SPU
+	    {	
+			PARAM* Vtal;	// template-argument-list for SCfunctempl,
+				// used only to transmit it to cpp_overload()
+			LIST* Erd;	// OPvar: reaching definitions
+	    } SPU spu;
+	} SP sp;
+
+	struct SM
+	{
+	    targ_size_t Voffset;// member pointer offset
+	    Classsym* Vsym;	// struct tag
+	    elem* ethis;	// OPrelconst: 'this' for member pointer
+	} SM sm;
+
+	struct SS
+	{
+	    targ_size_t	Voffset;// offset from string
+	    char* Vstring;	// pointer to string (OPstring or OPasm)
+	    targ_size_t	Vstrlen;// length of string
+	} SS ss;
+
+	struct EOP
+	{   
+	    elem* Eleft;	// left child for unary & binary nodes
+	    elem* Eright;	// right child for binary nodes
+	    Symbol* Edtor;	// OPctor: destructor
+	} EOP eop;
+}				// variants for each type of elem
+
+/******************************************
+ * Elems:
+ *	Elems are the basic tree element. They can be either
+ *	terminal elems (leaves), unary elems (left subtree exists)
+ *	or binary elems (left and right subtrees exist).
+ */
+struct elem
+{
+debug {
+    ushort	id;
+}
+
+    ubyte Eoper;	// operator (OPxxxx)
+    ubyte Ecount;	// # of parents of this elem - 1,
+				// always 0 until CSE elimination is done
+    eve EV;		// variants for each type of elem
+	
+	ref elem* E1()
+	{
+		return EV.eop.Eleft;		/* left child			*/
+	}
+
+	ref elem* E2()
+	{
+		return EV.eop.Eright;		/* right child			*/
+	}
+
+	ref LIST* Erd()
+	{
+		return EV.sp.spu.Erd;		// reaching definition
+	}
+	
+    union
+    {
+		// PARSER
+		struct
+		{
+			TYPE* ET;	// pointer to type of elem
+			ubyte PEFflags;
+		}
+
+		// OPTIMIZER
+		struct
+		{
+			tym_t Ety;			// data type (TYxxxx)
+			uint Eexp;		// index into expnod[]
+
+			// These flags are all temporary markers, used once and then
+			// thrown away.
+			ubyte Nflags;	// NFLxxx
+version (MARS) {
+			ubyte Ejty;		// original Jupiter/Mars type
+}
+		}
+
+		// CODGEN
+		struct
+		{
+			// Ety2: Must be in same position as Ety!
+			tym_t Ety2;			// data type (TYxxxx)
+			ubyte Ecomsub;	// number of remaining references to
+						// this common subexp (used to determine
+						// first, intermediate, and last references
+						// to a CSE)
+
+version (TARGET_POWERPC) {
+			ubyte Gflags;
+}
+		}
+    }
+
+    targ_size_t Enumbytes;	// number of bytes for type if TYstruct | TYarray
+//    TARGET_structELEM		// target specific additions
+    Srcpos Esrcpos;		// source file position
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/enum_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,15 @@
+module dmd.backend.enum_t;
+
+import dmd.backend.SEN;
+import dmd.backend.Symbol;
+import dmd.backend.LIST;
+
+struct enum_t
+{
+    uint SEflags;
+
+    Symbol* SEalias;		// pointer to identifier E to use if
+				/* enum was defined as:			*/
+				/*	typedef enum { ... } E;		*/
+    symlist_t SEenumlist;	// all members of enum
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/func_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,68 @@
+module dmd.backend.func_t;
+
+import dmd.backend.LIST;
+import dmd.backend.block;
+import dmd.backend.symtab_t;
+import dmd.backend.Srcpos;
+import dmd.backend.Symbol;
+import dmd.backend.Classsym;
+import dmd.backend.Funcsym;
+import dmd.backend.elem;
+import dmd.backend.token_t;
+import dmd.backend.Thunk;
+import dmd.backend.PARAM;
+
+struct func_t
+{
+    symlist_t Fsymtree;		// local Symbol table
+    block* Fstartblock;		// list of blocks comprising function
+    symtab_t Flocsym;		// local Symbol table
+    Srcpos Fstartline;		// starting line # of function
+    Srcpos Fendline;		// line # of closing brace of function
+    Symbol* F__func__;		// symbol for __func__[] string
+    uint Fflags;
+	uint Fflags3;
+    ubyte Foper;	// operator number (OPxxxx) if Foperator
+
+    Symbol* Fparsescope;	// use this scope to parse friend functions
+				// which are defined within a class, so the
+				// class is in scope, but are not members
+				// of the class
+
+    Classsym* Fclass;		// if member of a class, this is the class
+				// (I think this is redundant with Sscope)
+    Funcsym* Foversym;		// overloaded function at same scope
+    symlist_t Fclassfriends;	/* Symbol list of classes of which this	*/
+				/* function is a friend			*/
+    block* Fbaseblock;		// block where base initializers get attached
+    block* Fbaseendblock;	// block where member destructors get attached
+    elem* Fbaseinit;		/* list of member initializers (meminit_t) */
+				/* this field has meaning only for	*/
+				/* functions which are constructors	*/
+    token_t* Fbody;	/* if deferred parse, this is the list	*/
+				/* of tokens that make up the function	*/
+				/* body					*/
+				// also used if SCfunctempl, SCftexpspec
+    uint Fsequence;		// sequence number at point of definition
+    union 
+    {
+		Symbol* Ftempl;		// if Finstance this is the template that generated it
+		Thunk* Fthunk;	// !=NULL if this function is actually a thunk
+    }
+	
+    Funcsym* Falias;		// SCfuncalias: function Symbol referenced
+				// by using-declaration
+
+    symlist_t Fthunks;		// list of thunks off of this function
+
+    param_t* Farglist;		// SCfunctempl: the template-parameter-list
+    param_t* Fptal;		// Finstance: this is the template-argument-list
+				// SCftexpspec: for explicit specialization, this
+				// is the template-argument-list
+    list_t Ffwdrefinstances;	// SCfunctempl: list of forward referenced instances
+    list_t Fexcspec;		// List of types in the exception-specification
+				// (NULL if none or empty)
+    Funcsym* Fexplicitspec;	// SCfunctempl, SCftexpspec: threaded list
+				// of SCftexpspec explicit specializations
+    Funcsym* Fsurrogatesym;	// Fsurrogate: surrogate cast function   
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/glue.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,552 @@
+module dmd.backend.glue;
+
+import dmd.Array;
+import dmd.Dsymbol;
+import dmd.File;
+import dmd.FileName;
+import dmd.Library;
+import dmd.OutBuffer;
+import dmd.Module;
+import dmd.Identifier;
+import dmd.AssertExp;
+import dmd.TOK;
+import dmd.Global;
+import dmd.Param;
+import dmd.backend.Config;
+import dmd.backend.Configv;
+import dmd.backend.StringTab;
+
+import core.stdc.string;
+
+__gshared Array obj_symbols_towrite;
+
+extern (C++) extern
+{
+	__gshared Outbuffer objbuf;
+	int go_flag(char* cp);
+	void util_set64();
+	void util_set386();
+}
+
+import std.contracts;
+import std.string;
+
+string lastmname;
+
+struct Outbuffer
+{
+    ubyte* buf;		// the buffer itself
+    ubyte* pend;	// pointer past the end of the buffer
+    ubyte* p;		// current position in buffer
+    uint len;		// size of buffer
+    uint inc;		// default increment size
+
+    this(uint inc)
+	{
+		assert(false);
+	}
+	
+    ~this()
+	{
+		assert(false);
+	}
+	
+    void reset()
+	{
+		assert(false);
+	}
+
+    // Reserve nbytes in buffer
+    void reserve(uint nbytes)
+	{
+		assert(false);
+	}
+
+    // Write n zeros; return pointer to start of zeros
+    void* writezeros(uint n)
+	{
+		assert(false);
+	}
+
+    // Position buffer to accept the specified number of bytes at offset
+    int position(uint offset, uint nbytes);
+
+    // Write an array to the buffer, no reserve check
+    void writen(const(void)* b, int len)
+    {
+		memcpy(p,b,len);
+		p += len;
+    }
+
+    // Clear bytes, no reserve check
+    void clearn(int len)
+    {
+		int i;
+		for (i=0; i< len; i++)
+			*p++ = 0;
+    }
+
+    // Write an array to the buffer.
+    void write(const void *b, int len)
+	{
+		assert(false);
+	}
+
+    void write(Outbuffer* b)
+	{
+		write(b.buf, b.p - b.buf);
+	}
+
+    /**
+     * Flushes the stream. This will write any buffered
+     * output bytes.
+     */
+    void flush() { }
+
+    /**
+     * Writes an 8 bit byte, no reserve check.
+     */
+    void writeByten(char v)
+    {
+		*p++ = v;
+    }
+
+    /**
+     * Writes an 8 bit byte.
+     */
+    void writeByte(int v)
+	{
+		assert(false);
+	}
+
+    /**
+     * Writes a 16 bit little-end short, no reserve check.
+     */
+    void writeWordn(int v)
+    {
+version (_WIN32) {
+		*cast(ushort*)p = cast(short)v;
+} else {
+		p[0] = v;
+		p[1] = v >> 8;
+}
+		p += 2;
+    }
+
+    /**
+     * Writes a 16 bit little-end short.
+     */
+    void writeWord(int v)
+    {
+		reserve(2);
+		writeWordn(v);
+    }
+
+    /**
+     * Writes a 16 bit big-end short.
+     */
+    void writeShort(int v)
+    {
+		if (pend - p < 2)
+			reserve(2);
+
+static if (false) {
+		p[0] = (cast(ubyte*)&v)[1];
+		p[1] = v;
+} else {
+		ubyte* q = p;
+		q[0] = cast(ubyte)(v >> 8);
+		q[1] = cast(ubyte)v;
+}
+		p += 2;
+    }
+
+    /**
+     * Writes a 16 bit char.
+     */
+    void writeChar(int v)
+    {
+		writeShort(v);
+    }
+
+    /**
+     * Writes a 32 bit int.
+     */
+    void write32(long v)
+	{
+		assert(false);
+	}
+
+    /**
+     * Writes a 64 bit long.
+     */
+///#if __INTSIZE == 4
+    void write64(long v)
+	{
+		assert(false);
+	}
+///#endif
+
+    /**
+     * Writes a 32 bit float.
+     */
+    void writeFloat(float v)
+	{
+		assert(false);
+	}
+
+    /**
+     * Writes a 64 bit double.
+     */
+    void writeDouble(double v)
+	{
+		assert(false);
+	}
+
+    void write(const(char)* s)
+	{
+		assert(false);
+	}
+
+    void write(const(ubyte)* s)
+	{
+		assert(false);
+	}
+
+    void writeString(const(char)* s)
+	{
+		assert(false);
+	}
+
+    void prependBytes(const(char)* s)
+	{
+		assert(false);
+	}
+
+    void bracket(char c1, char c2)
+	{
+		assert(false);
+	}
+
+    /**
+     * Returns the number of bytes written.
+     */
+    int size()
+    {
+		return p - buf;
+    }
+
+    char* toString()
+	{
+		assert(false);
+	}
+	
+    void setsize(uint size)
+	{
+		assert(false);
+	}
+
+    void writesLEB128(long value)
+	{
+		assert(false);
+	}
+	
+    void writeuLEB128(uint value)
+	{
+		assert(false);
+	}
+}
+
+static this()
+{
+	obj_symbols_towrite = new Array();
+}
+
+/**************************************
+ * Append s to list of object files to generate later.
+ */
+ 
+void obj_append(Dsymbol s)
+{
+    obj_symbols_towrite.push(cast(void*)s);
+}
+
+extern (C++) {
+	void backend_init();
+	void backend_term();
+	void obj_term();
+	void rtlsym_reset();
+    void slist_reset();
+	void el_reset();
+	void cg87_reset();
+	void out_reset();
+	void obj_init(Outbuffer* objbuf, const(char)* filename, const(char)* csegname);
+}
+
+void clearStringTab()
+{
+    //printf("clearStringTab()\n");
+    memset(stringTab.ptr, 0, stringTab.sizeof);
+    stidx = 0;
+
+    assertexp_sfilename = null;
+    assertexp_name = null;
+    assertexp_mn = null;
+}
+
+void obj_start(char *srcfile)
+{
+    //printf("obj_start()\n");
+
+    out_config_init();
+
+    rtlsym_reset();
+    slist_reset();
+    clearStringTab();
+
+    obj_init(&objbuf, srcfile, null);
+
+    el_reset();
+    cg87_reset();
+    out_reset();
+}
+
+void obj_end(Library library, File objfile)
+{
+	obj_term();
+
+    if (library)
+    {
+		// Transfer image to library
+		library.addObject(objfile.name.toChars(), objbuf.buf, objbuf.p - objbuf.buf);
+		objbuf.buf = null;
+    }
+    else
+    {
+		// Transfer image to file
+		objfile.setbuffer(objbuf.buf, objbuf.p - objbuf.buf);
+		objbuf.buf = null;
+
+		string p = FileName.path(objfile.name.toChars());
+		FileName.ensurePathExists(p);
+		//mem.free(p);
+
+		//printf("write obj %s\n", objfile.name.toChars());
+		objfile.writev();
+    }
+
+    objbuf.pend = null;
+    objbuf.p = null;
+    objbuf.len = 0;
+    objbuf.inc = 0;
+}
+
+void obj_write_deferred(Library library)
+{
+	for (int i = 0; i < obj_symbols_towrite.dim; i++)
+    {	
+		Dsymbol s = cast(Dsymbol)obj_symbols_towrite.data[i];
+		Module m = s.getModule();
+
+		string mname;
+		if (m)
+		{   
+			mname = m.srcfile.toChars();
+			lastmname = mname;
+		}
+		else
+		{
+			//mname = s->ident->toChars();
+			mname = lastmname;
+			assert(mname.length != 0);
+		}
+
+		obj_start(cast(char*)toStringz(mname));
+
+		static int count;
+		count++;		// sequence for generating names
+
+		/* Create a module that's a doppelganger of m, with just
+		 * enough to be able to create the moduleinfo.
+		 */
+		OutBuffer idbuf = new OutBuffer();
+		idbuf.printf("%s.%d", m ? m.ident.toChars() : mname, count);
+		string idstr = idbuf.extractString();
+		idbuf.data = null;
+		Identifier id = new Identifier(idstr, TOK.TOKidentifier);
+
+		Module md = new Module(mname, id, 0, 0);
+		md.members = new Array();
+		md.members.push(cast(void*)s);	// its only 'member' is s
+		if (m)
+		{
+			md.doppelganger = 1;	// identify this module as doppelganger
+			md.md = m.md;
+			md.aimports.push(cast(void*)m);	// it only 'imports' m
+			md.massert = m.massert;
+			md.marray = m.marray;
+		}
+
+		md.genobjfile(0);
+
+		/* Set object file name to be source name with sequence number,
+		 * as mangled symbol names get way too long.
+		 */
+		string fname = FileName.removeExt(mname);
+		
+		OutBuffer namebuf = new OutBuffer();
+		uint hash = 0;
+		foreach (char c; s.toChars())
+			hash += c;
+
+		namebuf.printf("%s_%x_%x.%s", fname, count, hash, global.obj_ext);
+		fname = namebuf.extractString();
+
+		//printf("writing '%s'\n", fname);
+		File objfile = new File(fname);
+		obj_end(library, objfile);
+    }
+
+    obj_symbols_towrite.dim = 0;
+}
+
+/**************************************
+ * Initialize config variables.
+ */
+
+void out_config_init()
+{
+    Param* params = &global.params;
+
+    if (!config.target_cpu)
+    {
+		config.target_cpu = TARGET_PentiumPro;
+		config.target_scheduler = config.target_cpu;
+    }
+    config.fulltypes = CVNONE;
+    config.inline8087 = 1;
+    config.memmodel = 0;
+    config.flags |= CFGuchar;	// make sure TYchar is unsigned
+version (TARGET_WINDOS) {
+    if (params.isX86_64)
+		config.exe = EX_WIN64;
+    else
+		config.exe = EX_NT;
+
+    // Win32 eh
+    config.flags2 |= CFG2seh;
+
+    if (params.run)
+		config.wflags |= WFexe;		// EXE file only optimizations
+    else if (params.link && !global.params.deffile)
+		config.wflags |= WFexe;		// EXE file only optimizations
+    else if (params.exefile)		// if writing out EXE file
+    {	
+		size_t len = params.exefile.length;
+		if (len >= 4 && icmp(params.exefile[len-3..len], "exe") == 0)
+			config.wflags |= WFexe;
+    }
+    config.flags4 |= CFG4underscore;
+}
+version (TARGET_LINUX) {
+    if (params.isX86_64)
+		config.exe = EX_LINUX64;
+    else
+		config.exe = EX_LINUX;
+    config.flags |= CFGnoebp;
+    config.flags |= CFGalwaysframe;
+    if (params.pic)
+		config.flags3 |= CFG3pic;
+}
+version (TARGET_OSX) {
+    if (params.isX86_64)
+		config.exe = EX_OSX64;
+    else
+		config.exe = EX_OSX;
+    config.flags |= CFGnoebp;
+    config.flags |= CFGalwaysframe;
+    if (params.pic)
+		config.flags3 |= CFG3pic;
+}
+version (TARGET_FREEBSD) {
+    if (params.isX86_64)
+		config.exe = EX_FREEBSD64;
+    else
+		config.exe = EX_FREEBSD;
+    config.flags |= CFGnoebp;
+    config.flags |= CFGalwaysframe;
+    if (params.pic)
+		config.flags3 |= CFG3pic;
+}
+version (TARGET_SOLARIS) {
+    if (params.isX86_64)
+		config.exe = EX_SOLARIS64;
+    else
+		config.exe = EX_SOLARIS;
+    config.flags |= CFGnoebp;
+    config.flags |= CFGalwaysframe;
+    if (params.pic)
+		config.flags3 |= CFG3pic;
+}
+    config.flags2 |= CFG2nodeflib;	// no default library
+    config.flags3 |= CFG3eseqds;
+static if (false) {
+    if (env.getEEcontext().EEcompile != 2)
+		config.flags4 |= CFG4allcomdat;
+    if (env.nochecks())
+		config.flags4 |= CFG4nochecks;	// no runtime checking
+} else version (TARGET_OSX) {
+} else {
+    config.flags4 |= CFG4allcomdat;
+}
+    if (params.trace)
+		config.flags |= CFGtrace;	// turn on profiler
+    if (params.nofloat)
+		config.flags3 |= CFG3wkfloat;
+
+    configv.verbose = params.verbose;
+
+    if (params.optimize)
+		go_flag(cast(char*)"-o".ptr);
+
+    if (params.symdebug)
+    {
+version (ELFOBJ_OR_MACHOBJ) {
+	configv.addlinenumbers = 1;
+	config.fulltypes = (params.symdebug == 1) ? CVDWARF_D : CVDWARF_C;
+}
+version (OMFOBJ) {
+	configv.addlinenumbers = 1;
+	config.fulltypes = CV4;
+}
+	if (!params.optimize)
+	    config.flags |= CFGalwaysframe;
+    }
+    else
+    {
+		configv.addlinenumbers = 0;
+		config.fulltypes = CVNONE;
+		//config.flags &= ~CFGalwaysframe;
+    }
+
+    if (params.isX86_64)
+    {
+		util_set64();
+		cod3_set64();
+    }
+    else
+    {
+		util_set386();
+		cod3_set386();
+    }
+
+debug {
+    debugb = params.debugb;
+    debugc = params.debugc;
+    debugf = params.debugf;
+    debugr = params.debugr;
+    debugw = params.debugw;
+    debugx = params.debugx;
+    debugy = params.debugy;
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/iasm.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,4433 @@
+module dmd.backend.iasm;
+
+import dmd.Dsymbol;
+import dmd.LabelDsymbol;
+import dmd.AsmStatement;
+import dmd.Type;
+import dmd.Scope;
+import dmd.Loc;
+import dmd.Token;
+import dmd.TOK;
+import dmd.Identifier;
+import dmd.Declaration;
+import dmd.VarDeclaration;
+import dmd.EnumMember;
+import dmd.ExpInitializer;
+import dmd.Expression;
+import dmd.IdentifierExp;
+import dmd.StringExp;
+import dmd.Global;
+import dmd.WANT;
+import dmd.STC;
+import dmd.TY;
+import dmd.EnumUtils;
+import dmd.TupleDeclaration;
+import dmd.VarExp;
+import dmd.Id;
+import dmd.FuncExp;
+import dmd.DotIdExp;
+
+import dmd.backend.code;
+import dmd.backend.Srcpos;
+import dmd.backend.FL;
+import dmd.backend.Util;
+import dmd.backend.regm_t;
+import dmd.backend.Config;
+import dmd.backend.targ_types;
+import dmd.backend.elem;
+import dmd.Util;
+
+import std.stdio : writef, writefln;
+import std.string : toStringz;
+import std.algorithm : min;
+
+import core.stdc.stdlib : realloc;
+import core.stdc.stdio : printf;
+import core.stdc.string : strlen;
+import core.stdc.limits;
+
+import std.bitmanip;
+
+alias int[10] jmp_buf;
+
+extern (C) extern 
+{
+	int setjmp(jmp_buf env);
+	void longjmp(jmp_buf env, int value);
+	
+	void cod3_set386();
+	code* genlinnum(code*, Srcpos);
+	code *code_calloc();
+	
+	__gshared int BPRM;
+}
+
+const(char)*[ASMTK.ASMTKmax] apszAsmtk = [
+	"__LOCAL_SIZE",
+	"dword".ptr,
+	"even".ptr,
+	"far".ptr,
+	"naked".ptr,
+	"near".ptr,
+	"ptr".ptr,
+	"qword".ptr,
+	"seg".ptr,
+	"word".ptr,
+];
+
+extern (Pascal) extern {
+	code* cat(code* c1 , code* c2 );
+}
+
+extern (C++) extern 
+{
+	void init_optab();
+	OP* asm_op_lookup(const(char)* s);
+	const(char)* asm_opstr(OP* pop);
+	int binary(const(char)* p , const(char)** tab, int high);
+}
+
+static ubyte asm_TKlbra_seen = false;
+
+struct REG
+{
+	char regstr[6];
+	ubyte val;
+	opflag_t ty;
+}
+
+OP* asm_op_lookup(string s)
+{
+	return asm_op_lookup(toStringz(s));
+}
+
+// For amod (3 bits)
+enum ASM_MODIFIERS : ubyte
+{
+    _normal,	    // Normal register value
+    _rseg,	    // Segment registers
+    _rspecial,	    // Special registers
+    _addr16,	    // 16 bit address
+    _addr32,	    // 32 bit address
+    _fn16,	    // 16 bit function call
+    _fn32,	    // 32 bit function call
+    _flbl	    // Label
+}
+
+mixin(BringToCurrentScope!(ASM_MODIFIERS));
+
+// For aopty (3 bits)
+enum ASM_OPERAND_TYPE : ubyte
+{
+    _reg,	    // _r8, _r16, _r32
+    _m,		    // _m8, _m16, _m32, _m48
+    _imm,	    // _imm8, _imm16, _imm32
+    _rel,	    // _rel8, _rel16, _rel32
+    _mnoi,	    // _m1616, _m1632
+    _p,		    // _p1616, _p1632
+    _rm,	    // _rm8, _rm16, _rm32
+    _float	    // Floating point operand, look at cRegmask for the
+		    // actual size
+}
+
+mixin(BringToCurrentScope!(ASM_OPERAND_TYPE));
+
+/* Register definitions */
+
+enum AX	= 0;
+enum CX	= 1;
+enum DX	= 2;
+enum BX	= 3;
+enum SP	= 4;
+enum BP	= 5;
+enum SI	= 6;
+enum DI	= 7;
+
+enum ES	= 9;
+enum PSW	= 10;
+enum STACK	= 11;	// top of stack
+enum MEM	= 12;	// memory
+enum OTHER	= 13;	// other things
+enum ST0	= 14;	// 8087 top of stack register
+enum ST01	= 15;	// top two 8087 registers; for complex types
+
+enum NOREG = 100;	// no register
+
+enum AL = 0;
+enum CL = 1;
+enum DL = 2;
+enum BL = 3;
+enum AH = 4;
+enum CH = 5;
+enum DH = 6;
+enum BH = 7;
+
+enum mAX = 1;
+enum mCX = 2;
+enum mDX = 4;
+enum mBX = 8;
+enum mSP = 0x10;
+enum mBP = 0x20;
+enum mSI = 0x40;
+enum mDI = 0x80;
+enum mES = (1 << ES);	// 0x200
+enum mPSW = (1 << PSW);	// 0x400
+
+enum mSTACK = (1 << STACK);	// 0x800
+enum mMEM = (1 << MEM);	// 0x1000
+enum mOTHER = (1 << OTHER);	// 0x2000
+
+enum mST0 = (1 << ST0);	// 0x4000
+enum mST01 = (1 << ST01);	// 0x8000
+
+version (XXX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+    // To support positional independent code,
+    // must be able to remove BX from available registers
+///extern regm_t ALLREGS;			
+///#define ALLREGS_INIT		(mAX|mBX|mCX|mDX|mSI|mDI)
+///#define ALLREGS_INIT_PIC	(mAX|mCX|mDX|mSI|mDI)
+///extern regm_t BYTEREGS;			
+///#define BYTEREGS_INIT		(mAX|mBX|mCX|mDX)
+///#define BYTEREGS_INIT_PIC	(mAX|mCX|mDX)
+} else {
+enum ALLREGS = (mAX|mBX|mCX|mDX|mSI|mDI);
+///#define ALLREGS_INIT		ALLREGS
+///#undef BYTEREGS
+///#define BYTEREGS		(mAX|mBX|mCX|mDX)
+}
+
+//#define NPTRSIZE	tysize[TYnptr]
+enum NPTRSIZE = 4;
+
+uint ADDFWAIT() { return 0; }
+
+enum I16 = 0;		// no 16 bit code for D
+enum I32 = (NPTRSIZE == 4);
+enum I64 = (NPTRSIZE == 8);	// true if generating 64 bit code
+
+// For uRegmask (6 bits)
+
+// uRegmask flags when aopty == _float
+enum _rst = 0x1;
+enum _rsti = 0x2;
+enum _64 = 0x4;
+enum _80 = 0x8;
+enum _128 = 0x40;
+enum _112 = 0x10;
+enum _224 = 0x20;
+
+ushort CONSTRUCT_FLAGS(ushort uSizemask, ubyte aopty, ubyte amod, ushort uRegmask ) {
+    return cast(ushort)( (uSizemask) | (aopty) << 4 | (amod) << 7 | (uRegmask) << 10);
+}
+
+// _seg register values (amod == _rseg)
+//
+enum _ds = CONSTRUCT_FLAGS( 0, 0, _rseg, 0x01 );
+enum _es = CONSTRUCT_FLAGS( 0, 0, _rseg, 0x02 );
+enum _ss = CONSTRUCT_FLAGS( 0, 0, _rseg, 0x04 );
+enum _fs = CONSTRUCT_FLAGS( 0, 0, _rseg, 0x08 );
+enum _gs = CONSTRUCT_FLAGS( 0, 0, _rseg, 0x10 );
+enum _cs = CONSTRUCT_FLAGS( 0, 0, _rseg, 0x20 );
+
+//
+// _special register values
+//
+enum _crn = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rspecial, 0x01 ); // CRn register (0,2,3)
+enum _drn = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rspecial, 0x02 ); // DRn register (0-3,6-7)
+enum _trn = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rspecial, 0x04 ); // TRn register (3-7)
+enum _mm  = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rspecial, 0x08 ); // MMn register (0-7)
+enum _xmm = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rspecial, 0x10 ); // XMMn register (0-7)
+
+//
+// Default register values
+//
+enum _al = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._normal, 0x01 );	// AL register
+enum _ax = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._normal, 0x02 );	// AX register
+enum _eax = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._normal, 0x04 );	// EAX register
+enum _dx = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._normal, 0x08 );	// DX register
+enum _cl = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._normal, 0x10 );	// CL register
+
+enum _rplus_r = 0x20;
+//#define _plus_r	CONSTRUCT_FLAGS( 0, 0, 0, _rplus_r )
+		// Add the register to the opcode (no mod r/m)
+
+ubyte ASM_GET_uSizemask(uint us) {
+	return ((us) & 0x0F);
+}
+
+ASM_OPERAND_TYPE ASM_GET_aopty(uint us) {
+	return cast(ASM_OPERAND_TYPE)(((us) & 0x70) >> 4);
+}
+
+ASM_MODIFIERS ASM_GET_amod(uint us)	{
+	return (cast(ASM_MODIFIERS)(((us) & 0x380) >> 7));
+}
+
+ubyte ASM_GET_uRegmask(uint us) {
+	return (((us) & 0xFC00) >> 10);
+}
+
+enum _st = CONSTRUCT_FLAGS( 0, _float, 0, _rst );	// stack register 0
+enum _m112 = CONSTRUCT_FLAGS( 0, _m, 0, _112 );
+enum _m224 = CONSTRUCT_FLAGS( 0, _m, 0, _224 );
+enum _m512 = _m224;
+enum _sti = CONSTRUCT_FLAGS( 0, _float, 0, _rsti );
+
+REG regFp =	{ "ST", 0, _st };
+
+REG[8] aregFp = [
+	{ "ST(0)", 0, _sti },
+	{ "ST(1)", 1, _sti },
+	{ "ST(2)", 2, _sti },
+	{ "ST(3)", 3, _sti },
+	{ "ST(4)", 4, _sti },
+	{ "ST(5)", 5, _sti },
+	{ "ST(6)", 6, _sti },
+	{ "ST(7)", 7, _sti }
+];
+
+// For uSizemask (4 bits)
+enum _8  = 0x1;
+enum _16 = 0x2;
+enum _32 = 0x4;
+enum _48 = 0x8;
+enum _anysize = (_8 | _16 | _32 | _48 );
+
+enum _modrm = 0x10;
+
+//// This is for when the reg field of modregrm specifies which instruction it is
+enum NUM_MASK = 0x7;
+//#define _0	(0x0 | _modrm)		// insure that some _modrm bit is set
+//#define _1	0x1			// with _0
+//#define _2	0x2
+//#define _3	0x3
+//#define _4	0x4
+//#define _5	0x5
+//#define _6	0x6
+//#define _7	0x7
+//
+//#define	_modrm	0x10
+//
+//#define _r	_modrm
+//#define _cb	_modrm
+//#define _cw	_modrm
+//#define _cd	_modrm
+//#define _cp	_modrm
+//#define _ib	0
+//#define _iw	0
+//#define _id	0
+//#define _rb	0
+//#define _rw	0
+//#define _rd	0
+enum _16_bit = 0x20;
+enum _32_bit = 0x40;
+enum _I386 = 0x80;		// opcode is only for 386 and later
+enum _16_bit_addr = 0x100;
+enum _32_bit_addr = 0x200;
+enum _fwait = 0x400;	// Add an FWAIT prior to the instruction opcode
+enum _nfwait = 0x800;	// Do not add an FWAIT prior to the instruction
+
+enum MOD_MASK = 0xF000;	// Mod mask
+enum _modsi = 0x1000;	// Instruction modifies SI
+enum _moddx = 0x2000;	// Instruction modifies DX
+enum _mod2 = 0x3000;	// Instruction modifies second operand
+enum _modax = 0x4000;	// Instruction modifies AX
+enum _modnot1 = 0x5000;	// Instruction does not modify first operand
+enum _modaxdx = 0x6000;	// instruction modifies AX and DX
+enum _moddi = 0x7000;	// Instruction modifies DI
+enum _modsidi = 0x8000;	// Instruction modifies SI and DI
+enum _modcx	= 0x9000;	// Instruction modifies CX
+enum _modes = 0xa000;	// Instruction modifies ES
+enum _modall = 0xb000;	// Instruction modifies all register values
+enum _modsiax = 0xc000;	// Instruction modifies AX and SI
+enum _modsinot1 = 0xd000;	// Instruction modifies SI and not first param
+
+/////////////////////////////////////////////////
+// Operand flags - usOp1, usOp2, usOp3
+//
+
+alias ushort opflag_t;
+
+// Operand flags for normal opcodes
+
+enum _r8 = CONSTRUCT_FLAGS( _8, ASM_OPERAND_TYPE._reg, ASM_MODIFIERS._normal, 0 );
+enum _r16 = CONSTRUCT_FLAGS(_16, ASM_OPERAND_TYPE._reg, ASM_MODIFIERS._normal, 0 );
+enum _r32 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._reg, ASM_MODIFIERS._normal, 0 );
+enum _m8 = CONSTRUCT_FLAGS(_8, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._normal, 0 );
+enum _m16 = CONSTRUCT_FLAGS(_16, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._normal, 0 );
+enum _m32 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._normal, 0 );
+enum _m48 = CONSTRUCT_FLAGS( _48, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._normal, 0 );
+enum _m64 = CONSTRUCT_FLAGS( _anysize, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._normal, 0 );
+enum _m128 = CONSTRUCT_FLAGS( _anysize, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._normal, 0 );
+enum _rm8 = CONSTRUCT_FLAGS(_8, ASM_OPERAND_TYPE._rm, ASM_MODIFIERS._normal, 0 );
+enum _rm16 = CONSTRUCT_FLAGS(_16, ASM_OPERAND_TYPE._rm, ASM_MODIFIERS._normal, 0 );
+enum _rm32 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._rm, ASM_MODIFIERS._normal, 0);
+enum _r32m16 = CONSTRUCT_FLAGS(_32|_16, ASM_OPERAND_TYPE._rm, ASM_MODIFIERS._normal, 0);
+enum _imm8 = CONSTRUCT_FLAGS(_8, ASM_OPERAND_TYPE._imm, ASM_MODIFIERS._normal, 0 );
+enum _imm16 = CONSTRUCT_FLAGS(_16, ASM_OPERAND_TYPE._imm, ASM_MODIFIERS._normal, 0);
+enum _imm32 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._imm, ASM_MODIFIERS._normal, 0);
+enum _rel8 = CONSTRUCT_FLAGS(_8, ASM_OPERAND_TYPE._rel, ASM_MODIFIERS._normal, 0);
+enum _rel16 = CONSTRUCT_FLAGS(_16, ASM_OPERAND_TYPE._rel, ASM_MODIFIERS._normal, 0);
+enum _rel32 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._rel, ASM_MODIFIERS._normal, 0);
+enum _p1616 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._p, ASM_MODIFIERS._normal, 0);
+enum _m1616 = CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._mnoi, ASM_MODIFIERS._normal, 0);
+enum _p1632 = CONSTRUCT_FLAGS(_48, ASM_OPERAND_TYPE._p, ASM_MODIFIERS._normal, 0 );
+enum _m1632 = CONSTRUCT_FLAGS(_48, ASM_OPERAND_TYPE._mnoi, ASM_MODIFIERS._normal, 0);
+enum _special = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rspecial, 0 );
+enum _seg = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._rseg, 0 );
+enum _a16 = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._addr16, 0 );
+enum _a32 = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._addr32, 0 );
+enum _f16 = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._fn16, 0);
+						// Near function pointer
+enum _f32 = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._fn32, 0);
+						// Far function pointer
+enum _lbl = CONSTRUCT_FLAGS( 0, 0, ASM_MODIFIERS._flbl, 0 );
+						// Label (in current function)
+
+enum _mmm32 = CONSTRUCT_FLAGS( 0, ASM_OPERAND_TYPE._m, 0, _32);
+enum _mmm64 = CONSTRUCT_FLAGS( 0, ASM_OPERAND_TYPE._m, 0, _64);
+enum _mmm128 = CONSTRUCT_FLAGS( 0, ASM_OPERAND_TYPE._m, 0, _128);
+
+enum _xmm_m32 = CONSTRUCT_FLAGS( _32, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._rspecial, 0);
+enum _xmm_m64 =CONSTRUCT_FLAGS( _anysize, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._rspecial, 0);
+enum _xmm_m128 =CONSTRUCT_FLAGS( _anysize, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._rspecial, 0);
+
+enum _moffs8 = (_rel8);
+enum _moffs16 = (_rel16 );
+enum _moffs32 = (_rel32 );
+
+////////////////////////////////////////////////////////////////////
+// Operand flags for floating point opcodes are all just aliases for
+// normal opcode variants and only asm_determine_operator_flags should
+// need to care.
+//
+enum _fm80 = CONSTRUCT_FLAGS( 0, ASM_OPERAND_TYPE._m, 0, _80 );
+enum _fm64 = CONSTRUCT_FLAGS( 0, ASM_OPERAND_TYPE._m, 0, _64 );
+enum _fm128 = CONSTRUCT_FLAGS( 0, ASM_OPERAND_TYPE._m, 0, _128 );
+enum _fanysize = (_64 | _80 | _112 | _224);
+
+enum _AL 		=0;
+enum _AH		=4;
+enum _AX		=0;
+enum _EAX		=0;
+enum _BL		=3;
+enum _BH		=7;
+enum _BX		=3;
+enum _EBX		=3;
+enum _CL		=1;
+enum _CH		=5;
+enum _CX		=1;
+enum _ECX		=1;
+enum _DL		=2;
+enum _DH		=6;
+enum _DX		=2;
+enum _EDX		=2;
+enum _BP		=5;
+enum _EBP		=5;
+enum _SP		=4;
+enum _ESP		=4;
+enum _DI		=7;
+enum _EDI		=7;
+enum _SI		=6;
+enum _ESI		=6;
+enum _ES		=0;
+enum _CS		=1;
+enum _SS		=2;
+enum _DS		=3;
+enum _GS		=5;
+enum _FS		=4;
+
+enum ASM = 0x36;			// string of asm bytes, actually an SS: opcode
+enum ASM_END = 0xffff;		// special opcode meaning end of table
+
+struct PTRNTAB0
+{
+	uint usOpcode;
+//	#define ASM_END	0xffff		// special opcode meaning end of table
+	ushort usFlags;
+}
+
+struct PTRNTAB1
+{
+	uint usOpcode;
+	ushort usFlags;
+	opflag_t usOp1;
+}
+
+struct PTRNTAB2
+{
+	uint usOpcode;
+	ushort usFlags;
+	opflag_t usOp1;
+	opflag_t usOp2;
+}
+
+struct PTRNTAB3
+{
+	uint usOpcode;
+	ushort usFlags;
+	opflag_t usOp1;
+	opflag_t usOp2;
+	opflag_t usOp3;
+}
+
+union PTRNTAB
+{
+	PTRNTAB0	*pptb0;
+	PTRNTAB1	*pptb1;
+	PTRNTAB2	*pptb2;
+	PTRNTAB3	*pptb3;
+}
+
+struct OP
+{
+	ubyte usNumops;
+	PTRNTAB	ptb;
+}
+
+enum ASM_JUMPTYPE
+{
+    ASM_JUMPTYPE_UNSPECIFIED,
+    ASM_JUMPTYPE_SHORT,
+    ASM_JUMPTYPE_NEAR,
+    ASM_JUMPTYPE_FAR
+}		    // ajt
+
+mixin(BringToCurrentScope!(ASM_JUMPTYPE));
+
+struct OPND
+{
+	REG* base;		// if plain register
+	REG* pregDisp1;		// if [register1]
+	REG* pregDisp2;
+	REG* segreg;		// if segment override
+	char indirect = 0;		// if had a '*' or '.'
+	char bOffset = 0;		// if 'offset' keyword
+	char bSeg = 0;		// if 'segment' keyword
+	char bPtr = 0;		// if 'ptr' keyword
+	uint uchMultiplier;	// register multiplier; valid values are 0,1,2,4,8
+	opflag_t usFlags;
+	Dsymbol s;
+	int disp;
+	real real_ = 0;
+	Type ptype;
+	ASM_JUMPTYPE ajt;
+}
+
+struct ASM_STATE
+{
+	ubyte ucItype;	// Instruction type
+	Loc loc;
+	ubyte bInit;
+	LabelDsymbol psDollar;
+	Dsymbol psLocalsize;
+	jmp_buf env;
+	ubyte bReturnax;
+	AsmStatement statement;
+	Scope sc;
+}
+
+enum IT
+{
+	ITprefix	= 0x10,	// special prefix
+	ITjump		= 0x20,	// jump instructions CALL, Jxx and LOOPxx
+	ITimmed		= 0x30,	// value of an immediate operand controls
+						// code generation
+	ITopt		= 0x40,	// not all operands are required
+	ITshift		= 0x50,	// rotate and shift instructions
+	ITfloat		= 0x60,	// floating point coprocessor instructions
+	ITdata		= 0x70,	// DB, DW, DD, DQ, DT pseudo-ops
+	ITaddr		= 0x80,	// DA (define addresss) pseudo-op
+	ITMASK		= 0xF0,
+	ITSIZE		= 0x0F,	// mask for size
+}
+
+alias IT.ITprefix ITprefix;
+alias IT.ITjump ITjump;
+alias IT.ITimmed ITimmed;
+alias IT.ITopt ITopt;
+alias IT.ITshift ITshift;
+alias IT.ITfloat ITfloat;
+alias IT.ITdata ITdata;
+alias IT.ITaddr ITaddr;
+alias IT.ITMASK ITMASK;
+alias IT.ITSIZE ITSIZE;
+
+__gshared ASM_STATE asmstate;
+__gshared Token* asmtok;
+__gshared TOK tok_value;
+
+// Additional tokens for the inline assembler
+enum ASMTK 
+{
+    ASMTKlocalsize = TOKMAX + 1,
+    ASMTKdword,
+    ASMTKeven,
+    ASMTKfar,
+    ASMTKnaked,
+    ASMTKnear,
+    ASMTKptr,
+    ASMTKqword,
+    ASMTKseg,
+    ASMTKword,
+    ASMTKmax = ASMTKword - (TOK.TOKMAX + 1) + 1
+}
+
+mixin(BringToCurrentScope!(ASMTK));
+
+enum OP_DB
+{
+///version (SCPP) {
+///    // These are the number of bytes
+///    OPdb = 1,
+///    OPdw = 2,
+///    OPdd = 4,
+///    OPdq = 8,
+///    OPdt = 10,
+///    OPdf = 4,
+///    OPde = 10,
+///    OPds = 2,
+///    OPdi = 4,
+///    OPdl = 8,
+///}
+///version (MARS) {
+    // Integral types
+    OPdb,
+    OPds,
+    OPdi,
+    OPdl,
+
+    // Float types
+    OPdf,
+    OPdd,
+    OPde,
+
+    // Deprecated
+    OPdw = OPds,
+    OPdq = OPdl,
+    OPdt = OPde,
+///}
+}
+
+OPND* opnd_calloc()
+{   
+	return new OPND();
+}
+
+void opnd_free(OPND* o)
+{
+    delete o;
+}
+
+/******************************
+ * Convert assembly instruction into a code, and append
+ * it to the code generated for this block.
+ */
+
+code* asm_emit(Loc loc, uint usNumops, PTRNTAB ptb, OP* pop, OPND* popnd1, OPND* popnd2, OPND* popnd3)
+{
+debug {
+	ubyte auchOpcode[16];
+	uint usIdx = 0;
+	void emit(ubyte op)	{
+		auchOpcode[usIdx++] = op;
+	}
+} else {
+	void emit(ubyte op) {}
+}
+	Identifier id;
+//	ushort us;
+	ubyte* puc;
+	uint usDefaultseg;
+	code* pc = null;
+	OPND* popndTmp;
+	ASM_OPERAND_TYPE aoptyTmp;
+	ushort uSizemaskTmp;
+	REG* pregSegment;
+	code* pcPrefix = null;
+
+	uint uSizemask1 = 0;
+	uint uSizemask2 = 0;
+	uint uSizemask3 = 0;
+
+	//ASM_OPERAND_TYPE    aopty1 = ASM_OPERAND_TYPE._reg , aopty2 = 0, aopty3 = 0;
+	ASM_MODIFIERS amod1 = ASM_MODIFIERS._normal;
+	ASM_MODIFIERS amod2 = ASM_MODIFIERS._normal;
+	ASM_MODIFIERS amod3 = ASM_MODIFIERS._normal;
+
+	uint uRegmask1 = 0;
+	uint uRegmask2 = 0;
+	uint uRegmask3 = 0;
+	
+	uint uSizemaskTable1 = 0;
+	uint uSizemaskTable2 = 0;
+	uint uSizemaskTable3 = 0;
+
+	ASM_OPERAND_TYPE aoptyTable1 = ASM_OPERAND_TYPE._reg;
+	ASM_OPERAND_TYPE aoptyTable2 = ASM_OPERAND_TYPE._reg;
+	ASM_OPERAND_TYPE aoptyTable3 = ASM_OPERAND_TYPE._reg;
+
+	ASM_MODIFIERS amodTable1 = ASM_MODIFIERS._normal;
+	ASM_MODIFIERS amodTable2 = ASM_MODIFIERS._normal;
+	ASM_MODIFIERS amodTable3 = ASM_MODIFIERS._normal;
+
+	uint uRegmaskTable1 = 0;
+	uint uRegmaskTable2 = 0;
+	uint uRegmaskTable3 = 0;
+	
+	pc = code_calloc();
+	pc.Iflags |= CF.CFpsw;		// assume we want to keep the flags
+
+	if (popnd1)
+	{
+	    uSizemask1 = ASM_GET_uSizemask(popnd1.usFlags);
+	    //aopty1 = ASM_GET_aopty(popnd1.usFlags);
+	    amod1 = ASM_GET_amod(popnd1.usFlags);
+	    uRegmask1 = ASM_GET_uRegmask(popnd1.usFlags);
+
+	    uSizemaskTable1 = ASM_GET_uSizemask(ptb.pptb1.usOp1);
+	    aoptyTable1 = ASM_GET_aopty(ptb.pptb1.usOp1);
+	    amodTable1 = ASM_GET_amod(ptb.pptb1.usOp1);
+	    uRegmaskTable1 = ASM_GET_uRegmask(ptb.pptb1.usOp1);
+	    
+	}
+
+	if (popnd2)
+	{
+static if (false) {
+	    printf("\nasm_emit:\nop: ");
+	    asm_output_flags(popnd2.usFlags);
+	    printf("\ntb: ");
+	    asm_output_flags(ptb.pptb2.usOp2);
+	    printf("\n");
+}
+	    uSizemask2 = ASM_GET_uSizemask(popnd2.usFlags);
+	    //aopty2 = ASM_GET_aopty(popnd2.usFlags);
+	    amod2 = ASM_GET_amod(popnd2.usFlags);
+	    uRegmask2 = ASM_GET_uRegmask(popnd2.usFlags);
+
+	    uSizemaskTable2 = ASM_GET_uSizemask(ptb.pptb2.usOp2);
+	    aoptyTable2 = ASM_GET_aopty(ptb.pptb2.usOp2);
+	    amodTable2 = ASM_GET_amod(ptb.pptb2.usOp2);
+	    uRegmaskTable2 = ASM_GET_uRegmask(ptb.pptb2.usOp2);
+	}
+	if (popnd3)
+	{
+	    uSizemask3 = ASM_GET_uSizemask(popnd3.usFlags);
+	    //aopty3 = ASM_GET_aopty(popnd3.usFlags);
+	    amod3 = ASM_GET_amod(popnd3.usFlags);
+	    uRegmask3 = ASM_GET_uRegmask(popnd3.usFlags);
+
+	    uSizemaskTable3 = ASM_GET_uSizemask(ptb.pptb3.usOp3);
+	    aoptyTable3 = ASM_GET_aopty(ptb.pptb3.usOp3);
+	    amodTable3 = ASM_GET_amod(ptb.pptb3.usOp3);
+	    uRegmaskTable3 = ASM_GET_uRegmask(ptb.pptb3.usOp3);
+	}
+
+	asmstate.statement.regs |= asm_modify_regs(ptb, popnd1, popnd2);
+
+	if (!I32 && ptb.pptb0.usFlags & _I386)
+	{
+	    switch (usNumops)
+	    {
+			case 0:
+				break;
+
+			case 1:
+				if (popnd1 && popnd1.s)
+				{
+L386_WARNING:
+					id = popnd1.s.ident;
+L386_WARNING2:
+					if (config.target_cpu < TARGET.TARGET_80386)
+					{   
+						// Reference to %s caused a 386 instruction to be generated
+						//warerr(WM_386_op, id.toChars());
+					}
+				}
+				break;
+
+			case 2:
+			case 3:	    // The third operand is always an ASM_OPERAND_TYPE._imm
+				if (popnd1 && popnd1.s)
+					goto L386_WARNING;
+				if (popnd2 && popnd2.s)
+				{
+					id = popnd2.s.ident;
+					goto L386_WARNING2;
+				}
+				break;
+	    }
+	}
+
+	switch (usNumops)
+	{
+	    case 0:
+			if ((I32 && (ptb.pptb0.usFlags & _16_bit)) || (!I32 && (ptb.pptb0.usFlags & _32_bit)))
+			{
+				emit(0x66);
+				pc.Iflags |= CF.CFopsize;
+			}
+			break;
+
+	    // 3 and 2 are the same because the third operand is always
+	    // an immediate and does not affect operation size
+	    case 3:
+	    case 2:
+			if ((I32 && 
+				  (amod2 == ASM_MODIFIERS._addr16 ||
+				   (uSizemaskTable2 & _16 && aoptyTable2 == ASM_OPERAND_TYPE._rel) ||
+				   (uSizemaskTable2 & _32 && aoptyTable2 == ASM_OPERAND_TYPE._mnoi) ||
+				   (ptb.pptb2.usFlags & _16_bit_addr)
+				 )
+				) ||
+				 (!I32 &&
+				   (amod2 == ASM_MODIFIERS._addr32 ||
+				(uSizemaskTable2 & _32 && aoptyTable2 == ASM_OPERAND_TYPE._rel) ||
+				(uSizemaskTable2 & _48 && aoptyTable2 == ASM_OPERAND_TYPE._mnoi) ||
+				(ptb.pptb2.usFlags & _32_bit_addr)))
+			  )
+			{
+				emit(0x67);
+				pc.Iflags |= CF.CFaddrsize;
+
+				if (I32)
+					amod2 = ASM_MODIFIERS._addr16;
+				else
+					amod2 = ASM_MODIFIERS._addr32;
+
+				popnd2.usFlags &= ~CONSTRUCT_FLAGS(0,0,7,0);
+				popnd2.usFlags |= CONSTRUCT_FLAGS(0,0,amod2,0);
+			}
+
+
+			/* Fall through, operand 1 controls the opsize, but the
+			address size can be in either operand 1 or operand 2,
+			hence the extra checking the flags tested for SHOULD
+			be mutex on operand 1 and operand 2 because there is
+			only one MOD R/M byte
+			 */
+
+	    case 1:
+			if ((I32 &&
+				  (amod1 == ASM_MODIFIERS._addr16 ||
+				   (uSizemaskTable1 & _16 && aoptyTable1 == ASM_OPERAND_TYPE._rel) ||
+					(uSizemaskTable1 & _32 && aoptyTable1 == ASM_OPERAND_TYPE._mnoi) ||
+				(ptb.pptb1.usFlags & _16_bit_addr))) ||
+				 (!I32 &&
+				  (amod1 == ASM_MODIFIERS._addr32 ||
+				(uSizemaskTable1 & _32 && aoptyTable1 == ASM_OPERAND_TYPE._rel) ||
+				(uSizemaskTable1 & _48 && aoptyTable1 == ASM_OPERAND_TYPE._mnoi) ||
+				 (ptb.pptb1.usFlags & _32_bit_addr))))
+			{
+				emit(0x67);	// address size prefix
+				pc.Iflags |= CF.CFaddrsize;
+				if (I32)
+					amod1 = ASM_MODIFIERS._addr16;
+				else
+					amod1 = ASM_MODIFIERS._addr32;
+				popnd1.usFlags &= ~CONSTRUCT_FLAGS(0,0,7,0);
+				popnd1.usFlags |= CONSTRUCT_FLAGS(0,0,amod1,0);
+			}
+
+			// If the size of the operand is unknown, assume that it is
+			// the default size
+			if ((I32 && (ptb.pptb0.usFlags & _16_bit)) ||
+				(!I32 && (ptb.pptb0.usFlags & _32_bit)))
+			{
+				//if (asmstate.ucItype != ITjump)
+				{	emit(0x66);
+				pc.Iflags |= CF.CFopsize;
+				}
+			}
+			if (((pregSegment = (popndTmp = popnd1).segreg) != null) ||
+				((popndTmp = popnd2) != null &&
+				(pregSegment = popndTmp.segreg) != null)
+			  )
+			{
+				if ((popndTmp.pregDisp1 &&
+					popndTmp.pregDisp1.val == _BP) ||
+					popndTmp.pregDisp2 &&
+					popndTmp.pregDisp2.val == _BP)
+					usDefaultseg = _SS;
+				else
+					usDefaultseg = _DS;
+				if (pregSegment.val != usDefaultseg)
+				switch (pregSegment.val) {
+				case _CS:
+					emit(0x2e);
+					pc.Iflags |= CF.CFcs;
+					break;
+				case _SS:
+					emit(0x36);
+					pc.Iflags |= CF.CFss;
+					break;
+				case _DS:
+					emit(0x3e);
+					pc.Iflags |= CF.CFds;
+					break;
+				case _ES:
+					emit(0x26);
+					pc.Iflags |= CF.CFes;
+					break;
+				case _FS:
+					emit(0x64);
+					pc.Iflags |= CF.CFfs;
+					break;
+				case _GS:
+					emit(0x65);
+					pc.Iflags |= CF.CFgs;
+					break;
+				default:
+					assert(0);
+				}
+			}
+			break;
+		}
+		uint usOpcode = ptb.pptb0.usOpcode;
+
+		if ((usOpcode & 0xFFFFFF00) == 0x660F3A00 ||	// SSE4
+			(usOpcode & 0xFFFFFF00) == 0x660F3800)	// SSE4
+		{
+			pc.Iflags |= CF.CFopsize;
+			pc.Iop = 0x0F;
+			pc.Iop2 = (usOpcode >> 8) & 0xFF;
+			pc.Iop3 = usOpcode & 0xFF;
+			goto L3;
+		}
+		switch (usOpcode & 0xFF0000)
+		{
+			case 0:
+			break;
+
+			case 0x660000:
+			pc.Iflags |= CF.CFopsize;
+			usOpcode &= 0xFFFF;
+			break;
+
+			case 0xF20000:			// REPNE
+			case 0xF30000:			// REP/REPE
+			// BUG: What if there's an address size prefix or segment
+			// override prefix? Must the REP be adjacent to the rest
+			// of the opcode?
+			pcPrefix = code_calloc();
+			pcPrefix.Iop = cast(ubyte)(usOpcode >> 16);
+			usOpcode &= 0xFFFF;
+			break;
+
+			case 0x0F0000:			// an AMD instruction
+			puc = (cast(ubyte*) &usOpcode);
+			if (puc[1] != 0x0F)		// if not AMD instruction 0x0F0F
+				goto L4;
+			emit(puc[2]);
+			emit(puc[1]);
+			emit(puc[0]);
+			pc.Iop = puc[2];
+			pc.Iop2 = puc[1];
+			pc.IEVint2() = puc[0];
+			pc.IFL2 = FL.FLconst;
+			goto L3;
+
+			default:
+			puc = (cast(ubyte*) &usOpcode);
+			L4:
+			emit(puc[2]);
+			emit(puc[1]);
+			emit(puc[0]);
+			pc.Iop = puc[2];
+			pc.Iop2 = puc[1];
+			pc.Irm = puc[0];
+			goto L3;
+		}
+		if (usOpcode & 0xff00)
+		{
+			puc = (cast(ubyte*) &(usOpcode));
+			emit(puc[1]);
+			emit(puc[0]);
+			pc.Iop = puc[1];
+			if (pc.Iop == 0x0f)
+			pc.Iop2 = puc[0];
+			else
+			{
+			if (usOpcode == 0xDFE0)	// FSTSW AX
+			{   pc.Irm = puc[0];
+				goto L2;
+			}
+			if (asmstate.ucItype == IT.ITfloat)
+				pc.Irm = puc[0];
+			else
+			{   
+				pc.IEVint2() = puc[0];
+				pc.IFL2 = FL.FLconst;
+			}
+			}
+		}
+		else
+		{
+			emit(cast(ubyte)usOpcode);
+			pc.Iop = cast(ubyte)usOpcode;
+		}
+    L3:	;
+
+		// If CALL, Jxx or LOOPx to a symbolic location
+		if (/*asmstate.ucItype == ITjump &&*/
+			popnd1 && popnd1.s && popnd1.s.isLabel())
+		{   
+			Dsymbol s = popnd1.s;
+			if (s == asmstate.psDollar)
+			{
+				pc.IFL2 = FL.FLconst;
+				if (uSizemaskTable1 & (_8 | _16))
+					pc.IEVint2() = popnd1.disp;
+				else if (uSizemaskTable1 & _32)
+					pc.IEVpointer2() = cast(targ_size_t) popnd1.disp;
+			}   
+			else
+			{	
+				LabelDsymbol label = s.isLabel();
+				if (label)
+				{   
+					if ((pc.Iop & 0xF0) == 0x70)
+						pc.Iflags |= CF.CFjmp16;
+					if (usNumops == 1)
+					{	
+						pc.IFL2 = FL.FLblock;
+						pc.IEVlsym2() = label;
+					}
+					else
+					{	
+						pc.IFL1 = FL.FLblock;
+						pc.IEVlsym1() = label;
+					}
+				}
+			}
+	}
+
+	switch (usNumops)
+	{
+	    case 0:
+			break;
+
+		case 1:
+			if (((aoptyTable1 == ASM_OPERAND_TYPE._reg || aoptyTable1 == ASM_OPERAND_TYPE._float) &&
+				 amodTable1 == ASM_MODIFIERS._normal && (uRegmaskTable1 & _rplus_r)))
+			{
+				if (asmstate.ucItype == IT.ITfloat)
+					pc.Irm += popnd1.base.val;
+				else if (pc.Iop == 0x0f)
+					pc.Iop2 += popnd1.base.val;
+				else
+					pc.Iop += popnd1.base.val;
+debug {
+				auchOpcode[usIdx-1] += popnd1.base.val;
+}
+			}
+			else
+			{	
+				asm_make_modrm_byte(
+///debug {
+				auchOpcode, &usIdx,
+///}
+				pc, 
+				ptb.pptb1.usFlags,
+				popnd1, null);
+			}
+
+			popndTmp = popnd1;
+			aoptyTmp = aoptyTable1;
+			uSizemaskTmp = cast(ushort)uSizemaskTable1;
+	L1:
+			if (aoptyTmp == ASM_OPERAND_TYPE._imm)
+			{
+				Declaration d = popndTmp.s ? popndTmp.s.isDeclaration() : null;
+				if (popndTmp.bSeg)
+				{
+					if (!(d && d.isDataseg()))
+						asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+				}
+				switch (uSizemaskTmp)
+				{
+					case _8:
+					case _16:
+					case _32:
+						if (popndTmp.s is asmstate.psLocalsize)
+						{
+							pc.IFL2 = FL.FLlocalsize;
+							pc.IEVdsym2() = null;
+							pc.Iflags |= CF.CFoff;
+							pc.IEVoffset2() = popndTmp.disp;
+						}
+						else if (d)
+						{
+static if (false) {
+							if ((pc.IFL2 = d.Sfl) == 0)
+								pc.IFL2 = FL.FLdsymbol;
+} else {
+							pc.IFL2 = FL.FLdsymbol;
+}
+							pc.Iflags &= ~(CF.CFseg | CF.CFoff);
+							if (popndTmp.bSeg)
+								pc.Iflags |= CF.CFseg;
+							else
+								pc.Iflags |= CF.CFoff;
+
+							pc.IEVoffset2() = popndTmp.disp;
+							pc.IEVdsym2() = d;
+						}
+						else
+						{
+							pc.IEVint2() = popndTmp.disp;
+							pc.IFL2 = FL.FLconst;
+						}
+						break;
+				}
+			}
+				
+			break;
+		case 2:
+	//
+	// If there are two immediate operands then
+	//
+			if (aoptyTable1 == ASM_OPERAND_TYPE._imm && aoptyTable2 == ASM_OPERAND_TYPE._imm)
+			{
+				pc.IEVint1() = popnd1.disp;
+				pc.IFL1 = FL.FLconst;
+				pc.IEVint2() = popnd2.disp;
+				pc.IFL2 = FL.FLconst;
+				break;
+			}
+			if (aoptyTable2 == ASM_OPERAND_TYPE._m ||
+				aoptyTable2 == ASM_OPERAND_TYPE._rel ||
+				// If not MMX register (_mm) or XMM register (_xmm)
+				(amodTable1 == ASM_MODIFIERS._rspecial && !(uRegmaskTable1 & (0x08 | 0x10)) && !uSizemaskTable1) ||
+				aoptyTable2 == ASM_OPERAND_TYPE._rm ||
+				(popnd1.usFlags == _r32 && popnd2.usFlags == _xmm) ||
+				(popnd1.usFlags == _r32 && popnd2.usFlags == _mm))
+			{
+static if (false) {
+				printf("test4 %d,%d,%d,%d\n",
+				(aoptyTable2 == ASM_OPERAND_TYPE._m),
+				(aoptyTable2 == ASM_OPERAND_TYPE._rel),
+				(amodTable1 == ASM_MODIFIERS._rspecial && !(uRegmaskTable1 & (0x08 | 0x10))),
+				(aoptyTable2 == ASM_OPERAND_TYPE._rm)
+				);
+				printf("usOpcode = %x\n", usOpcode);
+}
+				if (ptb.pptb0.usOpcode == 0x0F7E ||	// MOVD _rm32,_mm
+					ptb.pptb0.usOpcode == 0x660F7E	// MOVD _rm32,_xmm
+				   )
+				{
+					asm_make_modrm_byte(
+///debug {
+					auchOpcode, &usIdx,
+///}
+					pc, 
+					ptb.pptb1.usFlags,
+					popnd1, popnd2);
+				}
+				else
+				{
+					asm_make_modrm_byte(
+///debug {
+					auchOpcode, &usIdx,
+///}
+					pc, 
+					ptb.pptb1.usFlags,
+					popnd2, popnd1);
+				}
+				popndTmp = popnd1;
+				aoptyTmp = aoptyTable1;
+				uSizemaskTmp = cast(ushort)uSizemaskTable1;
+			}
+			else
+			{
+				if (((aoptyTable1 == ASM_OPERAND_TYPE._reg || aoptyTable1 == ASM_OPERAND_TYPE._float) &&
+					 amodTable1 == ASM_MODIFIERS._normal &&
+					 (uRegmaskTable1 & _rplus_r)))
+				{
+					if (asmstate.ucItype == IT.ITfloat)
+						pc.Irm += popnd1.base.val;
+					else if (pc.Iop == 0x0f)
+						pc.Iop2 += popnd1.base.val;
+					else
+						pc.Iop += popnd1.base.val;
+debug {
+					auchOpcode[usIdx-1] += popnd1.base.val;
+}
+				}
+				else if (((aoptyTable2 == ASM_OPERAND_TYPE._reg || aoptyTable2 == ASM_OPERAND_TYPE._float) &&
+					 amodTable2 == ASM_MODIFIERS._normal &&
+					 (uRegmaskTable2 & _rplus_r)))
+				{
+					if (asmstate.ucItype == IT.ITfloat)
+						pc.Irm += popnd2.base.val;
+					else if (pc.Iop == 0x0f)
+						pc.Iop2 += popnd2.base.val;
+					else
+						pc.Iop += popnd2.base.val;
+debug {
+					auchOpcode[usIdx-1] += popnd2.base.val;
+}
+				}
+				else if (ptb.pptb0.usOpcode == 0xF30FD6 ||
+					 ptb.pptb0.usOpcode == 0x0F12 ||
+					 ptb.pptb0.usOpcode == 0x0F16 ||
+					 ptb.pptb0.usOpcode == 0x660F50 ||
+					 ptb.pptb0.usOpcode == 0x0F50 ||
+					 ptb.pptb0.usOpcode == 0x660FD7 ||
+					 ptb.pptb0.usOpcode == 0x0FD7)
+				{
+					asm_make_modrm_byte(
+///debug {
+						auchOpcode, &usIdx,
+///}
+						pc, 
+						ptb.pptb1.usFlags,
+						popnd2, popnd1);
+				}
+				else
+				{
+					asm_make_modrm_byte(
+///debug {
+						auchOpcode, &usIdx,
+///}
+						pc, 
+						ptb.pptb1.usFlags,
+						popnd1, popnd2);
+
+				}
+				if (aoptyTable1 == ASM_OPERAND_TYPE._imm)
+				{
+					popndTmp = popnd1;
+					aoptyTmp = aoptyTable1;
+					uSizemaskTmp = cast(ushort)uSizemaskTable1;
+				}
+				else
+				{
+					popndTmp = popnd2;
+					aoptyTmp = aoptyTable2;
+					uSizemaskTmp = cast(ushort)uSizemaskTable2;
+				}
+			}
+			goto L1;	
+
+		case 3:
+			if (aoptyTable2 == ASM_OPERAND_TYPE._m || aoptyTable2 == ASM_OPERAND_TYPE._rm ||
+				usOpcode == 0x0FC5) // PEXTRW
+			{
+				asm_make_modrm_byte(
+///debug {
+					auchOpcode, &usIdx,
+///}
+					pc, 
+					ptb.pptb1.usFlags,
+					popnd2, popnd1);
+				popndTmp = popnd3;
+				aoptyTmp = aoptyTable3;
+				uSizemaskTmp = cast(ushort)uSizemaskTable3;
+			} else {
+				if (((aoptyTable1 == ASM_OPERAND_TYPE._reg || aoptyTable1 == ASM_OPERAND_TYPE._float) &&
+					 amodTable1 == ASM_MODIFIERS._normal &&
+					 (uRegmaskTable1 &_rplus_r)))
+				{
+					if (asmstate.ucItype == IT.ITfloat)
+						pc.Irm += popnd1.base.val;
+					else if (pc.Iop == 0x0f)
+						pc.Iop2 += popnd1.base.val;
+					else
+						pc.Iop += popnd1.base.val;
+debug {
+					auchOpcode[usIdx-1] += popnd1.base.val;
+}
+				}
+				else if (((aoptyTable2 == ASM_OPERAND_TYPE._reg || aoptyTable2 == ASM_OPERAND_TYPE._float) &&
+					 amodTable2 == ASM_MODIFIERS._normal &&
+					 (uRegmaskTable2 &_rplus_r)))
+				{
+					if (asmstate.ucItype == IT.ITfloat)
+						pc.Irm += popnd1.base.val;
+					else if (pc.Iop == 0x0f)
+						pc.Iop2 += popnd1.base.val;
+					else
+						pc.Iop += popnd2.base.val;
+debug {
+					auchOpcode[usIdx-1] += popnd2.base.val;
+}
+				}
+				else
+					asm_make_modrm_byte(
+///debug {
+						auchOpcode, &usIdx,
+///}
+						pc, 
+						ptb.pptb1.usFlags,
+						popnd1, popnd2);
+
+				popndTmp = popnd3;
+				aoptyTmp = aoptyTable3;
+				uSizemaskTmp = cast(ushort)uSizemaskTable3;
+			}
+			goto L1;	
+	}
+L2:
+
+	if ((pc.Iop & 0xF8) == 0xD8 &&
+	    ADDFWAIT() &&
+	    !(ptb.pptb0.usFlags & _nfwait))
+		pc.Iflags |= CF.CFwait;
+	else if ((ptb.pptb0.usFlags & _fwait) &&
+	    config.target_cpu >= TARGET.TARGET_80386)
+		pc.Iflags |= CF.CFwait;
+
+debug {
+	if (debuga)
+	{   
+		uint u;
+
+	    for (u = 0; u < usIdx; u++) 
+			printf("  %02X", auchOpcode[u]);
+	
+	    printf("\t%s\t", asm_opstr(pop));
+	    if (popnd1)
+			asm_output_popnd(popnd1);
+	    if (popnd2) {
+			printf(",");
+			asm_output_popnd(popnd2);
+	    }
+	    if (popnd3) {
+			printf(",");
+			asm_output_popnd(popnd3);
+	    }
+	    printf("\n");
+	}
+}
+
+	pc = cat(pcPrefix, pc);
+	pc = asm_genloc(loc, pc);
+	return pc;
+}
+
+void asm_token_trans(Token* tok)
+{
+    tok_value = TOK.TOKeof;
+
+    if (tok)
+    {
+		tok_value = tok.value;
+		if (tok_value == TOK.TOKidentifier)
+		{   
+			string id = tok.ident.toChars();
+			size_t len = id.length;
+			if (len < 20)
+			{
+				ASMTK asmtk = cast(ASMTK) binary(toStringz(id), apszAsmtk.ptr, ASMTK.ASMTKmax);
+				if (cast(int)asmtk >= 0)
+					tok_value = cast(TOK)(asmtk + TOK.TOKMAX + 1);
+			}
+		}
+    }
+}
+
+void asm_token()
+{
+    if (asmtok)
+		asmtok = asmtok.next;
+
+    asm_token_trans(asmtok);
+}
+
+
+/**********************
+ * If c is a power of 2, return that power else -1.
+ */
+
+int ispow2(ulong c)
+{	
+	int i;
+
+	if (c == 0 || (c & (c - 1)))
+	    i = -1;
+	else
+	    for (i = 0; c >>= 1; i++) {
+			;
+		}
+
+	return i;
+}
+
+// Error numbers
+enum ASMERRMSGS
+{
+    EM_bad_float_op,
+    EM_bad_addr_mode,
+    EM_align,
+    EM_opcode_exp,
+    EM_prefix,
+    EM_eol,
+    EM_bad_operand,
+    EM_bad_integral_operand,
+    EM_ident_exp,
+    EM_not_struct,
+    EM_nops_expected,
+    EM_bad_op,
+    EM_const_init,
+    EM_undefined,
+    EM_pointer,
+    EM_colon,
+    EM_rbra,
+    EM_rpar,
+    EM_ptr_exp,
+    EM_num,
+    EM_float,
+    EM_char,
+    EM_label_expected,
+    EM_uplevel,
+    EM_type_as_operand,
+}
+
+mixin(BringToCurrentScope!(ASMERRMSGS));
+
+string[] asmerrmsgs =
+[
+    "unknown operand for floating point instruction",
+    "bad addr mode",
+    "align %d must be a power of 2",
+    "opcode expected, not %s",
+    "prefix",
+    "end of instruction",
+    "bad operand",
+    "bad integral operand",
+    "identifier expected",
+    "not struct",
+    "nops expected",
+    "bad type/size of operands '%s'",
+    "constant initializer expected",
+    "undefined identifier '%s'",
+    "pointer",
+    "colon",
+    "] expected instead of '%s'",
+    ") expected instead of '%s'",
+    "ptr expected",
+    "integer expected",
+    "floating point expected",
+    "character is truncated",
+    "label expected",
+    "uplevel nested reference to variable %s",
+    "cannot use type %s as an operand"
+];
+
+void asmerr(T...)(int errnum, T t)
+{   
+    string format = asmerrmsgs[errnum];
+	asmerr(format, t);
+}
+
+void asmerr(T...)(string format, T t)
+{
+    string p = asmstate.loc.toChars();
+	if (p.length != 0)
+		writef("%s: ", p);
+
+	writefln(format, t);
+
+    longjmp(asmstate.env,1);
+}
+
+PTRNTAB asm_classify(OP* pop, OPND* popnd1, OPND* popnd2, OPND* popnd3, uint* pusNumops)
+{
+	uint usNumops;
+	uint usActual;
+	PTRNTAB	ptbRet = { null };
+	opflag_t usFlags1 = 0 ;
+	opflag_t usFlags2 = 0;
+	opflag_t usFlags3 = 0;
+
+	PTRNTAB1 *pptb1; 
+	PTRNTAB2 *pptb2;
+	PTRNTAB3 *pptb3;
+
+	char bFake = false;
+	
+	ubyte bMatch1, bMatch2, bMatch3, bRetry = false;
+
+	// How many arguments are there?  the parser is strictly left to right
+	// so this should work.
+
+	if (!popnd1)
+	    usNumops = 0;
+	else
+	{
+	    popnd1.usFlags = usFlags1 = asm_determine_operand_flags(popnd1);
+	    if (!popnd2) 
+			usNumops = 1;
+	    else
+	    {
+			popnd2.usFlags = usFlags2 = asm_determine_operand_flags(popnd2);
+			if (!popnd3)
+				usNumops = 2;
+			else
+			{
+				popnd3.usFlags = usFlags3 = asm_determine_operand_flags(popnd3);
+				usNumops = 3;
+			}
+		}
+	}
+
+	// Now check to insure that the number of operands is correct
+	usActual = (pop.usNumops & IT.ITSIZE);
+	if (usActual != usNumops && asmstate.ucItype != IT.ITopt &&
+	    asmstate.ucItype != IT.ITfloat)
+	{
+PARAM_ERROR:
+		asmerr(ASMERRMSGS.EM_nops_expected, usActual, asm_opstr(pop), usNumops);
+	}
+	*pusNumops = usNumops;
+//
+//	The number of arguments matches, now check to find the opcode
+//	in the associated opcode table
+//
+RETRY:
+	//printf("usActual = %d\n", usActual);
+	switch (usActual)
+	{
+	    case 0:
+			ptbRet = pop.ptb ;
+			goto RETURN_IT;
+
+	    case 1:
+			//printf("usFlags1 = "); asm_output_flags(usFlags1); printf("\n");
+			for (pptb1 = pop.ptb.pptb1; pptb1.usOpcode != ASM_END;
+				pptb1++)
+			{
+				//printf("table    = "); asm_output_flags(pptb1.usOp1); printf("\n");
+				bMatch1 = asm_match_flags(usFlags1, pptb1.usOp1);
+				if (bMatch1)
+				{   if (pptb1.usOpcode == 0x68 &&
+					I32 &&
+					pptb1.usOp1 == _imm16
+					  )
+					// Don't match PUSH imm16 in 32 bit code
+					continue;
+					break;
+				}
+				if ((asmstate.ucItype == IT.ITimmed) &&
+					asm_match_flags(usFlags1,
+					CONSTRUCT_FLAGS(_8 | _16 | _32, ASM_OPERAND_TYPE._imm, ASM_MODIFIERS._normal,
+							 0)) &&
+					popnd1.disp == pptb1.usFlags)
+					break;
+				if ((asmstate.ucItype == IT.ITopt ||
+					 asmstate.ucItype == IT.ITfloat) &&
+					!usNumops &&
+					!pptb1.usOp1)
+				{
+					if (usNumops > 1)
+					goto PARAM_ERROR;
+					break;
+				}
+			}
+			if (pptb1.usOpcode == ASM_END)
+			{
+debug {
+				if (debuga)
+				{	
+					printf("\t%s\t", asm_opstr(pop));
+					if (popnd1)
+						asm_output_popnd(popnd1);
+					if (popnd2) {
+						printf(",");
+						asm_output_popnd(popnd2);
+					}
+					if (popnd3) {
+						printf(",");
+						asm_output_popnd(popnd3);
+					}
+					printf("\n");
+					
+					printf("OPCODE mism = ");
+					if (popnd1)
+						asm_output_flags(popnd1.usFlags);
+					else
+						printf("NONE");
+					printf("\n");
+				}
+}
+TYPE_SIZE_ERROR:
+				if (popnd1 && ASM_GET_aopty(popnd1.usFlags) != ASM_OPERAND_TYPE._reg)
+				{
+					usFlags1 = popnd1.usFlags |= _anysize;
+					if (asmstate.ucItype == IT.ITjump)
+					{
+						if (bRetry && popnd1.s && !popnd1.s.isLabel())
+						{
+							asmerr(ASMERRMSGS.EM_label_expected, popnd1.s.toChars());
+						}
+
+						popnd1.usFlags |= CONSTRUCT_FLAGS(0, 0, 0, _fanysize);
+					}
+				}	
+				if (popnd2 && ASM_GET_aopty(popnd2.usFlags) != ASM_OPERAND_TYPE._reg) {
+					usFlags2 = popnd2.usFlags |= (_anysize);
+					if (asmstate.ucItype == IT.ITjump)
+					popnd2.usFlags |= CONSTRUCT_FLAGS(0, 0, 0,
+						_fanysize);
+				}	
+				if (popnd3 && ASM_GET_aopty(popnd3.usFlags) != ASM_OPERAND_TYPE._reg) {
+					usFlags3 = popnd3.usFlags |= (_anysize);
+					if (asmstate.ucItype == IT.ITjump)
+					popnd3.usFlags |= CONSTRUCT_FLAGS(0, 0, 0,
+						_fanysize);
+				}
+				if (bRetry)
+				{
+					asmerr(ASMERRMSGS.EM_bad_op, fromStringz(asm_opstr(pop)));	// illegal type/size of operands
+				}
+				bRetry = true;
+				goto RETRY;
+			}
+			ptbRet.pptb1 = pptb1;
+			goto RETURN_IT;
+
+	    case 2:
+			//printf("usFlags1 = "); asm_output_flags(usFlags1); printf(" ");
+			//printf("usFlags2 = "); asm_output_flags(usFlags2); printf("\n");
+			for (pptb2 = pop.ptb.pptb2;
+				 pptb2.usOpcode != ASM_END;
+				 pptb2++)
+			{
+				//printf("table1   = "); asm_output_flags(pptb2.usOp1); printf(" ");
+				//printf("table2   = "); asm_output_flags(pptb2.usOp2); printf("\n");
+				bMatch1 = asm_match_flags(usFlags1, pptb2.usOp1);
+				bMatch2 = asm_match_flags(usFlags2, pptb2.usOp2);
+				//printf("match1 = %d, match2 = %d\n",bMatch1,bMatch2);
+				if (bMatch1 && bMatch2) {
+
+					//printf("match\n");
+
+					// OK, if they both match and the first op in the table is not AL 
+					// or size of 8 and the second is immediate 8,
+					// then check to see if the constant
+					// is a signed 8 bit constant.  If so, then do not match, otherwise match
+					//
+					if (!bRetry &&
+						!((ASM_GET_uSizemask(pptb2.usOp1) & _8) ||
+						  (ASM_GET_uRegmask(pptb2.usOp1) & _al)) &&
+						(ASM_GET_aopty(pptb2.usOp2) == ASM_OPERAND_TYPE._imm) &&
+						(ASM_GET_uSizemask(pptb2.usOp2) & _8))
+					{
+						if (popnd2.disp <= char.max)
+							break;
+						else
+							bFake = true;
+					}
+					else
+						break;
+				}
+				if (asmstate.ucItype == IT.ITopt || asmstate.ucItype == IT.ITfloat)
+				{
+					switch (usNumops)
+					{
+						case 0:
+							if (!pptb2.usOp1)
+								goto Lfound2;
+							break;
+						case 1:
+							if (bMatch1 && !pptb2.usOp2)
+								goto Lfound2;
+							break;
+						case 2:
+							break;
+						default:
+							goto PARAM_ERROR;
+					}
+				}
+static if (false) {
+				if (asmstate.ucItype == IT.ITshift &&
+					!pptb2.usOp2 &&
+					bMatch1 && popnd2.disp == 1 &&
+					asm_match_flags(usFlags2,
+					CONSTRUCT_FLAGS(_8|_16|_32, ASM_OPERAND_TYPE._imm,ASM_MODIFIERS._normal,0))
+				  )
+				{
+					break;
+				}
+}
+			}
+			Lfound2:
+			if (pptb2.usOpcode == ASM_END)
+			{
+debug {
+				if (debuga)
+				{	
+					printf("\t%s\t", asm_opstr(pop));
+					if (popnd1)
+						asm_output_popnd(popnd1);
+					if (popnd2) {
+						printf(",");
+						asm_output_popnd(popnd2);
+					}
+					if (popnd3) {
+						printf(",");
+						asm_output_popnd(popnd3);
+					}
+					printf("\n");
+					
+					printf("OPCODE mismatch = ");
+					if (popnd1)
+						asm_output_flags(popnd1.usFlags);
+					else
+						printf("NONE");
+					printf( " Op2 = ");
+					if (popnd2)
+						asm_output_flags(popnd2.usFlags);
+					else
+						printf("NONE");
+					printf("\n");
+				}
+}
+				goto TYPE_SIZE_ERROR;
+			}
+			ptbRet.pptb2 = pptb2;
+			goto RETURN_IT;
+
+		case 3:
+			for (pptb3 = pop.ptb.pptb3;
+				 pptb3.usOpcode != ASM_END;
+				 pptb3++)
+			{
+				bMatch1 = asm_match_flags(usFlags1, pptb3.usOp1);
+				bMatch2 = asm_match_flags(usFlags2, pptb3.usOp2);
+				bMatch3 = asm_match_flags(usFlags3, pptb3.usOp3);
+				if (bMatch1 && bMatch2 && bMatch3)
+					goto Lfound3;
+
+				if (asmstate.ucItype == IT.ITopt)
+				{
+					switch (usNumops)
+					{
+					case 0:
+						if (!pptb3.usOp1)
+							goto Lfound3;
+						break;
+					case 1:
+						if (bMatch1 && !pptb3.usOp2)
+							goto Lfound3;
+						break;
+					case 2:
+						if (bMatch1 && bMatch2 && !pptb3.usOp3)
+							goto Lfound3;
+						break;
+					case 3:
+						break;
+					default:
+						goto PARAM_ERROR;
+					}
+				}
+			}
+			Lfound3:
+			if (pptb3.usOpcode == ASM_END)
+			{
+debug {
+				if (debuga)
+				{	
+					printf("\t%s\t", asm_opstr(pop));
+					if (popnd1)
+						asm_output_popnd(popnd1);
+					if (popnd2) {
+						printf(",");
+						asm_output_popnd(popnd2);
+					}
+					if (popnd3) {
+						printf(",");
+						asm_output_popnd(popnd3);
+					}
+					printf("\n");
+					
+					printf("OPCODE mismatch = ");
+					if (popnd1)
+						asm_output_flags(popnd1.usFlags);
+					else
+						printf("NONE");
+					printf( " Op2 = ");
+					if (popnd2)
+						asm_output_flags(popnd2.usFlags);
+					else
+						printf("NONE");
+					if (popnd3)
+						asm_output_flags(popnd3.usFlags);
+					printf("\n");
+				}
+}
+				goto TYPE_SIZE_ERROR;
+			}
+
+			ptbRet.pptb3 = pptb3;
+			goto RETURN_IT;
+	}
+
+RETURN_IT:
+	if (bRetry && !bFake)
+	{
+	    asmerr(ASMERRMSGS.EM_bad_op, fromStringz(asm_opstr(pop)));
+	}
+	return ptbRet;
+}
+
+/*******************************
+ *	start of inline assemblers expression parser
+ *	NOTE: functions in call order instead of alphabetical
+ */
+
+/*******************************************
+ * Parse DA expression
+ *
+ * Very limited define address to place a code
+ * address in the assembly
+ * Problems:
+ *	o	Should use dw offset and dd offset instead,
+ *		for near/far support.
+ *	o	Should be able to add an offset to the label address.
+ *	o	Blocks addressed by DA should get their Bpred set correctly
+ *		for optimizer.
+ */
+
+code* asm_da_parse(OP* pop)
+{
+    code* clst = null;
+    elem* e;
+    
+    while (1)
+    {	
+		code* c;
+
+		if (tok_value == TOK.TOKidentifier)
+		{
+			LabelDsymbol label = asmstate.sc.func.searchLabel(asmtok.ident);
+			if (!label)
+				error(asmstate.loc, "label '%s' not found\n", asmtok.ident.toChars());
+
+			c = code_calloc();
+			c.Iop = ASM;
+			c.Iflags = CF.CFaddrsize;
+			c.IFL1 = FL.FLblockoff;
+			c.IEVlsym1() = label;
+			c = asm_genloc(asmstate.loc, c);
+			clst = cat(clst,c);
+		}
+		else
+			asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+
+		asm_token();
+		if (tok_value != TOK.TOKcomma)
+			break;
+
+		asm_token();
+    }
+    
+    asmstate.statement.regs |= mES | ALLREGS;
+    asmstate.bReturnax = true;
+
+    return clst;
+}
+
+/*******************************************
+ * Parse DB, DW, DD, DQ and DT expressions.
+ */
+
+code* asm_db_parse(OP* pop)
+{
+    uint usSize;
+    uint usMaxbytes;
+    uint usBytes;
+
+    union DT
+    {	
+		targ_ullong ul;
+		targ_float f;
+		targ_double d;
+		targ_ldouble ld;
+		char value[10];
+    }
+	
+	DT dt;
+
+    code* c;
+    uint op;
+    static ubyte[7] opsize = [ 1,2,4,8,4,8,10 ];
+
+    op = pop.usNumops & IT.ITSIZE;
+    usSize = opsize[op];
+
+    usBytes = 0;
+    usMaxbytes = 0;
+    c = code_calloc();
+    c.Iop = ASM;
+    
+    while (1)
+    {
+		size_t len;
+		ubyte* q;
+
+		if (usBytes+usSize > usMaxbytes)
+		{   
+			usMaxbytes = usBytes + usSize + 10;
+			c.IEV1.as.bytes = cast(char*)realloc(c.IEV1.as.bytes,usMaxbytes);
+		}
+		switch (tok_value)
+		{
+			case TOK.TOKint32v:
+				dt.ul = asmtok.int32value;
+				goto L1;
+			case TOK.TOKuns32v:
+				dt.ul = asmtok.uns32value;
+				goto L1;
+			case TOK.TOKint64v:
+				dt.ul = asmtok.int64value;
+				goto L1;
+			case TOK.TOKuns64v:
+				dt.ul = asmtok.uns64value;
+				goto L1;
+			L1:
+				switch (op)
+				{
+					case OP_DB.OPdb:
+					case OP_DB.OPds:
+					case OP_DB.OPdi:
+					case OP_DB.OPdl:
+						break;
+					default:
+						asmerr(ASMERRMSGS.EM_float);
+				}
+				goto L2;
+
+			case TOK.TOKfloat32v:
+			case TOK.TOKfloat64v:
+			case TOK.TOKfloat80v:
+				switch (op)
+				{
+					case OP_DB.OPdf:
+						dt.f = asmtok.float80value;
+						break;
+					case OP_DB.OPdd:
+						dt.d = asmtok.float80value;
+						break;
+					case OP_DB.OPde:
+						dt.ld = asmtok.float80value;
+						break;
+					default:
+						asmerr(ASMERRMSGS.EM_num);
+				}
+				goto L2;
+
+			L2:
+				memcpy(c.IEV1.as.bytes + usBytes,&dt,usSize);
+				usBytes += usSize;
+				break;
+
+			case TOK.TOKstring:
+				len = asmtok.len;
+				q = cast(ubyte*)asmtok.ustring;
+				L3:
+				if (len)
+				{
+					usMaxbytes += len * usSize;
+					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;
+					for (size_t i = 0; i < len; i++)
+					{
+						// Be careful that this works
+						memset(p, 0, usSize);
+						switch (op)
+						{
+							case OP_DB.OPdb:
+								*p = cast(ubyte)*q;
+								if (*p != *q)
+									asmerr(ASMERRMSGS.EM_char);
+								break;
+
+							case OP_DB.OPds:
+								*cast(short*)p = *cast(ubyte*)q;
+								if (*cast(short*)p != *q)
+									asmerr(ASMERRMSGS.EM_char);
+								break;
+
+							case OP_DB.OPdi:
+							case OP_DB.OPdl:
+								*cast(int*)p = *q;
+								break;
+
+							default:
+								asmerr(ASMERRMSGS.EM_float);
+						}
+						q++;
+						p += usSize;
+					}
+
+					usBytes += len * usSize;
+				}
+				break;
+
+			case TOK.TOKidentifier:
+			{
+				Expression e = new IdentifierExp(asmstate.loc, asmtok.ident);
+				e = e.semantic(asmstate.sc);
+				e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+				if (e.op == TOK.TOKint64)
+				{   
+					dt.ul = e.toInteger();
+					goto L2;
+				}
+				else if (e.op == TOK.TOKfloat64)
+				{
+					switch (op)
+					{
+					case OP_DB.OPdf:
+						dt.f = e.toReal();
+						break;
+					case OP_DB.OPdd:
+						dt.d = e.toReal();
+						break;
+					case OP_DB.OPde:
+						dt.ld = e.toReal();
+						break;
+					default:
+						asmerr(ASMERRMSGS.EM_num);
+					}
+					goto L2;
+				}
+				else if (e.op == TOK.TOKstring)
+				{   
+					StringExp se = cast(StringExp)e;
+					q = cast(ubyte*)se.string_;
+					len = se.len;
+					goto L3;
+				}
+				goto Ldefault;
+			}
+
+			default:
+				Ldefault:
+				asmerr(ASMERRMSGS.EM_const_init);		// constant initializer
+				break;
+		}
+		c.IEV1.as.len = usBytes;
+
+		asm_token();
+		if (tok_value != TOK.TOKcomma)
+			break;
+
+		asm_token();
+    }
+
+    c = asm_genloc(asmstate.loc, c);
+
+    asmstate.statement.regs |= /* mES| */ ALLREGS;
+    asmstate.bReturnax = true;
+
+    return c;
+}
+
+/**********************************
+ * Parse and get integer expression.
+ */
+
+int asm_getnum()
+{   
+	int v;
+    long i;
+
+    switch (tok_value)
+    {
+		case TOK.TOKint32v:
+			v = asmtok.int32value;
+			break;
+
+		case TOK.TOKuns32v:
+			v = asmtok.uns32value;
+			break;
+
+		case TOK.TOKidentifier:
+			Expression e = new IdentifierExp(asmstate.loc, asmtok.ident);
+			e = e.semantic(asmstate.sc);
+			e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			i = e.toInteger();
+			v = cast(int) i;
+			if (v != i)
+				asmerr(ASMERRMSGS.EM_num);
+			break;
+
+		default:
+			asmerr(ASMERRMSGS.EM_num);
+			break;
+    }
+
+    asm_token();
+
+    return v;
+}
+
+
+/*******************************
+ */
+
+OPND* asm_cond_exp()
+{
+    OPND* o1;
+	OPND* o2;
+	OPND* o3;
+
+    //printf("asm_cond_exp()\n");
+    o1 = asm_log_or_exp();
+    if (tok_value == TOK.TOKquestion)
+    {
+		asm_token();
+		o2 = asm_cond_exp();
+		asm_token();
+		asm_chktok(TOK.TOKcolon, ASMERRMSGS.EM_colon);
+		o3 = asm_cond_exp();
+		o1 = (o1.disp) ? o2 : o3;
+    }
+
+    return o1;
+}
+
+regm_t asm_modify_regs(PTRNTAB ptb, OPND* popnd1, OPND* popnd2)
+{
+    regm_t usRet = 0;
+    
+    switch (ptb.pptb0.usFlags & MOD_MASK) {
+		case _modsi:
+			usRet |= mSI;
+			break;
+		case _moddx:
+			usRet |= mDX;
+			break;
+		case _mod2:
+			if (popnd2)
+				usRet |= asm_modify_regs(ptb, popnd2, null);
+			break;
+		case _modax:
+			usRet |= mAX;
+			break;
+		case _modnot1:
+			popnd1 = null;
+			break;
+		case _modaxdx:
+			usRet |= (mAX | mDX);
+			break;
+		case _moddi:
+			usRet |= mDI;
+			break;
+		case _modsidi:
+			usRet |= (mSI | mDI);
+			break;
+		case _modcx:
+			usRet |= mCX;
+			break;
+		case _modes:
+			/*usRet |= mES;*/
+			break;
+		case _modall:
+			asmstate.bReturnax = true;
+			return /*mES |*/ ALLREGS;
+		case _modsiax:
+			usRet |= (mSI | mAX);
+			break;
+		case _modsinot1:
+			usRet |= mSI;
+			popnd1 = null;
+			break;
+		default:
+			break;	///
+    }
+    if (popnd1 && ASM_GET_aopty(popnd1.usFlags) == ASM_OPERAND_TYPE._reg) {
+		switch (ASM_GET_amod(popnd1.usFlags)) {
+			default:
+				if (ASM_GET_uSizemask(popnd1.usFlags) == _8) {
+					switch(popnd1.base.val) {
+						case _AL:
+						case _AH:
+							usRet |= mAX;
+							break;
+						case _BL:
+						case _BH:
+							usRet |= mBX;
+							break;
+						case _CL:
+						case _CH:
+							usRet |= mCX;
+							break;
+						case _DL:
+						case _DH:
+							usRet |= mDX;
+							break;
+					}
+				}
+				else {
+					switch (popnd1.base.val) {
+						case _AX:
+							usRet |= mAX;
+							break;
+						case _BX:
+							usRet |= mBX;
+							break;
+						case _CX:
+							usRet |= mCX;
+							break;
+						case _DX:
+							usRet |= mDX;
+							break;
+						case _SI:
+							usRet |= mSI;
+							break;
+						case _DI:
+							usRet |= mDI;
+							break;
+						default:
+							break;	///
+					}
+				}
+				break;
+
+			case ASM_MODIFIERS._rseg:
+				//if (popnd1.base.val == _ES)
+				//usRet |= mES;
+				break;
+			
+			case ASM_MODIFIERS._rspecial:
+				break;
+		}
+    }
+    if (usRet & mAX)
+		asmstate.bReturnax = true;
+    
+    return usRet;
+}
+
+
+/****************************
+ * Fill in the modregrm and sib bytes of code.
+ */
+ 
+uint X(ubyte r1, ubyte r2) {
+	return (((r1) * 16) + (r2));
+}
+
+uint Y(ubyte r1) {
+	return X(r1, 9);
+}
+
+void asm_make_modrm_byte(
+///debug {
+	ubyte[] puchOpcode, uint* pusIdx,
+///}
+	code *pc,
+	ushort usFlags,
+	OPND *popnd, OPND *popnd2)
+{
+///    #undef modregrm
+
+    union MODRM_BYTE			// mrmb
+	{
+		struct MODRM
+		{
+			mixin(bitfields!(
+				uint, "rm",    	3,
+				uint, "reg",   	3,
+				uint, "mod",   	2));
+		}
+		
+		ubyte uchOpcode;
+		MODRM modregrm;
+    }
+
+    union SIB_BYTE
+	{
+		struct SIB
+		{
+			
+			mixin(bitfields!(
+				uint, "base",	3,
+				uint, "index",	3,
+				uint, "ss",		2));
+		}
+		
+		ubyte uchOpcode;
+		SIB sib;
+    }
+	
+
+    MODRM_BYTE	mrmb;
+    SIB_BYTE	sib;
+    char		bSib = false;
+    char		bDisp = false;
+    char		b32bit = false;
+    ubyte* 		puc;
+    char		bModset = false;
+    Dsymbol		s;
+    
+    uint uSizemask = 0;
+    ASM_OPERAND_TYPE    aopty;
+    ASM_MODIFIERS	    amod;
+    ushort uRegmask;
+    ubyte bOffsetsym = false;
+
+static if (false) {
+    printf("asm_make_modrm_byte(usFlags = x%x)\n", usFlags);
+    printf("op1: ");
+    asm_output_flags(popnd.usFlags);
+    if (popnd2)
+    {	
+		printf(" op2: ");
+		asm_output_flags(popnd2.usFlags);
+    }
+    printf("\n");
+}
+
+    uSizemask = ASM_GET_uSizemask(popnd.usFlags);
+    aopty = ASM_GET_aopty(popnd.usFlags);
+    amod = ASM_GET_amod(popnd.usFlags);
+    uRegmask = ASM_GET_uRegmask(popnd.usFlags);
+    s = popnd.s;
+    if (s)
+    {
+		Declaration d = s.isDeclaration();
+
+		if (amod == ASM_MODIFIERS._fn16 && aopty == ASM_OPERAND_TYPE._rel && popnd2)
+		{   
+			aopty = ASM_OPERAND_TYPE._m;
+			goto L1;
+		}
+
+		if (amod == ASM_MODIFIERS._fn16 || amod == ASM_MODIFIERS._fn32)
+		{
+			pc.Iflags |= CF.CFoff;
+debug {
+			puchOpcode[(*pusIdx)++] = 0;
+			puchOpcode[(*pusIdx)++] = 0;
+}
+			if (aopty == ASM_OPERAND_TYPE._m || aopty == ASM_OPERAND_TYPE._mnoi)
+			{
+				pc.IFL1 = FL.FLdata;
+				pc.IEVdsym1() = d;
+				pc.IEVoffset1() = 0;
+			}
+			else
+			{
+				if (aopty == ASM_OPERAND_TYPE._p)
+					pc.Iflags |= CF.CFseg;
+				
+				debug if (aopty == ASM_OPERAND_TYPE._p || aopty == ASM_OPERAND_TYPE._rel)
+				{   
+					puchOpcode[(*pusIdx)++] = 0;
+					puchOpcode[(*pusIdx)++] = 0;
+				}
+
+				pc.IFL2 = FL.FLfunc;
+				pc.IEVdsym2() = d;
+				pc.IEVoffset2() = 0;
+				//return;
+			}
+		}
+		else
+		{
+		  L1:
+			LabelDsymbol label = s.isLabel();
+			if (label)
+			{
+				if (s == asmstate.psDollar)
+				{
+					pc.IFL1 = FL.FLconst;
+					if (uSizemask & (_8 | _16))
+						pc.IEVint1() = popnd.disp;
+					else if (uSizemask & _32)
+						pc.IEVpointer1() = cast(targ_size_t) popnd.disp;
+				}
+				else
+				{   
+					pc.IFL1 = FL.FLblockoff;
+					pc.IEVlsym1() = label;
+				}
+			}
+			else if (s == asmstate.psLocalsize)
+			{
+				pc.IFL1 = FL.FLlocalsize;
+				pc.IEVdsym1() = null;
+				pc.Iflags |= CF.CFoff;
+				pc.IEVoffset1() = popnd.disp;
+			}
+			else if (s.isFuncDeclaration())
+			{
+				pc.IFL1 = FL.FLfunc;
+				pc.IEVdsym1() = d;
+				pc.IEVoffset1() = popnd.disp;
+			}
+			else
+			{
+				debug if (debuga)
+					printf("Setting up symbol %s\n", d.ident.toChars());
+
+				pc.IFL1 = FL.FLdsymbol;
+				pc.IEVdsym1() = d;
+				pc.Iflags |= CF.CFoff;
+				pc.IEVoffset1() = popnd.disp;
+			}
+		}
+    }
+
+    mrmb.modregrm.reg = usFlags & NUM_MASK;
+
+    if (s && (aopty == ASM_OPERAND_TYPE._m || aopty == ASM_OPERAND_TYPE._mnoi) && !s.isLabel())
+    {
+		if (s == asmstate.psLocalsize)
+		{
+		DATA_REF:
+			mrmb.modregrm.rm = BPRM;
+			if (amod == ASM_MODIFIERS._addr16 || amod == ASM_MODIFIERS._addr32)
+				mrmb.modregrm.mod = 0x2;
+			else
+				mrmb.modregrm.mod = 0x0;
+		}
+		else
+		{
+			Declaration d = s.isDeclaration();
+			assert(d);
+			if (d.isDataseg() || d.isCodeseg())
+			{
+				if (( I32 && amod == ASM_MODIFIERS._addr16) ||
+					(!I32 && amod == ASM_MODIFIERS._addr32))
+					asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+				goto DATA_REF;
+			}
+			mrmb.modregrm.rm = BPRM;
+			mrmb.modregrm.mod = 0x2;
+		}
+    }
+    
+    if (aopty == ASM_OPERAND_TYPE._reg || amod == ASM_MODIFIERS._rspecial) {
+	    mrmb.modregrm.mod = 0x3;
+	    mrmb.modregrm.rm = mrmb.modregrm.rm | popnd.base.val;
+    }
+    else if (amod == ASM_MODIFIERS._addr16 || (amod == ASM_MODIFIERS._flbl && !I32))
+    {   
+		uint rm;
+
+		debug if (debuga)
+			printf("This is an ADDR16\n");
+
+		if (!popnd.pregDisp1)
+		{   rm = 0x6;
+			if (!s)
+			bDisp = true;
+		}
+		else
+		{   
+			uint r1r2;
+
+			if (popnd.pregDisp2)
+				r1r2 = X(popnd.pregDisp1.val,popnd.pregDisp2.val);
+			else
+				r1r2 = Y(popnd.pregDisp1.val);
+
+			switch (r1r2)
+			{
+				case X(_BX,_SI):	rm = 0;	break;
+				case X(_BX,_DI):	rm = 1;	break;
+				case Y(_BX):		rm = 7;	break;
+
+				case X(_BP,_SI):	rm = 2;	break;
+				case X(_BP,_DI):	rm = 3;	break;
+				case Y(_BP):		rm = 6;	bDisp = true;	break;
+
+				case X(_SI,_BX):	rm = 0;	break;
+				case X(_SI,_BP):	rm = 2;	break;
+				case Y(_SI):		rm = 4;	break;
+
+				case X(_DI,_BX):	rm = 1;	break;
+				case X(_DI,_BP):	rm = 3;	break;
+				case Y(_DI):		rm = 5;	break;
+
+				default:
+					asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+			}
+		}
+		mrmb.modregrm.rm = rm;
+
+		debug if (debuga)
+			printf("This is an mod = %d, popnd.s =%ld, popnd.disp = %ld\n",
+			   mrmb.modregrm.mod, s, popnd.disp);
+
+		if (!s || (!mrmb.modregrm.mod && popnd.disp))
+		{
+			if ((!popnd.disp && !bDisp) || !popnd.pregDisp1)
+				mrmb.modregrm.mod = 0x0;
+			else if (popnd.disp >= CHAR_MIN && popnd.disp <= SCHAR_MAX)
+				mrmb.modregrm.mod = 0x1;
+			else
+				mrmb.modregrm.mod = 0X2;
+		}
+		else
+			bOffsetsym = true;
+	    
+    }
+    else if (amod == ASM_MODIFIERS._addr32 || (amod == ASM_MODIFIERS._flbl && I32))
+    {
+		debug if (debuga)
+			printf("This is an ADDR32\n");
+
+		if (!popnd.pregDisp1)
+			mrmb.modregrm.rm = 0x5;
+		else if (popnd.pregDisp2 || 
+			 popnd.uchMultiplier ||
+			 popnd.pregDisp1.val == _ESP)
+		{
+			if (popnd.pregDisp2)
+			{   
+				if (popnd.pregDisp2.val == _ESP)
+					asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+			}
+			else
+			{   
+				if (popnd.uchMultiplier && popnd.pregDisp1.val ==_ESP)
+					asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+				bDisp = true;
+			}
+			
+			mrmb.modregrm.rm = 0x4;
+			bSib = true;
+			if (bDisp)
+			{
+				if (!popnd.uchMultiplier &&
+					popnd.pregDisp1.val==_ESP)
+				{
+					sib.sib.base = popnd.pregDisp1.val;
+					sib.sib.index = 0x4;
+				}
+				else
+				{
+					debug if (debuga)
+						printf("Resetting the mod to 0\n");
+		
+					if (popnd.pregDisp2)
+					{
+						if (popnd.pregDisp2.val != _EBP)
+							asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+					}
+					else
+					{   
+						mrmb.modregrm.mod = 0x0;
+						bModset = true;
+					}
+					
+					sib.sib.base = 0x5;
+					sib.sib.index = popnd.pregDisp1.val;
+				}
+			}
+			else
+			{
+				sib.sib.base = popnd.pregDisp1.val;
+				//
+				// This is to handle the special case
+				// of using the EBP register and no
+				// displacement.  You must put in an
+				// 8 byte displacement in order to
+				// get the correct opcodes.
+				//
+				if (popnd.pregDisp1.val == _EBP && (!popnd.disp && !s))
+				{
+					debug if (debuga)
+						printf("Setting the mod to 1 in the _EBP case\n");
+
+					mrmb.modregrm.mod = 0x1;
+					bDisp = true;   // Need a
+									// displacement
+					bModset = true;
+				}
+					
+				sib.sib.index = popnd.pregDisp2.val;
+			}
+			switch (popnd.uchMultiplier)
+			{
+				case 0:	sib.sib.ss = 0;	break;
+				case 1:	sib.sib.ss = 0;	break;
+				case 2:	sib.sib.ss = 1;	break;
+				case 4:	sib.sib.ss = 2;	break;
+				case 8:	sib.sib.ss = 3;	break;
+
+				default:
+					asmerr(ASMERRMSGS.EM_bad_addr_mode);		// illegal addressing mode
+					break;
+			}
+			if (bDisp && sib.sib.base == 0x5)
+				b32bit = true;
+		}
+		else
+		{   
+			uint rm;
+
+			if (popnd.uchMultiplier)
+				asmerr(ASMERRMSGS.EM_bad_addr_mode);		// illegal addressing mode
+			switch (popnd.pregDisp1.val)
+			{
+				case _EAX:	rm = 0;	break;
+				case _ECX:	rm = 1;	break;
+				case _EDX:	rm = 2;	break;
+				case _EBX:	rm = 3;	break;
+				case _ESI:	rm = 6;	break;
+				case _EDI:	rm = 7;	break;
+
+				case _EBP:
+					if (!popnd.disp && !s)
+					{
+						mrmb.modregrm.mod = 0x1;
+						bDisp = true;   // Need a displacement
+						bModset = true;
+					}
+					rm = 5;
+					break;
+
+				default:
+					asmerr(ASMERRMSGS.EM_bad_addr_mode);	// illegal addressing mode
+					break;
+			}
+			mrmb.modregrm.rm = rm;
+		}
+		if (!bModset && (!s || (!mrmb.modregrm.mod && popnd.disp)))
+		{
+			if ((!popnd.disp && !mrmb.modregrm.mod) ||
+				(!popnd.pregDisp1 && !popnd.pregDisp2))
+			{
+				mrmb.modregrm.mod = 0x0;
+				bDisp = true;
+			}
+			else if (popnd.disp >= CHAR_MIN && popnd.disp <= SCHAR_MAX)
+				mrmb.modregrm.mod = 0x1;
+			else
+				mrmb.modregrm.mod = 0x2;
+		}
+		else
+			bOffsetsym = true;
+    }
+    if (popnd2 && !mrmb.modregrm.reg &&
+		asmstate.ucItype != IT.ITshift &&
+		(ASM_GET_aopty(popnd2.usFlags) == ASM_OPERAND_TYPE._reg  ||
+		ASM_GET_amod(popnd2.usFlags) == ASM_MODIFIERS._rseg ||
+		ASM_GET_amod(popnd2.usFlags) == ASM_MODIFIERS._rspecial))
+    {
+	    mrmb.modregrm.reg =  popnd2.base.val;
+    }
+	debug puchOpcode[ (*pusIdx)++ ] = mrmb.uchOpcode;
+
+    pc.Irm = mrmb.uchOpcode;
+    //printf("Irm = %02x\n", pc.Irm);
+    if (bSib)
+    {
+		debug puchOpcode[ (*pusIdx)++ ] = sib.uchOpcode;
+	    pc.Isib= sib.uchOpcode;
+    }
+    if ((!s || (popnd.pregDisp1 && !bOffsetsym)) &&
+		aopty != ASM_OPERAND_TYPE._imm &&
+		(popnd.disp || bDisp))
+    {
+	    if (popnd.usFlags & _a16)
+	    {
+			debug {
+				puc = (cast(ubyte*) &(popnd.disp));
+				puchOpcode[(*pusIdx)++] = puc[1];
+				puchOpcode[(*pusIdx)++] = puc[0];
+			}
+		    if (usFlags & (_modrm | NUM_MASK)) {
+				debug if (debuga)
+					printf("Setting up value %ld\n", popnd.disp);
+
+				pc.IEVint1() = popnd.disp;
+				pc.IFL1 = FL.FLconst;
+		    }
+		    else {
+				pc.IEVint2() = popnd.disp;
+				pc.IFL2 = FL.FLconst;
+		    }
+			    
+	    }
+	    else
+	    {
+			debug {
+				puc = (cast(ubyte*) &(popnd.disp));
+				puchOpcode[(*pusIdx)++] = puc[3];
+				puchOpcode[(*pusIdx)++] = puc[2];
+				puchOpcode[(*pusIdx)++] = puc[1];
+				puchOpcode[(*pusIdx)++] = puc[0];
+			}
+		    if (usFlags & (_modrm | NUM_MASK)) {
+				debug if (debuga)
+					printf("Setting up value %ld\n", popnd.disp);
+
+			    pc.IEVpointer1() = cast(targ_size_t) popnd.disp;
+			    pc.IFL1 = FL.FLconst;
+		    } else {
+			    pc.IEVpointer2() = cast(targ_size_t) popnd.disp;
+			    pc.IFL2 = FL.FLconst;
+		    }
+	    }
+    }
+}
+
+void asm_output_popnd(OPND* popnd)
+{
+	if (popnd.segreg)
+		printf("%s:", popnd.segreg.regstr);
+	
+	if (popnd.s)
+		writef("%s", popnd.s.ident.toChars());
+	
+	if (popnd.base)
+		printf("%s", popnd.base.regstr);
+
+	if (popnd.pregDisp1) {
+		if (popnd.pregDisp2) {
+			if (popnd.usFlags & _a32)
+				if (popnd.uchMultiplier)
+					printf("[%s][%s*%d]",
+						popnd.pregDisp1.regstr,
+						popnd.pregDisp2.regstr,
+						popnd.uchMultiplier);
+				else
+					printf("[%s][%s]",
+						popnd.pregDisp1.regstr,
+						popnd.pregDisp2.regstr);
+			else
+				printf("[%s+%s]",
+					popnd.pregDisp1.regstr,
+					popnd.pregDisp2.regstr);
+		}
+		else {
+			if (popnd.uchMultiplier)
+				printf("[%s*%d]",
+					popnd.pregDisp1.regstr,
+					popnd.uchMultiplier);
+			else
+				printf("[%s]",
+					popnd.pregDisp1.regstr);
+		}
+	}
+	if (ASM_GET_aopty(popnd.usFlags) == ASM_OPERAND_TYPE._imm)
+		printf("%lxh", popnd.disp);
+	else if (popnd.disp)
+		printf("+%lxh", popnd.disp);
+}
+
+/*******************************
+ * Prepend line number to c.
+ */
+
+code* asm_genloc(Loc loc, code* c)
+{
+    if (global.params.symdebug)
+    {   
+		code* pcLin;
+		Srcpos srcpos;
+
+		srcpos.Slinnum = loc.linnum;
+		srcpos.Sfilename = cast(char*)toStringz(loc.filename);
+		pcLin = genlinnum(null, srcpos);
+
+		c = cat(pcLin, c);
+    }
+
+    return c;
+}
+
+opflag_t asm_determine_operand_flags(OPND* popnd)
+{
+	Dsymbol ps;
+	int ty;
+	opflag_t us;
+	opflag_t sz;
+	ASM_OPERAND_TYPE opty;
+	ASM_MODIFIERS amod;
+
+	// If specified 'offset' or 'segment' but no symbol
+	if ((popnd.bOffset || popnd.bSeg) && !popnd.s)
+	    asmerr(ASMERRMSGS.EM_bad_addr_mode);		// illegal addressing mode
+	    
+	if (asmstate.ucItype == IT.ITfloat)
+	    return asm_determine_float_flags(popnd);
+
+	// If just a register	
+	if (popnd.base && !popnd.s && !popnd.disp && !popnd.real_)
+		return popnd.base.ty;
+
+	debug if (debuga)
+	    printf("popnd.base = %s\n, popnd.pregDisp1 = %ld\n", popnd.base ? popnd.base.regstr : "NONE", popnd.pregDisp1);
+
+	ps = popnd.s;
+	Declaration ds = ps ? ps.isDeclaration() : null;
+	if (ds && ds.storage_class & STC.STClazy)
+	    sz = _anysize;
+	else
+	    sz = cast(ushort)asm_type_size((ds && ds.storage_class & (STC.STCout | STC.STCref)) ? popnd.ptype.pointerTo() : popnd.ptype);
+	if (popnd.pregDisp1 && !popnd.base)
+	{
+	    if (ps && ps.isLabel() && sz == _anysize)
+			sz = I32 ? _32 : _16;
+	    return (popnd.pregDisp1.ty & _r32)
+			? CONSTRUCT_FLAGS(sz, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._addr32, 0)
+			: CONSTRUCT_FLAGS(sz, ASM_OPERAND_TYPE._m, ASM_MODIFIERS._addr16, 0);
+	}
+	else if (ps)
+	{
+		if (popnd.bOffset || popnd.bSeg || ps == asmstate.psLocalsize)
+		    return I32
+			? CONSTRUCT_FLAGS(_32, ASM_OPERAND_TYPE._imm, ASM_MODIFIERS._normal, 0)
+			: CONSTRUCT_FLAGS(_16, ASM_OPERAND_TYPE._imm, ASM_MODIFIERS._normal, 0);
+		
+		if (ps.isLabel())
+		{
+		    switch (popnd.ajt)
+		    {
+				case ASM_JUMPTYPE.ASM_JUMPTYPE_UNSPECIFIED:
+					if (ps == asmstate.psDollar)
+					{
+						if (popnd.disp >= CHAR_MIN &&
+							popnd.disp <= CHAR_MAX)
+							us = CONSTRUCT_FLAGS(_8, _rel, ASM_MODIFIERS._flbl,0);
+						else
+						if (popnd.disp >= SHRT_MIN &&
+							popnd.disp <= SHRT_MIN)
+							us = CONSTRUCT_FLAGS(_16, _rel, ASM_MODIFIERS._flbl,0);
+						else
+							us = CONSTRUCT_FLAGS(_32, _rel, ASM_MODIFIERS._flbl,0);
+					}
+					else if (asmstate.ucItype != ITjump)
+					{	
+						if (sz == _8)
+						{   us = CONSTRUCT_FLAGS(_8,ASM_OPERAND_TYPE._rel,ASM_MODIFIERS._flbl,0);
+							break;
+						}
+						goto case_near;
+					}
+					else
+						us = I32
+						? CONSTRUCT_FLAGS(_8|_32, ASM_OPERAND_TYPE._rel, ASM_MODIFIERS._flbl, 0)
+						: CONSTRUCT_FLAGS(_8|_16, ASM_OPERAND_TYPE._rel, ASM_MODIFIERS._flbl, 0);
+					break;
+					
+				case ASM_JUMPTYPE.ASM_JUMPTYPE_NEAR:
+				case_near:
+					us = I32
+					? CONSTRUCT_FLAGS(_32, _rel, _flbl, 0)
+					: CONSTRUCT_FLAGS(_16, _rel, _flbl, 0);
+					break;
+				case ASM_JUMPTYPE.ASM_JUMPTYPE_SHORT:
+					us = CONSTRUCT_FLAGS(_8, _rel, _flbl, 0);
+					break;
+				case ASM_JUMPTYPE.ASM_JUMPTYPE_FAR:
+					us = I32
+					? CONSTRUCT_FLAGS(_48, _rel, _flbl, 0)
+					: CONSTRUCT_FLAGS(_32, _rel, _flbl, 0);
+					break;
+				default:
+					assert(0);
+		    }
+		    return us;
+		}
+		if (!popnd.ptype)
+		    return CONSTRUCT_FLAGS(sz, _m, _normal, 0);
+		ty = popnd.ptype.ty;
+		if (ty == Tpointer && popnd.ptype.nextOf().ty == Tfunction &&
+		    !ps.isVarDeclaration())
+		{
+static if (true) {
+		    return CONSTRUCT_FLAGS(_32, _m, _fn16, 0);
+} else {
+		    ty = popnd.ptype.Tnext.Tty;
+		    if (tyfarfunc(tybasic(ty))) {
+			return I32
+			    ? CONSTRUCT_FLAGS(_48, _mnoi, _fn32, 0)
+			    : CONSTRUCT_FLAGS(_32, _mnoi, _fn32, 0);
+		    }
+		    else {
+			return I32
+			    ? CONSTRUCT_FLAGS(_32, _m, _fn16, 0)
+			    : CONSTRUCT_FLAGS(_16, _m, _fn16, 0);
+		    }
+}
+		}
+		else if (ty == TY.Tfunction)
+		{
+static if (true) {
+		    return CONSTRUCT_FLAGS(_32, _rel, _fn16, 0);
+} else {
+		    if (tyfarfunc(tybasic(ty)))
+			return I32
+			    ? CONSTRUCT_FLAGS(_48, _p, _fn32, 0)
+			    : CONSTRUCT_FLAGS(_32, _p, _fn32, 0);
+		    else
+			return I32
+			    ? CONSTRUCT_FLAGS(_32, _rel, _fn16, 0)
+			    : CONSTRUCT_FLAGS(_16, _rel, _fn16, 0);
+}
+		}
+		else if (asmstate.ucItype == IT.ITjump)
+		{   
+			amod = _normal;
+		    goto L1;
+		}
+		else
+		    return CONSTRUCT_FLAGS(sz, _m, _normal, 0);
+	}
+	if (popnd.segreg /*|| popnd.bPtr*/)
+	{
+	    amod = I32 ? _addr32 : _addr16;
+	    if (asmstate.ucItype == ITjump)
+	    {
+			L1:
+			opty = _m;
+			if (I32)
+			{   if (sz == _48)
+				opty = _mnoi;
+			}
+			else
+			{
+				if (sz == _32)
+				opty = _mnoi;
+			}
+			us = CONSTRUCT_FLAGS(sz,opty,amod,0);
+	    }
+	    else
+			us = CONSTRUCT_FLAGS(sz, 
+//				     _rel, amod, 0);
+				     _m, amod, 0);
+	}
+
+	else if (popnd.ptype)
+	    us = CONSTRUCT_FLAGS(sz, _imm, _normal, 0);
+
+	else if (popnd.disp >= CHAR_MIN && popnd.disp <= UCHAR_MAX)
+	    us = CONSTRUCT_FLAGS(_8 | _16 | _32, _imm, _normal, 0);
+	else if (popnd.disp >= SHRT_MIN && popnd.disp <= USHRT_MAX)
+	    us = CONSTRUCT_FLAGS(_16 | _32, _imm, _normal, 0);
+	else
+	    us = CONSTRUCT_FLAGS(_32, _imm, _normal, 0);
+	return us;
+}
+
+/*******************************
+ * Match flags in operand against flags in opcode table.
+ * Returns:
+ *	!=0 if match
+ */
+
+ubyte asm_match_flags(opflag_t usOp, opflag_t usTable)
+{
+    ASM_OPERAND_TYPE	aoptyTable;
+    ASM_OPERAND_TYPE	aoptyOp;
+    ASM_MODIFIERS	amodTable;
+    ASM_MODIFIERS	amodOp;
+    uint uRegmaskTable;
+    uint uRegmaskOp;
+    ubyte bRegmatch;
+    ubyte bRetval = false;
+    uint uSizemaskOp;
+    uint uSizemaskTable;
+    ubyte bSizematch;
+
+    //printf("asm_match_flags(usOp = x%x, usTable = x%x)\n", usOp, usTable);
+    if (asmstate.ucItype == IT.ITfloat)
+    {
+		bRetval = asm_match_float_flags(usOp, usTable);
+		goto EXIT;
+    }
+
+    uSizemaskOp = ASM_GET_uSizemask(usOp);
+    uSizemaskTable = ASM_GET_uSizemask(usTable);
+
+    // Check #1, if the sizes do not match, NO match
+    bSizematch = (uSizemaskOp & uSizemaskTable) != 0;
+
+    amodOp = ASM_GET_amod(usOp);
+    
+    aoptyTable = ASM_GET_aopty(usTable);
+    aoptyOp = ASM_GET_aopty(usOp);
+
+    // _mmm64 matches with a 64 bit mem or an MMX register
+    if (usTable == _mmm64)
+    {
+		if (usOp == _mm)
+			goto Lmatch;
+		if (aoptyOp == _m && (bSizematch || uSizemaskOp == _anysize))
+			goto Lmatch;
+		goto EXIT;
+    }
+
+    // _xmm_m32, _xmm_m64, _xmm_m128 match with XMM register or memory
+    if (usTable == _xmm_m32 ||
+		usTable == _xmm_m64 ||
+		usTable == _xmm_m128)
+    {
+		if (usOp == _xmm)
+			goto Lmatch;
+		if (aoptyOp == _m && (bSizematch || uSizemaskOp == _anysize))
+			goto Lmatch;
+    }
+
+    if (!bSizematch && uSizemaskTable)
+    {
+		//printf("no size match\n");
+		goto EXIT;
+    }
+
+
+//
+// The operand types must match, otherwise return false.
+// There is one exception for the _rm which is a table entry which matches
+// _reg or _m
+//
+    if (aoptyTable != aoptyOp)
+    {
+		if (aoptyTable == _rm && (aoptyOp == _reg ||
+					  aoptyOp == _m ||
+					  aoptyOp == _rel))
+			goto Lok;
+
+		if (aoptyTable == _mnoi && aoptyOp == _m &&
+			(uSizemaskOp == _32 && amodOp == _addr16 ||
+			 uSizemaskOp == _48 && amodOp == _addr32 ||
+			 uSizemaskOp == _48 && amodOp == _normal)
+		  )
+			goto Lok;
+		goto EXIT;
+    }
+Lok:
+
+//
+// Looks like a match so far, check to see if anything special is going on
+//
+    amodTable = ASM_GET_amod(usTable);
+    uRegmaskOp = ASM_GET_uRegmask(usOp);
+    uRegmaskTable = ASM_GET_uRegmask(usTable);
+    bRegmatch = ((!uRegmaskTable && !uRegmaskOp) ||
+		 (uRegmaskTable & uRegmaskOp));
+
+    switch (amodTable)
+    {
+		case _normal:		// Normal's match with normals
+			switch(amodOp) {
+				case _normal:
+				case _addr16:
+				case _addr32:
+				case _fn16:
+				case _fn32:
+				case _flbl:
+				bRetval = (bSizematch || bRegmatch);
+				goto EXIT;
+				default:
+				goto EXIT;
+			}
+		case _rseg:
+		case _rspecial:
+			bRetval = (amodOp == amodTable && bRegmatch);
+			goto EXIT;
+    }
+EXIT:
+static if (false) {
+    printf("OP : ");
+    asm_output_flags(usOp);
+    printf("\nTBL: ");
+    asm_output_flags(usTable);
+    writef(": %s\n", bRetval ? "MATCH" : "NOMATCH");
+}
+    return bRetval;
+
+Lmatch:
+    //printf("match\n");
+    return 1;
+}
+
+void asm_output_flags(opflag_t usFlags)
+{
+	ASM_OPERAND_TYPE    aopty = ASM_GET_aopty(usFlags);
+	ASM_MODIFIERS	    amod = ASM_GET_amod(usFlags);
+	uint uRegmask = ASM_GET_uRegmask(usFlags);
+	uint uSizemask = ASM_GET_uSizemask(usFlags);
+
+	if (uSizemask == _anysize)
+	    printf("_anysize ");
+	else if (uSizemask == 0)
+	    printf("0        ");
+	else
+	{
+	    if (uSizemask & _8)
+			printf("_8  ");
+	    if (uSizemask & _16)
+			printf("_16 ");
+	    if (uSizemask & _32)
+			printf("_32 ");
+	    if (uSizemask & _48)
+			printf("_48 ");
+	}
+
+	printf("_");
+	switch (aopty) {
+	    case ASM_OPERAND_TYPE._reg:
+			printf("reg   ");
+			break;
+	    case ASM_OPERAND_TYPE._m:
+			printf("m     ");
+			break;
+	    case ASM_OPERAND_TYPE._imm:
+			printf("imm   ");
+			break;
+	    case ASM_OPERAND_TYPE._rel:
+			printf("rel   ");
+			break;
+	    case ASM_OPERAND_TYPE._mnoi:
+			printf("mnoi  ");
+			break;
+	    case ASM_OPERAND_TYPE._p:
+			printf("p     ");
+			break;
+	    case ASM_OPERAND_TYPE._rm:
+			printf("rm    ");
+			break;
+	    case ASM_OPERAND_TYPE._float:
+			printf("float ");
+			break;
+	    default:
+			printf(" UNKNOWN ");
+	}
+
+	printf("_");
+	switch (amod) {
+	    case ASM_MODIFIERS._normal:
+			printf("normal   ");
+			if (uRegmask & 1) printf("_al ");
+			if (uRegmask & 2) printf("_ax ");
+			if (uRegmask & 4) printf("_eax ");
+			if (uRegmask & 8) printf("_dx ");
+			if (uRegmask & 0x10) printf("_cl ");
+			return;
+	    case ASM_MODIFIERS._rseg:
+			printf("rseg     ");
+			break;
+	    case ASM_MODIFIERS._rspecial:
+			printf("rspecial ");
+			break;
+	    case ASM_MODIFIERS._addr16:
+			printf("addr16   ");
+			break;
+	    case ASM_MODIFIERS._addr32:
+			printf("addr32   ");
+			break;
+	    case ASM_MODIFIERS._fn16:
+			printf("fn16     ");
+			break;
+	    case ASM_MODIFIERS._fn32:
+			printf("fn32     ");
+			break;
+	    case ASM_MODIFIERS._flbl:
+			printf("flbl     ");
+			break;
+	    default:
+			printf("UNKNOWN  ");
+			break;
+	}
+
+	printf("uRegmask=x%02x", uRegmask);	   
+}
+
+OPND* asm_log_or_exp()
+{
+	OPND* o1 = asm_log_and_exp();
+	OPND* o2;
+
+	while (tok_value == TOK.TOKoror)
+	{
+		asm_token();
+		o2 = asm_log_and_exp();
+		if (asm_isint(o1) && asm_isint(o2))
+		    o1.disp = o1.disp || o2.disp;
+		else
+		    asmerr(ASMERRMSGS.EM_bad_integral_operand);		// illegal operand
+		o2.disp = 0;
+		o1 = asm_merge_opnds(o1, o2);
+	}
+	return o1;
+}
+
+void asm_chktok(TOK toknum, uint errnum)
+{
+    if (tok_value == toknum)
+		asm_token();			// scan past token
+    else
+		/* When we run out of tokens, asmtok is null.
+		 * But when this happens when a ';' was hit.
+		 */
+		asmerr(errnum, asmtok ? asmtok.toChars() : ";");
+}
+
+opflag_t asm_determine_float_flags(OPND* popnd)
+{
+    //printf("asm_determine_float_flags()\n");
+
+    opflag_t us;
+	opflag_t usFloat;
+
+    // Insure that if it is a register, that it is not a normal processor
+    // register.
+
+    if (popnd.base && 
+	    !popnd.s && !popnd.disp && !popnd.real_
+	    && !(popnd.base.ty & (_r8 | _r16 | _r32)))
+    {
+		return popnd.base.ty;
+    }
+    if (popnd.pregDisp1 && !popnd.base)
+    {
+		us = asm_float_type_size(popnd.ptype, &usFloat);
+		//printf("us = x%x, usFloat = x%x\n", us, usFloat);
+		if (popnd.pregDisp1.ty & _r32)
+			return(CONSTRUCT_FLAGS(us, _m, _addr32, usFloat));
+		else if (popnd.pregDisp1.ty & _r16)
+			return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat));
+    }
+    else if (popnd.s !is null)
+    {
+		us = asm_float_type_size(popnd.ptype, &usFloat);
+		return CONSTRUCT_FLAGS(us, _m, _normal, usFloat);
+    }
+
+    if (popnd.segreg)
+    {
+		us = asm_float_type_size(popnd.ptype, &usFloat);
+		if (I32)
+			return(CONSTRUCT_FLAGS(us, _m, _addr32, usFloat));
+		else
+			return(CONSTRUCT_FLAGS(us, _m, _addr16, usFloat));
+    }
+
+static if (false) {
+    if (popnd.real_)
+    {
+		switch (popnd.ptype.ty)
+		{
+			case TY.Tfloat32:
+				popnd.s = fconst(popnd.real_);
+				return(CONSTRUCT_FLAGS(_32, _m, _normal, 0));
+
+			case TY.Tfloat64:
+				popnd.s = dconst(popnd.real_);
+				return(CONSTRUCT_FLAGS(0, _m, _normal, _64));
+
+			case TY.Tfloat80:
+				popnd.s = ldconst(popnd.real_);
+				return(CONSTRUCT_FLAGS(0, _m, _normal, _80));
+		}
+    }
+}
+
+    asmerr(ASMERRMSGS.EM_bad_float_op);	// unknown operand for floating point instruction
+    return 0;
+}
+
+uint asm_type_size(Type ptype)
+{   
+    //if (ptype) printf("asm_type_size('%s') = %d\n", ptype.toChars(), (int)ptype.size());
+    uint u = _anysize;
+    if (ptype && ptype.ty != TY.Tfunction /*&& ptype.isscalar()*/)
+    {
+		switch (cast(int)ptype.size())
+		{
+			case 0:	asmerr(ASMERRMSGS.EM_bad_op, "0 size");	break;
+			case 1:	u = _8;		break;
+			case 2:	u = _16;	break;
+			case 4:	u = _32;	break;
+			case 6:	u = _48;	break;
+			default:
+				break;	///
+		}
+    }
+    return u;
+}
+
+bool asm_match_float_flags(opflag_t usOp, opflag_t usTable)
+{
+    ASM_OPERAND_TYPE	aoptyTable;
+    ASM_OPERAND_TYPE	aoptyOp;
+    ASM_MODIFIERS	amodTable;
+    ASM_MODIFIERS	amodOp;
+    uint uRegmaskTable;
+    uint uRegmaskOp;
+    ubyte bRegmatch;
+
+    
+//
+// Check #1, if the sizes do not match, NO match
+//
+    uRegmaskOp = ASM_GET_uRegmask(usOp);
+    uRegmaskTable = ASM_GET_uRegmask(usTable);
+    bRegmatch = (uRegmaskTable & uRegmaskOp) != 0;
+    
+    if (!(ASM_GET_uSizemask(usTable) & ASM_GET_uSizemask(usOp) || bRegmatch))
+		return false;
+    
+    aoptyTable = ASM_GET_aopty(usTable);
+    aoptyOp = ASM_GET_aopty(usOp);
+//
+// The operand types must match, otherwise return false.
+// There is one exception for the _rm which is a table entry which matches
+// _reg or _m
+//
+    if (aoptyTable != aoptyOp)
+    {
+		if (aoptyOp != _float)
+			return false;
+    }
+
+//
+// Looks like a match so far, check to see if anything special is going on
+//
+    amodOp = ASM_GET_amod(usOp);
+    amodTable = ASM_GET_amod(usTable);
+    switch (amodTable)
+    {
+		// Normal's match with normals
+		case _normal:
+			switch(amodOp)
+			{
+				case _normal:
+				case _addr16:
+				case _addr32:
+				case _fn16:
+				case _fn32:
+				case _flbl:
+					return true;
+
+				default:
+					return false;
+			}
+
+		case _rseg:
+		case _rspecial:
+			return false;
+		default:
+			assert(0);
+    }
+}
+
+OPND* asm_log_and_exp()
+{
+	OPND* o1 = asm_inc_or_exp();
+	OPND* o2;
+
+	while (tok_value == TOKandand)
+	{
+		asm_token();
+		o2 = asm_inc_or_exp();
+		if (asm_isint(o1) && asm_isint(o2))
+			o1.disp = o1.disp && o2.disp;
+		else {
+			asmerr(EM_bad_integral_operand);		// illegal operand
+		}
+		o2.disp = 0;
+		o1 = asm_merge_opnds(o1, o2);
+	}
+	return o1;
+}
+
+bool 	asm_isint(OPND *o)
+{
+    if (!o || o.base || o.s)
+		return false;
+
+    //return o.disp != 0;
+    return true;
+}
+
+/*******************************
+ * Merge operands o1 and o2 into a single operand.
+ */
+
+OPND* asm_merge_opnds(OPND* o1, OPND* o2)
+{
+	debug immutable(char)* psz;
+    debug if (debuga)
+    {	
+		printf("asm_merge_opnds(o1 = ");
+		if (o1) asm_output_popnd(o1);
+			printf(", o2 = ");
+		if (o2) asm_output_popnd(o2);
+			printf(")\n");
+    }
+
+	if (!o1)
+		return o2;
+	if (!o2)
+		return o1;
+version (EXTRA_DEBUG) {
+	printf("Combining Operands: mult1 = %d, mult2 = %d",
+		o1.uchMultiplier, o2.uchMultiplier);
+}
+	/*	combine the OPND's disp field */
+	if (o2.segreg) {
+	    if (o1.segreg) {
+			debug psz = "o1.segment && o2.segreg".ptr;
+			goto ILLEGAL_ADDRESS_ERROR;
+	    }
+	    else
+			o1.segreg = o2.segreg;
+	}
+	
+	// combine the OPND's symbol field
+	if (o1.s && o2.s)
+	{
+	    debug psz = "o1.s && os.s";
+ILLEGAL_ADDRESS_ERROR:
+		debug printf("Invalid addr because /%s/\n", psz);
+    
+	    asmerr(EM_bad_addr_mode);		// illegal addressing mode
+	}
+	else if (o2.s)
+	    o1.s = o2.s;
+	else if (o1.s && o1.s.isTupleDeclaration())
+	{   
+		TupleDeclaration tup = o1.s.isTupleDeclaration();
+
+	    size_t index = o2.disp;
+	    if (index >= tup.objects.dim)
+			error(asmstate.loc, "tuple index %u exceeds %u", index, tup.objects.dim);
+	    else
+	    {
+			Object o = cast(Object)tup.objects.data[index];
+			if (auto d = cast(Dsymbol)o)
+			{   
+				o1.s = d;
+				return o1;
+			}
+			else if (auto e = cast(Expression)o)
+			{
+				if (e.op == TOKvar)
+				{   
+					o1.s = (cast(VarExp)e).var;
+					return o1;
+				}
+				else if (e.op == TOKfunction)
+				{   
+					o1.s = (cast(FuncExp)e).fd;
+					return o1;
+				}
+			}
+			error(asmstate.loc, "invalid asm operand %s", o1.s.toChars());
+	    }
+	}
+
+	if (o1.disp && o2.disp)
+	    o1.disp += o2.disp;
+	else if (o2.disp)
+	    o1.disp = o2.disp;
+
+	/* combine the OPND's base field */
+	if (o1.base !is null && o2.base !is null) {
+		debug psz = "o1.base != null && o2.base != null".ptr;
+		goto ILLEGAL_ADDRESS_ERROR;
+	}
+	else if (o2.base)
+		o1.base = o2.base;
+
+	/* Combine the displacement register fields */
+	if (o2.pregDisp1)
+	{
+		if (o1.pregDisp2)
+		{
+		    debug psz = "o2.pregDisp1 && o1.pregDisp2";
+		    goto ILLEGAL_ADDRESS_ERROR;
+		}
+		else if (o1.pregDisp1)
+		{
+		    if (o1.uchMultiplier ||
+			    (o2.pregDisp1.val == _ESP &&
+			    (o2.pregDisp1.ty & _r32) &&
+			    !o2.uchMultiplier))
+		    {
+				o1.pregDisp2 = o1.pregDisp1;
+				o1.pregDisp1 = o2.pregDisp1;
+		    }
+		    else
+				o1.pregDisp2 = o2.pregDisp1;
+		}
+		else 
+			o1.pregDisp1 = o2.pregDisp1;
+	}
+	if (o2.pregDisp2) {
+		if (o1.pregDisp2) {
+			debug psz = "o1.pregDisp2 && o2.pregDisp2";
+			goto ILLEGAL_ADDRESS_ERROR;
+		}
+		else
+			o1.pregDisp2 = o2.pregDisp2;
+	}
+	if (o2.uchMultiplier)
+	{
+	    if (o1.uchMultiplier)
+	    {
+			debug psz = "o1.uchMultiplier && o2.uchMultiplier";
+			goto ILLEGAL_ADDRESS_ERROR;
+	    }
+	    else
+			o1.uchMultiplier = o2.uchMultiplier;
+	}
+	if (o2.ptype && !o1.ptype)
+	    o1.ptype = o2.ptype;
+	if (o2.bOffset)
+	    o1.bOffset = o2.bOffset;
+	if (o2.bSeg)
+	    o1.bSeg = o2.bSeg;
+	
+	if (o2.ajt && !o1.ajt)
+	    o1.ajt = o2.ajt;
+
+	opnd_free(o2);
+version (EXTRA_DEBUG) {
+	printf("Result = %d\n", o1.uchMultiplier);
+}
+	debug if (debuga)
+	{   printf("Merged result = /");
+	    asm_output_popnd(o1);
+	    printf("/\n");
+	}
+
+	return o1;
+}
+
+opflag_t asm_float_type_size(Type ptype, opflag_t* pusFloat)
+{
+    *pusFloat = 0;
+    
+    //printf("asm_float_type_size('%s')\n", ptype.toChars());
+    if (ptype && ptype.isscalar())
+    {
+		int sz = cast(int)ptype.size();
+		if (sz == REALSIZE)
+		{   
+			*pusFloat = _80;
+			return 0;
+		}
+		switch (sz)
+		{
+			case 2:
+				return _16;
+			case 4:
+				return _32;
+			case 8:
+				*pusFloat = _64;
+				return 0;
+			default:
+				break;
+		}
+    }
+
+    *pusFloat = _fanysize;
+    return _anysize;
+}
+
+OPND* asm_inc_or_exp()
+{
+	OPND* o1 = asm_xor_exp();
+	OPND* o2;
+
+	while (tok_value == TOKor)
+	{
+		asm_token();
+		o2 = asm_xor_exp();
+		if (asm_isint(o1) && asm_isint(o2))
+			o1.disp |= o2.disp;
+		else {
+			asmerr(EM_bad_integral_operand);		// illegal operand
+		}
+		o2.disp = 0;
+		o1 = asm_merge_opnds(o1, o2);
+	}
+	return o1;
+}
+
+OPND* asm_xor_exp()
+{
+	OPND* o1 = asm_and_exp();
+	OPND* o2;
+
+	while (tok_value == TOKxor)
+	{
+		asm_token();
+		o2 = asm_and_exp();
+		if (asm_isint(o1) && asm_isint(o2))
+			o1.disp ^= o2.disp;
+		else {
+			asmerr(EM_bad_integral_operand);		// illegal operand
+		}
+		o2.disp = 0;
+		o1 = asm_merge_opnds(o1, o2);
+	}
+	return o1;
+}
+
+OPND* asm_and_exp()
+{ 
+	OPND* o1 = asm_equal_exp();
+	OPND* o2;
+
+	while (tok_value == TOKand)
+	{
+		asm_token();
+		o2 = asm_equal_exp();
+		if (asm_isint(o1) && asm_isint(o2))
+			o1.disp &= o2.disp;
+		else {
+			asmerr(EM_bad_integral_operand);		// illegal operand
+		}
+		o2.disp = 0;
+		o1 = asm_merge_opnds(o1, o2);
+	}
+	return o1;
+}
+
+OPND* asm_equal_exp()
+{
+    OPND* o1 = asm_rel_exp();
+	OPND* o2;
+
+    while (1)
+    {
+		switch (tok_value)
+		{
+			case TOKequal:
+				asm_token();
+				o2 = asm_rel_exp();
+				if (asm_isint(o1) && asm_isint(o2))
+					o1.disp = o1.disp == o2.disp;
+				else {
+					asmerr(EM_bad_integral_operand);	// illegal operand
+				}
+				o2.disp = 0;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			case TOKnotequal:
+				asm_token();
+				o2 = asm_rel_exp();
+				if (asm_isint(o1) && asm_isint(o2))
+					o1.disp = o1.disp != o2.disp;
+				else {
+					asmerr(EM_bad_integral_operand);
+				}
+				o2.disp = 0;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			default:
+				return o1;
+		}
+    }
+	
+	assert(false);
+}
+
+OPND* asm_rel_exp()
+{
+    OPND* o1 = asm_shift_exp();
+	OPND* o2;
+
+    TOK tok_save;
+
+    while (1)
+    {
+		switch (tok_value)
+		{
+			case TOKgt:
+			case TOKge:
+			case TOKlt:
+			case TOKle:
+				tok_save = tok_value;
+				asm_token();
+				o2 = asm_shift_exp();
+				if (asm_isint(o1) && asm_isint(o2))
+				{
+					switch (tok_save)
+					{
+						case TOKgt:
+							o1.disp = o1.disp > o2.disp;
+							break;
+						case TOKge:
+							o1.disp = o1.disp >= o2.disp;
+							break;
+						case TOKlt:
+							o1.disp = o1.disp < o2.disp;
+							break;
+						case TOKle:
+							o1.disp = o1.disp <= o2.disp;
+							break;
+					}
+				}
+				else
+					asmerr(EM_bad_integral_operand);
+				o2.disp = 0;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			default:
+				return o1;
+		}
+    }
+	
+	assert(false);
+}
+
+OPND* asm_shift_exp()
+{
+    OPND* o1 = asm_add_exp();
+	OPND* o2;
+    
+	int op;
+    TOK tk;
+
+    while (tok_value == TOKshl || tok_value == TOKshr || tok_value == TOKushr)
+    {   
+		tk = tok_value;
+		asm_token();
+		o2 = asm_add_exp();
+		if (asm_isint(o1) && asm_isint(o2))
+		{   if (tk == TOKshl)
+			o1.disp <<= o2.disp;
+			else if (tk == TOKushr)
+			o1.disp = cast(uint)o1.disp >> o2.disp;
+			else
+			o1.disp >>= o2.disp;
+		}
+		else
+			asmerr(EM_bad_integral_operand);
+		o2.disp = 0;
+		o1 = asm_merge_opnds(o1, o2);
+    }
+    return o1;
+}
+
+/*******************************
+ */
+
+OPND* asm_add_exp()
+{
+    OPND* o1 = asm_mul_exp();
+	OPND* o2;
+
+    while (1)
+    {
+		switch (tok_value) 
+		{
+			case TOKadd:
+				asm_token();
+				o2 = asm_mul_exp();
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			case TOKmin:
+				asm_token();
+				o2 = asm_mul_exp();
+				if (asm_isint(o1) && asm_isint(o2))
+				{
+					o1.disp -= o2.disp;
+					o2.disp = 0;
+				}
+				else
+					o2.disp = - o2.disp;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			default:
+				return o1;
+		}
+    }
+	
+	assert(false);
+}
+
+/*******************************
+ */
+
+OPND* asm_mul_exp()
+{
+    OPND* o1;
+	OPND* o2;
+    OPND* popndTmp;
+
+    //printf("+asm_mul_exp()\n");
+    o1 = asm_br_exp();
+    while (1)
+    {
+		switch (tok_value)
+		{
+			case TOKmul:
+				asm_token();
+				o2 = asm_br_exp();
+version (EXTRA_DEBUG) {
+				printf("Star  o1.isint=%d, o2.isint=%d, lbra_seen=%d\n",
+					asm_isint(o1), asm_isint(o2), asm_TKlbra_seen );
+}
+				if (asm_isNonZeroInt(o1) && asm_isNonZeroInt(o2))
+					o1.disp *= o2.disp;
+				else if (asm_TKlbra_seen && o1.pregDisp1 && asm_isNonZeroInt(o2))
+				{
+					o1.uchMultiplier = o2.disp;
+version (EXTRA_DEBUG) {
+					printf("Multiplier: %d\n", o1.uchMultiplier);
+}
+				}
+				else if (asm_TKlbra_seen && o2.pregDisp1 && asm_isNonZeroInt(o1))
+				{
+					popndTmp = o2;
+					o2 = o1;
+					o1 = popndTmp;
+					o1.uchMultiplier = o2.disp;
+version (EXTRA_DEBUG) {
+					printf("Multiplier: %d\n",
+					o1.uchMultiplier);
+}
+				}
+				else if (asm_isint(o1) && asm_isint(o2))
+					o1.disp *= o2.disp;
+				else
+					asmerr(EM_bad_operand);
+				o2.disp = 0;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			case TOKdiv:
+				asm_token();
+				o2 = asm_br_exp();
+				if (asm_isint(o1) && asm_isint(o2))
+					o1.disp /= o2.disp;
+				else
+					asmerr(EM_bad_integral_operand);
+				o2.disp = 0;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			case TOKmod:
+				asm_token();
+				o2 = asm_br_exp();
+				if (asm_isint(o1) && asm_isint(o2))
+					o1.disp %= o2.disp;
+				else
+					asmerr(EM_bad_integral_operand);
+				o2.disp = 0;
+				o1 = asm_merge_opnds(o1, o2);
+				break;
+
+			default:
+				return o1;
+		}
+    }
+
+    return o1;
+}
+
+OPND* asm_br_exp()
+{
+    //printf("asm_br_exp()\n");
+	
+	OPND* o1 = asm_una_exp();
+	OPND* o2;
+    Declaration s;
+	
+    while (1)
+    {
+		switch (tok_value)
+		{
+			case TOKlbracket:
+			{
+version (EXTRA_DEBUG) {
+				printf("Saw a left bracket\n");
+}
+				asm_token();
+				asm_TKlbra_seen++;
+				o2 = asm_cond_exp();
+				asm_TKlbra_seen--;
+				asm_chktok(TOKrbracket,EM_rbra);
+version (EXTRA_DEBUG) {
+				printf("Saw a right bracket\n");
+}
+				o1 = asm_merge_opnds(o1, o2);
+				if (tok_value == TOKidentifier)
+				{   o2 = asm_una_exp();
+					o1 = asm_merge_opnds(o1, o2);
+				}
+				break;
+			}
+			default:
+				return o1;
+		}
+    }
+	
+	assert(false);
+}
+
+/*******************************
+ */
+
+OPND* asm_una_exp()
+{
+	OPND* o1;
+	int op;
+	Type ptype;
+	Type ptypeSpec;
+	ASM_JUMPTYPE ajt = ASM_JUMPTYPE_UNSPECIFIED;
+	char bPtr = 0;
+	
+	switch (cast(int)tok_value)
+	{
+static if (false) {
+		case TOKand:
+		    asm_token();
+		    o1 = asm_una_exp();
+		    break;
+
+		case TOKmul: 
+		    asm_token();
+		    o1 = asm_una_exp();
+		    ++o1.indirect;
+		    break;
+}
+		case TOKadd:
+		    asm_token();
+		    o1 = asm_una_exp();
+		    break;
+
+		case TOKmin: 
+		    asm_token();
+			o1 = asm_una_exp();
+			if (asm_isint(o1))
+				o1.disp = -o1.disp;
+		    break;
+
+		case TOKnot: 
+		    asm_token();
+			o1 = asm_una_exp();
+			if (asm_isint(o1))
+				o1.disp = !o1.disp;
+		    break;
+
+		case TOKtilde: 
+		    asm_token();
+			o1 = asm_una_exp();
+			if (asm_isint(o1))
+				o1.disp = ~o1.disp;
+		    break;
+
+static if (false) {
+		case TOKlparen:
+		    // stoken() is called directly here because we really
+		    // want the INT token to be an INT.
+		    stoken();
+		    if (type_specifier(&ptypeSpec)) /* if type_name	*/
+		    {   
+				ptype = declar_abstract(ptypeSpec);
+						/* read abstract_declarator	 */
+				fixdeclar(ptype);/* fix declarator		 */
+				type_free(ptypeSpec);/* the declar() function
+							allocates the typespec again */
+				chktok(TOKrparen,EM_rpar);
+				ptype.Tcount--;
+				goto CAST_REF;
+		    }
+		    else
+		    {
+				type_free(ptypeSpec);
+				o1 = asm_cond_exp();
+				chktok(TOKrparen, EM_rpar);
+		    }
+		    break;
+}
+
+		case TOKidentifier:
+		    // Check for offset keyword
+		    if (asmtok.ident == Id.offset)
+		    {
+				if (!global.params.useDeprecated)
+					error(asmstate.loc, "offset deprecated, use offsetof");
+				goto Loffset;
+		    }
+		    if (asmtok.ident == Id.offsetof)
+		    {
+		      Loffset:
+				asm_token();
+				o1 = asm_cond_exp();
+				if (!o1)
+					o1 = opnd_calloc();
+				o1.bOffset= true;
+		    }
+		    else
+				o1 = asm_primary_exp();
+		    break;
+
+		case ASMTK.ASMTKseg:
+		    asm_token();
+		    o1 = asm_cond_exp();
+		    if (!o1)
+			o1 = opnd_calloc();
+		    o1.bSeg= true;
+		    break;
+			
+		case TOKint16:
+		    if (asmstate.ucItype != ITjump)
+		    {
+			ptype = Type.tint16;
+			goto TYPE_REF;
+		    }
+		    ajt = ASM_JUMPTYPE_SHORT;
+		    asm_token();
+		    goto JUMP_REF2;
+
+		case ASMTKnear:
+		    ajt = ASM_JUMPTYPE_NEAR;
+		    goto JUMP_REF;
+
+		case ASMTKfar:
+		    ajt = ASM_JUMPTYPE_FAR;
+JUMP_REF:
+		    asm_token();
+		    asm_chktok(cast(TOK) ASMTKptr, EM_ptr_exp);
+JUMP_REF2:
+		    o1 = asm_cond_exp();
+		    if (!o1)
+				o1 = opnd_calloc();
+		    o1.ajt= ajt;
+		    break;
+		    
+		case TOKint8:
+		    ptype = Type.tint8;
+		    goto TYPE_REF;
+		case TOKint32:
+		case ASMTKdword:
+		    ptype = Type.tint32;
+		    goto TYPE_REF;
+		case TOKfloat32:
+		    ptype = Type.tfloat32;
+		    goto TYPE_REF;
+		case ASMTKqword:
+		case TOKfloat64:
+		    ptype = Type.tfloat64;
+		    goto TYPE_REF;
+		case TOKfloat80:
+		    ptype = Type.tfloat80;
+		    goto TYPE_REF;
+		case ASMTKword:
+		    ptype = Type.tint16;
+TYPE_REF:
+		    bPtr = 1;
+		    asm_token();
+		    asm_chktok(cast(TOK) ASMTKptr, EM_ptr_exp);
+CAST_REF:
+		    o1 = asm_cond_exp();
+		    if (!o1)
+				o1 = opnd_calloc();
+		    o1.ptype = ptype;
+		    o1.bPtr = bPtr;
+		    break;
+		    
+		default:
+		    o1 = asm_primary_exp();
+		    break;
+	}
+	return o1;
+}
+
+bool asm_isNonZeroInt(OPND* o)
+{
+    if (!o || o.base || o.s)
+		return false;
+
+    return o.disp != 0;
+}
+
+OPND* asm_primary_exp()
+{
+	OPND* o1 = null;
+	OPND* o2 = null;
+	Type ptype;
+	Dsymbol s;
+	Dsymbol scopesym;
+
+	TOK tkOld;
+	int global;
+	REG* regp;
+
+ 	global = 0;	
+	switch (cast(int)tok_value)
+	{
+	    case TOKdollar:
+			o1 = opnd_calloc();
+			o1.s = asmstate.psDollar;
+			asm_token();
+			break;
+
+static if (false) {
+	    case TOKthis:
+			strcpy(tok.TKid,cpp_name_this);
+}
+	    case TOKidentifier:
+	    case_ident:
+			o1 = opnd_calloc();
+			regp = asm_reg_lookup(asmtok.ident.toChars());
+			if (regp !is null)
+			{
+				asm_token();
+				// see if it is segment override (like SS:)
+				if (!asm_TKlbra_seen &&
+					(regp.ty & _seg) &&
+					tok_value == TOKcolon)
+				{
+				o1.segreg = regp;
+				asm_token();
+				o2 = asm_cond_exp();
+				o1 = asm_merge_opnds(o1, o2);
+				}
+				else if (asm_TKlbra_seen)
+				{   // should be a register
+				if (o1.pregDisp1)
+					asmerr(EM_bad_operand);
+				else
+					o1.pregDisp1 = regp;
+				}
+				else
+				{   if (o1.base == null)
+					o1.base = regp;
+				else
+					asmerr(EM_bad_operand);
+				}
+				break;
+			}
+			// If floating point instruction and id is a floating register
+			else if (asmstate.ucItype == ITfloat &&
+				 asm_is_fpreg(asmtok.ident.toChars()))
+			{
+				asm_token();
+				if (tok_value == TOKlparen)
+				{	
+					uint n;
+
+					asm_token();
+					asm_chktok(TOKint32v, EM_num);
+					n = cast(uint)asmtok.uns64value;
+					if (n > 7)
+						asmerr(EM_bad_operand);
+					o1.base = &(aregFp[n]);
+					asm_chktok(TOKrparen, EM_rpar);
+				}
+				else
+					o1.base = &regFp;
+			}
+			else
+			{
+				if (asmstate.ucItype == ITjump)
+				{
+					s = null;
+					if (asmstate.sc.func.labtab)
+						s = asmstate.sc.func.labtab.lookup(asmtok.ident);
+					if (!s)
+						s = asmstate.sc.search(Loc(0), asmtok.ident, &scopesym);
+					if (!s)
+					{   // Assume it is a label, and define that label
+						s = asmstate.sc.func.searchLabel(asmtok.ident);
+					}
+				}
+				else
+					s = asmstate.sc.search(Loc(0), asmtok.ident, &scopesym);
+
+				if (!s)
+					asmerr(EM_undefined, asmtok.toChars());
+
+				Identifier id = asmtok.ident;
+				asm_token();
+				if (tok_value == TOKdot)
+				{	
+					Expression e;
+					VarExp v;
+
+					e = new IdentifierExp(asmstate.loc, id);
+					while (1)
+					{
+						asm_token();
+						if (tok_value == TOKidentifier)
+						{
+							e = new DotIdExp(asmstate.loc, e, asmtok.ident);
+							asm_token();
+							if (tok_value != TOKdot)
+								break;
+						}
+						else
+						{
+							asmerr(EM_ident_exp);
+							break;
+						}
+					}
+					e = e.semantic(asmstate.sc);
+					e = e.optimize(WANTvalue | WANTinterpret);
+					if (e.isConst())
+					{
+						if (e.type.isintegral())
+						{
+							o1.disp = cast(int)e.toInteger();
+							goto Lpost;
+						}
+						else if (e.type.isreal())
+						{
+							o1.real_ = e.toReal();
+							o1.ptype = e.type;
+							goto Lpost;
+						}
+						else
+						{
+							asmerr(EM_bad_op, e.toChars());
+						}
+					}
+					else if (e.op == TOKvar)
+					{
+						v = cast(VarExp)e;
+						s = v.var;
+					}
+					else
+					{
+						asmerr(EM_bad_op, e.toChars());
+					}
+				}
+
+				asm_merge_symbol(o1,s);
+
+				/* This attempts to answer the question: is
+				 *	char[8] foo;
+				 * of size 1 or size 8? Presume it is 8 if foo
+				 * is the last token of the operand.
+				 */
+				if (o1.ptype && tok_value != TOKcomma && tok_value != TOKeof)
+				{
+				for (;
+					 o1.ptype.ty == Tsarray;
+					 o1.ptype = o1.ptype.nextOf())
+				{
+					;
+				}
+				}
+
+			Lpost:
+static if (false) {
+				// for []
+				if (tok_value == TOKlbracket)
+					o1 = asm_prim_post(o1);
+}
+				goto Lret;
+			}
+			break;
+
+	    case TOKint32v:
+	    case TOKuns32v:
+			o1 = opnd_calloc();
+			o1.disp = asmtok.int32value;
+			asm_token();
+			break;
+
+	    case TOKfloat32v:
+			o1 = opnd_calloc();
+			o1.real_ = asmtok.float80value;
+			o1.ptype = Type.tfloat32;
+			asm_token();
+			break;
+
+	    case TOKfloat64v:
+			o1 = opnd_calloc();
+			o1.real_ = asmtok.float80value;
+			o1.ptype = Type.tfloat64;
+			asm_token();
+			break;
+
+	    case TOKfloat80v:
+			o1 = opnd_calloc();
+			o1.real_ = asmtok.float80value;
+			o1.ptype = Type.tfloat80;
+			asm_token();
+			break;
+
+	    case ASMTKlocalsize:
+			o1 = opnd_calloc();
+			o1.s = asmstate.psLocalsize;
+			o1.ptype = Type.tint32;
+			asm_token();
+			break;
+			
+		default:
+			break;	///
+	}
+Lret:
+	return o1;
+}
+
+void asm_merge_symbol(OPND* o1, Dsymbol s)
+{   
+	Type ptype;
+    VarDeclaration v;
+    EnumMember em;
+
+    //printf("asm_merge_symbol(s = %s %s)\n", s.kind(), s.toChars());
+    s = s.toAlias();
+    //printf("s = %s %s\n", s.kind(), s.toChars());
+    if (s.isLabel())
+    {
+		o1.s = s;
+		return;
+    }
+
+    v = s.isVarDeclaration();
+    if (v)
+    {
+		if (v.isParameter())
+			asmstate.statement.refparam = true;
+
+		v.checkNestedReference(asmstate.sc, asmstate.loc);
+static if (false) {
+		if (!v.isDataseg() && v.parent != asmstate.sc.parent && v.parent)
+		{
+			asmerr(EM_uplevel, v.toChars());
+		}
+}
+		if (v.storage_class & STCfield)
+		{
+			o1.disp += v.offset;
+			goto L2;
+		}
+		if ((v.isConst()
+///version (DMDV2) {
+			|| v.isInvariant() || v.storage_class & STCmanifest
+///}
+			) && !v.type.isfloating() && v.init)
+		{   
+			ExpInitializer ei = v.init.isExpInitializer();
+
+			if (ei)
+			{
+				o1.disp = cast(int)ei.exp.toInteger();
+				return;
+			}
+		}
+    }
+    em = s.isEnumMember();
+    if (em)
+    {
+		o1.disp = cast(int)em.value.toInteger();
+		return;
+    }
+    o1.s = s;	// a C identifier
+L2:
+    Declaration d = s.isDeclaration();
+    if (!d)
+    {
+		asmerr("%s %s is not a declaration", s.kind(), s.toChars());
+    }
+    else if (d.getType())
+		asmerr(EM_type_as_operand, d.getType().toChars());
+    else if (d.isTupleDeclaration()) {
+		;
+    } else
+		o1.ptype = d.type.toBasetype();
+}
+
+REG[63] regtab = 
+[
+	{"AL",	_AL,	_r8 | _al,},
+	{"AH",	_AH,	_r8,},
+	{"AX",	_AX,	_r16 | _ax,},
+	{"EAX",	_EAX,	_r32 | _eax,},
+	{"BL",	_BL,	_r8,},	
+	{"BH",	_BH,	_r8,},
+	{"BX",	_BX,	_r16,},
+	{"EBX",	_EBX,	_r32,},
+	{"CL",	_CL,	_r8 | _cl,},
+	{"CH",	_CH,	_r8,},
+	{"CX",	_CX,	_r16,},
+	{"ECX",	_ECX,	_r32,},	
+	{"DL",	_DL,	_r8,},	
+	{"DH",	_DH,	_r8,},
+	{"DX",	_DX,	_r16 | _dx,},
+	{"EDX",	_EDX,	_r32,},
+	{"BP",	_BP,	_r16,},
+	{"EBP",	_EBP,	_r32,},
+	{"SP",	_SP,	_r16,},	
+	{"ESP",	_ESP,	_r32,},
+	{"DI",	_DI,	_r16,},	
+	{"EDI",	_EDI,	_r32,},
+	{"SI",	_SI,	_r16,},
+	{"ESI",	_ESI,	_r32,},
+	{"ES",	_ES,	_seg | _es,},
+	{"CS",	_CS,	_seg | _cs,},
+	{"SS",	_SS,	_seg | _ss,},	
+	{"DS",	_DS,	_seg | _ds,},
+	{"GS",	_GS,	_seg | _gs,},
+	{"FS",	_FS,	_seg | _fs,},
+	{"CR0",	0,	_special | _crn,},
+	{"CR2",	2,	_special | _crn,},
+	{"CR3",	3,	_special | _crn,},
+	{"CR4",	4,	_special | _crn,},
+	{"DR0",	0,	_special | _drn,},
+	{"DR1",	1,	_special | _drn,},
+	{"DR2",	2,	_special | _drn,},
+	{"DR3",	3,	_special | _drn,},
+	{"DR4",	4,	_special | _drn,},
+	{"DR5",	5,	_special | _drn,},
+	{"DR6",	6,	_special | _drn,},
+	{"DR7",	7,	_special | _drn,},
+	{"TR3",	3,	_special | _trn,},
+	{"TR4",	4,	_special | _trn,},
+	{"TR5",	5,	_special | _trn,},
+	{"TR6",	6,	_special | _trn,},
+	{"TR7",	7,	_special | _trn,},
+	{"MM0",	0,	_mm,},
+	{"MM1",	1,	_mm,},
+	{"MM2",	2,	_mm,},
+	{"MM3",	3,	_mm,},
+	{"MM4",	4,	_mm,},
+	{"MM5",	5,	_mm,},
+	{"MM6",	6,	_mm,},
+	{"MM7",	7,	_mm,},
+	{"XMM0",	0,	_xmm,},
+	{"XMM1",	1,	_xmm,},
+	{"XMM2",	2,	_xmm,},
+	{"XMM3",	3,	_xmm,},
+	{"XMM4",	4,	_xmm,},
+	{"XMM5",	5,	_xmm,},
+	{"XMM6",	6,	_xmm,},
+	{"XMM7",	7,	_xmm,},
+];
+
+REG* asm_reg_lookup(string s)
+{
+    //dbg_printf("asm_reg_lookup('%s')\n",s);	
+
+    for (int i = 0; i < regtab.length; i++)
+    {
+		if (regtab[i].regstr[0..min(s.length, $)] == s)
+		{
+			return &regtab[i];
+		}
+    }
+
+    return null;
+}
+
+int asm_is_fpreg(string szReg)
+{
+static if (true) {
+	return(szReg.length == 2 && szReg[0] == 'S' && 
+		szReg[1] == 'T');
+} else {
+	return(szReg.length == 2 && (szReg[0] == 's' || szReg[0] == 'S') &&
+		(szReg[1] == 't' || szReg[1] == 'T'));
+}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/immed_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,11 @@
+module dmd.backend.immed_t;
+
+import dmd.backend.targ_types;
+import dmd.backend.regm_t;
+import dmd.backend.REGMAX;
+
+struct immed_t
+{
+	targ_int value[REGMAX];	// immediate values in registers
+    regm_t mval;		// Mask of which values in regimmed.value[] are valid
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/mTY.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,43 @@
+module dmd.backend.mTY;
+
+enum mTY
+{
+	/* Linkage type			*/
+	mTYnear = 0x100,
+	mTYfar = 0x200,
+	mTYcs = 0x400,		// in code segment
+	mTYthread = 0x800,
+	mTYLINK = 0xF00,		// all linkage bits
+
+	mTYloadds = 0x1000,
+	mTYexport = 0x2000,
+	mTYweak	= 0x0000,
+	mTYimport = 0x4000,
+	mTYnaked = 0x8000,
+	mTYMOD = 0xF000,		// all modifier bits
+	
+	mTYbasic = 0x3F,	/* bit mask for basic types	*/
+	
+	/* Modifiers to basic types	*/
+///	#ifdef JHANDLE
+///	mTYarrayhandle = 0x80,
+///	#else
+	mTYarrayhandle = 0x0,
+///	#endif
+	mTYconst = 0x40,
+	mTYvolatile = 0x80,
+	mTYrestrict = 0,		// BUG: add for C99
+	mTYmutable = 0,		// need to add support
+	mTYunaligned = 0,		// non-zero for PowerPC
+
+	mTYimmutable = 0x1000000,	// immutable data
+	mTYshared = 0x2000000,	// shared data
+	mTYnothrow = 0x4000000,	// nothrow function
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(mTY));
+
+uint tybasic(uint ty) {
+	return ((ty) & mTY.mTYbasic);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/mTYman.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.backend.mTYman;
+
+enum mTYman {
+	mTYman_c = 1,	// C mangling
+	mTYman_cpp = 2,	// C++ mangling
+	mTYman_pas = 3,	// Pascal mangling
+	mTYman_for = 4,	// FORTRAN mangling
+	mTYman_sys = 5,	// _syscall mangling
+	mTYman_std = 6,	// _stdcall mangling
+	mTYman_d = 7,	// D mangling
+}
+
+import dmd.EnumUtils;
+mixin(BringToCurrentScope!(mTYman));
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/regm_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3 @@
+module dmd.backend.regm_t;
+
+alias ushort regm_t;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/rel.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,32 @@
+module dmd.backend.rel;
+
+import dmd.backend.OPER;
+
+extern (C++) extern
+{
+	ubyte* get_rel_not();
+	ubyte* get_rel_swap();
+	ubyte* get_rel_integral();
+	ubyte* get_rel_exception();
+	ubyte* get_rel_unord();
+}
+
+ubyte rel_not(OPER op) {
+	return get_rel_not[cast(int)(op) - RELOPMIN];
+}
+
+ubyte rel_swap(OPER op) {
+	return get_rel_swap[cast(int)(op) - RELOPMIN];
+}
+
+ubyte rel_integral(OPER op){
+	return get_rel_integral[cast(int)(op) - RELOPMIN];
+}
+
+ubyte rel_exception(OPER op) {
+	return get_rel_exception[cast(int)(op) - RELOPMIN];
+}
+
+ubyte rel_unord(OPER op) {
+	return get_rel_unord[cast(int)(op) - RELOPMIN];
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/struct_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,134 @@
+module dmd.backend.struct_t;
+
+import dmd.backend.targ_types;
+import dmd.backend.LIST;
+import dmd.backend.Symbol;
+
+/***********************************
+ * Special information for structs.
+ */
+
+struct struct_t
+{
+    targ_size_t Sstructsize;	// size of struct
+    symlist_t Sfldlst;		// all members of struct (list freeable)
+    Symbol* Sroot;		// root of binary tree Symbol table
+    uint Salignsize;	// size of struct for alignment purposes
+    ubyte Sstructalign;	// struct member alignment in effect
+    uint Sflags;
+/+
+#define STRanonymous	0x01	// set for unions with no tag names
+#define STRglobal	0x02	// defined at file scope
+#define STRnotagname	0x04	// struct/class with no tag name
+#define STRoutdef	0x08	// we've output the debug definition
+#define STRbitfields    0x10	// set if struct contains bit fields
+#define STRpredef	0x1000 // a predefined struct
+#define STRunion	0x4000	// actually, it's a union
+
+#define STRabstract	0x20	// abstract class
+#define STRbitcopy	0x40	// set if operator=() is merely a bit copy
+#define STRanyctor	0x80	// set if any constructors were defined
+				// by the user
+#define STRnoctor	0x100	// no constructors allowed
+#define STRgen		0x200	// if struct is an instantiation of a
+				// template class, and was generated by
+				// that template
+#define STRvtblext	0x400	// generate vtbl[] only when first member function
+				// definition is encountered (see Fvtblgen)
+#define STRexport	0x800	// all member functions are to be _export
+#define STRclass	0x8000	// it's a class, not a struct
+#if TX86
+#define STRimport	0x40000	// imported class
+#define STRstaticmems	0x80000	// class has static members
+#endif
+#define	STR0size	0x100000	// zero sized struct
+#define STRinstantiating 0x200000	// if currently being instantiated
+#define STRexplicit	0x400000	// if explicit template instantiation
+#define STRgenctor0	0x800000	// need to gen X::X()
+    tym_t ptrtype;		// type of pointer to refer to classes by
+    unsigned short access;	// current access privilege, here so
+				// enum declarations can get at it
+    targ_size_t Snonvirtsize;	// size of struct excluding virtual classes
+    list_t Svirtual;		// freeable list of mptrs
+				// that go into vtbl[]
+#if TX86
+    list_t *Spvirtder;		// pointer into Svirtual that points to start
+				// of virtual functions for this (derived) class
+    symlist_t Sopoverload;	// overloaded operator funcs (list freeable)
+#endif
+    symlist_t Scastoverload;	// overloaded cast funcs (list freeable)
+    symlist_t Sclassfriends;	// list of classes of which this is a friend
+				// (list is freeable)
+    symlist_t Sfriendclass;	// classes which are a friend to this class
+				// (list is freeable)
+    symlist_t Sfriendfuncs;	// functions which are a friend to this class
+				// (list is freeable)
+    symlist_t Sinlinefuncs;	// list of tokenized functions
+    baseclass_t *Sbase;		// list of direct base classes
+    baseclass_t *Svirtbase;	// list of all virtual base classes
+    baseclass_t *Smptrbase;	// list of all base classes that have
+				// their own vtbl[]
+    baseclass_t *Sprimary;	// if not NULL, then points to primary
+				// base class
+    Funcsym *Svecctor;		// constructor for use by vec_new()
+    Funcsym *Sctor;		// constructor function
+
+    Funcsym *Sdtor;		// basic destructor
+#if VBTABLES
+    Funcsym *Sprimdtor;		// primary destructor
+    Funcsym *Spriminv;		// primary invariant
+    Funcsym *Sscaldeldtor;	// scalar deleting destructor
+#endif
+
+    Funcsym *Sinvariant;	// basic invariant function
+
+    Symbol *Svptr;		// Symbol of vptr
+    Symbol *Svtbl;		// Symbol of vtbl[]
+#if VBTABLES
+    Symbol *Svbptr;		// Symbol of pointer to vbtbl[]
+    Symbol *Svbptr_parent;	// base class for which Svbptr is a member.
+				// NULL if Svbptr is a member of this class
+    targ_size_t Svbptr_off;	// offset of Svbptr member
+    Symbol *Svbtbl;		// virtual base offset table
+    baseclass_t *Svbptrbase;	// list of all base classes in canonical
+				// order that have their own vbtbl[]
+#endif
+    Funcsym *Sopeq;		// X& X::operator =(X&)
+    Funcsym *Sopeq2;		// Sopeq, but no copy of virtual bases
+    Funcsym *Scpct;		// copy constructor
+    Funcsym *Sveccpct;		// vector copy constructor
+    Symbol *Salias;		// pointer to identifier S to use if
+				// struct was defined as:
+				//	typedef struct { ... } S;
+
+    Symbol *Stempsym;		// if this struct is an instantiation
+				// of a template class, this is the
+				// template class Symbol
+
+    /* For:
+     *	template<class T> struct A { };
+     *	template<class T> struct A<T *> { };
+     *
+     *  A<int> a;		// primary
+     * Gives:
+     *	Sarglist = <int>
+     *	Spr_arglist = NULL;
+     *
+     *  A<int*> a;		// specialization
+     * Gives:
+     *	Sarglist = <int>
+     *	Spr_arglist = <int*>;
+     */
+
+    param_t *Sarglist;		// if this struct is an instantiation
+				// of a template class, this is the
+				// actual arg list used
+    param_t *Spr_arglist;	// if this struct is an instantiation
+				// of a specialized template class, this is the
+				// actual primary arg list used.
+				// It is NULL for the
+				// primary template class (since it would be
+				// identical to Sarglist).
+    TARGET_structSTRUCT
++/
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/symtab_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,12 @@
+module dmd.backend.symtab_t;
+
+import dmd.backend.Symbol;
+import dmd.backend.Util;
+import dmd.backend.SYMIDX;
+
+struct symtab_t
+{
+    SYMIDX top;			// 1 past end
+    SYMIDX symmax;		// max # of entries in tab[] possible
+    Symbol** tab;		// local Symbol table
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/targ_types.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,37 @@
+module dmd.backend.targ_types;
+
+/***************************
+ * Target machine data types as they appear on the host.
+ */
+
+alias char	 targ_char;
+alias ubyte	 targ_uchar;
+alias byte	 targ_schar;
+alias short	 targ_short;
+alias ushort targ_ushort;
+alias long	 targ_long;
+alias ulong	 targ_ulong;
+alias long 	 targ_llong;
+alias ulong	 targ_ullong;
+alias float	 targ_float;
+alias double targ_double;
+alias real   targ_ldouble;
+alias int 	 targ_int;
+alias uint   targ_uns;
+alias size_t targ_size_t;
+alias ptrdiff_t targ_ptrdiff_t;
+
+alias cfloat Complex_f;
+alias cdouble Complex_d;
+alias creal Complex_ld;
+
+extern(C) extern __gshared targ_size_t localsize;
+extern(C) extern __gshared targ_size_t Toff;
+extern(C) extern __gshared targ_size_t Poff;
+extern(C) extern __gshared targ_size_t Aoff;
+extern(C) extern __gshared targ_size_t Poffset;
+extern(C) extern __gshared targ_size_t funcoffset;
+extern(C) extern __gshared targ_size_t framehandleroffset;
+extern(C) extern __gshared targ_size_t Aoffset;
+extern(C) extern __gshared targ_size_t Toffset;
+extern(C) extern __gshared targ_size_t EEoffset;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/template_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,31 @@
+module dmd.backend.template_t;
+
+/***********************************
+ * Special information for class templates.
+ */
+
+struct template_t
+{
+/+
+    symlist_t     TMinstances;	// list of Symbols that are instances
+    param_t	 *TMptpl;	// template-parameter-list
+    struct token_t *TMbody;	// tokens making up class body
+    unsigned TMsequence;	// sequence number at point of definition
+    list_t TMmemberfuncs;	// templates for member functions (list of TMF's)
+    list_t TMexplicit;		// list of TME's: primary member template explicit specializations
+    list_t TMnestedexplicit;	// list of TMNE's: primary member template nested explicit specializations
+    Symbol *TMnext;		// threaded list of template classes headed
+				// up by template_class_list
+    enum_TK        TMtk;	// TKstruct, TKclass or TKunion
+    int		   TMflags;	// STRxxx flags
+
+    symbol *TMprimary;		// primary class template
+    symbol *TMpartial;		// next class template partial specialization
+    param_t *TMptal;		// template-argument-list for partial specialization
+				// (NULL for primary class template)
+    list_t TMfriends;		// list of Classsym's for which any instantiated
+				// classes of this template will be friends of
+    list_t TMnestedfriends;	// list of TMNF's
+    int TMflags2;		// !=0 means dummy template created by template_createargtab()
++/
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/token_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,3 @@
+module dmd.backend.token_t;
+
+struct token_t;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/backend/vec_t.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,4 @@
+module dmd.backend.vec_t;
+
+alias uint vec_base_t;			/* base type of vector	*/
+alias vec_base_t* vec_t;
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/codegen/Util.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1149 @@
+module dmd.codegen.Util;
+
+import dmd.Loc;
+import dmd.IRState;
+import dmd.Type;
+import dmd.Array;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.Identifier;
+import dmd.RET;
+import dmd.TY;
+import dmd.LINK;
+import dmd.Expression;
+import dmd.Argument;
+import dmd.STC;
+import dmd.Global;
+import dmd.InterfaceDeclaration;
+import dmd.AggregateDeclaration;
+import dmd.AttribDeclaration;
+import dmd.TupleDeclaration;
+import dmd.StructDeclaration;
+import dmd.VarDeclaration;
+import dmd.ClassDeclaration;
+import dmd.TemplateMixin;
+import dmd.TypedefDeclaration;
+import dmd.ExpInitializer;
+import dmd.TypeFunction;
+import dmd.TypeStruct;
+import dmd.TypeSArray;
+import dmd.TOK;
+import dmd.Util;
+import dmd.LabelStatement;
+import dmd.DsymbolExp;
+import dmd.LabelDsymbol;
+import dmd.backend.elem;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.Classsym;
+import dmd.backend.SC;
+import dmd.backend.FL;
+import dmd.backend.SFL;
+import dmd.backend.STR;
+import dmd.backend.TYM;
+import dmd.backend.TF;
+import dmd.backend.OPER;
+import dmd.backend.mTYman;
+import dmd.backend.TYFL;
+import dmd.backend.mTY;
+import dmd.backend.Symbol;
+import dmd.backend.Blockx;
+import dmd.backend.RTLSYM;
+import dmd.backend.block;
+import dmd.backend.LIST;
+
+import std.string;
+import core.stdc.string;
+
+/************************************
+ * 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;
+    RET retmethod;
+    int reverse;
+    TypeFunction tf;
+    OPER op;
+
+static if (false) {
+    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());
+}
+
+    t = t.toBasetype();
+    if (t.ty == TY.Tdelegate)
+    {
+		// A delegate consists of:
+		//	{ Object *this; Function *funcptr; }
+		assert(!fd);
+		assert(t.nextOf().ty == TY.Tfunction);
+		tf = cast(TypeFunction)t.nextOf();
+		ethis = ec;
+		ec = el_same(&ethis);
+		ethis = el_una(OPER.OP64_32, TYM.TYnptr, ethis);	// get this
+		ec = array_toPtr(t, ec);		// get funcptr
+		ec = el_una(OPER.OPind, tf.totym(), ec);
+    }
+    else
+    {	
+		assert(t.ty == TY.Tfunction);
+		tf = cast(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 == LINK.LINKd && tf.varargs == 1);
+
+		for (i = 0; i < arguments.dim ; i++)
+		{   
+			Expression arg;
+			elem* ea;
+
+			arg = cast(Expression)arguments.data[i];
+			//printf("\targ[%d]: %s\n", i, arg.toChars());
+
+			size_t nparams = Argument.dim(tf.parameters);
+			if (i - j < nparams && i >= j)
+			{
+				Argument p = Argument.getNth(tf.parameters, i - j);
+
+				if (p.storageClass & (STC.STCout | STC.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 (tybasic(ea.Ety) == TYM.TYstruct)
+			{
+				ea = el_una(OPER.OPstrpar, TYM.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 == RET.RETstack)
+    {
+		if (!ehidden)
+		{   
+			// Don't have one, so create one
+			type* tt;
+
+			if (tf.next.toBasetype().ty == TY.Tstruct)
+				tt = tf.next.toCtype();
+			else
+				tt = type_fake(tf.next.totym());
+
+			Symbol* stmp = symbol_genauto(tt);
+			ehidden = el_ptr(stmp);
+		}
+		if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) && tf.linkage != LINK.LINKd) {
+			;	// ehidden goes last on Linux/OSX C++
+		} else {
+			if (ep)
+			{
+static if (false) { // BUG: implement
+				if (reverse && type_mangle(tfunc) == mTYman.mTYman_cpp) {
+					ep = el_param(ehidden,ep);
+				} else {
+					ep = el_param(ep,ehidden);
+				}
+} else {
+				ep = el_param(ep,ehidden);
+}
+			}
+			else
+			ep = ehidden;
+			ehidden = null;
+		}
+    }
+
+    if (fd && fd.isMember2())
+    {
+		InterfaceDeclaration intd;
+		Symbol* sfunc;
+		AggregateDeclaration ad;
+
+		ad = fd.isThis();
+		if (ad)
+		{
+			ethis = ec;
+			if (ad.isStructDeclaration() && tybasic(ec.Ety) != TYM.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;
+			uint vindex;
+
+			assert(ethis);
+			ev = el_same(&ethis);
+			ev = el_una(OPER.OPind, TYM.TYnptr, ev);
+			vindex = fd.vtblIndex;
+
+			// Build *(ev + vindex * 4)
+			ec = el_bin(OPER.OPadd, TYM.TYnptr, ev, el_long(TYM.TYint, vindex * 4));
+			ec = el_una(OPER.OPind, TYM.TYnptr, ec);
+			ec = el_una(OPER.OPind, tybasic(sfunc.Stype.Tty), ec);
+		}
+    }
+    else if (fd && fd.isNested())
+    {
+		assert(!ethis);
+		ethis = getEthis(Loc(0), irs, fd);
+    }
+
+    ep = el_param(ep, ethis);
+    if (ehidden)
+		ep = el_param(ep, ehidden);	// if ehidden goes last
+
+    tyret = tret.totym();
+
+    // Look for intrinsic functions
+    if (ec.Eoper == OPER.OPvar && (op = intrinsic_oper(ec.EV.sp.Vsym.Sident.ptr)) != OPER.OPMAX)
+    {
+		el_free(ec);
+		if (OTbinary(op))
+		{
+			ep.Eoper = op;
+			ep.Ety = tyret;
+			e = ep;
+			if (op == OPER.OPscale)
+			{
+				elem *et = e.E1;
+				e.E1() = el_una(OPER.OPd_ld, TYM.TYldouble, e.E1);
+				e.E1() = el_una(OPER.OPs32_d, TYM.TYdouble, e.E2);
+				e.E2() = et;
+			}
+			else if (op == OPER.OPyl2x || op == OPER.OPyl2xp1)
+			{
+				elem *et = e.E1;
+				e.E1() = e.E2;
+				e.E2() = et;
+			}
+		}
+		else
+			e = el_una(op,tyret,ep);
+    }
+    else if (ep)
+		e = el_bin(tf.ispure ? OPER.OPcallns : OPER.OPcall, tyret, ec, ep);
+    else
+		e = el_una(tf.ispure ? OPER.OPucallns : OPER.OPucall, tyret, ec);
+
+    if (retmethod == RET.RETstack)
+    {
+		e.Ety = TYM.TYnptr;
+		e = el_una(OPER.OPind, tyret, e);
+    }
+
+version (DMDV2) {
+    if (tf.isref)
+    {
+		e.Ety = TYM.TYnptr;
+		e = el_una(OPER.OPind, tyret, e);
+    }
+}
+
+    if (tybasic(tyret) == TYM.TYstruct)
+    {
+		e.Enumbytes = cast(uint)tret.size();
+    }
+
+    e = el_combine(eside, e);
+    return e;
+}
+
+/**************************************
+ * Fake a struct symbol.
+ */
+
+Classsym* fake_classsym(Identifier id)
+{   
+	TYPE* t;
+    Classsym* scc;
+
+    scc = cast(Classsym*)symbol_calloc(toStringz(id.toChars()));
+    scc.Sclass = SC.SCstruct;
+    scc.Sstruct = struct_calloc();
+    scc.Sstruct.Sstructalign = 8;
+    //scc.Sstruct.ptrtype = TYM.TYnptr;
+    scc.Sstruct.Sflags = STR.STRglobal;
+
+    t = type_alloc(TYM.TYstruct);
+    t.Tflags |= TF.TFsizeunknown | TF.TFforward;
+    t.Ttag = scc;		// structure tag name
+    assert(t.Tmangle == 0);
+    t.Tmangle = mTYman.mTYman_d;
+    t.Tcount++;
+    scc.Stype = t;
+    slist_add(scc);
+    return scc;
+}
+
+/******************************************
+ * Return elem that evaluates to the static frame pointer for function fd.
+ * If fd is a member function, the returned expression will compute the value
+ * of fd's 'this' variable.
+ * This routine is critical for implementing nested functions.
+ */
+
+elem* getEthis(Loc loc, IRState* irs, Dsymbol fd)
+{
+	elem* ethis;
+    FuncDeclaration thisfd = irs.getFunc();
+    Dsymbol fdparent = fd.toParent2();
+
+    //printf("getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", thisfd.toChars(), fd.toChars(), fdparent.toChars());
+    if (fdparent == thisfd)
+    {	
+		/* Going down one nesting level, i.e. we're calling
+		 * a nested function from its enclosing function.
+		 */
+///version (DMDV2) {
+		if (irs.sclosure)
+			ethis = el_var(irs.sclosure);
+		else
+///}
+		if (irs.sthis)
+		{   
+			// We have a 'this' pointer for the current function
+			ethis = el_var(irs.sthis);
+
+			/* If no variables in the current function's frame are
+			 * referenced by nested functions, then we can 'skip'
+			 * adding this frame into the linked list of stack
+			 * frames.
+			 */
+version (DMDV2) {
+			bool cond = (thisfd.closureVars.dim != 0);
+} else {
+			bool cond = thisfd.nestedFrameRef;
+}
+			if (cond)
+			{	
+				/* Local variables are referenced, can't skip.
+				 * Address of 'this' gives the 'this' for the nested
+				 * function
+				 */
+				ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis);
+			}
+		}
+		else
+		{   
+			/* No 'this' pointer for current function,
+			 * use null if no references to the current function's frame
+			 */
+			ethis = el_long(TYM.TYnptr, 0);
+version (DMDV2) {
+			bool cond = (thisfd.closureVars.dim != 0);
+} else {
+			bool cond = thisfd.nestedFrameRef;
+}
+			if (cond)
+			{	
+				/* OPframeptr is an operator that gets the frame pointer
+				 * for the current function, i.e. for the x86 it gets
+				 * the value of EBP
+				 */
+				ethis.Eoper = OPER.OPframeptr;
+			}
+		}
+    }
+    else
+    {
+		if (!irs.sthis)		// if no frame pointer for this function
+		{
+			fd.error(loc, "is a nested function and cannot be accessed from %s", irs.getFunc().toChars());
+			ethis = el_long(TYM.TYnptr, 0);	// error recovery
+		}
+		else
+		{
+			ethis = el_var(irs.sthis);
+			Dsymbol s = thisfd;
+			while (fd != s)
+			{	
+				/* Go up a nesting level, i.e. we need to find the 'this'
+				 * of an enclosing function.
+				 * Our 'enclosing function' may also be an inner class.
+				 */
+
+				//printf("\ts = '%s'\n", s.toChars());
+				thisfd = s.isFuncDeclaration();
+				if (thisfd)
+				{   
+					/* Enclosing function is a function.
+					 */
+					if (fdparent == s.toParent2())
+						break;
+
+					if (thisfd.isNested())
+					{
+						FuncDeclaration p = s.toParent2().isFuncDeclaration();
+version (DMDV2) {
+						bool cond = !p || p.closureVars.dim;
+} else {
+						bool cond = !p || p.nestedFrameRef;
+}
+						if (cond) {
+							ethis = el_una(OPER.OPind, TYM.TYnptr, ethis);
+						}
+					}
+					else if (thisfd.vthis)
+					{
+						;
+					}
+					else
+					{
+						// Error should have been caught by front end
+						assert(0);
+					}
+				}
+				else
+				{   
+					/* Enclosed by an aggregate. That means the current
+					 * function must be a member function of that aggregate.
+					 */
+					ClassDeclaration cd;
+					StructDeclaration sd;
+					AggregateDeclaration ad = s.isAggregateDeclaration();
+
+					if (!ad)
+						goto Lnoframe;
+
+					cd = s.isClassDeclaration();
+
+					if (cd && fd.isClassDeclaration() && fd.isClassDeclaration().isBaseOf(cd, null))
+						break;
+
+					sd = s.isStructDeclaration();
+
+					if (fd == sd)
+						break;
+
+					if (!ad.isNested() || !ad.vthis)
+					{
+					  Lnoframe:
+						irs.getFunc().error(loc, "cannot get frame pointer to %s", fd.toChars());
+						return el_long(TYM.TYnptr, 0);	// error recovery
+					}
+
+					ethis = el_bin(OPER.OPadd, TYM.TYnptr, ethis, el_long(TYM.TYint, ad.vthis.offset));
+					ethis = el_una(OPER.OPind, TYM.TYnptr, ethis);
+
+					if (fdparent == s.toParent2())
+						break;
+
+					if (auto fdd = s.toParent2().isFuncDeclaration())
+					{
+						/* Remember that frames for functions that have no
+						 * nested references are skipped in the linked list
+						 * of frames.
+						 */
+version (DMDV2) {
+						bool cond = (fdd.closureVars.dim != 0);
+} else {
+						bool cond = fdd.nestedFrameRef;						
+}
+						if (cond) {
+							ethis = el_una(OPER.OPind, TYM.TYnptr, ethis);
+						}
+						break;
+					}
+				}
+				s = s.toParent2();
+				assert(s);
+			}
+		}
+    }
+
+static if (false) {
+    printf("ethis:\n");
+    elem_print(ethis);
+    printf("\n");
+}
+
+    return ethis;
+}
+
+/*****************************************
+ * 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 TY.Tpointer:
+	    break;
+
+	case TY.Tarray:
+	case TY.Tdelegate:
+	    if (e.Eoper == OPER.OPcomma)
+	    {
+			e.Ety = TYM.TYnptr;
+			e.E2() = array_toPtr(t, e.E2);
+	    }
+	    else if (e.Eoper == OPER.OPpair)
+	    {
+			e.Eoper = OPER.OPcomma;
+			e.Ety = TYM.TYnptr;
+	    }
+	    else
+	    {
+static if (true) {
+			e = el_una(OPER.OPmsw, TYM.TYnptr, e);
+} else {
+			e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+			e = el_bin(OPER.OPadd, TYM.TYnptr, e, el_long(TYM.TYint, 4));
+			e = el_una(OPER.OPind, TYM.TYnptr, e);
+}
+	    }
+	    break;
+
+	case TY.Tsarray:
+	    e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+	    break;
+
+	default:
+	    ///t.print();
+	    assert(0);
+    }
+    return e;
+}
+
+/*******************************************
+ * Take address of an elem.
+ */
+
+elem* addressElem(elem* e, Type t)
+{
+    elem** pe;
+
+    //printf("addressElem()\n");
+
+    for (pe = &e; (*pe).Eoper == OPER.OPcomma; pe = &(*pe).E2()) {
+		;
+	}
+
+    if ((*pe).Eoper != OPER.OPvar && (*pe).Eoper != OPER.OPind)
+    {
+		Symbol* stmp;
+		elem* eeq;
+		elem* ee = *pe;
+		type* tx;
+
+		// Convert to ((tmp=ee),tmp)
+		TY ty;
+		if (t && ((ty = t.toBasetype().ty) == TY.Tstruct || ty == TY.Tsarray))
+			tx = t.toCtype();
+		else
+			tx = type_fake(ee.Ety);
+		stmp = symbol_genauto(tx);
+		eeq = el_bin(OPER.OPeq,ee.Ety,el_var(stmp),ee);
+
+		if (tybasic(ee.Ety) == TYM.TYstruct)
+		{
+			eeq.Eoper = OPER.OPstreq;
+			eeq.Enumbytes = ee.Enumbytes;
+		}
+		else if (tybasic(ee.Ety) == TYM.TYarray)
+		{
+			eeq.Eoper = OPER.OPstreq;
+			eeq.Ety = TYM.TYstruct;
+			eeq.Ejty = cast(ubyte)eeq.Ety;
+			eeq.Enumbytes = cast(uint)t.size();
+		}
+		*pe = el_bin(OPER.OPcomma, ee.Ety, eeq, el_var(stmp));
+    }
+
+    e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+    return e;
+}
+
+/*******************************************
+ * Convert intrinsic function to operator.
+ * Returns that operator, -1 if not an intrinsic function.
+ */
+
+extern (C++) extern int intrinsic_op(char* name);
+ 
+OPER intrinsic_oper(const(char)* name)
+{
+	int result = intrinsic_op(cast(char*)name);
+	if (result == -1) return OPER.OPMAX;
+	return cast(OPER)result;
+}
+
+/**************************************
+ */
+
+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 = cast(Dsymbol)decl.data[i];
+				e = el_combine(e, Dsymbol_toElem(s, irs));
+			}
+		}
+    }
+    else if ((vd = s.isVarDeclaration()) !is null)
+    {
+		s = s.toAlias();
+		if (s != vd)
+			return Dsymbol_toElem(s, irs);
+		if (vd.isStatic() || vd.storage_class & (STC.STCextern | STC.STCtls | STC.STCgshared))
+			vd.toObjFile(0);
+		else
+		{
+			sp = s.toSymbol();
+			symbol_add(sp);
+			//printf("\tadding symbol '%s'\n", sp.Sident);
+			if (vd.init)
+			{
+				ExpInitializer ie = vd.init.isExpInitializer();
+				if (ie) {
+					e = ie.exp.toElem(irs);
+				}
+			}
+		}
+    }
+    else if ((cd = s.isClassDeclaration()) !is null)
+    {
+		irs.deferToObj.push(cast(void*)s);
+    }
+    else if ((sd = s.isStructDeclaration()) !is null)
+    {
+		irs.deferToObj.push(cast(void*)sd);
+    }
+    else if ((fd = s.isFuncDeclaration()) !is null)
+    {
+		//printf("function %s\n", fd.toChars());
+		irs.deferToObj.push(cast(void*)fd);
+    }
+    else if ((tm = s.isTemplateMixin()) !is null)
+    {
+		//printf("%s\n", tm.toChars());
+		if (tm.members)
+		{
+			for (size_t i = 0; i < tm.members.dim; i++)
+			{
+				Dsymbol sm = cast(Dsymbol)tm.members.data[i];
+				e = el_combine(e, Dsymbol_toElem(sm, irs));
+			}
+		}
+    }
+    else if ((td = s.isTupleDeclaration()) !is null)
+    {
+		for (size_t i = 0; i < td.objects.dim; i++)
+		{   
+			Object o = cast(Object)td.objects.data[i];
+			///if (o.dyncast() == DYNCAST_EXPRESSION)
+			if (Expression eo = cast(Expression)o)
+			{	
+				if (eo.op == TOK.TOKdsymbol)
+				{   
+					DsymbolExp se = cast(DsymbolExp)eo;
+					e = el_combine(e, Dsymbol_toElem(se.s, irs));
+				}
+			}
+		}
+    }
+    else if ((tyd = s.isTypedefDeclaration()) !is null)
+    {
+		irs.deferToObj.push(cast(void*)tyd);
+    }
+
+    return e;
+}
+
+/**************************************
+ * Given an expression e that is an array,
+ * determine and set the 'length' variable.
+ * Input:
+ *	lengthVar	Symbol of 'length' variable
+ *	&e	expression that is the array
+ *	t1	Type of the array
+ * Output:
+ *	e	is rewritten to avoid side effects
+ * Returns:
+ *	expression that initializes 'length'
+ */
+
+elem* resolveLengthVar(VarDeclaration lengthVar, elem** pe, Type t1)
+{
+    //printf("resolveLengthVar()\n");
+    elem* einit = null;
+
+    if (lengthVar && !(lengthVar.storage_class & STC.STCconst))
+    {   
+		elem* elength;
+		Symbol* slength;
+
+		if (t1.ty == TY.Tsarray)
+		{   
+			TypeSArray tsa = cast(TypeSArray)t1;
+			long length = tsa.dim.toInteger();
+
+			elength = el_long(TYM.TYuint, length);
+			goto L3;
+		}
+		else if (t1.ty == TY.Tarray)
+		{
+			elength = *pe;
+			*pe = el_same(&elength);
+			elength = el_una(OPER.OP64_32, TYM.TYuint, elength);
+
+		L3:
+			slength = lengthVar.toSymbol();
+			//symbol_add(slength);
+
+			einit = el_bin(OPER.OPeq, TYM.TYuint, el_var(slength), elength);
+		}
+    }
+    return einit;
+}
+
+/*******************************************
+ * Set an array pointed to by eptr to evalue:
+ *	eptr[0..edim] = evalue;
+ * Input:
+ *	eptr	where to write the data to
+ *	evalue	value to write
+ *	edim	number of times to write evalue to eptr[]
+ *	tb	type of evalue
+ */
+
+elem* setArray(elem* eptr, elem* edim, Type tb, elem* evalue, IRState* irs, int op)
+{   
+	int r;
+    elem* e;
+    int sz = cast(int)tb.size();
+
+    if (tb.ty == TY.Tfloat80 || tb.ty == TY.Timaginary80)
+		r = RTLSYM.RTLSYM_MEMSET80;
+    else if (tb.ty == TY.Tcomplex80)
+		r = RTLSYM.RTLSYM_MEMSET160;
+    else if (tb.ty == TY.Tcomplex64)
+		r = RTLSYM.RTLSYM_MEMSET128;
+    else
+    {
+		switch (sz)
+		{
+			case 1:	 r = RTLSYM.RTLSYM_MEMSET8;		break;
+			case 2:	 r = RTLSYM.RTLSYM_MEMSET16;	break;
+			case 4:	 r = RTLSYM.RTLSYM_MEMSET32;	break;
+			case 8:	 r = RTLSYM.RTLSYM_MEMSET64;	break;
+			default: r = RTLSYM.RTLSYM_MEMSETN;		break;
+		}
+
+		/* Determine if we need to do postblit
+		 */
+		if (op != TOK.TOKblit)
+		{
+			StructDeclaration sd = needsPostblit(tb);
+			if (sd)
+			{   
+				/* Need to do postblit.
+				 *   void *_d_arraysetassign(void *p, void *value, int dim, TypeInfo ti);
+				 */
+				r = (op == TOK.TOKconstruct) ? RTLSYM.RTLSYM_ARRAYSETCTOR : RTLSYM.RTLSYM_ARRAYSETASSIGN;
+				evalue = el_una(OPER.OPaddr, TYM.TYnptr, evalue);
+				Expression ti = tb.getTypeInfo(null);
+				elem* eti = ti.toElem(irs);
+				e = el_params(eti, edim, evalue, eptr, null);
+				e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[r]), e);
+				return e;
+			}
+		}
+
+		if (r == RTLSYM.RTLSYM_MEMSETN)
+		{
+			// void *_memsetn(void *p, void *value, int dim, int sizelem)
+			evalue = el_una(OPER.OPaddr, TYM.TYnptr, evalue);
+			elem *esz = el_long(TYM.TYint, sz);
+			e = el_params(esz, edim, evalue, eptr, null);
+			e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[r]), e);
+			return e;
+		}
+    }
+    if (sz > 1 && sz <= 8 && evalue.Eoper == OPER.OPconst && el_allbits(evalue, 0))
+    {
+		r = RTLSYM.RTLSYM_MEMSET8;
+		edim = el_bin(OPER.OPmul, TYM.TYuint, edim, el_long(TYM.TYuint, sz));
+    }
+
+    if (tybasic(evalue.Ety) == TYM.TYstruct)
+    {
+		evalue = el_una(OPER.OPstrpar, TYM.TYstruct, evalue);
+		evalue.Enumbytes = evalue.E1.Enumbytes;
+		assert(evalue.Enumbytes);
+    }
+
+    // Be careful about parameter side effect ordering
+    if (r == RTLSYM.RTLSYM_MEMSET8)
+    {
+		e = el_param(edim, evalue);
+		e = el_bin(OPER.OPmemset, TYM.TYnptr, eptr, e);
+    }
+    else
+    {
+		e = el_params(edim, evalue, eptr, null);
+		e = el_bin(OPER.OPcall, TYM.TYnptr, el_var(rtlsym[r]), e);
+    }
+    return e;
+}
+
+/*************************
+ * Initialize the hidden aggregate member, vthis, with
+ * the context pointer.
+ * Returns:
+ *	*(ey + ad.vthis.offset) = this;
+ */
+version (DMDV2) {
+	elem* setEthis(Loc loc, IRState* irs, elem* ey, AggregateDeclaration ad)
+	{
+		elem* ethis;
+		FuncDeclaration thisfd = irs.getFunc();
+		int offset = 0;
+		Dsymbol cdp = ad.toParent2();	// class/func we're nested in
+
+		//printf("setEthis(ad = %s, cdp = %s, thisfd = %s)\n", ad.toChars(), cdp.toChars(), thisfd.toChars());
+
+		if (cdp is thisfd)
+		{   
+			/* Class we're new'ing is a local class in this function:
+			 *	void thisfd() { class ad { } }
+			 */
+			if (irs.sclosure)
+				ethis = el_var(irs.sclosure);
+			else if (irs.sthis)
+			{
+///	version (DMDV2) {
+				if (thisfd.closureVars.dim)
+///	} else {
+///				if (thisfd.nestedFrameRef)
+///	}
+				{
+					ethis = el_ptr(irs.sthis);
+				}
+				else
+					ethis = el_var(irs.sthis);
+			}
+			else
+			{
+				ethis = el_long(TYM.TYnptr, 0);
+///	version (DMDV2) {
+				if (thisfd.closureVars.dim)
+///	} else {
+///				if (thisfd.nestedFrameRef)
+///	}
+				{
+					ethis.Eoper = OPER.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, ad.toParent2());
+			ethis = el_una(OPER.OPaddr, TYM.TYnptr, ethis);
+		}
+
+		ey = el_bin(OPER.OPadd, TYM.TYnptr, ey, el_long(TYM.TYint, ad.vthis.offset));
+		ey = el_una(OPER.OPind, TYM.TYnptr, ey);
+		ey = el_bin(OPER.OPeq,  TYM.TYnptr, ey, ethis);
+
+		return ey;
+	}
+}
+
+/********************************************
+ * Determine if t is an array of structs that need a postblit.
+ */
+StructDeclaration needsPostblit(Type t)
+{
+    t = t.toBasetype();
+
+    while (t.ty == TY.Tsarray)
+		t = t.nextOf().toBasetype();
+
+    if (t.ty == TY.Tstruct)
+    {   
+		StructDeclaration sd = (cast(TypeStruct)t).sym;
+		if (sd.postblit)
+			return sd;
+    }
+
+    return null;
+}
+
+/*****************************************
+ * Convert array to a dynamic array.
+ */
+
+elem* array_toDarray(Type t, elem* e)
+{
+    uint dim;
+    elem* ef = null;
+    elem* ex;
+
+    //printf("array_toDarray(t = %s)\n", t.toChars());
+    //elem_print(e);
+    t = t.toBasetype();
+    switch (t.ty)
+    {
+		case TY.Tarray:
+			break;
+
+		case TY.Tsarray:
+			e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+			dim = cast(uint)(cast(TypeSArray)t).dim.toInteger();
+			e = el_pair(TYM.TYullong, el_long(TYM.TYint, dim), e);
+			break;
+
+		default:
+		L1:
+			switch (e.Eoper)
+			{
+				case OPER.OPconst:
+				{
+					size_t len = tysize[tybasic(e.Ety)];
+					elem* es = el_calloc();
+					es.Eoper = OPER.OPstring;
+
+					// Match MEM_PH_FREE for OPstring in ztc\el.c
+					es.EV.ss.Vstring = cast(char*)malloc(len);	///
+					memcpy(es.EV.ss.Vstring, &e.EV, len);
+
+					es.EV.ss.Vstrlen = len;
+					es.Ety = TYM.TYnptr;
+					e = es;
+					break;
+				}
+
+				case OPER.OPvar:
+					e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+					break;
+
+				case OPER.OPcomma:
+					ef = el_combine(ef, e.E1);
+					ex = e;
+					e = e.E2;
+					ex.E1() = null;
+					ex.E2() = null;
+					el_free(ex);
+					goto L1;
+
+				case OPER.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 == TYM.TYstruct)
+					{
+						if (e.Enumbytes == 4)
+							ty = TYM.TYint;
+						else if (e.Enumbytes == 8)
+							ty = TYM.TYllong;
+					}
+					e.Ety = ty;
+					stmp = symbol_genauto(type_fake(ty));
+					e = el_bin(OPER.OPeq, e.Ety, el_var(stmp), e);
+					e = el_bin(OPER.OPcomma, TYM.TYnptr, e, el_una(OPER.OPaddr, TYM.TYnptr, el_var(stmp)));
+					break;
+				}
+			}
+			dim = 1;
+			e = el_pair(TYM.TYullong, el_long(TYM.TYint, dim), e);
+			break;
+    }
+
+    return el_combine(ef, e);
+}
+
+elem* sarray_toDarray(Loc loc, Type tfrom, Type tto, elem* e)
+{
+    //printf("sarray_toDarray()\n");
+    //elem_print(e);
+
+    elem* elen;
+    uint dim = cast(uint)(cast(TypeSArray)tfrom).dim.toInteger();
+
+    if (tto)
+    {
+		uint fsize = cast(uint)tfrom.nextOf().size();
+		uint tsize = cast(uint)tto.nextOf().size();
+
+		if ((dim * fsize) % tsize != 0)
+		{
+		  Lerr:
+			error(loc, "cannot cast %s to %s since sizes don't line up", tfrom.toChars(), tto.toChars());
+		}
+		dim = (dim * fsize) / tsize;
+	}
+
+  L1:
+    elen = el_long(TYM.TYint, dim);
+    e = el_una(OPER.OPaddr, TYM.TYnptr, e);
+    e = el_pair(TYM.TYullong, elen, e);
+    return e;
+}
+
+elem* eval_Darray(IRState* irs, Expression e)
+{
+    elem* ex = e.toElem(irs);
+    return array_toDarray(e.type, ex);
+}
+
+/***********************************************
+ * Generate code to set index into scope table.
+ */
+
+void setScopeIndex(Blockx* blx, block* b, int scope_index)
+{
+version (SEH) {
+    block_appendexp(b, nteh_setScopeTableIndex(blx, scope_index));
+}
+}
+
+/****************************************
+ * Create a static symbol we can hang DT initializers onto.
+ */
+
+Symbol* static_sym()
+{
+    Symbol* s;
+    type* t;
+
+    t = type_alloc(TYint);
+    t.Tcount++;
+    s = symbol_calloc("internal");
+    s.Sclass = SCstatic;
+    s.Sfl = FLextern;
+    s.Sflags |= SFLnodebug;
+    s.Stype = t;
+version (ELFOBJ_OR_MACHOBJ) {
+    s.Sseg = DATA;
+}
+    slist_add(s);
+    return s;
+}
+
+/**************************************
+ * Convert label to block.
+ */
+
+block* labelToBlock(Loc loc, Blockx *blx, LabelDsymbol label)
+{
+    LabelStatement s;
+
+    if (!label.statement)
+    {
+		error(loc, "undefined label %s", label.toChars());
+		return null;
+    }
+
+    s = label.statement;
+    if (!s.lblock)
+    {	
+		s.lblock = block_calloc(blx);
+		if (s.isReturnLabel)
+			s.lblock.Btry = null;
+    }
+    return s.lblock;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/condition/util/findCondition.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,22 @@
+module dmd.condition.util.findCondition;
+
+import dmd.String;
+import dmd.Array;
+import dmd.Identifier;
+
+bool findCondition(Array ids, Identifier ident)
+{
+    if (ids)
+    {
+		for (int i = 0; i < ids.dim; i++)
+		{
+			String id = cast(String)ids.data[i];
+
+			if (id.str == ident.toChars()) {
+				return true;
+			}
+		}
+    }
+
+    return false;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/declaration/Match.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,14 @@
+module dmd.declaration.Match;
+
+import dmd.FuncDeclaration;
+import dmd.MATCH;
+
+struct Match
+{
+	int count;			// number of matches found
+    MATCH last;			// match level of lastf
+    FuncDeclaration lastf;	// last matching function we found
+    FuncDeclaration nextf;	// current matching function
+    FuncDeclaration anyf;	// pick a func, any func, to use for error recovery
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Add.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,105 @@
+module dmd.expression.Add;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.Loc;
+import dmd.RealExp;
+import dmd.ComplexExp;
+import dmd.IntegerExp;
+import dmd.TOK;
+import dmd.SymOffExp;
+import dmd.Complex;
+
+Expression Add(Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+
+version (LOG) {
+    printf("Add(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
+}
+    if (type.isreal())
+    {
+		e = new RealExp(loc, e1.toReal() + e2.toReal(), type);
+    }
+    else if (type.isimaginary())
+    {
+		e = new RealExp(loc, e1.toImaginary() + e2.toImaginary(), type);
+    }
+    else if (type.iscomplex())
+    {
+		// This rigamarole is necessary so that -0.0 doesn't get
+		// converted to +0.0 by doing an extraneous add with +0.0
+		Complex!(real) c1;
+		real r1;
+		real i1;
+
+		Complex!(real) c2;
+		real r2;
+		real i2;
+
+		Complex!(real) v;
+		int x;
+
+		if (e1.type.isreal())
+		{   
+			r1 = e1.toReal();
+			x = 0;
+		}
+		else if (e1.type.isimaginary())
+		{   
+			i1 = e1.toImaginary();
+			x = 3;
+		}
+		else
+		{   
+			c1 = e1.toComplex();
+			x = 6;
+		}
+
+		if (e2.type.isreal())
+		{   
+			r2 = e2.toReal();
+		}
+		else if (e2.type.isimaginary())
+		{   
+			i2 = e2.toImaginary();
+			x += 1;
+		}
+		else
+		{   
+			c2 = e2.toComplex();
+			x += 2;
+		}
+
+		switch (x)
+		{
+			case 0+0:	v = Complex!(real)(r1 + r2, 0);			break;
+			case 0+1:	v = Complex!(real)(r1, i2);				break;
+			case 0+2:	v = Complex!(real)(r1 + c2.re, c2.im);	break;
+			case 3+0:	v = Complex!(real)(r2, i1);				break;
+			case 3+1:	v = Complex!(real)(0, i1 + i2);			break;
+			case 3+2:	v = Complex!(real)(c2.re, i1 + c2.im);	break;
+			case 6+0:	v = Complex!(real)(c1.re + r2, c1.im);	break;
+			case 6+1:	v = Complex!(real)(c1.re, c1.im + i2);	break;
+			case 6+2:	v = Complex!(real)(c1.re + c2.re, c1.im + c2.im);	break;
+		}
+		e = new ComplexExp(loc, v, type);
+    }
+    else if (e1.op == TOK.TOKsymoff)
+    {
+		SymOffExp soe = cast(SymOffExp)e1;
+		e = new SymOffExp(loc, soe.var, soe.offset + cast(uint)e2.toInteger());
+		e.type = type;
+    }
+    else if (e2.op == TOK.TOKsymoff)
+    {
+		SymOffExp soe = cast(SymOffExp)e2;
+		e = new SymOffExp(loc, soe.var, soe.offset + cast(uint)e1.toInteger());
+		e.type = type;
+    }
+    else
+		e = new IntegerExp(loc, e1.toInteger() + e2.toInteger(), type);
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/And.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,10 @@
+module dmd.expression.And;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.IntegerExp;
+
+Expression And(Type type, Expression e1, Expression e2)
+{
+    return new IntegerExp(e1.loc, e1.toInteger() & e2.toInteger(), type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/ArrayLength.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,39 @@
+module dmd.expression.ArrayLength;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.StringExp;
+import dmd.IntegerExp;
+import dmd.ArrayLiteralExp;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.AssocArrayLiteralExp;
+import dmd.GlobalExpressions;
+
+Expression ArrayLength(Type type, Expression e1)
+{
+	Expression e;
+    Loc loc = e1.loc;
+
+    if (e1.op == TOKstring)
+    {	
+		StringExp es1 = cast(StringExp)e1;
+		e = new IntegerExp(loc, es1.len, type);
+    }
+    else if (e1.op == TOKarrayliteral)
+    {
+		ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
+		size_t dim = ale.elements ? ale.elements.dim : 0;
+		e = new IntegerExp(loc, dim, type);
+    }
+    else if (e1.op == TOKassocarrayliteral)
+    {	
+		AssocArrayLiteralExp ale = cast(AssocArrayLiteralExp)e1;
+		size_t dim = ale.keys.dim;
+		e = new IntegerExp(loc, dim, type);
+    }
+    else
+		e = EXP_CANT_INTERPRET;
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Cat.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,267 @@
+module dmd.expression.Cat;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.StringExp;
+import dmd.ArrayLiteralExp;
+import dmd.Global;
+import dmd.TY;
+import dmd.Type;
+import dmd.GlobalExpressions;
+import dmd.ArrayTypes;
+import dmd.TypeSArray;
+import dmd.IntegerExp;
+
+import core.stdc.string;
+import core.stdc.stdlib;
+
+import std.contracts;
+
+/* Also return EXP_CANT_INTERPRET if this fails
+ */
+Expression Cat(Type type, Expression e1, Expression e2)
+{   
+	Expression e = EXP_CANT_INTERPRET;
+    Loc loc = e1.loc;
+	
+	Type t;
+
+    Type t1 = e1.type.toBasetype();
+    Type t2 = e2.type.toBasetype();
+
+    //printf("Cat(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
+    //printf("\tt1 = %s, t2 = %s\n", t1.toChars(), t2.toChars());
+
+    if (e1.op == TOKnull && (e2.op == TOKint64 || e2.op == TOKstructliteral))
+    {	
+		e = e2;
+		goto L2;
+    }
+    else if ((e1.op == TOKint64 || e1.op == TOKstructliteral) && e2.op == TOKnull)
+    {	
+		e = e1;
+	L2:
+		Type tn = e.type.toBasetype();
+		if (tn.ty == Tchar || tn.ty == Twchar || tn.ty == Tdchar)
+		{
+			// Create a StringExp
+			size_t len = 1;
+			int sz = cast(int)tn.size();
+			ulong v = e.toInteger();
+
+			char* s = cast(char*)malloc((len + 1) * sz);
+			memcpy(s, &v, sz);
+
+			// Add terminating 0
+			memset(s + len * sz, 0, sz);
+
+			StringExp es = new StringExp(loc, assumeUnique(s[0..len]));
+			es.sz = cast(ubyte)sz;
+			es.committed = 1;
+			e = es;
+		}
+		else
+		{   
+			// Create an ArrayLiteralExp
+			Expressions elements = new Expressions();
+			elements.push(cast(void*)e);
+			e = new ArrayLiteralExp(e.loc, elements);
+		}
+		e.type = type;
+		return e;
+    }
+    else if (e1.op == TOKstring && e2.op == TOKstring)
+    {
+		// Concatenate the strings
+		StringExp es1 = cast(StringExp)e1;
+		StringExp es2 = cast(StringExp)e2;
+		
+		size_t len = es1.len + es2.len;
+		int sz = es1.sz;
+
+		if (sz != es2.sz)
+		{
+			/* Can happen with:
+			 *   auto s = "foo"d ~ "bar"c;
+			 */
+			assert(global.errors);
+			return e;
+		}
+
+		char* s = cast(char*)malloc((len + 1) * sz);
+		memcpy(s, es1.string_, es1.len * sz);
+		memcpy(s + es1.len * sz, es2.string_, es2.len * sz);
+
+		// Add terminating 0
+		memset(s + len * sz, 0, sz);
+
+		StringExp es = new StringExp(loc, assumeUnique(s[0..len]));
+		es.sz = cast(ubyte)sz;
+		es.committed = es1.committed | es2.committed;
+		
+		Type tt;
+		if (es1.committed)
+			tt = es1.type;
+		else
+			tt = es2.type;
+
+		es.type = type;
+		e = es;
+    }
+    else if (e1.op == TOKstring && e2.op == TOKint64)
+    {
+		// Concatenate the strings
+		StringExp es1 = cast(StringExp)e1;
+		size_t len = es1.len + 1;
+		int sz = es1.sz;
+		ulong v = e2.toInteger();
+
+		char* s = cast(char*)malloc((len + 1) * sz);
+		memcpy(s, es1.string_, es1.len * sz);
+		memcpy(s + es1.len * sz, &v, sz);
+
+		// Add terminating 0
+		memset(s + len * sz, 0, sz);
+
+		StringExp es = new StringExp(loc, assumeUnique(s[0..len]));
+		es.sz = cast(ubyte)sz;
+		es.committed = es1.committed;
+		Type tt = es1.type;
+		es.type = type;
+		e = es;
+    }
+    else if (e1.op == TOKint64 && e2.op == TOKstring)
+    {
+		// Concatenate the strings
+		StringExp es2 = cast(StringExp)e2;
+		size_t len = 1 + es2.len;
+		int sz = es2.sz;
+		ulong v = e1.toInteger();
+
+		char* s = cast(char*)malloc((len + 1) * sz);
+		memcpy(s, &v, sz);
+		memcpy(s + sz, es2.string_, es2.len * sz);
+
+		// Add terminating 0
+		memset(s + len * sz, 0, sz);
+
+		StringExp es = new StringExp(loc, assumeUnique(s[0..len]));
+		es.sz = cast(ubyte)sz;
+		es.committed = es2.committed;
+		Type tt = es2.type;
+		es.type = type;
+		e = es;
+    }
+    else if (e1.op == TOKarrayliteral && e2.op == TOKarrayliteral &&
+		t1.nextOf().equals(t2.nextOf()))
+    {
+		// Concatenate the arrays
+		ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
+		ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+
+		es1 = new ArrayLiteralExp(es1.loc, cast(Expressions)es1.elements.copy());
+		es1.elements.insert(es1.elements.dim, es2.elements);
+		e = es1;
+
+		if (type.toBasetype().ty == Tsarray)
+		{
+			e.type = new TypeSArray(t1.nextOf(), new IntegerExp(loc, es1.elements.dim, Type.tindex));
+			e.type = e.type.semantic(loc, null);
+		}
+		else
+			e.type = type;
+    }
+    else if (e1.op == TOKarrayliteral && e2.op == TOKnull &&
+		t1.nextOf().equals(t2.nextOf()))
+    {
+		e = e1;
+		goto L3;
+    }
+    else if (e1.op == TOKnull && e2.op == TOKarrayliteral &&
+		t1.nextOf().equals(t2.nextOf()))
+    {
+		e = e2;
+	L3:
+		// Concatenate the array with null
+		ArrayLiteralExp es = cast(ArrayLiteralExp)e;
+
+		es = new ArrayLiteralExp(es.loc, cast(Expressions)es.elements.copy());
+		e = es;
+
+		if (type.toBasetype().ty == Tsarray)
+		{
+			e.type = new TypeSArray(t1.nextOf(), new IntegerExp(loc, es.elements.dim, Type.tindex));
+			e.type = e.type.semantic(loc, null);
+		}
+		else
+			e.type = type;
+    }
+    else if ((e1.op == TOKarrayliteral || e1.op == TOKnull) &&
+		e1.type.toBasetype().nextOf().equals(e2.type))
+    {
+		ArrayLiteralExp es1;
+		if (e1.op == TOKarrayliteral)
+		{   es1 = cast(ArrayLiteralExp)e1;
+			es1 = new ArrayLiteralExp(es1.loc, cast(Expressions)es1.elements.copy());
+			es1.elements.push(cast(void*)e2);
+		}
+		else
+		{
+			es1 = new ArrayLiteralExp(e1.loc, e2);
+		}
+		e = es1;
+
+		if (type.toBasetype().ty == Tsarray)
+		{
+			e.type = new TypeSArray(e2.type, new IntegerExp(loc, es1.elements.dim, Type.tindex));
+			e.type = e.type.semantic(loc, null);
+		}
+		else
+			e.type = type;
+    }
+    else if (e2.op == TOKarrayliteral &&
+		e2.type.toBasetype().nextOf().equals(e1.type))
+    {
+		ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+
+		es2 = new ArrayLiteralExp(es2.loc, cast(Expressions)es2.elements.copy());
+		es2.elements.shift(cast(void*)e1);
+		e = es2;
+
+		if (type.toBasetype().ty == Tsarray)
+		{
+			e.type = new TypeSArray(e1.type, new IntegerExp(loc, es2.elements.dim, Type.tindex));
+			e.type = e.type.semantic(loc, null);
+		}
+		else
+			e.type = type;
+    }
+    else if (e1.op == TOKnull && e2.op == TOKstring)
+    {
+		t = e1.type;
+		e = e2;
+		goto L1;
+    }
+    else if (e1.op == TOKstring && e2.op == TOKnull)
+    {
+		e = e1;
+		t = e2.type;
+	L1:
+		Type tb = t.toBasetype();
+		if (tb.ty == Tarray && tb.nextOf().equals(e.type))
+		{   
+			Expressions expressions = new Expressions();
+			expressions.push(cast(void*)e);
+			e = new ArrayLiteralExp(loc, expressions);
+			e.type = t;
+		}
+		if (!e.type.equals(type))
+		{   
+			StringExp se = cast(StringExp)e.copy();
+			e = se.castTo(null, type);
+		}
+    }
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Cmp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,148 @@
+module dmd.expression.Cmp;
+
+import dmd.IntegerExp;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.Type;
+import dmd.Expression;
+import dmd.StringExp;
+import dmd.GlobalExpressions;
+
+import core.stdc.string;
+
+Expression Cmp(TOK op, Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+    ulong n;
+    real r1;
+    real r2;
+
+    //printf("Cmp(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
+
+    if (e1.op == TOKstring && e2.op == TOKstring)
+    {	
+		StringExp es1 = cast(StringExp)e1;
+		StringExp es2 = cast(StringExp)e2;
+		size_t sz = es1.sz;
+		assert(sz == es2.sz);
+
+		size_t len = es1.len;
+		if (es2.len < len)
+			len = es2.len;
+
+		int cmp = memcmp(es1.string_, es2.string_, sz * len);
+		if (cmp == 0)
+			cmp = es1.len - es2.len;
+
+		switch (op)
+		{
+			case TOKlt:	n = cmp <  0;	break;
+			case TOKle:	n = cmp <= 0;	break;
+			case TOKgt:	n = cmp >  0;	break;
+			case TOKge:	n = cmp >= 0;	break;
+
+			case TOKleg:   n = 1;		break;
+			case TOKlg:	   n = cmp != 0;	break;
+			case TOKunord: n = 0;		break;
+			case TOKue:	   n = cmp == 0;	break;
+			case TOKug:	   n = cmp >  0;	break;
+			case TOKuge:   n = cmp >= 0;	break;
+			case TOKul:	   n = cmp <  0;	break;
+			case TOKule:   n = cmp <= 0;	break;
+
+			default:
+			assert(0);
+		}
+    }
+    else if (e1.isConst() != 1 || e2.isConst() != 1)
+		return EXP_CANT_INTERPRET;
+    else if (e1.type.isreal())
+    {
+		r1 = e1.toReal();
+		r2 = e2.toReal();
+		goto L1;
+    }
+    else if (e1.type.isimaginary())
+    {
+		r1 = e1.toImaginary();
+		r2 = e2.toImaginary();
+	L1:
+
+		// DMC is the only compiler I know of that handles NAN arguments
+		// correctly in comparisons.
+		switch (op)
+		{
+			case TOKlt:	   n = r1 <  r2;	break;
+			case TOKle:	   n = r1 <= r2;	break;
+			case TOKgt:	   n = r1 >  r2;	break;
+			case TOKge:	   n = r1 >= r2;	break;
+			case TOKleg:   n = r1 <>=  r2;	break;
+			case TOKlg:	   n = r1 <>   r2;	break;
+			case TOKunord: n = r1 !<>= r2;	break;
+			case TOKue:	   n = r1 !<>  r2;	break;
+			case TOKug:	   n = r1 !<=  r2;	break;
+			case TOKuge:   n = r1 !<   r2;	break;
+			case TOKul:	   n = r1 !>=  r2;	break;
+			case TOKule:   n = r1 !>   r2;	break;
+
+			default: assert(0);
+		}
+    }
+    else if (e1.type.iscomplex())
+    {
+		assert(0);
+    }
+    else
+    {   
+		long n1;
+		long n2;
+
+		n1 = e1.toInteger();
+		n2 = e2.toInteger();
+
+		if (e1.type.isunsigned() || e2.type.isunsigned())
+		{
+			switch (op)
+			{
+				case TOKlt:		n = (cast(ulong) n1) <  (cast(ulong) n2);		break;
+				case TOKle:		n = (cast(ulong) n1) <= (cast(ulong) n2);		break;
+				case TOKgt:		n = (cast(ulong) n1) >  (cast(ulong) n2);		break;
+				case TOKge:		n = (cast(ulong) n1) >= (cast(ulong) n2);		break;
+				case TOKleg:	n = 1;									break;
+				case TOKlg:		n = (cast(ulong) n1) != (cast(ulong) n2);		break;
+				case TOKunord:	n = 0;									break;
+				case TOKue:		n = (cast(ulong) n1) == (cast(ulong) n2);		break;
+				case TOKug:		n = (cast(ulong) n1) >  (cast(ulong) n2);		break;
+				case TOKuge:	n = (cast(ulong) n1) >= (cast(ulong) n2);	break;
+				case TOKul:		n = (cast(ulong) n1) <  (cast(ulong) n2);		break;
+				case TOKule:	n = (cast(ulong) n1) <= (cast(ulong) n2);	break;
+
+				default: assert(0);
+			}
+		}
+		else
+		{
+			switch (op)
+			{
+				case TOKlt:	n = n1 <  n2;		break;
+				case TOKle:	n = n1 <= n2;		break;
+				case TOKgt:	n = n1 >  n2;		break;
+				case TOKge:	n = n1 >= n2;		break;
+				case TOKleg:	n = 1;			break;
+				case TOKlg:	n = n1 != n2;		break;
+				case TOKunord:	n = 0;			break;
+				case TOKue:	n = n1 == n2;		break;
+				case TOKug:	n = n1 >  n2;		break;
+				case TOKuge:	n = n1 >= n2;	break;
+				case TOKul:	n = n1 <  n2;		break;
+				case TOKule:	n = n1 <= n2;	break;
+				default: assert(0);
+			}
+		}
+    }
+
+    e = new IntegerExp(loc, n, type);
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Com.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,12 @@
+module dmd.expression.Com;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.IntegerExp;
+import dmd.Loc;
+
+Expression Com(Type type, Expression e1)
+{
+    Loc loc = e1.loc;
+    return new IntegerExp(loc, ~e1.toInteger(), type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Div.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,93 @@
+module dmd.expression.Div;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.RealExp;
+import dmd.ComplexExp;
+import dmd.IntegerExp;
+import dmd.Complex;
+
+Expression Div(Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+
+    if (type.isfloating())
+    {
+		Complex!(real) c;
+		real r;
+
+		//e1.type.print();
+		//e2.type.print();
+		if (e2.type.isreal())
+		{
+			if (e1.type.isreal())
+			{
+				e = new RealExp(loc, e1.toReal() / e2.toReal(), type);
+				return e;
+			}
+
+			//r = e2.toReal();
+			//c = e1.toComplex();
+			//printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r);
+			r = e2.toReal();
+			c = e1.toComplex();
+			c = Complex!(real)(c.re / r, c.im / r);
+		}
+		else if (e2.type.isimaginary())
+		{
+			//r = e2.toImaginary();
+			//c = e1.toComplex();
+			//printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r);
+			r = e2.toImaginary();
+			c = e1.toComplex();
+			c = Complex!(real)(c.im / r, -c.re / r);
+		}
+		else
+		{
+			Complex!(real) c1 = e1.toComplex();
+			Complex!(real) c2 = e2.toComplex();
+			
+			real denumerator = c2.re*c2.re + c2.im*c2.im;
+			real numerator_re = c1.re*c2.re + c1.im*c2.im;
+			real numerator_im = c1.im*c2.re - c1.re*c2.im;
+
+			c = Complex!(real)(numerator_re / denumerator, numerator_im / denumerator);
+		}
+
+		if (type.isreal())
+			e = new RealExp(loc, c.re, type);
+		else if (type.isimaginary())
+			e = new RealExp(loc, c.im, type);
+		else if (type.iscomplex())
+			e = new ComplexExp(loc, c, type);
+		else
+			assert(0);
+	}
+	else
+	{   
+		long n1;
+		long n2;
+		long n;
+
+		n1 = e1.toInteger();
+		n2 = e2.toInteger();
+
+		if (n2 == 0)
+		{   
+			e2.error("divide by 0");
+			e2 = new IntegerExp(loc, 1, e2.type);
+			n2 = 1;
+		}
+
+		if (e1.type.isunsigned() || e2.type.isunsigned())
+			n = (cast(ulong) n1) / (cast(ulong) n2);
+		else
+			n = n1 / n2;
+
+		e = new IntegerExp(loc, n, type);
+    }
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Equal.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,209 @@
+module dmd.expression.Equal;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.StringExp;
+import dmd.GlobalExpressions;
+import dmd.ArrayLiteralExp;
+import dmd.StructLiteralExp;
+import dmd.Global;
+import dmd.IntegerExp;
+
+import core.stdc.string;
+
+/* Also returns EXP_CANT_INTERPRET if cannot be computed.
+ */
+Expression Equal(TOK op, Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+    bool cmp;
+    real r1;
+    real r2;
+
+    //printf("Equal(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
+
+    assert(op == TOK.TOKequal || op == TOK.TOKnotequal);
+
+    if (e1.op == TOK.TOKnull)
+    {
+		if (e2.op == TOK.TOKnull)
+			cmp = true;
+		else if (e2.op == TOK.TOKstring)
+		{   StringExp es2 = cast(StringExp)e2;
+			cmp = (0 == es2.len);
+		}
+		else if (e2.op == TOK.TOKarrayliteral)
+		{   
+			ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+			cmp = !es2.elements || (0 == es2.elements.dim);
+		}
+		else
+			return EXP_CANT_INTERPRET;
+    }
+    else if (e2.op == TOK.TOKnull)
+    {
+		if (e1.op == TOK.TOKstring)
+		{   
+			StringExp es1 = cast(StringExp)e1;
+			cmp = (0 == es1.len);
+		}
+		else if (e1.op == TOK.TOKarrayliteral)
+		{   
+			ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
+			cmp = !es1.elements || (0 == es1.elements.dim);
+		}
+		else
+			return EXP_CANT_INTERPRET;
+    }
+    else if (e1.op == TOK.TOKstring && e2.op == TOK.TOKstring)
+    {	
+		StringExp es1 = cast(StringExp)e1;
+		StringExp es2 = cast(StringExp)e2;
+
+		if (es1.sz != es2.sz)
+		{
+			assert(global.errors);
+			return EXP_CANT_INTERPRET;
+		}
+		if (es1.len == es2.len && memcmp(es1.string_, es2.string_, es1.sz * es1.len) == 0)
+			cmp = true;
+		else
+			cmp = false;
+    }
+    else if (e1.op == TOK.TOKarrayliteral && e2.op == TOK.TOKarrayliteral)
+    {   
+		ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
+		ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+
+		if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
+			cmp = true;		// both arrays are empty
+		else if (!es1.elements || !es2.elements)
+			cmp = false;
+		else if (es1.elements.dim != es2.elements.dim)
+			cmp = false;
+		else
+		{
+			for (size_t i = 0; i < es1.elements.dim; i++)
+			{   
+				Expression ee1 = cast(Expression)es1.elements.data[i];
+				Expression ee2 = cast(Expression)es2.elements.data[i];
+
+				Expression v = Equal(TOK.TOKequal, Type.tint32, ee1, ee2);
+				if (v == EXP_CANT_INTERPRET)
+					return EXP_CANT_INTERPRET;
+				long tmp = v.toInteger();
+				cmp = (tmp != 0);
+				if (!cmp)
+					break;
+			}
+		}
+    }
+    else if (e1.op == TOK.TOKarrayliteral && e2.op == TOK.TOKstring)
+    {	
+		// Swap operands and use common code
+		Expression ee = e1;
+		e1 = e2;
+		e2 = ee;
+		goto Lsa;
+    }
+    else if (e1.op == TOK.TOKstring && e2.op == TOK.TOKarrayliteral)
+    {
+     Lsa:
+		StringExp es1 = cast(StringExp)e1;
+		ArrayLiteralExp es2 = cast(ArrayLiteralExp)e2;
+		size_t dim1 = es1.len;
+		size_t dim2 = es2.elements ? es2.elements.dim : 0;
+		if (dim1 != dim2)
+			cmp = false;
+		else
+		{
+			for (size_t i = 0; i < dim1; i++)
+			{
+				ulong c = es1.charAt(i);
+				Expression ee2 = cast(Expression)es2.elements.data[i];
+				if (ee2.isConst() != 1)
+					return EXP_CANT_INTERPRET;
+				cmp = (c == ee2.toInteger());
+				if (!cmp)
+					break;
+			}
+		}
+    }
+    else if (e1.op == TOK.TOKstructliteral && e2.op == TOK.TOKstructliteral)
+    {   
+		StructLiteralExp es1 = cast(StructLiteralExp)e1;
+		StructLiteralExp es2 = cast(StructLiteralExp)e2;
+
+		if (es1.sd != es2.sd)
+			cmp = false;
+		else if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
+			cmp = true;		// both arrays are empty
+		else if (!es1.elements || !es2.elements)
+			cmp = false;
+		else if (es1.elements.dim != es2.elements.dim)
+			cmp = false;
+		else
+		{
+			cmp = true;
+			for (size_t i = 0; i < es1.elements.dim; i++)
+			{   
+				Expression ee1 = cast(Expression)es1.elements.data[i];
+				Expression ee2 = cast(Expression)es2.elements.data[i];
+
+				if (ee1 == ee2)
+					continue;
+				if (!ee1 || !ee2)
+				{   
+					cmp = false;
+					break;
+				}
+				Expression v = Equal(TOK.TOKequal, Type.tint32, ee1, ee2);
+				if (v == EXP_CANT_INTERPRET)
+					return EXP_CANT_INTERPRET;
+				long tmp = v.toInteger();
+				cmp = (tmp != 0);
+				if (!cmp)
+					break;
+			}
+		}
+    }
+///static if (false) {
+///    else if (e1.op == TOKarrayliteral && e2.op == TOKstring)
+///    {
+///    }
+///}
+    else if (e1.isConst() != 1 || e2.isConst() != 1)
+		return EXP_CANT_INTERPRET;
+    else if (e1.type.isreal())
+    {
+		r1 = e1.toReal();
+		r2 = e2.toReal();
+		goto L1;
+    }
+    else if (e1.type.isimaginary())
+    {
+		r1 = e1.toImaginary();
+		r2 = e2.toImaginary();
+	L1:
+		cmp = (r1 == r2);
+    }
+    else if (e1.type.iscomplex())
+    {
+		cmp = (e1.toComplex() == e2.toComplex());
+    }
+    else if (e1.type.isintegral())
+    {
+		cmp = (e1.toInteger() == e2.toInteger());
+    }
+    else
+		return EXP_CANT_INTERPRET;
+    if (op == TOK.TOKnotequal)
+		cmp = !cmp;
+
+    e = new IntegerExp(loc, cmp, type);
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Identity.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,42 @@
+module dmd.expression.Identity;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.SymOffExp;
+import dmd.IntegerExp;
+
+import dmd.expression.Equal;
+
+Expression Identity(TOK op, Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+    int cmp;
+
+    if (e1.op == TOK.TOKnull)
+    {
+		cmp = (e2.op == TOK.TOKnull);
+    }
+    else if (e2.op == TOK.TOKnull)
+    {
+		cmp = 0;
+    }
+    else if (e1.op == TOK.TOKsymoff && e2.op == TOK.TOKsymoff)
+    {
+		SymOffExp es1 = cast(SymOffExp)e1;
+		SymOffExp es2 = cast(SymOffExp)e2;
+
+		cmp = (es1.var == es2.var && es1.offset == es2.offset);
+    }
+    else if (e1.isConst() == 1 && e2.isConst() == 1)
+		return Equal((op == TOK.TOKidentity) ? TOK.TOKequal : TOK.TOKnotequal, type, e1, e2);
+    else
+		assert(0);
+
+    if (op == TOK.TOKnotidentity)
+		cmp ^= 1;
+
+    return new IntegerExp(loc, cmp, type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Index.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,96 @@
+module dmd.expression.Index;
+
+import dmd.Type;
+import dmd.Loc;
+import dmd.StringExp;
+import dmd.TOK;
+import dmd.Expression;
+import dmd.GlobalExpressions;
+import dmd.IntegerExp;
+import dmd.TY;
+import dmd.TypeSArray;
+import dmd.ArrayLiteralExp;
+import dmd.AssocArrayLiteralExp;
+
+import dmd.expression.Equal;
+
+/* Also return EXP_CANT_INTERPRET if this fails
+ */
+Expression Index(Type type, Expression e1, Expression e2)
+{   
+	Expression e = EXP_CANT_INTERPRET;
+    Loc loc = e1.loc;
+
+    //printf("Index(e1 = %s, e2 = %s)\n", e1.toChars(), e2.toChars());
+    assert(e1.type);
+    if (e1.op == TOKstring && e2.op == TOKint64)
+    {	
+		StringExp es1 = cast(StringExp)e1;
+		ulong i = e2.toInteger();
+
+		if (i >= es1.len)
+			e1.error("string index %ju is out of bounds [0 .. %zu]", i, es1.len);
+		else
+		{   
+			uint value = es1.charAt(cast(uint)i);
+			e = new IntegerExp(loc, value, type);
+		}
+    }
+    else if (e1.type.toBasetype().ty == Tsarray && e2.op == TOKint64)
+    {	
+		TypeSArray tsa = cast(TypeSArray)e1.type.toBasetype();
+		ulong length = tsa.dim.toInteger();
+		ulong i = e2.toInteger();
+
+		if (i >= length)
+		{   
+			e2.error("array index %ju is out of bounds %s[0 .. %ju]", i, e1.toChars(), length);
+		}
+		else if (e1.op == TOKarrayliteral && !e1.checkSideEffect(2))
+		{   
+			ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
+			e = cast(Expression)ale.elements.data[cast(uint)i];
+			e.type = type;
+		}
+    }
+    else if (e1.type.toBasetype().ty == Tarray && e2.op == TOKint64)
+    {
+		ulong i = e2.toInteger();
+
+		if (e1.op == TOKarrayliteral && !e1.checkSideEffect(2))
+		{   
+			ArrayLiteralExp ale = cast(ArrayLiteralExp)e1;
+			if (i >= ale.elements.dim)
+			{   
+				e2.error("array index %ju is out of bounds %s[0 .. %u]", i, e1.toChars(), ale.elements.dim);
+			}
+			else
+			{	
+				e = cast(Expression)ale.elements.data[cast(uint)i];
+				e.type = type;
+			}
+		}
+    }
+    else if (e1.op == TOKassocarrayliteral && !e1.checkSideEffect(2))
+    {
+		AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)e1;
+		/* Search the keys backwards, in case there are duplicate keys
+		 */
+		for (size_t i = ae.keys.dim; i;)
+		{
+			i--;
+			Expression ekey = cast(Expression)ae.keys.data[i];
+			Expression ex = Equal(TOKequal, Type.tbool, ekey, e2);
+			if (ex is EXP_CANT_INTERPRET)
+				return ex;
+			if (ex.isBool(true))
+			{	
+				e = cast(Expression)ae.values.data[i];
+				e.type = type;
+				break;
+			}
+		}
+    }
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Min.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,97 @@
+module dmd.expression.Min;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.Loc;
+import dmd.RealExp;
+import dmd.ComplexExp;
+import dmd.IntegerExp;
+import dmd.TOK;
+import dmd.SymOffExp;
+import dmd.Complex;
+
+Expression Min(Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+
+    if (type.isreal())
+    {
+		e = new RealExp(loc, e1.toReal() - e2.toReal(), type);
+    }
+    else if (type.isimaginary())
+    {
+		e = new RealExp(loc, e1.toImaginary() - e2.toImaginary(), type);
+    }
+    else if (type.iscomplex())
+    {
+		// This rigamarole is necessary so that -0.0 doesn't get
+		// converted to +0.0 by doing an extraneous add with +0.0
+		Complex!(real) c1;
+		real r1;
+		real i1;
+
+		Complex!(real) c2;
+		real r2;
+		real i2;
+
+		Complex!(real) v;
+		int x;
+
+		if (e1.type.isreal())
+		{
+			r1 = e1.toReal();
+			x = 0;
+		}
+		else if (e1.type.isimaginary())
+		{   
+			i1 = e1.toImaginary();
+			x = 3;
+		}
+		else
+		{   
+			c1 = e1.toComplex();
+			x = 6;
+		}
+
+		if (e2.type.isreal())
+		{   
+			r2 = e2.toReal();
+		}
+		else if (e2.type.isimaginary())
+		{   
+			i2 = e2.toImaginary();
+			x += 1;
+		}
+		else
+		{   
+			c2 = e2.toComplex();
+			x += 2;
+		}
+
+		switch (x)
+		{
+			case 0+0:	v = Complex!(real)(r1 - r2, 0);	break;
+			case 0+1:	v = Complex!(real)(r1, -i2);	break;
+			case 0+2:	v = Complex!(real)(r1 - c2.re, -c2.im);		break;
+			case 3+0:	v = Complex!(real)(-r2, i1);		break;
+			case 3+1:	v = Complex!(real)(0, i1 - i2);	break;
+			case 3+2:	v = Complex!(real)(c2.re, i1 - c2.im);		break;
+			case 6+0:	v = Complex!(real)(c1.re - r2, c1.im);		break;
+			case 6+1:	v = Complex!(real)(c1.re, c1.im - i2);		break;
+			case 6+2:	v = Complex!(real)(c1.re - c2.re, c1.im - c2.im);		break;
+		}
+		e = new ComplexExp(loc, v, type);
+    }
+    else if (e1.op == TOK.TOKsymoff)
+    {
+		SymOffExp soe = cast(SymOffExp)e1;
+		e = new SymOffExp(loc, soe.var, soe.offset - cast(uint)e2.toInteger());
+		e.type = type;
+    }
+    else
+    {
+		e = new IntegerExp(loc, e1.toInteger() - e2.toInteger(), type);
+    }
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Mod.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,67 @@
+module dmd.expression.Mod;
+
+import dmd.Loc;
+import dmd.Type;
+import dmd.Expression;
+import dmd.IntegerExp;
+import dmd.RealExp;
+import dmd.ComplexExp;
+import dmd.Complex;
+
+import core.stdc.math;
+
+Expression Mod(Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+
+    if (type.isfloating())
+    {
+		Complex!(real) c;
+
+		if (e2.type.isreal())
+		{   
+			real r2 = e2.toReal();
+			c = Complex!(real)(fmodl(e1.toReal(), r2), fmodl(e1.toImaginary(), r2));;
+		}
+		else if (e2.type.isimaginary())
+		{   
+			real i2 = e2.toImaginary();
+			c = Complex!(real)(fmodl(e1.toReal(), i2), fmodl(e1.toImaginary(), i2));
+		}
+		else
+			assert(0);
+
+		if (type.isreal())
+			e = new RealExp(loc, c.re, type);
+		else if (type.isimaginary())
+			e = new RealExp(loc, c.im, type);
+		else if (type.iscomplex())
+			e = new ComplexExp(loc, c, type);
+		else
+			assert(0);
+    }
+    else
+    {   
+		long n1;
+		long n2;
+		long n;
+
+		n1 = e1.toInteger();
+		n2 = e2.toInteger();
+		if (n2 == 0)
+		{   
+			e2.error("divide by 0");
+			e2 = new IntegerExp(loc, 1, e2.type);
+			n2 = 1;
+		}
+
+		if (e1.type.isunsigned() || e2.type.isunsigned())
+			n = (cast(ulong) n1) % (cast(ulong) n2);
+		else
+			n = n1 % n2;
+
+		e = new IntegerExp(loc, n, type);
+    }
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Mul.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,66 @@
+module dmd.expression.Mul;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.RealExp;
+import dmd.IntegerExp;
+import dmd.ComplexExp;
+import dmd.Loc;
+import dmd.Complex;
+
+Expression Mul(Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+
+    if (type.isfloating())
+    {   
+		Complex!(real) c;
+		real r;
+		
+		if (e1.type.isreal())
+		{
+			r = e1.toReal();
+			c = e2.toComplex();
+			c = Complex!(real)(r * c.re, r * c.im);
+		}
+		else if (e1.type.isimaginary())
+		{
+			r = e1.toImaginary();
+			c = e2.toComplex();
+			c = Complex!(real)(-r * c.im, r * c.re);
+		}
+		else if (e2.type.isreal())
+		{
+			r = e2.toReal();
+			c = e1.toComplex();
+			c = Complex!(real)(r * c.re, r * c.im);
+		}
+		else if (e2.type.isimaginary())
+		{
+			r = e2.toImaginary();
+			c = e1.toComplex();
+			c = Complex!(real)(-r * c.im, r * c.re);
+		}
+		else
+		{
+			Complex!(real) c1 = e1.toComplex();
+			Complex!(real) c2 = e2.toComplex();
+			c = Complex!(real)(c1.re * c2.re - c1.im * c2.im, c1.re * c2.im + c1.im * c2.re);
+		}
+
+		if (type.isreal())
+			e = new RealExp(loc, c.re, type);
+		else if (type.isimaginary())
+			e = new RealExp(loc, c.im, type);
+		else if (type.iscomplex())
+			e = new ComplexExp(loc, c, type);
+		else
+			assert(0);
+    }
+    else
+    {
+		e = new IntegerExp(loc, e1.toInteger() * e2.toInteger(), type);
+    }
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Neg.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,33 @@
+module dmd.expression.Neg;
+
+import dmd.Type;
+import dmd.Loc;
+import dmd.RealExp;
+import dmd.Expression;
+import dmd.ComplexExp;
+import dmd.IntegerExp;
+import dmd.Complex;
+
+Expression Neg(Type type, Expression e1)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+
+    if (e1.type.isreal())
+    {
+		e = new RealExp(loc, -e1.toReal(), type);
+    }
+    else if (e1.type.isimaginary())
+    {
+		e = new RealExp(loc, -e1.toImaginary(), type);
+    }
+    else if (e1.type.iscomplex())
+    {
+		Complex!(real) c = e1.toComplex();
+		e = new ComplexExp(loc, Complex!(real)(-c.re, -c.im), type);
+    }
+    else
+		e = new IntegerExp(loc, -e1.toInteger(), type);
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Not.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,10 @@
+module dmd.expression.Not;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.IntegerExp;
+
+Expression Not(Type type, Expression e1)
+{   
+    return new IntegerExp(e1.loc, e1.isBool(false), type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Or.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,10 @@
+module dmd.expression.Or;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.IntegerExp;
+
+Expression Or(Type type, Expression e1, Expression e2)
+{
+    return new IntegerExp(e1.loc, e1.toInteger() | e2.toInteger(), type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Ptr.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,35 @@
+module dmd.expression.Ptr;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.TOK;
+import dmd.AddrExp;
+import dmd.AddExp;
+import dmd.StructLiteralExp;
+import dmd.GlobalExpressions;
+
+Expression Ptr(Type type, Expression e1)
+{
+    //printf("Ptr(e1 = %s)\n", e1->toChars());
+    if (e1.op == TOK.TOKadd)
+    {	
+		AddExp ae = cast(AddExp)e1;
+		if (ae.e1.op == TOK.TOKaddress && ae.e2.op == TOK.TOKint64)
+		{   
+			AddrExp ade = cast(AddrExp)ae.e1;
+			if (ade.e1.op == TOK.TOKstructliteral)
+			{	
+				StructLiteralExp se = cast(StructLiteralExp)ade.e1;
+				uint offset = cast(uint)ae.e2.toInteger();
+				Expression e = se.getField(type, offset);
+				if (!e)
+					e = EXP_CANT_INTERPRET;
+
+				return e;
+			}
+		}
+    }
+
+    return EXP_CANT_INTERPRET;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Shl.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,10 @@
+module dmd.expression.Shl;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.IntegerExp;
+
+Expression Shl(Type type, Expression e1, Expression e2)
+{   
+    return new IntegerExp(e1.loc, e1.toInteger() << e2.toInteger(), type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Shr.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,52 @@
+module dmd.expression.Shr;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.Loc;
+import dmd.IntegerExp;
+import dmd.TY;
+
+Expression Shr(Type type, Expression e1, Expression e2)
+{   
+    Loc loc = e1.loc;
+
+    long value = e1.toInteger();
+    uint  count = cast(uint)e2.toInteger();
+
+    switch (e1.type.toBasetype().ty)
+    {
+		case TY.Tint8:
+			value = cast(byte)(value) >> count;
+			break;
+
+		case TY.Tuns8:
+			value = cast(ubyte)(value) >> count;
+			break;
+
+		case TY.Tint16:
+			value = cast(short)(value) >> count;
+			break;
+
+		case TY.Tuns16:
+			value = cast(ushort)(value) >> count;
+			break;
+
+		case TY.Tint32:
+			value = cast(int)(value) >> count;
+			break;
+
+		case TY.Tuns32:
+			value = cast(uint)(value) >> count;
+			break;
+
+		case TY.Tint64:
+			value = cast(long)(value) >> count;
+			break;
+
+		case TY.Tuns64:
+			value = cast(ulong)(value) >> count;
+			break;
+    }
+
+    return new IntegerExp(loc, value, type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Slice.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,79 @@
+module dmd.expression.Slice;
+
+import dmd.Expression;
+import dmd.Type;
+import dmd.Loc;
+import dmd.TOK;
+import dmd.StringExp;
+import dmd.GlobalExpressions;
+import dmd.ArrayLiteralExp;
+import dmd.ArrayTypes;
+
+import core.stdc.stdlib;
+import core.stdc.string;
+
+import std.contracts;
+
+/* Also return EXP_CANT_INTERPRET if this fails
+ */
+Expression Slice(Type type, Expression e1, Expression lwr, Expression upr)
+{   
+	Expression e = EXP_CANT_INTERPRET;
+    Loc loc = e1.loc;
+
+version (LOG) {
+    printf("Slice()\n");
+    if (lwr)
+    {	
+		printf("\te1 = %s\n", e1.toChars());
+		printf("\tlwr = %s\n", lwr.toChars());
+		printf("\tupr = %s\n", upr.toChars());
+    }
+}
+    if (e1.op == TOKstring && lwr.op == TOKint64 && upr.op == TOKint64)
+    {	
+		StringExp es1 = cast(StringExp)e1;
+		ulong ilwr = lwr.toInteger();
+		ulong iupr = upr.toInteger();
+
+		if (iupr > es1.len || ilwr > iupr)
+			e1.error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
+		else
+		{   
+			size_t len = cast(size_t)(iupr - ilwr);
+			int sz = es1.sz;
+
+			char* s = cast(char*)malloc((len + 1) * sz);
+			memcpy(s, cast(ubyte*)es1.string_ + ilwr * sz, len * sz);
+			memset(s + len * sz, 0, sz);
+
+			StringExp es = new StringExp(loc, assumeUnique(s[0..len]), es1.postfix);
+			es.sz = cast(ubyte)sz;
+			es.committed = 1;
+			es.type = type;
+			e = es;
+		}
+    }
+    else if (e1.op == TOKarrayliteral &&
+	    lwr.op == TOKint64 && upr.op == TOKint64 &&
+	    !e1.checkSideEffect(2))
+    {	
+		ArrayLiteralExp es1 = cast(ArrayLiteralExp)e1;
+		ulong ilwr = lwr.toInteger();
+		ulong iupr = upr.toInteger();
+
+		if (iupr > es1.elements.dim || ilwr > iupr)
+			e1.error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr);
+		else
+		{
+			Expressions elements = new Expressions();
+			elements.setDim(cast(uint)(iupr - ilwr));
+			memcpy(elements.data,
+			   es1.elements.data + ilwr,
+			   cast(uint)(iupr - ilwr) * (*es1.elements.data).sizeof);
+			e = new ArrayLiteralExp(e1.loc, elements);
+			e.type = type;
+		}
+    }
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Ushr.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,50 @@
+module dmd.expression.Ushr;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.Loc;
+import dmd.TY;
+import dmd.IntegerExp;
+
+Expression Ushr(Type type, Expression e1, Expression e2)
+{   
+	Expression e;
+    Loc loc = e1.loc;
+    uint count;
+    ulong value;
+
+    value = e1.toInteger();
+    count = cast(uint)e2.toInteger();
+
+	switch (e1.type.toBasetype().ty)
+    {
+		case Tint8:
+		case Tuns8:
+			assert(0);		// no way to trigger this
+			value = (value & 0xFF) >> count;
+			break;
+
+		case Tint16:
+		case Tuns16:
+			assert(0);		// no way to trigger this
+			value = (value & 0xFFFF) >> count;
+			break;
+
+		case Tint32:
+		case Tuns32:
+			value = (value & 0xFFFFFFFF) >> count;
+			break;
+
+		case Tint64:
+		case Tuns64:
+			value = cast(ulong)(value) >> count;
+			break;
+
+		default:
+			assert(0);
+    }
+
+    e = new IntegerExp(loc, value, type);
+
+    return e;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Util.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1363 @@
+module dmd.expression.Util;
+
+import dmd.Expression;
+import dmd.Loc;
+import dmd.BUILTIN;
+import dmd.Scope;
+import dmd.FuncExp;
+import dmd.DelegateExp;
+import dmd.LINK;
+import dmd.NullExp;
+import dmd.SymOffExp;
+import dmd.ExpInitializer;
+import dmd.Lexer;
+import dmd.TypeSArray;
+import dmd.TypeArray;
+import dmd.VarDeclaration;
+import dmd.VoidInitializer;
+import dmd.DeclarationExp;
+import dmd.VarExp;
+import dmd.NewExp;
+import dmd.STC;
+import dmd.WANT;
+import dmd.IndexExp;
+import dmd.AssignExp;
+import dmd.CommaExp;
+import dmd.Argument;
+import dmd.DefaultInitExp;
+import dmd.Identifier;
+import dmd.Dsymbol;
+import dmd.Global;
+import dmd.ScopeDsymbol;
+import dmd.DotIdExp;
+import dmd.DotVarExp;
+import dmd.CallExp;
+import dmd.TY;
+import dmd.MATCH;
+import dmd.TypeFunction;
+import dmd.declaration.Match;
+import dmd.ArrayTypes;
+import dmd.Declaration;
+import dmd.FuncAliasDeclaration;
+import dmd.AliasDeclaration;
+import dmd.FuncDeclaration;
+import dmd.TemplateDeclaration;
+import dmd.AggregateDeclaration;
+import dmd.IntegerExp;
+import dmd.Type;
+import dmd.TOK;
+import dmd.TypeExp;
+import dmd.TypeTuple;
+import dmd.TupleExp;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.ClassDeclaration;
+import dmd.TypeClass;
+import dmd.StructDeclaration;
+import dmd.TypeStruct;
+import dmd.MOD;
+import dmd.PROT;
+import dmd.PREC;
+import dmd.Util;
+import dmd.TypeAArray;
+import dmd.Id;
+
+import std.stdio : writef;
+
+
+/***********************************
+ * Utility to build a function call out of this reference and argument.
+ */
+Expression build_overload(Loc loc, Scope sc, Expression ethis, Expression earg, Identifier id)
+{
+    Expression e;
+
+    //printf("build_overload(id = '%s')\n", id.toChars());
+    //earg.print();
+    //earg.type.print();
+    e = new DotIdExp(loc, ethis, id);
+
+    if (earg)
+		e = new CallExp(loc, e, earg);
+    else
+		e = new CallExp(loc, e);
+
+    e = e.semantic(sc);
+    return e;
+}
+
+/***************************************
+ * Search for function funcid in aggregate ad.
+ */
+
+Dsymbol search_function(ScopeDsymbol ad, Identifier funcid)
+{
+    Dsymbol s;
+    FuncDeclaration fd;
+    TemplateDeclaration td;
+
+    s = ad.search(Loc(0), funcid, 0);
+    if (s)
+    {
+		Dsymbol s2;
+
+		//printf("search_function: s = '%s'\n", s.kind());
+		s2 = s.toAlias();
+		//printf("search_function: s2 = '%s'\n", s2.kind());
+		fd = s2.isFuncDeclaration();
+		if (fd && fd.type.ty == TY.Tfunction)
+			return fd;
+
+		td = s2.isTemplateDeclaration();
+		if (td)
+			return td;
+    }
+
+    return null;
+}
+
+/********************************************
+ * Find function in overload list that exactly matches t.
+ */
+
+/***************************************************
+ * Visit each overloaded function in turn, and call
+ * dg(param, f) on it.
+ * Exit when no more, or dg(param, f) returns 1.
+ * Returns:
+ *	0	continue
+ *	1	done
+ */
+
+int overloadApply(FuncDeclaration fstart, int delegate(FuncDeclaration) dg)
+{
+    FuncDeclaration f;
+    Declaration d;
+    Declaration next;
+
+    for (d = fstart; d; d = next)
+    {	
+		FuncAliasDeclaration fa = d.isFuncAliasDeclaration();
+
+		if (fa)
+		{
+			if (overloadApply(fa.funcalias, dg))
+				return 1;
+			next = fa.overnext;
+		}
+		else
+		{
+			AliasDeclaration a = d.isAliasDeclaration();
+
+			if (a)
+			{
+				Dsymbol s = a.toAlias();
+				next = s.isDeclaration();
+				if (next is a)
+					break;
+				if (next is fstart)
+					break;
+			}
+			else
+			{
+				f = d.isFuncDeclaration();
+				if (f is null)
+				{  
+					d.error("is aliased to a function");
+					break;		// BUG: should print error message?
+				}
+				if (dg(f))
+					return 1;
+
+				next = f.overnext;
+			}
+		}
+    }
+    return 0;
+}
+
+/********************************************
+ * Decide which function matches the arguments best.
+ */
+
+struct Param2
+{
+    Match* m;
+    Expression ethis;
+    Expressions arguments;
+	
+	int fp2(FuncDeclaration f)
+	{   
+		MATCH match;
+
+		if (f != m.lastf)		// skip duplicates
+		{
+			m.anyf = f;
+			TypeFunction tf = cast(TypeFunction)f.type;
+			match = tf.callMatch(f.needThis() ? ethis : null, arguments);
+			//printf("match = %d\n", match);
+			if (match != MATCH.MATCHnomatch)
+			{
+				if (match > m.last)
+					goto LfIsBetter;
+
+				if (match < m.last)
+					goto LlastIsBetter;
+
+				/* See if one of the matches overrides the other.
+				 */
+				if (m.lastf.overrides(f))
+					goto LlastIsBetter;
+				else if (f.overrides(m.lastf))
+					goto LfIsBetter;
+
+				/* Try to disambiguate using template-style partial ordering rules.
+				 * In essence, if f() and g() are ambiguous, if f() can call g(),
+				 * but g() cannot call f(), then pick f().
+				 * This is because f() is "more specialized."
+				 */
+				{
+					MATCH c1 = f.leastAsSpecialized(m.lastf);
+					MATCH c2 = m.lastf.leastAsSpecialized(f);
+					//printf("c1 = %d, c2 = %d\n", c1, c2);
+					if (c1 > c2)
+						goto LfIsBetter;
+					if (c1 < c2)
+						goto LlastIsBetter;
+				}
+
+			Lambiguous:
+				m.nextf = f;
+				m.count++;
+				return 0;
+
+			LfIsBetter:
+				m.last = match;
+				m.lastf = f;
+				m.count = 1;
+				return 0;
+
+			LlastIsBetter:
+				return 0;
+			}
+		}
+		return 0;
+	}
+}
+
+struct Param1
+{
+    Type t;		// type to match
+    FuncDeclaration f;	// return value
+	
+	int fp1(FuncDeclaration f)
+	{   
+		if (t.equals(f.type))
+		{	
+			this.f = f;
+			return 1;
+		}
+
+	version (DMDV2) {
+		/* Allow covariant matches, if it's just a const conversion
+		 * of the return type
+		 */
+		if (t.ty == Tfunction)
+		{   
+			TypeFunction tf = cast(TypeFunction)f.type;
+			if (tf.covariant(t) == 1 &&
+				tf.nextOf().implicitConvTo(t.nextOf()) >= MATCHconst)
+			{
+				this.f = f;
+				return 1;
+			}
+		}
+	}
+		return 0;
+	}
+}
+
+void overloadResolveX(Match* m, FuncDeclaration fstart, Expression ethis, Expressions arguments)
+{
+    Param2 p;
+    p.m = m;
+    p.ethis = ethis;
+    p.arguments = arguments;
+    overloadApply(fstart, &p.fp2);
+}
+
+void templateResolve(Match* m, TemplateDeclaration td, Scope sc, Loc loc, Objects targsi, Expression ethis, Expressions arguments)
+{
+    FuncDeclaration fd;
+
+    assert(td);
+    fd = td.deduceFunctionTemplate(sc, loc, targsi, ethis, arguments);
+    if (!fd)
+		return;
+    m.anyf = fd;
+    if (m.last >= MATCH.MATCHexact)
+    {
+		m.nextf = fd;
+		m.count++;
+    }
+    else
+    {
+		m.last = MATCH.MATCHexact;
+		m.lastf = fd;
+		m.count = 1;
+    }
+}
+
+/******************************
+ * Perform semantic() on an array of Expressions.
+ */
+
+void arrayExpressionSemantic(Expressions exps, Scope sc)
+{
+    if (exps)
+    {
+		for (size_t i = 0; i < exps.dim; i++)
+		{   
+			Expression e = cast(Expression)exps.data[i];
+
+			e = e.semantic(sc);
+			exps.data[i] = cast(void*)e;
+		}
+    }
+}
+
+/****************************************
+ * Preprocess arguments to function.
+ */
+
+void preFunctionArguments(Loc loc, Scope sc, Expressions exps)
+{
+    if (exps)
+    {
+		expandTuples(exps);
+
+		for (size_t i = 0; i < exps.dim; i++)
+		{   
+			Expression arg = cast(Expression)exps.data[i];
+
+			if (!arg.type)
+			{
+debug {
+				if (!global.gag)
+					writef("1: \n");
+}
+				arg.error("%s is not an expression", arg.toChars());
+				arg = new IntegerExp(arg.loc, 0, Type.tint32);
+			}
+
+			arg = resolveProperties(sc, arg);
+			exps.data[i] = cast(void*) arg;
+
+			//arg.rvalue();
+static if (false) {
+			if (arg.type.ty == TY.Tfunction)
+			{
+				arg = new AddrExp(arg.loc, arg);
+				arg = arg.semantic(sc);
+				exps.data[i] = cast(void*) arg;
+			}
+}
+		}
+    }
+}
+
+/*************************************************************
+ * Given var, we need to get the
+ * right 'this' pointer if var is in an outer class, but our
+ * existing 'this' pointer is in an inner class.
+ * Input:
+ *	e1	existing 'this'
+ *	ad	struct or class we need the correct 'this' for
+ *	var	the specific member of ad we're accessing
+ */
+
+Expression getRightThis(Loc loc, Scope sc, AggregateDeclaration ad, Expression e1, Declaration var)
+{
+	//printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1.toChars(), ad.toChars(), var.toChars());
+ L1:
+    Type t = e1.type.toBasetype();
+    //printf("e1.type = %s, var.type = %s\n", e1.type.toChars(), var.type.toChars());
+
+    /* If e1 is not the 'this' pointer for ad
+     */
+    if (ad && !(t.ty == TY.Tpointer && t.nextOf().ty == TY.Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) && !(t.ty == TY.Tstruct && (cast(TypeStruct)t).sym == ad))
+    {
+		ClassDeclaration cd = ad.isClassDeclaration();
+		ClassDeclaration tcd = t.isClassHandle();
+
+		/* e1 is the right this if ad is a base class of e1
+		 */
+		if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
+		{
+			/* Only classes can be inner classes with an 'outer'
+			 * member pointing to the enclosing class instance
+			 */
+			if (tcd && tcd.isNested())
+			{   
+				/* e1 is the 'this' pointer for an inner class: tcd.
+				 * Rewrite it as the 'this' pointer for the outer class.
+				 */
+
+				e1 = new DotVarExp(loc, e1, tcd.vthis);
+				e1.type = tcd.vthis.type;
+				// Do not call checkNestedRef()
+				//e1 = e1.semantic(sc);
+
+				// Skip up over nested functions, and get the enclosing
+				// class type.
+				int n = 0;
+				Dsymbol s;
+				for (s = tcd.toParent(); s && s.isFuncDeclaration(); s = s.toParent())
+				{   
+					FuncDeclaration f = s.isFuncDeclaration();
+					if (f.vthis)
+					{
+						//printf("rewriting e1 to %s's this\n", f.toChars());
+						n++;
+						e1 = new VarExp(loc, f.vthis);
+					}
+				}
+				if (s && s.isClassDeclaration())
+				{   
+					e1.type = s.isClassDeclaration().type;
+					if (n > 1)
+						e1 = e1.semantic(sc);
+				}
+				else
+					e1 = e1.semantic(sc);
+				goto L1;
+			}
+			/* Can't find a path from e1 to ad
+			 */
+			e1.error("this for %s needs to be type %s not type %s", var.toChars(), ad.toChars(), t.toChars());
+		}
+    }
+    return e1;
+}
+
+/*******************************************
+ * Given a symbol that could be either a FuncDeclaration or
+ * a function template, resolve it to a function symbol.
+ *	sc		instantiation scope
+ *	loc		instantiation location
+ *	targsi		initial list of template arguments
+ *	ethis		if !null, the 'this' pointer argument
+ *	fargs		arguments to function
+ *	flags		1: do not issue error message on no match, just return null
+ */
+
+FuncDeclaration resolveFuncCall(Scope sc, Loc loc, Dsymbol s,
+	Objects tiargs,
+	Expression ethis,
+	Expressions arguments,
+	int flags)
+{
+	if (!s)
+		return null;			// no match
+    FuncDeclaration f = s.isFuncDeclaration();
+    if (f)
+		f = f.overloadResolve(loc, ethis, arguments);
+    else
+    {	
+		TemplateDeclaration td = s.isTemplateDeclaration();
+		assert(td);
+		f = td.deduceFunctionTemplate(sc, loc, tiargs, null, arguments, flags);
+    }
+    return f;
+}
+
+/****************************************
+ * Now that we know the exact type of the function we're calling,
+ * the arguments[] need to be adjusted:
+ *	1. implicitly convert argument to the corresponding parameter type
+ *	2. add default arguments for any missing arguments
+ *	3. do default promotions on arguments corresponding to ...
+ *	4. add hidden _arguments[] argument
+ *	5. call copy constructor for struct value arguments
+ */
+
+void functionArguments(Loc loc, Scope sc, TypeFunction tf, Expressions arguments)
+{
+	uint n;
+
+    //printf("functionArguments()\n");
+    assert(arguments);
+    size_t nargs = arguments ? arguments.dim : 0;
+    size_t nparams = Argument.dim(tf.parameters);
+
+    if (nargs > nparams && tf.varargs == 0)
+	error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars());
+
+    n = (nargs > nparams) ? nargs : nparams;	// n = max(nargs, nparams)
+
+    int done = 0;
+    for (size_t i = 0; i < n; i++)
+    {
+		Expression arg;
+
+		if (i < nargs)
+			arg = cast(Expression)arguments.data[i];
+		else
+			arg = null;
+
+		Type tb;
+
+		if (i < nparams)
+		{
+			Argument p = Argument.getNth(tf.parameters, i);
+
+			if (!arg)
+			{
+				if (!p.defaultArg)
+				{
+					if (tf.varargs == 2 && i + 1 == nparams)
+						goto L2;
+
+					error(loc, "expected %d function arguments, not %d", nparams, nargs);
+					break;
+				}
+				arg = p.defaultArg;
+version (DMDV2) {
+				if (arg.op == TOK.TOKdefault)
+				{   
+					DefaultInitExp de = cast(DefaultInitExp)arg;
+					arg = de.resolve(loc, sc);
+				}
+				else
+				{
+					arg = arg.copy();
+				}
+} else {
+				arg = arg.copy();
+}
+				arguments.push(cast(void*)arg);
+				nargs++;
+			}
+
+			if (tf.varargs == 2 && i + 1 == nparams)
+			{
+				//printf("\t\tvarargs == 2, p.type = '%s'\n", p.type.toChars());
+				if (arg.implicitConvTo(p.type))
+				{
+					if (nargs != nparams)
+						error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
+					goto L1;
+				}
+				 L2:
+				tb = p.type.toBasetype();		///
+				Type tret = p.isLazyArray();
+				switch (tb.ty)
+				{
+					case TY.Tsarray:
+					case TY.Tarray:
+					{	// Create a static array variable v of type arg.type
+version (IN_GCC) {
+						/* GCC 4.0 does not like zero length arrays used like
+						   this; pass a null array value instead. Could also
+						   just make a one-element array. */
+						if (nargs - i == 0)
+						{
+							arg = new NullExp(loc);
+							break;
+						}
+}
+						Identifier id = Lexer.uniqueId("__arrayArg");
+						Type t = new TypeSArray((cast(TypeArray)tb).next, new IntegerExp(nargs - i));
+						t = t.semantic(loc, sc);
+						VarDeclaration v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
+						v.semantic(sc);
+						v.parent = sc.parent;
+						//sc.insert(v);
+
+						Expression c = new DeclarationExp(Loc(0), v);
+						c.type = v.type;
+
+						for (size_t u = i; u < nargs; u++)
+						{   
+							Expression a = cast(Expression)arguments.data[u];
+							if (tret && !(cast(TypeArray)tb).next.equals(a.type))
+								a = a.toDelegate(sc, tret);
+
+							Expression e = new VarExp(loc, v);
+							e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
+							AssignExp ae = new AssignExp(loc, e, a);
+
+			version (DMDV2) {
+							ae.op = TOK.TOKconstruct;
+			}
+
+							if (c)
+								c = new CommaExp(loc, c, ae);
+							else
+								c = ae;
+						}
+
+						arg = new VarExp(loc, v);
+						if (c)
+							arg = new CommaExp(loc, c, arg);
+						break;
+					}
+
+					case TY.Tclass:
+					{	/* Set arg to be:
+						 *	new Tclass(arg0, arg1, ..., argn)
+						 */
+						Expressions args = new Expressions();
+						args.setDim(nargs - i);
+						for (size_t u = i; u < nargs; u++)
+							args.data[u - i] = arguments.data[u];
+						arg = new NewExp(loc, null, null, p.type, args);
+						break;
+					}
+
+					default:
+						if (!arg)
+						{   
+							error(loc, "not enough arguments");
+							return;
+						}
+						break;
+				}
+
+				arg = arg.semantic(sc);
+				//printf("\targ = '%s'\n", arg.toChars());
+				arguments.setDim(i + 1);
+				done = 1;
+			}
+
+		L1:
+			if (!(p.storageClass & STC.STClazy && p.type.ty == TY.Tvoid))
+			{
+				if (p.type != arg.type)
+				{
+					//printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
+					arg = arg.implicitCastTo(sc, p.type);
+					arg = arg.optimize(WANT.WANTvalue);
+				}
+			}
+			if (p.storageClass & STC.STCref)
+			{
+				arg = arg.toLvalue(sc, arg);
+			}
+			else if (p.storageClass & STC.STCout)
+			{
+				arg = arg.modifiableLvalue(sc, arg);
+			}
+
+			// Convert static arrays to pointers
+			tb = arg.type.toBasetype();
+			if (tb.ty == TY.Tsarray)
+			{
+				arg = arg.checkToPointer();
+			}
+version (DMDV2) {
+			if (tb.ty == TY.Tstruct && !(p.storageClass & (STC.STCref | STC.STCout)))
+			{
+				arg = callCpCtor(loc, sc, arg);
+			}
+}
+
+			// Convert lazy argument to a delegate
+			if (p.storageClass & STC.STClazy)
+			{
+				arg = arg.toDelegate(sc, p.type);
+			}
+version (DMDV2) {
+			/* Look for arguments that cannot 'escape' from the called
+			 * function.
+			 */
+			if (!tf.parameterEscapes(p))
+			{
+				/* Function literals can only appear once, so if this
+				 * appearance was scoped, there cannot be any others.
+				 */
+				if (arg.op == TOK.TOKfunction)
+				{   
+					FuncExp fe = cast(FuncExp)arg;
+					fe.fd.tookAddressOf = 0;
+				}
+
+				/* For passing a delegate to a scoped parameter,
+				 * this doesn't count as taking the address of it.
+				 * We only worry about 'escaping' references to the function.
+				 */
+				else if (arg.op == TOK.TOKdelegate)
+				{   
+					DelegateExp de = cast(DelegateExp)arg;
+					if (de.e1.op == TOK.TOKvar)
+					{	
+						VarExp ve = cast(VarExp)de.e1;
+						FuncDeclaration f = ve.var.isFuncDeclaration();
+						if (f)
+						{   
+							f.tookAddressOf--;
+							//printf("tookAddressOf = %d\n", f.tookAddressOf);
+						}
+					}
+				}
+			}
+}
+		}
+		else
+		{
+			// If not D linkage, do promotions
+			if (tf.linkage != LINK.LINKd)
+			{
+				// Promote bytes, words, etc., to ints
+				arg = arg.integralPromotions(sc);
+
+				// Promote floats to doubles
+				switch (arg.type.ty)
+				{
+					case TY.Tfloat32:
+						arg = arg.castTo(sc, Type.tfloat64);
+						break;
+
+					case TY.Timaginary32:
+						arg = arg.castTo(sc, Type.timaginary64);
+						break;
+					default:
+						break;
+				}
+			}
+
+			// Convert static arrays to dynamic arrays
+			tb = arg.type.toBasetype();
+			if (tb.ty == TY.Tsarray)
+			{	
+				TypeSArray ts = cast(TypeSArray)tb;
+				Type ta = ts.next.arrayOf();
+				if (ts.size(arg.loc) == 0)
+				{   
+					arg = new NullExp(arg.loc);
+					arg.type = ta;
+				}
+				else
+				{
+					arg = arg.castTo(sc, ta);
+				}
+			}
+version (DMDV2) {
+			if (tb.ty == TY.Tstruct)
+			{
+				arg = callCpCtor(loc, sc, arg);
+			}
+
+			// Give error for overloaded function addresses
+			if (arg.op == TOK.TOKsymoff)
+			{	
+				SymOffExp se = cast(SymOffExp)arg;
+				if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
+					arg.error("function %s is overloaded", arg.toChars());
+			}
+}
+			arg.rvalue();
+		}
+		arg = arg.optimize(WANT.WANTvalue);
+		arguments.data[i] = cast(void*) arg;
+		if (done)
+			break;
+    }
+
+    // If D linkage and variadic, add _arguments[] as first argument
+    if (tf.linkage == LINK.LINKd && tf.varargs == 1)
+    {
+		Expression e = createTypeInfoArray(sc, cast(Expression*)&arguments.data[nparams], arguments.dim - nparams);
+		arguments.insert(0, cast(void*)e);
+    }
+}
+
+/****************************************
+ * Expand tuples.
+ */
+
+void expandTuples(Expressions exps)
+{
+    //printf("expandTuples()\n");
+    if (exps)
+    {
+		for (size_t i = 0; i < exps.dim; i++)
+		{   
+			Expression arg = cast(Expression)exps.data[i];
+			if (!arg)
+				continue;
+
+			// Look for tuple with 0 members
+			if (arg.op == TOK.TOKtype)
+			{	
+				TypeExp e = cast(TypeExp)arg;
+				if (e.type.toBasetype().ty == TY.Ttuple)
+				{   
+					TypeTuple tt = cast(TypeTuple)e.type.toBasetype();
+
+					if (!tt.arguments || tt.arguments.dim == 0)
+					{
+						exps.remove(i);
+						if (i == exps.dim)
+							return;
+						i--;
+						continue;
+					}
+				}
+			}
+
+			// Inline expand all the tuples
+			while (arg.op == TOK.TOKtuple)
+			{	
+				TupleExp te = cast(TupleExp)arg;
+
+				exps.remove(i);		// remove arg
+				exps.insert(i, cast(void*)te.exps);	// replace with tuple contents
+
+				if (i == exps.dim)
+					return;		// empty tuple, no more arguments
+
+				arg = cast(Expression)exps.data[i];
+			}
+		}
+    }
+}
+
+/**************************************************
+ * Write out argument types to buf.
+ */
+
+void argExpTypesToCBuffer(OutBuffer buf, Expressions arguments, HdrGenState* hgs)
+{
+    if (arguments)
+    {	
+		scope OutBuffer argbuf = new OutBuffer();
+
+		for (size_t i = 0; i < arguments.dim; i++)
+		{   
+			Expression arg = cast(Expression)arguments.data[i];
+
+			if (i)
+				buf.writeByte(',');
+
+			argbuf.reset();
+			arg.type.toCBuffer2(argbuf, hgs, MOD.MODundefined);
+			buf.write(argbuf);
+		}
+    }
+}
+
+/****************************************
+ * Determine if scope sc has package level access to s.
+ */
+
+bool hasPackageAccess(Scope sc, Dsymbol s)
+{
+version (LOG) {
+    printf("hasPackageAccess(s = '%s', sc = '%p')\n", s.toChars(), sc);
+}
+
+    for (; s; s = s.parent)
+    {
+		if (s.isPackage() && !s.isModule())
+			break;
+    }
+version (LOG) {
+    if (s)
+		printf("\tthis is in package '%s'\n", s.toChars());
+}
+
+    if (s && s == sc.module_.parent)
+    {
+version (LOG) {
+		printf("\ts is in same package as sc\n");
+}
+		return true;
+    }
+
+
+version (LOG) {
+    printf("\tno package access\n");
+}
+
+    return false;
+}
+
+/*********************************************
+ * Call copy constructor for struct value argument.
+ */
+version (DMDV2) {
+	Expression callCpCtor(Loc loc, Scope sc, Expression e)
+	{
+		Type tb = e.type.toBasetype();
+		assert(tb.ty == Tstruct);
+		StructDeclaration sd = (cast(TypeStruct)tb).sym;
+		if (sd.cpctor)
+		{
+			/* Create a variable tmp, and replace the argument e with:
+			 *	(tmp = e),tmp
+			 * and let AssignExp() handle the construction.
+			 * This is not the most efficent, ideally tmp would be constructed
+			 * directly onto the stack.
+			 */
+			Identifier idtmp = Lexer.uniqueId("__tmp");
+			VarDeclaration tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(Loc(0), e));
+			Expression ae = new DeclarationExp(loc, tmp);
+			e = new CommaExp(loc, ae, new VarExp(loc, tmp));
+			e = e.semantic(sc);
+		}
+		return e;
+	}
+}
+
+/***************************************
+ * Create a static array of TypeInfo references
+ * corresponding to an array of Expression's.
+ * Used to supply hidden _arguments[] value for variadic D functions.
+ */
+
+Expression createTypeInfoArray(Scope sc, Expression* exps, int dim)
+{
+	assert(false);
+}
+
+/**************************************
+ * Evaluate builtin function.
+ * Return result: null if cannot evaluate it.
+ */
+
+Expression eval_builtin(BUILTIN builtin, Expressions arguments)
+{
+	assert(false);
+}
+
+Expression fromConstInitializer(int result, Expression e1)
+{
+    //printf("fromConstInitializer(result = %x, %s)\n", result, e1.toChars());
+    //static int xx; if (xx++ == 10) assert(0);
+    Expression e = e1;
+    if (e1.op == TOK.TOKvar)
+    {	
+		VarExp ve = cast(VarExp)e1;
+		VarDeclaration v = ve.var.isVarDeclaration();
+		e = expandVar(result, v);
+		if (e)
+		{   
+			if (e.type != e1.type)
+			{   
+				// Type 'paint' operation
+				e = e.copy();
+				e.type = e1.type;
+			}
+		}
+		else
+		{
+			e = e1;
+		}
+    }
+    return e;
+}
+
+/*************************************
+ * If variable has a const initializer,
+ * return that initializer.
+ */
+
+Expression expandVar(int result, VarDeclaration v)
+{
+	//printf("expandVar(result = %d, v = %p, %s)\n", result, v, v ? v.toChars() : "null");
+
+    Expression e = null;
+    if (!v)
+		return e;
+
+    if (v.isConst() || v.isInvariant() || v.storage_class & STC.STCmanifest)
+    {
+		if (!v.type)
+		{
+			//error("ICE");
+			return e;
+		}
+
+		Type tb = v.type.toBasetype();
+		if (result & WANT.WANTinterpret || v.storage_class & STC.STCmanifest || (tb.ty != TY.Tsarray && tb.ty != TY.Tstruct))
+		{
+			if (v.init)
+			{
+				if (v.inuse)
+				{   
+					if (v.storage_class & STC.STCmanifest)
+						v.error("recursive initialization of constant");
+					goto L1;
+				}
+				Expression ei = v.init.toExpression();
+				if (!ei)
+					goto L1;
+				if (ei.op == TOK.TOKconstruct || ei.op == TOK.TOKblit)
+				{   
+					AssignExp ae = cast(AssignExp)ei;
+					ei = ae.e2;
+					if (ei.isConst() != 1 && ei.op != TOK.TOKstring)
+						goto L1;
+					if (ei.type != v.type)
+						goto L1;
+				}
+				if (v.scope_)
+				{
+					v.inuse++;
+					e = ei.syntaxCopy();
+					e = e.semantic(v.scope_);
+					e = e.implicitCastTo(v.scope_, v.type);
+					// enabling this line causes test22 in test suite to fail
+					//ei.type = e.type;
+					v.scope_ = null;
+					v.inuse--;
+				}
+				else if (!ei.type)
+				{
+					goto L1;
+				}
+				else
+					// Should remove the copy() operation by
+					// making all mods to expressions copy-on-write
+					e = ei.copy();
+			}
+			else
+			{
+static if (true) {
+			goto L1;
+} else {
+			// BUG: what if const is initialized in constructor?
+			e = v.type.defaultInit();
+			e.loc = e1.loc;
+}
+			}
+			if (e.type != v.type)
+			{
+				e = e.castTo(null, v.type);
+			}
+			v.inuse++;
+			e = e.optimize(result);
+			v.inuse--;
+		}
+    }
+L1:
+    //if (e) printf("\te = %s, e.type = %s\n", e.toChars(), e.type.toChars());
+    return e;
+}
+
+/****************************************
+ * Check access to d for expression e.d
+ */
+
+void accessCheck(Loc loc, Scope sc, Expression e, Declaration d)
+{
+version (LOG) {
+    if (e)
+    {	
+		printf("accessCheck(%s . %s)\n", e.toChars(), d.toChars());
+		printf("\te.type = %s\n", e.type.toChars());
+    }
+    else
+    {
+		//printf("accessCheck(%s)\n", d.toChars());
+    }
+}
+    if (!e)
+    {
+		if (d.prot() == PROT.PROTprivate && d.getModule() != sc.module_ ||
+			d.prot() == PROT.PROTpackage && !hasPackageAccess(sc, d))
+
+			error(loc, "%s %s.%s is not accessible from %s",
+			d.kind(), d.getModule().toChars(), d.toChars(), sc.module_.toChars());
+    }
+    else if (e.type.ty == TY.Tclass)
+    {   
+		// Do access check
+		ClassDeclaration cd;
+
+		cd = cast(ClassDeclaration)((cast(TypeClass)e.type).sym);
+static if (true) {
+		if (e.op == TOK.TOKsuper)
+		{   
+			ClassDeclaration cd2 = sc.func.toParent().isClassDeclaration();
+			if (cd2)
+				cd = cd2;
+		}
+}
+		cd.accessCheck(loc, sc, d);
+    }
+    else if (e.type.ty == TY.Tstruct)
+    {   
+		// Do access check
+		StructDeclaration cd = cast(StructDeclaration)((cast(TypeStruct)e.type).sym);
+		cd.accessCheck(loc, sc, d);
+    }
+}
+
+/*****************************************
+ * Given array of arguments and an aggregate type,
+ * if any of the argument types are missing, attempt to infer
+ * them from the aggregate type.
+ */
+
+void inferApplyArgTypes(TOK op, Arguments arguments, Expression aggr)
+{
+    if (!arguments || !arguments.dim)
+		return;
+
+    /* Return if no arguments need types.
+     */
+    for (size_t u = 0; 1; u++)
+    {	
+		if (u == arguments.dim)
+			return;
+
+		Argument arg = cast(Argument)arguments.data[u];
+		if (!arg.type)
+			break;
+    }
+
+    AggregateDeclaration ad;
+
+    Argument arg = cast(Argument)arguments.data[0];
+    Type taggr = aggr.type;
+    if (!taggr)
+		return;
+    Type tab = taggr.toBasetype();
+    switch (tab.ty)
+    {
+		case TY.Tarray:
+		case TY.Tsarray:
+		case TY.Ttuple:
+			if (arguments.dim == 2)
+			{
+				if (!arg.type)
+					arg.type = Type.tsize_t;	// key type
+				arg = cast(Argument)arguments.data[1];
+			}
+			if (!arg.type && tab.ty != TY.Ttuple)
+				arg.type = tab.nextOf();	// value type
+			break;
+
+		case TY.Taarray:
+		{   
+			TypeAArray taa = cast(TypeAArray)tab;
+
+			if (arguments.dim == 2)
+			{
+				if (!arg.type)
+					arg.type = taa.index;	// key type
+				arg = cast(Argument)arguments.data[1];
+			}
+			if (!arg.type)
+				arg.type = taa.next;		// value type
+			break;
+		}
+
+		case TY.Tclass:
+			ad = (cast(TypeClass)tab).sym;
+			goto Laggr;
+
+		case TY.Tstruct:
+			ad = (cast(TypeStruct)tab).sym;
+			goto Laggr;
+
+		Laggr:
+			if (arguments.dim == 1)
+			{
+				if (!arg.type)
+				{
+					/* Look for a head() or rear() overload
+					 */
+					Identifier id = (op == TOK.TOKforeach) ? Id.Fhead : Id.Ftoe;
+					Dsymbol s = search_function(ad, id);
+					FuncDeclaration fd = s ? s.isFuncDeclaration() : null;
+					if (!fd)
+					{	
+						if (s && s.isTemplateDeclaration())
+							break;
+						goto Lapply;
+					}
+					arg.type = fd.type.nextOf();
+				}
+				break;
+			}
+
+		Lapply:
+		{   /* Look for an
+			 *	int opApply(int delegate(ref Type [, ...]) dg);
+			 * overload
+			 */
+			Dsymbol s = search_function(ad, (op == TOK.TOKforeach_reverse) ? Id.applyReverse : Id.apply);
+			if (s)
+			{
+				FuncDeclaration fd = s.isFuncDeclaration();
+				if (fd) 
+				{   
+					inferApplyArgTypesX(fd, arguments);
+					break;
+				}
+static if (false) {
+				TemplateDeclaration td = s.isTemplateDeclaration();
+				if (td)
+				{   
+					inferApplyArgTypesZ(td, arguments);
+					break;
+				}
+}
+			}
+			break;
+		}
+
+		case TY.Tdelegate:
+		{
+			if (0 && aggr.op == TOK.TOKdelegate)
+			{	
+				DelegateExp de = cast(DelegateExp)aggr;
+
+				FuncDeclaration fd = de.func.isFuncDeclaration();
+				if (fd)
+					inferApplyArgTypesX(fd, arguments);
+				}
+			else
+			{
+				inferApplyArgTypesY(cast(TypeFunction)tab.nextOf(), arguments);
+			}
+			break;
+		}
+
+		default:
+			break;		// ignore error, caught later
+    }
+}
+
+struct Param3
+{
+	/********************************
+	 * Recursive helper function,
+	 * analogous to func.overloadResolveX().
+	 */
+
+	int fp3(FuncDeclaration f)
+	{
+		TypeFunction tf = cast(TypeFunction)f.type;
+		if (inferApplyArgTypesY(tf, arguments) == 1)
+			return 0;
+
+		if (arguments.dim == 0)
+			return 1;
+
+		return 0;
+	}
+	
+	Arguments arguments;
+}
+
+void inferApplyArgTypesX(FuncDeclaration fstart, Arguments arguments)
+{
+	Param3 p3;
+	p3.arguments = arguments;
+    overloadApply(fstart, &p3.fp3);
+}
+
+/******************************
+ * Infer arguments from type of function.
+ * Returns:
+ *	0 match for this function
+ *	1 no match for this function
+ */
+
+int inferApplyArgTypesY(TypeFunction tf, Arguments arguments)
+{   
+	size_t nparams;
+    Argument p;
+
+    if (Argument.dim(tf.parameters) != 1)
+		goto Lnomatch;
+
+    p = Argument.getNth(tf.parameters, 0);
+    if (p.type.ty != TY.Tdelegate)
+		goto Lnomatch;
+
+    tf = cast(TypeFunction)p.type.nextOf();
+    assert(tf.ty == TY.Tfunction);
+
+    /* We now have tf, the type of the delegate. Match it against
+     * the arguments, filling in missing argument types.
+     */
+    nparams = Argument.dim(tf.parameters);
+    if (nparams == 0 || tf.varargs)
+		goto Lnomatch;		// not enough parameters
+    if (arguments.dim != nparams)
+		goto Lnomatch;		// not enough parameters
+
+    for (size_t u = 0; u < nparams; u++)
+    {
+		Argument arg = cast(Argument)arguments.data[u];
+		Argument param = Argument.getNth(tf.parameters, u);
+		if (arg.type)
+		{   
+			if (!arg.type.equals(param.type))
+			{
+				/* Cannot resolve argument types. Indicate an
+				 * error by setting the number of arguments to 0.
+				 */
+				arguments.dim = 0;
+				goto Lmatch;
+			}
+			continue;
+		}
+		arg.type = param.type;
+    }
+
+  Lmatch:
+    return 0;
+
+  Lnomatch:
+    return 1;
+}
+
+/**************************************************
+ * Write expression out to buf, but wrap it
+ * in ( ) if its precedence is less than pr.
+ */
+
+void expToCBuffer(OutBuffer buf, HdrGenState* hgs, Expression e, PREC pr)
+{
+    //if (precedence[e.op] == 0) e.dump(0);
+    if (precedence[e.op] < pr ||
+	/* Despite precedence, we don't allow a<b<c expressions.
+	 * They must be parenthesized.
+	 */
+	(pr == PREC.PREC_rel && precedence[e.op] == pr))
+    {
+		buf.writeByte('(');
+		e.toCBuffer(buf, hgs);
+		buf.writeByte(')');
+    }
+    else
+		e.toCBuffer(buf, hgs);
+}
+
+/**************************************************
+ * Write out argument list to buf.
+ */
+
+void argsToCBuffer(OutBuffer buf, Expressions arguments, HdrGenState* hgs)
+{
+    if (arguments)
+    {
+		for (size_t i = 0; i < arguments.dim; i++)
+		{   
+			Expression arg = cast(Expression)arguments.data[i];
+
+			if (arg)
+			{	
+				if (i)
+					buf.writeByte(',');
+				expToCBuffer(buf, hgs, arg, PREC.PREC_assign);
+			}
+		}
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/Xor.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,10 @@
+module dmd.expression.Xor;
+
+import dmd.Type;
+import dmd.Expression;
+import dmd.IntegerExp;
+
+Expression Xor(Type type, Expression e1, Expression e2)
+{
+    return new IntegerExp(e1.loc, e1.toInteger() ^ e2.toInteger(), type);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/shift_optimize.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,32 @@
+module dmd.expression.shift_optimize;
+
+import dmd.Expression;
+import dmd.BinExp;
+import dmd.Type;
+import dmd.IntegerExp;
+
+Expression shift_optimize(int result, BinExp e, Expression function(Type, Expression, Expression) shift)
+{   
+	Expression ex = e;
+
+    e.e1 = e.e1.optimize(result);
+    e.e2 = e.e2.optimize(result);
+
+    if (e.e2.isConst() == 1)
+    {
+		long i2 = e.e2.toInteger();
+		ulong sz = e.e1.type.size() * 8;
+
+		if (i2 < 0 || i2 > sz)
+		{   
+			e.error("shift by %jd is outside the range 0..%zu", i2, sz);
+			e.e2 = new IntegerExp(0);
+		}
+
+		if (e.e1.isConst() == 1) {
+			ex = shift(e.type, e.e1, e.e2);
+		}
+    }
+
+    return ex;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/expression/util/arrayTypeCompatible.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,34 @@
+module dmd.expression.util.arrayTypeCompatible;
+
+import dmd.Loc;
+import dmd.Type;
+import dmd.TY;
+import dmd.MATCH;
+import dmd.Util;
+
+/***********************************
+ * See if both types are arrays that can be compared
+ * for equality. Return !=0 if so.
+ * If they are arrays, but incompatible, issue error.
+ * This is to enable comparing things like an immutable
+ * array with a mutable one.
+ */
+bool arrayTypeCompatible(Loc loc, Type t1, Type t2)
+{
+    t1 = t1.toBasetype();
+    t2 = t2.toBasetype();
+
+    if ((t1.ty == TY.Tarray || t1.ty == TY.Tsarray || t1.ty == TY.Tpointer) && (t2.ty == TY.Tarray || t2.ty == TY.Tsarray || t2.ty == TY.Tpointer))
+	{
+		if (t1.nextOf().implicitConvTo(t2.nextOf()) < MATCH.MATCHconst && 
+			t2.nextOf().implicitConvTo(t1.nextOf()) < MATCH.MATCHconst &&
+			(t1.nextOf().ty != TY.Tvoid && t2.nextOf().ty != TY.Tvoid))
+		{
+			error(loc, "array equality comparison type mismatch, %s vs %s", t1.toChars(), t2.toChars());
+		}
+		
+		return true;
+    }
+
+    return false;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/type/Util.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,46 @@
+module dmd.type.Util;
+
+import dmd.TY;
+import dmd.Expression;
+import dmd.Scope;
+import dmd.Type;
+import dmd.TupleDeclaration;
+import dmd.TypeTuple;
+import dmd.ScopeDsymbol;
+import dmd.ArrayScopeSymbol;
+
+/**************************
+ * This evaluates exp while setting length to be the number
+ * of elements in the tuple t.
+ */
+Expression semanticLength(Scope sc, Type t, Expression exp)
+{
+    if (t.ty == TY.Ttuple)
+    {
+		ScopeDsymbol sym = new ArrayScopeSymbol(sc, cast(TypeTuple)t);
+		sym.parent = sc.scopesym;
+		sc = sc.push(sym);
+
+		exp = exp.semantic(sc);
+
+		sc.pop();
+    }
+    else
+		exp = exp.semantic(sc);
+
+    return exp;
+}
+
+Expression semanticLength(Scope sc, TupleDeclaration s, Expression exp)
+{
+	assert(false);
+	
+    ScopeDsymbol sym = new ArrayScopeSymbol(sc, s);
+    sym.parent = sc.scopesym;
+    sc = sc.push(sym);
+
+    exp = exp.semantic(sc);
+
+    sc.pop();
+    return exp;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,1105 @@
+module main;
+
+import dmd.Array;
+import dmd.Module;
+import dmd.Global;
+import dmd.VersionCondition;
+import dmd.DebugCondition;
+import dmd.Loc;
+import dmd.Lexer;
+import dmd.OutBuffer;
+import dmd.FileName;
+import dmd.Type;
+import dmd.File;
+import dmd.Id;
+import dmd.Identifier;
+import dmd.Library;
+import dmd.TOK;
+import dmd.String;
+import dmd.backend.glue;
+
+import std.stdarg;
+import std.string : toStringz;
+import std.contracts;
+
+import core.stdc.string;
+import core.stdc.stdio;
+import core.stdc.ctype;
+import core.stdc.errno;
+import core.stdc.stdlib;
+import core.stdc.limits;
+
+import core.memory;
+
+import dlib.CrashHandler;
+import dbg.ui.CrashWindow;
+
+import dmd.Util;
+
+bool loop = true;
+
+enum ExitCode
+{
+	EXIT_SUCCESS = 0,
+}
+
+version (Windows)
+{
+    private import core.stdc.wchar_;
+}
+
+extern (C) void gc_init();
+extern (C) void gc_term();
+extern (C) void _minit();
+extern (C) void _moduleCtor();
+extern (C) void _moduleDtor();
+extern (C) void thread_joinAll();
+
+shared bool _d_isHalting = false;
+
+import win32.windows;
+
+extern (C) int main(int argc, char **argv)
+{
+    char[][] args;
+    int result;
+
+    version (OSX)
+    {   /* OSX does not provide a way to get at the top of the
+         * stack, except for the magic value 0xC0000000.
+         * But as far as the gc is concerned, argv is at the top
+         * of the main thread's stack, so save the address of that.
+         */
+        __osx_stack_end = cast(void*)&argv;
+    }
+
+    version (Posix)
+    {
+        _STI_monitor_staticctor();
+        _STI_critical_init();
+    }
+
+    version (Windows)
+    {
+        wchar_t*  wcbuf = GetCommandLineW();
+        size_t    wclen = wcslen(wcbuf);
+        int       wargc = 0;
+        wchar_t** wargs = CommandLineToArgvW(wcbuf, &wargc);
+        assert(wargc == argc);
+
+        char*     cargp = null;
+        size_t    cargl = WideCharToMultiByte(65001, 0, wcbuf, wclen, null, 0, null, null);
+
+        cargp = cast(char*) alloca(cargl);
+        args  = ((cast(char[]*) alloca(wargc * (char[]).sizeof)))[0 .. wargc];
+
+        for (size_t i = 0, p = 0; i < wargc; i++)
+        {
+            int wlen = wcslen(wargs[i]);
+            int clen = WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, null, 0, null, null);
+            args[i]  = cargp[p .. p+clen];
+            p += clen; assert(p <= cargl);
+            WideCharToMultiByte(65001, 0, &wargs[i][0], wlen, &args[i][0], clen, null, null);
+        }
+        LocalFree(cast(HANDLE)wargs);
+        wargs = null;
+        wargc = 0;
+    }
+    else version (Posix)
+    {
+        char[]* am = cast(char[]*) malloc(argc * (char[]).sizeof);
+        scope(exit) free(am);
+
+        for (size_t i = 0; i < argc; i++)
+        {
+            auto len = strlen(argv[i]);
+            am[i] = argv[i][0 .. len];
+        }
+        args = am[0 .. argc];
+    }
+
+	gc_init();
+	version (Windows)
+		_minit();
+	_moduleCtor();
+	
+	CrashHandlerInit();
+	GC.disable();
+
+	result = main(cast(string[])args);
+	
+	thread_joinAll();
+	_d_isHalting = true;
+	_moduleDtor();
+	gc_term();
+
+    version (Posix)
+    {
+        _STD_critical_term();
+        _STD_monitor_staticdtor();
+    }
+
+    return result;
+}
+
+int main(string[] args)
+{
+    Array files = new Array();
+    Array libmodules = new Array();
+    Module m;
+    int status = ExitCode.EXIT_SUCCESS;
+    int argcstart = args.length;
+    int setdebuglib = 0;
+	
+	global = new Global();
+
+///    if (response_expand(&argc,&argv))        // expand response files
+///        error("can't open response file");
+
+    files.reserve(args.length - 1);
+
+    // Set default values
+    global.params.argv0 = args[0];
+    global.params.link = 1;
+    global.params.useAssert = 1;
+    global.params.useInvariants = 1;
+    global.params.useIn = 1;
+    global.params.useOut = 1;
+    global.params.useArrayBounds = 1;
+    global.params.useSwitchError = 1;
+    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();
+    global.params.objfiles = new Array();
+    global.params.ddocfiles = new Array();
+
+version (TARGET_WINDOS) {
+    global.params.defaultlibname = "phobos";
+} else version (XXX) { //#elif TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+    global.params.defaultlibname = "phobos2";
+} else version (TARGET_NET) {
+} else {
+    static assert(false, "fix this");
+}
+
+    // Predefine version identifiers
+    VersionCondition.addPredefinedGlobalIdent("DigitalMars");
+
+version (TARGET_WINDOS) {
+    VersionCondition.addPredefinedGlobalIdent("Windows");
+    global.params.isWindows = 1;
+version (TARGET_NET) {
+    // TARGET_NET macro is NOT mutually-exclusive with TARGET_WINDOS
+    VersionCondition.addPredefinedGlobalIdent("D_NET");
+}
+} else version (TARGET_LINUX) {
+    VersionCondition.addPredefinedGlobalIdent("Posix");
+    VersionCondition.addPredefinedGlobalIdent("linux");
+    global.params.isLinux = 1;
+} else version (TARGET_OSX) {
+    VersionCondition.addPredefinedGlobalIdent("Posix");
+    VersionCondition.addPredefinedGlobalIdent("OSX");
+    global.params.isOSX = 1;
+
+    // For legacy compatibility
+    VersionCondition.addPredefinedGlobalIdent("darwin");
+} else version (TARGET_FREEBSD) {
+    VersionCondition.addPredefinedGlobalIdent("Posix");
+    VersionCondition.addPredefinedGlobalIdent("FreeBSD");
+    global.params.isFreeBSD = 1;
+} else version (TARGET_SOLARIS) {
+    VersionCondition.addPredefinedGlobalIdent("Posix");
+    VersionCondition.addPredefinedGlobalIdent("Solaris");
+    global.params.isSolaris = 1;
+} else {
+        static assert (false, "fix this");
+}
+
+    VersionCondition.addPredefinedGlobalIdent("LittleEndian");
+    //VersionCondition.addPredefinedGlobalIdent("D_Bits");
+version (DMDV2) {
+    VersionCondition.addPredefinedGlobalIdent("D_Version2");
+}
+    VersionCondition.addPredefinedGlobalIdent("all");
+
+version (_WIN32) {
+    inifile(args[0], "sc.ini");
+} else version (XXX) {///linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+    inifile(argv[0], "dmd.conf");
+} else {
+        static assert (false, "fix this");
+}
+    args = getenv_setargv("DFLAGS", args);
+
+version (disabled) {
+    for (i = 0; i < argc; i++)
+    {
+        writef("argv[%d] = '%s'\n", i, argv[i]);
+    }
+}
+
+    foreach(i; 1..args.length)
+    {
+		auto arg = args[i];
+        auto p = arg.ptr;
+        if (*p == '-')
+        {
+			arg = arg[1..$];
+            if (arg == "d")
+                global.params.useDeprecated = 1;
+            else if (arg == "c")
+                global.params.link = 0;
+            else if (arg == "cov")
+                global.params.cov = 1;
+///version (XXX) {// TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
+///            else if (arg == "fPIC")
+///                global.params.pic = 1;
+///}
+            else if (arg == "multiobj")
+                global.params.multiobj = 1;
+            else if (arg == "g")
+                global.params.symdebug = 1;
+            else if (arg == "gc")
+                global.params.symdebug = 2;
+            else if (arg == "gt")
+            {        error("use -profile instead of -gt\n");
+                global.params.trace = 1;
+            }
+            else if (arg == "m64")
+                global.params.isX86_64 = 1;
+            else if (arg == "profile")
+                global.params.trace = 1;
+            else if (arg == "v")
+                global.params.verbose = 1;
+///version (DMDV2) {
+            else if (arg == "vtls")
+                global.params.vtls = 1;
+///}
+            else if (arg == "v1")
+            {
+version (DMDV1) {
+                global.params.Dversion = 1;
+} else {
+                error("use DMD 1.0 series compilers for -v1 switch");
+                break;
+}
+            }
+            else if (arg == "w")
+                global.params.warnings = 1;
+            else if (arg == "O")
+                global.params.optimize = 1;
+            else if (p[1] == 'o')
+            {
+                switch (p[2])
+                {
+                    case '-':
+                        global.params.obj = 0;
+                        break;
+
+                    case 'd':
+                        if (!p[3])
+                            goto Lnoarg;
+                        global.params.objdir = arg[(p - arg.ptr) + 3..$];
+                        break;
+
+                    case 'f':
+					{
+                        if (!p[3])
+                            goto Lnoarg;
+							
+                        global.params.objname = arg[(p - arg.ptr) + 3..$];
+                        break;
+					}
+
+                    case 'p':
+                        if (p[3])
+                            goto Lerror;
+                        global.params.preservePaths = 1;
+                        break;
+
+                    case 0:
+                        error("-o no longer supported, use -of or -od");
+                        break;
+
+                    default:
+                        goto Lerror;
+                }
+            }
+            else if (p[1] == 'D')
+            {        global.params.doDocComments = 1;
+                switch (p[2])
+                {
+                    case 'd':
+                        if (!p[3])
+                            goto Lnoarg;
+                        global.params.docdir = arg[(p - arg.ptr) + 3..$];
+                        break;
+                    case 'f':
+                        if (!p[3])
+                            goto Lnoarg;
+                        global.params.docname = arg[(p - arg.ptr) + 3..$];
+                        break;
+
+                    case 0:
+                        break;
+
+                    default:
+                        goto Lerror;
+                }
+            }
+///version (_DH) {
+            else if (p[1] == 'H')
+            {        global.params.doHdrGeneration = 1;
+                switch (p[2])
+                {
+                    case 'd':
+                        if (!p[3])
+                            goto Lnoarg;
+                        global.params.hdrdir = arg[(p - arg.ptr) + 3..$];
+                        break;
+
+                    case 'f':
+                        if (!p[3])
+                            goto Lnoarg;
+                        global.params.hdrname = arg[(p - arg.ptr) + 3..$];
+                        break;
+
+                    case 0:
+                        break;
+
+                    default:
+                        goto Lerror;
+                }
+            }
+///}
+            else if (arg == "ignore")
+                global.params.ignoreUnsupportedPragmas = 1;
+            else if (arg == "inline")
+                global.params.useInline = 1;
+            else if (arg == "lib")
+                global.params.lib = 1;
+            else if (arg == "nofloat")
+                global.params.nofloat = 1;
+            else if (arg == "quiet")
+                global.params.quiet = 1;
+            else if (arg == "release")
+                global.params.release = 1;
+///version (DMDV2) {
+            else if (arg == "safe")
+                global.params.safe = 1;
+///}
+            else if (arg == "unittest")
+                global.params.useUnitTests = 1;
+            else if (p[1] == 'I')
+            {
+                if (!global.params.imppath)
+                    global.params.imppath = new Array();
+                global.params.imppath.push(cast(void*)new String(arg[(p - arg.ptr) + 2..$]));	///
+            }
+            else if (p[1] == 'J')
+            {
+                if (!global.params.fileImppath)
+                    global.params.fileImppath = new Array();
+                global.params.fileImppath.push(cast(void*)new String(arg[(p - arg.ptr) + 2..$]));
+            }
+            else if (memcmp(p + 1, "debug".ptr, 5) == 0 && p[6] != 'l')
+            {
+                // Parse:
+                //        -debug
+                //        -debug=number
+                //        -debug=identifier
+                if (p[6] == '=')
+                {
+                    if (isdigit(p[7]))
+                    {        long level;
+
+                        errno = 0;
+                        level = strtol(p + 7, cast(char**)&p, 10);
+                        if (*p || errno || level > INT_MAX)
+                            goto Lerror;
+                        DebugCondition.setGlobalLevel(cast(int)level);
+                    }
+                    else if (Lexer.isValidIdentifier(arg[(p - arg.ptr) + 7..$]))		///
+                        DebugCondition.addGlobalIdent(p + 7);
+                    else
+                        goto Lerror;
+                }
+                else if (p[6])
+                    goto Lerror;
+                else
+                    global.params.debuglevel = 1;
+            }
+            else if (memcmp(p + 1, "version".ptr, 5) == 0)
+            {
+                // Parse:
+                //        -version=number
+                //        -version=identifier
+                if (p[8] == '=')
+                {
+                    if (isdigit(p[9]))
+                    {        long level;
+
+                        errno = 0;
+                        level = strtol(p + 9, cast(char**)&p, 10);	///
+                        if (*p || errno || level > INT_MAX)
+                            goto Lerror;
+                        VersionCondition.setGlobalLevel(cast(int)level);
+                    }
+                    else if (Lexer.isValidIdentifier(arg[(p - arg.ptr) + 9..$]))	///
+                        VersionCondition.addGlobalIdent(arg[(p - arg.ptr) + 9..$]);
+                    else
+                        goto Lerror;
+                }
+                else
+                    goto Lerror;
+            }
+            else if (arg == "-b")
+                global.params.debugb = 1;
+            else if (arg == "-c")
+                global.params.debugc = 1;
+            else if (arg == "-f")
+                global.params.debugf = 1;
+            else if (arg == "-help")
+            {        usage();
+                exit(EXIT_SUCCESS);
+            }
+            else if (arg == "-r")
+                global.params.debugr = 1;
+            else if (arg == "-x")
+                global.params.debugx = 1;
+            else if (arg == "-y")
+                global.params.debugy = 1;
+            else if (p[1] == 'L')
+            {
+                global.params.linkswitches.push(cast(void*)p + 2);
+            }
+            else if (memcmp(p + 1, "defaultlib=".ptr, 11) == 0)
+            {
+                global.params.defaultlibname = p + 1 + 11;
+            }
+            else if (memcmp(p + 1, "debuglib=".ptr, 9) == 0)
+            {
+                setdebuglib = 1;
+                global.params.debuglibname = p + 1 + 9;
+            }
+            else if (memcmp(p + 1, "deps=".ptr, 5) == 0)
+            {
+                global.params.moduleDepsFile = arg[(p - arg.ptr) + 1 + 5..$];
+                if (!global.params.moduleDepsFile[0])
+                    goto Lnoarg;
+                global.params.moduleDeps = new OutBuffer;
+            }
+            else if (memcmp(p + 1, "man".ptr, 3) == 0)
+            {
+version (_WIN32) {
+version (DMDV1) {
+                browse("http://www.digitalmars.com/d/1.0/dmd-windows.html");
+} else {
+                browse("http://www.digitalmars.com/d/2.0/dmd-windows.html");
+}
+}
+version (linux) {
+version (DMDV1) {
+                browse("http://www.digitalmars.com/d/1.0/dmd-linux.html");
+} else {
+                browse("http://www.digitalmars.com/d/2.0/dmd-linux.html");
+}
+}
+version (__APPLE__) {
+version (DMDV1) {
+                browse("http://www.digitalmars.com/d/1.0/dmd-osx.html");
+} else {
+                browse("http://www.digitalmars.com/d/2.0/dmd-osx.html");
+}
+}
+version (__FreeBSD__) {
+version (DMDV1) {
+                browse("http://www.digitalmars.com/d/1.0/dmd-freebsd.html");
+} else {
+                browse("http://www.digitalmars.com/d/2.0/dmd-freebsd.html");
+}
+}
+                exit(EXIT_SUCCESS);
+            }
+            else if (arg == "run")
+            {        global.params.run = 1;
+                global.params.runargs_length = ((i >= argcstart) ? args.length : argcstart) - i - 1;
+                if (global.params.runargs_length)
+                {
+                    files.push(cast(void*)args[i + 1].ptr);
+                    global.params.runargs = args[i + 2..$];
+                    i += global.params.runargs_length;
+                    global.params.runargs_length--;
+                }
+                else
+                {   global.params.run = 0;
+                    goto Lnoarg;
+                }
+            }
+            else
+            {
+             Lerror:
+                error("unrecognized switch '%s'", args[i]);
+                continue;
+
+             Lnoarg:
+                error("argument expected for switch '%s'", args[i]);
+                continue;
+            }
+        }
+        else
+        {
+version (TARGET_WINDOS) {
+            string ext = FileName.ext(p[0..arg.length]);
+            if (ext != null && FileName.compare(ext, "exe") == 0)
+            {
+                global.params.objname = arg[(p - arg.ptr)..$];
+                continue;
+            }
+}
+            files.push(cast(void*)new String(arg[(p - arg.ptr)..$]));
+        }
+    }
+    if (global.errors)
+    {
+        fatal();
+    }
+    if (files.dim == 0)
+    {        usage();
+        return EXIT_FAILURE;
+    }
+
+    if (!setdebuglib)
+        global.params.debuglibname = global.params.defaultlibname;
+
+version (TARGET_OSX) {
+    global.params.pic = 1;
+}
+
+    if (global.params.release)
+    {        global.params.useInvariants = 0;
+        global.params.useIn = 0;
+        global.params.useOut = 0;
+        global.params.useAssert = 0;
+        global.params.useArrayBounds = 0;
+        global.params.useSwitchError = 0;
+    }
+
+    if (global.params.run)
+        global.params.quiet = 1;
+
+    if (global.params.useUnitTests)
+        global.params.useAssert = 1;
+
+    if (!global.params.obj || global.params.lib)
+        global.params.link = 0;
+
+    if (global.params.link)
+    {
+        global.params.exefile = global.params.objname;
+        global.params.oneobj = 1;
+        if (global.params.objname)
+        {
+            /* Use this to name the one object file with the same
+             * name as the exe file.
+             */
+            global.params.objname = FileName.forceExt(global.params.objname, global.obj_ext).toChars();
+
+            /* If output directory is given, use that path rather than
+             * the exe file path.
+             */
+            if (global.params.objdir)
+            {
+				string name = FileName.name(global.params.objname);
+                global.params.objname = FileName.combine(global.params.objdir, name);
+            }
+        }
+    }
+    else if (global.params.lib)
+    {
+        global.params.libname = global.params.objname;
+        global.params.objname = null;
+
+        // Haven't investigated handling these options with multiobj
+        if (!global.params.cov && !global.params.trace)
+            global.params.multiobj = 1;
+    }
+    else if (global.params.run)
+    {
+        error("flags conflict with -run");
+        fatal();
+    }
+    else
+    {
+        if (global.params.objname && files.dim > 1)
+        {
+            global.params.oneobj = 1;
+            //error("multiple source files, but only one .obj name");
+            //fatal();
+        }
+    }
+    if (global.params.isX86_64)
+    {
+        VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86_64");
+        VersionCondition.addPredefinedGlobalIdent("X86_64");
+        VersionCondition.addPredefinedGlobalIdent("D_LP64");
+version (TARGET_WINDOS) {
+        VersionCondition.addPredefinedGlobalIdent("Win64");
+}
+    }
+    else
+    {
+        VersionCondition.addPredefinedGlobalIdent("D_InlineAsm");
+        VersionCondition.addPredefinedGlobalIdent("D_InlineAsm_X86");
+        VersionCondition.addPredefinedGlobalIdent("X86");
+version (TARGET_WINDOS) {
+        VersionCondition.addPredefinedGlobalIdent("Win32");
+}
+    }
+    if (global.params.doDocComments)
+        VersionCondition.addPredefinedGlobalIdent("D_Ddoc");
+    if (global.params.cov)
+        VersionCondition.addPredefinedGlobalIdent("D_Coverage");
+    if (global.params.pic)
+        VersionCondition.addPredefinedGlobalIdent("D_PIC");
+version (DMDV2) {
+    if (global.params.useUnitTests)
+        VersionCondition.addPredefinedGlobalIdent("unittest");
+}
+
+    // Initialization
+    Type.init();
+    Id.initialize();
+    Module.init();
+    initPrecedence();
+
+    backend_init();
+
+    //printf("%d source files\n",files.dim);
+
+    // Build import search path
+    if (global.params.imppath)
+    {
+        for (int i = 0; i < global.params.imppath.dim; i++)
+        {
+            string path = (cast(String)global.params.imppath.data[i]).str;
+            string[] a = FileName.splitPath(path);
+
+            global.path ~= a;
+        }
+    }
+
+    // Build string import search path
+    if (global.params.fileImppath)
+    {
+        for (int i = 0; i < global.params.fileImppath.dim; i++)
+        {
+            string path = (cast(String)global.params.fileImppath.data[i]).str;
+            string[] a = FileName.splitPath(path);
+			
+            global.filePath ~= a;
+        }
+    }
+
+    // Create Modules
+    Array modules = new Array();
+    modules.reserve(files.dim);
+    int firstmodule = 1;
+    for (int i = 0; i < files.dim; i++)
+    {
+        string ext;
+        string name;
+
+		String s = cast(String) files.data[i];
+        string mp = s.str;
+
+version (_WIN32) {
+		char[] copy = null;
+        // Convert / to \ so linker will work
+        foreach (j, c; mp)
+        {
+            if (c == '/') {
+				if (copy is null) copy = mp.dup;
+                copy[j] = '\\';
+			}
+        }
+
+		if (copy !is null) mp = assumeUnique(copy);
+}
+		string p = mp;
+		
+        p = FileName.name(p);                // strip path
+        ext = FileName.ext(p);
+		
+        if (ext.length != 0)
+        {   /* Deduce what to do with a file based on its extension
+             */
+            if (FileName.equals(ext, global.obj_ext))
+            {
+                global.params.objfiles.push(files.data[i]);
+                libmodules.push(files.data[i]);
+                continue;
+            }
+
+            if (FileName.equals(ext, global.lib_ext))
+            {
+                global.params.libfiles.push(files.data[i]);
+                libmodules.push(files.data[i]);
+                continue;
+            }
+
+            if (ext == global.ddoc_ext)
+            {
+                global.params.ddocfiles.push(files.data[i]);
+                continue;
+            }
+
+version (TARGET_WINDOS) {
+            if (FileName.equals(ext, "res"))
+            {
+                global.params.resfile = (cast(immutable(char)*)files.data[i])[0..0];		/// !!!
+                continue;
+            }
+
+            if (FileName.equals(ext, "def"))
+            {
+                global.params.deffile = (cast(immutable(char)*)files.data[i])[0..0];
+                continue;
+            }
+
+            if (FileName.equals(ext, "exe"))
+            {
+                assert(0);        // should have already been handled
+            }
+}
+
+            /* Examine extension to see if it is a valid
+             * D source file extension
+             */
+            if (FileName.equals(ext, global.mars_ext) ||
+                FileName.equals(ext, global.hdr_ext) ||
+                FileName.equals(ext, "dd") ||
+                FileName.equals(ext, "htm") ||
+                FileName.equals(ext, "html") ||
+                FileName.equals(ext, "xhtml"))
+            {
+				immutable(char)* e = ext.ptr;
+                e--;                        // skip onto '.'
+                assert(*e == '.');
+				
+				immutable(char)* n = p.ptr;
+
+                name = n[0..(e-n)];	// strip extension
+
+                if (name.length == 0 || name == ".." || name == ".")
+                {
+                Linvalid:
+                    error("invalid file name '%s'", (cast(String)files.data[i]).str);
+                    fatal();
+                }
+            }
+            else
+            {        error("unrecognized file extension %s\n", ext);
+                fatal();
+            }
+        }
+        else
+        {
+			name = p;
+            if (!*name)
+                goto Linvalid;
+        }
+
+        /* At this point, name is the D source file name stripped of
+         * its path and extension.
+         */
+
+        Identifier id = new Identifier(name, TOK.TOKreserved);
+        m = new Module((cast(String) files.data[i]).str, id, global.params.doDocComments, global.params.doHdrGeneration);
+        modules.push(cast(void*)m);
+
+        if (firstmodule)
+        {
+			global.params.objfiles.push(cast(void*)m.objfile.name);
+            firstmodule = 0;
+        }
+    }
+
+    // Read files
+//version = ASYNCREAD;
+version (ASYNCREAD) {
+    // Multi threaded
+    AsyncRead *aw = AsyncRead.create(modules.dim);
+    for (i = 0; i < modules.dim; i++)
+    {
+        m = cast(Module *)modules.data[i];
+        aw.addFile(m.srcfile);
+    }
+    aw.start();
+} else {
+    // Single threaded
+    for (int i = 0; i < modules.dim; i++)
+    {
+        m = cast(Module)modules.data[i];
+        m.read(Loc(0));
+    }
+}
+
+    // Parse files
+    int anydocfiles = 0;
+    for (int i = 0; i < modules.dim; i++)
+    {
+        m = cast(Module)modules.data[i];
+        if (global.params.verbose)
+            writef("parse     %s\n", m.toChars());
+        if (!Module.rootModule)
+            Module.rootModule = m;
+        m.importedFrom = m;
+        if (!global.params.oneobj || i == 0 || m.isDocFile)
+            m.deleteObjFile();
+version (ASYNCREAD) {
+        if (aw.read(i))
+        {
+            error("cannot read file %s", m.srcfile.name.toChars());
+        }
+}
+
+		//while (loop) {}
+        m.parse();
+        if (m.isDocFile)
+        {
+            anydocfiles = 1;
+            m.gendocfile();
+
+            // Remove m from list of modules
+            modules.remove(i);
+            i--;
+
+            // Remove m's object file from list of object files
+            for (int j = 0; j < global.params.objfiles.dim; j++)
+            {
+                if (m.objfile.name.str == (cast(FileName)global.params.objfiles.data[j]).str)
+                {
+                    global.params.objfiles.remove(j);
+                    break;
+                }
+            }
+
+            if (global.params.objfiles.dim == 0)
+                global.params.link = 0;
+        }
+    }
+version (ASYNCREAD) {
+    AsyncRead.dispose(aw);
+}
+
+    if (anydocfiles && modules.dim &&
+        (global.params.oneobj || global.params.objname))
+    {
+        error("conflicting Ddoc and obj generation options");
+        fatal();
+    }
+    if (global.errors)
+        fatal();
+version (_DH) {
+    if (global.params.doHdrGeneration)
+    {
+        /* Generate 'header' import files.
+         * Since 'header' import files must be independent of command
+         * line switches and what else is imported, they are generated
+         * before any semantic analysis.
+         */
+        for (i = 0; i < modules.dim; i++)
+        {
+            m = cast(Module *)modules.data[i];
+            if (global.params.verbose)
+                writef("import    %s\n", m.toChars());
+            m.genhdrfile();
+        }
+    }
+    if (global.errors)
+        fatal();
+}
+
+    // Do semantic analysis
+    for (int i = 0; i < modules.dim; i++)
+    {
+        m = cast(Module)modules.data[i];
+        if (global.params.verbose)
+            writef("semantic  %s\n", m.toChars());
+        m.semantic();
+    }
+    if (global.errors)
+        fatal();
+
+    // Do pass 2 semantic analysis
+    for (int i = 0; i < modules.dim; i++)
+    {
+        m = cast(Module)modules.data[i];
+        if (global.params.verbose)
+            writef("semantic2 %s\n", m.toChars());
+        m.semantic2();
+    }
+    if (global.errors)
+        fatal();
+
+    // Do pass 3 semantic analysis
+    for (int i = 0; i < modules.dim; i++)
+    {
+        m = cast(Module)modules.data[i];
+        if (global.params.verbose)
+            writef("semantic3 %s\n", m.toChars());
+        m.semantic3();
+    }
+    if (global.errors)
+        fatal();
+
+    if (global.params.moduleDeps !is null)
+    {
+        assert(global.params.moduleDepsFile !is null);
+
+        File deps = new File(global.params.moduleDepsFile);
+        OutBuffer ob = global.params.moduleDeps;
+        deps.setbuffer(cast(void*)ob.data, ob.offset);
+        deps.writev();
+    }
+
+
+    // Scan for functions to inline
+    if (global.params.useInline)
+    {
+        /* The problem with useArrayBounds and useAssert is that the
+         * module being linked to may not have generated them, so if
+         * we inline functions from those modules, the symbols for them will
+         * not be found at link time.
+         */
+        if (!global.params.useArrayBounds && !global.params.useAssert)
+        {
+            // Do pass 3 semantic analysis on all imported modules,
+            // since otherwise functions in them cannot be inlined
+            for (int i = 0; i < Module.amodules.dim; i++)
+            {
+                m = cast(Module)Module.amodules.data[i];
+                if (global.params.verbose)
+                    writef("semantic3 %s\n", m.toChars());
+                m.semantic3();
+            }
+            if (global.errors)
+                fatal();
+        }
+
+        for (int i = 0; i < modules.dim; i++)
+        {
+            m = cast(Module)modules.data[i];
+            if (global.params.verbose)
+                writef("inline scan %s\n", m.toChars());
+				
+            m.inlineScan();
+        }
+    }
+    if (global.errors)
+        fatal();
+
+    Library library = null;
+    if (global.params.lib)
+    {
+        library = new Library();
+        library.setFilename(global.params.objdir, global.params.libname);
+
+        // Add input object and input library files to output library
+        for (int i = 0; i < libmodules.dim; i++)
+        {
+            string p = (cast(String)libmodules.data[i]).str;
+            library.addObject(p, null, 0);
+        }
+    }
+
+    // Generate output files
+    if (global.params.oneobj)
+    {
+        for (int i = 0; i < modules.dim; i++)
+        {
+            m = cast(Module)modules.data[i];
+            if (global.params.verbose)
+                writef("code      %s\n", m.toChars());
+            if (i == 0)
+                obj_start(cast(char*)toStringz(m.srcfile.toChars()));
+            m.genobjfile(0);
+            if (!global.errors && global.params.doDocComments)
+                m.gendocfile();
+        }
+        if (!global.errors && modules.dim)
+        {
+            obj_end(library, (cast(Module)modules.data[0]).objfile);
+        }
+    }
+    else
+    {
+        for (int i = 0; i < modules.dim; i++)
+        {
+            m = cast(Module)modules.data[i];
+            if (global.params.verbose)
+                writef("code      %s\n", m.toChars());
+            if (global.params.obj)
+            {  
+				obj_start(cast(char*)toStringz(m.srcfile.toChars()));
+                m.genobjfile(global.params.multiobj);
+                obj_end(library, m.objfile);
+                obj_write_deferred(library);
+            }
+            if (global.errors)
+            {
+                if (!global.params.lib)
+                    m.deleteObjFile();
+            }
+            else
+            {
+                if (global.params.doDocComments)
+                    m.gendocfile();
+            }
+        }
+    }
+
+    if (global.params.lib && !global.errors)
+        library.write();
+
+    backend_term();
+    if (global.errors)
+        fatal();
+
+    if (!global.params.objfiles.dim)
+    {
+        if (global.params.link)
+            error("no object files to link");
+    }
+    else
+    {
+        if (global.params.link)
+            status = runLINK();
+
+        if (global.params.run)
+        {
+            if (!status)
+            {
+                status = runProgram();
+
+                /* Delete .obj files and .exe file
+                 */
+                for (int i = 0; i < modules.dim; i++)
+                {
+                    m = cast(Module)modules.data[i];
+                    m.deleteObjFile();
+                    if (global.params.oneobj)
+                        break;
+                }
+                deleteExeFile();
+            }
+        }
+    }
+
+    return status;
+}
\ No newline at end of file