Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions libISA/backend_c.ml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand All @@ -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 ()
Expand All @@ -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 ->
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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);
}
Expand All @@ -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 ()
Expand All @@ -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 ()
Expand Down Expand Up @@ -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
Expand Down
16 changes: 16 additions & 0 deletions tests/backends/ffi_import_03.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// FFI testing support functions to be imported into ISA test programs
// Copyright (C) 2025-2026 Intel Corporation
#include <stdint.h>
#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;
}
36 changes: 36 additions & 0 deletions tests/backends/ffi_import_03.isa
Original file line number Diff line number Diff line change
@@ -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
Loading