http server
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user