Skip to content

Commit b522e7c

Browse files
committed
Auto merge of #137225 - RalfJung:vectorcall, r=nnethercote
vectorcall ABI: require SSE2 According to the official docs at https://learn.microsoft.com/en-us/cpp/cpp/vectorcall, SSE2 is required for this ABI. Add a check that enforces this. I put this together with the other checks ensuring the target features required for a function are present... however, since the ABI is known pre-monomorphization, it would be possible to do this check earlier, which would have the advantage of checking even in `cargo check`. It would have the disadvantage of spreading this code in yet more places. The first commit just does a little refactoring of the mono-time ABI check to make it easier to add the new check. Cc `@workingjubilee` try-job: dist-i586-gnu-i586-i686-musl
2 parents b880760 + 83fd16f commit b522e7c

16 files changed

+172
-108
lines changed

compiler/rustc_monomorphize/messages.ftl

+35-13
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,40 @@
1-
monomorphize_abi_error_disabled_vector_type_call =
2-
this function call uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller
3-
.label = function called here
4-
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
5-
monomorphize_abi_error_disabled_vector_type_def =
6-
this function definition uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled
7-
.label = function defined here
1+
monomorphize_abi_error_disabled_vector_type =
2+
this function {$is_call ->
3+
[true] call
4+
*[false] definition
5+
} uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled{$is_call ->
6+
[true] {" "}in the caller
7+
*[false] {""}
8+
}
9+
.label = function {$is_call ->
10+
[true] called
11+
*[false] defined
12+
} here
813
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
914
10-
monomorphize_abi_error_unsupported_vector_type_call =
11-
this function call uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
12-
.label = function called here
13-
monomorphize_abi_error_unsupported_vector_type_def =
14-
this function definition uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
15-
.label = function defined here
15+
monomorphize_abi_error_unsupported_vector_type =
16+
this function {$is_call ->
17+
[true] call
18+
*[false] definition
19+
} uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
20+
.label = function {$is_call ->
21+
[true] called
22+
*[false] defined
23+
} here
24+
25+
monomorphize_abi_required_target_feature =
26+
this function {$is_call ->
27+
[true] call
28+
*[false] definition
29+
} uses ABI "{$abi}" which requires the `{$required_feature}` target feature, which is not enabled{$is_call ->
30+
[true] {" "}in the caller
31+
*[false] {""}
32+
}
33+
.label = function {$is_call ->
34+
[true] called
35+
*[false] defined
36+
} here
37+
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
1638
1739
monomorphize_couldnt_dump_mono_stats =
1840
unexpected error occurred while dumping monomorphization stats: {$error}

compiler/rustc_monomorphize/src/errors.rs

+17-18
Original file line numberDiff line numberDiff line change
@@ -70,37 +70,36 @@ pub(crate) struct UnknownCguCollectionMode<'a> {
7070
}
7171

7272
#[derive(LintDiagnostic)]
73-
#[diag(monomorphize_abi_error_disabled_vector_type_def)]
73+
#[diag(monomorphize_abi_error_disabled_vector_type)]
7474
#[help]
75-
pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> {
75+
pub(crate) struct AbiErrorDisabledVectorType<'a> {
7676
#[label]
7777
pub span: Span,
7878
pub required_feature: &'a str,
7979
pub ty: Ty<'a>,
80+
/// Whether this is a problem at a call site or at a declaration.
81+
pub is_call: bool,
8082
}
8183

8284
#[derive(LintDiagnostic)]
83-
#[diag(monomorphize_abi_error_disabled_vector_type_call)]
84-
#[help]
85-
pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> {
86-
#[label]
87-
pub span: Span,
88-
pub required_feature: &'a str,
89-
pub ty: Ty<'a>,
90-
}
91-
92-
#[derive(LintDiagnostic)]
93-
#[diag(monomorphize_abi_error_unsupported_vector_type_def)]
94-
pub(crate) struct AbiErrorUnsupportedVectorTypeDef<'a> {
85+
#[diag(monomorphize_abi_error_unsupported_vector_type)]
86+
pub(crate) struct AbiErrorUnsupportedVectorType<'a> {
9587
#[label]
9688
pub span: Span,
9789
pub ty: Ty<'a>,
90+
/// Whether this is a problem at a call site or at a declaration.
91+
pub is_call: bool,
9892
}
9993

100-
#[derive(LintDiagnostic)]
101-
#[diag(monomorphize_abi_error_unsupported_vector_type_call)]
102-
pub(crate) struct AbiErrorUnsupportedVectorTypeCall<'a> {
94+
#[derive(Diagnostic)]
95+
#[diag(monomorphize_abi_required_target_feature)]
96+
#[help]
97+
pub(crate) struct AbiRequiredTargetFeature<'a> {
98+
#[primary_span]
10399
#[label]
104100
pub span: Span,
105-
pub ty: Ty<'a>,
101+
pub required_feature: &'a str,
102+
pub abi: &'a str,
103+
/// Whether this is a problem at a call site or at a declaration.
104+
pub is_call: bool,
106105
}

compiler/rustc_monomorphize/src/mono_checks/abi_check.rs

+55-52
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@ use rustc_middle::mir::{self, traversal};
66
use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
77
use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
88
use rustc_span::def_id::DefId;
9-
use rustc_span::{DUMMY_SP, Span, Symbol};
10-
use rustc_target::callconv::{FnAbi, PassMode};
9+
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
10+
use rustc_target::callconv::{Conv, FnAbi, PassMode};
1111

12-
use crate::errors::{
13-
AbiErrorDisabledVectorTypeCall, AbiErrorDisabledVectorTypeDef,
14-
AbiErrorUnsupportedVectorTypeCall, AbiErrorUnsupportedVectorTypeDef,
15-
};
12+
use crate::errors;
1613

1714
fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
1815
match mode {
@@ -27,35 +24,68 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
2724

2825
/// Checks whether a certain function ABI is compatible with the target features currently enabled
2926
/// for a certain function.
30-
/// If not, `emit_err` is called, with `Some(feature)` if a certain feature should be enabled and
31-
/// with `None` if no feature is known that would make the ABI compatible.
27+
/// `is_call` indicates whether this is a call-site check or a definition-site check;
28+
/// this is only relevant for the wording in the emitted error.
3229
fn do_check_abi<'tcx>(
3330
tcx: TyCtxt<'tcx>,
3431
abi: &FnAbi<'tcx, Ty<'tcx>>,
35-
target_feature_def: DefId,
36-
mut emit_err: impl FnMut(Ty<'tcx>, Option<&'static str>),
32+
def_id: DefId,
33+
is_call: bool,
34+
span: impl Fn() -> Span,
3735
) {
3836
let feature_def = tcx.sess.target.features_for_correct_vector_abi();
39-
let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def);
37+
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
38+
let have_feature = |feat: Symbol| {
39+
tcx.sess.unstable_target_features.contains(&feat)
40+
|| codegen_attrs.target_features.iter().any(|x| x.name == feat)
41+
};
4042
for arg_abi in abi.args.iter().chain(std::iter::once(&abi.ret)) {
4143
let size = arg_abi.layout.size;
4244
if uses_vector_registers(&arg_abi.mode, &arg_abi.layout.backend_repr) {
4345
// Find the first feature that provides at least this vector size.
4446
let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
4547
Some((_, feature)) => feature,
4648
None => {
47-
emit_err(arg_abi.layout.ty, None);
49+
let span = span();
50+
tcx.emit_node_span_lint(
51+
ABI_UNSUPPORTED_VECTOR_TYPES,
52+
CRATE_HIR_ID,
53+
span,
54+
errors::AbiErrorUnsupportedVectorType {
55+
span,
56+
ty: arg_abi.layout.ty,
57+
is_call,
58+
},
59+
);
4860
continue;
4961
}
5062
};
51-
let feature_sym = Symbol::intern(feature);
52-
if !tcx.sess.unstable_target_features.contains(&feature_sym)
53-
&& !codegen_attrs.target_features.iter().any(|x| x.name == feature_sym)
54-
{
55-
emit_err(arg_abi.layout.ty, Some(&feature));
63+
if !have_feature(Symbol::intern(feature)) {
64+
// Emit error.
65+
let span = span();
66+
tcx.emit_node_span_lint(
67+
ABI_UNSUPPORTED_VECTOR_TYPES,
68+
CRATE_HIR_ID,
69+
span,
70+
errors::AbiErrorDisabledVectorType {
71+
span,
72+
required_feature: feature,
73+
ty: arg_abi.layout.ty,
74+
is_call,
75+
},
76+
);
5677
}
5778
}
5879
}
80+
// The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
81+
if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) {
82+
tcx.dcx().emit_err(errors::AbiRequiredTargetFeature {
83+
span: span(),
84+
required_feature: "sse2",
85+
abi: "vectorcall",
86+
is_call,
87+
});
88+
}
5989
}
6090

6191
/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
@@ -68,24 +98,13 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
6898
// function.
6999
return;
70100
};
71-
do_check_abi(tcx, abi, instance.def_id(), |ty, required_feature| {
72-
let span = tcx.def_span(instance.def_id());
73-
if let Some(required_feature) = required_feature {
74-
tcx.emit_node_span_lint(
75-
ABI_UNSUPPORTED_VECTOR_TYPES,
76-
CRATE_HIR_ID,
77-
span,
78-
AbiErrorDisabledVectorTypeDef { span, required_feature, ty },
79-
);
80-
} else {
81-
tcx.emit_node_span_lint(
82-
ABI_UNSUPPORTED_VECTOR_TYPES,
83-
CRATE_HIR_ID,
84-
span,
85-
AbiErrorUnsupportedVectorTypeDef { span, ty },
86-
);
87-
}
88-
})
101+
do_check_abi(
102+
tcx,
103+
abi,
104+
instance.def_id(),
105+
/*is_call*/ false,
106+
|| tcx.def_span(instance.def_id()),
107+
)
89108
}
90109

91110
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -122,23 +141,7 @@ fn check_call_site_abi<'tcx>(
122141
// ABI failed to compute; this will not get through codegen.
123142
return;
124143
};
125-
do_check_abi(tcx, callee_abi, caller.def_id(), |ty, required_feature| {
126-
if let Some(required_feature) = required_feature {
127-
tcx.emit_node_span_lint(
128-
ABI_UNSUPPORTED_VECTOR_TYPES,
129-
CRATE_HIR_ID,
130-
span,
131-
AbiErrorDisabledVectorTypeCall { span, required_feature, ty },
132-
);
133-
} else {
134-
tcx.emit_node_span_lint(
135-
ABI_UNSUPPORTED_VECTOR_TYPES,
136-
CRATE_HIR_ID,
137-
span,
138-
AbiErrorUnsupportedVectorTypeCall { span, ty },
139-
);
140-
}
141-
});
144+
do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
142145
}
143146

144147
fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {
File renamed without changes.

0 commit comments

Comments
 (0)