New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
async/closure environment does not align local variables #22419
Comments
align
pragma on variables in async/closure environment does not align
What does the C output for this look like? Does C normally allow aligning variables on the stack? |
@Varriount first, a more minimal example, type
ValidatorPubKey = object
#blob {.align: 16}: array[96, byte]
blob: array[96, byte]
iterator count0(): int {.closure.} =
var x {.align: 16}: uint8
var y {.align: 16}: ValidatorPubKey
let value = cast[uint64](unsafeAddr y)
echo "f() = ", cast[uint64](unsafeAddr y), " mod(8) = ", value mod 8
yield 0
for _ in count0():
discard Which gets compiled into N_LIB_PRIVATE N_CLOSURE(NI, count0__a_u3)(void* ClE_0) {
NI result;
tyObject_Env_adotnim_count0___c3bxH9barzvxNMwrfFOIflA* colonenvP_;
NIM_BOOL* nimErr_;
{nimErr_ = nimErrorFlag();
result = (NI)0;
colonenvP_ = (tyObject_Env_adotnim_count0___c3bxH9barzvxNMwrfFOIflA*) ClE_0;
while (1) {
if (!1) goto LA1;
{
NimStringV2 colontmpD_;
NimStringV2 colontmpD__2;
tyArray__sMpvt1sOxOJ3LFGulnbeMQ T4_;
colontmpD_.len = 0; colontmpD_.p = NIM_NIL;
colontmpD__2.len = 0; colontmpD__2.p = NIM_NIL;
switch ((*colonenvP_).colonstate_) {
case -1:
if (colontmpD__2.p && !(colontmpD__2.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD__2.p);
}
if (colontmpD_.p && !(colontmpD_.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD_.p);
}
goto BeforeRet_;
case 0: goto STATE0;
case 1: goto STATE1;
}
STATE0: ;
(*colonenvP_).x1 = (NU8)0;
nimZeroMem((void*)(&(*colonenvP_).y2), sizeof(tyObject_ValidatorPubKey__bQ4vtAU3wDlHhbTUukGMVg));
(*colonenvP_).value3 = ((NU64) (ptrdiff_t) ((&(*colonenvP_).y2)));
T4_[0] = TM__R8RUzYq41iOx0I9bZH5Nyrw_4;
colontmpD_ = dollar___systemZdollars_u14(((NU64) (ptrdiff_t) ((&(*colonenvP_).y2))));
if (NIM_UNLIKELY(*nimErr_)) goto LA3_;
T4_[1] = colontmpD_;
T4_[2] = TM__R8RUzYq41iOx0I9bZH5Nyrw_6;
colontmpD__2 = dollar___systemZdollars_u14((NU64)((NU64)((*colonenvP_).value3) % (NU64)(8ULL)));
if (NIM_UNLIKELY(*nimErr_)) goto LA3_;
T4_[3] = colontmpD__2;
echoBinSafe(T4_, 4);
(*colonenvP_).colonstate_ = ((NI)1);
result = ((NI)0);
if (colontmpD__2.p && !(colontmpD__2.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD__2.p);
}
if (colontmpD_.p && !(colontmpD_.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD_.p);
}
goto BeforeRet_;
STATE1: ;
(*colonenvP_).colonstate_ = ((NI)-1);
if (colontmpD__2.p && !(colontmpD__2.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD__2.p);
}
if (colontmpD_.p && !(colontmpD_.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD_.p);
}
goto LA2;
{
LA3_:;
}
{
if (colontmpD__2.p && !(colontmpD__2.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD__2.p);
}
if (colontmpD_.p && !(colontmpD_.p->cap & NIM_STRLIT_FLAG)) {
deallocShared(colontmpD_.p);
}
}
if (NIM_UNLIKELY(*nimErr_)) goto BeforeRet_;
} LA2: ;
} LA1: ;
}BeforeRet_: ;
popFrame();
return result;
} The salient difference is this
through which For example:
Where struct tyObject_Env_adotnim_count0___c3bxH9barzvxNMwrfFOIflA {
RootObj Sup;
NI colonstate_;
NU8 x1;
tyObject_ValidatorPubKey__bQ4vtAU3wDlHhbTUukGMVg y2;
NU64 value3;
}; is the closure iterator's environment. That is, it's using C's It is, however, capable of doing the alignment, because if one instead writes: type
ValidatorPubKey = object
blob {.align: 16}: array[96, byte]
iterator count0(): int {.closure.} =
var x: uint8
var y: ValidatorPubKey
let value = cast[uint64](unsafeAddr y)
echo "f() = ", cast[uint64](unsafeAddr y), " mod(8) = ", value mod 8
yield 0
for _ in count0():
discard and removes the The only difference adding the
that is, it uses the |
It is supposed to be divided by 8 and leaves a remainder of 0, right? just like f() = 139669055053968 mod(8) = 0
e() = 140730649107728 mod(8) = 0 |
That's the intent, yes. Ideally even without needing the
I'd consider (a) to be a probably-bug in itself, but even if one disagrees, (b) definitely is. |
without explicit align, the alignment of also, with |
#22425) * fixes #22419; async/closure environment does not align local variables * Apply suggestions from code review * Update tests/align/talign.nim Co-authored-by: Jacek Sieka <arnetheduck@gmail.com> * apply code review * update tests --------- Co-authored-by: Jacek Sieka <arnetheduck@gmail.com> (cherry picked from commit 5334dc9)
#22425) * fixes #22419; async/closure environment does not align local variables * Apply suggestions from code review * Update tests/align/talign.nim Co-authored-by: Jacek Sieka <arnetheduck@gmail.com> * apply code review * update tests --------- Co-authored-by: Jacek Sieka <arnetheduck@gmail.com> (cherry picked from commit 5334dc9)
Description
Nim Version
Current Output
Expected Output
Aligned local variables in closure environment (with or without
align
pragmas, but here evenalign
doesn't work around the issue).Possible Solution
No response
Additional Information
No response
The text was updated successfully, but these errors were encountered: