-
Notifications
You must be signed in to change notification settings - Fork 1
Summary of multiple fixes/feature requests. #8
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
39bd757 to
b2e3d8b
Compare
I'm interested in a minimal repro; I believe I fixed it by accident, but I'm unsure. The underlying issue is that I used a wrong libclang method to get the type name, I guess.
The generated code for this was (and still is) broken. See #11 for some notes on that. I'm on fixing it, even removing the UB from potentially unaligned pointer creation :)
Agreed! This is already implemented as of yesterday. We gracefully degrade now by ignoring fields or entire struct, yielding an error message but continuing the code-gen for further structs.
Agreed! This is already implemented as of yesterday, via letting the user pick any function declaration prefix they like (as in: empty string,
Agreed! This is already implemented as of yesterday.
That is an interesting problem. Originally the scope of this generator was structs only, but we might be able to create function stubs as well? I have to look into this further.
I think this is problem with the distribution of the clang in question. I'd really like to not opt-out of using What we maybe could do here however: opt-in macro to generate a bist (built-in self test) function that verifies that
This can not work in the generic use case: The generated code can not itself detect whether the foreign ABI is little or big endian. For Wasm this is no problem, we always know its little endian. But for generic code, we can't know. Worst case is PowerPC, where endianness can be configured per page in the MMU. As much as I'd like to get away with auto-detection, I hesitant to do it. What however we can do is, to have a macro that defines whether to byteswap or not for the generated code, instead of a a generator CLI flag. Do you think that would be better re. usability? Thank you for the PR, sorry for the mess in the code. I tried to significantly clean up the code, which introduced a bunch of merge conflicts with this PR. I'm however in the progress of fixing most if not all of the bugs and most of the features mentioned above. I'll report back once I got the UB out of the pointer arithmetic. |
|
BUGFIX: The function namespace was hardcoded to
So, let us discuss an example: Above code is a host code function in Wasmtime that is implemented for a Wasm32 guest. My assumption is, that the passed parameters into the function from the Wasm32 guest, won't be LE32 to host automatically by the runtime, but rather needs to be done. Thus, I am currently employing My modification to create the typedef setters was roughly like this (however your code base currently looks completely different):
As you see in the example, my understanding is that I need to handle LE/BE for the given function parameters anyway. However, even though I see your point with PPC LE/BE for each page, I wonder if we can handle this anyway? Today, your prefered approach was to Note: I started reworking your code to create the host code wrappers (as given in the example above) in an automated fashion. However, there are so many caveats to consider, that I dropped this idea for the moment and just implemented it quickly by hand. However, if one would like to have a production grade approach, I would prefer the auto-gen wrapper generator ;-) |
I agree with the conclusion (of using a temporary stack allocated variables), but not with the reason: Yes, the types need to be accurate. Yes, the the same type (e.g. HOWEVER: this is UB, if the pointer is not aligned. Wasm has weak alignment requirements. So does x86_64. But the abstract machine that the C spec defines does not. So, we can not just use the pointer without ensuring it is aligned. Introducing a branch for that is pointless IMHO, so the correct way can only be a byteswise copy from that pointer to a stack allocated (and hence properly aligned) I generally see a strong argument for Rust here, by the way. Type handling is much cleaner (explicit, architecture-independent bit widths for integers and floats!), and actually rules around pointer handling and UB are more relaxed than with C. In C, just assigning an unaligned address to a pointer variable is instant UB. Even if the pointer is never de-referenced. In Rust, this is allowed. Just de-referencing the pointer is of course also UB in Rust. |
|
Oops, didn't mean to close the PR. I did implement the Bugfix in a slightly different way, I think the namespace prefix can be applied to the token stream in I would prefer, if we can branch out feature requests and bug reports in the issues, than its a bit more organized. Thank you again for the feedback! |
This branch is used in airbus/a653lib#11
{namespace_prefix}_{op}__{struct_name}__{field_name} structwithout the empty space and struct, which can't be used as a function.set-functions, perform a*(<type>*)(struct_base_addr + offset) = valueinstead of*(struct_base_addr + offset) = value. Because thestruct_base_addris of typeuint8_t*, thus current setters are solely writing 1 Byte.offset unknown.--target=wasm32-wasi --sysroot=...pulls intime.h, with a struct containing a broken offset:static inlineinstead of solelyinline.PROCESS_STATUS_TYPEwhich containsPROCESS_ATTRIBUTE_TYPE ATTRIBUTESas yet another struct). The nested struct can subsequently employed with anyway given get and set.SAMPLING_PORT_ID_TYPE SAMPLING_PORT_IDis defined as alongthus in theory 4 Byte. While the guest i.e. Wasm32 compiles it to 4 Bytes, the host i.e. x86_64 compiles it to 8 Bytes. As a consequence, when callingextern void GET_SAMPLING_PORT_STATUS ( /*in */ SAMPLING_PORT_ID_TYPE SAMPLING_PORT_ID, /*out*/ SAMPLING_PORT_STATUS_TYPE *SAMPLING_PORT_STATUS, /*out*/ RETURN_CODE_TYPE *RETURN_CODE )in Wasm32, passes an address to a 4 Byte memory location (SAMPLING_PORT_STATUS_TYPE). However, when naively passing this address to the hosts a653lib, it will write a 8 Byte value to this memory location. Thus overwriting content. Furthermore, a naiiv passthrough does not handle Little-Endian to Big-Endian handling. Thus, all typedefs passed through the ARINC653 function calls must be handled by get/set as well.Note: Todays clang does not have a proper
stdint.himplementation, in case source code is compiled with--target=wasm32-wasiand without--sysroot=.... Consequently, most<u>int<8/16/32/64_tfields fallback toint32_tin Wasm32. In case--sysroot=...is employed, this behaviour can't be seen i.e.stdint.htypes have the expected bitwidth. However,char,short,long, ... have always intended bitwidth in case source code is compiled into Wasm32 (again--target=wasm32-wasi). Which means: as long as ARINC653 headers rely onchar,short,long, ... one can useinlinein a Wasm-Runtime offering ARINC653.Idea: We could use the https://man7.org/linux/man-pages/man3/endian.3.html instead of
#include<byteswap.h>, which simplifies the code significantly as it swaps or not swaps automatically (during compilation it chooses the option). Especially, as the a653lib needs to use such mechanism as well.