<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - WinException: Off-by-one building IP2state table"
   href="https://bugs.llvm.org/show_bug.cgi?id=46358">46358</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>WinException: Off-by-one building IP2state table
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Backend: X86
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>sneves@dei.uc.pt
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>craig.topper@gmail.com, llvm-bugs@lists.llvm.org, llvm-dev@redking.me.uk, spatel+llvm@rotateright.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Consider the following example C++ code:


#include <cstdio>

int main(int argc, char* argv[]) {
    try {
        try {
            puts(new char[argc]());
        } catch(...) {
            return -2;
        }
    } catch(...) {
        return -1;
    }
}


It doesn't really matter what it does, all it matters is that there are a few
try..catch blocks that don't get elided. Compiling this with `clang-cl.exe -O2
-EHsc /FA /Fatest.asm test.cpp` we get in test.asm

        $ip2state$main:
        .long   .Lfunc_begin0@IMGREL    # IP
        .long   -1                      # ToState
        .long   .Ltmp0@IMGREL+1         # IP
        .long   1                       # ToState
        .long   .Ltmp1@IMGREL+1         # IP
        .long   -1                      # ToState
        .long   "?catch$3@?0?main@4HA"@IMGREL # IP
        .long   3                       # ToState
        .long   "?catch$4@?0?main@4HA"@IMGREL # IP
        .long   2                       # ToState

Now, as you can see, both beginning of the try block offsets in there are off
byte a single byte (the +1). I tracked this down to
<a href="https://github.com/llvm/llvm-project/blob/50155bcd46428eda1551efe9616f6611b0ef779a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp#L885-L937">https://github.com/llvm/llvm-project/blob/50155bcd46428eda1551efe9616f6611b0ef779a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp#L885-L937</a>

In particular, we have

      // Emit an entry indicating that PCs after 'Label' have this EH state.
      IPToStateTable.push_back(std::make_pair(getLabel(ChangeLabel),
StateChange.NewState));

but looking at the definition of getLabel, we see that (unless the target is
Aarch64, for whatever reason) it adds 1 to the address of its argument. The
following diff appears to fix this issue, although I do not know if it's a
proper fix:


diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
index 039867557..b0d48458c 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
@@ -929,7 +929,7 @@ void WinException::computeIP2StateTable(
         ChangeLabel = StateChange.PreviousEndLabel;
       // Emit an entry indicating that PCs after 'Label' have this EH state.
       IPToStateTable.push_back(
-          std::make_pair(getLabel(ChangeLabel), StateChange.NewState));
+          std::make_pair(create32bitRef(ChangeLabel), StateChange.NewState));
       // FIXME: assert that NewState is between CatchLow and CatchHigh.
     }
   }


With this patch, the above output becomes

        $ip2state$main:
        .long   .Lfunc_begin0@IMGREL    # IP
        .long   -1                      # ToState
        .long   .Ltmp0@IMGREL           # IP
        .long   1                       # ToState
        .long   .Ltmp1@IMGREL           # IP
        .long   -1                      # ToState
        .long   "?catch$3@?0?main@4HA"@IMGREL # IP
        .long   3                       # ToState
        .long   "?catch$4@?0?main@4HA"@IMGREL # IP
        .long   2                       # ToState

as expected.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>