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

    <tr>
        <th>Summary</th>
        <td>
            `fir.embox` lowering produces invalid IR during `fir-to-llvm-ir`
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            flang:codegen
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
            clementval,
            jeanPerier
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          matthias-springer
      </td>
    </tr>
</table>

<pre>
    I noticed that `fir-opt` produces invalid IR during `fir-to-llvm-ir` for this test case:

```mlir
fir.global @elesize_of_embox constant : i32 {
  %0 = fir.zero_bits !fir.ptr<i32>
  %1 = fir.embox %0 : (!fir.ptr<i32>) -> !fir.box<!fir.ptr<i32>>
  %2 = fir.box_elesize %1 : (!fir.box<!fir.ptr<i32>>) -> i32
  fir.has_value %2 : i32
}
```

Error:
```
within split at llvm-project/flang/test/Fir/convert-to-llvm.fir:1 offset :4:8: error: ops with side effects not allowed in global initializers
  %2 = fir.box_elesize %1 : (!fir.box<!fir.ptr<i32>>) -> i32
       ^
within split at llvm-project/flang/test/Fir/convert-to-llvm.fir:1 offset :4:8: note: see current operation: %23 = "llvm.load"(%22) <{ordering = 0 : i64}> : (!llvm.ptr) -> i64
```

This is only one of the problems. The dialect conversion also inserts an `unrealized_conversion_cast` from the boxed ptr to a bare pointer:

```mlir
  "llvm.mlir.global"() <{addr_space = 0 : i32, constant, global_type = i32, linkage = #llvm.linkage<external>, sym_name = "elesize_of_embox", visibility_ = 0 : i64}> ({
    %0 = "llvm.mlir.zero"() : () -> !llvm.ptr
    %1 = "llvm.mlir.constant"() <{value = 9 : i32}> : () -> i32
    %2 = "llvm.mlir.zero"() : () -> !llvm.ptr
    %3 = "llvm.getelementptr"(%2) <{elem_type = i32, rawConstantIndices = array<i32: 1>}> : (!llvm.ptr) -> !llvm.ptr
    %4 = "llvm.ptrtoint"(%3) : (!llvm.ptr) -> i64

    ...

    %20 = "llvm.insertvalue"(%19, %0) <{position = array<i64: 0>}> : (!llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, !llvm.ptr) -> !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>
    %21 = "builtin.unrealized_conversion_cast"(%20) : (!llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>) -> !llvm.ptr
    %22 = "llvm.getelementptr"(%21) <{elem_type = !llvm.struct<(ptr, i64, i32, i8, i8, i8, i8)>, rawConstantIndices = array<i32: 0, 1>}> : (!llvm.ptr) -> !llvm.ptr
    %23 = "llvm.load"(%22) <{ordering = 0 : i64}> : (!llvm.ptr) -> i64
    %24 = "llvm.trunc"(%23) <{overflowFlags = #llvm.overflow<none>}> : (i64) -> i32
 "llvm.return"(%24) : (i32) -> ()
  }) : () -> ()
```

Within `fir.global`, `fir.embox` does not lower to an `alloca` but directly to an LLVM struct. This does not compose with the remaining ops. I think the only thing you can do is returning the boxed values via `fir.has_value`, everything else produces invalid IR.

Why does Flang store the LLVM struct that is generated during "boxing" in a stack allocation? Why not use the LLVM struct directly? In the type converter, there is `convertBoxType` and `convertBoxTypeAsStruct`. Why isn't `convertBoxTypeAsStruct` used everywhere?

Context: I am looking at this as part of [refactorings of the dialect conversion framework](https://discourse.llvm.org/t/rfc-merging-1-1-and-1-n-dialect-conversions/82513) and ran into issues with `HasValueOpConversion` and `InsertValueOpConversion` (in `CodeGen.cpp`). Ideally, these should run with a type converter. I'm trying to understand what's the right solution here.

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8WF-P4jgS_zTmpQRKHAjwwANND3dIe7rT3Wj3ETlJBbxt7Mh26GY-_ansJEA307envr0RGoa4Un9-9as_HuGcPGjEFZs9Mc5LhSfU_iwU45zxDeP8dxT6H2glWno0ex6J1h-NXZ2E90cp3Ng1VuoD2lFhqstqB9p4WWIF_ig8sDyppR2bxrM8gcaaqi3RgdRnoWQFu39C1dLrvaA3Y6XOp7G0JF8bC_4oHXh0HkrhkGVrloRPnsTPSUnLknUt7eSgTCEUsGmCCp38gXtT7_FUmDcojXZeaA8sW4PMOLD5E0vWAIzPEmDZM5CCH2jNvpDeAeMpPWi8ZdlGZpxl33rxdBCPqjsNa2B88eg1voQxy771KgvzxrLNI8GrCT6YKMzbvgumt31r6FNlvWF6QopJ5ijc_ixUi72ZdXfM5s-3qEaQv1lrbAf5zcmr9EepwTVKehAeQsYaa37H0jO-rZXQB8a3lDTGt1tpGd-WRp_R-j7Bk1qS4hRMXTsMaZmybL0gh7CzCqZxQLbAyQoB6xpL74hfIJQyr1iB1NAlXWrppVDyB1r358IY_rDZtz8fCG08ER4cIpSttag9mAat8NLoGMGMZyFIxnnQpoyoQuku6IyT8xTZ_MnYCmOhZc8Q-SrzKWWdqDmgEZQQAkPU-fQjL75TTUoHRqsLGI1gavBHpPouFJ7cBL4fESopFJYeYsROGg1COQNSO7TegdBU9a22GPJW7a-C-1K40DFqa05BdWHesILGW_AGBBTCIjRGao_2pz0BBljoQdceenR6YERV2b1rRIm30GTU_YauQf-Ob-_9pYmCnYiS-kUcsEtCFpMQn7Fsg28erRYq8GgD7nLaa3Hqpfn7NhWbLpylk4VU0l_2j9PFF337umlgd7FSJ7uNtMvvtRUNiR60pB-1XOO_x6zrINkzLAe43jHpQ9EM9fhVP-8Jf0CPcWgF1vbMv_pKpx-yZsXrpottpytJI4lOhbXi0hf_GlJK23-skIdOTu-cbLz1xNXBv-wu2p9WXVQ3mUyuPyi4-3zHcgopGfSnS4qSqHEFojFOUuO4jzSnbgPJTyN13ralD91xETzcBOfoK0IpF4_-XnaM_wywr6i-gjHQtmil8lJPPmkoAz2SB_h_KdLPuMD5H2Fs-jPK_o8y8ccon5DoF3j__xlHvbH7KvO21eXVWnZj7Yy2VuZ1q8TB3bXq_oRlG200fgg8IHzfy3pzFn1r9dXe9IZTISMDTiELYRzNnx-3uU7i3Zj9La4XcTXux1ceUtQ9i1MjT6AyGDcj2ovijAwv0qJUCpIoWg-VtFh6denOf_nl179BpBVNbOmuakpzaozDuH7R_LV4ElJTxkzjJrCjvVy_hKOwBdDPA1xMC6XQUBlaDyJC9Pw6wUOfcnCWoo9hWEm70PCM9hLVoXL46NLQ9cPfjpfo8ZYWLXDeWAymbgKL1xDp4ICaNieshhsH54V5k7ShcVokBTgvyheIkMUVawtkgwBp3UfVPZwkt9PhOFRtt-JhqFF_RIvkAMuT7uDJvH2_NBQvCF19PFi7f8Vaz5NJcEA6zfjcfypJHlYRvFcyybJtRGljtMc3T6TbgTiBMuaF4hc-3q2Eg0ZYTzscmz1ZrEXpDSHk-rXuwSJXW3HCV2Nf2OyZ8cXR-8bRHsa3jG8r6UrTWoeTWGM2LMGMb21djk9oD1Ifxuk4HQtdjdOxHncGxlcDjvHtgs_SUMQEkhUapPbEK0cECsRkefJX4X4l8vy92Qwv3wC7C8PxoQSVaaiRjanwL6gnZdMECi4nsKtQKHXp8ucQ3NG0qgLb6mhZvMv0BHaMz0_g7SXw3UCrK7TUbit4PQrP-NzFQpKHowdnVBuGMaWK6DyqVlm1zJZihKt0nvFFvuT5YnRcLbNiUZezKplxXvJpOs9EXpbZdDHLaz4v-EiueMKnacqXySKb8sWk5GmdL7BIi7TCuajoPnwSUg3ZGAUMV2m6SPJ8pESBynX_ARCvLNm6NBUeUHdXfrsKN5uiPTg2TZR03l2VeekVrt43pNCHCIr_8s4_aq1a3dPpIP2xLSalOTG-Jcnu6-amFUnB-LaL6bzi_w4AAP__6WQFGQ">