diff --git a/lib/x86.ml b/lib/x86.ml index 07eba99..2a0a5a7 100644 --- a/lib/x86.ml +++ b/lib/x86.ml @@ -1776,7 +1776,29 @@ and call_native f ~sym ?(chan = false) ~(args : Tast.expr list) ~rty dst = call_sym f.b sym; if chan then guard f; if not (is_void rty) then begin - if is_agg rty then unsupported "aggregate return from %s" sym; + (* Unreachable, and it is worth saying why rather than leaving it reading + like a gap in the backend. Nothing that crosses this boundary returns an + aggregate, by two rules that both live in [check.ml]: + + - every aggregate-valued runtime result comes back through an + *out-pointer* the checker allocates, so the Flan-level return type is + [Unit] or a scalar. [flan_vec_as_slice] is the one that looks like a + counter-example and is not: [check.ml] builds it as [rt loc + Types.Unit] and [flan_rt.c] writes the two words through [void *out]. + Every other [rt] builder in the file answers [Unit], an [Int], a + [Ptr], an [Alloc] or a [Handle]. + - [crossable], which admits [String] and [Slice _] only as "a + parameter" and refuses an aggregate return from a [declare] outright. + + So this is a guard against those two rules changing, and not a feature + waiting to be written. If one ever does change, the work it names is + *SysV classification* and not the internal convention in the header: C + returns a 16-byte slice in rax:rdx, and there is no classifier in this + file. Refusing is the honest answer until there is. *) + if is_agg rty then + unsupported + "%s returns %s by value, which needs SysV return classification this \ + backend does not have" sym (Types.to_string rty); store_loc f ~reg:(if is_float rty then xmm0 else rax) dst rty end