This commit is contained in:
agra
2026-03-02 21:00:55 +02:00
parent 2f4f898d54
commit bbb5426777
42 changed files with 483 additions and 9023 deletions

View File

@@ -204,13 +204,15 @@ pub const Lowering = struct {
}
}
// ARCH: Architecture enum { aarch64; x86_64; wasm32; unknown; }
// ARCH: Architecture enum { aarch64; x86_64; wasm32; wasm64; unknown; }
const arch_name_id = self.module.types.internString("Architecture");
if (self.module.types.findByName(arch_name_id)) |arch_ty| {
const arch_info = self.module.types.get(arch_ty);
if (arch_info == .@"enum") {
const tag: u32 = if (tc.isWasm())
const tag: u32 = if (tc.isWasm32())
self.findVariantIndex(arch_info.@"enum".variants, "wasm32")
else if (tc.isWasm64())
self.findVariantIndex(arch_info.@"enum".variants, "wasm64")
else if (tc.isAarch64())
self.findVariantIndex(arch_info.@"enum".variants, "aarch64")
else if (tc.isX86_64())
@@ -221,8 +223,8 @@ pub const Lowering = struct {
}
}
// POINTER_SIZE: s64 (4 for wasm, 8 otherwise)
const ptr_size: i64 = if (tc.isWasm()) 4 else 8;
// POINTER_SIZE: s64 (4 for wasm32, 8 for wasm64 and other 64-bit targets)
const ptr_size: i64 = if (tc.isWasm32()) 4 else 8;
self.comptime_constants.put("POINTER_SIZE", .{ .int_val = ptr_size }) catch {};
}
@@ -2126,6 +2128,52 @@ pub const Lowering = struct {
}
}
/// Evaluate a compile-time match expression for `inline if ... == { case ... }`.
/// Returns the body of the matching arm, or null if the match can't be resolved.
fn evalComptimeMatch(self: *Lowering, me: *const ast.MatchExpr) ?*const Node {
// Subject must be a comptime constant identifier
const name = switch (me.subject.data) {
.identifier => |id| id.name,
else => return null,
};
const cv = self.comptime_constants.get(name) orelse return null;
switch (cv) {
.enum_tag => |et| {
const enum_info = self.module.types.get(et.ty);
if (enum_info != .@"enum") return null;
for (me.arms) |arm| {
if (arm.pattern == null) continue; // default arm
const variant_name = switch (arm.pattern.?.data) {
.enum_literal => |el| el.name,
else => continue,
};
const variant_idx = self.findVariantIndex(enum_info.@"enum".variants, variant_name);
if (et.tag == variant_idx) return arm.body;
}
// No match — try default arm
for (me.arms) |arm| {
if (arm.pattern == null) return arm.body;
}
return null;
},
.int_val => |iv| {
for (me.arms) |arm| {
if (arm.pattern == null) continue;
const rhs_val: i64 = switch (arm.pattern.?.data) {
.int_literal => |il| il.value,
else => continue,
};
if (iv == rhs_val) return arm.body;
}
for (me.arms) |arm| {
if (arm.pattern == null) return arm.body;
}
return null;
},
}
}
fn lowerWhile(self: *Lowering, we: *const ast.WhileExpr) Ref {
const header_bb = self.freshBlock("while.hdr");
const body_bb = self.freshBlock("while.body");
@@ -2240,6 +2288,14 @@ pub const Lowering = struct {
}
fn lowerMatch(self: *Lowering, me: *const ast.MatchExpr) Ref {
// inline if match: evaluate at compile time, only lower the matching arm
if (me.is_comptime) {
if (self.evalComptimeMatch(me)) |arm_body| {
return self.lowerInlineBranch(arm_body);
}
// Couldn't evaluate — fall through to runtime
}
const is_type_match = isTypeCategoryMatch(me);
const subject = self.lowerExpr(me.subject);
@@ -3904,6 +3960,15 @@ pub const Lowering = struct {
// Try to resolve the method by struct type name
const struct_name = self.getStructTypeName(obj_ty);
if (struct_name) |sname| {
// Intercept BuildOptions compiler builtins
if (std.mem.eql(u8, sname, "BuildOptions")) {
if (std.mem.eql(u8, fa.field, "add_link_flag")) {
return self.builder.callBuiltin(.build_options_add_link_flag, method_args.items, .void);
} else if (std.mem.eql(u8, fa.field, "set_output_path")) {
return self.builder.callBuiltin(.build_options_set_output_path, method_args.items, .void);
}
}
// Try direct qualified name: StructName.method
const qualified = std.fmt.allocPrint(self.alloc, "{s}.{s}", .{ sname, fa.field }) catch fa.field;
@@ -7530,6 +7595,12 @@ pub const Lowering = struct {
const oi = self.module.types.get(obj_ty);
if (oi == .@"struct") {
const struct_name = self.module.types.getString(oi.@"struct".name);
// Intercept BuildOptions compiler builtins
if (std.mem.eql(u8, struct_name, "BuildOptions")) {
if (std.mem.eql(u8, cfa.field, "add_link_flag") or std.mem.eql(u8, cfa.field, "set_output_path")) {
return .void;
}
}
const qualified = std.fmt.allocPrint(self.alloc, "{s}.{s}", .{ struct_name, cfa.field }) catch cfa.field;
if (self.resolveFuncByName(qualified)) |fid| {
return self.module.functions.items[@intFromEnum(fid)].ret;