Skip to content

Commit 8c2577c

Browse files
committed
Don't disable stdsimd anymore
This doesn't enable simd support. Actually using the functions will result in a compilation error.
1 parent 94effb9 commit 8c2577c

File tree

5 files changed

+230
-73
lines changed

5 files changed

+230
-73
lines changed

patches/0001-Disable-stdsimd.patch

-67
This file was deleted.

src/base.rs

+52-1
Original file line numberDiff line numberDiff line change
@@ -656,7 +656,58 @@ fn trans_stmt<'a, 'tcx: 'a>(
656656
| StatementKind::Retag { .. }
657657
| StatementKind::AscribeUserType(..) => {}
658658

659-
StatementKind::InlineAsm { .. } => unimpl!("Inline assembly is not supported"),
659+
StatementKind::InlineAsm(asm) => {
660+
use syntax::ast::Name;
661+
let InlineAsm { asm, outputs: _, inputs: _ } = &**asm;
662+
let rustc::hir::InlineAsm {
663+
asm: asm_code, // Name
664+
outputs, // Vec<Name>
665+
inputs, // Vec<Name>
666+
clobbers, // Vec<Name>
667+
volatile, // bool
668+
alignstack, // bool
669+
dialect, // syntax::ast::AsmDialect
670+
asm_str_style: _,
671+
ctxt: _,
672+
} = asm;
673+
match &*asm_code.as_str() {
674+
"cpuid" | "cpuid\n" => {
675+
assert_eq!(inputs, &[Name::intern("{eax}"), Name::intern("{ecx}")]);
676+
677+
assert_eq!(outputs.len(), 4);
678+
for (i, c) in (&["={eax}", "={ebx}", "={ecx}", "={edx}"]).iter().enumerate() {
679+
assert_eq!(&outputs[i].constraint.as_str(), c);
680+
assert!(!outputs[i].is_rw);
681+
assert!(!outputs[i].is_indirect);
682+
}
683+
684+
assert_eq!(clobbers, &[Name::intern("rbx")]);
685+
686+
assert!(!volatile);
687+
assert!(!alignstack);
688+
689+
crate::trap::trap_unimplemented(fx, "__cpuid_count arch intrinsic is not supported");
690+
}
691+
"xgetbv" => {
692+
assert_eq!(inputs, &[Name::intern("{ecx}")]);
693+
694+
assert_eq!(outputs.len(), 2);
695+
for (i, c) in (&["={eax}", "={edx}"]).iter().enumerate() {
696+
assert_eq!(&outputs[i].constraint.as_str(), c);
697+
assert!(!outputs[i].is_rw);
698+
assert!(!outputs[i].is_indirect);
699+
}
700+
701+
assert_eq!(clobbers, &[]);
702+
703+
assert!(!volatile);
704+
assert!(!alignstack);
705+
706+
crate::trap::trap_unimplemented(fx, "_xgetbv arch intrinsic is not supported");
707+
}
708+
_ => unimpl!("Inline assembly is not supported"),
709+
}
710+
}
660711
}
661712
}
662713

src/lib.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ mod linkage;
4343
mod main_shim;
4444
mod metadata;
4545
mod pretty_clif;
46+
mod target_features_whitelist;
4647
mod trap;
4748
mod unimpl;
4849
mod unsize;
@@ -164,7 +165,21 @@ impl CodegenBackend for CraneliftCodegenBackend {
164165
rustc_codegen_utils::symbol_names::provide(providers);
165166
rustc_codegen_ssa::back::symbol_export::provide(providers);
166167

167-
providers.target_features_whitelist = |tcx, _cnum| tcx.arena.alloc(FxHashMap::default());
168+
providers.target_features_whitelist = |tcx, cnum| {
169+
assert_eq!(cnum, LOCAL_CRATE);
170+
if tcx.sess.opts.actually_rustdoc {
171+
// rustdoc needs to be able to document functions that use all the features, so
172+
// whitelist them all
173+
tcx.arena.alloc(target_features_whitelist::all_known_features()
174+
.map(|(a, b)| (a.to_string(), b))
175+
.collect())
176+
} else {
177+
tcx.arena.alloc(target_features_whitelist::target_feature_whitelist(tcx.sess)
178+
.iter()
179+
.map(|&(a, b)| (a.to_string(), b))
180+
.collect())
181+
}
182+
};
168183
}
169184
fn provide_extern(&self, providers: &mut Providers) {
170185
rustc_codegen_ssa::back::symbol_export::provide_extern(providers);

src/target_features_whitelist.rs

+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use syntax::symbol::{sym, Symbol};
2+
3+
use rustc::session::Session;
4+
5+
// Copied from https://github.com/rust-lang/rust/blob/f69b07144a151f46aaee1b6230ba4160e9394562/src/librustc_codegen_llvm/llvm_util.rs#L93-L264
6+
7+
// WARNING: the features after applying `to_llvm_feature` must be known
8+
// to LLVM or the feature detection code will walk past the end of the feature
9+
// array, leading to crashes.
10+
11+
const ARM_WHITELIST: &[(&str, Option<Symbol>)] = &[
12+
("aclass", Some(sym::arm_target_feature)),
13+
("mclass", Some(sym::arm_target_feature)),
14+
("rclass", Some(sym::arm_target_feature)),
15+
("dsp", Some(sym::arm_target_feature)),
16+
("neon", Some(sym::arm_target_feature)),
17+
("v5te", Some(sym::arm_target_feature)),
18+
("v6", Some(sym::arm_target_feature)),
19+
("v6k", Some(sym::arm_target_feature)),
20+
("v6t2", Some(sym::arm_target_feature)),
21+
("v7", Some(sym::arm_target_feature)),
22+
("v8", Some(sym::arm_target_feature)),
23+
("vfp2", Some(sym::arm_target_feature)),
24+
("vfp3", Some(sym::arm_target_feature)),
25+
("vfp4", Some(sym::arm_target_feature)),
26+
];
27+
28+
const AARCH64_WHITELIST: &[(&str, Option<Symbol>)] = &[
29+
("fp", Some(sym::aarch64_target_feature)),
30+
("neon", Some(sym::aarch64_target_feature)),
31+
("sve", Some(sym::aarch64_target_feature)),
32+
("crc", Some(sym::aarch64_target_feature)),
33+
("crypto", Some(sym::aarch64_target_feature)),
34+
("ras", Some(sym::aarch64_target_feature)),
35+
("lse", Some(sym::aarch64_target_feature)),
36+
("rdm", Some(sym::aarch64_target_feature)),
37+
("fp16", Some(sym::aarch64_target_feature)),
38+
("rcpc", Some(sym::aarch64_target_feature)),
39+
("dotprod", Some(sym::aarch64_target_feature)),
40+
("v8.1a", Some(sym::aarch64_target_feature)),
41+
("v8.2a", Some(sym::aarch64_target_feature)),
42+
("v8.3a", Some(sym::aarch64_target_feature)),
43+
];
44+
45+
const X86_WHITELIST: &[(&str, Option<Symbol>)] = &[
46+
("adx", Some(sym::adx_target_feature)),
47+
("aes", None),
48+
("avx", None),
49+
("avx2", None),
50+
("avx512bw", Some(sym::avx512_target_feature)),
51+
("avx512cd", Some(sym::avx512_target_feature)),
52+
("avx512dq", Some(sym::avx512_target_feature)),
53+
("avx512er", Some(sym::avx512_target_feature)),
54+
("avx512f", Some(sym::avx512_target_feature)),
55+
("avx512ifma", Some(sym::avx512_target_feature)),
56+
("avx512pf", Some(sym::avx512_target_feature)),
57+
("avx512vbmi", Some(sym::avx512_target_feature)),
58+
("avx512vl", Some(sym::avx512_target_feature)),
59+
("avx512vpopcntdq", Some(sym::avx512_target_feature)),
60+
("bmi1", None),
61+
("bmi2", None),
62+
("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
63+
("f16c", Some(sym::f16c_target_feature)),
64+
("fma", None),
65+
("fxsr", None),
66+
("lzcnt", None),
67+
("mmx", Some(sym::mmx_target_feature)),
68+
("movbe", Some(sym::movbe_target_feature)),
69+
("pclmulqdq", None),
70+
("popcnt", None),
71+
("rdrand", None),
72+
("rdseed", None),
73+
("rtm", Some(sym::rtm_target_feature)),
74+
("sha", None),
75+
("sse", None),
76+
("sse2", None),
77+
("sse3", None),
78+
("sse4.1", None),
79+
("sse4.2", None),
80+
("sse4a", Some(sym::sse4a_target_feature)),
81+
("ssse3", None),
82+
("tbm", Some(sym::tbm_target_feature)),
83+
("xsave", None),
84+
("xsavec", None),
85+
("xsaveopt", None),
86+
("xsaves", None),
87+
];
88+
89+
const HEXAGON_WHITELIST: &[(&str, Option<Symbol>)] = &[
90+
("hvx", Some(sym::hexagon_target_feature)),
91+
("hvx-double", Some(sym::hexagon_target_feature)),
92+
];
93+
94+
const POWERPC_WHITELIST: &[(&str, Option<Symbol>)] = &[
95+
("altivec", Some(sym::powerpc_target_feature)),
96+
("power8-altivec", Some(sym::powerpc_target_feature)),
97+
("power9-altivec", Some(sym::powerpc_target_feature)),
98+
("power8-vector", Some(sym::powerpc_target_feature)),
99+
("power9-vector", Some(sym::powerpc_target_feature)),
100+
("vsx", Some(sym::powerpc_target_feature)),
101+
];
102+
103+
const MIPS_WHITELIST: &[(&str, Option<Symbol>)] = &[
104+
("fp64", Some(sym::mips_target_feature)),
105+
("msa", Some(sym::mips_target_feature)),
106+
];
107+
108+
const WASM_WHITELIST: &[(&str, Option<Symbol>)] = &[
109+
("simd128", Some(sym::wasm_target_feature)),
110+
("atomics", Some(sym::wasm_target_feature)),
111+
];
112+
113+
/// When rustdoc is running, provide a list of all known features so that all their respective
114+
/// primitives may be documented.
115+
///
116+
/// IMPORTANT: If you're adding another whitelist to the above lists, make sure to add it to this
117+
/// iterator!
118+
pub fn all_known_features() -> impl Iterator<Item=(&'static str, Option<Symbol>)> {
119+
ARM_WHITELIST.iter().cloned()
120+
.chain(AARCH64_WHITELIST.iter().cloned())
121+
.chain(X86_WHITELIST.iter().cloned())
122+
.chain(HEXAGON_WHITELIST.iter().cloned())
123+
.chain(POWERPC_WHITELIST.iter().cloned())
124+
.chain(MIPS_WHITELIST.iter().cloned())
125+
.chain(WASM_WHITELIST.iter().cloned())
126+
}
127+
128+
pub fn target_feature_whitelist(sess: &Session)
129+
-> &'static [(&'static str, Option<Symbol>)]
130+
{
131+
match &*sess.target.target.arch {
132+
"arm" => ARM_WHITELIST,
133+
"aarch64" => AARCH64_WHITELIST,
134+
"x86" | "x86_64" => X86_WHITELIST,
135+
"hexagon" => HEXAGON_WHITELIST,
136+
"mips" | "mips64" => MIPS_WHITELIST,
137+
"powerpc" | "powerpc64" => POWERPC_WHITELIST,
138+
// wasm32 on emscripten does not support these target features
139+
"wasm32" if !sess.target.target.options.is_like_emscripten => WASM_WHITELIST,
140+
_ => &[],
141+
}
142+
}

src/trap.rs

+20-4
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,48 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, ms
2424
fx.bcx.ins().call(puts, &[msg_ptr]);
2525
}
2626

27+
/// Use this when `rustc_codegen_llvm` would insert a call to the panic handler.
28+
///
2729
/// Trap code: user0
2830
pub fn trap_panic(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
2931
codegen_print(fx, msg.as_ref());
3032
fx.bcx.ins().trap(TrapCode::User(0));
3133
}
3234

35+
/// Use this for example when a function call should never return. This will fill the current block,
36+
/// so you can **not** add instructions to it afterwards.
37+
///
3338
/// Trap code: user65535
3439
pub fn trap_unreachable(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
3540
codegen_print(fx, msg.as_ref());
3641
fx.bcx.ins().trap(TrapCode::User(!0));
3742
}
3843

44+
/// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen.
45+
/// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions
46+
/// to it afterwards.
47+
///
3948
/// Trap code: user65535
40-
pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CValue<'tcx> {
49+
pub fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, impl cranelift_module::Backend>, msg: impl AsRef<str>) {
4150
codegen_print(fx, msg.as_ref());
4251
let true_ = fx.bcx.ins().iconst(types::I32, 1);
4352
fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
53+
}
54+
55+
/// Like `trap_unreachable` but returns a fake value of the specified type.
56+
///
57+
/// Trap code: user65535
58+
pub fn trap_unreachable_ret_value<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CValue<'tcx> {
59+
trap_unimplemented(fx, msg);
4460
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
4561
CValue::by_ref(zero, dest_layout)
4662
}
4763

64+
/// Like `trap_unreachable` but returns a fake place for the specified type.
65+
///
4866
/// Trap code: user65535
4967
pub fn trap_unreachable_ret_place<'tcx>(fx: &mut FunctionCx<'_, 'tcx, impl cranelift_module::Backend>, dest_layout: TyLayout<'tcx>, msg: impl AsRef<str>) -> CPlace<'tcx> {
50-
codegen_print(fx, msg.as_ref());
51-
let true_ = fx.bcx.ins().iconst(types::I32, 1);
52-
fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
68+
trap_unimplemented(fx, msg);
5369
let zero = fx.bcx.ins().iconst(fx.pointer_type, 0);
5470
CPlace::for_addr(zero, dest_layout)
5571
}

0 commit comments

Comments
 (0)