diff --git a/libISA/backend_c.ml b/libISA/backend_c.ml index 8194f3e2..a181af65 100644 --- a/libISA/backend_c.ml +++ b/libISA/backend_c.ml @@ -1401,10 +1401,12 @@ let fun_decls (xs : AST.declaration list) : AST.declaration list = (**************************************************************** * The core of this process is data conversion for which we * generate the following from the ASL variable name and type - * - A C variable name - * - The corresponding C type - * - Code to convert the ASL type to the C type - * - Code to convert the C type to the ASL type + * - c_name: A C variable name + * - pp_c_type: Code to generate the corresponding C type + * - pp_c_decl: Code to generate a declaration for the C variable + * - pp_c_ref: Code to pass the argument by reference (either x (for arrays) or &x) + * - pp_asl_to_c: Code to convert the ASL type to the C type + * - pp_c_to_asl: Code to convert the C type to the ASL type * The type and conversion code are Format functions. * Optionally, the C variable can be a pointer to a value. * For convenience, the ASL variable and type are also part of the @@ -1417,6 +1419,7 @@ type ffi_conversion = { c_name : Ident.t; pp_c_type : (PP.formatter -> unit) option; pp_c_decl : PP.formatter -> unit; + pp_c_ref : (PP.formatter -> unit); pp_asl_to_c : PP.formatter -> unit; pp_c_to_asl : PP.formatter -> unit; } @@ -1434,6 +1437,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na pp_c_type = Some (fun fmt -> PP.fprintf fmt "uint%d_t" n_fixed); pp_c_decl = (fun fmt -> PP.fprintf fmt "uint%d_t %a%a" n_fixed ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () @@ -1455,6 +1459,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na PP.fprintf fmt "uint64_t %a[%d]" ident c_name chunks); + pp_c_ref = (fun fmt -> PP.fprintf fmt "%a" ident c_name); (* no & required *) pp_asl_to_c = (fun fmt -> Runtime.ffi_asl2c_bits_large fmt n pp_c_name pp_asl_name); pp_c_to_asl = (fun fmt -> @@ -1469,6 +1474,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na c_name = c_name; pp_c_type = Some (fun fmt -> PP.fprintf fmt "bool%a" ptr ()); pp_c_decl = (fun fmt -> PP.fprintf fmt "bool %a%a" ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () ident c_name ident asl_name); pp_c_to_asl = (fun fmt -> PP.fprintf fmt "bool %a = %a%a;" ident asl_name ptr () ident c_name); } @@ -1483,6 +1489,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na c_name = c_name; pp_c_type = Some (fun fmt -> PP.fprintf fmt "const char*%a" ptr ()); pp_c_decl = (fun fmt -> PP.fprintf fmt "const char *%a%a" ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () ident c_name ident asl_name); pp_c_to_asl = (fun fmt -> PP.fprintf fmt "const char *%a = %a%a;" ident asl_name ptr () ident c_name); } @@ -1493,6 +1500,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na c_name = c_name; pp_c_type = Some (fun fmt -> PP.fprintf fmt "enum %a%a" ident tc ptr ()); pp_c_decl = (fun fmt -> PP.fprintf fmt "enum %a %a%a" ident tc ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () ident c_name ident asl_name); pp_c_to_asl = (fun fmt -> PP.fprintf fmt "%a %a = %a%a;" ident tc ident asl_name ptr () ident c_name); } @@ -1502,6 +1510,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na c_name = c_name; pp_c_type = Some (fun fmt -> PP.fprintf fmt "int%a" ptr ()); pp_c_decl = (fun fmt -> PP.fprintf fmt "int %a%a" ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () ident c_name ident asl_name); pp_c_to_asl = (fun fmt -> PP.fprintf fmt "%a %a = %a%a;" ident tc ident asl_name ptr () ident c_name); } @@ -1511,6 +1520,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na c_name = c_name; pp_c_type = Some (fun fmt -> PP.fprintf fmt "%s%a" !ffi_integer ptr ()); pp_c_decl = (fun fmt -> PP.fprintf fmt "%s %a%a" !ffi_integer ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () @@ -1530,6 +1540,7 @@ let mk_ffi_conversion (loc : Loc.t) (indirect : bool) (c_name : Ident.t) (asl_na c_name = c_name; pp_c_type = Some (fun fmt -> PP.fprintf fmt "int%a" ptr ()); pp_c_decl = (fun fmt -> PP.fprintf fmt "int %a%a" ptr () ident c_name); + pp_c_ref = (fun fmt -> PP.fprintf fmt "&%a" ident c_name); pp_asl_to_c = (fun fmt -> PP.fprintf fmt "%a%a = %a;" ptr () @@ -1807,8 +1818,7 @@ let mk_ffi_import_wrapper Ident.pp asl_field_name Ident.pp asl_name in - let pp_c_arg fmt = PP.fprintf fmt "&%a" Ident.pp field.c_name in - (pp_insert, field_indirect.pp_c_decl, field.pp_c_decl, pp_c_arg, field.pp_c_to_asl) + (pp_insert, field_indirect.pp_c_decl, field.pp_c_decl, field.pp_c_ref, field.pp_c_to_asl) ) |> Utils.split5 in diff --git a/tests/backends/ffi_import_03.c b/tests/backends/ffi_import_03.c new file mode 100644 index 00000000..beb08c50 --- /dev/null +++ b/tests/backends/ffi_import_03.c @@ -0,0 +1,16 @@ +// FFI testing support functions to be imported into ISA test programs +// Copyright (C) 2025-2026 Intel Corporation +#include +#include "isa_ffi.h" + +// Wide bitvectors are represented as arrays of uint64_t +// If returning a wide bitvector, an extra array argument is +// added as the last argument + +void FFI_bits_bool(int64_t x, uint64_t r0[2], bool *r1) +{ + for(int i = 0; i < 2; ++i) { + r0[i] = (uint64_t)x; + } + *r1 = true; +} diff --git a/tests/backends/ffi_import_03.isa b/tests/backends/ffi_import_03.isa new file mode 100644 index 00000000..a820186c --- /dev/null +++ b/tests/backends/ffi_import_03.isa @@ -0,0 +1,36 @@ +// RUN: %aslrun %s --transform-foreign --extra-c=%S/ffi_import_03.c | filecheck %s +// Copyright (C) 2025-2026 Intel Corporation + +// UNSUPPORTED: interpreter + +// Check that returning a tuple containing a large bitvector works +// (Fixes a bug caused by the generated C containing "&v1" +// when v1 is the array the result should be placed in. +// This is incorrect because C automatically promotes arrays to pointers +// by implicitly adding the "&" for us.) +// +// Note that this test does not invoke the :xform_tuples transform so +// we manually apply the effect of :xform_tuples by introducing the +// __Return_FFI_bits_bool tuple. + +record __Return_FFI_bits_bool = { + r0 : Bits(128), + r1 : Boolean +}; + +function FFI_bits_bool(x : Integer) -> __Return_FFI_bits_bool; + +foreign import function "FFI_bits_bool" = FFI_bits_bool with {}; + +function main() -> Builtin::Foreign::CInt +begin + let ret1 := FFI_bits_bool(3); + + Std::Print::Bits::Hex(ret1.r0); Print("\n"); + // CHECK: 128'x30000000000000003 + + Std::Print::Boolean(ret1.r1); Print("\n"); + // CHECK: True + + return Builtin::Foreign::CInt::From_Integer(0); +end