-
Notifications
You must be signed in to change notification settings - Fork 148
[CIR] [workaround] Don't use InactiveUnionFieldAttr for non-largest member #1160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Hi! Thanks for looking into this again. For the case below the current implementation still fails to lower to LLVM, but works fine without
Is this expected? |
Have you considered making |
Yes, this is more or less "expected". I took a quick look and find it is due to the incorrect result from |
It may not solve the root problem. I spent some time to think about this and my conclusion is:
Here is the story:
Previously, it just works because the type of the initializer is not considered to be an union type. It makes sense in LLVM since union type is not a thing in LLVM. But it causes problem in the previous PR. |
I sent #1166 which is another perspective of what I called "two type systems". |
This makes sense, as long as we can still emit the same LLVM, feels like CIR could still be more generic.
Yea. I guess we could do casts followed by memcpy's or memsets? What does OG codegen does?
I think #1166 sounds a bit more simple and probably prefered if it's a complete replacement for this PR, what's your take? My understanding is that by reverting the largest member stuff we emit code that is closer to LLVM? or is there anything else extra in that PR? |
Yeah, for local variables, we can do that (we have comments in LowerToLLVM.cpp right now for this). But for global variable with constant initializer, it looks not the case. For global variables, it looks like its type is not the union but the initializer type: https://godbolt.org/z/rvMEKcEYh and when we want to get its value, due to the opaque pointer, we can load it directly in LLVM. But in CIR, the story looks sightly different, we will decide the type of the global variable first and decide the type of the initializer later. Then if the type mismatches, the problem will be thrown directly. So I feel this is some fundamental differences.
Yes, it can be a replacement for this. I should make it clear. If we like that, we can close this. |
…1166) Close #1131 This is another solution to #1160 This patch revert #1007 and remain its test. The problem described in #1007 is workaround by skipping the check of equivalent of element types in arrays. We can't mock such checks simply by adding another attribute to `ConstStructAttr` since the types are aggregated. e.g., we have to handle the cases like `struct { union { ... } }` and `struct { struct { union { ... } } }` and so on. To make it, we have to introduce what I called "two type systems" in #1160. This is not very good giving it removes a reasonable check. But it might not be so problematic since the Sema part has already checked it. (Of course, we still need face the risks to introduce new bugs any way)
Landed #1166, closing this one |
…1166) Close #1131 This is another solution to #1160 This patch revert #1007 and remain its test. The problem described in #1007 is workaround by skipping the check of equivalent of element types in arrays. We can't mock such checks simply by adding another attribute to `ConstStructAttr` since the types are aggregated. e.g., we have to handle the cases like `struct { union { ... } }` and `struct { struct { union { ... } } }` and so on. To make it, we have to introduce what I called "two type systems" in #1160. This is not very good giving it removes a reasonable check. But it might not be so problematic since the Sema part has already checked it. (Of course, we still need face the risks to introduce new bugs any way)
…lvm#1166) Close llvm/clangir#1131 This is another solution to llvm/clangir#1160 This patch revert llvm/clangir#1007 and remain its test. The problem described in llvm/clangir#1007 is workaround by skipping the check of equivalent of element types in arrays. We can't mock such checks simply by adding another attribute to `ConstStructAttr` since the types are aggregated. e.g., we have to handle the cases like `struct { union { ... } }` and `struct { struct { union { ... } } }` and so on. To make it, we have to introduce what I called "two type systems" in llvm/clangir#1160. This is not very good giving it removes a reasonable check. But it might not be so problematic since the Sema part has already checked it. (Of course, we still need face the risks to introduce new bugs any way)
Close #1131
I took more time than I thought on this. The problem seems to be more complex than I thought. And the patch itself is a workaround to stop the regression.
Following off are some details that we can look back future:
InactiveUnionFieldAttr
, the line to compare the synthesized type and desired type (the union type) fails.clangir/clang/lib/CIR/CodeGen/CIRGenExprConst.cpp
Lines 456 to 458 in 3aed38c
then the type of the initializer is not considered to be an union, so the computed size is not correct, which is the reason for the crash.
It is worth to note that, before we introduce
InactiveUnionFieldAttr
, the comparison between the synthesized type and the desired type would fail too. But we can have the right size after all. So the reproducer in Union Initializer Fails During CIRGen #1131 works.It doesn't work if we don't add these padding bits if we used
InactiveUnionFieldAttr
. It can avoid the crash. But then when lowering the code, we have to adding these padding bits by our selves. The problem is the type mismatch.In such manner, in
clangir/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Line 433 in 3aed38c
struct { i64 }
. But the generated type for the init value (inclangir/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Line 447 in 3aed38c
i32
. Then we have to consider how to instantiate astruct { i64 }
with ani32
. The specific example is easy by usingzext
instruction. But how about the generic case? Especially the type of the struct can be not compatible with the init type. This may not be super hard but I'd like to not fix it in the patch.