Skip to content

Commit 1b0c619

Browse files
committed
Win64 ABI: Pass/return delegates like slices - in (up to) 2 GP registers
I expect this to be slightly more performant than the previous behavior, where a delegate was treated like a corresponding struct, passed via hidden pointer and returned via sret. The primary motivation is a smooth preparation for PR #3578 - in order to allow people to experiment with `-preview=in` without recompiling druntime and Phobos, `in` slices and delegates must not be passed by-ref with `-preview=in` (see dlang/dmd#11828). This would have required a special case for delegates on Win64, which is IMO better handled this way.
1 parent 6343bf0 commit 1b0c619

File tree

2 files changed

+8
-3
lines changed

2 files changed

+8
-3
lines changed

gen/abi-win64.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ struct Win64TargetABI : TargetABI {
7171

7272
// Remaining aggregates which can NOT be rewritten as integers (size > 8
7373
// bytes or not a power of 2) are passed by ref to hidden copy.
74-
return isAggregate(t) && !canRewriteAsInt(t);
74+
// LDC-specific exceptions: slices and delegates are left alone (as non-
75+
// rewritten IR structs) and passed/returned as 2 separate args => passed in
76+
// up to 2 GP registers and returned in RAX & RDX.
77+
return isAggregate(t) && !canRewriteAsInt(t) && t->ty != Tarray &&
78+
t->ty != Tdelegate;
7579
}
7680

7781
public:
@@ -113,6 +117,7 @@ struct Win64TargetABI : TargetABI {
113117
// are returned in a register (RAX, or XMM0 for single float/ifloat/
114118
// double/idouble)
115119
// * 80-bit real/ireal are returned on the x87 stack
120+
// * LDC-specific: slices and delegates are returned in RAX & RDX
116121
// * all other types are returned via sret
117122
return passPointerToHiddenCopy(rt, /*isReturnValue=*/true, tf->linkage);
118123
}

gen/dibuilder.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1255,9 +1255,9 @@ void DIBuilder::EmitLocalVariable(llvm::Value *ll, VarDeclaration *vd,
12551255
if (isaArgument(ll) && addr.empty()) {
12561256
forceAsLocal = true;
12571257
} else {
1258-
// 2) dynamic arrays and vectors
1258+
// 2) dynamic arrays, delegates and vectors
12591259
TY ty = type->toBasetype()->ty;
1260-
if (ty == Tarray || ty == Tvector)
1260+
if (ty == Tarray || ty == Tdelegate || ty == Tvector)
12611261
forceAsLocal = true;
12621262
}
12631263
}

0 commit comments

Comments
 (0)