This commit is contained in:
agra
2026-02-18 03:22:06 +02:00
parent 4aff004118
commit ae5e6cd507
3 changed files with 23 additions and 17 deletions

View File

@@ -1662,15 +1662,6 @@ pub const CodeGen = struct {
/// Walk an AST body to find a struct declaration (from `return struct { ... }` or bare struct expr).
fn findDeclInBody(comptime T: type, comptime tag: std.meta.FieldEnum(@TypeOf(@as(Node, undefined).data)), body: *Node) ?T {
const extract = struct {
fn get(node: *Node) ?T {
return if (@field(node.data, @tagName(tag)) != @as(?T, null))
@field(node.data, @tagName(tag))
else
null;
}
};
_ = extract;
if (body.data == tag) return @field(body.data, @tagName(tag));
if (body.data == .block) {
for (body.data.block.stmts) |stmt| {
@@ -3258,7 +3249,6 @@ pub const CodeGen = struct {
const uname = result_type.union_type;
const resolved = self.resolveAlias(uname);
const info = self.lookupTaggedEnumInfo(resolved) orelse return self.emitError("unknown tagged enum type");
const tag_ty = self.getEnumLLVMType(resolved);
var lhs_val = try self.genExprAsType(binop.lhs, result_type);
var rhs_val = try self.genExprAsType(binop.rhs, result_type);
@@ -3270,7 +3260,6 @@ pub const CodeGen = struct {
// Extract tags (field 0) and compare
const lhs_tag = self.extractValue(lhs_val, 0, "lhs_tag");
const rhs_tag = self.extractValue(rhs_val, 0, "rhs_tag");
_ = tag_ty;
const pred: c_uint = if (binop.op == .eq) c.LLVMIntEQ else c.LLVMIntNE;
return self.icmp(pred, lhs_tag, rhs_tag, "tag_cmp");
}
@@ -5498,6 +5487,7 @@ pub const CodeGen = struct {
// Generate arguments with type conversion to match parameter types
const num_params = c.LLVMCountParamTypes(fn_type);
if (num_params > 64) return self.emitErrorFmt("function has {d} parameters, exceeding maximum of 64", .{num_params});
var param_llvm_types: [64]c.LLVMTypeRef = undefined;
if (num_params > 0) {
c.LLVMGetParamTypes(fn_type, &param_llvm_types);
@@ -5645,6 +5635,7 @@ pub const CodeGen = struct {
// Build LLVM function type from FunctionTypeInfo
const ptr_ty_llvm = self.ptrType();
if (fti.param_types.len > 64) return self.emitErrorFmt("indirect call has {d} parameters, exceeding maximum of 64", .{fti.param_types.len});
var param_llvm_types: [64]c.LLVMTypeRef = undefined;
for (fti.param_types, 0..) |pt, i| {
// [N]T and [:0]T params are pointers at the ABI level
@@ -5963,8 +5954,8 @@ pub const CodeGen = struct {
// Find the cast argument and extract the runtime type tag + any value source
var cast_arg_idx: usize = 0;
var type_tag_node: *Node = undefined;
var any_val_node: *Node = undefined;
var type_tag_node: ?*Node = null;
var any_val_node: ?*Node = null;
for (call_node.args, 0..) |arg, i| {
if (arg.data == .call and arg.data.call.callee.data == .identifier) {
const name = arg.data.call.callee.data.identifier.name;
@@ -5978,8 +5969,8 @@ pub const CodeGen = struct {
}
// Generate the runtime type tag value and the Any value
const type_tag_val = try self.genExpr(type_tag_node);
const any_val = try self.genExpr(any_val_node);
const type_tag_val = try self.genExpr(type_tag_node orelse return self.emitError("runtime dispatch requires a cast() argument"));
const any_val = try self.genExpr(any_val_node orelse return self.emitError("runtime dispatch requires a cast() argument"));
// Generate non-cast arguments (evaluated once, before the switch)
var other_arg_vals = std.ArrayList(?c.LLVMValueRef).empty;
for (call_node.args, 0..) |arg, i| {
@@ -6469,7 +6460,7 @@ pub const CodeGen = struct {
try self.pushScope();
if (for_expr.index_name) |idx_name| {
if (!std.mem.eql(u8, idx_name, "_")) {
try self.named_values.put(idx_name, .{ .ptr = idx_alloca, .ty = Type.s(64), .is_const = true });
try self.registerVariable(idx_name, idx_alloca, Type.s(64));
}
}
@@ -6502,6 +6493,7 @@ pub const CodeGen = struct {
if (!std.mem.eql(u8, for_expr.capture_name, "_")) {
// Alias mode: capture points directly to element in array/slice
try self.saveShadowed(for_expr.capture_name);
try self.named_values.put(for_expr.capture_name, .{
.ptr = elem_gep,
.ty = elem_ty,
@@ -6578,6 +6570,7 @@ pub const CodeGen = struct {
if (subject_ty.isEnum()) enum_name = subject_ty.enum_type;
if (subject_ty.isUnion()) union_name = subject_ty.union_type;
// Get the switch value: for unions, load the tag from field 0; for enums, use the value directly
// Get the switch value: for unions, load the tag from field 0; for enums, use the value directly
const subject_val: c.LLVMValueRef = if (union_name != null) blk: {
// Union: load tag from field 0 of the alloca

View File

@@ -81,6 +81,7 @@ pub const Value = union(enum) {
return switch (self) {
.bool_val => |bv| bv,
.int_val => |iv| iv != 0,
.null_val => false,
else => true,
};
}
@@ -881,7 +882,10 @@ pub const Compiler = struct {
// without sema info): assume fat pointer layout {ptr=0, len=1}
if (std.mem.eql(u8, fa.field, "len")) {
try self.emit(.{ .get_field = 1 });
} else if (std.mem.eql(u8, fa.field, "ptr")) {
try self.emit(.{ .get_field = 0 });
} else {
// Other fields (e.g. union promoted fields) default to field 0
try self.emit(.{ .get_field = 0 });
}
},

View File

@@ -363,7 +363,16 @@ pub const Parser = struct {
if (self.current.tag == .int_literal) {
const arg_start = self.current.loc.start;
const text = self.tokenSlice(self.current);
const value = std.fmt.parseInt(i64, text, 10) catch 0;
const base: u8 = if (text.len > 2 and text[0] == '0' and (text[1] == 'x' or text[1] == 'X'))
16
else if (text.len > 2 and text[0] == '0' and (text[1] == 'b' or text[1] == 'B'))
2
else
10;
const digits = if (base != 10) text[2..] else text;
const value = std.fmt.parseInt(i64, digits, base) catch {
return self.fail("invalid integer literal in type argument");
};
self.advance();
try args.append(self.allocator, try self.createNode(arg_start, .{ .int_literal = .{ .value = value } }));
} else {