@@ -10,6 +10,7 @@ use rustc_errors::ErrorReported;
10
10
use rustc_index:: vec:: Idx ;
11
11
use rustc_middle:: bug;
12
12
use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf , TyAndLayout } ;
13
+ use rustc_middle:: ty:: query:: Providers ;
13
14
use rustc_middle:: ty:: subst:: SubstsRef ;
14
15
use rustc_middle:: ty:: {
15
16
self , Const , FloatTy , GeneratorSubsts , IntTy , ParamEnv , PolyFnSig , Ty , TyKind , TypeAndMut ,
@@ -20,12 +21,49 @@ use rustc_span::Span;
20
21
use rustc_span:: DUMMY_SP ;
21
22
use rustc_target:: abi:: call:: { CastTarget , FnAbi , PassMode , Reg , RegKind } ;
22
23
use rustc_target:: abi:: { Abi , Align , FieldsShape , Primitive , Scalar , Size , VariantIdx , Variants } ;
24
+ use rustc_target:: spec:: abi:: Abi as SpecAbi ;
23
25
use std:: cell:: RefCell ;
24
26
use std:: collections:: hash_map:: Entry ;
25
27
use std:: fmt;
26
28
27
29
use num_traits:: cast:: FromPrimitive ;
28
30
31
+ pub ( crate ) fn provide ( providers : & mut Providers ) {
32
+ // This is a lil weird: so, we obviously don't support C ABIs at all. However, libcore does declare some extern
33
+ // C functions:
34
+ // https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/library/core/src/slice/cmp.rs#L119
35
+ // However, those functions will be implemented by compiler-builtins:
36
+ // https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/library/core/src/lib.rs#L23-L27
37
+ // This theoretically then should be fine to leave as C, but, there's no backend hook for
38
+ // FnAbi::adjust_for_cabi, causing it to panic:
39
+ // https://github.com/rust-lang/rust/blob/5fae56971d8487088c0099c82c0a5ce1638b5f62/compiler/rustc_target/src/abi/call/mod.rs#L603
40
+ // So, treat any extern "C" functions as actually being Rust ABI, to be able to compile libcore with arch=spirv.
41
+ providers. fn_sig = |tcx, def_id| {
42
+ // We can't capture the old fn_sig and just call that, because fn_sig is a `fn`, not a `Fn`, i.e. it can't
43
+ // capture variables. Fortunately, the defaults are exposed (thanks rustdoc), so use that instead.
44
+ let result = ( rustc_interface:: DEFAULT_QUERY_PROVIDERS . fn_sig ) ( tcx, def_id) ;
45
+ result. map_bound ( |mut inner| {
46
+ if let SpecAbi :: C { .. } = inner. abi {
47
+ inner. abi = SpecAbi :: Rust ;
48
+ }
49
+ inner
50
+ } )
51
+ } ;
52
+ }
53
+
54
+ pub ( crate ) fn provide_extern ( providers : & mut Providers ) {
55
+ // See comments in provide(), only this time we use the default *extern* provider.
56
+ providers. fn_sig = |tcx, def_id| {
57
+ let result = ( rustc_interface:: DEFAULT_EXTERN_QUERY_PROVIDERS . fn_sig ) ( tcx, def_id) ;
58
+ result. map_bound ( |mut inner| {
59
+ if let SpecAbi :: C { .. } = inner. abi {
60
+ inner. abi = SpecAbi :: Rust ;
61
+ }
62
+ inner
63
+ } )
64
+ } ;
65
+ }
66
+
29
67
/// If a struct contains a pointer to itself, even indirectly, then doing a naiive recursive walk
30
68
/// of the fields will result in an infinite loop. Because pointers are the only thing that are
31
69
/// allowed to be recursive, keep track of what pointers we've translated, or are currently in the
0 commit comments