@@ -284,6 +284,16 @@ let escape_c_string s =
284284
285285let ebpf_type_from_ir_type = Codegen_common. ir_type_to_c Codegen_common. EbpfKernel
286286
287+ (* * Type conversion for kfunc signatures. Unlike ebpf_type_from_ir_type, this keeps
288+ [IRBool] as C [bool] rather than collapsing it to [__u8], so the emitted prototype
289+ matches the kernel's actual kfunc signature (kfunc/extern type matching is strict). *)
290+ let rec kfunc_signature_type_to_c = function
291+ | Ir. IRU8 -> " __u8" | Ir. IRU16 -> " __u16" | Ir. IRU32 -> " __u32" | Ir. IRU64 -> " __u64"
292+ | Ir. IRI8 -> " __s8" | Ir. IRI16 -> " __s16" | Ir. IRI32 -> " __s32" | Ir. IRI64 -> " __s64"
293+ | Ir. IRBool -> " bool" | Ir. IRChar -> " char" | Ir. IRVoid -> " void"
294+ | Ir. IRPointer (inner_type , _ ) -> sprintf " %s*" (kfunc_signature_type_to_c inner_type)
295+ | other -> ebpf_type_from_ir_type other
296+
287297(* * Generate proper C declaration for eBPF, handling function pointers correctly *)
288298let generate_ebpf_c_declaration = Codegen_common. c_declaration Codegen_common. EbpfKernel
289299
@@ -3036,6 +3046,27 @@ let generate_declarations_in_source_order_unified ctx ir_multi_prog ~_btf_path _
30363046 (* Generate struct_ops instance *)
30373047 emit_line ctx (sprintf " /* eBPF struct_ops instance: %s */" struct_ops_instance.ir_instance_name);
30383048 emit_blank_line ctx
3049+
3050+ | Ir. IRDeclKfuncDecl kfunc_decl ->
3051+ (* Emit a function-signature declaration so eBPF programs can call the kfunc.
3052+ Kernel-provided kfuncs need `extern ... __ksym;`; locally-defined @kfunc
3053+ functions just need a forward prototype. *)
3054+ let params_str = match kfunc_decl.Ir. ikfunc_params with
3055+ | [] -> " void"
3056+ | params -> String. concat " , " (List. map (fun (name , ir_type ) ->
3057+ sprintf " %s %s" (kfunc_signature_type_to_c ir_type) name
3058+ ) params)
3059+ in
3060+ let return_type_str = kfunc_signature_type_to_c kfunc_decl.Ir. ikfunc_return_type in
3061+ if kfunc_decl.Ir. ikfunc_is_extern then
3062+ emit_line ctx (sprintf " extern %s %s(%s) __ksym;"
3063+ return_type_str kfunc_decl.Ir. ikfunc_name params_str)
3064+ else (
3065+ emit_line ctx " /* kfunc declaration */" ;
3066+ emit_line ctx (sprintf " %s %s(%s);"
3067+ return_type_str kfunc_decl.Ir. ikfunc_name params_str)
3068+ );
3069+ emit_blank_line ctx
30393070 ) ir_multi_prog.Ir. source_declarations;
30403071
30413072 (* Emit callbacks at the end if no functions were found (fallback) *)
@@ -3241,7 +3272,7 @@ let collect_callback_dependencies ir_multi_prog =
32413272
32423273(* * Compile multi-program IR to eBPF C code with automatic tail call detection *)
32433274let compile_multi_to_c_with_tail_calls
3244- ?(kfunc_declarations = [] ) ?( tail_call_analysis =None ) ?(btf_path =None )
3275+ ?(tail_call_analysis =None ) ?(btf_path =None )
32453276 (ir_multi_prog : Ir.ir_multi_program ) =
32463277
32473278 let ctx = create_c_context () in
@@ -3260,30 +3291,10 @@ let compile_multi_to_c_with_tail_calls
32603291 let uses_dynptr = check_dynptr_usage ir_multi_prog in
32613292 if uses_dynptr then generate_dynptr_macros ctx;
32623293
3263- (* Generate kfunc declarations *)
3264- let rec ast_type_to_c_type ast_type =
3265- match ast_type with
3266- | Ast. U8 -> " __u8" | Ast. U16 -> " __u16" | Ast. U32 -> " __u32" | Ast. U64 -> " __u64"
3267- | Ast. I8 -> " __s8" | Ast. I16 -> " __s16" | Ast. I32 -> " __s32" | Ast. I64 -> " __s64"
3268- | Ast. Bool -> " bool" | Ast. Char -> " char" | Ast. Void -> " void"
3269- | Ast. Pointer inner_type -> sprintf " %s*" (ast_type_to_c_type inner_type)
3270- | _ -> " void"
3271- in
3272- List. iter (fun kfunc ->
3273- let params_str = String. concat " , " (List. map (fun (name , param_type ) ->
3274- let c_type = ast_type_to_c_type param_type in
3275- sprintf " %s %s" c_type name
3276- ) kfunc.Ast. func_params) in
3277- let return_type_str = match Ast. get_return_type kfunc.Ast. func_return_type with
3278- | Some ret_type -> ast_type_to_c_type ret_type
3279- | None -> " void"
3280- in
3281- emit_line ctx (sprintf " /* kfunc declaration */" );
3282- emit_line ctx (sprintf " %s %s(%s);" return_type_str kfunc.Ast. func_name params_str);
3283- ) kfunc_declarations;
3284-
3285- if kfunc_declarations <> [] then emit_blank_line ctx;
3286-
3294+ (* Kfunc declarations (both kernel-provided `extern` kfuncs and locally-defined
3295+ @kfunc prototypes) are carried in the IR as IRDeclKfuncDecl and emitted in
3296+ source order by generate_declarations_in_source_order_unified. *)
3297+
32873298 (* Generate string type definitions *)
32883299 generate_string_typedefs ctx ir_multi_prog;
32893300
@@ -3316,16 +3327,16 @@ let compile_multi_to_c_with_tail_calls
33163327 (final_output, final_tail_call_analysis)
33173328
33183329(* * Multi-program compilation entry point that returns both code and tail call analysis *)
3319- let compile_multi_to_c ?(kfunc_declarations = [] ) ?( tail_call_analysis =None ) ?(btf_path =None ) ir_multi_program =
3330+ let compile_multi_to_c ?(tail_call_analysis =None ) ?(btf_path =None ) ir_multi_program =
33203331 compile_multi_to_c_with_tail_calls
3321- ~kfunc_declarations ~ tail_call_analysis ~btf_path ir_multi_program
3332+ ~tail_call_analysis ~btf_path ir_multi_program
33223333
33233334(* * Alias for backward compatibility with existing code *)
33243335let compile_multi_to_c_with_analysis = compile_multi_to_c
33253336
33263337(* * Generate complete C program from multiple IR programs - main interface *)
3327- let generate_c_multi_program ?(kfunc_declarations = [] ) ?( btf_path =None ) ir_multi_prog =
3328- let (c_code, _) = compile_multi_to_c ~kfunc_declarations ~ btf_path ir_multi_prog in
3338+ let generate_c_multi_program ?(btf_path =None ) ir_multi_prog =
3339+ let (c_code, _) = compile_multi_to_c ~btf_path ir_multi_prog in
33293340 c_code
33303341
33313342(* * Generate complete C program from IR *)
0 commit comments