<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/54090>54090</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            LLVM should stop mangling function symbols based on calling convention
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          rnk
      </td>
    </tr>
</table>

<pre>
    LLVM has an [IR Mangler](https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/IR/Mangler.h) class, which has two responsibilities:
1. Adding underscore prefixes to symbols on some platforms (MachO & x86 Windows)
2. Mangling wacky Windows calling conventions (stdcall, vectorcall, fastcall)

I believe the first behavior is useful, because it makes simple LLVM IR more portable. It papers over a common portability issue for frontends. They can easily call the platform C library (`main`, `malloc`, `free`, `printf`, `puts`) with the same IR on all platforms. It makes writing generic IR tests for all platforms easier, since you don't have to change IR function names based on the target.

The second behavior, however, is very specific to Windows APIs, and doesn't help make target-neutral IR portable. I think it was a mistake to implement this behavior in LLVM. This should have always been a frontend responsibility. I think it became the IR mangler's responsibility to do it because, for fastcall, the leading Windows underscore changes to an `@` symbol.

The calling convention mangling has a history of causing issues, the latest of which is [D120382](https://reviews.llvm.org/D120382). For this reason, Clang implements the calling convention mangling [in the frontend](https://github.com/llvm/llvm-project/blob/2ce6bc61e876f4e7918952a565488d737ce647f6/clang/lib/AST/Mangle.cpp#L198-L239).

For reference, here are the three Windows calling convention manglings that get byte suffixes:
```
void foo(int);
stdcall -> _foo@4
fastcall -> @foo@4
vectorcall -> foo@@4
```

----

Assuming folks agree that this is a desirable direction, we should come up with a migration plan. I think the simplest thing to do is to add a static method to the Mangler class that accepts a calling convention, base name, and `llvm::FunctionType` and returns a string mangled name. Frontends can call this API directly if they need mangling when constructing LLVM IR. Clang handles this itself to handle corner cases involving incomplete types, which probably aren't a concern for non-C frontends.

The most straightforward way to prevent the IR mangler from prefixing these fastcall and vectorcall symbols with underscores would be to prefix them with the existing IR mangler escape, `\01`. This would presumably make IR from such a frontend incompatible with old IR for LTO purposes, but it matches clang's behavior today, so in some ways it is more compatible with the dominant existing IR producer.

Another way to handle this would be to extend the [current mangler check for question mark prefixes](https://github.com/llvm/llvm-project/blob/2ce6bc61e876f4e7918952a565488d737ce647f6/llvm/lib/IR/Mangler.cpp#L149) to look for `@` anywhere in the symbol. This is a behavior change for frontends that create symbols with `@` in them, and any language that uses that character for its symbols will need to prefix such symbols with `_` to avoid having an ABI break at the object file level. This would also break LTO with old bitcode since the IR symbols would change. However, we went through the same IR ABI break when we eliminated the `\01` escape from all C++ symbols emitted by Clang, and I don't recall any user-reported issues, just challenges with updating IR test case expectations.

I think the first approach, `\01` prefixing, is a better transition path. We can add the API (`Mangler::mangleForCallingConvention(StringRef, DataLayout, CallingConv::ID, FunctionType)`), announce the deprecation plan, migrate frontends, and remove the old mangler behavior one release later.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy9V9tu4zgS_Rr7hYhhy_eHPLidbUyANGbRE-w8DiiJsjihRA1J2a2_31NFXez0YoDFAhsYjiWSdT11qpjavHt-e_vXN1FKL2QtZtsvr9_FN1lfjHKz7cssOZQhNH62Ps2Sr_hcdCjbdJHZCg_GXId_T42zf6os4DE1NsW_Sup62qPrzLS5ml68fsdXr2hRzpKjyIz0fpacxa3UWckWhZsVTvnG1l6n2uigFZuyfJktT6uFOOW5ri-irXPlfGadEo1Thf6hcNQK31WpNV7YWnhbYc3IUFhXeQG3vsms_BU_duLHYSd-13Vub9B-jLKTRQwCSb_J7KMbdohMGn6b2fqq6qBhGonzIacVMv-KMFg3PBXSh_i7Fx2_X0WqjFZXJUKpRKGdD3hTyqu2TmgvWq-KlgWkKpN4EjqISn7AM6-rxijBaUOyKnbbuiBToxbiNYhGNgiHsFflhIShVYUIxB0Uww7yfQul0FQ4WwdV534h3kvVwbtaKOm16dhRNm4ImzgLo1MnXUcOz3ZLzvBuSUbykzE2m54Lp9T01Dhdh-LuuQ2en47iBkixIi-RJHgEa0n3mC52Kvp-c8AAon9RtXI6o91B-eDZmYdD7AYwDHUe4FOis63ILSC5D8AWBd6KrESSWWfR1hklU9QwwotUepWTIWRXkO6iwuI-fe9krgIG8jFrpKm0N6SUfyKH-NUJ36hMFzAV6gYMnf75ykCXOJ5b5XujlGnYzV7hU63a4KQh8-7yC5N0_UFwuFHNikr7wIesYGBUQCXt8Xd4qhktlGO89qVtTR5jIM1NdrRTIeYjGh5rrntQSnCsImoJfD1TJHv_6RDZk9vhBADMxUCQGwvizFKMklzEQ3Duijmmh2uZuAlw2Szx3Rf2Twn5uTSjffSO-U3AfZRmJ2whyCZa4FrwozGS4ETrkYQQLlDiyypZrg_Jf-JDp65a3fyCWG1h3QWvht3JcSG-wmHOhQMcCXxncTaS1A6p8qz370yHAToCccjP_0bMSaZ2abZbqcN-V2zU_rg6HLeJ3O62m8Mh36_3WN_six22ZmQrCdJ08PTb-8jZi6xpZsn6bXU8PL0l6yN5e58PchxUrJxC7XFp4KeQLiInlCCHv6HU0XmKjgwod8CoC6i5tmB6H5sAgSJ--PFqdQ6UWYQHfEOcu_4SV3qCFk-z9T_EH7Rls9zEpQGRcQ3vH1YnOo_rcXFa_2RB_H7C3_3zCSiryMfCmg8g8UL-s2uMDk3gzJXXjopc5NopZiPuhmqo2IyaWNtEwqTCvzjJ0QLp1VORMpUyvjyLh9a-FmMl5TkOgzMCSKlSobQ5vaZTfTuOnTiaJ7NMNYHM-zlL3J1AlMyZA58hEIw-JGh9-tqz6nvXUC_gDU6F1tWebXAkMHJIzlJQMUNH4l7UNyHNnNnHBb1JF2RvJ2qFc2Oh3EqwGMyD3DbjNtH3yEVfdKCT3BCfcMyDV6Yg1-NrnHQ1OQ-PsFpfrbkyQdSIO4IJ9AW4cTehoLJS5KsjWEcKp24LvLuama629dP5rsV-5qvKIkEwVupLSU3rJl0OUmfqxBxzjUR-z7MkrOpnHM5rqRD-Eb8U3ju4DvMP42WiVbxgOKWqVwRhJKmaOrH6AaIkBXeqlc8wV_Tte7Y9L1f437eUKBCigHKOCLcxaqtkr2-z8r67xIgCf4R11mlxmnYjaG_vv4qmdY31MdRpG-LoEzI4K3pG2t91t2Bz2XGft9TpeNTjroZjsI3no88KycncoiIlYnzvLXKat8jgQ7JOtcUBN-Smx0uYPI-hVD_YPZINzs5a5yiDQ_xgfvbBLv6FhtOznPsYJ9b_G6kPcpjTH8bwgdM3ROfkkbE2mjz1Xll3N-byvif1vTjigHlsTEw_XT3MmZFVMrTDoB4BOqmIkquBUaBRUNZbeek5s_VqEFRKJ7NAlUFzDohqkokKYH6YQM5A_Kz0D1JJvMi9g0wHEkA9py-Y0WHnh5CxDG1KIcesbmhouSrzAH5pAL-4nyA8wjrVIbO56ofQvpxHGyKvc5wW4pdpegTp32L5O9teHsfjyTAmPGzFTYKgHFQPvqk--6qNdUiccJ4lX_AZLVCVDnQu7SJHDkF_HWdlUG7klo7i7p6comEUR6bJ6c_WcyqMUTyvRcJpcjlUFQ9VRKyoEczDgdvWIyHed694HZINUI5b2ifKmeivH7MJcYEgACbF-Bk7ogzlQvyuuIlQxyOx1ELizWW44HKTigWKgeUcO9z5rsEdfuMe9V0VpOxFBvkmcZEIPMhN26Og1xd6_dDzMIDwJSeGtbbtAIJcNRTYsX3ThtjQpzFvvCM4Vdn-pkiQGhhlLDRbK-zBIO3jBOsW8_x5nR_XRzkPOhgV7_j9GIERuJma5njxGRAxXn1-bvjz1pnn_5qhBpx83W6Wx-W8hGWJzFNV5Jt9ukzzdL0r0sN6k61lulrK_WpuJC7H_hkkOkuSWt0i1PAbHDnXz8kyoc-WvlfLxSFf7mW63aSb1VEmxQEsonA1NeNMPnfPbFLaXjwWDdh-GtjnGHX0BUTB6iBfthiJ3LOrP-as9pnN_jdkY9OZ">