@@ -1113,6 +1113,12 @@ let collect_type_aliases_from_userspace_program userspace_prog =
11131113
11141114 List. rev ! type_aliases
11151115
1116+ (* * Helper function to take first n elements from a list *)
1117+ let rec list_take n lst =
1118+ match n, lst with
1119+ | 0 , _ | _ , [] -> []
1120+ | n , x :: xs -> x :: list_take (n - 1 ) xs
1121+
11161122(* * Get printf format specifier for IR type *)
11171123let get_printf_format_specifier ir_type =
11181124 match ir_type with
@@ -1134,35 +1140,41 @@ let get_printf_format_specifier ir_type =
11341140
11351141(* * Fix format specifiers in a format string based on argument types *)
11361142let fix_format_specifiers format_string arg_types =
1137- let format_chars = String. to_seq format_string |> List. of_seq in
1138- let rec fix_formats chars arg_types_list acc =
1139- match chars with
1140- | [] -> String. concat " " (List. rev acc)
1141- | '%' :: '%' :: rest ->
1142- (* Escaped % - keep as is *)
1143- fix_formats rest arg_types_list (" %%" :: acc)
1144- | '%' :: rest ->
1145- (* Format specifier - find the end and replace *)
1146- let rec find_spec_end spec_chars =
1147- match spec_chars with
1148- | [] -> ([] , [] )
1149- | ('d' | 'i' | 'u' | 'o' | 'x' | 'X' | 'f' | 'F' | 'e' | 'E' | 'g' | 'G' | 'c' | 's' | 'p' | 'n' ) :: rest ->
1150- (spec_chars, rest)
1151- | c :: rest ->
1152- let (spec, remaining) = find_spec_end rest in
1153- (c :: spec, remaining)
1154- in
1155- let (spec_chars, remaining) = find_spec_end rest in
1156- (match arg_types_list with
1157- | [] -> fix_formats remaining [] (String. concat " " (List. rev_map (String. make 1 ) spec_chars) :: " %" :: acc)
1158- | arg_type :: rest_types ->
1159- let new_spec = get_printf_format_specifier arg_type in
1160- fix_formats remaining rest_types (new_spec :: acc))
1161- | c :: rest ->
1162- (* Regular character - keep as is *)
1163- fix_formats rest arg_types_list (String. make 1 c :: acc)
1143+ (* Count existing format specifiers in the string *)
1144+ let count_format_specs str =
1145+ let rec count chars spec_count =
1146+ match chars with
1147+ | [] -> spec_count
1148+ | '%' :: '%' :: rest -> count rest spec_count (* Skip escaped %% *)
1149+ | '%' :: rest ->
1150+ (* Find the end of this format specifier *)
1151+ let rec find_spec_end spec_chars =
1152+ match spec_chars with
1153+ | [] -> rest
1154+ | ('d' | 'i' | 'u' | 'o' | 'x' | 'X' | 'f' | 'F' | 'e' | 'E' | 'g' | 'G' | 'c' | 's' | 'p' | 'n' ) :: remaining ->
1155+ remaining
1156+ | _ :: remaining ->
1157+ find_spec_end remaining
1158+ in
1159+ let remaining = find_spec_end rest in
1160+ count remaining (spec_count + 1 )
1161+ | _ :: rest -> count rest spec_count
1162+ in
1163+ count (String. to_seq str |> List. of_seq) 0
11641164 in
1165- fix_formats format_chars arg_types []
1165+
1166+ let existing_specs = count_format_specs format_string in
1167+ let needed_specs = List. length arg_types in
1168+
1169+ if existing_specs > = needed_specs then
1170+ (* Already has enough format specifiers - don't add more *)
1171+ format_string
1172+ else
1173+ (* Need to add format specifiers for missing arguments *)
1174+ let missing_count = needed_specs - existing_specs in
1175+ let missing_types = List. rev (list_take missing_count (List. rev arg_types)) in
1176+ let missing_specs = List. map get_printf_format_specifier missing_types in
1177+ format_string ^ String. concat " " missing_specs
11661178
11671179
11681180
@@ -2598,7 +2610,9 @@ let generate_ringbuf_handlers_from_registry (registry : Ir.ir_ring_buffer_regist
25982610 let value_type = c_type_from_ir_type rb_decl.rb_value_type in
25992611 let handler_name = match List. assoc_opt ringbuf_name registry.event_handler_registrations with
26002612 | Some handler -> handler
2601- | None -> ringbuf_name ^ " _default_handler"
2613+ | None ->
2614+ (* Try callback function naming convention: {ringbuf_name}_callback *)
2615+ ringbuf_name ^ " _callback"
26022616 in
26032617 sprintf {|
26042618// Ring buffer event handler for % s
@@ -3039,12 +3053,18 @@ let generate_complete_userspace_program_from_ir ?(config_declarations = []) ?(ty
30393053 let non_empty_parts = List. filter (fun s -> s <> " " ) parts in
30403054 if non_empty_parts = [] then " " else String. concat " \n " non_empty_parts in
30413055
3056+ let dispatch_is_used = List. length all_usage.used_dispatch_functions > 0 in
3057+
30423058 let map_operation_functions = if all_usage.uses_map_operations then
3043- generate_map_operation_functions used_global_maps ir_multi_prog ~dispatch_used: ( List. length all_usage.used_dispatch_functions > 0 )
3059+ generate_map_operation_functions used_global_maps ir_multi_prog ~dispatch_used: dispatch_is_used
30443060 else " " in
30453061
3062+ (* Generate ring buffer handlers separately if needed *)
3063+ let ringbuf_handlers = if not dispatch_is_used || all_usage.uses_map_operations then " "
3064+ else generate_ringbuf_handlers_from_registry ir_multi_prog.ring_buffer_registry ~dispatch_used: dispatch_is_used in
3065+
30463066 let ringbuf_dispatch_functions =
3047- if List. length all_usage.used_dispatch_functions = 0 then " "
3067+ if not dispatch_is_used then " "
30483068 else generate_dispatch_functions all_usage.used_dispatch_functions in
30493069
30503070
@@ -3209,7 +3229,9 @@ void cleanup_bpf_maps(void) {
32093229% s
32103230
32113231% s
3212- | } includes string_typedefs type_alias_definitions string_helpers enum_definitions structs_with_pinned skeleton_code all_fd_declarations map_operation_functions ringbuf_dispatch_functions auto_bpf_init_code getopt_parsing_code bpf_helper_functions struct_ops_attach_functions functions
3232+
3233+ % s
3234+ | } includes string_typedefs type_alias_definitions string_helpers enum_definitions structs_with_pinned skeleton_code all_fd_declarations map_operation_functions ringbuf_handlers ringbuf_dispatch_functions auto_bpf_init_code getopt_parsing_code bpf_helper_functions struct_ops_attach_functions functions
32133235
32143236(* * Generate userspace C code from IR multi-program *)
32153237let generate_userspace_code_from_ir ?(config_declarations = [] ) ?(type_aliases = [] ) ?(tail_call_analysis = {Tail_call_analyzer. dependencies = [] ; prog_array_size = 0 ; index_mapping = Hashtbl. create 16 ; errors = [] }) ?(kfunc_dependencies = {kfunc_definitions = [] ; private_functions = [] ; program_dependencies = [] ; module_name = " " }) ?(resolved_imports = [] ) ?symbol_table (ir_multi_prog : ir_multi_program ) ?(output_dir = " ." ) source_filename =
0 commit comments