Skip to content

Commit 734d244

Browse files
sayantnAmanieu
authored andcommitted
Add checks for void pointer types to ensure consistency
1 parent d8785a3 commit 734d244

File tree

1 file changed

+74
-20
lines changed

1 file changed

+74
-20
lines changed

crates/stdarch-verify/tests/x86-intel.rs

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ static TUPLE: Type = Type::Tuple;
6767
static CPUID: Type = Type::CpuidResult;
6868
static NEVER: Type = Type::Never;
6969

70-
#[derive(Debug)]
70+
#[derive(Debug, PartialEq, Copy, Clone)]
7171
enum Type {
7272
PrimFloat(u8),
7373
PrimSigned(u8),
@@ -520,7 +520,7 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
520520

521521
// Make sure we've got the right return type.
522522
if let Some(t) = rust.ret {
523-
equate(t, &intel.return_.type_, "", rust.name, false)?;
523+
equate(t, &intel.return_.type_, "", intel, false)?;
524524
} else if !intel.return_.type_.is_empty() && intel.return_.type_ != "void" {
525525
bail!(
526526
"{} returns `{}` with intel, void in rust",
@@ -542,7 +542,7 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
542542
}
543543
for (i, (a, b)) in intel.parameters.iter().zip(rust.arguments).enumerate() {
544544
let is_const = rust.required_const.contains(&i);
545-
equate(b, &a.type_, &a.etype, &intel.name, is_const)?;
545+
equate(b, &a.type_, &a.etype, &intel, is_const)?;
546546
}
547547
}
548548

@@ -655,11 +655,59 @@ fn matches(rust: &Function, intel: &Intrinsic) -> Result<(), String> {
655655
Ok(())
656656
}
657657

658+
fn pointed_type(intrinsic: &Intrinsic) -> Result<Type, String> {
659+
Ok(
660+
if intrinsic.tech == "AMX"
661+
|| intrinsic
662+
.cpuid
663+
.iter()
664+
.any(|cpuid| matches!(&**cpuid, "KEYLOCKER" | "KEYLOCKER_WIDE" | "XSAVE" | "FXSR"))
665+
{
666+
// AMX, KEYLOCKER and XSAVE intrinsics should take `*u8`
667+
U8
668+
} else if intrinsic.name == "_mm_clflush" {
669+
// Just a false match in the following logic
670+
U8
671+
} else if ["_mm_storeu_si", "_mm_loadu_si"]
672+
.iter()
673+
.any(|x| intrinsic.name.starts_with(x))
674+
{
675+
// These have already been stabilized, so cannot be changed anymore
676+
U8
677+
} else if intrinsic.name.ends_with("i8") {
678+
I8
679+
} else if intrinsic.name.ends_with("i16") {
680+
I16
681+
} else if intrinsic.name.ends_with("i32") {
682+
I32
683+
} else if intrinsic.name.ends_with("i64") {
684+
I64
685+
} else if intrinsic.name.ends_with("i128") {
686+
M128I
687+
} else if intrinsic.name.ends_with("i256") {
688+
M256I
689+
} else if intrinsic.name.ends_with("i512") {
690+
M512I
691+
} else if intrinsic.name.ends_with("h") {
692+
F16
693+
} else if intrinsic.name.ends_with("s") {
694+
F32
695+
} else if intrinsic.name.ends_with("d") {
696+
F64
697+
} else {
698+
bail!(
699+
"Don't know what type of *void to use for {}",
700+
intrinsic.name
701+
);
702+
},
703+
)
704+
}
705+
658706
fn equate(
659707
t: &Type,
660708
intel: &str,
661709
etype: &str,
662-
intrinsic: &str,
710+
intrinsic: &Intrinsic,
663711
is_const: bool,
664712
) -> Result<(), String> {
665713
// Make pointer adjacent to the type: float * foo => float* foo
@@ -676,7 +724,7 @@ fn equate(
676724
if etype == "IMM" || intel == "constexpr int" {
677725
// The _bittest intrinsics claim to only accept immediates but actually
678726
// accept run-time values as well.
679-
if !is_const && !intrinsic.starts_with("_bittest") {
727+
if !is_const && !intrinsic.name.starts_with("_bittest") {
680728
bail!("argument required to be const but isn't");
681729
}
682730
} else {
@@ -723,7 +771,16 @@ fn equate(
723771
(&Type::MMASK16, "__mmask16") => {}
724772
(&Type::MMASK8, "__mmask8") => {}
725773

726-
(&Type::MutPtr(_), "void*") => {}
774+
(&Type::MutPtr(_type), "void*") | (&Type::ConstPtr(_type), "void const*") => {
775+
let pointed_type = pointed_type(intrinsic)?;
776+
if _type != &pointed_type {
777+
bail!(
778+
"incorrect void pointer type {_type:?} in {}, should be pointer to {pointed_type:?}",
779+
intrinsic.name,
780+
);
781+
}
782+
}
783+
727784
(&Type::MutPtr(&Type::PrimFloat(32)), "float*") => {}
728785
(&Type::MutPtr(&Type::PrimFloat(64)), "double*") => {}
729786
(&Type::MutPtr(&Type::PrimSigned(8)), "char*") => {}
@@ -752,7 +809,6 @@ fn equate(
752809
(&Type::MutPtr(&Type::M512I), "__m512i*") => {}
753810
(&Type::MutPtr(&Type::M512D), "__m512d*") => {}
754811

755-
(&Type::ConstPtr(_), "void const*") => {}
756812
(&Type::ConstPtr(&Type::PrimFloat(16)), "_Float16 const*") => {}
757813
(&Type::ConstPtr(&Type::PrimFloat(32)), "float const*") => {}
758814
(&Type::ConstPtr(&Type::PrimFloat(64)), "double const*") => {}
@@ -792,34 +848,32 @@ fn equate(
792848
// This is a macro (?) in C which seems to mutate its arguments, but
793849
// that means that we're taking pointers to arguments in rust
794850
// as we're not exposing it as a macro.
795-
(&Type::MutPtr(&Type::M128), "__m128") if intrinsic == "_MM_TRANSPOSE4_PS" => {}
851+
(&Type::MutPtr(&Type::M128), "__m128") if intrinsic.name == "_MM_TRANSPOSE4_PS" => {}
796852

797853
// The _rdtsc intrinsic uses a __int64 return type, but this is a bug in
798854
// the intrinsics guide: https://github.com/rust-lang/stdarch/issues/559
799855
// We have manually fixed the bug by changing the return type to `u64`.
800-
(&Type::PrimUnsigned(64), "__int64") if intrinsic == "_rdtsc" => {}
856+
(&Type::PrimUnsigned(64), "__int64") if intrinsic.name == "_rdtsc" => {}
801857

802858
// The _bittest and _bittest64 intrinsics takes a mutable pointer in the
803859
// intrinsics guide even though it never writes through the pointer:
804-
(&Type::ConstPtr(&Type::PrimSigned(32)), "__int32*") if intrinsic == "_bittest" => {}
805-
(&Type::ConstPtr(&Type::PrimSigned(64)), "__int64*") if intrinsic == "_bittest64" => {}
860+
(&Type::ConstPtr(&Type::PrimSigned(32)), "__int32*") if intrinsic.name == "_bittest" => {}
861+
(&Type::ConstPtr(&Type::PrimSigned(64)), "__int64*") if intrinsic.name == "_bittest64" => {}
806862
// The _xrstor, _fxrstor, _xrstor64, _fxrstor64 intrinsics take a
807863
// mutable pointer in the intrinsics guide even though they never write
808864
// through the pointer:
809865
(&Type::ConstPtr(&Type::PrimUnsigned(8)), "void*")
810-
if intrinsic == "_xrstor"
811-
|| intrinsic == "_xrstor64"
812-
|| intrinsic == "_fxrstor"
813-
|| intrinsic == "_fxrstor64" => {}
866+
if matches!(
867+
&*intrinsic.name,
868+
"_xrstor" | "_xrstor64" | "_fxrstor" | "_fxrstor64"
869+
) => {}
814870
// The _mm_stream_load_si128 intrinsic take a mutable pointer in the intrinsics
815871
// guide even though they never write through the pointer
816-
(&Type::ConstPtr(&Type::M128I), "void*") if intrinsic == "_mm_stream_load_si128" => {}
872+
(&Type::ConstPtr(&Type::M128I), "void*") if intrinsic.name == "_mm_stream_load_si128" => {}
817873

818874
_ => bail!(
819-
"failed to equate: `{}` and {:?} for {}",
820-
intel,
821-
t,
822-
intrinsic
875+
"failed to equate: `{intel}` and {t:?} for {}",
876+
intrinsic.name
823877
),
824878
}
825879
Ok(())

0 commit comments

Comments
 (0)