Skip to content

Commit 68441a4

Browse files
Rollup merge of rust-lang#137720 - folkertdev:naked-function-target-feature, r=Amanieu
support `#[target_feature(enable = ...)]` on `#[naked]` functions fixes rust-lang#136280 Instructions that are part of a target feature require a special directive on some targets. This PR adds those for the most common targets. This is very WIP, but I'm hoping to collect some feedback on what is (not) supported and how to report that to users. r? @ghost cc @taiki-e @Amanieu
2 parents 2e071b2 + 133ea4b commit 68441a4

12 files changed

Lines changed: 297 additions & 7 deletions

File tree

compiler/rustc_codegen_cranelift/src/global_asm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for GlobalAsmContext<'_, 'tcx> {
3030
operands: &[GlobalAsmOperandRef<'tcx>],
3131
options: InlineAsmOptions,
3232
_line_spans: &[Span],
33+
_target_features: &[String],
3334
) {
3435
codegen_global_asm_inner(self.tcx, self.global_asm, template, operands, options);
3536
}

compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
929929
operands: &[GlobalAsmOperandRef<'tcx>],
930930
options: InlineAsmOptions,
931931
line_spans: &[Span],
932+
_target_features: &[String],
932933
) {
933934
let asm_arch = self.tcx.sess.asm_arch.unwrap();
934935

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
414414
operands: &[GlobalAsmOperandRef<'tcx>],
415415
options: InlineAsmOptions,
416416
_line_spans: &[Span],
417+
target_features: &[String],
417418
) {
418419
let asm_arch = self.tcx.sess.asm_arch.unwrap();
419420

@@ -499,14 +500,11 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
499500
template_str.push_str("\n.att_syntax\n");
500501
}
501502

502-
let target_features = self.tcx.global_backend_features(()).join(",");
503-
let target_cpu = llvm_util::target_cpu(self.tcx.sess);
504-
505503
llvm::append_module_inline_asm(
506504
self.llmod,
507505
template_str.as_bytes(),
508-
&target_features,
509-
target_cpu,
506+
&target_features.join(","),
507+
llvm_util::target_cpu(self.tcx.sess),
510508
);
511509
}
512510

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,14 @@ where
490490
})
491491
.collect();
492492

493-
cx.codegen_global_asm(asm.template, &operands, asm.options, asm.line_spans);
493+
let target_features = cx.tcx().global_backend_features(());
494+
cx.codegen_global_asm(
495+
asm.template,
496+
&operands,
497+
asm.options,
498+
asm.line_spans,
499+
&target_features,
500+
);
494501
} else {
495502
span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
496503
}

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ pub fn codegen_naked_asm<
5454
template_vec.extend(template.iter().cloned());
5555
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(end.into()));
5656

57-
cx.codegen_global_asm(&template_vec, &operands, options, line_spans);
57+
let target_features: Vec<_> =
58+
cx.tcx().asm_target_features(instance.def_id()).iter().map(|s| format!("+{s}")).collect();
59+
cx.codegen_global_asm(&template_vec, &operands, options, line_spans, &target_features);
5860
}
5961

6062
fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>>(

compiler/rustc_codegen_ssa/src/traits/asm.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ pub trait AsmCodegenMethods<'tcx> {
7272
operands: &[GlobalAsmOperandRef<'tcx>],
7373
options: InlineAsmOptions,
7474
line_spans: &[Span],
75+
target_features: &[String],
7576
);
7677

7778
/// The mangled name of this instance
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
//@ revisions: aarch64-elf aarch64-macho aarch64-coff x86_64 s390x riscv64 powerpc64 loongarch64
2+
//@ add-minicore
3+
//@ assembly-output: emit-asm
4+
//@ min-llvm-version: 23
5+
//
6+
//@ [x86_64] compile-flags: --target x86_64-unknown-linux-gnu
7+
//@ [x86_64] needs-llvm-components: x86
8+
//
9+
//@ [aarch64-elf] compile-flags: --target aarch64-unknown-linux-gnu
10+
//@ [aarch64-elf] needs-llvm-components: aarch64
11+
//@ [aarch64-macho] compile-flags: --target aarch64-apple-darwin
12+
//@ [aarch64-macho] needs-llvm-components: aarch64
13+
//@ [aarch64-coff] compile-flags: --target aarch64-pc-windows-gnullvm
14+
//@ [aarch64-coff] needs-llvm-components: aarch64
15+
//
16+
//@ [s390x] compile-flags: --target s390x-unknown-linux-gnu
17+
//@ [s390x] needs-llvm-components: systemz
18+
//
19+
//@ [powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu
20+
//@ [powerpc64] needs-llvm-components: powerpc
21+
//
22+
//@ [riscv64] compile-flags: --target riscv64gc-unknown-linux-gnu
23+
//@ [riscv64] needs-llvm-components: riscv
24+
//
25+
// NOTE: loongarch64 does not error when using an instruction without enabling the corresponding
26+
// target feature.
27+
//@ [loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
28+
//@ [loongarch64] needs-llvm-components: loongarch
29+
30+
// Test that the #[target_feature(enable = ...)]` works on naked functions.
31+
32+
#![crate_type = "lib"]
33+
#![feature(no_core, naked_functions_target_feature)]
34+
#![feature(s390x_target_feature, powerpc_target_feature, loongarch_target_feature)]
35+
#![no_core]
36+
37+
extern crate minicore;
38+
use minicore::*;
39+
40+
// x86_64-LABEL: vpclmulqdq:
41+
// x86_64: vpclmulqdq
42+
#[no_mangle]
43+
#[unsafe(naked)]
44+
#[cfg(target_arch = "x86_64")]
45+
#[target_feature(enable = "vpclmulqdq")]
46+
unsafe extern "C" fn vpclmulqdq() {
47+
naked_asm!("vpclmulqdq zmm1, zmm2, zmm3, 4")
48+
}
49+
50+
// i8mm is not enabled by default
51+
//
52+
// note that aarch64-apple-darwin enables more features than aarch64-unknown-linux-gnu
53+
//
54+
// aarch64-elf-LABEL: i8mm:
55+
// aarch64-elf: usdot
56+
// aarch64-macho-LABEL: i8mm:
57+
// aarch64-macho: usdot
58+
// aarch64-coff-LABEL: i8mm:
59+
// aarch64-coff: usdot
60+
#[no_mangle]
61+
#[unsafe(naked)]
62+
#[cfg(target_arch = "aarch64")]
63+
#[target_feature(enable = "i8mm")]
64+
unsafe extern "C" fn i8mm() {
65+
naked_asm!("usdot v0.4s, v1.16b, v2.4b[3]")
66+
}
67+
68+
// riscv64: sh1add:
69+
// riscv64: sh1add
70+
#[no_mangle]
71+
#[unsafe(naked)]
72+
#[cfg(target_arch = "riscv64")]
73+
#[target_feature(enable = "zba")]
74+
unsafe extern "C" fn sh1add() {
75+
naked_asm!("sh1add a0, a1, a2", "ret");
76+
}
77+
78+
#[cfg(target_arch = "s390x")]
79+
mod s390x {
80+
use super::*;
81+
82+
// s390x: vector:
83+
// s390x: vavglg
84+
#[no_mangle]
85+
#[unsafe(naked)]
86+
#[target_feature(enable = "vector")]
87+
unsafe extern "C" fn vector() {
88+
naked_asm!("vavglg %v0, %v0, %v0")
89+
}
90+
91+
// s390x: vector_enhancements_1:
92+
// s390x: vfcesbs
93+
#[no_mangle]
94+
#[unsafe(naked)]
95+
#[target_feature(enable = "vector-enhancements-1")]
96+
unsafe extern "C" fn vector_enhancements_1() {
97+
naked_asm!("vfcesbs %v0, %v0, %v0")
98+
}
99+
100+
// s390x: vector_enhancements_2:
101+
// s390x: vclfp
102+
#[no_mangle]
103+
#[unsafe(naked)]
104+
#[target_feature(enable = "vector-enhancements-2")]
105+
unsafe extern "C" fn vector_enhancements_2() {
106+
naked_asm!("vclfp %v0, %v0, 0, 0, 0")
107+
}
108+
109+
// s390x: vector_packed_decimal:
110+
// s390x: vlrlr
111+
#[no_mangle]
112+
#[unsafe(naked)]
113+
#[target_feature(enable = "vector-packed-decimal")]
114+
unsafe extern "C" fn vector_packed_decimal() {
115+
naked_asm!("vlrlr %v24, %r3, 0(%r2)", "br %r14")
116+
}
117+
118+
// s390x: vector_packed_decimal_enhancement:
119+
// s390x: vcvbg
120+
#[no_mangle]
121+
#[unsafe(naked)]
122+
#[target_feature(enable = "vector-packed-decimal-enhancement")]
123+
unsafe extern "C" fn vector_packed_decimal_enhancement() {
124+
naked_asm!("vcvbg %r0, %v0, 0, 1")
125+
}
126+
127+
// s390x: vector_packed_decimal_enhancement_2:
128+
// s390x: vupkzl
129+
#[no_mangle]
130+
#[unsafe(naked)]
131+
#[target_feature(enable = "vector-packed-decimal-enhancement-2")]
132+
unsafe extern "C" fn vector_packed_decimal_enhancement_2() {
133+
naked_asm!("vupkzl %v0, %v0, 0")
134+
}
135+
}
136+
137+
// powerpc64: power10_vector:
138+
// powerpc64: xxpermx
139+
#[no_mangle]
140+
#[unsafe(naked)]
141+
#[cfg(target_arch = "powerpc64")]
142+
#[target_feature(enable = "power10-vector")]
143+
unsafe extern "C" fn power10_vector() {
144+
naked_asm!("xxpermx 34, 0, 1, 2, 0", "blr")
145+
}
146+
147+
// loongarch64: lasx:
148+
// loongarch64: xvadd.b
149+
#[no_mangle]
150+
#[unsafe(naked)]
151+
#[cfg(target_arch = "loongarch64")]
152+
#[target_feature(enable = "lasx")]
153+
unsafe extern "C" fn lasx() {
154+
naked_asm!("xvadd.b $xr0, $xr0, $xr1", "ret")
155+
}
156+
157+
// wasm32: simd128:
158+
// wasm32: i8x16.shuffle
159+
#[no_mangle]
160+
#[unsafe(naked)]
161+
#[cfg(target_arch = "wasm32")]
162+
#[target_feature(enable = "simd128")]
163+
unsafe extern "C" fn simd128() {
164+
naked_asm!("i8x16.shuffle 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15", "return");
165+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//@ add-minicore
2+
//@ build-fail
3+
//@ revisions: vanilla sha3
4+
//@ compile-flags: --target aarch64-unknown-linux-gnu -Z deduplicate-diagnostics=yes
5+
//@[sha3] compile-flags: -Ctarget-feature=+sha3
6+
//@ needs-llvm-components: aarch64
7+
//@ min-llvm-version: 23
8+
9+
#![crate_type = "lib"]
10+
#![feature(no_core, naked_functions_target_feature)]
11+
#![no_core]
12+
13+
extern crate minicore;
14+
use minicore::*;
15+
16+
// check that a naked function using target features does not keep these features enabled
17+
// for subsequent asm blocks.
18+
19+
#[no_mangle]
20+
#[unsafe(naked)]
21+
#[target_feature(enable = "i8mm")]
22+
unsafe extern "C" fn a() {
23+
naked_asm!("usdot v0.4s, v1.16b, v2.4b[3]")
24+
}
25+
26+
//~? ERROR instruction requires: i8mm
27+
28+
#[no_mangle]
29+
#[unsafe(naked)]
30+
unsafe extern "C" fn c() {
31+
naked_asm!("usdot v0.4s, v2.16b, v2.4b[3]")
32+
}
33+
34+
#[no_mangle]
35+
#[unsafe(naked)]
36+
#[target_feature(enable = "sha3")]
37+
unsafe extern "C" fn d() {
38+
naked_asm!("eor3 v0.16b, v1.16b, v2.16b, v3.16b")
39+
}
40+
41+
//[vanilla]~? ERROR instruction requires: sha3
42+
43+
#[no_mangle]
44+
#[unsafe(naked)]
45+
unsafe extern "C" fn b() {
46+
naked_asm!("eor3 v0.16b, v1.16b, v2.16b, v3.16b")
47+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: instruction requires: i8mm
2+
|
3+
note: instantiated into assembly here
4+
--> <inline asm>:15:1
5+
|
6+
LL | usdot v0.4s, v2.16b, v2.4b[3]
7+
| ^
8+
9+
error: aborting due to 1 previous error
10+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
error: instruction requires: sha3
2+
|
3+
note: instantiated into assembly here
4+
--> <inline asm>:6:1
5+
|
6+
LL | eor3 v0.16b, v1.16b, v2.16b, v3.16b
7+
| ^
8+
9+
error: instruction requires: i8mm
10+
|
11+
note: instantiated into assembly here
12+
--> <inline asm>:15:1
13+
|
14+
LL | usdot v0.4s, v2.16b, v2.4b[3]
15+
| ^
16+
17+
error: aborting due to 2 previous errors
18+

0 commit comments

Comments
 (0)