Entry points declare their "interface" (all uniforms, inputs, outputs, etc.) as parameters. spir-v uses globals to declare the interface. So, we need to generate a lil stub for the "real" main that collects all those global variables and calls the user-defined main function.
(
&self,
instance: &Instance<'_>,
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
entry_func: SpirvValue,
name: String,
entry: Entry,
)
| 59 | // "real" main that collects all those global variables and calls the user-defined main |
| 60 | // function. |
| 61 | pub fn entry_stub( |
| 62 | &self, |
| 63 | instance: &Instance<'_>, |
| 64 | fn_abi: &FnAbi<'tcx, Ty<'tcx>>, |
| 65 | entry_func: SpirvValue, |
| 66 | name: String, |
| 67 | entry: Entry, |
| 68 | ) { |
| 69 | let span = self |
| 70 | .tcx |
| 71 | .def_ident_span(instance.def_id()) |
| 72 | .unwrap_or_else(|| self.tcx.def_span(instance.def_id())); |
| 73 | let hir_params = { |
| 74 | let fn_local_def_id = if let Some(id) = instance.def_id().as_local() { |
| 75 | id |
| 76 | } else { |
| 77 | self.tcx |
| 78 | .sess |
| 79 | .span_err(span, format!("cannot declare {name} as an entry point")); |
| 80 | return; |
| 81 | }; |
| 82 | let body = self |
| 83 | .tcx |
| 84 | .hir() |
| 85 | .body(self.tcx.hir().body_owned_by(fn_local_def_id)); |
| 86 | body.params |
| 87 | }; |
| 88 | for (arg_abi, hir_param) in fn_abi.args.iter().zip(hir_params) { |
| 89 | match arg_abi.mode { |
| 90 | PassMode::Direct(_) => {} |
| 91 | PassMode::Pair(..) => { |
| 92 | // FIXME(eddyb) implement `ScalarPair` `Input`s, or change |
| 93 | // the `FnAbi` readjustment to only use `PassMode::Pair` for |
| 94 | // pointers to `!Sized` types, but not other `ScalarPair`s. |
| 95 | if !matches!(arg_abi.layout.ty.kind(), ty::Ref(..)) { |
| 96 | self.tcx.sess.span_err( |
| 97 | hir_param.ty_span, |
| 98 | format!( |
| 99 | "entry point parameter type not yet supported \ |
| 100 | (`{}` has `ScalarPair` ABI but is not a `&T`)", |
| 101 | arg_abi.layout.ty |
| 102 | ), |
| 103 | ); |
| 104 | } |
| 105 | } |
| 106 | // FIXME(eddyb) support these (by just ignoring them) - if there |
| 107 | // is any validation concern, it should be done on the types. |
| 108 | PassMode::Ignore => self.tcx.sess.span_fatal( |
| 109 | hir_param.ty_span, |
| 110 | format!( |
| 111 | "entry point parameter type not yet supported \ |
| 112 | (`{}` has size `0`)", |
| 113 | arg_abi.layout.ty |
| 114 | ), |
| 115 | ), |
| 116 | _ => span_bug!( |
| 117 | hir_param.ty_span, |
| 118 | "query hooks should've made this `PassMode` impossible: {:#?}", |
no test coverage detected