FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

(* * Copyright 2025 Multikernel Technologies, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *) (** Kernel Module Code Generation for @kfunc Functions This module generates kernel module C code for functions annotated with @kfunc. The generated module automatically registers kfuncs with the eBPF subsystem. *) open Ast open Printf (** Kernel module generation context *) type kmodule_context = { module_name: string; kfunc_functions: function_def list; private_functions: function_def list; dependencies: string list; } (** Create a new kernel module context *) let create_context module_name = { module_name; kfunc_functions = []; private_functions = []; dependencies = []; } (** Add a kfunc to the context *) let add_kfunc context func_def = { context with kfunc_functions = func_def :: context.kfunc_functions } (** Add a private function to the context *) let add_private context func_def = { context with private_functions = func_def :: context.private_functions } (** Convert KernelScript type to C type for kernel module *) let kernelscript_type_to_c_type = function | U8 -> "u8" | U16 -> "u16" | U32 -> "u32" | U64 -> "u64" | I8 -> "s8" | I16 -> "s16" | I32 -> "s32" | I64 -> "s64" | Bool -> "bool" | Char -> "char" | Void -> "void" | Pointer U8 -> "u8 *" | Pointer U16 -> "u16 *" | Pointer U32 -> "u32 *" | Pointer U64 -> "u64 *" | Pointer I8 -> "s8 *" | Pointer I16 -> "s16 *" | Pointer I32 -> "s32 *" | Pointer I64 -> "s64 *" | Pointer Char -> "char *" | Pointer Void -> "void *" | _ -> "void *" (* Fallback for complex types *) (** Generate function signature for regular kernel module functions *) let generate_function_signature func_def = let return_type = match get_return_type func_def.func_return_type with | Some ret_type -> kernelscript_type_to_c_type ret_type | None -> "void" in let params = List.map (fun (param_name, param_type) -> sprintf "%s %s" (kernelscript_type_to_c_type param_type) param_name ) func_def.func_params in let params_str = if params = [] then "void" else String.concat ", " params in sprintf "static %s %s(%s)" return_type func_def.func_name params_str (** Generate function signature for kfunc kernel module functions with proper annotations *) let generate_kfunc_signature func_def = let return_type = match get_return_type func_def.func_return_type with | Some ret_type -> kernelscript_type_to_c_type ret_type | None -> "void" in let params = List.map (fun (param_name, param_type) -> sprintf "%s %s" (kernelscript_type_to_c_type param_type) param_name ) func_def.func_params in let params_str = if params = [] then "void" else String.concat ", " params in sprintf "__bpf_kfunc %s %s(%s)" return_type func_def.func_name params_str (** Generate function prototype for regular kernel module functions *) let generate_function_prototype func_def = let return_type = match get_return_type func_def.func_return_type with | Some ret_type -> kernelscript_type_to_c_type ret_type | None -> "void" in let params = List.map (fun (param_name, param_type) -> sprintf "%s %s" (kernelscript_type_to_c_type param_type) param_name ) func_def.func_params in let params_str = if params = [] then "void" else String.concat ", " params in sprintf "static %s %s(%s);" return_type func_def.func_name params_str (** Generate statement translation *) let rec generate_statement_translation stmt = match stmt.stmt_desc with | Return (Some expr) -> sprintf " return %s;" (generate_expression_translation expr) | Return None -> " return;" | Assignment (var_name, expr) -> sprintf " %s = %s;" var_name (generate_expression_translation expr) | CompoundAssignment (var_name, op, expr) -> let expr_str = generate_expression_translation expr in let op_str = match op with | Add -> "+" | Sub -> "-" | Mul -> "*" | Div -> "/" | Mod -> "%" | _ -> failwith "Unsupported operator in compound assignment" in sprintf " %s %s= %s;" var_name op_str expr_str | Declaration (var_name, Some var_type, expr_opt) -> (match expr_opt with | Some expr -> sprintf " %s %s = %s;" (kernelscript_type_to_c_type var_type) var_name (generate_expression_translation expr) | None -> sprintf " %s %s;" (kernelscript_type_to_c_type var_type) var_name) | Declaration (var_name, None, expr_opt) -> (match expr_opt with | Some expr -> sprintf " auto %s = %s;" var_name (generate_expression_translation expr) | None -> sprintf " /* Declaration %s; */" var_name) | If (condition, then_stmts, else_stmts) -> let condition_str = generate_expression_translation condition in let then_block = String.concat "\n" (List.map generate_statement_translation then_stmts) in let else_block = match else_stmts with | Some stmts -> sprintf " else {\n%s\n }" (String.concat "\n" (List.map generate_statement_translation stmts)) | None -> "" in sprintf " if (%s) {\n%s\n }%s" condition_str then_block else_block | For (var_name, start_expr, end_expr, body_stmts) -> let start_str = generate_expression_translation start_expr in let end_str = generate_expression_translation end_expr in let body_str = String.concat "\n" (List.map generate_statement_translation body_stmts) in sprintf " for (int %s = %s; %s < %s; %s++) {\n%s\n }" var_name start_str var_name end_str var_name body_str | While (condition, body_stmts) -> let condition_str = generate_expression_translation condition in let body_str = String.concat "\n" (List.map generate_statement_translation body_stmts) in sprintf " while (%s) {\n%s\n }" condition_str body_str | ExprStmt expr -> sprintf " %s;" (generate_expression_translation expr) | Break -> " break;" | Continue -> " continue;" | Delete (DeletePointer ptr_expr) -> (* Translate pointer deletion to kfree() *) let ptr_str = generate_expression_translation ptr_expr in sprintf " kfree(%s);" ptr_str | Delete (DeleteMapEntry (map_expr, key_expr)) -> (* Map deletion not supported in kernel modules - this should be caught earlier *) sprintf " /* Map deletion not supported in kernel modules: delete %s[%s] */" (generate_expression_translation map_expr) (generate_expression_translation key_expr) | _ -> " /* TODO: Implement statement translation */" (** Generate expression translation *) and generate_expression_translation expr = match expr.expr_desc with | Literal (IntLit (value, _)) -> Ast.IntegerValue.to_string value | Literal (StringLit str) -> sprintf "\"%s\"" str | Literal (BoolLit true) -> "true" | Literal (BoolLit false) -> "false" | Literal NullLit -> "NULL" | Identifier name -> name | BinaryOp (left, op, right) -> let left_str = generate_expression_translation left in let right_str = generate_expression_translation right in let op_str = match op with | Add -> "+" | Sub -> "-" | Mul -> "*" | Div -> "/" | Mod -> "%" | Eq -> "==" | Ne -> "!=" | Lt -> "" | Ge -> ">=" | And -> "&&" | Or -> "||" in sprintf "(%s %s %s)" left_str op_str right_str | UnaryOp (op, operand) -> let operand_str = generate_expression_translation operand in let op_str = match op with | Not -> "!" | Neg -> "-" | Deref -> "*" | AddressOf -> "&" in sprintf "(%s%s)" op_str operand_str | Call (callee_expr, args) -> (* Generate the callee expression (could be function name or function pointer) *) let callee_str = generate_expression_translation callee_expr in (* Check if this is a simple function name (identifier) that needs special handling *) let (actual_name, translated_args) = match callee_expr.expr_desc with | Identifier func_name -> (* Check if this is a built-in function that needs context-specific translation *) (match Stdlib.get_kernel_implementation func_name with | Some kernel_impl when kernel_impl "" -> (* This is a built-in function - translate for kernel module context *) (match func_name with | "print" -> (* For kernel modules, printk needs KERN_INFO prefix and proper formatting *) let c_args = List.map generate_expression_translation args in (match c_args with | [] -> (kernel_impl, ["KERN_INFO \"\""]) | [first] -> (kernel_impl, [sprintf "KERN_INFO %s" first]) | first :: rest -> (* For multiple args, format as: printk(KERN_INFO format, args...) *) let format_specifiers = List.map (fun _ -> "%s") rest in let format_str = sprintf "KERN_INFO %s %s" first (String.concat " " format_specifiers) in (kernel_impl, format_str :: rest)) | _ -> (* For other built-in functions, use standard conversion *) let c_args = List.map generate_expression_translation args in (kernel_impl, c_args)) | _ -> (* Regular function call *) let c_args = List.map generate_expression_translation args in (func_name, c_args)) | _ -> (* Complex expression (function pointer call) *) let c_args = List.map generate_expression_translation args in (callee_str, c_args) in let args_str = String.concat ", " translated_args in sprintf "%s(%s)" actual_name args_str | FieldAccess (obj, field) -> sprintf "%s.%s" (generate_expression_translation obj) field | ArrowAccess (obj, field) -> sprintf "%s->%s" (generate_expression_translation obj) field | ArrayAccess (array, index) -> sprintf "%s[%s]" (generate_expression_translation array) (generate_expression_translation index) | New typ -> (* Basic allocation with GFP_KERNEL (default for kernel context) *) let c_type = kernelscript_type_to_c_type typ in sprintf "kmalloc(sizeof(%s), GFP_KERNEL)" c_type | NewWithFlag (typ, flag_expr) -> (* Allocation with specific GFP flag *) let c_type = kernelscript_type_to_c_type typ in let flag_str = generate_expression_translation flag_expr in sprintf "kmalloc(sizeof(%s), %s)" c_type flag_str | _ -> "/* TODO: Implement expression translation */" (** Generate function implementation for regular kernel module functions *) let generate_function_implementation func_def = let signature = generate_function_signature func_def in let body = String.concat "\n" (List.map generate_statement_translation func_def.func_body) in sprintf "%s\n{\n%s\n}" signature body (** Generate function implementation for kfunc kernel module functions *) let generate_kfunc_implementation func_def = let signature = generate_kfunc_signature func_def in let body = String.concat "\n" (List.map generate_statement_translation func_def.func_body) in sprintf "%s\n{\n%s\n}" signature body (** Generate complete kernel module *) let generate_kernel_module context = let header = sprintf {|/* * Generated kernel module for kfunc definitions * Module: %s * Generated by KernelScript compiler */ #include #include #include #include #include #include MODULE_LICENSE("GPL"); MODULE_AUTHOR("KernelScript Compiler"); MODULE_DESCRIPTION("Auto-generated kfunc module for %s"); MODULE_VERSION("1.0"); |} context.module_name context.module_name in (* Forward prototypes for private helpers so kfuncs defined later can call them. Kfuncs don't need their own prototypes - __bpf_kfunc_start_defs() suppresses -Wmissing-prototypes, and upstream kfunc modules don't emit them either. *) let prototypes_section = if context.private_functions = [] then "" else sprintf "/* Function prototypes */\n%s\n\n" (String.concat "\n" (List.map generate_function_prototype context.private_functions)) in (* Generate private function implementations first (so kfuncs can call them) *) let private_implementations = String.concat "\n\n" (List.map generate_function_implementation context.private_functions) in (* Generate kfunc implementations *) let kfunc_implementations = if context.kfunc_functions = [] then "" else sprintf {| /* Begin kfunc definitions */ __bpf_kfunc_start_defs(); %s /* End kfunc definitions */ __bpf_kfunc_end_defs(); |} (String.concat "\n\n" (List.map generate_kfunc_implementation context.kfunc_functions)) in let kfunc_btf_ids = String.concat "\n" (List.map (fun func_def -> sprintf "BTF_ID_FLAGS(func, %s)" func_def.func_name ) context.kfunc_functions) in let btf_id_set = sprintf {| /* BTF ID set for kfuncs */ BTF_KFUNCS_START(%s_kfunc_btf_ids) %s BTF_KFUNCS_END(%s_kfunc_btf_ids) static const struct btf_kfunc_id_set %s_kfunc_set = { .owner = THIS_MODULE, .set = &%s_kfunc_btf_ids, }; |} context.module_name kfunc_btf_ids context.module_name context.module_name context.module_name in let init_function = sprintf {| static int __init %s_init(void) { int ret; pr_info("Loading %s kfunc module\n"); /* Register BTF kfunc set */ ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, &%s_kfunc_set); if (ret < 0) { pr_err("Failed to register kfunc set: %%d\n", ret); return ret; } pr_info("%s kfunc module loaded successfully\n"); return 0; } static void __exit %s_exit(void) { /* Cleanup is handled automatically by the kernel during module unload */ pr_info("%s kfunc module unloaded successfully\n"); } module_init(%s_init); module_exit(%s_exit); |} context.module_name context.module_name context.module_name context.module_name context.module_name context.module_name context.module_name context.module_name in (* Combine all function implementations *) let all_implementations = if private_implementations = "" then kfunc_implementations else if kfunc_implementations = "" then private_implementations else sprintf "%s\n\n%s" private_implementations kfunc_implementations in sprintf "%s\n%s%s\n\n%s\n\n%s" header prototypes_section all_implementations btf_id_set init_function (** Extract kfunc functions from AST *) let extract_kfunc_functions ast = List.filter_map (function | AttributedFunction attr_func -> (* Check if this is a kfunc *) let is_kfunc = List.exists (function | SimpleAttribute "kfunc" -> true | _ -> false ) attr_func.attr_list in if is_kfunc then Some attr_func.attr_function else None | _ -> None ) ast (** Extract private functions from AST *) let extract_private_functions ast = List.filter_map (function | AttributedFunction attr_func -> (* Check if this is a private function *) let is_private = List.exists (function | SimpleAttribute "private" -> true | _ -> false ) attr_func.attr_list in if is_private then Some attr_func.attr_function else None | _ -> None ) ast (** Main entry point for kernel module generation *) let generate_kernel_module_from_ast module_name ast = let kfunc_functions = extract_kfunc_functions ast in let private_functions = extract_private_functions ast in if kfunc_functions = [] && private_functions = [] then None (* No kernel module functions found, don't generate module *) else let context = create_context module_name in let context_with_kfuncs = List.fold_left add_kfunc context kfunc_functions in let context_with_all = List.fold_left add_private context_with_kfuncs private_functions in Some (generate_kernel_module context_with_all)

Back | FazBrowse Home | New Git URL