-
Notifications
You must be signed in to change notification settings - Fork 24
Expand file tree
/
Copy pathcodegen_common.ml
More file actions
126 lines (116 loc) · 6 KB
/
Copy pathcodegen_common.ml
File metadata and controls
126 lines (116 loc) · 6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
(*
* 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.
*)
(** Shared codegen utilities for eBPF and userspace C code generation *)
open Printf
open Ir
(** Target-specific type naming *)
type c_target = EbpfKernel | UserspaceStd
(** Convert IR type to C type string *)
let rec ir_type_to_c target = function
| IRU8 -> (match target with EbpfKernel -> "__u8" | UserspaceStd -> "uint8_t")
| IRU16 -> (match target with EbpfKernel -> "__u16" | UserspaceStd -> "uint16_t")
| IRU32 -> (match target with EbpfKernel -> "__u32" | UserspaceStd -> "uint32_t")
| IRU64 -> (match target with EbpfKernel -> "__u64" | UserspaceStd -> "uint64_t")
| IRI8 -> (match target with EbpfKernel -> "__s8" | UserspaceStd -> "int8_t")
| IRI16 -> (match target with EbpfKernel -> "__s16" | UserspaceStd -> "int16_t")
| IRI32 -> (match target with EbpfKernel -> "__s32" | UserspaceStd -> "int32_t")
| IRI64 -> (match target with EbpfKernel -> "__s64" | UserspaceStd -> "int64_t")
| IRF32 -> (match target with EbpfKernel -> "__u32" | UserspaceStd -> "float")
| IRF64 -> (match target with EbpfKernel -> "__u64" | UserspaceStd -> "double")
| IRVoid -> "void"
| IRBool -> (match target with EbpfKernel -> "__u8" | UserspaceStd -> "bool")
| IRChar -> "char"
| IRStr size ->
(match target with
| EbpfKernel -> sprintf "str_%d_t" size
| UserspaceStd -> "char") (* Base type for userspace string - size handled in declaration *)
| IRPointer (inner_type, _) -> sprintf "%s*" (ir_type_to_c target inner_type)
| IRArray (inner_type, size, _) -> sprintf "%s[%d]" (ir_type_to_c target inner_type) size
| IRStruct ("perf_options", _) -> "ks_perf_options" (* Namespace KS type away from kernel structs *)
| IRStruct (name, _) -> sprintf "struct %s" name
| IREnum (name, _) -> sprintf "enum %s" name
| IRResult (ok_type, _err_type) -> ir_type_to_c target ok_type (* simplified to ok type *)
| IRTypeAlias (name, _) -> name (* Use the alias name directly *)
| IRStructOps (name, _) -> sprintf "struct %s_ops" name
| IRFunctionPointer (param_types, return_type) ->
let return_type_str = ir_type_to_c target return_type in
let param_types_str = List.map (ir_type_to_c target) param_types in
let params_str = if param_types_str = [] then "void" else String.concat ", " param_types_str in
sprintf "%s (*)" return_type_str ^ sprintf "(%s)" params_str
| IRRingbuf (_value_type, _size) ->
(match target with
| EbpfKernel -> "void*"
| UserspaceStd -> "struct ring_buffer*")
(** Generate C declaration: handles function pointers, arrays, strings *)
let c_declaration target ir_type var_name =
match ir_type with
| IRFunctionPointer (param_types, return_type) ->
let return_type_str = ir_type_to_c target return_type in
let param_types_str = List.map (ir_type_to_c target) param_types in
let params_str = if param_types_str = [] then "void" else String.concat ", " param_types_str in
sprintf "%s (*%s)(%s)" return_type_str var_name params_str
| IRStr size ->
(match target with
| EbpfKernel -> sprintf "str_%d_t %s" size var_name
| UserspaceStd -> sprintf "char %s[%d]" var_name size)
| IRArray (element_type, size, _) ->
let element_type_str = ir_type_to_c target element_type in
sprintf "%s %s[%d]" element_type_str var_name size
| _ -> sprintf "%s %s" (ir_type_to_c target ir_type) var_name
(** Check if position indicates kernel-defined type (<builtin> or .kh) *)
let is_kernel_defined_pos pos =
let is_builtin = pos.Ast.filename = "<builtin>" in
let is_btf_type = Filename.check_suffix pos.Ast.filename ".kh" in
is_builtin || is_btf_type
(** Check if struct should be included (not kernel-defined) *)
let should_include_struct _struct_name _struct_ops_declarations pos =
not (is_kernel_defined_pos pos)
(** Generate typedef string *)
let generate_typedef target name ir_type =
match ir_type with
| IRFunctionPointer (param_types, return_type) ->
let return_type_str = ir_type_to_c target return_type in
let param_types_str = List.map (ir_type_to_c target) param_types in
let params_str = if param_types_str = [] then "void" else String.concat ", " param_types_str in
sprintf "typedef %s (*%s)(%s);" return_type_str name params_str
| IRArray (inner_type, size, _) ->
let element_type_str = ir_type_to_c target inner_type in
sprintf "typedef %s %s[%d];" element_type_str name size
| _ ->
let c_type = ir_type_to_c target ir_type in
sprintf "typedef %s %s;" c_type name
(** Generate struct definition string *)
let generate_struct_def target name fields =
let field_lines = List.map (fun (field_name, field_type) ->
match field_type with
| IRArray (inner_type, size, _) ->
let element_type_str = ir_type_to_c target inner_type in
sprintf " %s %s[%d];" element_type_str field_name size
| IRStr size when target = UserspaceStd ->
sprintf " char %s[%d];" field_name size
| _ ->
let c_type = ir_type_to_c target field_type in
sprintf " %s %s;" c_type field_name
) fields in
sprintf "struct %s {\n%s\n};" name (String.concat "\n" field_lines)
(** Generate enum definition string *)
let generate_enum_def name values =
let value_count = List.length values in
let enum_lines = List.mapi (fun i (const_name, value) ->
sprintf " %s = %s%s" const_name (Ast.IntegerValue.to_string value)
(if i = value_count - 1 then "" else ",")
) values in
sprintf "enum %s {\n%s\n};" name (String.concat "\n" enum_lines)