Skip to content

Commit

Permalink
Add test for SIMD encodings in return types
Browse files Browse the repository at this point in the history
  • Loading branch information
madsmtm committed May 10, 2024
1 parent bafa30b commit 1ed5859
Show file tree
Hide file tree
Showing 5 changed files with 247 additions and 1 deletion.
8 changes: 7 additions & 1 deletion crates/objc2-encode/src/encoding_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use core::fmt;
use core::str::FromStr;

use crate::helper::{compare_encodings, Helper, NestingLevel};
use crate::parse::{ParseError, Parser};
use crate::parse::{ErrorKind, ParseError, Parser};
use crate::Encoding;

/// The boxed version of [`Encoding`].
Expand Down Expand Up @@ -123,6 +123,12 @@ impl EncodingBox {
parser.strip_leading_qualifiers();

match parser.parse_encoding_or_none() {
Err(ErrorKind::Unknown(b'0'..=b'9')) => {
let remaining = parser.remaining();
*s = remaining;

Ok(EncodingBox::None)
}
Err(err) => Err(ParseError::new(parser, err)),
Ok(encoding) => {
let remaining = parser.remaining();
Expand Down
2 changes: 2 additions & 0 deletions crates/tests/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ fn main() {
builder.compiler("clang");
builder.file("extern/encode_utils.m");
builder.file("extern/test_object.m");
builder.file("extern/test_simd_return.m");
println!("cargo:rerun-if-changed=extern/encode_utils.m");
println!("cargo:rerun-if-changed=extern/test_object.m");
println!("cargo:rerun-if-changed=extern/test_simd_return.m");

builder.flag("-fblocks");

Expand Down
55 changes: 55 additions & 0 deletions crates/tests/extern/test_simd_return.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <Foundation/NSObject.h>

#ifdef TARGET_OS_MAC

#include <simd/simd.h>

@interface TestSimdReturn: NSObject
@end

#define METHOD(type) + (simd_ ## type) type
#define METHOD_POW2(type, from) + (simd_ ## type) type { return simd_make_ ## type([self from], [self from]); }

@implementation TestSimdReturn
METHOD(float1) {
return 42;
}
METHOD_POW2(float2, float1)
METHOD(float3) {
return simd_make_float3([self float1], [self float1], [self float1]);
}
METHOD_POW2(float4, float2)
METHOD_POW2(float8, float4)
METHOD_POW2(float16, float8)

METHOD(char1) {
return 42;
}
METHOD_POW2(char2, char1)
METHOD(char3) {
return simd_make_char3([self char1], [self char1], [self char1]);
}
METHOD_POW2(char4, char2)
METHOD_POW2(char8, char4)
METHOD_POW2(char16, char8)
METHOD_POW2(char32, char16)
METHOD_POW2(char64, char32)

METHOD(quatf) {
return simd_quaternion([self float4]);
}

METHOD(float2x2) {
return simd_matrix([self float2], [self float2]);
}

METHOD(float2x4) {
return simd_matrix([self float4], [self float4]);
}

METHOD(float4x4) {
return simd_matrix([self float4], [self float4], [self float4], [self float4]);
}
@end

#endif // TARGET_OS_MAC
4 changes: 4 additions & 0 deletions crates/tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//!
//! This is used so that we don't need to add a `build.rs` script to `block2`.
#![no_std]
#![cfg_attr(feature = "apple", feature(repr_simd))]

use std::os::raw::c_void;

Expand All @@ -21,6 +22,9 @@ mod test_encode_utils;
mod test_foundation_retain_semantics;
#[cfg(test)]
mod test_object;
#[cfg(test)]
#[cfg(feature = "apple")]
mod test_simd_return;

#[no_mangle]
extern "C" fn debug_block(block: *mut c_void) {
Expand Down
179 changes: 179 additions & 0 deletions crates/tests/src/test_simd_return.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
use core::ffi::{c_char, c_float};

use objc2::runtime::NSObject;
use objc2::{extern_class, extern_methods, mutability, ClassType, Encode, Encoding};

extern_class!(
struct TestSimdReturn;

unsafe impl ClassType for TestSimdReturn {
type Super = NSObject;
type Mutability = mutability::InteriorMutable;
}
);

macro_rules! methods {
($(
$(#[$($m:tt)*])*
$name:ident: $ty:ty { $expr:expr }
)*) => {$(
#[test]
$(#[$($m)*])*
fn $name() {
extern_methods!(
#[allow(non_local_definitions)]
unsafe impl TestSimdReturn {
#[method($name)]
fn $name() -> $ty;
}
);

let res = TestSimdReturn::$name();
assert_eq!(res, $expr);
}
)*};
}

macro_rules! encode_none {
($ty:ty) => {
unsafe impl Encode for $ty {
const ENCODING: Encoding = Encoding::None;
}
};
}

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Float2([f32; 2]);
encode_none!(Float2);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Float3([f32; 3]);
encode_none!(Float3);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Float4([f32; 4]);
encode_none!(Float4);

#[repr(transparent)]
#[derive(PartialEq, Debug)]
struct Float8([f32; 8]);
encode_none!(Float8);

#[repr(transparent)]
#[derive(PartialEq, Debug)]
struct Float16([f32; 16]);
encode_none!(Float16);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Char2([i8; 2]);
encode_none!(Char2);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Char3([i8; 3]);
encode_none!(Char3);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Char4([i8; 4]);
encode_none!(Char4);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Char8([i8; 8]);
encode_none!(Char8);

#[repr(simd)]
#[derive(PartialEq, Debug)]
struct Char16([i8; 16]);
encode_none!(Char16);

#[repr(transparent)]
#[derive(PartialEq, Debug)]
struct Char32([i8; 32]);
encode_none!(Char32);

#[repr(transparent)]
#[derive(PartialEq, Debug)]
struct Char64([i8; 64]);
encode_none!(Char64);

#[repr(C)]
#[derive(PartialEq, Debug)]
struct Quatf(Float4);
unsafe impl Encode for Quatf {
const ENCODING: Encoding = Encoding::Struct("?", &[Encoding::None]);
}

#[repr(C)]
#[derive(PartialEq, Debug)]
struct Float2x2([Float2; 2]);
unsafe impl Encode for Float2x2 {
const ENCODING: Encoding = Encoding::Struct("?", &[Encoding::Array(2, &Encoding::None)]);
}

#[repr(C)]
#[derive(PartialEq, Debug)]
struct Float2x4([Float4; 2]);
unsafe impl Encode for Float2x4 {
const ENCODING: Encoding = Encoding::Struct("?", &[Encoding::Array(2, &Encoding::None)]);
}

#[repr(C)]
#[derive(PartialEq, Debug)]
struct Float4x4([Float4; 4]);
unsafe impl Encode for Float4x4 {
const ENCODING: Encoding = Encoding::Struct("?", &[Encoding::Array(4, &Encoding::None)]);
}

// Note: Most of these are currently ignored, as Rust does not yet have
// support for SIMD types in FFI:
// <https://github.com/rust-lang/rust/issues/63068>
//
// Additionally, we're not currently handling them in message sending.
methods! {
float1: c_float { 42.0 }
#[cfg_attr(target_pointer_width = "32", ignore = "Rust does not yet support SIMD in FFI")]
float2: Float2 { Float2([42.0; 2]) }
#[cfg_attr(target_pointer_width = "32", ignore = "Rust does not yet support SIMD in FFI")]
float3: Float3 { Float3([42.0; 3]) }
#[cfg_attr(target_pointer_width = "32", ignore = "Rust does not yet support SIMD in FFI")]
float4: Float4 { Float4([42.0; 4]) }
#[cfg_attr(not(target_arch = "aarch64"), ignore = "Rust does not yet support SIMD in FFI")]
float8: Float8 { Float8([42.0; 8]) }
#[cfg_attr(not(target_arch = "aarch64"), ignore = "Rust does not yet support SIMD in FFI")]
float16: Float16 { Float16([42.0; 16]) }

char1: c_char { 42 }
char2: Char2 { Char2([42; 2]) }
#[cfg_attr(target_arch = "x86", ignore = "Rust does not yet support SIMD in FFI")]
#[cfg_attr(target_arch = "x86_64", ignore = "Rust does not yet support SIMD in FFI")]
char3: Char3 { Char3([42; 3]) }
#[cfg_attr(target_arch = "x86", ignore = "Rust does not yet support SIMD in FFI")]
#[cfg_attr(target_arch = "x86_64", ignore = "Rust does not yet support SIMD in FFI")]
char4: Char4 { Char4([42; 4]) }
#[cfg_attr(target_pointer_width = "32", ignore = "Rust does not yet support SIMD in FFI")]
char8: Char8 { Char8([42; 8]) }
#[cfg_attr(target_pointer_width = "32", ignore = "Rust does not yet support SIMD in FFI")]
char16: Char16 { Char16([42; 16]) }
#[cfg_attr(not(target_arch = "aarch64"), ignore = "Rust does not yet support SIMD in FFI")]
char32: Char32 { Char32([42; 32]) }
#[cfg_attr(not(target_arch = "aarch64"), ignore = "Rust does not yet support SIMD in FFI")]
char64: Char64 { Char64([42; 64]) }

#[cfg_attr(target_arch = "arm", ignore = "Rust does not yet support SIMD in FFI")]
quatf: Quatf { Quatf(Float4([42.0; 4])) }

#[cfg_attr(target_arch = "arm", ignore = "Rust does not yet support SIMD in FFI")]
float2x2: Float2x2 { Float2x2([Float2([42.0; 2]), Float2([42.0; 2])]) }
#[cfg_attr(target_arch = "arm", ignore = "Rust does not yet support SIMD in FFI")]
#[cfg_attr(target_arch = "aarch64", ignore = "Rust does not yet support SIMD in FFI")]
float2x4: Float2x4 { Float2x4([Float4([42.0; 4]), Float4([42.0; 4])]) }
#[cfg_attr(target_arch = "arm", ignore = "Rust does not yet support SIMD in FFI")]
#[cfg_attr(target_arch = "aarch64", ignore = "Rust does not yet support SIMD in FFI")]
float4x4: Float4x4 { Float4x4([Float4([42.0; 4]), Float4([42.0; 4]), Float4([42.0; 4]), Float4([42.0; 4])]) }
}

0 comments on commit 1ed5859

Please sign in to comment.