-
Notifications
You must be signed in to change notification settings - Fork 52
New middle::Type
#152
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
base: next
Are you sure you want to change the base?
New middle::Type
#152
Conversation
`middle::Arg` accepts a reference and turns it into a pointer, throwing away any lifetime information. This change adds a a marker to `middle::Arg` with a lifetime so Rust is able to verify that the provided argument lives long enough.
* Disable `complex` when compiling for Windows
Libffi does not include any code for complex types when `_WIN32` is
defined.
* Fix padding on structs in `libffi-sys`
* `ffi_raw` and `ffi_trampoline` does not have an explicit padding set
by libffi.
* `ffi_closure` is padded to 8 bytes and has an extra padding field when
compiling with MSVC for i686.
* Set the correct ABI for x86_64 MSVC
The default ABI when compiling for x86_64 with MSVC was set to GNUW64
instead of the expected WIN64. This caused an error when passing
`double`s to and from functions.
* Fixed warning about unused import on Windows
`std::path::{Path, PathBuf}` was imported in the build scripts of
libffi-sys, but not used on Windows. This moves the import to
`not_msvc.rs` to avoid the error message.
* Clean up and modify build script for msvc
* Use the full (relative) path for all files and folders to
keep every file and folder path consistent.
* Use separate header files for x86, x86_64, and aarch64. See the bottom
of the commit message for the commands used to generate the headers.
* Use compiler from `cc` crate instead of looking for `cl.exe` using
`cc::windows_registry`. This will hopefully open up for
cross-compiling for msvc targets in the future.
* Store the resulting assembly file from pre-processing in the target
directory instead of inside `libffi-sys-rs/libffi/`.
* Define `FFI_STATIC_BUILD` when building for MSVC.
* Emit helpers for cargo for when to recompile libffi.
The headers were generated using Visual Studio 2022 and
msys2-x86_64-20250221.
The headers for x86_64 were generated using the following command:
`./configure --build x86_64-pc-msys --target x86_64-pc-msys --host x86_64-pc-msys --disable-dependency-tracking --with-pic --disable-shared --disable-docs CC="$(pwd)/msvcc.sh -m64" CXX="$(pwd)/msvcc.sh -m64" CPP="cl.exe -nologo -EP" CXXCPP="cl.exe -nologo -EP"`
The headers for i686 were generated using the following command:
`./configure --build i686-pc-msys --target i686-pc-msys --host i686-pc-msys --disable-dependency-tracking --with-pic --disable-shared --disable-docs CC="$(pwd)/msvcc.sh" CXX="$(pwd)/msvcc.sh" CPP="cl.exe -nologo -EP" CXXCPP="cl.exe -nologo -EP"`
The headers for aarch64 were generated using the following command:
`./configure --build x86_64-pc-msys --target aarch64-pc-msys --host aarch64-pc-msys --disable-dependency-tracking --with-pic --disable-shared --disable-docs CC="$(pwd)/msvcc.sh -m64" CXX="$(pwd)/msvcc.sh -m64" CPP="cl.exe -nologo -EP" CXXCPP="cl.exe -nologo -EP"`
* Select build process by `CARGO_CFG_TARGET_ENV`
`target_env` represent the host building the code for build scripts, and
does not necessarily reflect the target platform. This change uses
`CARGO_CFG_TARGET_ENV` to select the correct build process.
Currently, it is seemingly not possible to cross-compile libffi-sys for
MSVC, but it might be possible in the future.
Type tags are stored in the `type_` field of `ffi_type`s, which is a `c_ushort`. `c_ushort` is an unsigned integer with at least 16 bits. On most modern architectures, `c_ushort` is equivalent to `u16`. This commit changes the types of the constants used for the `type_` field to `u16` to avoid having to cast the constants when using them.
Removes duplicate definitions of the following symbols: * libffi_sys::ffi_type_complex_longdouble * libffi::middle::types::longdouble * libffi::middle::types::complex_longdouble * libffi::middle::Type::complex_longdouble
Added `ffi_type`s to `middle::types` that can be used when testing `middle::Type` with miri.
This adds another test to `middle::types` that tests the behavior when cloning and dropping `Type`s. The test can run with miri.
`longdouble` does not work with "system" feature on MacOS.
|
Changing I would say that the "most" breaking change is removing |
Cifs in the middle and high modules had a `set_abi` function to set a non-default ABI. This is not necessarily safe as the ABI is used for initializing a cif in `ffi_prep_cif`. Changing the ABI after initialization may cause problems when calling a function using the cif. The `set_abi` functions were replaced with `_with_abi` variants for cif constructors (`new` and `new_variadic`).
|
I'll have to take a closer look at the safety guarantees to see if that change is worth it. |
f6fa715 to
fb8fac9
Compare
This commit changes `middle::Type` from a smart pointer to `ffi_type` to an enum that represents possible types that can be sent to, and returned from libffi. Allocation of `ffi_type`s has been moved to a separate `FfiType` struct. A new `FfiTypeArray` has also been created. Functions that were previously used to create different `Type`s are still present, but they are deprecated in favor of referring to `Type` variants directly. All allocations now happens using functionality from `alloc` instead of using `libc::malloc` and `libc::free`. After this change, it is possible to remove libc as a dependency. `middle::Type` does not contain a `void` variant as it is not a valid type for arguments in libffi. Instead, functions now accept an `Option<Type>` for the return type, where `None` represents a void. `high:CType` was slightly simplified as the `RetType` is no longer needed after PR libffi-rs#108 was merged. For return types, a new `CRetType` trait was added that is implemented for all types that implements `CType` in addition to `()`.
|
I have thought some more about this, and I think something should change with types/cifs in middle for libffi-rs. As I have previously stated, I have three proposals for how this could be dealt with in middle.
There might be other solutions that I have not thought of, but I think something should be changed to make the middle module as correct and safe as possible. I don't know if this PR is the best place to discuss this, or if it should be moved to a separate issue? |
9989ec4 to
ea037e5
Compare
I've been busy the last few weeks, but now I am back with a bigger PR.
This PR contains a rewrite of
middle::Type. I started to rewrite it because I found it hard to follow how the oldTypeworked. I realize that I might have just replaced something that I did not understand with something everybody else does not understand, but I have at least tried to separate out safe functionality (such as just describing libffi type signatures) from unsafe code to handle allocation of memory.In addition, I have made some breaking changes. None of the changes should require major changes downstream (hopefully), but I am not the best judge over what breaking changes are acceptable and not. Please let me know if you have any input on changes that should be made or changes that I've made that should be undone.
Breaking changes
middle::Typeis now an enum. It does not manage the memory offfi_types forCifs, which is handled by newFfiTypeArrayandFfiTypestructs.FfiTypes passes tests inmiddle::typeswith miri. The tests should probably be modified to useFfiTypeArayas well.middle::Typedoes not have avoidvariant asffi_type_voidcannot be used for argument types in libffi. Instead, when creating aCif, the result type is anOption<Type>whereNonerepresents avoidreturn type.()no longer implementsCType. Instead, it implementsCRetType, a new trait which is implemented for()and all types that implementCType.RetTypefrom theCTypetrait as it is no longer needed. It was previously needed, but become obsolete after Fixed out-of-bounds write inlow::call#108 was merged.Other changes
There are a few other changes I have made that I think it is worth to highlight to get eventual feedback.
Memory management
This crate previously used
libc::mallocandlibc::freeto manage memory forffi_type. This PR exchanges that for creatingBoxes,Box::into_rawandBox::from_raw. With this PR, there is no longer any use oflibcand it can be removed as a dependency.Boxes come with their own set of problems, but this change should avoid problems with uniqueness by not creatingBoxes except for allocating memory andfrom_rawwhen dropping them. This has the advantage that it allocates memory using the global allocator configured in projects using libffi-rs. In the future this should also make it fairly easy to allow the usage of custom (non-global) allocators if anyone should wish to do so.I did consider using
alloc::allocto allocate memory, but was hesitant to do so as the documentation states that it "is expected to be deprecated".Documentation of unsafe code
I have tried to add comments where it is useful to understand the memory management and why/when it is safe to do everything needed to manage memory for
ffi_types. I am sure there are places where things could be documented better, and there are probably comments that are superfluous and only add clutter.I will try to review the comments later, but currently I am blind on my own code.
Deprecation of
TypefunctionsPreviously,
Types had to be constructed from functions such asType::u8(). Since the newTypeis an enum, this is no longer needed (for all types except structs). I chose to keep the old functions, but deprecate them as I find it better to refer directly to theTypeenum variants when possible.Unresolved issues
Does not currently compile with
systemfeature flag on Mac due to missinglong doublesymbols.