Thread overview
[Issue 10664] Win64: exception handling does not work with COMDAT folding
Mar 19, 2015
Temtaime
Aug 09, 2020
Walter Bright
Aug 09, 2020
Rainer Schuetze
Aug 29, 2020
Walter Bright
Sep 15, 2020
Walter Bright
Sep 15, 2020
Walter Bright
Sep 15, 2020
Dlang Bot
Sep 15, 2020
Dlang Bot
March 19, 2015
https://issues.dlang.org/show_bug.cgi?id=10664

Temtaime <temtaime@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |temtaime@gmail.com

--- Comment #1 from Temtaime <temtaime@gmail.com> ---
Is there any fix not workaround ?
It increases .exe's size significantly.

--
June 09, 2015
https://issues.dlang.org/show_bug.cgi?id=10664

Andrei Alexandrescu <andrei@erdani.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|D1 & D2                     |D2

--
August 09, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #2 from Walter Bright <bugzilla@digitalmars.com> ---
It would be easier to understand without the templates, lambdas, lazy parameters, etc. :-/

--
August 09, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

--- Comment #3 from Rainer Schuetze <r.sagitario@gmx.de> ---
Here's a version without lazy and templates:

import core.exception;

Exception collectExceptionE(int delegate () expression, ref int result)
{
    try
    {
        result = expression();
    }
    catch (Exception e)
    {
        return e;
    }
    return null;
}

RangeError collectExceptionR(int delegate () expression, ref int result)
{
    try
    {
        result = expression();
    }
    catch (RangeError e)
    {
        return e;
    }
    return null;
}

void main()
{
    int b;
    int foo() { throw new Exception("blah"); }
    assert(collectExceptionE(&foo, b));

    int[] a = new int[3];
    int goo() { return a[4]; }
    collectExceptionR(&goo, b);
}

I suspect that the functions need to be the exact same code, and only the associated exception data differs. That's also why you cannot easily eliminate the delegate call.

Please note that you have to remove /OPT:NOICF from sc.ini to reproduce, as it was added as a workaround.

--
August 29, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |backend

--
September 15, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

--- Comment #4 from Walter Bright <bugzilla@digitalmars.com> ---
You're right, it's the handler table that is different. The handler table is all based on offsets from the start of the function, so that works. The only pointer in it is the pointer to the catch type (the `*__ClassZ` symbols), and hence the only actual difference in the handler table.

The best fix I can think of for this is to embed in the catch blocks a reference to the catch type. Then functions that differ only in catch type won't be merged, and /OPT:NOICF will no longer be needed.

--
September 15, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

--- Comment #5 from Walter Bright <bugzilla@digitalmars.com> ---
I.e. this works:

import core.exception;
import core.bitop;

Exception collectExceptionE(int delegate () expression, ref int result)
{
    try
    {
        result = expression();
    }
    catch (Exception e)
    {
        core.bitop.volatileLoad(cast(size_t*)Exception.classinfo); <*****
        return e;
    }
    return null;
}

RangeError collectExceptionR(int delegate () expression, ref int result)
{
    try
    {
        result = expression();
    }
    catch (RangeError e)
    {
        core.bitop.volatileLoad(cast(size_t*)RangeError.classinfo); <*****
        return e;
    }
    return null;
}

void main()
{
    int b;
    int foo() { throw new Exception("blah"); }
    assert(collectExceptionE(&foo, b));

    int[] a = new int[3];
    int goo() { return a[4]; }
    collectExceptionR(&goo, b);
}

--
September 15, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |pull

--- Comment #6 from Dlang Bot <dlang-bot@dlang.rocks> ---
@WalterBright created dlang/dmd pull request #11736 "fix Issue 10664 - Win64: exception handling does not work with COMDAT…" fixing this issue:

- fix Issue 10664 - Win64: exception handling does not work with COMDAT folding

https://github.com/dlang/dmd/pull/11736

--
September 15, 2020
https://issues.dlang.org/show_bug.cgi?id=10664

Dlang Bot <dlang-bot@dlang.rocks> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |FIXED

--- Comment #7 from Dlang Bot <dlang-bot@dlang.rocks> ---
dlang/dmd pull request #11736 "fix Issue 10664 - Win64: exception handling does not work with COMDAT…" was merged into master:

- f3d96a38deee69fdfaabe49cd1a6c5a2b53563ce by Walter Bright:
  fix Issue 10664 - Win64: exception handling does not work with COMDAT folding

https://github.com/dlang/dmd/pull/11736

--