http server

This commit is contained in:
agra
2026-02-17 19:26:43 +02:00
parent 4fd87309d9
commit 4aff004118
8 changed files with 356 additions and 84 deletions

View File

@@ -1319,7 +1319,7 @@ pub const CodeGen = struct {
.void_val => self.constInt32(0),
.pointer_val => c.LLVMConstNull(self.ptrType()),
.null_val => c.LLVMConstNull(self.ptrType()),
.struct_val, .array_val, .type_val, .function_val => unreachable,
.struct_val, .array_val, .type_val, .function_val, .byte_ptr_val, .union_val => unreachable,
};
}
@@ -1451,13 +1451,21 @@ pub const CodeGen = struct {
}
}
}
// Safety net: inline declarations that should have been hoisted
// Inline type declarations: resolve by registered name
if (tn.data == .struct_decl) {
const sn = tn.data.struct_decl.name;
if (self.type_registry.get(sn)) |e| {
if (e == .struct_info) return .{ .struct_type = sn };
}
}
if (tn.data == .union_decl) {
const un = tn.data.union_decl.name;
if (self.type_registry.get(un)) |e| switch (e) {
.union_info => return .{ .union_type = un },
.tagged_enum => return .{ .union_type = un },
else => {},
};
}
if (tn.data == .enum_decl) {
const en = tn.data.enum_decl.name;
if (self.type_registry.get(en)) |e| switch (e) {
@@ -3565,17 +3573,14 @@ pub const CodeGen = struct {
var hoisted = inline_sd;
hoisted.name = synthetic_name;
try self.registerStructType(hoisted);
type_node.data = .{ .type_expr = .{ .name = synthetic_name } };
},
.union_decl => |inline_ud| {
var hoisted_ud = inline_ud;
hoisted_ud.name = synthetic_name;
try self.registerUnionType(hoisted_ud);
type_node.data = .{ .type_expr = .{ .name = synthetic_name } };
},
.enum_decl => |inline_ed| {
if (inline_ed.variant_types.len > 0) {
// Tagged enum with payloads
var hoisted = inline_ed;
hoisted.name = synthetic_name;
try self.registerTaggedEnum(hoisted);
@@ -3587,7 +3592,6 @@ pub const CodeGen = struct {
try self.enum_backing_types.put(synthetic_name, self.typeToLLVM(bt));
}
}
type_node.data = .{ .type_expr = .{ .name = synthetic_name } };
},
else => {},
}
@@ -4927,21 +4931,7 @@ pub const CodeGen = struct {
return self.convertValue(val, src_ty, target_ty);
}
fn genAlloc(self: *CodeGen, args: []const *Node) !c.LLVMValueRef {
if (args.len != 1) return self.emitError("alloc expects exactly 1 argument: alloc(size)");
const builtins = try self.requireBuiltins();
const size_val = try self.genExpr(args[0]);
const i64_type = self.i64Type();
// calloc(size + 1, 1) — extra byte for null terminator
const one_i64 = c.LLVMConstInt(i64_type, 1, 0);
const size_plus_one = c.LLVMBuildAdd(self.builder, size_val, one_i64, "szp1");
const calloc_fn = builtins.calloc_fn;
const calloc_ty = c.LLVMGlobalGetValueType(calloc_fn);
var calloc_args = [_]c.LLVMValueRef{ size_plus_one, one_i64 };
const ptr = c.LLVMBuildCall2(self.builder, calloc_ty, calloc_fn, &calloc_args, 2, "alloc_ptr");
// Build string slice: {ptr, size}
return self.buildStringSlice(ptr, size_val);
}
fn genMalloc(self: *CodeGen, args: []const *Node) !c.LLVMValueRef {
if (args.len != 1) return self.emitError("malloc expects exactly 1 argument: malloc(size)");
@@ -4974,6 +4964,19 @@ pub const CodeGen = struct {
return null;
}
fn genMemset(self: *CodeGen, args: []const *Node) !c.LLVMValueRef {
if (args.len != 3) return self.emitError("memset expects 3 arguments: memset(dst, val, size)");
const builtins = try self.requireBuiltins();
const dst = try self.genExpr(args[0]);
const val = try self.genExpr(args[1]);
const size_val = try self.genExpr(args[2]);
const val_i32 = self.trunc(val, self.i32Type(), "memset_val");
const fn_ty = c.LLVMGlobalGetValueType(builtins.memset_fn);
var call_args = [_]c.LLVMValueRef{ dst, val_i32, size_val };
_ = c.LLVMBuildCall2(self.builder, fn_ty, builtins.memset_fn, &call_args, 3, "");
return null;
}
fn genVectorExtract(self: *CodeGen, vec_val: c.LLVMValueRef, field: []const u8) !c.LLVMValueRef {
if (field.len == 1) {
const idx_val = componentToIndex(field[0]) orelse return self.emitErrorFmt("invalid vector component '{c}'", .{field[0]});
@@ -6882,10 +6885,10 @@ pub const CodeGen = struct {
if (std.mem.eql(u8, base, "cos")) return self.genMathIntrinsic(call_node, "cos");
if (std.mem.eql(u8, base, "size_of")) return self.genSizeOf(call_node);
if (std.mem.eql(u8, base, "cast")) return self.genCast(call_node);
if (std.mem.eql(u8, base, "alloc")) return self.genAlloc(call_node.args);
if (std.mem.eql(u8, base, "malloc")) return self.genMalloc(call_node.args);
if (std.mem.eql(u8, base, "free")) return self.genFree(call_node.args);
if (std.mem.eql(u8, base, "memcpy")) return self.genMemcpy(call_node.args);
if (std.mem.eql(u8, base, "memset")) return self.genMemset(call_node.args);
if (std.mem.eql(u8, base, "type_of")) return self.genTypeOf(call_node);
if (std.mem.eql(u8, base, "type_name")) return self.genTypeName(call_node);
if (std.mem.eql(u8, base, "field_count")) return self.genFieldCount(call_node);
@@ -7144,11 +7147,10 @@ pub const CodeGen = struct {
if (call_node.args.len > 0) return self.resolveType(call_node.args[0]);
return Type.s(64);
}
// Built-in: alloc returns string
if (std.mem.eql(u8, base_name, "alloc")) return .string_type;
if (std.mem.eql(u8, base_name, "malloc")) return .{ .pointer_type = .{ .pointee_name = "void" } };
if (std.mem.eql(u8, base_name, "free")) return .void_type;
if (std.mem.eql(u8, base_name, "memcpy")) return .void_type;
if (std.mem.eql(u8, base_name, "memcpy")) return .{ .pointer_type = .{ .pointee_name = "void" } };
if (std.mem.eql(u8, base_name, "memset")) return .void_type;
// Check generic templates — infer return type from widened bindings
const template = self.generic_templates.get(callee_name) orelse blk: {
// Intra-namespace fallback