@@ -1106,9 +1106,55 @@ let generate_declarations_in_source_order ctx _ir_multi_program type_aliases =
11061106 (* Function has side effects on ctx, no return value needed *)
11071107 ()
11081108
1109+ (* * Check if IR multi-program contains object allocation instructions *)
1110+ let rec check_object_allocation_usage_in_instrs instrs =
1111+ List. exists (fun instr ->
1112+ match instr.instr_desc with
1113+ | IRObjectNew (_ , _ ) | IRObjectDelete _ -> true
1114+ | IRIf (_ , then_body , else_body ) ->
1115+ (check_object_allocation_usage_in_instrs then_body) ||
1116+ (match else_body with
1117+ | Some else_instrs -> check_object_allocation_usage_in_instrs else_instrs
1118+ | None -> false )
1119+ | IRIfElseChain (conditions_and_bodies , final_else ) ->
1120+ (List. exists (fun (_ , then_body ) ->
1121+ check_object_allocation_usage_in_instrs then_body
1122+ ) conditions_and_bodies) ||
1123+ (match final_else with
1124+ | Some else_instrs -> check_object_allocation_usage_in_instrs else_instrs
1125+ | None -> false )
1126+ | IRBpfLoop (_ , _ , _ , _ , body_instrs ) ->
1127+ check_object_allocation_usage_in_instrs body_instrs
1128+ | IRTry (try_instrs , catch_clauses ) ->
1129+ (check_object_allocation_usage_in_instrs try_instrs) ||
1130+ (List. exists (fun clause ->
1131+ check_object_allocation_usage_in_instrs clause.catch_body
1132+ ) catch_clauses)
1133+ | IRDefer defer_instrs ->
1134+ check_object_allocation_usage_in_instrs defer_instrs
1135+ | _ -> false
1136+ ) instrs
1137+
1138+ let check_object_allocation_usage_in_function ir_func =
1139+ List. exists (fun block ->
1140+ check_object_allocation_usage_in_instrs block.instructions
1141+ ) ir_func.basic_blocks
1142+
1143+ let check_object_allocation_usage ir_multi_prog =
1144+ (* Check all programs *)
1145+ (List. exists (fun ir_prog ->
1146+ check_object_allocation_usage_in_function ir_prog.entry_function
1147+ ) ir_multi_prog.programs) ||
1148+ (* Check kernel functions *)
1149+ (List. exists check_object_allocation_usage_in_function ir_multi_prog.kernel_functions)
1150+
1151+ (* * Check if a single IR program contains object allocation instructions *)
1152+ let check_object_allocation_usage_in_program ir_prog =
1153+ check_object_allocation_usage_in_function ir_prog.entry_function
1154+
11091155(* * Generate standard eBPF includes *)
11101156
1111- let generate_includes ctx ?(program_types =[] ) () =
1157+ let generate_includes ctx ?(program_types =[] ) ?( ir_multi_prog = None ) ?( ir_program = None ) () =
11121158 (* Use vmlinux.h which contains all kernel types from BTF *)
11131159 let vmlinux_includes = [
11141160 " #include \" vmlinux.h\" " ;
@@ -1156,34 +1202,43 @@ let generate_includes ctx ?(program_types=[]) () =
11561202 List. iter (emit_line ctx) all_includes;
11571203 emit_blank_line ctx;
11581204
1159- (* Use proper kernel implementation: extern declarations and macros *)
1160- emit_line ctx " extern void *bpf_obj_new_impl(__u64 local_type_id__k, void *meta__ign) __ksym;" ;
1161- emit_line ctx " extern void bpf_obj_drop_impl(void *p__alloc, void *meta__ign) __ksym;" ;
1162- emit_blank_line ctx;
1163-
1164- (* Use exact kernel implementation for proper typeof handling *)
1165- emit_line ctx " #define ___concat(a, b) a ## b" ;
1166- emit_line ctx " #ifdef __clang__" ;
1167- emit_line ctx " #define ___bpf_typeof(type) ((typeof(type) *) 0)" ;
1168- emit_line ctx " #else" ;
1169- emit_line ctx " #define ___bpf_typeof1(type, NR) ({ \\ " ;
1170- emit_line ctx " extern typeof(type) *___concat(bpf_type_tmp_, NR); \\ " ;
1171- emit_line ctx " ___concat(bpf_type_tmp_, NR); \\ " ;
1172- emit_line ctx " })" ;
1173- emit_line ctx " #define ___bpf_typeof(type) ___bpf_typeof1(type, __COUNTER__)" ;
1174- emit_line ctx " #endif" ;
1175- emit_blank_line ctx;
1176-
1177- (* Add BPF_TYPE_ID_LOCAL constant *)
1178- emit_line ctx " #ifndef BPF_TYPE_ID_LOCAL" ;
1179- emit_line ctx " #define BPF_TYPE_ID_LOCAL 1" ;
1180- emit_line ctx " #endif" ;
1181- emit_blank_line ctx;
1205+ (* Only include object allocation code if the program actually uses new() or delete() *)
1206+ let uses_object_allocation = match ir_multi_prog, ir_program with
1207+ | Some multi_prog , _ -> check_object_allocation_usage multi_prog
1208+ | None , Some single_prog -> check_object_allocation_usage_in_program single_prog
1209+ | None , None -> false (* Conservative: don't include if we can't analyze *)
1210+ in
11821211
1183- emit_line ctx " #define bpf_core_type_id_kernel(type) __builtin_btf_type_id(*(type*)0, 0)" ;
1184- emit_line ctx " #define bpf_obj_new(type) ((type *)bpf_obj_new_impl(bpf_core_type_id_kernel(type), NULL))" ;
1185- emit_line ctx " #define bpf_obj_drop(ptr) bpf_obj_drop_impl(ptr, NULL)" ;
1186- emit_blank_line ctx
1212+ if uses_object_allocation then (
1213+ (* Use proper kernel implementation: extern declarations and macros *)
1214+ emit_line ctx " extern void *bpf_obj_new_impl(__u64 local_type_id__k, void *meta__ign) __ksym;" ;
1215+ emit_line ctx " extern void bpf_obj_drop_impl(void *p__alloc, void *meta__ign) __ksym;" ;
1216+ emit_blank_line ctx;
1217+
1218+ (* Use exact kernel implementation for proper typeof handling *)
1219+ emit_line ctx " #define ___concat(a, b) a ## b" ;
1220+ emit_line ctx " #ifdef __clang__" ;
1221+ emit_line ctx " #define ___bpf_typeof(type) ((typeof(type) *) 0)" ;
1222+ emit_line ctx " #else" ;
1223+ emit_line ctx " #define ___bpf_typeof1(type, NR) ({ \\ " ;
1224+ emit_line ctx " extern typeof(type) *___concat(bpf_type_tmp_, NR); \\ " ;
1225+ emit_line ctx " ___concat(bpf_type_tmp_, NR); \\ " ;
1226+ emit_line ctx " })" ;
1227+ emit_line ctx " #define ___bpf_typeof(type) ___bpf_typeof1(type, __COUNTER__)" ;
1228+ emit_line ctx " #endif" ;
1229+ emit_blank_line ctx;
1230+
1231+ (* Add BPF_TYPE_ID_LOCAL constant *)
1232+ emit_line ctx " #ifndef BPF_TYPE_ID_LOCAL" ;
1233+ emit_line ctx " #define BPF_TYPE_ID_LOCAL 1" ;
1234+ emit_line ctx " #endif" ;
1235+ emit_blank_line ctx;
1236+
1237+ emit_line ctx " #define bpf_core_type_id_kernel(type) __builtin_btf_type_id(*(type*)0, 0)" ;
1238+ emit_line ctx " #define bpf_obj_new(type) ((type *)bpf_obj_new_impl(bpf_core_type_id_kernel(type), NULL))" ;
1239+ emit_line ctx " #define bpf_obj_drop(ptr) bpf_obj_drop_impl(ptr, NULL)" ;
1240+ emit_blank_line ctx
1241+ )
11871242 )
11881243
11891244(* * Generate map definitions *)
@@ -3466,7 +3521,7 @@ let generate_c_program ?_config_declarations ir_prog =
34663521
34673522 (* Add standard includes *)
34683523 let program_types = [ir_prog.program_type] in
3469- generate_includes ctx ~program_types () ;
3524+ generate_includes ctx ~program_types ~ir_program: ( Some ir_prog) () ;
34703525
34713526 (* Generate string type definitions *)
34723527 let temp_multi_prog = {
@@ -3539,7 +3594,7 @@ let generate_c_multi_program ?_config_declarations ?(type_aliases=[]) ?(variable
35393594
35403595 (* Add standard includes *)
35413596 let program_types = List. map (fun prog -> prog.program_type) ir_multi_prog.programs in
3542- generate_includes ctx ~program_types () ;
3597+ generate_includes ctx ~program_types ~ir_multi_prog: ( Some ir_multi_prog) () ;
35433598
35443599 (* Generate string type definitions *)
35453600 generate_string_typedefs ctx ir_multi_prog;
@@ -3658,7 +3713,7 @@ let compile_multi_to_c_with_tail_calls
36583713
36593714 (* Generate headers and includes *)
36603715 let program_types = List. map (fun ir_prog -> ir_prog.program_type) ir_multi_prog.programs in
3661- generate_includes ctx ~program_types () ;
3716+ generate_includes ctx ~program_types ~ir_multi_prog: ( Some ir_multi_prog) () ;
36623717
36633718 (* Generate dynptr safety macros and helper functions *)
36643719 emit_line ctx " /* eBPF Dynptr API integration for enhanced pointer safety */" ;
0 commit comments