mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-06-05 07:13:27 -04:00
9aec2758cc
Instead of doing everything at once which is a hopelessly large task, this introduces a piecemeal transition that can be done in small increments at a time. This is a minimal changeset that keeps the compiler compiling. It only uses the InternPool for a small set of types. Behavior tests are not passing. Air.Inst.Ref and Zir.Inst.Ref are separated into different enums but compile-time verified to have the same fields in the same order. The large set of changes is mainly to deal with the fact that most Type and Value methods now require a Module to be passed in, so that the InternPool object can be accessed.
97 lines
2.4 KiB
Zig
97 lines
2.4 KiB
Zig
const std = @import("std");
|
|
const Order = std.math.Order;
|
|
|
|
const RangeSet = @This();
|
|
const Module = @import("Module.zig");
|
|
const SwitchProngSrc = @import("Module.zig").SwitchProngSrc;
|
|
const Type = @import("type.zig").Type;
|
|
const Value = @import("value.zig").Value;
|
|
|
|
ranges: std.ArrayList(Range),
|
|
module: *Module,
|
|
|
|
pub const Range = struct {
|
|
first: Value,
|
|
last: Value,
|
|
src: SwitchProngSrc,
|
|
};
|
|
|
|
pub fn init(allocator: std.mem.Allocator, module: *Module) RangeSet {
|
|
return .{
|
|
.ranges = std.ArrayList(Range).init(allocator),
|
|
.module = module,
|
|
};
|
|
}
|
|
|
|
pub fn deinit(self: *RangeSet) void {
|
|
self.ranges.deinit();
|
|
}
|
|
|
|
pub fn add(
|
|
self: *RangeSet,
|
|
first: Value,
|
|
last: Value,
|
|
ty: Type,
|
|
src: SwitchProngSrc,
|
|
) !?SwitchProngSrc {
|
|
for (self.ranges.items) |range| {
|
|
if (last.compareAll(.gte, range.first, ty, self.module) and
|
|
first.compareAll(.lte, range.last, ty, self.module))
|
|
{
|
|
return range.src; // They overlap.
|
|
}
|
|
}
|
|
try self.ranges.append(.{
|
|
.first = first,
|
|
.last = last,
|
|
.src = src,
|
|
});
|
|
return null;
|
|
}
|
|
|
|
const LessThanContext = struct { ty: Type, module: *Module };
|
|
|
|
/// Assumes a and b do not overlap
|
|
fn lessThan(ctx: LessThanContext, a: Range, b: Range) bool {
|
|
return a.first.compareAll(.lt, b.first, ctx.ty, ctx.module);
|
|
}
|
|
|
|
pub fn spans(self: *RangeSet, first: Value, last: Value, ty: Type) !bool {
|
|
if (self.ranges.items.len == 0)
|
|
return false;
|
|
|
|
const mod = self.module;
|
|
std.mem.sort(Range, self.ranges.items, LessThanContext{
|
|
.ty = ty,
|
|
.module = mod,
|
|
}, lessThan);
|
|
|
|
if (!self.ranges.items[0].first.eql(first, ty, mod) or
|
|
!self.ranges.items[self.ranges.items.len - 1].last.eql(last, ty, mod))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var space: Value.BigIntSpace = undefined;
|
|
|
|
var counter = try std.math.big.int.Managed.init(self.ranges.allocator);
|
|
defer counter.deinit();
|
|
|
|
// look for gaps
|
|
for (self.ranges.items[1..], 0..) |cur, i| {
|
|
// i starts counting from the second item.
|
|
const prev = self.ranges.items[i];
|
|
|
|
// prev.last + 1 == cur.first
|
|
try counter.copy(prev.last.toBigInt(&space, mod));
|
|
try counter.addScalar(&counter, 1);
|
|
|
|
const cur_start_int = cur.first.toBigInt(&space, mod);
|
|
if (!cur_start_int.eq(counter.toConst())) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|