D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 20154 - bad closure if local variables have larger alignment requirements
Summary: bad closure if local variables have larger alignment requirements
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 All
: P3 normal
Assignee: No Owner
URL:
Keywords: backend, wrong-code
Depends on:
Blocks:
 
Reported: 2019-08-23 09:35 UTC by Rainer Schuetze
Modified: 2024-12-13 19:05 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Rainer Schuetze 2019-08-23 09:35:35 UTC
If a local variable has larger alignment requirements, closures that capture function arguments can fail:

struct SpinLock
{
    align(64) int x;
}

void collectReferences(int x) //ref HashTab references)
{
	SpinLock lock; // dmd BUG: alignment causes bad capture!

	void mark() scope nothrow
	{
		assert (x == 7);
	}

	mark();
}

void main()
{
	collectReferences(7);
}


For Win64, RSP is aligned according to alignof(SpinLock) for alignments 32-128. This makes the closure offset for the function argument x non-constant.

Side note: no alignment happens for align(256) or higher.

For Win32, alignment is silently omitted.
Comment 1 Walter Bright 2020-08-09 03:35:55 UTC
The alignment code is emitted for Win64, but not for Win32. But you listed the bug applying to x86_64.

So please clarify:

Is this working for 64 bit platforms?
Comment 2 Walter Bright 2020-08-09 03:42:43 UTC
Currently, stack alignment is enforced only for 64 bit compilations and 32 bit OSX compilations. See the setting of `enforcealign` in codgen() in cgcod.d.
Comment 3 Walter Bright 2020-08-09 04:17:41 UTC
A somewhat more illustrative test:


struct SpinLock
{
    align(64)
	int x;
}

void collectReferences(int x) //ref HashTab references)
{
    SpinLock lock = SpinLock(8); // dmd BUG: alignment causes bad capture!

    void mark() scope nothrow
    {
	assert(lock.x == 8);
	assert(x == 7);
    }

    mark();
}

void main()
{
    collectReferences(7);
}
Comment 4 Rainer Schuetze 2020-08-09 05:53:25 UTC
(In reply to Walter Bright from comment #1)
> The alignment code is emitted for Win64, but not for Win32. But you listed
> the bug applying to x86_64.

Win32 passes the assert, but ignores alignments.

> 
> So please clarify:
> 
> Is this working for 64 bit platforms?

No.
Comment 5 Walter Bright 2020-08-09 07:09:35 UTC
Thanks, I think I understand it now. But the solution isn't obvious :-/
Comment 6 dlangBugzillaToGithub 2024-12-13 19:05:08 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/17920

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB