Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c1b30d7
move arrayBoundsCheck() from the glue layer to funcsem.d, so that it …
rainers Jun 22, 2025
94c142e
remove tracing GC allocation on AA literals, it is an outlier as it i…
rainers Jun 22, 2025
6c3f1f5
expression printing with -vcg-ast should show lowerings
rainers Jun 22, 2025
2fc5587
add templated AA implementation binary comppatible with rt.aaa, call …
rainers Jun 22, 2025
f2e990a
generate TypeInfo_AssociativeArray members equals() and getHash() fro…
rainers Jun 22, 2025
f7cf663
interrpreter: allow assigning basic type values to lvalue
rainers Jun 22, 2025
c839205
Expression_toDt: support full slice of ArrayLiteralExp, identical to …
rainers Jun 22, 2025
84b0f25
fix #21456: foreach over associative array allows incompatible types …
rainers Jun 23, 2025
8db58d5
fix #21258: Phobos 3 build broken due to recent changes
rainers Jun 23, 2025
74508e1
replace AA runtime hooks in rt.aaa with their templated versions in c…
rainers Jun 23, 2025
f3dde3c
delete obsolete rt.aaa
rainers Jun 23, 2025
6304341
add missing update in expression.h, fix typos, add comment to AssocAr…
rainers Jun 24, 2025
65958b7
add comments to the IndexExp lowerings
rainers Jun 27, 2025
6d73689
add CallExp.loweredFrom and NotExp.loweredFrom instead of reconstruct…
rainers Jul 8, 2025
ddf6f6e
fix typo
rainers Jul 12, 2025
0179737
add pragma(inline,true) to simple wrapper functions
rainers Jul 12, 2025
8e8ce41
precompile bytesHash into druntime
rainers Jul 12, 2025
9192d88
avoid hashOf/keyEqual wrapper calls if unnecessary
rainers Jul 13, 2025
e187dc6
add changelog entry
rainers Jul 13, 2025
44489cb
use array ctor with initial elements
rainers Jul 16, 2025
3ef696d
use d_bool instead of bool in C++ header
rainers Jul 16, 2025
1e09cad
fix after rebase
rainers Jul 23, 2025
0a5e7d4
explicitly lower array literals for AA literal
rainers Jul 24, 2025
d9012e4
missing flags assignment, reserve keys/value array
rainers Jul 26, 2025
8398fb6
restore error on mutable array as key
rainers Jul 27, 2025
9ab10e1
_aaKeys, _aaValues: use preallocated array and copyEmplace instead of…
rainers Aug 1, 2025
d9758b0
fix evaluation order of InExp, print NotExp lowering with -vcg-ast
rainers Aug 3, 2025
6ef1415
use _d-prefix for AA compiler hooks consistently, remove Id symbols n…
rainers Aug 3, 2025
641cd7d
restore error "not an Lvalue"
rainers Aug 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions changelog/dmd.aa-lowered-to-templates.dd
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
The compiler now lowers associative array operations to a templated implementation in druntime

The compiler now lowers associative array operations to templates defined in core.internal.newaa
instead of relying on a precompiled implementation based on TypeInfo.

In addition to better performance by not having to go through TypeInfo and allowing inlining of
simple operations this paves the way for proper inference of
function attributes inherited from key and value constructors, toHash() on the key and comparison of
key values. This inference is currently mostly avoided to keep backward compatibility with
the runtime implementation that doesn't check function attributes.

Some changes that are the result of the refactoring:

- AA support no longer available at CTFE without object.d/newaa.d. Some operations used to work,
but now need the lowerings before these can be intercepted by the interpreter.

- creating an AA literal at runtime passes keys and values as arguments normally, not with
special move/blit operations, so more postblit/dtor operations can happen

- _d_assocarrayliteralTXTrace removed. Apart from the creation of associative array literals
no other AA operation is hooked for -profile-gc. You will now see the allocations as done
by the AA implementation.

- aa[key] = S() with S.ctor and S.opAssign is no longer a double lookup

- aa.remove(key) now works with alias this
10 changes: 0 additions & 10 deletions compiler/src/dmd/backend/drtlsym.d
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,6 @@ Symbol* getRtlsym(RTLSYM i) @trusted
case RTLSYM.MEMSETDOUBLE: symbolz(ps,FL.func,FREGSAVED,"_memsetDouble", 0, t); break;
case RTLSYM.MEMSETSIMD: symbolz(ps,FL.func,FREGSAVED,"_memsetSIMD",0, t); break;
case RTLSYM.MEMSETN: symbolz(ps,FL.func,FREGSAVED,"_memsetn", 0, t); break;
case RTLSYM.ASSOCARRAYLITERALTX: symbolz(ps,FL.func,FREGSAVED,"_d_assocarrayliteralTX", 0, t); break;
case RTLSYM.CALLFINALIZER: symbolz(ps,FL.func,FREGSAVED,"_d_callfinalizer", 0, t); break;
case RTLSYM.CALLINTERFACEFINALIZER: symbolz(ps,FL.func,FREGSAVED,"_d_callinterfacefinalizer", 0, t); break;
case RTLSYM.ALLOCMEMORY: symbolz(ps,FL.func,FREGSAVED,"_d_allocmemory", 0, t); break;
Expand All @@ -113,14 +112,6 @@ Symbol* getRtlsym(RTLSYM i) @trusted
case RTLSYM.ARRAYASSIGN_R: symbolz(ps,FL.func,FREGSAVED,"_d_arrayassign_r", 0, t); break;
case RTLSYM.ARRAYASSIGN_L: symbolz(ps,FL.func,FREGSAVED,"_d_arrayassign_l", 0, t); break;

/* Associative Arrays https://github.com/dlang/dmd/blob/master/druntime/src/rt/aaA.d */
case RTLSYM.AANEW: symbolz(ps,FL.func,FREGSAVED,"_aaNew", 0, t); break;
case RTLSYM.AAEQUAL: symbolz(ps,FL.func,FREGSAVED,"_aaEqual", 0, t); break;
case RTLSYM.AAINX: symbolz(ps,FL.func,FREGSAVED,"_aaInX", 0, t); break;
case RTLSYM.AADELX: symbolz(ps,FL.func,FREGSAVED,"_aaDelX", 0, t); break;
case RTLSYM.AAGETY: symbolz(ps,FL.func,FREGSAVED,"_aaGetY", 0, t); break;
case RTLSYM.AAGETRVALUEX: symbolz(ps,FL.func,FREGSAVED,"_aaGetRvalueX", 0, t); break;

case RTLSYM.EXCEPT_HANDLER3: symbolz(ps,FL.func,fregsaved,"_except_handler3", 0, tsclib); break;
case RTLSYM.CPP_HANDLER: symbolz(ps,FL.func,FREGSAVED,"_cpp_framehandler", 0, tsclib); break;
case RTLSYM.D_HANDLER: symbolz(ps,FL.func,FREGSAVED,"_d_framehandler", 0, tsclib); break;
Expand Down Expand Up @@ -155,7 +146,6 @@ Symbol* getRtlsym(RTLSYM i) @trusted

case RTLSYM.TRACECALLFINALIZER: symbolz(ps,FL.func,FREGSAVED,"_d_callfinalizerTrace", 0, t); break;
case RTLSYM.TRACECALLINTERFACEFINALIZER: symbolz(ps,FL.func,FREGSAVED,"_d_callinterfacefinalizerTrace", 0, t); break;
case RTLSYM.TRACEASSOCARRAYLITERALTX: symbolz(ps,FL.func,FREGSAVED,"_d_assocarrayliteralTXTrace", 0, t); break;
case RTLSYM.TRACEARRAYAPPENDCD: symbolz(ps,FL.func,FREGSAVED,"_d_arrayappendcdTrace", 0, t); break;
case RTLSYM.TRACEARRAYAPPENDWD: symbolz(ps,FL.func,FREGSAVED,"_d_arrayappendwdTrace", 0, t); break;
case RTLSYM.TRACEALLOCMEMORY: symbolz(ps,FL.func,FREGSAVED,"_d_allocmemoryTrace", 0, t); break;
Expand Down
8 changes: 0 additions & 8 deletions compiler/src/dmd/backend/rtlsym.d
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ enum RTLSYM
MEMSETSIMD,
MEMSETN,

ASSOCARRAYLITERALTX,
CALLFINALIZER,
CALLINTERFACEFINALIZER,
ALLOCMEMORY,
Expand All @@ -58,12 +57,6 @@ enum RTLSYM
ARRAYASSIGN_R,
ARRAYASSIGN_L,
ARRAYEQ2,
AANEW,
AAEQUAL,
AAINX,
AADELX,
AAGETY,
AAGETRVALUEX,

EXCEPT_HANDLER3,
CPP_HANDLER,
Expand Down Expand Up @@ -99,7 +92,6 @@ enum RTLSYM

TRACECALLFINALIZER,
TRACECALLINTERFACEFINALIZER,
TRACEASSOCARRAYLITERALTX,
TRACEARRAYAPPENDCD,
TRACEARRAYAPPENDWD,
TRACEALLOCMEMORY,
Expand Down
23 changes: 17 additions & 6 deletions compiler/src/dmd/ctfeexpr.d
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ UnionExp copyLiteral(Expression e)
AssocArrayLiteralExp r = ue.exp().isAssocArrayLiteralExp();
r.type = aae.type;
r.lowering = aae.lowering;
r.loweringCtfe = aae.loweringCtfe;
r.ownedByCtfe = OwnedBy.ctfe;
return ue;
}
Expand Down Expand Up @@ -1459,7 +1460,7 @@ UnionExp ctfeCat(Loc loc, Type type, Expression e1, Expression e2)
/* Given an AA literal 'ae', and a key 'e2':
* Return ae[e2] if present, or NULL if not found.
*/
Expression findKeyInAA(Loc loc, AssocArrayLiteralExp ae, Expression e2)
Expression findKeyInAA(Loc loc, AssocArrayLiteralExp ae, Expression e2, size_t* pidx = null)
{
/* Search the keys backwards, in case there are duplicate keys
*/
Expand All @@ -1470,6 +1471,8 @@ Expression findKeyInAA(Loc loc, AssocArrayLiteralExp ae, Expression e2)
const int eq = ctfeEqual(loc, EXP.equal, ekey, e2);
if (eq)
{
if (pidx)
*pidx = i;
return (*ae.values)[i];
}
}
Expand Down Expand Up @@ -1583,11 +1586,6 @@ Expression ctfeCast(UnionExp* pue, Loc loc, Type type, Type to, Expression e, bo
*/
void assignInPlace(Expression dest, Expression src)
{
if (!(dest.op == EXP.structLiteral || dest.op == EXP.arrayLiteral || dest.op == EXP.string_))
{
printf("invalid op %d %d\n", src.op, dest.op);
assert(0);
}
Expressions* oldelems;
Expressions* newelems;
if (dest.op == EXP.structLiteral)
Expand Down Expand Up @@ -1622,6 +1620,16 @@ void assignInPlace(Expression dest, Expression src)
sliceAssignStringFromArrayLiteral(dest.isStringExp(), src.isArrayLiteralExp(), 0);
return;
}
else if (dest.op == EXP.int64 && src.op == EXP.int64)
{
dest.isIntegerExp().setInteger(src.isIntegerExp().getInteger());
return;
}
else if (dest.op == EXP.float64 && src.op == EXP.float64)
{
dest.isRealExp().value = src.isRealExp().value;
return;
}
else
{
printf("invalid op %d %d\n", src.op, dest.op);
Expand Down Expand Up @@ -1829,6 +1837,9 @@ bool isCtfeValueValid(Expression newval)
(
(e1.op == EXP.structLiteral || e1.op == EXP.arrayLiteral) && isCtfeValueValid(e1) ||
e1.op == EXP.variable ||
e1.op == EXP.int64 ||
e1.op == EXP.float64 ||
e1.op == EXP.string_ ||
e1.op == EXP.dotVariable && isCtfeReferenceValid(e1) ||
e1.op == EXP.index && isCtfeReferenceValid(e1) ||
e1.op == EXP.slice && e1.type.toBasetype().ty == Tsarray
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/dcast.d
Original file line number Diff line number Diff line change
Expand Up @@ -2862,7 +2862,9 @@ Expression castTo(Expression e, Scope* sc, Type t, Type att = null)
(*ae.keys)[i] = ex;
}
ae.type = t;
semanticTypeInfo(sc, ae.type);
ae.lowering = null; // we need a different lowering
ae.loweringCtfe = null;
ae.expressionSemantic(sc);
return ae;
}
return visit(e);
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dmd/declaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ extern (C++) class VarDeclaration : Declaration
{
isdataseg = 2; // The Variables does not go into the datasegment

if (!canTakeAddressOf())
if (!canTakeAddressOf() || (storage_class & STC.exptemp))
{
return false;
}
Expand Down Expand Up @@ -1395,6 +1395,8 @@ extern (C++) final class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration
extern (C++) final class TypeInfoAssociativeArrayDeclaration : TypeInfoDeclaration
{
Type entry; // type of TypeInfo_AssociativeArray.Entry!(t.index, t.next)
Dsymbol xopEqual; // implementation of TypeInfo_AssociativeArray.equals
Dsymbol xtoHash; // implementation of TypeInfo_AssociativeArray.getHash

extern (D) this(Type tinfo)
{
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dmd/declaration.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,8 @@ class TypeInfoAssociativeArrayDeclaration final : public TypeInfoDeclaration
{
public:
Type* entry;
Dsymbol* xopEqual;
Dsymbol* xtoHash;

static TypeInfoAssociativeArrayDeclaration *create(Type *tinfo);

Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dmd/delegatize.d
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,11 @@ private void lambdaSetParent(Expression e, FuncDeclaration fd)
iz.accept(this);
}
}
override void visit(AssocArrayLiteralExp e)
{
if (e.lowering)
walkPostorder(e.lowering, this);
}
}

scope LambdaSetParent lsp = new LambdaSetParent(fd);
Expand Down
Loading
Loading