|
4 | 4 | from llvmlite import ir |
5 | 5 | from pythonbpf.expr import ( |
6 | 6 | get_operand_value, |
| 7 | + eval_expr, |
7 | 8 | ) |
8 | 9 |
|
9 | 10 | logger = logging.getLogger(__name__) |
@@ -190,3 +191,86 @@ def get_buffer_ptr_and_size(buf_arg, builder, local_sym_tab, struct_sym_tab): |
190 | 191 | raise ValueError( |
191 | 192 | "comm expects either a struct field (obj.field) or variable name" |
192 | 193 | ) |
| 194 | + |
| 195 | + |
| 196 | +def get_char_array_ptr_and_size(buf_arg, builder, local_sym_tab, struct_sym_tab): |
| 197 | + """Get pointer to char array and its size.""" |
| 198 | + |
| 199 | + # Struct field: obj.field |
| 200 | + if isinstance(buf_arg, ast.Attribute) and isinstance(buf_arg.value, ast.Name): |
| 201 | + var_name = buf_arg.value.id |
| 202 | + field_name = buf_arg.attr |
| 203 | + |
| 204 | + if not (local_sym_tab and var_name in local_sym_tab): |
| 205 | + raise ValueError(f"Variable '{var_name}' not found") |
| 206 | + |
| 207 | + struct_type = local_sym_tab[var_name].metadata |
| 208 | + if not (struct_sym_tab and struct_type in struct_sym_tab): |
| 209 | + raise ValueError(f"Struct type '{struct_type}' not found") |
| 210 | + |
| 211 | + struct_info = struct_sym_tab[struct_type] |
| 212 | + if field_name not in struct_info.fields: |
| 213 | + raise ValueError(f"Field '{field_name}' not found") |
| 214 | + |
| 215 | + field_type = struct_info.field_type(field_name) |
| 216 | + if not _is_char_array(field_type): |
| 217 | + raise ValueError("Expected char array field") |
| 218 | + |
| 219 | + struct_ptr = local_sym_tab[var_name].var |
| 220 | + field_ptr = struct_info.gep(builder, struct_ptr, field_name) |
| 221 | + |
| 222 | + # GEP to first element: [N x i8]* -> i8* |
| 223 | + buf_ptr = builder.gep( |
| 224 | + field_ptr, |
| 225 | + [ir.Constant(ir.IntType(32), 0), ir.Constant(ir.IntType(32), 0)], |
| 226 | + inbounds=True, |
| 227 | + ) |
| 228 | + return buf_ptr, field_type.count |
| 229 | + |
| 230 | + elif isinstance(buf_arg, ast.Name): |
| 231 | + # NOTE: We shouldn't be doing this as we can't get size info |
| 232 | + var_name = buf_arg.id |
| 233 | + if not (local_sym_tab and var_name in local_sym_tab): |
| 234 | + raise ValueError(f"Variable '{var_name}' not found") |
| 235 | + |
| 236 | + var_ptr = local_sym_tab[var_name].var |
| 237 | + var_type = local_sym_tab[var_name].ir_type |
| 238 | + |
| 239 | + if not isinstance(var_type, ir.PointerType) and not isinstance( |
| 240 | + var_type.pointee, ir.IntType(8) |
| 241 | + ): |
| 242 | + raise ValueError("Expected str ptr variable") |
| 243 | + |
| 244 | + return var_ptr, 256 # Size unknown for str ptr, using 256 as default |
| 245 | + |
| 246 | + else: |
| 247 | + raise ValueError("Expected struct field or variable name") |
| 248 | + |
| 249 | + |
| 250 | +def _is_char_array(ir_type): |
| 251 | + """Check if IR type is [N x i8].""" |
| 252 | + return ( |
| 253 | + isinstance(ir_type, ir.ArrayType) |
| 254 | + and isinstance(ir_type.element, ir.IntType) |
| 255 | + and ir_type.element.width == 8 |
| 256 | + ) |
| 257 | + |
| 258 | + |
| 259 | +def get_ptr_from_arg( |
| 260 | + arg, func, module, builder, local_sym_tab, map_sym_tab, struct_sym_tab |
| 261 | +): |
| 262 | + """Evaluate argument and return pointer value""" |
| 263 | + |
| 264 | + result = eval_expr( |
| 265 | + func, module, builder, arg, local_sym_tab, map_sym_tab, struct_sym_tab |
| 266 | + ) |
| 267 | + |
| 268 | + if not result: |
| 269 | + raise ValueError("Failed to evaluate argument") |
| 270 | + |
| 271 | + val, val_type = result |
| 272 | + |
| 273 | + if not isinstance(val_type, ir.PointerType): |
| 274 | + raise ValueError(f"Expected pointer type, got {val_type}") |
| 275 | + |
| 276 | + return val, val_type |
0 commit comments