diff --git a/e2ir.c b/e2ir.c
index 6c3f6fd..382677e 100644
--- a/e2ir.c
+++ b/e2ir.c
@@ -2151,28 +2151,39 @@ elem *InExp::toElem(IRState *irs)
     elem *keyti;
     TypeAArray *taa = (TypeAArray *)e2->type->toBasetype();
 
-
-    // set to:
-    //  aaIn(aa, keyti, key);
-
-    if (tybasic(key->Ety) == TYstruct)
+    if (TypeAArray::new_abi())
     {
-        key = el_una(OPstrpar, TYstruct, key);
-        key->Enumbytes = key->E1->Enumbytes;
-        assert(key->Enumbytes);
-    }
-    else if (tybasic(key->Ety) == TYarray && taa->index->ty == Tsarray)
-    {   // e2->elem() turns string literals into a TYarray, so the
-        // length is lost. Restore it.
-        key = el_una(OPstrpar, TYstruct, key);
-        assert(e1->type->size() == taa->index->size());
-        key->Enumbytes = taa->index->size();
+        //void* _d_aaIn(TypeInfo_AssociativeArray ti, AA aa, void* pkey)
+        Symbol *s = taa->aaGetSymbol("In", 0);
+        elem *ti = taa->getInternalTypeInfo(NULL)->toElem(irs);
+        elem *pkey = addressElem(key, NULL);
+        ep = el_params(pkey, aa, ti, NULL);
+        e = el_bin(OPcall, type->totym(), el_var(s), ep);
     }
+    else
+    {
 
-    Symbol *s = taa->aaGetSymbol("In", 0);
-    keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
-    ep = el_params(key, keyti, aa, NULL);
-    e = el_bin(OPcall, type->totym(), el_var(s), ep);
+        if (tybasic(key->Ety) == TYstruct)
+        {
+            key = el_una(OPstrpar, TYstruct, key);
+            key->Enumbytes = key->E1->Enumbytes;
+            assert(key->Enumbytes);
+        }
+        else if (tybasic(key->Ety) == TYarray && taa->index->ty == Tsarray)
+        {   // e2->elem() turns string literals into a TYarray, so the
+            // length is lost. Restore it.
+            key = el_una(OPstrpar, TYstruct, key);
+            assert(e1->type->size() == taa->index->size());
+            key->Enumbytes = taa->index->size();
+        }
+
+        // set to:
+        //  aaIn(aa, keyti, key);
+        Symbol *s = taa->aaGetSymbol("In", 0);
+        keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
+        ep = el_params(key, keyti, aa, NULL);
+        e = el_bin(OPcall, type->totym(), el_var(s), ep);
+    }
 
     el_setLoc(e,loc);
     return e;
@@ -2191,17 +2202,29 @@ elem *RemoveExp::toElem(IRState *irs)
     elem *ep;
     elem *keyti;
 
-    if (tybasic(ekey->Ety) == TYstruct)
+    if (TypeAArray::new_abi())
     {
-        ekey = el_una(OPstrpar, TYstruct, ekey);
-        ekey->Enumbytes = ekey->E1->Enumbytes;
-        assert(ekey->Enumbytes);
+        //void _d_aaDel(TypeInfo_AssociativeArray ti, AA aa, void* pkey)
+        Symbol *s = taa->aaGetSymbol("Del", 0);
+        elem *ti = taa->getInternalTypeInfo(NULL)->toElem(irs);
+        elem *pkey = addressElem(ekey, NULL);
+        ep = el_params(pkey, ea, ti, NULL);
+        e = el_bin(OPcall, TYnptr, el_var(s), ep);
     }
+    else
+    {
+        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->key->getInternalTypeInfo(NULL)->toElem(irs);
-    ep = el_params(ekey, keyti, ea, NULL);
-    e = el_bin(OPcall, TYnptr, el_var(s), ep);
+        Symbol *s = taa->aaGetSymbol("Del", 0);
+        keyti = taa->key->getInternalTypeInfo(NULL)->toElem(irs);
+        ep = el_params(ekey, keyti, ea, NULL);
+        e = el_bin(OPcall, TYnptr, el_var(s), ep);
+    }
 
     el_setLoc(e,loc);
     return e;
@@ -3185,6 +3208,11 @@ elem *DeleteExp::toElem(IRState *irs)
             elem *ep;
             elem *keyti;
 
+            if (TypeAArray::new_abi()) {
+                //this is deprecated -> I don't care
+                assert(0);
+            }
+
             if (tybasic(ekey->Ety) == TYstruct)
             {
                 ekey = el_una(OPstrpar, TYstruct, ekey);
@@ -4049,7 +4077,56 @@ elem *IndexExp::toElem(IRState *irs)
 
     //printf("IndexExp::toElem() %s\n", toChars());
     t1 = e1->type->toBasetype();
-    if (t1->ty == Taarray)
+    if (TypeAArray::new_abi() && t1->ty == Taarray)
+    {
+        //void* _d_aaGet(TypeInfo_AssociativeArray ti, AA* aa, void* pkey)
+        //void* _d_aaGetRvalue(TypeInfo_AssociativeArray ti, AA aa, void* pkey)
+
+        TypeAArray *taa = (TypeAArray *)t1;
+        elem *ti;
+        elem *ep;
+        Symbol *s;
+
+        // n2 becomes the index, also known as the key
+        elem *n2 = e2->toElem(irs);
+        if (modifiable)
+        {
+            n1 = el_una(OPaddr, TYnptr, n1);
+            s = taa->aaGetSymbol("Get", 1);
+        }
+        else
+        {
+            s = taa->aaGetSymbol("GetRvalue", 1);
+        }
+        //printf("taa->key = %s\n", taa->key->toChars());
+        ti = taa->getInternalTypeInfo(NULL)->toElem(irs);
+        //keyti = taa->key->getTypeInfo(NULL)->toElem(irs);
+        //printf("keyti:\n");
+        //elem_print(keyti);
+        elem *n2p = addressElem(n2, NULL);
+        ep = el_params(n2p, n1, ti, NULL);
+        e = el_bin(OPcall, TYnptr, el_var(s), ep);
+        if (global.params.useArrayBounds)
+        {
+            elem *n;
+            elem *ea;
+
+            n = el_same(&e);
+
+            // Construct: ((e || ModuleAssert(line)),n)
+            Symbol *sassert;
+
+            sassert = irs->blx->module->toModuleArray();
+            ea = el_bin(OPcall,TYvoid,el_var(sassert),
+                el_long(TYint, loc.linnum));
+            e = el_bin(OPoror,TYvoid,e,ea);
+            e = el_bin(OPcomma, TYnptr, e, n);
+        }
+        e = el_una(OPind, type->totym(), e);
+        if (tybasic(e->Ety) == TYstruct)
+            e->Enumbytes = type->size();
+    }
+    else if (!TypeAArray::new_abi() && t1->ty == Taarray)
     {
         // set to:
         //      *aaGet(aa, keyti, valuesize, index);
@@ -4251,8 +4328,54 @@ elem *ArrayLiteralExp::toElem(IRState *irs)
     return e;
 }
 
+//evaluate each exp in exps (where each item has the given type) and put the
+//results into an array on the stack
+//return pointer to the array
+static elem* exparray_to_stack(IRState *irs, Type *type, Expressions *exps)
+{
+    elem *e = NULL;
+    size_t dim = exps->dim;
+    ::type *catype = type_allocn(TYarray, type->toCtype());
+    catype->Tdim = dim;
+    Symbol *sret = symbol_genauto(catype);
+
+    for (size_t i = 0; i < dim; i++)
+    {
+        Expression *el = (Expression *)exps->data[i];
+        assert(el->type == type);
+        elem *ep = addressElem(el->toElem(irs), NULL);
+        elem *eoffs = el_long(TYnptr, type->size() * i);
+        elem *ee = el_bin(OPadd, TYnptr, el_ptr(sret), eoffs);
+        elem *ec = el_bin(OPmemcpy, TYnptr, ee, el_param(ep, el_long(TYnptr, type->size())));
+        e = el_combine(e, ec);
+    }
+
+    return el_combine(e, el_ptr(sret));
+}
 
 elem *AssocArrayLiteralExp::toElem(IRState *irs)
+{
+    if (!TypeAArray::new_abi())
+        return toElem_old(irs);
+
+    //BB* _d_aaLiteral(TypeInfo_AssociativeArray ti, size_t length, void *keys, void *values)
+
+    TypeAArray *taa = (TypeAArray *)type;
+
+    elem *ekeys = exparray_to_stack(irs, taa->key, keys);
+    elem *evals = exparray_to_stack(irs, taa->next, values);
+
+    Symbol *s = taa->aaGetSymbol("Literal", 0);
+
+    elem *ti = taa->getInternalTypeInfo(NULL)->toElem(irs);
+    elem *ep = el_params(evals, ekeys, el_long(TYnptr, keys->dim), ti, NULL);
+    elem *e = el_bin(OPcall, TYnptr, el_var(s), ep);
+
+    el_setLoc(e, loc);
+    return e;
+}
+
+elem *AssocArrayLiteralExp::toElem_old(IRState *irs)
 {   elem *e;
     size_t dim;
 
diff --git a/expression.h b/expression.h
index daf6e3f..eb2a88e 100644
--- a/expression.h
+++ b/expression.h
@@ -412,6 +412,7 @@ struct AssocArrayLiteralExp : Expression
     Expression *semantic(Scope *sc);
     int isBool(int result);
     elem *toElem(IRState *irs);
+    elem *toElem_old(IRState *irs);
     int checkSideEffect(int flag);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
diff --git a/idgen.c b/idgen.c
index 60de3a6..c3313a1 100644
--- a/idgen.c
+++ b/idgen.c
@@ -212,11 +212,18 @@ Msgtable msgtable[] =
     { "aaKeys", "_aaKeys" },
     { "aaValues", "_aaValues" },
     { "aaRehash", "_aaRehash" },
+    { "aaLen2", "_d_aaLen" },
+    { "aaKeys2", "_d_aaKeys" },
+    { "aaValues2", "_d_aaValues" },
+    { "aaRehash2", "_d_aaRehash" },
     { "monitorenter", "_d_monitorenter" },
     { "monitorexit", "_d_monitorexit" },
     { "criticalenter", "_d_criticalenter" },
     { "criticalexit", "_d_criticalexit" },
 
+    // AA runtime interface ABI compatibility hack
+    { "_new_abi" },
+
     // For pragma's
     { "GNU_asm" },
     { "lib" },
diff --git a/mars.c b/mars.c
index 06909fc..6c319b2 100644
--- a/mars.c
+++ b/mars.c
@@ -396,6 +396,7 @@ int main(int argc, char *argv[])
 #endif
 
     VersionCondition::addPredefinedGlobalIdent("D_HavePointerMap");
+    VersionCondition::addPredefinedGlobalIdent("D_NewAA"); //new AA runtime ABI
 
     VersionCondition::addPredefinedGlobalIdent("LittleEndian");
     //VersionCondition::addPredefinedGlobalIdent("D_Bits");
diff --git a/mtype.c b/mtype.c
index 56fc3f0..3876268 100644
--- a/mtype.c
+++ b/mtype.c
@@ -47,6 +47,8 @@
 #include "import.h"
 #include "aggregate.h"
 #include "hdrgen.h"
+#include "module.h"
+#include "cond.h"
 
 FuncDeclaration *hasThis(Scope *sc);
 
@@ -2278,6 +2280,25 @@ TypeAArray::TypeAArray(Type *t, Type *index)
     this->key = NULL;
 }
 
+int TypeAArray::new_abi()
+{
+    static int use_new_abi = 0;
+    if (use_new_abi == 0)
+    {
+        ClassDeclaration *cls = Type::typeinfoassociativearray;
+        assert(cls);
+        if (cls->search(NULL, Id::_new_abi, 0))
+        {
+            use_new_abi = 1;
+        }
+        else
+        {
+            use_new_abi = 2;
+        }
+    }
+    return use_new_abi == 1;
+}
+
 Type *TypeAArray::syntaxCopy()
 {
     Type *t = next->syntaxCopy();
@@ -2402,6 +2423,78 @@ Expression *TypeAArray::dotExp(Scope *sc, Expression *e, Identifier *ident)
 #if LOGDOTEXP
     printf("TypeAArray::dotExp(e = '%s', ident = '%s')\n", e->toChars(), ident->toChars());
 #endif
+
+    if (!new_abi())
+        return dotExp_old(sc, e, ident);
+
+    if (ident == Id::length)
+    {
+        Expression *ec;
+        FuncDeclaration *fd;
+        Expressions *arguments;
+
+        fd = FuncDeclaration::genCfunc(Type::tsize_t, Id::aaLen2);
+        ec = new VarExp(0, fd);
+        arguments = new Expressions();
+        arguments->push(getInternalTypeInfo(sc));
+        arguments->push(e);
+        e = new CallExp(e->loc, ec, arguments);
+        e->type = fd->type->next;
+    }
+    else if (ident == Id::keys)
+    {
+        Expression *ec;
+        FuncDeclaration *fd;
+        Expressions *arguments;
+        int size = key->size(e->loc);
+
+        assert(size);
+        fd = FuncDeclaration::genCfunc(Type::tindex, Id::aaKeys2);
+        ec = new VarExp(0, fd);
+        arguments = new Expressions();
+        arguments->push(getInternalTypeInfo(sc));
+        arguments->push(e);
+        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::aaValues2);
+        ec = new VarExp(0, fd);
+        arguments = new Expressions();
+        arguments->push(getInternalTypeInfo(sc));
+        arguments->push(e);
+        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::aaRehash2);
+        ec = new VarExp(0, fd);
+        arguments = new Expressions();
+        arguments->push(getInternalTypeInfo(sc));
+        arguments->push(e->addressOf(sc));
+        e = new CallExp(e->loc, ec, arguments);
+        e->type = this;
+    }
+    else
+    {
+        e = Type::dotExp(sc, e, ident);
+    }
+    return e;
+}
+
+//dotExp for old AA ABI
+Expression *TypeAArray::dotExp_old(Scope *sc, Expression *e, Identifier *ident)
+{
     if (ident == Id::length)
     {
         Expression *ec;
diff --git a/mtype.h b/mtype.h
index 4992ec8..b7967c7 100644
--- a/mtype.h
+++ b/mtype.h
@@ -409,6 +409,7 @@ struct TypeAArray : TypeArray
     void toDecoBuffer(OutBuffer *buf);
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
+    Expression *dotExp_old(Scope *sc, Expression *e, Identifier *ident);
     Expression *defaultInit(Loc loc);
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     int isZeroInit(Loc loc);
@@ -420,6 +421,9 @@ struct TypeAArray : TypeArray
     // Back end
     Symbol *aaGetSymbol(const char *func, int flags);
 
+    //use new ABI for AA runtime calls
+    static int new_abi();
+
     type *toCtype();
 };
 
diff --git a/statement.c b/statement.c
index a2f4562..cb1a0d9 100644
--- a/statement.c
+++ b/statement.c
@@ -1748,7 +1748,40 @@ Statement *ForeachStatement::semantic(Scope *sc)
                 }
             }
 
-            if (tab->ty == Taarray)
+            if (TypeAArray::new_abi() && tab->ty == Taarray)
+            {
+                // Check types
+                Parameter *arg = (Parameter *)arguments->data[0];
+                if (dim == 2)
+                {
+                    if (arg->storageClass & 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 = (Parameter *)arguments->data[1];
+                }
+                if (!arg->type->equals(taa->nextOf()))
+                    error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
+
+                //extern (D) alias int delegate(void *) dg_t;
+                //int _d_aaApply(TypeInfo_AssociativeArray ti, AA aa, dg_t dg)
+                //extern (D) alias int delegate(void *, void *) dg2_t;
+                //int _d_aaApply2(TypeInfo_AssociativeArray ti, AA aa, dg2_t dg)
+
+                FuncDeclaration *fdapply;
+                if (dim == 2)
+                    fdapply = FuncDeclaration::genCfunc(Type::tindex, "_d_aaApply2");
+                else
+                    fdapply = FuncDeclaration::genCfunc(Type::tindex, "_d_aaApply");
+                ec = new VarExp(0, fdapply);
+                Expressions *exps = new Expressions();
+                exps->push(taa->getInternalTypeInfo(sc));
+                exps->push(aggr);
+                exps->push(flde);
+                e = new CallExp(loc, ec, exps);
+                e->type = Type::tindex; // don't run semantic() on e
+            }
+            else if (!TypeAArray::new_abi() && tab->ty == Taarray)
             {
                 // Check types
                 Parameter *arg = (Parameter *)arguments->data[0];
diff --git a/tocsym.c b/tocsym.c
index 1df4f17..18f37e7 100644
--- a/tocsym.c
+++ b/tocsym.c
@@ -719,8 +719,15 @@ Symbol *TypeAArray::aaGetSymbol(const char *func, int flags)
         else
             sprintf(id, "_aa%s%s", func, buf.data);
 #else
-        id = (char *)alloca(3 + strlen(func) + 1);
-        sprintf(id, "_aa%s", func);
+        id = (char *)alloca(5 + strlen(func) + 1);
+        if (new_abi())
+        {
+            sprintf(id, "_d_aa%s", func);
+        }
+        else
+        {
+            sprintf(id, "_aa%s", func);
+        }
 #endif
         if (!sarray)
             sarray = new Array();
