wasi-sdk icon indicating copy to clipboard operation
wasi-sdk copied to clipboard

Apparent codegen bug when building optimized targetting WASI

Open kamrann opened this issue 5 months ago • 4 comments

I've hit a bug that is proving extremely hard to pin down or reduce in any way. So I'm really just looking for suggestions on what I might do to proceed, since I realize I don't have enough info for anyone else to look into it. I'm not even sure if this is the right place vs LLVM, but since it so far has shown up only in WASI builds, I'll start here.

It manifests in a quite bizarre way. I have a std::stringstream ss into which I insert character through a std::ostream_iterator<char> out:

char ch = /**/;
*out++ = ch;

What I'm getting out of the stringstream is not the characters inserted, but a string of digits of the character representations. For example inserting a space character yields not " ", but "32". I initially couldn't even fathom how this could happen, but I discovered that ostream_iterator<T> apparently maps to ss << T(x), so it seems like the only feasible explanation is that somehow the iterator is being incorrectly treated as ostream_iterator<int> or similar. This is very definitely not the case in my code (note the program behaves as expected in non-optimized WASI builds, and also optimized builds with the same clang version targetting x86).

Unfortunately repros are complicated by the fact my project uses C++20 modules and this issue is deep in the module dependency graph, so there is no simple way to create a preprocessed repro. And as for reduction, if I so much as breath on the code, the issue goes away.

  • add an additional lambda capture to try to log more info when the issue occurs -> no bug
  • merely adding #include <iostream> at the top of the file -> no bug
  • copying the function template which does the iterator assignment directly above the call site/into another module interface, and calling that instead -> no bug

Using modules I've got plenty of experience with compiler bugs, but very little when it comes to optimization-related bugs or looking at generated code. Does anyone have any suggestions or tricks for trying to pin down the issue or get more useful information in a case like this? Also please let me know if this would be better posted to the LLVM project.

kamrann avatar Jul 02 '25 10:07 kamrann

I see how it's hard to diagnose what is going on here. Some thoughts: maybe try to use wasm-tools print <your output> to look at the generated code (wasm-tools); maybe something will come from looking at that. All of this is odd, but something that may be worth looking into is why that char seems to be mis-typed as int; it could be that at the WebAssembly level a char is represented as an i32 and some pass does something with that (?). Could you explicitly set the type of that stream? Another thing to look for here is whether wasm-opt is a part of compilation (I believe it is still used by default if it is in the PATH). Honestly, though, it feels like this is a C++ level issue and probably needs to be asked at the LLVM level; they'll need a small reproducer, just like this project would to move forward with this. But hope one of these thoughts help!

abrown avatar Jul 02 '25 16:07 abrown

Another thing that might help here is to test with sanitizers, as there may be some undefined behavior, or perhaps even memory corruption.

I'm not sure if wasi-sdk supports clang's sanitizers, but at least some might work out of the box? If not, if you can build the project with emscripten, you can use sanitizers there just for debugging.

kripken avatar Jul 02 '25 18:07 kripken

Thanks for the suggestions. I'll give the wasm-tools a go. Though I agree, it feels like the issue is likely more fundamental. Unfortunately based on my attempts so far I think the chances of me being able to create a reduced reproduction are close to nil.

I'm compiling with sanitizers enabled for the x86 build and nothing is triggered there. For WASI, I believe I originally tried to do so but ran into a linker error, it seems the WASI SDK doesn't include the associated libraries. Whether that's because they're not supported, or just not built and bundled with the SDK, I don't know. Though that does remind me of something relating to my build that felt a little iffy, I guess there's a possibility that could be the culprit. Posted separately here as it's a more generally applicable question.

kamrann avatar Jul 03 '25 11:07 kamrann

@kamrann Do you think it could be a stack overflow? Try --Wl,--stack-first.

whitequark avatar Jul 28 '25 05:07 whitequark