ffi #foreign: C-variadic tail via args: ..T

Trailing `args: ..T` on a #foreign declaration now lowers to the C
calling convention's `...` instead of sx-side slice-packing. Drops
the per-arity #foreign-shim workaround for callers of variadic C
APIs (__android_log_print, printf-family, etc.). Closes issue-0043.

- IR: Function.is_variadic on inst.Function; declareFunction drops
  the variadic param from the IR signature for foreign+variadic
  decls.
- emit_llvm: LLVMFunctionType receives is_var_arg=1 when the flag
  is set; call lowering passes extras through unchanged.
- Lowering: packVariadicCallArgs early-outs for foreign+variadic
  (no slice-pack); new promoteCVariadicArgs applies C default
  argument promotion (bool/s8/s16/u8/u16 -> s32, f32 -> f64) to
  extras past the fixed param count.
- Test: examples/ffi-foreign-cvariadic.sx + .c exercise s64/f64/s32
  returns through C va_arg over s32/f64/*u8 element types.

134 host + 6 cross tests pass on the WIP-less baseline.
This commit is contained in:
agra
2026-05-22 13:13:43 +03:00
parent cc29cfa7ce
commit 30fed66616
7 changed files with 112 additions and 3 deletions

View File

@@ -662,7 +662,8 @@ pub const LLVMEmitter = struct {
param_types[j + sret_offset] = if (needs_c_abi) self.abiCoerceParamType(param.ty, llvm_ty) else llvm_ty;
}
const fn_type = c.LLVMFunctionType(ret_ty, param_types.ptr, param_count, 0);
const is_var_arg: c_int = if (func.is_variadic) 1 else 0;
const fn_type = c.LLVMFunctionType(ret_ty, param_types.ptr, param_count, is_var_arg);
const name_z = self.alloc.dupeZ(u8, name) catch unreachable;
defer self.alloc.free(name_z);