-
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 oldType
worked. 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::Type
is now an enum. It does not manage the memory offfi_type
s forCif
s, which is handled by newFfiTypeArray
andFfiType
structs.FfiType
s passes tests inmiddle::types
with miri. The tests should probably be modified to useFfiTypeAray
as well.middle::Type
does not have avoid
variant asffi_type_void
cannot be used for argument types in libffi. Instead, when creating aCif
, the result type is anOption<Type>
whereNone
represents avoid
return type.()
no longer implementsCType
. Instead, it implementsCRetType
, a new trait which is implemented for()
and all types that implementCType
.RetType
from theCType
trait 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::malloc
andlibc::free
to manage memory forffi_type
. This PR exchanges that for creatingBox
es,Box::into_raw
andBox::from_raw
. With this PR, there is no longer any use oflibc
and it can be removed as a dependency.Box
es come with their own set of problems, but this change should avoid problems with uniqueness by not creatingBox
es except for allocating memory andfrom_raw
when 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::alloc
to 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_type
s. 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
Type
functionsPreviously,
Type
s had to be constructed from functions such asType::u8()
. Since the newType
is 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 theType
enum variants when possible.Unresolved issues
Does not currently compile with
system
feature flag on Mac due to missinglong double
symbols.