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

    <tr>
        <th>Summary</th>
        <td>
            [C++20] [Modules] [NVPTX] Modules won't work for the NVPTX target
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
      </td>
    </tr>

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

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

<pre>
    There should be some way to make modules work for heterogeneous code. Being forced to somehow use host-only headers in GMFs and completely separate device-side code from modularized code is too much of a limitation. Especially since heterogeneous compilations could benefit significantly from modules in general.

Since we are compiling for different targets, we need to precompile interface units twice - one host and one device pass. The host pass works fine, but the device pass won't, raising `Module has a nontrivial global ctor, which NVPTX does not support.`:
```bash
echo "export module hello;" > hello.cppm
echo "import hello;" > main.cpp

echo "Building host pcm."
clang -xcuda -nocudalib -nocudainc -std=c++20 --offload-host-only -Xclang -emit-module-interface --precompile hello.cppm -o host.pcm
echo "Building host interface object."
clang -std=c++20 --target=x86_64 --offload-host-only host.pcm -c -o host.interface.o
echo "Building main for host."
clang -xcuda -nocudalib -nocudainc -std=c++20 --offload-host-only -fmodule-file=host.pcm main.cpp -c -o main_device.o

echo "Building device pcm."
clang -xcuda -nocudalib -nocudainc -std=c++20 --offload-device-only -Xclang -emit-module-interface --precompile hello.cppm -o device.pcm
echo "Building device interface object."
clang -std=c++20 --target=nvptx --offload-device-only device.pcm -c -o device.interface.o
echo "The above won't work. Here is the bitcode with the global ctor:"
clang -std=c++20 --target=nvptx --offload-device-only device.pcm -c -o device.interface.bc -emit-llvm
llvm-dis device.interface.bc -o -
echo "Building main for device."
clang -xcuda -nocudalib -nocudainc -std=c++20 --offload-device-only -fmodule-file=device.pcm main.cpp -c -o main_host.o
```
Note that using `--precompile` without `-Xclang -emit-module-interface` will just run the preprocessor and not generate an actual BMI with `-xcuda`.

I'm not too famililar with LLVM bitcode, but it seems to me that this doesn't work for NVPTX:
```llvm
@_ZGIW5hello__in_chrg = internal global i8 0, align 1
@llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @_ZGIW5hello, ptr null }]

define void @_ZGIW5hello() #0 {
  %1 = load i8, ptr @_ZGIW5hello__in_chrg, align 1
  %2 = icmp eq i8 %1, 0
  br i1 %2, label %3, label %4, !prof !4

3:                                                ; preds = %0
  store i8 1, ptr @_ZGIW5hello__in_chrg, align 1
  br label %4

4:                                                ; preds = %3, %0
  ret void
}
```
The `Module` constructor is here:
https://github.com/llvm/llvm-project/blob/42bcb35c0f2946b66ae397515823a3792f14b067/llvm/lib/IR/Module.cpp#L72-L76
The error message is raised here, and it looks like there should be a way to not trigger the error for some other kind of module configuration:
https://github.com/llvm/llvm-project/blob/636de2bf342ebae9a1d4ccb9c0029e72c7ce6e26/llvm/lib/Target/NVPTX/NVPTXAsmPrinter.cpp#L777-L799

cc @Artem-B @ChuanqiXu9
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy9V9tu2zgQ_Rr5hZAhS7ZsPfihbppugKQodoNusS8BRY0sNhKpklSS7tfvDCnZzq2Lot0NjEgk53J4ZjhDlbr6tr1uwACzjR7aipX4pjtg9_wbc5p1_BZYp6uhBcvutblltTasAQdG70GBHiwTuoI524FUe1oVUJEmWWn0PRsssEZbF2vVfkNNXoGxTCr2_urcMq4q1O_6Fi3isoWeG-6AVXAnBcRWVuDts9roLgDhRv4NVZiVFl0hykE0TNeMs1Z20nEntZqzd7YHIXlLdqUS8Ax218vWy9IgbF5BLR2K75WspeDKofLRNXjgZMDwdh4lZ1HyJvz_wzu4B8YNjJZHOlgl6xoJVo45bvbgbJS-JUkFgajeQFDA7SgEWHO0NCjpcG_3SAKLmVaBQ08XDQI9rOfWzhnGL6zS0AfJsloqID_lgG6bRwoooaJ07WjZcGkJZ5QnV36DrOEYFKa0ckbeIXls3-oSH8Jp44E3Ern-8Onj9WdWaSREaeRr6Htt3BzNRNnICL37X8ltE6ZANJpFaQoPJD1SilFpWx1lO1xgUfYujOei77vHWrLzWk_FOy4VSZ9GY1LZDbKtaH-BHtHNcTKIiJbjfPwghoqzWGl6trKcXjGcLLauirIzEaXobJcmLI51XbeaV_ExoePPoyXAxIvDluJjHOP4JLzHnbFYe0xzxPQ9yEdDuvwCwj3D_xxiSDKcfNjkN_nyRdCTaxaLA5KDq7l-BRExHY4_yf96JuuRvRq5QukDyCnCI1oa3oR8nqC-AnhK-l8X97Es_WTkR_Cvx34E_jPRV3e9e3gF-dH_SOk48WoKUIXhpb6DqXb4KjNnv1HjoBqM66V0viTfS9f4idPCgUXh_4JeijEibXs38ktvcYU4XxTWLP63hB_1_oskepL0J_t7Ke39mdBPCmwYftDYNl3DHXbcsaSfpiAOfWg0NgRa-m7yBuG2ZV8GLEJmUD6gaKw3WoC1SAl1Iir9oRmia64YF27AiO-uLkIWkB_PEb486pYXmEOdV6fuXfMOuyX29aB1efnpasqmqYVRTwborL-SjNt0DUUUW9AxI32wfG963oaO6RAtk5u_3l_8ufKn8uYGeRWNQcays3Dk1LHtyQ1LCASGd6_Y4mCArM2DzA1luPXavO9B-dQZ1aPVbsEeWLTeMZmlZKh3Znzg7Fm0OiOZV9cnTZavVtnqsPBoA9OsGjBgweYp1xXQXYDdaVk9U9xEaYEZnyXkJ4gzHK8WfjeUrEjAy14PtD1jx1tIA5ui6xl8JRbJKokmk1BpmFx4UZpueQktjbJHoyWNonSBeVfTc3m6swyDzH7wDy8OlMdViBd6OOCxGEUgpIsf3zDu5QTyCcTlr4CYBRKOUA04H8_R0_rsxYJARftwr6MTLfCi68xA6UpFm279h2PSONdbX6bP8bfHcziUcywdOPAHJzywnmhqRDgsMcHxsUxLUWYrkdRpsczLPOeQFevVYrVJM56ti7ReLMskX5_YkaR38Tv-C9D85S3NLtdpfLnOj9jBGATaYbnhe99l6LKKV2aPm2KAFQjrQqs13ndbeUtl4fGHDJ--YnylMXK_B-MrWTBNxcJ_62hSZLeSLtf1dC1Ftmq5H4z_QPhpnvIsryAt62yZQsmh4ItqKURZiCRJC1inYi0ghzR_ytN1aIrpeahq4_ON7T4aX6oO5K3XyF5RnCafEJTCb4yDLt7R69tm4Oqr_DwUM9gu8jxbp0mebGbVNquKrOAzJ10LWyxIb6e2NRaoECk7jgIWfL86fBg-qcFEcvhGCF19Nph2-8PcSWsHdJqer9abPJ01W0g29SJbQpEuNnVeQMXXUOabciUWZb0RMPOn0NIOEN5MbtMkTROUTpIsX27mWckXvCqLqqyWdbJJkBPAvtrOfTnXZj8zW4-hHPaWqry0zh4X8eMJjz3AZJ8P2E_NlnOjVacV3gFmHvLW4_0HIMfb4Q">